Skip to content

Security: owner-engineering archive successor contract v1 (repairs archive-reproducibility, 25 workflows) - #116

Merged
HMarcusWH merged 1 commit into
mainfrom
security/archive-tooling-closure-v2
Oct 31, 2026
Merged

HMarcusWH merged 1 commit into
mainfrom
security/archive-tooling-closure-v2

Conversation

@HMarcusWH

@HMarcusWH HMarcusWH commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

What this repairs

The required archive-reproducibility check has failed with E_TOOLING_CLOSURE ("Complete canonical code/guide closure differs between T and C") on every head since two reviewed integrity files changed after the historical tooling snapshot T 71cc34fa:

  • verification/integrity/workflow_contract.py
  • verification/integrity/tests/test_workflow.py

The v0.2.0 verifier requires the current verification/integrity/, verification/archive/ and guide closure to equal T's. That fails on main, on PR #115, and on PR #113's own final head 117f4905 (run 40778332081). The archive is not damaged. At the accepted base B 17c315f7, the full check including committed publication passed (run 39513915824).

The staged 30-workflow T2 candidate cannot be switched on as a fix. Its inherited verifier needs all twelve required checks of #113's final head to have succeeded, but archive-reproducibility failed there. It also needs an APPROVED review from an owner-authorized roster, but #113 has only COMMENTED bot reviews and the roster is UNCONFIGURED. This PR is the narrow route the owner chose: repair the archive check for the existing 25 workflows, approved under a transparently named owner engineering policy.

How the new gate works

The archive job's last step now runs verification/research/archive_successor_gate_v1.py instead of the candidate-bound equality check. The archive adversaries still run first, unchanged.

  1. Historical T, verified by T's own code. A fresh, clean clone at T runs T's unchanged python -B -m verification.archive.offline_smoke:

    • in standalone mode, on the committed supplement;
    • with T's own nonroot unshare --net/setpriv isolation;
    • with no GitHub, Git, token or import variables.

    The gate accepts only an isolated, T-bound, accepted-artifact-scope PASS with the original stage list. I checked those expectations against the real report from B's passing run. Standalone mode compares the packaged tooling with the code that executes, so a pass also proves T's code ran, not C's. A blocked replay stays BLOCKED.

  2. Current C, checked as Git objects. C must be the checkout HEAD, with no modified tracked files. pr113_tooling_migration.audit (reused, not reimplemented) checks:

    • T and B are ancestors of C;
    • the supplement is unchanged since B;
    • the 35 packaged T files are byte-exact;
    • only the two named closure files differ;
    • there are 25 workflows.

    The gate adds stricter checks:

    • the whole archival/v0.2.0 tree equals B's;
    • each changed closure file is at exactly its approved blob;
    • research-integrity.yml is exactly the approved change of its preactivation blob;
    • C's own run_tests --suite workflow passes with no skips.

    The source audit is repeated after both legs.

  3. Approval. archive_successor_policy_v1.json has authority OWNER_ENGINEERING_POLICY, owner HMarcusWH and independent_security_review: false. The gate rejects true. The policy takes effect only through the owner's merge. It is not an independent security review, not a PR WIP: finish mathematical implementation and verification infrastructure (certify in successor PR) #113 approval, not certification and not release acceptance. The PR WIP: finish mathematical implementation and verification infrastructure (certify in successor PR) #113 final-head failure stays recorded as a failure, and the gate does not depend on it.

Any third closure change, or a later edit of an approved file, fails with E_SUCCESSOR_DELTA until the policy is changed and merged again.

Files

Path Change
.github/workflows/research-integrity.yml archive step runs the gate; evidence directory added to the existing upload
verification/integrity/workflow_contract.py archive command, required-verifier list and APPROVED_WORKFLOW_SHA256
verification/research/archive_successor_gate_v1.py, archive_successor_policy_v1.json, test_archive_successor_gate_v1.py new gate, policy and 19 tests
verification/research/archive_successor_approval_v1.py stdlib helper that parses the single approved workflow change
verification/research/pr113_a2_successor_identity.py the two pins for the changed files
pr113_workflow_profile_v2.py, pr113_successor_workflow_profile.py, pr113_atomic_migration_preview.py and three of their tests the inactive 30-workflow candidate's "original 25 unchanged" checks accept exactly the owner-approved change, read from the policy at the inspected head, and still reject anything else
docs/operations/ARCHIVE_SUCCESSOR_CONTRACT_V1.md runbook

Unchanged: the historical bundle, verification/archive/, every recorded hash, the packaged T snapshot, verify_bundle.py (nothing relaxed), the workflow count (25), and the staged candidate's manifests, sources and review packet. No test is skipped or removed.

Evidence at 9054a48

  • Gate tests: 19/19. Each covers a rejection path: policy mutations, stale or foreign approvals, report forgeries (wrong binding, missing isolation, skipped or added stages, candidate-CI scope), blocked and failed legs, a mutated T checkout, source drift, output overlap, environment scrubbing and the process-group timeout kill.
  • Integrity suites: workflow 8/8, context, reference, preservation and tex pass. In archive, only the real-namespace case fails locally, identically on main, because it needs a nonroot runner.
  • All 257 existing research test modules give the same result on main and on this branch. This was run without Lean in the worktree; the Lean-dependent modules fail identically on both.
  • Running the gate CLI on this repository passes its policy and source audit, then reports BLOCKED as root, which T's launcher requires.
  • Genuine isolated T replay, in this PR's own CI (Research integrity run 41207232823): archive-reproducibility passed for the first time since the tooling changed.
    • T's own verifier ran in standalone mode as uid 1001, with network isolation ENFORCED and all capabilities zero.
    • It completed all 12 original stages, including the legacy 29-test replay ("Ran 29 tests … OK"), "FINAL kit verification PASS: 21 pages, 17 claims, 340 protected canonical blobs", and the C10 consistency check with its audited axioms.
    • The gate passed all 8 of its stages. The current-C workflow suite ran 8 methods and passed. Approval is recorded as OWNER_ENGINEERING_POLICY, independent_security_review: false.
  • Every other check on 9054a48 is green: Research Lean (the full research suite, axiom audit, C10, D0-F, default target, root imports, placeholder rejection), Lean, Executable verification, Application contract on Ubuntu and Windows, Integrity portability, frozen-source preservation and release-export integrity.

The owner has instructed that this PR be merged once it is green. That merge is the owner-engineering approval event recorded in the policy.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KdhJ3TNPDaXGbNLXiKuZPC

…r the 25-workflow profile

The required archive-reproducibility check has failed with E_TOOLING_CLOSURE
on every head since two reviewed integrity files (workflow_contract.py,
tests/test_workflow.py) changed after the historical tooling snapshot T
71cc34f: the v0.2.0 verifier requires the current integrity/archive/guide
closure to equal T's. That includes main and PR #113's final head 117f490
(run 40778332081). At the accepted base B 17c315f the full check passed
(run 39513915824).

The archive job's last step now runs
verification/research/archive_successor_gate_v1.py instead of the
candidate-bound equality check. It runs two legs:

- Historical T: a fresh clean clone at T runs T's own unchanged
  verification.archive.offline_smoke in standalone mode on the committed
  supplement, with T's nonroot network-namespace isolation and no GitHub, Git,
  token or import variables. Only an isolated, T-bound, accepted-artifact PASS
  with the original stage list is accepted (checked against the real report
  shape of B's passing run). Standalone mode compares the packaged tooling
  with the executing code, so a pass also proves T's code ran. A blocked
  replay stays BLOCKED.
- Current C: HEAD equals the candidate with no modified tracked files.
  pr113_tooling_migration.audit checks T/B ancestry, the supplement unchanged
  since B, the 35 packaged T files byte-exact, the closure differing in
  exactly the two named files, and 25 workflows. The whole archival/v0.2.0
  tree must equal B's; each changed closure file must be at exactly its
  approved blob; research-integrity.yml must be exactly the approved change of
  its preactivation blob; and C's own workflow integrity suite must pass. The
  source audit is repeated after both legs.

archive_successor_policy_v1.json records the approval as an OWNER ENGINEERING
POLICY. It becomes effective through the owner's merge and is never an
independent review: the gate rejects independent_security_review=true. It
pins the approved blobs and keeps the PR #113 final-head failure as recorded
history; the gate does not require it to have succeeded.

Pins that track these bytes move with this change: APPROVED_WORKFLOW_SHA256,
the archive command and the required-verifier list in workflow_contract.py,
and the A2 successor identity pins.

The inactive 30-workflow candidate requires the original 25 installed
workflows to be unchanged. Its checks and tests now accept exactly the one
owner-approved change, read from the policy committed at the inspected head
through archive_successor_approval_v1.py, and still reject any other
difference. Its manifests, staged sources and review packet are unchanged.

The historical bundle, verification/archive/, every recorded hash and the
packaged T snapshot are unchanged, and nothing in verify_bundle.py is
relaxed. The runbook is docs/operations/ARCHIVE_SUCCESSOR_CONTRACT_V1.md.

Local, without Lean in the worktree: all 257 existing research test modules
give the same result on main and on this branch, and the new gate module
passes 19/19. The integrity suites workflow, context, reference, preservation
and tex pass; the archive suite's real-namespace case needs a nonroot runner
and fails identically on main. The gate CLI on this repository passes its
policy and source audit, then reports BLOCKED as root, as T's launcher
requires. The genuine isolated T replay runs in CI only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KdhJ3TNPDaXGbNLXiKuZPC
@HMarcusWH
HMarcusWH marked this pull request as ready for review October 31, 2026 14:44
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-31T14:45:17.498732Z 9054a48 Draft marked ready
🔒 Security Review ✅ Completed 2026-10-31T14:48:38.450978Z 9054a48 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@HMarcusWH
HMarcusWH merged commit 0800556 into main Oct 31, 2026
9 checks passed
HMarcusWH pushed a commit that referenced this pull request Oct 31, 2026
…tatus

The installed-wheel CI run reported APP_INTERNAL instead of BUDGET_MEMORY
for a 20 MB budget. Under very low limits the child could fail before
its own handlers ran: the dynamic loader could not map a shared library
(exit 127), interpreter startup failed to initialise importlib, or the
jsonschema extension failed to load and was misreported as a missing
extra (SCHEMA_DEPENDENCY).

The budgeted child now starts under the 2 GiB default ceiling and lowers
its own RLIMIT_AS to the configured value once the interpreter and the
application's code are loaded, before it reads the request. The limit is
on total address space, so request work stays within it. Memory failures
that still surface as ImportError or ENOMEM, in the child or before it
runs, are classified as BUDGET_MEMORY; other failures are not relabelled.
A sweep from 6 MB to 62 MB now yields only BUDGET_MEMORY or success.

Docs: the archive-reproducibility repair is on main (#116, owner-
engineering policy, not an independent security review); the ROADMAP,
README, acceptance status, bridge guides and the PR115 archive diagnosis
note say so, and branch-status wording no longer goes stale on merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KdhJ3TNPDaXGbNLXiKuZPC
HMarcusWH pushed a commit that referenced this pull request Nov 1, 2026
The numeric release 0.2.0 is published as permansson-app-v0.2.0 (commit
63a66c8, release workflow run 41313849870). The documentation still
described it as an unreleased candidate and the release workflow as a
pending change. This change touches documentation and the implementation
manifest only. The release, its tag and assets, the package code, the
workflows and every pinned file are unchanged.

- Application README: release status, how to download, check and install
  the published wheel, and the release workflow as the app's one workflow.
- RELEASE_ACCEPTANCE: the workflow is installed (#118); a Released versions
  table with the commit, run and hashes; the local re-verification after
  publication; rebuild-and-compare commands that were run as written.
- ACCEPTANCE_STATUS, ROADMAP, ARCHITECTURE, ACCEPTANCE, IMPLEMENTATION_OVERVIEW
  and the docs index: released and installed states; the remaining gates.
- Root README and the archive successor contracts: release link; the
  contracts are in effect since #116 and #118 were merged.
- IMPLEMENTATION_MANIFEST: the 29 planned rows still marked
  REQUIRED_BEFORE_RELEASE are now DEFERRED_ALTERNATE_LAYOUT. The release
  was qualified without them, by the installed-distribution runner and the
  release gate, which are listed as related files. The candidate hashes of
  the changed documents and the current inventory are refreshed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KdhJ3TNPDaXGbNLXiKuZPC
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.

2 participants