> For the complete documentation index, see [llms.txt](https://docs.opendatadiscovery.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opendatadiscovery.org/developer-guides/architecture-decision-log/adr-0019-data-collaboration-disabled-by-default.md).

# ADR-0019: Data Collaboration ships disabled by default

## Status

**Accepted.** Reconstructed from the codebase on 2026-05-30; the decision is live in the source today.

## Context

Data Collaboration (the in-platform Discussions surface and the Slack message bridge) is a heavyweight, outbound-integration feature: it needs a Slack OAuth token, a background sender, and Postgres coordination artefacts. Most deployments do not use it. The platform needs a default that keeps the feature inert for the operators who never configure it, while making it a single, explicit opt-in for those who do.

## Decision

**Data Collaboration ships with `enabled: false` (under `datacollaboration:`) as the verbatim default, and the whole feature is gated by a `@ConditionalOnDataCollaboration` conditional.** The feature's controller (and its background components) carry that annotation; when the property is not `true`, the conditional does not match, the controller bean is never registered, and **every Data Collaboration route returns 404 Not Found** — there is no degraded mode, no "feature disabled" payload.

The gating is centralised in one `Condition` class that reads the property from Spring's `Environment` (defaulting to `false`), consulted through a single reusable `@ConditionalOnDataCollaboration` meta-annotation. A developer changing the gating semantics touches one place, not each component.

This is one member of the platform's **ship-disabled-by-default family** for heavyweight / outbound-integration features, alongside GenAI (ADR-0004) and Notifications (ADR-0040). Once an operator turns the feature on, the required integration config is validated fail-fast at boot (ADR-0018) — so the deployment story is: feature off → operator opts in → operator must supply the Slack OAuth token or the platform refuses to start.

## Consequences

* A default deployment runs with Data Collaboration entirely absent — no beans, no background workers, no Postgres artefacts created.
* Because gating removes the controller bean rather than guarding each method, a disabled feature responds **404** (route does not exist), not 403 or a disabled-state body. A client cannot distinguish "feature disabled" from "wrong URL" without out-of-band knowledge.
* Enabling is a single property (`datacollaboration.enabled: true`) plus the integration config that ADR-0018 then requires at boot; there is no per-route toggle.
* The single-`Condition` + meta-annotation design keeps the on/off semantics in one file, avoiding the drift that scattered per-bean property checks would produce.

## Evidence

* `odd-platform-api/src/main/resources/application.yml:205` — `enabled: false` (under the `datacollaboration:` key), the verbatim shipped default.
* `odd-platform-api/.../datacollaboration/controller/DataCollaborationController.java:21-22` — `@ConditionalOnDataCollaboration` on the `@RestController` class: no bean when disabled, so its routes 404.
* `odd-platform-api/.../datacollaboration/config/DataCollaborationFeatureCondition.java:18-22` — the single `Condition` reads `FeatureResolver.DATA_COLLABORATION_ENABLED_PROPERTY` from the `Environment` with default `false`.
* `odd-platform-api/.../datacollaboration/config/ConditionalOnDataCollaboration.java` — the reusable `@Conditional(DataCollaborationFeatureCondition.class)` meta-annotation applied across the feature's components.

## See also

* [Data Collaboration](/features/active-platform-features/data-collaboration.md) — the feature and its configuration.
* [ADR-0020 — Decoupled outbound Slack delivery](/developer-guides/architecture-decision-log/adr-0020-decoupled-outbound-slack-delivery.md) — how messages are delivered once the feature is enabled.
* [ADR-0004 — GenAI ships disabled by default](/developer-guides/architecture-decision-log/adr-0004-genai-disabled-by-default.md) and [ADR-0040 — Notifications ship disabled by default](/developer-guides/architecture-decision-log/adr-0040-notifications-disabled-by-default.md) — the same ship-off-by-default posture for other features.
