# V1 ADR 003: MongoDB Runtime Topology

Status: Accepted during Block 16.1

Date: 2026-06-25

## Context

MongoDB is the committed persistence target for V1, but the Flutter UI and pure
Dart scheduling core must not own production database credentials. Block 15
completed the adapter-neutral document schema, codecs, repository contracts,
index catalog, payload limits, and migration contracts.

Before adding a MongoDB dependency, Block 16 needs a runtime decision that keeps
credentials inside a trusted boundary, supports transactions, and avoids
deprecated MongoDB client-access products.

Sources checked on 2026-06-25:

- MongoDB official client libraries list:
  `https://www.mongodb.com/docs/drivers/`
- MongoDB Node.js driver docs:
  `https://www.mongodb.com/docs/drivers/node/current/`
- MongoDB Node.js transaction docs:
  `https://www.mongodb.com/docs/drivers/node/current/crud/transactions/`
- MongoDB transaction manual:
  `https://www.mongodb.com/docs/manual/core/transactions/`
- MongoDB Atlas App Services EOL notice:
  `https://www.mongodb.com/docs/api/doc/atlas-app-services-admin-api-v3/`
- Deprecated Atlas Data API docs:
  `https://www.mongodb.com/docs/api/doc/atlas-data-api-v1/`
- Dart package checks:
  `https://pub.dev/packages/mongo_dart` and
  `https://pub.dev/packages/mongo_db_driver`

## Decision

V1 selects a trusted service boundary for MongoDB persistence.

The MongoDB-owning runtime is a separate Node.js/TypeScript service using the
official MongoDB Node.js driver. This service owns:

- MongoDB connection strings and credentials;
- TLS/SRV driver configuration;
- client lifecycle and health checks;
- index bootstrap from the Block 15 index catalog;
- document reads/writes against the V1 collection contract;
- sessions and transactions for multi-record scheduling writes;
- redacted diagnostics and failure mapping.

The Flutter UI never connects directly to MongoDB and never receives connection
strings, database credentials, raw MongoDB documents, driver clients,
collections, sessions, or cursors.

The pure Dart package remains dependency-free with respect to MongoDB. Dart
domain and application code continue to use repository interfaces and typed use
case results. The trusted service exposes a narrow versioned application API
that maps to the Block 14 use cases and Block 15 document contract.

During the UI foundation/design spike, the first Flutter UI should use the
existing in-memory application composition by default. Persisted development
flows may use a local trusted service process, but that process remains outside
the Flutter binary and reads secrets only from runtime configuration.

## Rejected Options

### Direct MongoDB from Flutter or mobile Dart

Rejected. It would place database credentials in an untrusted binary and force
the UI to own network/database failure modes. It also couples the UI to driver
types and makes owner-scope/security mistakes harder to contain.

### Pure Dart MongoDB adapter as the production V1 foundation

Rejected for now. MongoDB's official client library list does not include Dart.
`mongo_dart` is active and useful for experiments, but it is community-supported
rather than an official MongoDB driver. `mongo_db_driver` advertises sessions and
transactions, but its package page explicitly identifies it as pre-alpha and not
suitable for production. Neither should become the V1 persistence foundation
without a later ADR reversing this decision.

### Atlas Data API, Atlas Device SDKs, App Services, GraphQL, Functions, or
Custom HTTPS Endpoints

Rejected. MongoDB's App Services notice says these paths reached end-of-life on
September 30, 2025, with database triggers remaining available. They are not a
stable V1 foundation.

### SQLite or another local fallback

Rejected. MongoDB remains the committed persistence target. A disconnected
fallback would add an unplanned sync/reconciliation problem and violate the
current persistence target rules.

## Driver and Deployment Requirements

The selected service must use the official MongoDB Node.js driver current major
line at implementation time.

Mandatory capabilities:

- `mongodb+srv://` and TLS-capable connections for Atlas;
- BSON fidelity at the adapter edge;
- sessions and multi-document transactions;
- explicit transaction retry handling for documented retryable categories;
- bounded connection and operation timeouts;
- graceful startup/shutdown and health checks;
- idempotent index creation;
- redacted logging;
- no raw driver values in public service DTOs.

MongoDB deployment requirements:

- Multi-document scheduling writes require MongoDB Server 4.0 or later.
- Transaction acceptance requires a transaction-capable deployment. V1 local and
  CI testing must use a replica set or supported sharded deployment, not a
  standalone server.
- If the service cannot verify transaction capability at startup for a
  production Mongo-backed configuration, it must fail closed instead of falling
  back to untracked in-memory writes.

## Configuration Boundary

Development configuration:

- Uses environment variables or a local secret file excluded from git.
- May point to a disposable local replica set or scoped Atlas development
  database.
- Must use a database name or prefix that is safe for destructive test cleanup.

Test configuration:

- Uses uniquely named disposable databases/collections.
- Fails if the configured target does not match the expected test scope.
- Redacts connection strings and credentials from test output.

Production configuration:

- Secrets come from deployment secret storage.
- The Flutter/mobile app receives only service endpoint configuration and
  application-layer auth/session material once that future work is explicitly
  planned.
- Production authentication, account management, cross-device sync, Atlas
  provisioning, network allowlists, and cluster creation remain out of scope for
  this block.

## Threat and Safety Checklist

- No MongoDB connection string is committed to source control.
- No MongoDB credential is embedded in Flutter, mobile, desktop, or web UI
  assets.
- Normal logs do not include task titles, hidden locked-block names, full
  documents, connection strings, or credential fragments.
- Every repository query and write includes owner scope.
- Hidden locked-time details remain hidden by default in service responses.
- Duplicate operation IDs are enforced by a unique owner-operation index.
- Revision predicates are required for authoritative updates.
- Transaction retries are bounded and observable.
- A production Mongo connection failure fails closed.
- In-memory composition remains available only as explicit local/design-spike
  wiring, not as a silent production persistence fallback.

## Consequences

Block 16.2 must add any MongoDB dependency only in the trusted service/runtime
module, not in the pure Dart core package.

The implementation path should provide two composition roots:

- in-memory Dart application wiring for tests and UI design work;
- trusted service-backed persistence for MongoDB-backed development and future
  deployment.

If a later chunk cannot implement the selected service boundary without
duplicating scheduling rules unsafely, it must stop and record the blocker
rather than embedding credentials in Flutter or adopting an unmaintained driver
as a shortcut.
