Repository navigation
Description
Summary
Design #2898 recorded the rule for pkgs/id — reconstruction is admission: authority-bearing data is validated when created live, so it must be validated where it is rebuilt. Its six origins were the journal seams known that evening. Four more instances have since been filed, in three shapes its phases did not cover — two of them in state that did not exist when #2898 was written:
- id(world): WorldCore::restore installs checkpoint-carried handoff transfers unvalidated — duplicate sides, non-advancing import epochs, and sequence-claiming transfer events all accepted, unlike the standalone entries #3942 — checkpoint-carried handoff state is installed, not validated. The region-seam transfers added by id: implement: journaled region-seam export/import #3870 phase 1 (PR feat(id): region-seam handoff journal foundation (#3900) #3922) are checked strictly as standalone
EntityExported/EntityImportedentries (core.rs:322-375), but aCheckpoint'stransferslist is assigned verbatim (core.handoff_transfers = transfers.unwrap_or_default(),core.rs:504): duplicate(handoff_id, direction)sides, a non-advancing import epoch, and a sequence-claiming transfer event all restoreOk(laptop probe against the realrestore), while the same arm validates the profile, the caps ceiling, and schedule agreement for everything else it carries. Compaction launders bad transfer state into the canonical durable form. - id(world): restore's checkpoint consecutiveness check uses plain + 1 — a penultimate u64::MAX sequence panics in debug/test builds and wraps to an accepted MAX → 0 step in release #3736 + id(world): restore's EntityImported epoch check uses plain + 1 — prior=u64::MAX wraps to an accepted epoch 0 in release and panics in debug/test #3961 — restore's own succession checks use a plain
+ 1, the only two admission predicates incore.rsthat do (every sibling useschecked_add/saturating_add). Checkpoint event consecutiveness (core.rs:476) accepts a wrappedu64::MAX → 0step in release and panics in debug; theEntityImportedepoch advance (core.rs:368) acceptsprior = u64::MAX, new = 0in release — the fencing epoch going backwards — and panics in debug. - id(waiting): WaitingPool::restore ignores the arrived and ready-queue duplicate guards — an already-applied or ready event is held again and handed out a second time #3911 —
WaitingPool::restore(id-corewaiting.rs:312) checks only already-held;insertandparkboth also refuse arrived and ready-queue keys (the guard set closed id(waiting): WaitingPool::insert's duplicate guard misses the ready queue — the same key inserted twice before take_ready is handed out twice #2001 established). The event store routes every hold throughrestore, so an already-applied event can be held and handed out a second time. One caller (the fork-proof park) relies on the gap on purpose — see decision 3.
#2898's closing-audit scope (sandbox snapshot, restore_program, petname persistence) names none of these surfaces; the transfers field did not exist then. This design is #2898's follow-on — the same pattern as #2497 following #1554 — and re-scopes none of its phases.
Full design doc: files/designs/code-id-restore-admission-followon.md in the keep-the-four-repos-healthy goal workspace. Audit baseline: origin/main 83709fac (all sites below read verbatim at HEAD this pass).
The contract
Every path into state is admission. State that arrives carried inside a reconstruction container is validated item-by-item with exactly the rules its standalone form is validated with, before it is installed. A succession predicate in an admission path is checked arithmetic: the successor of
u64::MAXdoes not exist, so the entry is refused — never wrapped to 0, never a panic. And a reconstruction entry point applies the same guard set as the live entry points of the same structure; any deliberate relaxation is a named, separate route, not a silent property of the restore path.
Recorded decisions
- Carried transfers are validated by the standalone rules, with the standalone errors — per element, in list order, before assignment: no duplicate
(handoff_id, direction); an import'snew_owner_epochis the checked successor ofprior_owner_epoch; an export carries nonew_owner_epoch(id(world): WorldCore::restore installs checkpoint-carried handoff transfers unvalidated — duplicate sides, non-advancing import epochs, and sequence-claiming transfer events all accepted, unlike the standalone entries #3942's acceptance); each transfer'seventhassequence == 0 && participant_id == 0. Refusal aborts the whole restore. One shared per-transfer validation helper is preferred so the arms cannot drift a third time, but the contract is the equivalence, not the refactor. Replaying transfers through the standalone arms loses (the arms push replay events and bump counters; checkpoint transfers are already-applied state). - Succession is
checked_add, notsaturating_add. Saturation would letMAX → MAXpass an advance check; it is the right idiom for counters that may sit at a cap (since_checkpoint) and the wrong one for a predicate whose job is that the value moved. The two filed sites are the wholecore.rsinventory (grep-verified this pass); the closing audit greps the rest ofpkgs/id. - The waiting pool's guards are the pool's guards — with the proof park made explicit.
restoregains the ready-queue guard unconditionally and the arrived guard on its hold path. The deliberate exception —present_proofre-holding an arrived fork-proof header for good so its conflicts stay seen — becomes an explicit held-for-good route (apark-style entry), not a borrowed missing guard. Copyinginsert's guard verbatim without moving the proof caller loses: it silently un-parks proof headers.restore's capacity posture (larger-cap stores still open; excess drops, never wedges) is unchanged. - No wire-format or writer change. Live writers cannot produce any refused state — standalone validation is what they already pass, and id(world): WorldCore::restore installs checkpoint-carried handoff transfers unvalidated — duplicate sides, non-advancing import epochs, and sequence-claiming transfer events all accepted, unlike the standalone entries #3942's controls show a valid checkpoint restores
Ok— so restore strictness is safe for every journal live code can write (Design: reconstruction is admission — validate authority-bearing inputs where they are rebuilt (pkgs/id) #2898's original strictness argument).
Alternatives that lose (in the doc): folding these into #2898's Phase 3 audit (a named bounded scope inside #2882/#2876; stretching it re-scopes their acceptance from a comment); a Phase 1 bound on the transfers list (no cap value is recorded anywhere — the closing audit dispositions it instead).
Phased breakdown
- Phase 1 — checkpoint-carried handoffs are validated (adopted: id(world): WorldCore::restore installs checkpoint-carried handoff transfers unvalidated — duplicate sides, non-advancing import epochs, and sequence-claiming transfer events all accepted, unlike the standalone entries #3942). Per its acceptance. Lands first: the trust-boundary hole, and id: implement: journaled region-seam export/import #3870's coordinator phases 2–5 assume the dedupe/epoch invariants it protects.
- Phase 2 — succession is checked arithmetic (adopted: id(world): restore's checkpoint consecutiveness check uses plain + 1 — a penultimate u64::MAX sequence panics in debug/test builds and wraps to an accepted MAX → 0 step in release #3736 + id(world): restore's EntityImported epoch check uses plain + 1 — prior=u64::MAX wraps to an accepted epoch 0 in release and panics in debug/test #3961). Both predicates become checked-successor comparisons;
u64::MAXboundary tests at each site (refusal must be restore's own error in both build profiles); same-file grep proof. Independent of Phase 1 in code — but Phase 1's carried-import epoch check uses the checked form, so whichever lands second writes that predicate in its final shape exactly once. - Phase 3a — the waiting pool's restore applies the pool's guards (adopted: id(waiting): WaitingPool::restore ignores the arrived and ready-queue duplicate guards — an already-applied or ready event is held again and handed out a second time #3911). Per its acceptance and decision 3 (explicit proof-park route, behaviour pinned by test). Independent of Phases 1–2 (different crate).
- Phase 3b — closing audit (new issue, gated on Phases 1, 2 and 3a). Reconstruction-entry-point inventory for
pkgs/idwith a disposition per surface (citing Design: reconstruction is admission — validate authority-bearing inputs where they are rebuilt (pkgs/id) #2898 Phase 3's outcomes where scopes overlap rather than re-auditing); a crate-wide grep disposition for plain arithmetic inside admission predicates; the transfers-bound disposition; a cross-note on Design: reconstruction is admission — validate authority-bearing inputs where they are rebuilt (pkgs/id) #2898.
Open questions stay in the design doc (a bound on active handoffs — no recorded value, dispositioned by Phase 3b; snapshot-content equivalence — #2898 Phase 3's scope, cited not duplicated; store-row cleanup for arrived/ready refusals on reload — Phase 3a triage records it).
Related: #2898 (parent design — a follow-on note is posted there), #3870 (its phases 2–5 are untouched implementation work), #3231 (same crate, different gate — artifact parsed(), no field overlap). Not this design: #3963/#3964 (BoardGraph live-construction checks, no reconstruction surface); #2882's schedule arithmetic (a live-path check, stays in #2898's scope — Phase 2 here is restore succession predicates only).
🤖 Design architect pass 34 (2026-11-01), audit at origin/main 83709fac.
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · design filed, pass 34
15 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · triage findings
f486f2aab6a98cf709a4b37659441f318eafa0f8. The local primarymaincould not fast-forward because it is 2 commits ahead and 43 behind; the task worktree was based on the fetched main snapshot, without moving or rewriting local commits.pkgs/id/src/world/core.rs,validate_handoff_transferenforces transfer event, duplicate-side, and checked epoch rules; checkpoint transfers are validated before installation. Checkpoint event succession useschecked_add(1). PR fix(id): reject wrapped checkpoint sequences #4498 and fix(id): checked epoch advance in restore EntityImported arm #4505 are MERGED for the succession fixes.WaitingPool::restorestill only checksby_keybefore callinghold, so the Phase 3a guard/proof-park work is not yet landed. Phase 3 (audit) of #4000 — closing reconstruction-admission inventory for pkgs/id #4001 is OPEN and queue-parked, and its body gates the closing audit on id(waiting): WaitingPool::restore ignores the arrived and ready-queue duplicate guards — an already-applied or ready event is held again and handed out a second time #3911 plus phases 1-2. Finish id(waiting): WaitingPool::restore ignores the arrived and ready-queue duplicate guards — an already-applied or ready event is held again and handed out a second time #3911 first, then resume Phase 3 (audit) of #4000 — closing reconstruction-admission inventory for pkgs/id #4001; no parallel implementation was started.queue/8331-4000-reconstruction-admission-triageat/home/user/git/fleet/8331(no code changes).dezren39 commentedon Nov 4, 2026
agent-note:v1
state: picked-up
queue: repo-health-code-pilot
task: 9199 (triage, worker repo-worker-code, lane ec118cad-0fd3-4652-91c4-27432f2f2efd)
by: openchamber-scheduled-lane
at: 2026-11-04T07:11Z
Issue #4000 is still OPEN and carries the expedite marker. A prior triage note for task 8331 says phases 1–2 are resolved, #3911 remains outstanding, and #4001 is gated; the queue claim evaporated before that routing was finalized. This run will freshly revalidate all phase issues and current main, then record the verdict and route without duplicating existing work.
dezren39 commentedon Nov 4, 2026
agent-note:v1
state: triaged (live; routed; no duplicate packet)
queue: repo-health-code-pilot
task: 9199 (triage, worker repo-worker-code, lane ec118cad-0fd3-4652-91c4-27432f2f2efd)
by: openchamber-scheduled-lane
at: 2026-11-04T07:15Z
Fresh revalidation: #4000 remains OPEN and expedite-labelled. Against current origin/main 8bb1e43, Phase 1 (#3942) is CLOSED and carried transfers are validated before installation; Phase 2 (#3736/#3961) is CLOSED and the succession checks use checked_add. Phase 3a (#3911) remains OPEN and queue-claimed/in-progress (task 6238); current
WaitingPool::restorestill checks only already-held keys and omits the arrived/ready guards. Phase 3b (#4001) remains OPEN and queue-parked (task 5934), gated on #3911.Verdict: the umbrella design remains live; keep #4000 open. The remaining work is already routed through active task 6238 and gated task 5934, so this triage did not enqueue a duplicate fix packet. No code changes or tests were made. Removed stale queue/triage claim labels; #4000 retains its expedite marker.