proof-aware-crypto-tooling-.../src/pacta/attestation.py

222 lines
11 KiB
Python
Raw Normal View History

from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
from .config import RepoConfig
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
from .profiles import get_profile
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
from .signing import verify_attestation_signature_detailed
Log accountability: STH pinning, consistency enforcement, freshness, monitor A transparency log without split-view defense is just a signature with extra steps: the provider could serve one tree to the agent and another to the world, or roll the log back, and standalone receipt verification would never notice. The primitives (RFC 9162 consistency proofs) were already implemented and correct; this closes the loop on the AGENT side. - src/pacta/sthstore.py: a local STH pin store. Unknown log -> pin (trust-on-first-use, recorded as such). Same tree size -> the root must match the pin byte-for-byte; a mismatch is named EQUIVOCATION and is a hard rejection. Larger tree -> a consistency proof FROM THE PINNED SIZE is required and verified before the pin advances (receipts already embed a from-previous anchor; the anchor's root is itself checked against the pin so a lying anchor cannot bridge a split view). Smaller tree -> LOG ROLLBACK, hard rejection. - Freshness policy: --max-sth-age-seconds rejects stale (or future-dated) tree heads - an old-but-valid STH can hide later entries. - Wired into receipt-verify, claims, and agent (--sth-store, --consistency-proof, --max-sth-age-seconds); evidence records the pin action; any accountability failure fails the receipt closed. - Provider: log-consistency --from-size N (serve proofs for pinning agents whose pin is older than the receipt's embedded anchor) and log-audit (monitor self-check: recompute the tree, verify the stored STH and per-entry leaf hashes). Live drill in this commit's validation: pin-on-first-use -> matched -> grown-with-proof advance -> a real forged same-size split view REJECTED with the equivocation diagnostic -> freshness rejection -> clean self-audit. tests/test_sthstore.py covers pin/match/equivocation, growth-without-proof, lying consistency anchors, rollback, freshness. 45/45 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:08:34 +00:00
from .sthstore import check_sth_against_store, check_sth_freshness
2026-07-03 12:09:34 +00:00
from .transparency import load_receipt, verify_receipt
from .yamlio import load_data
@dataclass(slots=True)
class AttestationResult:
accepted: bool
provider: str | None
diagnostics: list[str] = field(default_factory=list)
certificates: list[dict[str, Any]] = field(default_factory=list)
evidence: dict[str, Any] = field(default_factory=dict)
trusted_base: list[str] = field(default_factory=list)
repo_commit: str | None = None
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
coverage_warnings: list[str] = field(default_factory=list)
def load_attestation(path: str | Path) -> dict[str, Any]:
raw = load_data(path)
if not isinstance(raw, dict):
raise ValueError(f"Attestation must be a mapping: {path}")
return raw
def validate_attestation(
raw: dict[str, Any],
repo: RepoConfig,
path: str | Path | None = None,
trusted_provider: str | None = None,
2026-07-03 11:03:58 +00:00
public_key_path: str | Path | None = None,
allow_unsigned: bool = False,
2026-07-03 12:09:34 +00:00
transparency_receipt_path: str | Path | None = None,
transparency_log_public_key_path: str | Path | None = None,
require_transparency_signatures: str = "ed25519",
require_transparency_receipt: bool = False,
Log accountability: STH pinning, consistency enforcement, freshness, monitor A transparency log without split-view defense is just a signature with extra steps: the provider could serve one tree to the agent and another to the world, or roll the log back, and standalone receipt verification would never notice. The primitives (RFC 9162 consistency proofs) were already implemented and correct; this closes the loop on the AGENT side. - src/pacta/sthstore.py: a local STH pin store. Unknown log -> pin (trust-on-first-use, recorded as such). Same tree size -> the root must match the pin byte-for-byte; a mismatch is named EQUIVOCATION and is a hard rejection. Larger tree -> a consistency proof FROM THE PINNED SIZE is required and verified before the pin advances (receipts already embed a from-previous anchor; the anchor's root is itself checked against the pin so a lying anchor cannot bridge a split view). Smaller tree -> LOG ROLLBACK, hard rejection. - Freshness policy: --max-sth-age-seconds rejects stale (or future-dated) tree heads - an old-but-valid STH can hide later entries. - Wired into receipt-verify, claims, and agent (--sth-store, --consistency-proof, --max-sth-age-seconds); evidence records the pin action; any accountability failure fails the receipt closed. - Provider: log-consistency --from-size N (serve proofs for pinning agents whose pin is older than the receipt's embedded anchor) and log-audit (monitor self-check: recompute the tree, verify the stored STH and per-entry leaf hashes). Live drill in this commit's validation: pin-on-first-use -> matched -> grown-with-proof advance -> a real forged same-size split view REJECTED with the equivocation diagnostic -> freshness rejection -> clean self-audit. tests/test_sthstore.py covers pin/match/equivocation, growth-without-proof, lying consistency anchors, rollback, freshness. 45/45 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:08:34 +00:00
sth_store_path: str | Path | None = None,
consistency_proof_path: str | Path | None = None,
max_sth_age_seconds: int | None = None,
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
require_verified_verifier: bool = False,
) -> AttestationResult:
provider = raw.get("provider")
subject = raw.get("subject") or {}
diagnostics: list[str] = []
if not provider:
diagnostics.append("Attestation is missing provider.")
if trusted_provider is None:
diagnostics.append("No trusted attestation provider was explicitly configured.")
elif provider != trusted_provider:
diagnostics.append(f"Attestation provider '{provider}' does not match trusted provider '{trusted_provider}'.")
if subject.get("component") and subject.get("component") != repo.name:
diagnostics.append(f"Attestation subject component '{subject.get('component')}' does not match repo '{repo.name}'.")
if repo.url and subject.get("repo_url") and subject.get("repo_url") != repo.url:
diagnostics.append("Attestation subject repo_url does not match config.")
if subject.get("verification_dir") and subject.get("verification_dir") != repo.verification_dir:
diagnostics.append("Attestation subject verification_dir does not match config.")
certs = raw.get("certificates") or []
if not isinstance(certs, list) or not certs:
diagnostics.append("Attestation contains no certificate results.")
certs = []
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
profile = get_profile(repo.kind, repo)
expected_names = set(repo.certificates or profile.default_certificates)
observed_names = {str(cert.get("name")) for cert in certs if isinstance(cert, dict)}
missing = sorted(expected_names - observed_names)
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
coverage_warnings: list[str] = []
if missing:
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
# Partial coverage is NOT a rejection: the uncovered certificates
# simply stay unproven in the claim card and the risk score degrades
# accordingly (e.g. an arithmetic-only attestation caps at R3).
coverage_warnings.append(
"Attestation does not cover configured certificate(s): " + ", ".join(missing)
)
signature = raw.get("signature") or {}
environment = raw.get("environment") or {}
signature_status = signature.get("status", "not_checked")
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
signature_backend = "none"
2026-07-03 11:03:58 +00:00
if public_key_path:
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
ok, error, signature_backend = verify_attestation_signature_detailed(raw, public_key_path)
2026-07-03 11:03:58 +00:00
if ok:
signature_status = "verified"
else:
diagnostics.append(f"Attestation signature verification failed: {error}")
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
if require_verified_verifier and signature_backend != "verified-dalek-serial":
diagnostics.append(
"Policy requires the dogfood (certificate-covered) Ed25519 verifier, but verification ran on "
f"backend '{signature_backend}'. Build it with: pacta dogfood-build --source <pinned-workspace>."
)
2026-07-03 11:03:58 +00:00
elif signature_status == "signed":
diagnostics.append("Signed attestation requires --attestation-public-key.")
elif signature_status == "not_implemented":
if allow_unsigned:
signature_status = "not_implemented"
else:
diagnostics.append("Unsigned attestation requires --allow-unsigned-attestation.")
elif signature_status != "verified":
diagnostics.append(f"Attestation signature status is not acceptable: {signature_status}")
2026-07-03 12:09:34 +00:00
transparency_evidence: dict[str, Any] = {}
if require_transparency_receipt and not transparency_receipt_path:
diagnostics.append("Transparency receipt is required by policy but was not supplied.")
if transparency_receipt_path:
if not transparency_log_public_key_path:
diagnostics.append("Transparency receipt verification requires --transparency-log-public-key.")
else:
receipt = load_receipt(transparency_receipt_path)
receipt_result = verify_receipt(
raw,
receipt,
transparency_log_public_key_path,
require_signatures=require_transparency_signatures,
)
transparency_evidence = receipt_result.evidence()
transparency_evidence["transparency_receipt_path"] = str(transparency_receipt_path)
if not receipt_result.accepted:
diagnostics.extend(receipt_result.diagnostics)
Log accountability: STH pinning, consistency enforcement, freshness, monitor A transparency log without split-view defense is just a signature with extra steps: the provider could serve one tree to the agent and another to the world, or roll the log back, and standalone receipt verification would never notice. The primitives (RFC 9162 consistency proofs) were already implemented and correct; this closes the loop on the AGENT side. - src/pacta/sthstore.py: a local STH pin store. Unknown log -> pin (trust-on-first-use, recorded as such). Same tree size -> the root must match the pin byte-for-byte; a mismatch is named EQUIVOCATION and is a hard rejection. Larger tree -> a consistency proof FROM THE PINNED SIZE is required and verified before the pin advances (receipts already embed a from-previous anchor; the anchor's root is itself checked against the pin so a lying anchor cannot bridge a split view). Smaller tree -> LOG ROLLBACK, hard rejection. - Freshness policy: --max-sth-age-seconds rejects stale (or future-dated) tree heads - an old-but-valid STH can hide later entries. - Wired into receipt-verify, claims, and agent (--sth-store, --consistency-proof, --max-sth-age-seconds); evidence records the pin action; any accountability failure fails the receipt closed. - Provider: log-consistency --from-size N (serve proofs for pinning agents whose pin is older than the receipt's embedded anchor) and log-audit (monitor self-check: recompute the tree, verify the stored STH and per-entry leaf hashes). Live drill in this commit's validation: pin-on-first-use -> matched -> grown-with-proof advance -> a real forged same-size split view REJECTED with the equivocation diagnostic -> freshness rejection -> clean self-audit. tests/test_sthstore.py covers pin/match/equivocation, growth-without-proof, lying consistency anchors, rollback, freshness. 45/45 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:08:34 +00:00
sth = receipt.get("sth") or {}
if max_sth_age_seconds is not None:
fresh, error = check_sth_freshness(sth, int(max_sth_age_seconds))
if not fresh:
diagnostics.append(error or "Signed tree head fails the freshness policy.")
if sth_store_path:
audit v3: paper-reality congruence + external-pointer integrity (Fable-5 Socratic pass) Two Fable-5 inventory agents cross-checked every empirical claim in the paper against code/deployed log, and every external pointer against the live internet. Fixes on both sides: CODE (system brought up to the paper's claims): - SECURITY: pin-store mutation (incl. permanent poisoning) was reachable via receipts whose head signature FAILED verification in two of three consumer paths (attestation.py, cli.py) - an unauthenticated forged head at the pinned size could poison a consumer's pin forever and pollute the equivocation-evidence pair with an unverifiable head, contradicting SS5.4's 'validly signed' precondition and Prop 1. Both paths now gate the store on a verified Ed25519 head signature (logclient.py already did). Regression test added. - Prop 2 made literally true: _normalize_certificate now derives the cleanliness verdict purely from (observed cone, local allowed set) in EVERY branch; the operator's axiom_status label is never copied (was passed through for non-proven certs), missing cone => unverifiable always. Labels can deny, never grant. Test added. - webdocs: '/v1/sth-history: every head ever signed' -> 'the published head history'. PAPER (claims brought down to reality): - 'every head ever signed' -> the signed head history since publication began (heads for sizes 1-7 predate the mirror and were not retained). - Run-3 bullet: 'independently checkable by diffing the two commit trees' was no longer reproducible (pre-rewrite objects discarded); now states the log-internal corroboration (identical cert lists and cones across leaves 4-7 vs 8-11) and that tree diffs are not public. - Appendix A leaf block now actually verbatim: scheme openssl-ed25519, verified_backend serial/u64, real Lean version (4.30.0-rc2) instead of 4.x.y placeholder, leaf's actual axiom order (finalize/new/update), machine_protection note quoted, elisions marked; preamble wording matches. - Appendix C upstream boundary reordered to check.sh's verbatim order. - '27 lines - all annotation' -> honest description (axiom-list entries + operation reordering from one fork's black_box barrier). - Prop 2 proof + App A: status label consulted only negatively. - SS7: provenance fields noted as outside the signed payload; consumer chain relies on none of them. - Bibliography: all 20 entries verified against DBLP/RFC-editor - zero errors; added missing page numbers to 6 entries; thebibliography width 19->20. All URLs verified public; no PlanetMacro leakage. 17 pages, 106 tests green, accumulator untouched (tree_size 12). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:33:28 +00:00
# The pin-store state machine (including permanent poisoning
# on equivocation) only ever runs on a VALIDLY SIGNED head;
# an unauthenticated head must not be able to mutate - let
# alone poison - the consumer's pin.
if receipt_result.signatures.get("ed25519") != "verified":
transparency_evidence["sth_store"] = "skipped_unverified_head"
diagnostics.append(
"STH store: head signature did not verify; pin store not consulted or updated."
)
else:
proof_hex = None
if consistency_proof_path:
raw_proof = load_data(consistency_proof_path)
proof_hex = [str(item) for item in (raw_proof.get("proof") if isinstance(raw_proof, dict) else raw_proof) or []]
sth_check = check_sth_against_store(
sth,
sth_store_path,
consistency_proof_hex=proof_hex,
consistency_from=receipt.get("consistency"),
)
transparency_evidence.update(sth_check.evidence())
if not sth_check.ok:
diagnostics.extend("STH store: " + note for note in sth_check.diagnostics)
2026-07-03 12:09:34 +00:00
accepted = not diagnostics
evidence = {
"evidence_mode": "third_party_attestation",
"attestation_provider": provider,
"attestation_path": str(path) if path else None,
"attestation_signature_status": signature_status,
Dogfood cryptography: pacta verifies signatures through the PROVEN code path "Eat your own dogfood": pacta consumes certificates about a verified Ed25519 implementation while checking those certificates' signatures with OpenSSL. Now it can use the object of its own evidence: - dogfood/pacta-verified-verify: a ~90-line Rust binary built against the PINNED proven source workspace (saymrwulf/curve25519-dalek-source at the exact commit the dalek certificates pin - the build records it: aa0f6ab...) with the serial backend pinned via RUSTFLAGS exactly as the verified extraction pins it. Cargo.toml is committed as a template ({{SOURCE}} placeholder) so no machine path is hardcoded; the rendered file, target/, and the built binary are gitignored. - pacta dogfood-build --source <workspace>: renders, builds, installs to dogfood/state/, and writes a provenance sidecar (source commit, backend cfg, rustc, and an honest coverage note: the certificates cover verify_sha512, the extraction-refactored image of this verify path; SHA-512 and the wire glue remain the theorems' documented boundary). pacta dogfood-status reports the active backend. - signing.verify_payload_ed25519_detailed: dispatch - the dogfood binary when present (backend "verified-dalek-serial"), OpenSSL fallback otherwise, and the backend that ACTUALLY ran is recorded in receipt signature statuses and attestation evidence. Fallback is never silent. - --require-verified-verifier (receipt-verify + agent): policy fails closed when verification did not run on the certificate-covered path. - ML-DSA is deliberately unchanged: no proven implementation exists, so the slot stays fail-closed "unavailable" - the honest hybrid-PQC posture is one proven-classical signature plus one required-but- unproven PQC slot, never a pretend backend. Validated live: receipt verification through the proven verifier (backend recorded), a corrupted signature bit rejected BY the proven binary, tampered attestations rejected, and the policy failing closed when the binary is absent. 49/49 tests green (incl. PEM-SPKI raw-key cross-check against openssl, dispatch/backend recording with a stub, and a real-binary roundtrip that skips gracefully where unbuilt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:13:48 +00:00
"attestation_signature_backend": signature_backend,
"attestation_log_url": raw.get("log_url") or signature.get("log_url"),
"attestation_issued_at": raw.get("issued_at"),
2026-07-03 11:03:58 +00:00
"check_log_path": (raw.get("replay") or {}).get("check_log_path"),
"axiom_log_path": (raw.get("replay") or {}).get("axiom_log_path"),
"lean_version": environment.get("lean_version"),
"lake_version": environment.get("lake_version"),
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
"attestation_coverage_warnings": coverage_warnings,
2026-07-03 12:09:34 +00:00
**transparency_evidence,
}
trusted_base = []
if accepted:
trusted_base.append(f"Third-party proof-checking attestation provider: {provider}.")
trusted_base.append("Provider environment, replay implementation, signing key custody, and log retention.")
2026-07-03 12:09:34 +00:00
if transparency_receipt_path:
trusted_base.append("Transparency log append-only behavior, signed tree head key custody, and monitor/auditor availability.")
return AttestationResult(
accepted=accepted,
provider=str(provider) if provider else None,
diagnostics=diagnostics,
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
certificates=[_normalize_certificate(cert, profile) for cert in certs if isinstance(cert, dict)],
evidence=evidence,
trusted_base=trusted_base,
repo_commit=subject.get("repo_commit"),
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
coverage_warnings=coverage_warnings,
)
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
def _normalize_certificate(cert: dict[str, Any], profile: Any) -> dict[str, Any]:
"""Normalize a provider-reported certificate against LOCAL policy.
The provider is trusted for its OBSERVATION (which axioms #print axioms
reported); it is never trusted for the VERDICT. axiom_status is re-derived
here by comparing the observed axioms against this agent's own allowed
set for the certificate - a provider that labels a dirty cone "clean"
gains nothing.
"""
name = str(cert.get("name") or "")
status = str(cert.get("status") or "unknown")
observed = [str(a) for a in (cert.get("observed_axioms") or [])]
expected = profile.expected_axioms_for(name)
audit v3: paper-reality congruence + external-pointer integrity (Fable-5 Socratic pass) Two Fable-5 inventory agents cross-checked every empirical claim in the paper against code/deployed log, and every external pointer against the live internet. Fixes on both sides: CODE (system brought up to the paper's claims): - SECURITY: pin-store mutation (incl. permanent poisoning) was reachable via receipts whose head signature FAILED verification in two of three consumer paths (attestation.py, cli.py) - an unauthenticated forged head at the pinned size could poison a consumer's pin forever and pollute the equivocation-evidence pair with an unverifiable head, contradicting SS5.4's 'validly signed' precondition and Prop 1. Both paths now gate the store on a verified Ed25519 head signature (logclient.py already did). Regression test added. - Prop 2 made literally true: _normalize_certificate now derives the cleanliness verdict purely from (observed cone, local allowed set) in EVERY branch; the operator's axiom_status label is never copied (was passed through for non-proven certs), missing cone => unverifiable always. Labels can deny, never grant. Test added. - webdocs: '/v1/sth-history: every head ever signed' -> 'the published head history'. PAPER (claims brought down to reality): - 'every head ever signed' -> the signed head history since publication began (heads for sizes 1-7 predate the mirror and were not retained). - Run-3 bullet: 'independently checkable by diffing the two commit trees' was no longer reproducible (pre-rewrite objects discarded); now states the log-internal corroboration (identical cert lists and cones across leaves 4-7 vs 8-11) and that tree diffs are not public. - Appendix A leaf block now actually verbatim: scheme openssl-ed25519, verified_backend serial/u64, real Lean version (4.30.0-rc2) instead of 4.x.y placeholder, leaf's actual axiom order (finalize/new/update), machine_protection note quoted, elisions marked; preamble wording matches. - Appendix C upstream boundary reordered to check.sh's verbatim order. - '27 lines - all annotation' -> honest description (axiom-list entries + operation reordering from one fork's black_box barrier). - Prop 2 proof + App A: status label consulted only negatively. - SS7: provenance fields noted as outside the signed payload; consumer chain relies on none of them. - Bibliography: all 20 entries verified against DBLP/RFC-editor - zero errors; added missing page numbers to 6 entries; thebibliography width 19->20. All URLs verified public; no PlanetMacro leakage. 17 pages, 106 tests green, accumulator untouched (tree_size 12). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:33:28 +00:00
# The cleanliness verdict is a function of (observed cone, local allowed
# set) ONLY - in every branch. The provider's status label still gates
# acceptance elsewhere (only status=="proven" certificates can count),
# but it can only deny, never grant, and the provider's own axiom_status
# label is never copied into the verdict.
if observed:
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
axiom_status = "clean" if sorted(observed) == sorted(expected) else "dirty"
else:
audit v3: paper-reality congruence + external-pointer integrity (Fable-5 Socratic pass) Two Fable-5 inventory agents cross-checked every empirical claim in the paper against code/deployed log, and every external pointer against the live internet. Fixes on both sides: CODE (system brought up to the paper's claims): - SECURITY: pin-store mutation (incl. permanent poisoning) was reachable via receipts whose head signature FAILED verification in two of three consumer paths (attestation.py, cli.py) - an unauthenticated forged head at the pinned size could poison a consumer's pin forever and pollute the equivocation-evidence pair with an unverifiable head, contradicting SS5.4's 'validly signed' precondition and Prop 1. Both paths now gate the store on a verified Ed25519 head signature (logclient.py already did). Regression test added. - Prop 2 made literally true: _normalize_certificate now derives the cleanliness verdict purely from (observed cone, local allowed set) in EVERY branch; the operator's axiom_status label is never copied (was passed through for non-proven certs), missing cone => unverifiable always. Labels can deny, never grant. Test added. - webdocs: '/v1/sth-history: every head ever signed' -> 'the published head history'. PAPER (claims brought down to reality): - 'every head ever signed' -> the signed head history since publication began (heads for sizes 1-7 predate the mirror and were not retained). - Run-3 bullet: 'independently checkable by diffing the two commit trees' was no longer reproducible (pre-rewrite objects discarded); now states the log-internal corroboration (identical cert lists and cones across leaves 4-7 vs 8-11) and that tree diffs are not public. - Appendix A leaf block now actually verbatim: scheme openssl-ed25519, verified_backend serial/u64, real Lean version (4.30.0-rc2) instead of 4.x.y placeholder, leaf's actual axiom order (finalize/new/update), machine_protection note quoted, elisions marked; preamble wording matches. - Appendix C upstream boundary reordered to check.sh's verbatim order. - '27 lines - all annotation' -> honest description (axiom-list entries + operation reordering from one fork's black_box barrier). - Prop 2 proof + App A: status label consulted only negatively. - SS7: provenance fields noted as outside the signed payload; consumer chain relies on none of them. - Bibliography: all 20 entries verified against DBLP/RFC-editor - zero errors; added missing page numbers to 6 entries; thebibliography width 19->20. All URLs verified public; no PlanetMacro leakage. 17 pages, 106 tests green, accumulator untouched (tree_size 12). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:33:28 +00:00
# no observed cone: nothing to re-derive from; distrust.
axiom_status = "unverifiable"
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
provider_verdict = str(cert.get("axiom_status") or "not_stated")
return {
Estate sync: boundary-axiom vocabulary + the four-tier apex reality (R4) The verified corpus completed its phase 2 on 2026-07-06: every ed25519 fork now carries FOUR button-enforced apex tiers up to the full lift (accept <=> decompress(R) = [k](-A)+[s]B as points), the complete scalar layer, and the constructive encoding/decoding chain. pacta was calibrated to the pre-apex corpus and - worse - had no vocabulary for boundary-audited certificates: its axiom audit knew only "clean = exactly the three standard axioms", so the apex tiers would have scored dirty. New vocabulary: - Profile.certificate_axioms: per-certificate ALLOWED axiom sets; expected_axioms_for(cert) resolves each certificate's own boundary. - RepoConfig.apex_boundary: a simple per-fork key (dalek-wrappers / hash3 / anza) expanded by the ed25519 profile into the exact per-tier allowed sets. AUTHORITY NOTE in profiles/ed25519.py: each repo's check.sh Phase 3b is the enforcement point; if the button and this table disagree, the button wins. - run_axiom_audit compares each certificate against ITS allowed set; deviation in EITHER direction (extra axiom or missing boundary axiom) is dirty. New risk reality: - R4 is now reachable: full four-tier apex + constructive chain + scalar arithmetic, all proven with cones pinned to their documented boundaries. R4 always carries explicit residual blockers (SHA-512 oracle, hypothesis-parametric wire parses, translation faithfulness, no side-channel/build assurance - those gate R5). - R3 unchanged (arithmetic pair) and now explains exactly which apex certificates are missing for R4. Attestation trust model hardened: - The provider is trusted for its OBSERVATION, never its VERDICT: axiom_status is re-derived locally from observed_axioms against the agent's own boundary policy. A provider that labels a dirty cone "clean" gains nothing; "proven" with no observed axioms is "unverifiable". - Partial attestations degrade instead of being rejected: uncovered certificates stay unproven and the score caps accordingly (an arithmetic-only attestation still authorizes an R3 library capsule, never a wallet). Also: scripts/mini_pytest.py - a dependency-free test runner (tmp_path, raises, monkeypatch, capsys) for hosts without pytest; examples regenerated FROM the tool (dalek/anza fixtures now R4, 16 certs; new full four-tier attestation example); tests updated + new tests/test_boundaries.py (lying-provider, missing-boundary-axiom, partial-coverage cases). 40/40 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:04:43 +00:00
"name": name,
"status": status,
"axiom_status": axiom_status,
"observed_axioms": observed,
"expected_axioms": list(expected),
"provider_axiom_verdict": provider_verdict,
}