ADR 004: Codex over Arca over Turso
ADR 004: Codex over Arca over Turso
Section titled “ADR 004: Codex over Arca over Turso”[!NOTE] Historical note: the
TURSO_*env var names in this ADR are superseded byVOX_DB_URL/VOX_DB_TOKEN. ADR text is preserved for context.
Status
Section titled “Status”Accepted — greenfield release baseline.
Context
Section titled “Context”Vox persisted data through vox-db (VoxDb / Codex), with related crates (vox-pm, etc.) and scattered env names (VOX_DB_*, legacy TURSO_*). Documentation referred to Arca, Codex, and VoxDb interchangeably. The public product name for the database layer must be Codex (not “codecs” or other typos). Schema DDL and store operations live in crates/vox-db (schema/ domains + store/ops_*.rs); the only supported SQL engine is Turso / libSQL.
Decision
Section titled “Decision”- Codex — The public, application-facing data API. In Rust,
vox_db::Codexis a type alias forVoxDb; new docs and APIs should say Codex. - Arca — Internal name for schema fragments, baseline migration, CAS tables, and SQL operations owned by
vox-db(schema/manifest.rs,store/). No second physical store. - Turso — Sole database engine. No parallel PostgreSQL/SQLite product paths for the same data plane.
- Greenfield baseline — Fresh releases use a forward migration chain from the current schema version; legacy shape is preserved via explicit importers, not an unbounded pile of historical migrations in docs.
- Convex-like behavior — Implemented as Codex capabilities (change log, subscriptions, invalidation, SSE/WebSocket), not a second database.
- Secrets —
VOX_DB_TOKEN(and auth material) are environment-only; never committed in TOML.VOX_DB_URLmay appear in config for convenience; token must not.
Consequences
Section titled “Consequences”- Repository tenancy — MCP and orchestration shard filesystem paths; coordination tables use
repository_idwhere applicable (e.g.a2a_messages). Theagent_eventstable does not currently includerepository_idon the baseline DDL. Session rows carry tenant context inagent_sessions.task_snapshotJSON when MCP setsSessionConfig::repository_idinvox-orchestrator.
Nomenclature note (2026-05-08):
vox-pmwas renamed tovox-package; references in this ADR are historical.
VoxDbremains the stable Rust identifier for ABI/compatibility; prefer Codex in user-facing text and new modules.- Compatibility aliases for legacy Turso-prefixed env names map to the same remote resolution as
VOX_DB_URL/VOX_DB_TOKENinvox_db::DbConfig::resolve_standalone(after canonical env, before older Turso spellings listed in env-vars SSOT). - Older first-party Turso env spellings are deprecated; they remain last-resort shims in
resolve_standalonealongside theVOX_TURSO_*compatibility tier (ordering in env-vars SSOT). - Direct
turso::usage outsidevox-db(and documented exceptions) is discouraged; domain code should callVoxDb/CodexAPIs (store/ops_*.rs). See direct Turso allowlist for the current enforcement story.
References
Section titled “References”- Environment variables (SSOT) — canonical
VOX_DB_*/ Turso alias precedence - Codex / Arca compatibility boundaries — API, env, and migration contract
- Codex vNext schema domains
- Codex BaaS scaffolding
- Orphan surface inventory
- Crate:
crates/vox-db,crates/vox-pm
Nomenclature note (2026-05-08):
vox-pmwas renamed tovox-package; references in this ADR are historical.
Status update — 2026-05
Section titled “Status update — 2026-05”Sanctioned satellites (libSQL files outside vox.db)
Section titled “Sanctioned satellites (libSQL files outside vox.db)”The “Turso-only” rule does not mean “single DB file.” It means “every relational
store uses libSQL/Turso, with the schema either in vox-db’s SCHEMA_FRAGMENTS
manifest or in an explicitly-listed sanctioned satellite.”
Current sanctioned satellites:
| Crate | DB file | Reason | Owner |
|---|---|---|---|
vox-secrets | .vox/clavis_vault.db | Blast-radius isolation: secrets must never share a process-level connection with user-data Codex. | Security |
vox-package | .vox_modules/local_store.db | Transitional; folded away by M-67. | Package |
The list above is mirrored mechanically in
contracts/db/data-storage-policy.v1.yaml
(tiers.a_relational.{owners, allow_direct_access, temporary_exceptions}).
Three CI checks enforce no further drift:
vox ci db-schema-coverage— everyCREATE TABLElives in an owner crate.vox ci policy-allowlist-parity— txt allowlist agrees with policy YAML.vox ci turso-import-guard— built-in prefixes auto-derived from policy YAML.
What is NOT a satellite
Section titled “What is NOT a satellite”- Operational JSON state (
.vox/process-supervision/*.state.json, orchestrator context snapshots) — Tier D cache. See file headers for rationale. - In-process
Arc<Mutex<HashMap>>registries (rate limit buckets, broadcast subscriptions, per-request receipts) — ephemeral by design.