Architecture Decision Records
ADRs document the context, decision, and consequences of every significant
architectural choice in BitVault. They are the primary artifact; code is
the implementation. When you wonder “why does it work this way?”, the ADR
explains the forces at play, what was rejected, and what was accepted — including
the costs.
V1 Freeze (2026-06-12) classification. Accepted = binds the V1 build
(P0–P2). Proposed = agreed direction, not committed to V1. Deferred = out
until a named P3+ forcing function. Totals: 26 Accepted · 2 Proposed · 10
Deferred (38). See Architecture Freeze V1.
How to Write an ADR
Each ADR has five required sections:
| Section |
Content |
| Status |
Accepted, Proposed, Deferred, or Superseded by ADR-XXXX |
| Context |
The problem, forces, and constraints that drove the decision |
| Decision |
One clear sentence: what was decided |
| Consequences |
Positive outcomes AND costs/trade-offs (both are required) |
| Alternatives considered |
What else was evaluated and why it was not chosen |
An ADR without honestly stated negative consequences will be sent back. For
guidance on proposing changes to existing decisions, see
Contributing.
Foundation
| # |
Title |
Status |
Date |
Key decision |
| 0001 |
Architecture style: modular monolith first |
Accepted |
2026-06-11 |
bitvaultd v1 single binary; extract to services by forcing function |
| 0002 |
Monorepo |
Accepted |
2026-06-11 |
One repo; go.work + pnpm/Turborepo |
| 0003 |
gRPC internal, REST external |
Accepted |
2026-06-11 |
buf + OpenAPI codegen; generated contracts |
| 0004 |
Postgres as metadata source of truth |
Accepted |
2026-06-11 |
Forward-only migrations; expand/contract schema evolution |
Storage
| # |
Title |
Status |
Date |
Key decision |
| 0005 |
Object storage abstraction |
Accepted |
2026-06-11 |
Provider interface; one adapter (MinIO/S3) in V1; conformance suite |
| 0011 |
Direct-to-storage presigned URLs |
Accepted |
2026-06-11 |
Bytes bypass compute; URL issued by control plane |
| 0016 |
Hashing: BLAKE3 |
Accepted |
2026-06-11 |
Content addressing; integrity verification at commit |
| 0017 |
Chunking strategy (FastCDC + packing) |
Deferred |
2026-06-11 |
Deferred — V1 is whole-object; chunk-delta is post-V1 |
| 0018 |
Deduplication scope |
Accepted |
2026-06-11 |
Whole-object, per-tenant dedup; no cross-tenant side-channel |
| 0019 |
Garbage collection |
Accepted |
2026-06-11 |
Safe GC: grace + atomic re-confirm (CAS); refcount is a hint |
| 0020 |
Storage placement federation |
Deferred |
2026-06-11 |
Deferred — single static provider in V1 |
| 0021 |
Resumable uploads |
Proposed |
2026-06-11 |
V1 = single-shot presigned PUT (size cap); multipart proposed |
Events & Messaging
| # |
Title |
Status |
Date |
Key decision |
| 0006 |
Event backbone: outbox (+ NATS at P3) |
Accepted |
2026-06-11 |
Outbox + in-proc bus in V1; NATS JetStream deferred to P3 |
Multi-Tenancy
| # |
Title |
Status |
Date |
Key decision |
| 0007 |
Multi-tenancy model |
Accepted |
2026-06-11 (rev 06-12) |
Shared DB + RLS; tenant_id everywhere; context via SET LOCAL (ADR-0038) |
Sync
| # |
Title |
Status |
Date |
Key decision |
| 0008 |
Sync and conflict resolution |
Accepted |
2026-06-11 (rev 06-12) |
Journal written at commit (source of truth); stale base → conflicted copy |
| 0022 |
Sync reconciliation: three-tree |
Accepted |
2026-06-11 |
Base/local/remote tree reconciliation (client planner) |
| 0023 |
Local sync database |
Accepted |
2026-06-11 |
SQLite on device |
| 0024 |
Sync protocol cursor |
Accepted |
2026-06-11 (rev 06-12) |
Monotonic per-tenant seq assigned at commit; cursor delta pull |
| 0025 |
File watching strategy |
Accepted |
2026-06-11 |
inotify / FSEvents / ReadDirectoryChangesW |
| 0026 |
Conflict resolution policy |
Accepted |
2026-06-11 |
Conflicted copy; both histories kept; user reconciles |
| 0027 |
Sync safety guards |
Accepted |
2026-06-11 |
Atomic apply; self-write suppression; bulk-change brake |
Security & AuthN
| # |
Title |
Status |
Date |
Key decision |
| 0010 |
AuthN/AuthZ |
Accepted |
2026-06-11 |
OAuth 2.1 + OIDC; RBAC deny-by-default |
| 0014 |
Encryption key management |
Accepted |
2026-06-11 (rev 06-12) |
Per-tenant DEK wrapped by KMS KEK; TENANT_KEY + BLOB schema footprint |
| 0035 |
Machine identity |
Deferred |
2026-06-11 |
Deferred — workload identity is P4 |
| 0036 |
Authentication policy (MFA/passkeys) |
Proposed |
2026-06-11 |
Basic authn V1 (ADR-0010); MFA/step-up/DPoP proposed |
| 0037 |
Public sharing security |
Accepted |
2026-06-11 (rev 06-12) |
Hashed capability token; expiry; scoped presigned URLs; abuse program deferred |
| 0038 |
RLS connection pooling |
Accepted |
2026-06-12 |
Transaction-local SET LOCAL tenant context; pooling-safe; default-deny; bleed test |
API & Contracts
| # |
Title |
Status |
Date |
Key decision |
| 0003 |
gRPC internal, REST external |
Accepted |
2026-06-11 |
buf lint + breaking-change CI; OpenAPI generated from proto |
| 0015 |
API versioning |
Accepted |
2026-06-11 |
URI versioning /v1/; buf breaking in CI for gRPC |
Observability
| # |
Title |
Status |
Date |
Key decision |
| 0013 |
Observability: OpenTelemetry |
Accepted |
2026-06-11 |
Traces + metrics + logs from commit #1; vendor-neutral; one trace per user action |
Deployment & Ops
| # |
Title |
Status |
Date |
Key decision |
| 0012 |
Deployment packaging |
Accepted |
2026-06-11 |
lite/standard (Compose) in V1; full + Helm/K8s deferred to P3/P4 |
| 0028 |
GitOps with ArgoCD |
Deferred |
2026-06-11 |
Deferred — P4 (extraction & scale) |
| 0029 |
Progressive delivery |
Deferred |
2026-06-11 |
Deferred — P4 |
| 0030 |
Secrets management |
Deferred |
2026-06-11 |
Deferred — P4; V1 uses env/keyfile secrets |
| 0031 |
IaC: OpenTofu |
Deferred |
2026-06-11 |
Deferred — P4 |
| 0032 |
CI/CD supply-chain security |
Deferred |
2026-06-11 |
Deferred — P4; V1 CI = build/test/lint |
| 0033 |
Backup and DR |
Deferred |
2026-06-11 |
Deferred — P4; V1 = pg_dump + object versioning |
| 0034 |
Environment promotion |
Deferred |
2026-06-11 |
Deferred — P4 (multi-env) |
Search
| # |
Title |
Status |
Date |
Key decision |
| 0009 |
Search derived index |
Accepted |
2026-06-11 |
Postgres-FTS in V1; OpenSearch (content search) deferred to P3 |