package attesto // ADR-0014 — a verifier bundle's provenance root, checked offline. // // The Merkle rules are pinned by bundle-tree-* in the golden corpus; these // tests cover what sits on top of them: the bundle hash authenticating the root // and the key lifecycle, the receipt time coming from the bundle's own receipts, // and the frozen revocation rule applied to the installation the leaf names. import ( "encoding/json" "fmt" "strings" "testing" "time" ) const testRevokedAt = "2026-08-18T12:40:00.000Z" func testBundleLeaf(seqNo int64, installation, occurredAt string) BundleLeaf { if occurredAt == "" { occurredAt = fmt.Sprintf("2026-08-18T12:3%d:00.000Z", seqNo) } return BundleLeaf{ SeqNo: seqNo, CapsuleRoot: strings.Repeat(fmt.Sprintf("%02x", seqNo), 32), InstallationID: installation, KeyID: "key-" + installation, VaultAssurance: "L1", OccurredAt: occurredAt, } } func testLifecycle(installation, revokedAt, reason string) map[string]any { status := "active" var revoked any if revokedAt != "" { status = "revoked" revoked = revokedAt } var reasonValue any if reason != "" { reasonValue = reason } return map[string]any{ "installation_id": installation, "key_id": "key-" + installation, "public_key_hex": strings.Repeat("ab", 32), "status": status, "revoked_at": revoked, "revocation_reason": reasonValue, "replaced_by_installation_id": nil, "revocation_instant_reconstructed": reason == "unrecorded", } } // roundTrip turns typed values into the map[string]any shape a JSON bundle has. func roundTrip(t *testing.T, value any) map[string]any { t.Helper() encoded, err := json.Marshal(value) if err != nil { t.Fatalf("marshal: %v", err) } var out map[string]any if err := json.Unmarshal(encoded, &out); err != nil { t.Fatalf("unmarshal: %v", err) } return out } func testBundle(t *testing.T, leaves []BundleLeaf, lifecycle []map[string]any, issued map[int64]string) map[string]any { t.Helper() tree, err := BundleProvenanceRoot(leaves) if err != nil { t.Fatalf("root: %v", err) } payload := map[string]any{ "kind": "verifier-bundle", "event_count": len(leaves), "provenance_root": tree.ProvenanceRoot, "provenance_event_count": tree.LeafCount, "vault_key_lifecycle": lifecycle, } hash, err := DomainHashHex(ProofstreamDomains["bundle"], payload) if err != nil { t.Fatalf("hash: %v", err) } receipts := []map[string]any{} for seqNo, moment := range issued { receipts = append(receipts, map[string]any{ "seq_no": seqNo, "receipt": map[string]any{"payload": map[string]any{"seq_no": seqNo, "issued_at": moment}}, }) } return roundTrip(t, map[string]any{"payload": payload, "bundle_hash": hash, "receipts": receipts}) } func testInclusion(t *testing.T, bundle map[string]any, leaves []BundleLeaf, seqNo int64) map[string]any { t.Helper() proof, err := BundleProvenanceProof(leaves, seqNo) if err != nil { t.Fatalf("prove: %v", err) } inclusion := roundTrip(t, proof) inclusion["kind"] = BundleInclusionKind inclusion["protocol"] = "ATTESTO-PROOFSTREAM-001" inclusion["protocol_version"] = "0.1-alpha" inclusion["bundle_hash"] = bundle["bundle_hash"] return inclusion } var ( testLeaves = []BundleLeaf{testBundleLeaf(1, "lvi_alpha", ""), testBundleLeaf(2, "lvi_beta", ""), testBundleLeaf(3, "lvi_alpha", "")} testIssued = map[int64]string{1: "2026-08-18T12:31:05.000Z", 2: "2026-08-18T12:32:05.000Z", 3: "2026-08-18T12:33:05.000Z"} ) func liveLifecycle() []map[string]any { return []map[string]any{testLifecycle("lvi_alpha", "", ""), testLifecycle("lvi_beta", "", "")} } func TestBundleProvenanceValidInclusionUnderLiveKeyIsAccepted(t *testing.T) { bundle := testBundle(t, testLeaves, liveLifecycle(), testIssued) report := VerifyBundleProvenance(bundle, testInclusion(t, bundle, testLeaves, 2)) if !report.Ok { t.Fatalf("expected ok: %v", report.Problems) } if report.Inclusion != InclusionValid || report.KeyStatus != KeyStatusValid || len(report.Flags) != 0 { t.Fatalf("unexpected report: %+v", report) } if *report.SeqNo != 2 || report.InstallationID != "lvi_beta" || report.ReceiptTime != testIssued[2] { t.Fatalf("unexpected facts: %+v", report) } ids := map[string]bool{} for _, claim := range report.NotClaimed { ids[claim["id"]] = true } if !ids["bundle_asserts_capsule_existence_not_contents"] || !ids["revocation_evaluated_against_platform_receipt_time_not_vault_occurred_at"] { t.Fatalf("non-claims missing: %v", report.NotClaimed) } } func TestBundleProvenanceForeignLeafIsNotIncluded(t *testing.T) { bundle := testBundle(t, testLeaves, liveLifecycle(), testIssued) inclusion := testInclusion(t, bundle, testLeaves, 1) inclusion["leaf"].(map[string]any)["capsule_root"] = strings.Repeat("ee", 32) report := VerifyBundleProvenance(bundle, inclusion) if report.Ok || report.Inclusion != InclusionInvalid { t.Fatalf("foreign leaf must not be included: %+v", report) } // The key verdict is still reported: the two facts are independent. if report.KeyStatus != KeyStatusValid { t.Fatalf("key status must still be evaluated: %+v", report) } } func TestBundleProvenanceWrongRootIsRefused(t *testing.T) { bundle := testBundle(t, testLeaves, liveLifecycle(), testIssued) inclusion := testInclusion(t, bundle, testLeaves, 1) inclusion["provenance_root"] = strings.Repeat("ab", 32) report := VerifyBundleProvenance(bundle, inclusion) if report.Ok || !strings.Contains(strings.Join(report.Problems, ";"), "different provenance_root") { t.Fatalf("wrong root must be refused: %+v", report) } } func TestBundleProvenanceKeyRevokedBeforeReceipt(t *testing.T) { leaves := []BundleLeaf{testBundleLeaf(1, "lvi_alpha", ""), testBundleLeaf(2, "lvi_beta", ""), testBundleLeaf(3, "lvi_alpha", "2026-08-18T12:45:00.000Z")} issued := map[int64]string{1: testIssued[1], 2: testIssued[2], 3: "2026-08-18T12:45:05.000Z"} lifecycle := []map[string]any{testLifecycle("lvi_alpha", testRevokedAt, "key_compromise"), testLifecycle("lvi_beta", "", "")} bundle := testBundle(t, leaves, lifecycle, issued) report := VerifyBundleProvenance(bundle, testInclusion(t, bundle, leaves, 3)) if report.Ok || report.Inclusion != InclusionValid || report.KeyStatus != KeyStatusRevokedAtReceipt { t.Fatalf("expected revoked_at_receipt: %+v", report) } if strings.Join(report.Flags, ",") != "revoked_at_receipt" || report.RevokedAt != testRevokedAt { t.Fatalf("unexpected flags: %+v", report) } // The same installation's earlier event, received before revocation, stands. earlier := VerifyBundleProvenance(bundle, testInclusion(t, bundle, leaves, 1)) if !earlier.Ok || earlier.KeyStatus != KeyStatusValid { t.Fatalf("earlier event must stand: %+v", earlier) } } func TestBundleProvenanceBackdatedClaimIsFlagged(t *testing.T) { issued := map[int64]string{1: testIssued[1], 2: testIssued[2], 3: "2026-08-18T12:45:05.000Z"} lifecycle := []map[string]any{testLifecycle("lvi_alpha", testRevokedAt, ""), testLifecycle("lvi_beta", "", "")} bundle := testBundle(t, testLeaves, lifecycle, issued) report := VerifyBundleProvenance(bundle, testInclusion(t, bundle, testLeaves, 3)) if report.KeyStatus != KeyStatusRevokedAtReceipt || strings.Join(report.Flags, ",") != "revoked_at_receipt,suspect_backdated" { t.Fatalf("expected suspect_backdated: %+v", report) } } func TestBundleProvenanceUnknownInstallation(t *testing.T) { bundle := testBundle(t, testLeaves, []map[string]any{testLifecycle("lvi_alpha", "", "")}, testIssued) report := VerifyBundleProvenance(bundle, testInclusion(t, bundle, testLeaves, 2)) if report.Ok || report.Inclusion != InclusionValid || report.KeyStatus != KeyStatusUnknownInstallation { t.Fatalf("expected unknown_installation: %+v", report) } } func TestBundleProvenanceTamperedLifecycleBreaksTheBundleHash(t *testing.T) { lifecycle := []map[string]any{testLifecycle("lvi_alpha", testRevokedAt, ""), testLifecycle("lvi_beta", "", "")} bundle := testBundle(t, testLeaves, lifecycle, testIssued) inclusion := testInclusion(t, bundle, testLeaves, 1) entries := bundle["payload"].(map[string]any)["vault_key_lifecycle"].([]any) entries[0].(map[string]any)["revoked_at"] = nil report := VerifyBundleProvenance(bundle, inclusion) if report.Ok || !strings.Contains(strings.Join(report.Problems, ";"), "bundle_hash mismatch") { t.Fatalf("a tampered lifecycle must break the bundle hash: %+v", report) } } func TestBundleProvenanceMissingReceiptLeavesTheKeyUnevaluated(t *testing.T) { bundle := testBundle(t, testLeaves, liveLifecycle(), map[int64]string{1: testIssued[1]}) report := VerifyBundleProvenance(bundle, testInclusion(t, bundle, testLeaves, 2)) if report.Ok || report.KeyStatus != KeyStatusNotEvaluated { t.Fatalf("expected not_evaluated: %+v", report) } } func TestBundleProvenanceInclusionForAnotherBundleIsRefused(t *testing.T) { bundle := testBundle(t, testLeaves, liveLifecycle(), testIssued) inclusion := testInclusion(t, bundle, testLeaves, 1) inclusion["bundle_hash"] = strings.Repeat("00", 32) report := VerifyBundleProvenance(bundle, inclusion) if !strings.Contains(strings.Join(report.Problems, ";"), "inclusion is for a different bundle") { t.Fatalf("expected refusal: %+v", report) } } func TestKeyRevocationMirrorsThePlatformRule(t *testing.T) { revoked := time.Date(2026, 8, 18, 12, 40, 0, 0, time.UTC) never := EvaluateKeyRevocation(nil, revoked, nil, "") if never.Status != KeyStatusValid || len(never.Flags) != 0 || never.RevokedAt != nil { t.Fatalf("never revoked must be valid: %+v", never) } before := EvaluateKeyRevocation(&revoked, revoked.Add(-time.Millisecond), nil, "") if !before.Accepted() || !before.RevokedAt.Equal(revoked) { t.Fatalf("received before revocation must be valid: %+v", before) } // Inclusive boundary: exactly at the instant is revoked. at := EvaluateKeyRevocation(&revoked, revoked, nil, "") if at.Status != KeyStatusRevokedAtReceipt || strings.Join(at.Flags, ",") != "revoked_at_receipt" { t.Fatalf("at the instant must be revoked: %+v", at) } claimedBefore := revoked.Add(-time.Minute) backdated := EvaluateKeyRevocation(&revoked, revoked.Add(time.Minute), &claimedBefore, "") if strings.Join(backdated.Flags, ",") != "revoked_at_receipt,suspect_backdated" { t.Fatalf("backdated claim must be flagged: %+v", backdated) } claimedAfter := revoked.Add(time.Minute) honest := EvaluateKeyRevocation(&revoked, revoked.Add(time.Minute), &claimedAfter, "") if strings.Join(honest.Flags, ",") != "revoked_at_receipt" { t.Fatalf("honest claim must not be flagged: %+v", honest) } reconstructed := EvaluateKeyRevocation(&revoked, revoked.Add(-time.Hour), nil, "unrecorded") if !reconstructed.Accepted() || !reconstructed.InstantReconstructed { t.Fatalf("unrecorded reason must be reported: %+v", reconstructed) } if EvaluateKeyRevocation(&revoked, revoked.Add(-time.Hour), nil, "rotation").InstantReconstructed { t.Fatalf("a measured instant must not be reported as reconstructed") } }