Repository navigation
release: v1.3.0 — speak the industry's language - #18
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t ahead of attestation work Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dentifier, Phase-2 version bump, transactional finalize, non-vacuous cosign negatives, honest SLSA wording
Second cosign spike (both pinned binaries, 2026-08-15) plus source review of
sigstore_bundle.proto, cosign verify_blob_attestation.go and SLSA v1.2:
- DSSE signature stays keyid-free AND verificationMaterial.publicKey becomes {}
(a populated hint beside an absent keyid is ambiguous under the proto's
hint-equality MUST; the empty identifier is unambiguous and Verified OK on
v2.6.5 and v3.1.3)
- cosign artifact-tamper cases must pass the artifact path (or recompute the
digest from disk): with --digest alone cosign never reads the artifact
- plugin.json + PLUGIN_VERSION bump moves to Phase 2 so the engine is final
after Phase 3 (no post-vendor delta; UAT bundles self-report 1.3.0)
- cmd_finalize gains a chain-file rollback guard + failure-injection tests
- compliance doc claims fields-required-at-L1 emission, not L1 attainment
- Phase 1 tests gain fixed hostile-encoding vectors; small-order blocklist and
Ed25519ph KAT deliberately skipped with rationale
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oding primitives
Phase 1 of PLAN_v1.3.0.md (amendment v2 layout). Nothing lifecycle-wired yet.
- RFC 8032 Ed25519 (sign/verify/public-from-seed), KAT-locked to the RFC 7.1
vectors; verify hardened for hostile input: s >= L, y >= p, non-square x,
x=0-with-sign-bit and wrong-length encodings all return False, never raise
- openssh_ed25519_seed parses the unencrypted openssh-key-v1 container and
dies actionably on encrypted/foreign/truncated keys; asserts the derived
public key equals the embedded blob (wrong-key signing is impossible)
- ssh_ed25519_pubkey_bytes, RFC 8410 SPKI PEM (golden-string tested)
- DSSE PAE (spec KAT), envelope + Sigstore v0.3 bundle builders: one
signature, sig-only signature object, verificationMaterial {"publicKey": {}}
- EphemeralEd25519Signer: the three-member v1.4 signer seam
- 35 new tests incl. fixed hostile-encoding vectors and a hand-built
openssh-key-v1 container helper written independently from the format spec
Test evidence: 241 passed (was 206), banned-literal grep green, only new
import is base64.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y bundle Phase 2 of PLAN_v1.3.0.md (amendment v2 layout, empty publicKey identifier). - approval chain action (gate/decision/note; engine fills approver from git config, degrading to "" — never blocks); _RECORD_DATA_FLAGS extended so the silent-drop guard sees the new flags; explicit fallthrough dies loudly - builder identity in the finalize block with per-field provenance labels: model self-reported (--model), Claude Code version measured via shutil.which-only probe, plugin version engine-constant - in-toto Statement v1 + SLSA Provenance v1 predicate: subjects = deduped artifacts (single chain descriptor for zero-artifact runs), approvals labeled agent-recorded, chain byproduct reuses the sealed chain_hash (LF-normalized text — never a byte re-hash), invocationId = genesis hash - DSSE-signed via the ephemeral key's parsed seed, bound to the published public key BEFORE any chain mutation; embedded under bundle.attestation before root_digest so the SSHSIG covers it; sidecars issue-N.sigstore.json (byte-identical canonical JSON, zero newline bytes) + issue-N.pub.pem - rollback guard: any failure after save_chain restores the chain file byte-for-byte and removes partial outputs; key deleted only after success - format version 1.1.0 + KNOWN_RPACK_VERSIONS membership check (three verify sites changed together, folded from Phase 3 so v1.0.0 fixtures stay warning-free at every commit); detail prints the bundle's version - reset/init --force/summary know the sidecars; gate and lint hooks deliberately unchanged (tested); plugin.json + PLUGIN_VERSION -> 1.3.0 together (amended sequencing) Test evidence: 270 passed (was 241). Real CLI e2e produced all three files, verify green zero warnings; the emitted sidecar verifies Verified OK with cosign v2.6.5 AND v3.1.3 (no ForgeProof code), artifact tamper exits 1 on both. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 3 of PLAN_v1.3.0.md. Read-side only, additive, zero filesystem reads
for attestation purposes.
- three new checks after coverage: attestation (well-formed statement/
envelope; the payload decode is a new json.loads over attacker bytes,
guarded with the read_json_file trio incl. RecursionError),
attestation_signature (DSSE over PAE verified against the bundle's OWN
ssh-ed25519 key — the one-key binding payoff), attestation_subjects
(subject set == artifact set or the single chain descriptor; chain
byproduct digest == the SEALED chain_hash, compared never recomputed)
- absent attestation is SILENT: skipped, zero errors, zero warnings, in
every mode including --strict; invariants only, never byte re-derivation
- failure classification: four new TAMPER_ERROR_MARKERS entries free of the
legacy 'hash mismatch'/'prev_hash' fragments; 'Attestation malformed'
errors deliberately match no marker (FAILED, not TAMPER) and never embed
attacker-controlled values (substring classification injection)
- additive result key 'attestation' {present, predicate_type, subject_count,
key_id (verifier-derived), builder, approvals}; markdown gains an
Attestation section (all bundle content through md_cell) with the exact
cosign reproduction command
- tests: per-invariant tamper matrix (payload edit, sig flip, foreign DSSE
key, subject digest edit, chain byproduct edit — each exactly one marker,
TAMPER DETECTED verdict, root_digest isolated green), malformed matrix
(wrong types, bad base64, bad JSON, missing keys, two signatures, deep
nesting with shape fallback + forced RecursionError) all FAILED-not-TAMPER;
all three frozen fixture classes now assert attestation==skipped,
warnings==[], format detail names the bundle's version — lenient AND strict
Test evidence: 290 passed (was 270).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rop and compliance mapping Phase 4 of PLAN_v1.3.0.md (amended wording throughout). - run skill: record the plan-gate approval right after init (engine fills approver), pass --model to finalize (self-reported, stated honestly), attestation in the finalize behavior list and the final report; explicit note that the seal step already stages the sidecars — do not 'fix' it - verify skill: the attestation result object + three checks, the new failure scenarios (tamper vs signed-malformed), and cosign as an alternative view — never a required step - push skill: PR body notes the attestation + how to verify it - rpack-format.md: format v1.1.0, membership-based recognition, the embedded attestation layout (keyid-free, empty publicKey), sidecar byte contracts, the chain_hash LF-normalization caveat, the #slsa-buildtype-v1 parameter schema and #builder-id trust-base documentation the engine URIs resolve to (also fixed the engine constant's path to the real references location) — plus the 1.0.0-is-valid-forever statement - chain-format.md: approval action row; finalize block's builder identity - docs/cosign-interop.md (new): pinned v2.6.5/v3.1.3 contract, the exact command, what each flag proves, and the --digest vacuousness pitfall - docs/compliance-mapping.md (new): SSDF-as-voluntary framing with the 2022->2026 mandate window and M-26-05 rescission, CISA form item 3 task mapping, CRA Annex VII 2(c)/6 at the manufacturer's discretion, and the amended SLSA wording: fields required at Build L1, no level claim - ROADMAP v1.3.0 narrative corrected (no 'converging regulation', no 'compliance-ready by default'); PRIVACY.md corrects the live username@hostname inaccuracy and adds the approver email + sidecars - TestSkillContract floor 13 -> 17 (the new invocation count) Test evidence: 290 passed; claude plugin validate clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n tier
Phase 5 of PLAN_v1.3.0.md (amended: non-vacuous artifact cases).
- cosign-interop CI job, matrixed over BOTH pinned binaries (v2.6.5, v3.1.3;
installer pinned by commit SHA d58896d6 # v3.9.2): stress/make_bundle.py
drives the real engine (init -> records -> approval -> finalize --model)
in RUNNER_TEMP, then one cosign run per artifact passing the artifact PATH
(cosign hashes each file itself — the attestation's own digest is never
fed back), one --digest run recomputed from disk with hashlib, and two
negatives: flipped artifact byte (claim check) and flipped envelope
payload byte (signature) must fail. cosign appears in this job only.
- stress harness: approval via the real CLI, finalize emits byte-exact
sidecars (no newline bytes) inside a 60s ceiling, attestation-field tamper
-> Root digest mismatch, reformatted sidecar does NOT affect verify
(verify reads no sidecar), reset removes the sidecars
- README: attestation in the intro and bundle contents, cosign as an
optional interop-only section (not Requirements), test count 168 -> 290
from a real --collect-only, three frozen fixtures, compat promise widened
to the v1.0.x/v1.1.x/v1.2.x lines
- CHANGELOG 1.3.0: full section, leading with the additive format bump and
the benign one-warning behavior on pre-v1.3 verifiers
Evidence: 290 pytest green; stress 292 passed / 0 failed / 0 skipped in
121.5s on Windows; the exact CI command sequence proven locally against both
binaries — 3x Verified OK per binary (path form), --digest form green, and
both negatives failing with the real tamper errors ('provided artifact
digest does not match any digest in statement', 'accepted signatures do not
match threshold, Found: 0, Expected 1').
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…osign v3 line The v3.1.3 leg of cosign-interop failed inside the installer step itself (exit 22): cosign v3.x releases replaced the detached cosign-linux-amd64.sig asset with a cosign-linux-amd64.sigstore.json bundle, and installer v3.9.2's custom-version path still downloads the .sig (404). Installer v4.1.2 switches on is_version_ge 3.0.1 to the bundle layout and still handles v2.6.5's .sig path. The v2.6.5 leg and the entire pytest/validate matrix were green on the first run — no engine or attestation change here, pin-bump only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All three pin sites move from 0bd8aae # v1.0.2 to the v1.1.0 merge commit; grep proves zero stale hits outside historical plan documents. The pinned commit's vendored engine is byte-identical (sha256 f713f3e9...) to this repo's engine-final commit ac9da9b. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ROADMAP: v1.3.0 🧭 → ✅, Last updated 2026-09-05. CHANGELOG 1.3.0 gains the forgeproof-verify v1.1.0 re-pin entry (done in e61a7d8, not yet recorded). No engine, manifest, hook, or fixture bytes change: plugin.json and PLUGIN_VERSION were bumped to 1.3.0 in Phase 2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
release: v1.3.0 — speak the industry's language
Every bundle now also carries a standards-conformant attestation: an in-toto Statement v1 with a SLSA Provenance v1 predicate, DSSE-signed inside a Sigstore bundle by the same ephemeral Ed25519 key that signs the chain, verifiable with plain cosign and no ForgeProof code present. Still pure stdlib; cosign is consumer-side only. Full notes:
CHANGELOG.md§1.3.0. Plan:PLAN_v1.3.0.md.Bundle format bumped additively to 1.1.0. Every prior
.rpackstill verifies with zero errors and zero warnings, strict mode included, enforced by three frozen fixtures (v1.0.1, v1.1.0, v1.2.2 engines). A v1.1.0 bundle read by a pre-v1.3 verifier is green with exactly one benign version warning.Merge instructions
ac9da9binverifier/UPSTREAM; a squash orphans that SHA and turns the Action's sync-check permanently red. Repo settings already allow merge commits only.git merge-base --is-ancestor ac9da9b origin/mainmust succeed.verify-provenancecheck is skipped by the head-branch filter (release branches carry no bundle). Expected and acceptable; the draft-PR matrix below covered the Action.Evidence
e61a7d8; run onccadf13linked in the checks tabcosign-interop(v2.6.5 and v3.1.3, pinned binaries)/forgeproof:verifyrenders the attestation section; tamper red, restore green; cosign v2.6.5 Verified OK outside ForgeProof, tampered artifact rejectedforgeproof-verifyv1.1.0 released,v1moved; all three plugin pins on6101dd7, zero staleAfter merge
v1.3.0(annotated) on the merge commit; push the tag.forgeproof-verifyverifier/UPSTREAMfrom SHAac9da9bto tagv1.3.0(one Action commit + tag, owed post-release).v1resolves to v1.1.0.🤖 Generated with Claude Code