Files
factory/vibe/ADR/README.md
Gabriel Radureau 23d8bc9231 docs(adr): ADR-0003 — sandbox state lifecycle (iso-prod seed, reset & prod-write isolation)
Records how erp-sandbox's DATA is seeded, reset, and kept structurally
incapable of harming prod — the application-data-layer complement to ADR-0001
(which rejected an in-cluster sandbox for INFRA rehearsal) and the lifecycle for
the erp-sandbox instance ADR-0002 stood up.

Decision: (1) iso-prod golden via read-only pg_dump of prod erp, app-scoped to
llx_*; (2) reset = DROP OWNED BY erp_sandbox_role CASCADE + pg_restore
--no-owner --role=erp_sandbox_role into the EXISTING db (no DROP/CREATE DATABASE,
no CREATEDB, no superuser; provisioner-owned infra objects like the pgbouncer
user_lookup function are left untouched); (3) prod-write isolation as a
structural invariant (superuser only in human-gated postgres.yaml CI; DROP
DATABASE gated by ownership — erp_sandbox_role owns only erp-sandbox, never prod
erp/erp_role; sandbox-scoped Dolibarr key; membership-only runtime creds;
host-guard; resettability); plus a human-gated promote via the read-only
dolibarr-data-snapshot diff under a separate prod-write credential.

The reset mechanism + the integrity invariant were validated against the live
erp-sandbox: DROP OWNED BY erp_sandbox_role + app-scoped pg_restore round-trips
to the golden checkpoint using only erp_sandbox_role membership (superuser=false,
createdb=false, not a member of erp_role), proving prod is structurally
unreachable from the sandbox credential.

Drafted via a clean-context agent; mechanism refined from a live prototype.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-28 20:21:00 +02:00

3.6 KiB

vibe > ADR

Architecture Decision Records

Status: 🟢 Active Last Updated: 2026-06-28 Related: vibe/PRD · vibe/Investigations Historical: doc/adr (foundational infra) · ansible/.../docs/adr (dated infra ADRs)

vibe/ADR/ is the canonical home for Architecture Decision Records going forward. The format is MADR-lite: one short, self-contained Markdown file per decision, focused on the why rather than the how. Use the _template.md skeleton to start a new one.

Where ADRs live

There are three ADR locations in this repo. Only the first accepts new records; the other two are read-only history kept for context.

Location Role Accepts new ADRs?
vibe/ADR/ (this folder) Canonical, MADR-lite, going forward Yes
doc/adr/ Foundational infrastructure ADRs (DNS, k3s, CI/CD, Vault, telegram-gateway auth) Historical
ansible/arcodange/factory/docs/adr/ Dated infra ADRs (network, CI/CD, Longhorn PVC recovery, internal DNS) Historical

When a new decision supersedes one of the historical records, write the new ADR here, set the old one's status note to Superseded by ADR-NNNN, and cross-link both ways.

Rules

  • One file per decision, named NNNN-kebab-title.md (zero-padded sequence, e.g. 0001-safe-prod-like-environment.md).
  • The body is immutable once Accepted. A decision is a historical fact: do not rewrite the Context/Decision/Consequences after acceptance. The only mutation allowed on an accepted ADR is its status (e.g. flipping AcceptedSuperseded).
  • Statuses: Proposed (under discussion) → Accepted (decided, body frozen) → Superseded (replaced; points to the successor ADR). A Proposed ADR may still be edited freely.
  • No-tombstone rule. Each file reads as currently true. Never leave "previously X, now Y", changelog lines, or "updated to ..." notes inside an ADR — git history is the audit trail. A superseded ADR keeps its original frozen body; the supersession is recorded only in its status line and the successor's References.
  • PR cross-link both ways. The ADR References section links the PR that introduced it; the PR description links back to the ADR. Keep links bidirectional.

Index

# Title Status Date
0001 Safe, production-like environment 🟢 Accepted 2026-06-23
0002 Per-application environments 🟢 Accepted 2026-06-25
0003 Sandbox state lifecycle 🟢 Accepted 2026-06-28

Rules to contribute

  1. Copy _template.md to NNNN-kebab-title.md using the next free sequence number and delete the top HTML-comment note.
  2. Fill in the blockquote (Status/Date/Deciders), then Context, Decision, Consequences, Alternatives considered, QA & validation, References.
  3. Open the ADR with status Proposed. Flip it to Accepted once the decision is settled — and from that point treat the body as frozen.
  4. Add a row to the Index table above (newest at the bottom to preserve chronological numbering).
  5. In the PR that lands the ADR, link to the ADR file; in the ADR's References, link back to the PR. Bidirectional links are mandatory.
  6. If this ADR supersedes a historical one in doc/adr/ or the Ansible ADR folder, update the old record's status note and cross-reference both directions.