> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getcollate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Breaking Changes - Platform & Security | Official Documentation

> LLM configuration moves to a top-level block, sessions are database-backed and capped per user, database timeouts tighten, and Hybrid Runner images become distroless in Collate 2.0.

# Platform & Security

Two changes here will stop a 2.0 server from behaving as expected with a 1.13 configuration: the LLM
and embedding configuration move, and the new session limits. Everything else — timeouts, logging,
object storage, distroless images — is lower-drama but still worth checking against your deployment.

## LLM and embedding configuration moved

**Breaking.** Affects every deployment using semantic search, natural-language query, or any LLM
feature.

Provider configuration is no longer nested inside `elasticsearch.naturalLanguageSearch`. It moves to
a new top-level **`llmConfiguration`** block, with embeddings as a sub-section reusing the same
provider credentials:

```yaml theme={null}
llmConfiguration:
  enabled: ${LLM_ENABLED:-false}
  provider: ${LLM_PROVIDER:-noop}   # noop | openai | azureOpenAI | bedrock | google | anthropic
  maxConcurrentRequests: ${LLM_MAX_CONCURRENT_REQUESTS:-5}
  embeddings:
    provider: ${EMBEDDING_PROVIDER:-bedrock}   # bedrock | openai | google | djl
```

Key environment variable renames: `AWS_BEDROCK_MODEL_ID` → `LLM_BEDROCK_MODEL_ID`, `OPENAI_API_KEY`
→ `LLM_OPENAI_API_KEY`, `OPENAI_API_ENDPOINT` → `LLM_OPENAI_ENDPOINT`, `GOOGLE_API_KEY` →
`LLM_GOOGLE_API_KEY`; `GOOGLE_API_ENDPOINT` is removed outright. Embedding-specific variables keep
their names but move under `llmConfiguration.embeddings`.

<Warning>
  `LLM_ENABLED` and `LLM_PROVIDER` gate the entire block — both must be set before embeddings or any
  other LLM feature will run. Porting credentials across without enabling the block leaves semantic
  search and NLQ switched off. `BEDROCK_AWS_IAM_AUTH_ENABLED` also flips from `false` to **`true`**:
  deployments that relied on the old default and supplied static keys should confirm which credential
  chain is used.
</Warning>

Natural-language query settings consolidate too: per-provider generation settings like
`COLLATE_NLQ_BEDROCK_MAX_TOKENS`/`COLLATE_NLQ_OPENAI_MAX_TOKENS` collapse into single
`COLLATE_NLQ_*` variables, and `providerClass` under `naturalLanguageSearch` now defaults to
**`NoOpNLQService`** — NLQ filter extraction stays off until `llmConfiguration` is enabled.

<Tip>
  Port your configuration into `llmConfiguration` **before** upgrading. Semantic search silently
  degrades to a no-op provider rather than failing loudly if the block is missing. This applies to
  self-managed and BYOC deployments; fully managed instances have it applied by Collate.
</Tip>

## Sessions are database-backed and capped per user

**Behavioural.** Users will be logged out.

Collate 2.0 adds a `user_session` table so sessions survive pod restarts and are shared across pods
— previously each pod held its own in-memory session state, causing spurious logouts behind a load
balancer without sticky sessions. Concurrent sessions are now capped:

```yaml theme={null}
authenticationConfiguration:
  sessionExpiry: ${AUTHENTICATION_SESSION_EXPIRY:-"604800"}   # 7 days, all auth providers
  maxActiveSessionsPerUser: ${AUTHENTICATION_MAX_ACTIVE_SESSIONS_PER_USER:-5}
```

When the limit is exceeded, the **least recently used active sessions are revoked**. `sessionExpiry`
now applies to all auth providers with a minimum of 3600 seconds;
`oidcConfiguration.sessionExpiry` becomes a deprecated fallback.

<Warning>
  Users who work across several browsers or devices, and **service accounts driving many concurrent
  sessions**, will start being silently signed out of the oldest sessions. Raise
  `AUTHENTICATION_MAX_ACTIVE_SESSIONS_PER_USER` if that's your pattern, but prefer bot tokens for
  automation.
</Warning>

Separately, the Chrome plugin's redirect URI must now be explicitly allow-listed
(`additionalTrustedRedirectUris`, matched **exactly** — scheme, host, port, path, and query) or login
won't complete (**breaking**).

## Database connection timeouts tighten significantly

**Behavioural.** Long-running queries will now be cut off.

| Setting                                                  | 1.13                | 2.0                  |
| -------------------------------------------------------- | ------------------- | -------------------- |
| `database.queryTimeoutSeconds`                           | N/A                 | **`300`** (new)      |
| Postgres `postgresqlSocketTimeout` (s)                   | `30000` (≈8.3 h)    | **`300`** (5 min)    |
| MySQL `mysqlSocketTimeout` (ms)                          | `30000000` (≈8.3 h) | **`300000`** (5 min) |
| Postgres `loginTimeout` / `postgresqlConnectTimeout` (s) | `300` / `60`        | `30` / `30`          |

<Warning>
  Any statement that previously ran for more than five minutes — a large reindex batch, a heavy Data
  Insights aggregation, an oversized CSV import — now aborts. Raise `DB_QUERY_TIMEOUT_SECONDS`,
  `DB_POSTGRESQL_SOCKET_TIMEOUT` or `DB_MYSQL_SOCKET_TIMEOUT` if you have legitimately long
  statements, and check upgrade logs for statement-timeout errors.
</Warning>

## Logging hardening removes secrets from DEBUG output

**Behavioural and security-relevant.** At `DEBUG`, the HTTP parser used to print every request
header verbatim — including `Authorization: Bearer <jwt>` and session cookies. Since `DEBUG` is
exactly what support asks customers to enable, and those logs get attached to tickets, the Jetty
logger is now pinned independently via `JETTY_LOG_LEVEL`, separate from the root `LOG_LEVEL`. Audit
entries move to `logs/audit.log` with an audit marker, filtered out of the console appender.

<Tip>
  If you parsed audit entries out of stdout, read `logs/audit.log` instead. If you need Jetty debug
  output, set `JETTY_LOG_LEVEL=DEBUG` explicitly, and be aware of what it prints.
</Tip>

Response compression is also enabled by default in 2.0 (`server.gzip.enabled: true`, responses above
\~256 bytes) — clients that mishandle `Content-Encoding: gzip` need `Accept-Encoding: identity`. The
`objectStorage` block's default `provider` changes from `NOOP` to `s3`, but `enabled` still defaults
to `false`, so nothing activates until you turn it on; this backs the new `/v1/attachments` API.

## HTTP/2 is available as an opt-in

**Additive.**

```yaml theme={null}
server:
  applicationConnectors:
    - type: ${SERVER_PROTOCOL:-http}   # http (default) | h2c (cleartext HTTP/2) | h2 (TLS)
```

Both HTTP/2 modes stay backwards compatible — HTTP/1.1 clients keep working on the same port. It's
worth enabling when browsers hit the server directly, but not worth it behind an HTTP/2-terminating
load balancer, which already gets you the benefit.

## Hybrid Runner and AI Platform images are distroless

**Breaking for anything that shells into these pods.** The images now ship distroless — only the
runtime and its dependencies, with no shell, package manager, or standard Unix tooling.
`kubectl exec ... -- /bin/sh` no longer works.

<Tip>
  Move debugging to logs, metrics, and ephemeral debug containers (`kubectl debug`). Init containers or
  sidecars that assumed a shell in the main image need reworking.
</Tip>

## SCIM provisioning moves in Settings

**Behavioural.** SCIM provisioning configuration moves to **Team and Users** > **Provisioning** in
admin settings. The capability itself is unchanged — only its location moved, so update any internal
runbooks or onboarding docs that reference the old path.

## The 2.0.0 database migration is a maintenance-window event

**Plan a maintenance window.** New tables include `task_entity`, `announcement_entity`,
`activity_stream` (partitioned), `user_session`, `user_preferences`, and the Context Center and AI
Governance Studio entity tables. `thread_entity` is **renamed** to `thread_entity_legacy`.

<Warning>
  On clusters with tens of millions of rows, composite index creation on service and entity tables
  (`(deleted, name)` and `(deleted, serviceType)` on all 13 service tables, for the new
  `/v1/services/overview` endpoint) is the long pole of the migration. Size your maintenance window
  accordingly, and take a full backup first — there is no automated downgrade path.
</Warning>

## Dependency and CVE updates

**Additive.** Not breaking, but relevant to hardened deployments. Backend versions verified
directly against the `2.0.0` `pom.xml`: Jetty **12.1.10**, jackson-databind **2.18.9**, log4j
**2.25.5**, plus Netty 4.1.137.Final (pinned via BOM), BouncyCastle 1.85, thrift 0.24.0,
reactor-netty-http 1.2.18, tomcat-jdbc/juli 11.0.11, httpcore5 5.4.3, Redshift JDBC 2.2.2, and
Kubernetes client-java 25.0.1.

Frontend: `ws` 8.21.0, `handlebars` 4.5.2, `js-yaml` 5.2.2, `fast-uri` 3.1.5, `nanoid` 3.3.17 and
`brace-expansion` 1.1.18 / 5.0.9. Other operationally relevant security fixes: test-connection
workflow triggers are authorized, CSRF failures fail secure and retry on the next request,
`testDestination` redacts destination configuration, and SCIM `displayName` synchronization is
fixed.

## Full detail

For the full narrative walkthrough of Platform & Security in Collate 2.0 — including screenshots and step-by-step context — see [Release 2.0: Platform & Security](/release-2.0/platform-and-security).
