SemVer-Trust

ADR-039 — The bootstrap-family writer contract: atomic writes, dry-run purity, and a repo-relative path fence

Status: Proposed (2026-07-21) Date: 2026-07-21 Related: ADR-037, ADR-028 Decision: every bootstrap-family command that writes obeys one contract, present and future:

Rationale: the policy’s registry paths carry no path validation today, and verification is safe only because it reads them exclusively from git trees, which cannot escape the repository. The moment a command reads or writes those paths on the filesystem it inherits a traversal surface: a hostile cloned repository could declare allowed_signers = "../../.ssh/authorized_keys" and turn enroll --write into an append of attacker-shaped key material into $HOME. A torn or partial registry write is worse than a no-op — it fails closed for every verifier of the repository — so writes must be atomic and strict-re-parsed. The fence’s reject-don’t-sanitize posture mirrors the existing attestation-subject validator. Rejected: MkdirAll on attacker-chosen or typo’d parent paths; sanitizing a traversing path instead of rejecting it; a non-atomic append that can leave a registry unparseable; create-then-chmod on key files (a race and a symlink-follow window). Revisit trigger: a new writer whose target cannot satisfy the atomic protocol — a reason to reconsider the writer, not to weaken the contract.