Skip to main content

Module validator_snapshot

Module validator_snapshot 

Source
Expand description

Copy-on-write immutable validator snapshot — the definitive fix for the gap ticket validator-immutability-proof left open (and named in its “Remaining gap” section): “read-only” validator sessions ran in the mission’s REAL session checkout, so the tamper fingerprint (crate::validator_integrity) could only catch writes at session boundaries and never saw write-then-revert inside the window.

With this module the validator never sees the real checkout. Before each validator session (the primary and the single retry — the same sites the fingerprint wraps) the orchestrator builds a THROWAWAY snapshot of the session checkout under the mission’s gitignored runs/ scratch:

  1. git worktree add --detach <path> <head> — the tree at HEAD, sharing the object store (no clone cost).
  2. The worker’s uncommitted state is replayed into it: git diff --binary HEAD captured in the real checkout and git applyed in the snapshot (tracked edits, staged or not), plus a byte copy of every untracked non-ignored file. Validators judge exactly the tree the worker left.
  3. The snapshot’s target/ is a COPY of the real checkout’s — the warm-target constraint. Contract commands (cargo test …) must not pay a cold full-workspace rebuild (~50 min in this repo): APFS clonefile (cp -c) when the filesystem supports it (instant, copy-on-write blocks), Linux reflink (cp --reflink=always) otherwise, a plain byte copy when the target is small enough, and — logged, naming the cost — a fresh empty target when no acceleration exists and the copy would be prohibitive. The real target/ is NEVER shared or symlinked: a validator poisoning shared build artifacts would inject into the real deliverable build.

The session’s cwd, the validator’s contract-command cwd, and the sandbox profile’s session_cwd all point at the snapshot, so where the sandbox can express it the real checkout is not even in the writable set. Only the verdict (PASS/FAIL/findings) crosses back; the snapshot is discarded after the round regardless of outcome (RAII, mirroring preflight.rs’s DisposableWorktree idiom). The deliverable gates and the out-of-contract sweep keep running against the REAL checkout.

The snapshot is physical separation, NOT containment (13th-pass review, P1 — ticket validator-mandatory-containment): the worktree sits underneath the real repository hierarchy and references the shared git directory, so an UNWRAPPED validator (enforce: off, the old default) could still walk to the real checkout, modify tests, run them, and restore the bytes — modify → use → restore leaves no drift for the tripwire to catch. The mandatory validator wrap (crate::sandbox::resolve_validator_containment) closes that: every validator session runs under a Seatbelt/bwrap profile regardless of sandbox.enforce, with the snapshot as the sole writable root, the real checkout’s source tree read-denied, and the shared .git readable but write-denied. Where the platform or backend cannot contain, the resolution FAILS CLOSED by default (ticket validator-containment-degrade-fail-closed); only the explicit validatorAllowUncontainedDegrade opt-in runs the round anyway, with the loud degradation decision recorded and the snapshot plus the tripwire as the remaining layers.

Two honest limits, both covered by the fingerprint-turned-tripwire on the real checkout:

  • The file tree is isolated; git REFS are not. Worktrees share the common .git, so a validator git branch -f in the snapshot still moves shared refs where no containment applies — which the tripwire’s for-each-ref half catches at session end. (Under the mandatory wrap the ref write is hard-denied by deny-default; the tripwire is the defense-in-depth for the degraded platforms.) A drift event now means the isolation itself failed.
  • Under an enforced sandbox the snapshot’s gitdir (.git/worktrees/<n>) lives outside the writable session_cwd, so validator git commands that try to refresh the index degrade (read-only git still works; commits fail — which validators should never need).

Structs§

ValidatorSnapshot
RAII guard for one validator session’s throwaway checkout. Drop removes it best-effort — git worktree remove --force (which also deletes the directory), a dir sweep for anything git declined, and a prune of stale administrative entries — so pass, fail, tamper-block, or error return can never leak it.

Enums§

TargetCopyTier
Which tier warmed the snapshot’s target/ — recorded on the validation.snapshot event.