computedriven computedriven/docs/custody-model.md
Two invariants discovered by the R0.4.2 review:

R0.4.3 custody & provenance model — written before the mechanism

Two invariants discovered by the R0.4.2 review:

Replay may reconstruct knowledge; replay alone must never reconstruct possession.

Naming something cannot grant lifecycle authority over it.

Knowledge vs possession

replay_lifecycle(log) answers "what is believed about locus L" — it is public, descriptive, and mints nothing. Acting as a participant requires a possession value that public evidence cannot produce:

To act as…You must hold…
the live CarrierLocusAttachment (live) or CarrierCustody (persisted recovery material) + the log
the finality authorityFinalityWarden
a lifecycle creatorWorldRoot → LocusRoot

Provenance chain

WorldRoot::bootstrap(mark)          <- THE trust boundary (see below)
   │  create_locus(LocusId)
   ▼
LocusRoot                            (move-only; one lifecycle start each)
   │  begin()
   ▼
VacantLocus(0) + FinalityWarden
   │  attach(carrier)
   ▼
LocusAttachment(N) ── suspend() ──> CarrierCustody(N)   [CONSUMES the live value]
CarrierCustody(N)  ── recover_attachment(custody, &admission) ──> LocusAttachment(N)   [admission = current, linear]

(R0.4.5: Live XOR Recoverable. The former custody() accessor was removed because it aliased live and recoverable possession.) Every minted value and evidence record privately carries the root's mark. A LocusId appears nowhere in this chain as an input that grants anything: knowing a name mints no vacancy, no warden, no custody.

Recovery model (review cases A–D)

  • **A. Same-Carrier planned restart (linear checkpointed

reconstitution):** suspend() consumes the live attachment and yields the one CarrierCustody; recover_attachment(custody, &admission) consumes the custody and yields the live attachment again, judged against the lineage's CURRENT LifecycleAdmission (R0.4.6/7 — never a caller-chosen slice; see docs/freshness-model.md, docs/admission-model.md). Recovery never advances a generation; a failed recovery hands the custody back. This is planned restart only — see docs/linearity-model.md for why unplanned crash recovery is NOT claimed.

  • B. Physical Carrier loss: the custody material died with the

Carrier. Orderly detach is therefore unavailable — exactly as intended — and only the warden's finality path can close the generation.

  • C. Network partition: the log stays readable everywhere, but a

reader holds neither A's custody nor a finality decision. The generation stays attached to A. Knowledge without possession.

  • D. Vacant locus: passive knowledge of vacancy is NOT mutation

authority (explicit decision). A VacantLocus value is held only by (i) the releasing Carrier via detach(admission) (which may hand it off deliberately), or (ii) the finality authority via finalize_loss(…, admission), which materializes the successor vacancy atomically with the closure (R0.4.7).

Two-layer provenance checking

  1. replay_lifecycle (public, descriptive) additionally rejects logs

whose events carry differing marks (MixedProvenance): splicing forged-root evidence into an honest history fails even descriptively.

  1. audit_replay(&WorldRoot, …) (authoritative, descriptive) verifies

every event against the root's own mark (ForeignProvenance).

  1. LifecycleAdmission (linear, current) is bound to the lineage mark

from birth; every transition checks the acting value's provenance against it (ForeignProvenance) and hands everything back on failure.

The trust boundary, stated exactly (no papering over)

WorldRoot::bootstrap(mark) is publicly callable — a library cannot make a global singleton. What the types DO enforce, in-process: no API reveals a mark (no accessor, no PartialEq on custody), so a holder of records, logs, custody-less state, or LocusIds cannot extract or forge the mark; evidence minted under a different bootstrap is rejected by both layers above. What is NOT claimed: cryptographic attestation (marks are modeling material, not crypto — skepticism list unchanged), secrecy of the bootstrap entropy (a deployment duty), or cross-log split-brain resolution. The claim is narrowed to exactly this: within a process, neither public evidence nor a LocusId can manufacture custody or finality capability; only material descending from the same bootstrap can.

Falsifiers this model must survive (implemented in R0.4.3)

  1. Honest Attached(A,0) log + no A-local custody → no way to mint

DetachReceipt(A,0) (Attack A dead; reconstitute no longer exists).

  1. VacantLocus::genesis/genesis_with_warden no longer exist —

LocusId-based minting is a compile error.

  1. A forged-root warden's finalization spliced into an honest log →

MixedProvenance; a fully forged log → ForeignProvenance on audit.

  1. Direct struct construction of custody/warden/records still E0451.

  2. Stale custody (from a closed generation) cannot recover.

  3. Custody for the wrong carrier cannot recover.

  4. Legitimate bootstrap still creates and runs a full lifecycle.

Open in the interactive atlas