ADR-0019: Data Collaboration ships disabled by default
ODD Platform ships Data Collaboration off by default — a conditional gates the whole controller on datacollaboration.enabled, so every route returns 404 until an operator opts in.
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 thedatacollaboration:key), the verbatim shipped default.odd-platform-api/.../datacollaboration/controller/DataCollaborationController.java:21-22—@ConditionalOnDataCollaborationon the@RestControllerclass: no bean when disabled, so its routes 404.odd-platform-api/.../datacollaboration/config/DataCollaborationFeatureCondition.java:18-22— the singleConditionreadsFeatureResolver.DATA_COLLABORATION_ENABLED_PROPERTYfrom theEnvironmentwith defaultfalse.odd-platform-api/.../datacollaboration/config/ConditionalOnDataCollaboration.java— the reusable@Conditional(DataCollaborationFeatureCondition.class)meta-annotation applied across the feature's components.
See also
Data Collaboration — the feature and its configuration.
ADR-0020 — Decoupled outbound Slack delivery — how messages are delivered once the feature is enabled.
ADR-0004 — GenAI ships disabled by default and ADR-0040 — Notifications ship disabled by default — the same ship-off-by-default posture for other features.
Last updated