Skip to content

Producer signatures + two-class base-judged PRs for the witnessed journal#94

Merged
MaxGhenis merged 1 commit into
codex/thesis-ledger-factsfrom
producer-signing
Jul 11, 2026
Merged

Producer signatures + two-class base-judged PRs for the witnessed journal#94
MaxGhenis merged 1 commit into
codex/thesis-ledger-factsfrom
producer-signing

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Adds Ed25519 producer signatures (fourth release sibling, genesis retro-signed, SPKI-pinned committed public key) and the two-class PR rule with base-ref gate isolation, adapted from the Axiom corpus signing architecture. Full rationale in the commit message and releases/README.md.

Bootstrap note: the predecessor gate cannot admit its own successor — the genesis .producer.sig is a release-file addition without a ledger append, which the OLD gate correctly refuses. This PR is therefore the one-time documented bootstrap merge, exactly like genesis itself: the incoming gate validates this state (verify_release_chain --full passes with the signature required), the push-time CI on the merged branch re-verifies immediately, and every subsequent PR is judged by this code as base. Follow-up tracked: install the pull_request_target trust-root job on the default branch + ruleset-required workflow.

🤖 Generated with Claude Code

…rnal

Adapted from the Axiom corpus signing architecture. Every release now
carries a fourth sibling, NNNN-<hash16>.producer.sig: a raw Ed25519
signature over the manifest's exact bytes, verified against the committed
releases/anchors/producer-ed25519.pub whose DER SPKI sha256 is pinned in
code (same pattern as the TSA anchor pins). The genesis release is
retro-signed in this commit, and verification requires a valid producer
signature on every release unconditionally — an admin push carrying a
valid manifest triple but no authorized signature is now detectably
unsigned, closing the authorship gap documented in releases/README.md.

PRs are split into two classes enforced by the gate itself: a change to
GATE_SURFACE (gate, verifier, canonicalization, cutter, workflow, anchors)
may not touch ledger/** or releases/manifests/**, and vice versa. For data
PRs the workflow checks out the BASE commit's gate surface into a detached
directory and judges the PR with the base's code — the PR's own gate copy
is never executed — mirroring the axiom-corpus base-ref verifier
isolation. A pull_request_target job (sourced by GitHub from the default
branch, not the candidate) is added as the future unspoofable trust root;
installing it on the default branch plus a ruleset-required workflow is a
follow-up, and until then the ordinary pull_request job performs the same
detached-base invocation. The cutter signs via key path only (--signing-key
/ --no-sign), never reading private-key bytes into Python, with staged
verification and dirfd-anchored atomic writes. Ed25519 verification uses
the cryptography package with an exact OpenSSL 3 fallback.

Implemented by GPT-5.6 Sol to its own spec; reviewed, integrated, and
genesis-signed by the orchestrator (private key never entered the
implementation checkout). 99 tests pass including adversarial signature,
mixed-PR, and base-isolation cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis merged commit 8470a7e into codex/thesis-ledger-facts Jul 11, 2026
3 of 6 checks passed
@MaxGhenis MaxGhenis deleted the producer-signing branch July 11, 2026 18:41
MaxGhenis pushed a commit to MaxGhenis/brier that referenced this pull request Jul 11, 2026
Upstream (PolicyEngine/ledger#94) added Ed25519 producer signatures as a
fourth release sibling and refuses unsigned proposals. This keeps brier
ahead of the next resolution cycle on both sides of that boundary.

Producer: propose_ledger_append signs each new manifest's exact bytes
before any remote object exists. The private key arrives only as the
LEDGER_PRODUCER_SIGNING_KEY env var (wired to exactly one workflow step),
is popped from the process environment before any network client can
inherit it, is materialized solely as an O_EXCL 0600 file in a 0700
tempdir for an argv-only openssl invocation, and is unlinked in finally.
The signature self-verifies against the public key taken from the fetched
BASE tree's committed anchor — not a local copy — and the staged
four-sibling release is fully verified before the proposal branch or PR
is created. Missing secret, signing failure, or self-verify failure abort
with no visible partial state and without leaking diagnostics.

Consumer: the vendored verifier is re-vendored byte-for-byte from the
post-#94 upstream, so pin refreshes now require a valid producer
signature on every historical release, refuse unsigned or wrong-key
states and tampered anchors (SPKI pin), and history-bind signature blobs
like receipts. Witness runs archive and inventory-bind .producer.sig
bytes into custody alongside manifests and receipts.

Implemented by GPT-5.6 Sol; reviewed and integrated with the real key
never entering the implementation checkout. 231 tests pass across the
pin, resolver, witness, registration, and publication suites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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