Repository navigation
Batch D: conformance golden vectors + spawn-audit hardening (P6 on-ramp) - #23
Merged
Merged
Conversation
The last named on-ramp before the Rust port (VISION.md Phase 6). Two disjoint
all-additive lanes; the only reference edit is isolation.py (not core-serialized).
VECTORS (decima/vectors.py + protocol/reference_vectors.json + check 510):
the machine-checkable port contract. build() re-derives, deterministically from
the running heartbeat reference through its public API, the full golden set —
canonical bytes + domain-separated content/event ids (key-order invariance, NFC
collapse, big ints, empty containers), blob ids, named + self-certifying keyed
principal derivation with Ed25519 public keys, deterministic Ed25519 signature
vectors, and a fixed ASSERT/RETRACT fold script (TYPE_DEF, versioned CONTENT, a
capability grant, its downhill attenuation, a typed EDGE, a RETRACT) reduced to
one state_root. The committed JSON is the code's frozen output, and check 510 is
a two-way lock: build() must equal the committed bytes (any drift in canonical
encoding / id derivation / signing / fold turns the reference oracle RED), and
every property is re-verified from first principles (domain separation, NFC-equal
ids, keys reproduce, keyed pids self-certify, signatures verify, one-byte tamper
fails closed, the script re-folds to the golden state_root, a tampered replayed
byte is caught on read). A Rust port is correct iff it reproduces this file.
SPAWNAUDIT (isolation.py + check 512): assert_no_raw_spawn, hardened beyond
name-matching. (A) the static scan now refuses the laundering surface a re-adder
would use to keep a spawn primitive out of the AST — reflective access
(getattr/setattr/vars/globals/locals), namespace tables
(__globals__/__builtins__/__dict__), and sys.modules[X] for any index but the
sanctioned sys.modules[__name__] self-pass; the check shows the counterfactual
(three laundered modules that pass the original four-rule scan are all refused,
while executor/cli_worker and the self-pass idiom still pass). (B) a new
spawn_firewall() moves enforcement to the interpreter audit boundary (PEP 578
sys.addaudithook): inside an armed region a spawn-family syscall raises
IsolationError however it was spelled — proven with a laundered
getattr(os,"sys"+"tem")("true") blocked before the child exists — while the
sanctioned door (spawn_worker, now wrapping its Popen in sanctioned_spawn())
still opens, and the firewall is scoped/lazy so it cannot break legitimate raw
spawners or the wider test runner.
Full oracle green 226 -> 228 checks (heartbeat: alive., exit 0), run under an
unprivileged uid (check 394's RLIMIT_NPROC fork assertion needs a non-root user
to bite; root bypasses the limit — an environment property, orthogonal to this
batch). Batch D done; P6 (the single Rust port) is unblocked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ath9hAwj37EriRGEDrj9a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last named on-ramp before the Rust port (VISION.md Phase 6 / the Cycle-57 audit's Batch D). Two disjoint, all-additive lanes; the only reference edit is
isolation.py, which is not a core-serialized file. Full heartbeat oracle green 226 → 228 checks (heartbeat: alive. ✓, exit 0).Why now
Phase 6 (the single Rust port) is gated on two things Batch D delivers: a machine-checkable statement of what a port must reproduce, and the one enforcement seam a port will fossilize being as strong as it claims.
VECTORS — the port contract, frozen
decima/vectors.py+protocol/reference_vectors.json+heartbeat/checks/510_reference_vectors.pybuild()re-derives — deterministically, from the running heartbeat reference through its public API only (fixed all-zero master seed, fixed event script, no wall-clock, noos.urandom, no floats) — the full golden set:évs.e+combining-acute to one identity, arbitrary-precision ints, empty containers);pid = blake2b(name)and self-certifying keyedpid = blake2b(pubkey), each with its Ed25519 public key;state_root.The committed JSON is the code's frozen output, not a hand-authored fixture. Check 510 is a two-way lock: (1)
build()re-run in-process must equal the committed bytes, so any change to canonical encoding / id derivation / the signing scheme / the fold turns the reference oracle RED the moment it lands; (2) every property is re-verified from first principles (domain separation, NFC-equal ids, keys reproduce, keyed pids self-certify, each signature verifies and a one-byte tamper fails closed, the script re-folds to the goldenstate_root, a tampered replayed byte is caught on read). A Rust port is correct iff it reproduces this file byte-for-byte.SPAWNAUDIT — the seam is a syscall floor, not just a name scan
heartbeat/decima/isolation.py+heartbeat/checks/512_spawnaudit.pyCloses the backlog's named weakness ("harden
assert_no_raw_spawnbeyond name-matching"):getattr/setattr/vars/globals/locals), namespace tables (__globals__/__builtins__/__dict__), andsys.modules[X]for any index but the sanctionedsys.modules[__name__]self-pass. The check shows the counterfactual: three laundered modules that pass the reconstructed original four-rule scan (no literal spawn token) are all refused, whileexecutor/cli_workerand the self-pass idiom still pass (no false positive).spawn_firewall()moves enforcement to the interpreter's audit boundary (PEP 578sys.addaudithook): inside an armed region a spawn-family syscall raisesIsolationErrorhowever it was spelled — proven with a launderedgetattr(os, "sys"+"tem")("true")(no.systemin its AST) blocked before the child exists, plussubprocess.Popen/os.posix_spawn. The sanctioned door (spawn_worker, now wrapping its ownPopeninsanctioned_spawn()) still opens under the same active firewall, and the firewall is scoped (inert outside its region; hook installed lazily on first use) so it cannot break the interpreter's legitimate raw spawners (process_effect's gated CLI effect, the MCP stdio transport) or the wider test runner.Testing
cd heartbeat && python3 smoke.py→heartbeat: alive. ✓, exit 0, 228 checks.394_isolation'sRLIMIT_NPROCfork sub-assertion only bites for a non-root user (root bypasses the limit) — an environment property, unchanged by and orthogonal to this batch. Under an unprivileged user the full oracle is green, as the release harness runs it.cd heartbeat && python3 -m decima.vectors(never hand-edit the JSON).Follow-up
Batch D — the last named on-ramp — is done. P6 (the single Rust port) is unblocked; its first move is a Rust kernel that reproduces
protocol/reference_vectors.jsonbyte-for-byte, validated against check 510's contract.🤖 Generated with Claude Code
https://claude.ai/code/session_012ath9hAwj37EriRGEDrj9a
Generated by Claude Code