computedriven computedriven/docs/admission-model.md
Invariant from the R0.4.6 review:

R0.4.7 atomic lifecycle admission — written before the mechanism

Invariant from the R0.4.6 review:

No authority-bearing lifecycle transition may take effect without consuming the current lifecycle admission capability that makes that transition current.

The hole

<!-- historical --> R0.4.6 serialized evidence (linear head, no rollback) but not operational mutation: capability transitions (attach, detach, finalize_loss, reopen) ran independently, minted a Copy event, and the head was advanced later by a separate append. In the gap the head lagged reality, and three forks followed:

  1. detach() produced Vacant(1) before its receipt was appended; the

warden finalized A@0 against the still-current head; reopen produced a second Vacant(1). Two carriers attached at generation 1.

  1. Vacant(1) consumed to attach B before B's record was appended; the

head still said vacant; reopen minted another Vacant(1). B and C.

  1. After accepted finality of A@0 and attachment of B@1, the stale

LocusAttachment(A,0) value still existed and could detach() into yet another Vacant(1). Evidence said A was fenced; A was not operationally fenced. <!-- /historical -->

Closure: the linear token is admission, and every mutation consumes it

LifecycleHead is renamed LifecycleAdmission: it is no longer knowledge with a linear identity, it is the single serialization point that makes a mutation current. LifecycleState remains descriptive knowledge.

Vacant + Admission ──attach(c)──► Attachment + AttachRecord + Admission'
Attachment + Admission ──detach()──► Vacant + DetachReceipt + Admission'
Warden(&) + Admission ──finalize_loss──► LossFinalization + Vacant + Admission'
  • Each transition CONSUMES the admission and returns the successor; the

evidence record it emits describes an already-serialized transition (records stay Copy; they are no longer the later operation that makes a completed mutation current).

  • Every failure path returns the un-consumed capability AND the

un-consumed admission with the error, so a retry cannot mint duplicates and a wrong call never destroys linear state. <!-- historical -->

  • The R0.4.6 append and reopen_after_closure are DELETED: finality

now materializes the successor vacancy atomically with the admission advance, so no second mint path for a vacancy exists, and the warden's min_generation fence became unnecessary. <!-- /historical -->

  • suspend/recover_attachment do not change lifecycle state; recovery

is judged against &Admission (borrowed) exactly as in R0.4.6.

  • Public replay_lifecycle/audit_replay over slices remain

descriptive; a LifecycleState cannot be passed where an admission is required (type error).

Operational fencing (form 3)

A stale LocusAttachment may remain representable, but every mutation requires the current admission, which now records Attached(B,1) or Vacant(1): the stale value's detach fails (WrongGeneration / WrongCarrier) and hands the stale value back, powerless; its suspend() custody cannot recover (CustodyMismatch). stale capability + no current admission = powerless.

Who holds the admission

The admission is the controller-side serialization point; carriers hold capability values. Orderly attach/detach need the carrier's value AND the admission; finality needs the warden AND the admission and no carrier cooperation — so a physically lost carrier (its attachment value gone) can still be finalized by the admission holder. Admission hand-off between parties is an explicit move in the one-process model.

Boundary (unchanged)

One-process safe-Rust model. No consensus/leases; no durable crash recovery (a persisted admission is bytes); trusted-root lineage forks remain outside the claim (Locus-birth uniqueness is World-level).

Falsifiers (the review's eight)

  1. detach-then-competing-finality cannot yield two usable vacancies.

  2. consuming a vacancy to attach B leaves no path to a C at that

generation, with no separate persistence step involved.

  1. post-finality stale Attachment(A,N) cannot detach or create a successor.

  2. stale vacancy/attachment values without the admission cannot mutate

(runtime + type-level: no admission-free transition exists).

  1. one admission admits exactly one mutation (reuse → E0382).

  2. failure paths return linear state; retry succeeds without duplicates.

  3. all R0.4.1–R0.4.6 falsifiers remain green.

  4. replay is descriptive; a LifecycleState is not an admission.

Open in the interactive atlas