diff --git a/satgate-landing/app/verify-evidence-pack/page.tsx b/satgate-landing/app/verify-evidence-pack/page.tsx index 9f32be4d..fc868f03 100644 --- a/satgate-landing/app/verify-evidence-pack/page.tsx +++ b/satgate-landing/app/verify-evidence-pack/page.tsx @@ -16,13 +16,36 @@ export default function VerifyEvidencePackPage() {
← Back to Home

Independent verification

-

Verify a SatGate Evidence Pack.

+

Don't trust us—verify it yourself.

- SatGate Evidence Packs are designed to be checked without SatGate credentials. A verifier should fetch the pack, fetch issuer JWKS, canonicalize the signed receipt with RFC 8785 JCS, recompute the SHA-256 receipt hash, verify the Ed25519 signature, and compare unsigned pack mirrors against the signed receipt. + SatGate Evidence Packs are designed to be checked without SatGate credentials. Fetch the pack and issuer JWKS, canonicalize the signed receipt with RFC 8785 JCS, recompute its SHA-256 hash, verify the Ed25519 signature, and compare unsigned pack mirrors against the signed receipt.

Get verifier tool Open sample production pack + Download sanitized closure +
+
+ + +
+
+

Read the result correctly.

+
+
+

valid=true

+

With an embedded key, this proves only that the artifact is internally self-consistent. It does not establish who controls the issuer.

+
+
+

trusted_issuer_valid=true

+

Buyer-verifiable proof requires the signature to validate against a separately fetched or pinned issuer JWKS, with trusted-issuer verification required.

+
+
+
+

Latest bounded closure record

+

The July 18 record is sanitized, staging-only evidence. It records strict verifier and trusted-issuer success, verifier-copy parity, restart parity, and containment of historical staging bearer links. It does not authorize production promotion.

+

Source manifest SHA-256: 62d00ac4bff91e56fea8f5e8e42ceb0bb46461c46ba5d5a8c9645047baba4f5a

+

Public record SHA-256: 162f523d054feb99c2d65fadad7ecb3aa2d5127f1748160ca97424b73215eb7c

@@ -55,6 +78,18 @@ python tools/verify_evidence_pack.py pack.json \ +
+
+

Current limits

+ +
+
+

What this proves — and what it does not.

diff --git a/satgate-landing/public/evidence/policy-to-proof-closure-20260718.json b/satgate-landing/public/evidence/policy-to-proof-closure-20260718.json new file mode 100644 index 00000000..c428a203 --- /dev/null +++ b/satgate-landing/public/evidence/policy-to-proof-closure-20260718.json @@ -0,0 +1,48 @@ +{ + "schema_version": "1.0", + "record_type": "policy_to_proof_sanitized_closure", + "generated_at": "2026-07-18T20:50:36Z", + "scope": "staging_only", + "source_fingerprints": { + "reviewed_candidate_commit": "f320ccf8a0f0248526c8cedea68ab14c9acb59d4", + "enterprise_merge_commit": "24bb146a2eb062959b86470bd819618d51f55505", + "sanitized_manifest_sha256": "62d00ac4bff91e56fea8f5e8e42ceb0bb46461c46ba5d5a8c9645047baba4f5a" + }, + "verification": { + "manifest_entries_verified": true, + "manifest_entry_count": 10, + "sensitive_data_scan_passed": true, + "json_string_boundary_passed": true, + "claim_hygiene_passed": true, + "verifier_copies_byte_identical": true, + "strict_verifier_tests_passed": true, + "strict_verifier_test_count": 71, + "strict_verifier_valid": true, + "trusted_issuer_valid": true, + "restart_parity_verified": true + }, + "historical_bearer_containment": { + "exposed_staging_evidence_urls_found": 2, + "retrievable_before_containment": true, + "targeted_archive_entries_removed": 2, + "process_cache_cleared_by_restart": true, + "all_urls_http_404_after_restart": true, + "not_found_responses_indistinguishable": true, + "git_history_rewritten": false, + "source_repository_private": true, + "residual_private_history_risk_accepted": true + }, + "boundaries": { + "production_touched": false, + "production_promotion_authorized": false, + "contains_raw_pack_identifiers": false, + "contains_raw_receipt_identifiers": false, + "contains_evidence_access_identifiers": false, + "contains_bearer_urls": false, + "contains_payment_credentials": false, + "proves_runtime_truth_independently": false, + "proves_billing_settlement": false, + "proves_external_archive_anchoring": false, + "proves_hardware_key_custody": false + } +} diff --git a/satgate-landing/scripts/check_proof_spine.py b/satgate-landing/scripts/check_proof_spine.py index 3115ed1f..e7d1264c 100644 --- a/satgate-landing/scripts/check_proof_spine.py +++ b/satgate-landing/scripts/check_proof_spine.py @@ -52,6 +52,17 @@ "policy_version", "decision_reason", ], + "app/verify-evidence-pack/page.tsx": [ + "Don't trust us—verify it yourself.", + "valid=true", + "trusted_issuer_valid=true", + "--jwks-file jwks.json", + "--require-trusted-issuer", + "Current limits", + "/evidence/policy-to-proof-closure-20260718.json", + "62d00ac4bff91e56fea8f5e8e42ceb0bb46461c46ba5d5a8c9645047baba4f5a", + "162f523d054feb99c2d65fadad7ecb3aa2d5127f1748160ca97424b73215eb7c", + ], "app/openai-budget-policy-generator/page.tsx": [ "receipt_id", "evidence_pack_id", @@ -158,12 +169,60 @@ def check_mcp_templates() -> list[str]: return errors +def check_sanitized_closure() -> list[str]: + errors: list[str] = [] + path = ROOT / "public/evidence/policy-to-proof-closure-20260718.json" + if not path.exists(): + return ["missing sanitized Policy-to-Proof closure record"] + record = json.loads(path.read_text()) + if record.get("scope") != "staging_only": + errors.append("sanitized closure scope must remain staging_only") + verification = record.get("verification", {}) + for key in [ + "manifest_entries_verified", + "sensitive_data_scan_passed", + "verifier_copies_byte_identical", + "strict_verifier_valid", + "trusted_issuer_valid", + "restart_parity_verified", + ]: + if verification.get(key) is not True: + errors.append(f"sanitized closure verification.{key} is not true") + boundaries = record.get("boundaries", {}) + for key in [ + "production_touched", + "production_promotion_authorized", + "contains_raw_pack_identifiers", + "contains_raw_receipt_identifiers", + "contains_evidence_access_identifiers", + "contains_bearer_urls", + "contains_payment_credentials", + "proves_runtime_truth_independently", + "proves_billing_settlement", + "proves_external_archive_anchoring", + "proves_hardware_key_custody", + ]: + if boundaries.get(key) is not False: + errors.append(f"sanitized closure boundaries.{key} must remain false") + containment = record.get("historical_bearer_containment", {}) + if containment.get("exposed_staging_evidence_urls_found") != 2: + errors.append("sanitized closure containment count drifted") + if containment.get("targeted_archive_entries_removed") != 2: + errors.append("sanitized closure removed count drifted") + if containment.get("all_urls_http_404_after_restart") is not True: + errors.append("sanitized closure must preserve post-restart 404 containment") + if containment.get("git_history_rewritten") is not False: + errors.append("sanitized closure must not imply Git history was rewritten") + return errors + + def main() -> int: errors = [] errors += check_phrases() errors += check_evidence_pack_schema() errors += check_evidence_pack_samples() errors += check_mcp_templates() + errors += check_sanitized_closure() if errors: print("Proof-spine guard failed:") for error in errors: