Skip to content

fix: HIGH-tier batch 1 — dead scope gate, set-hash + agent-ordering determinism, always-on parity gate#5

Closed
New1Direction wants to merge 5 commits into
fix/ledger-tenant-scopingfrom
fix/high-tier
Closed

fix: HIGH-tier batch 1 — dead scope gate, set-hash + agent-ordering determinism, always-on parity gate#5
New1Direction wants to merge 5 commits into
fix/ledger-tenant-scopingfrom
fix/high-tier

Conversation

@New1Direction
Copy link
Copy Markdown
Owner

First batch of HIGH-severity audit fixes (TDD, verified). Stacked on #4; base is fix/ledger-tenant-scoping.

Fixed in this PR

  • Dead SCOPE_MUTATION gate (governance) — the gate iterated WorkerResponse.artifacts (a List[dict]) as if it were a dict and guarded on isinstance(..., dict) (always False), so a worker could rewrite an immutable scope key (e.g. change the target domain) with no violation. Now scans each artifact and HALTs.
  • Set-bearing payloads hashed nondeterministically (determinism) — json.dumps(..., default=str) turned a set into str(set), whose order is PYTHONHASHSEED-dependent, so event_hash/payload_hash/reproducibility_hash/state_signature differed across processes. Added _canonical() (sets → sorted lists) at all hash sites. No-op for set-free payloads.
  • list(set(...)) in live agents (determinism) — pi_threat_model_generator + pi_zk_circom_underconstrained_sentry now use order-preserving dedup, so output byte order is hash-seed independent.
  • Determinism gates made unconditional (CI) — pin PYTHONHASHSEED=0; remove the paths: filter so the Rust↔Python parity gate runs on every PR (it was path-filtered, so a determinism break outside a few dirs could merge green).

Verification

  • Full CI Python suite: 1269 passed, 0 failed · Rust: 782 + 13 passed · ruff check + format clean.
  • Each code fix is RED→GREEN (subprocess hash-seed tests for the determinism ones).

Correction to the audit (honesty)

The audit listed a 5th high — the pi-semantic-governance.yml "dependency-confusion / dead merge gate." On inspection that file is untracked on every branch (never committed), so GitHub Actions never ran it: it's a latent risk if someone commits it, not a live CI vector as the finding implied. I left the untracked file in place (didn't create it; reality contradicts the finding) — recommend deleting it or never committing it.

Still open from the HIGH tier (next batch)

  • Mesh receipt hash folds wall-clock cpu_ms + TIMEOUT status (determinism)
  • Production receipt/audit IDs built from time.time() microseconds (determinism)
  • BashCommandHook command injection (shell=True + unsanitized interpolation)
  • Solidity sentry i64 overflow panic → use i128/guard (Rust parity)

🤖 Generated with Claude Code

PI Platform and others added 5 commits June 1, 2026 12:24
objective_tracker iterated worker_response.artifacts (a List[dict]) as if it were
a dict and guarded on isinstance(..., dict) (always False), so the entire
SCOPE_MUTATION branch was dead — a worker could rewrite an immutable scope key
(e.g. change the target domain or mode) with no violation. Now scans each
artifact dict in the list for a mutated scope key and HALTs. + regression tests.
json.dumps(payload, sort_keys=True, default=str) only orders dict KEYS; a set
value fell to str(set), whose order is PYTHONHASHSEED-dependent — so the
content-addressed event_hash/payload_hash/reproducibility_hash/state_signature
differed across processes for any set-bearing payload, breaking replay and
verify_partition_chain after a restart.

- core.py: add _canonical() — recursively converts set/frozenset to a
  deterministically-sorted list. Applied at all hash sites (event_hash,
  payload_hash, epoch coord hash) and in semantic_fabric (reproducibility_hash,
  state_signature). No-op for set-free payloads, so existing hashes are unchanged.
- test: real DomainEvent with a set payload now hashes identically across
  PYTHONHASHSEED=0..3 (was 4 distinct hashes).
… stable

pi_threat_model_generator and pi_zk_circom_underconstrained_sentry deduped with
list(set(...)) / set(...), whose iteration order depends on PYTHONHASHSEED — so
identical input produced different output byte order across processes, breaking
byte-identical replay. Switched to list(dict.fromkeys(...)) (insertion order).
Test: STRIDE_categories order is now identical across PYTHONHASHSEED=0..2.
…arity)

- ci.yml: pin PYTHONHASHSEED=0 (workflow-level) so set/dict iteration order is
  reproducible across runs — the byte-identical-output/replay guarantee assumes
  it, and it makes determinism regressions deterministically catchable.
- rust-core.yml: remove the paths: filter so the Rust<->Python byte-equivalence
  parity gate runs on every push/PR to main/develop. Previously a
  determinism-affecting change outside rust/** + 3 src dirs could merge green
  because the only parity gate never triggered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@New1Direction
Copy link
Copy Markdown
Owner Author

Consolidated. All commits from this PR are now in rust-core-loadbearing (fast-forwarded through the full stack), together with the 17 previously-uncommitted source files the package needed to import. The integration branch now imports cleanly, the committed test suite passes, and ruff/mypy/parse gates are green on a fresh checkout. Closing as superseded — history is preserved on rust-core-loadbearing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant