package release import ( "crypto/ed25519" "encoding/base64" "encoding/json" "strings" "testing" "time" ) // mintGrant mints a scoped key + grant with the root key, failing the test on // error — the happy path most cases start from. func mintGrant(t *testing.T, root ed25519.PrivateKey, name string, rungs []string, ttl time.Duration) (ed25519.PrivateKey, string) { t.Helper() seed, blob, err := MintKeyGrant(root, name, rungs, ttl) if err != nil { t.Fatalf("MintKeyGrant(%v): %v", rungs, err) } key, err := ParseSigningKey(seed, "test") if err != nil { t.Fatalf("ParseSigningKey: %v", err) } return key, blob } // forgeGrant signs an arbitrary grant payload with signer — the hand-crafted // grant an attacker (or a root-key holder trying to delegate stable) would // produce. This is how the verify-side guards are exercised without going // through MintKeyGrant, whose own refusals would otherwise hide them. func forgeGrant(t *testing.T, signer ed25519.PrivateKey, g Grant) string { t.Helper() payload, err := json.MarshalIndent(g, "", " ") if err != nil { t.Fatal(err) } b64 := base64.StdEncoding.EncodeToString(payload) blob, err := json.MarshalIndent(signedGrant{ Payload: b64, Sig: base64.StdEncoding.EncodeToString(ed25519.Sign(signer, []byte(b64))), }, "", " ") if err != nil { t.Fatal(err) } return base64.StdEncoding.EncodeToString(blob) } // goodGrant is a grant that passes every check, as the base for one-field // mutations. func goodGrant(pub ed25519.PublicKey) Grant { now := time.Date(2026, 8, 3, 12, 0, 0, 0, time.UTC) return Grant{ Schema: 1, Pub: base64.StdEncoding.EncodeToString(pub), Rungs: []string{RungCanary, RungEdge}, Name: "edge-builder", MintedAt: now, ExpiresAt: now.Add(90 * 24 * time.Hour), } } // The property the whole feature exists for, direction one: not even the // holder of the root key can mint a grant that reaches stable. // // Mutation-mindedness: delete the RungStable check in MintKeyGrant and this // fails on the first two cases — including the one where stable is smuggled // in beside a legitimate rung, which a check that only looked at rungs[0] // would miss. func TestMintRefusesStable(t *testing.T) { root, _ := testKeys(t) for _, rungs := range [][]string{ {RungStable}, {RungEdge, RungStable}, {RungCanary, RungStable, RungBeta}, } { _, _, err := MintKeyGrant(root, "edge-builder", rungs, 30*24*time.Hour) if err == nil { t.Fatalf("MintKeyGrant(%v) succeeded; stable must never be delegable", rungs) } if !strings.Contains(err.Error(), "stable") { t.Errorf("MintKeyGrant(%v) refusal %q does not name stable", rungs, err) } } } // Direction two, enforced separately: a grant that names stable and carries a // VALID root signature is still refused at verification. Mint and verify are // two different programs in production — the minting binary may be older than // the verifying one, or may not have been ours at all. // // Mutation-mindedness: delete the RungStable check in validateGrant and this // goes green while TestMintRefusesStable stays green, which is exactly the // hole the spec asks to be closed in both directions. func TestVerifyRefusesAHandCraftedStableGrant(t *testing.T) { root, rootPub := testKeys(t) _, scopedPub := testKeys(t) g := goodGrant(scopedPub) g.Rungs = []string{RungEdge, RungStable} blob := forgeGrant(t, root, g) sg, err := parseGrantBlob(blob, "test") if err != nil { t.Fatalf("parseGrantBlob: %v", err) } got, err := verifyGrant(rootPub, sg) if err == nil { t.Fatalf("verifyGrant honoured a stable grant: %+v", got) } if !strings.Contains(err.Error(), "stable") { t.Errorf("refusal %q does not name stable", err) } } // The second stable guard, in the scope decision itself: even if a grant // naming stable were somehow honoured, the channel check refuses stable. // // Mutation-mindedness: this is the belt to validateGrant's braces. Remove // either one alone and one of these two tests fails; that is the point of // having both. func TestGrantAllowsRefusesStableChannel(t *testing.T) { _, scopedPub := testKeys(t) g := goodGrant(scopedPub) g.Rungs = []string{RungEdge, RungStable} // as if validateGrant had let it by err := g.allows("stable", g.MintedAt) if err == nil { t.Fatal("grant.allows permitted stable") } if !strings.Contains(err.Error(), "stable") { t.Errorf("refusal %q does not name stable", err) } } // canary in a grant covers every canary/ channel — the fleet runs on // canary/* names, so a grant that only matched the literal string "canary" // would be useless. beta is reachable when granted; a rung outside the grant // is not; a channel that is not a rung at all is not. // // Mutation-mindedness: replace Rung(channel) with a plain string compare and // the canary/* cases fail; drop the covers() check and the out-of-scope cases // pass when they must not. func TestGrantScopeMatchesTheLadderVocabulary(t *testing.T) { _, scopedPub := testKeys(t) g := goodGrant(scopedPub) // canary, edge at := g.MintedAt for _, ch := range []string{"canary", "canary/platform-adoption", "canary/keymail", "canary/console", "canary/rehearsal", "edge"} { if err := g.allows(ch, at); err != nil { t.Errorf("grant covering %v refused %q: %v", g.Rungs, ch, err) } } for _, ch := range []string{"beta", "stable", "wip"} { if err := g.allows(ch, at); err == nil { t.Errorf("grant covering %v allowed %q", g.Rungs, ch) } } // A grant that names beta reaches beta and nothing above it. b := goodGrant(scopedPub) b.Rungs = []string{RungBeta} if err := b.allows("beta", at); err != nil { t.Errorf("beta grant refused beta: %v", err) } if err := b.allows("edge", at); err == nil { t.Error("beta-only grant allowed edge") } } // Expiry is compared against the moment passed in — the pointer's own // promoted_at at verification, wall clock at promotion — never against // time.Now() inside the check. // // Mutation-mindedness: swap `at` for time.Now() in allows() and the // "promoted while valid" case fails, because its `at` is a 2026 date and the // grant it uses expired 90 days after that. func TestGrantExpiryIsComparedAgainstTheGivenMoment(t *testing.T) { _, scopedPub := testKeys(t) g := goodGrant(scopedPub) if err := g.allows("edge", g.ExpiresAt.Add(-time.Second)); err != nil { t.Errorf("grant refused a moment inside its window: %v", err) } if err := g.allows("edge", g.ExpiresAt); err != nil { t.Errorf("grant refused its exact expiry instant: %v", err) } err := g.allows("edge", g.ExpiresAt.Add(time.Second)) if err == nil { t.Fatal("grant allowed a moment past its expiry") } if !strings.Contains(err.Error(), "expired") { t.Errorf("refusal %q does not say expired", err) } } // A grant's lifetime is capped at a year, at mint and at verification. A // root-key holder hand-crafting a ten-year edge key is not an attack the // scheme can prevent, but it is one it declines to honour: the bound on // delegation lives in the same place as the bound on what may be delegated. // // Mutation-mindedness: raise or delete maxGrantTTL in either place and the // corresponding half of this test goes green when it must not. func TestGrantLifetimeIsCappedAtOneYear(t *testing.T) { root, rootPub := testKeys(t) if _, _, err := MintKeyGrant(root, "edge-builder", []string{RungEdge}, maxGrantTTL+time.Hour); err == nil { t.Error("MintKeyGrant accepted a lifetime over the cap") } if _, _, err := MintKeyGrant(root, "edge-builder", []string{RungEdge}, maxGrantTTL); err != nil { t.Errorf("MintKeyGrant refused exactly the cap: %v", err) } if _, _, err := MintKeyGrant(root, "edge-builder", []string{RungEdge}, 0); err == nil { t.Error("MintKeyGrant accepted a zero lifetime") } if _, _, err := MintKeyGrant(root, "edge-builder", []string{RungEdge}, -time.Hour); err == nil { t.Error("MintKeyGrant accepted a negative lifetime") } _, scopedPub := testKeys(t) g := goodGrant(scopedPub) g.ExpiresAt = g.MintedAt.Add(maxGrantTTL + time.Hour) sg, err := parseGrantBlob(forgeGrant(t, root, g), "test") if err != nil { t.Fatal(err) } if _, err := verifyGrant(rootPub, sg); err == nil { t.Error("verifyGrant honoured a grant running longer than the cap") } } // A grant naming a rung that is not in the frozen vocabulary fails closed — // a typo must not silently widen or narrow a scope. // // Mutation-mindedness: drop the RungIndex check and "prod" is honoured as a // rung nothing matches, which is a scope nobody can reason about. func TestGrantRejectsUnknownRungs(t *testing.T) { root, rootPub := testKeys(t) if _, _, err := MintKeyGrant(root, "edge-builder", []string{"prod"}, time.Hour); err == nil { t.Error("MintKeyGrant accepted an unknown rung") } if _, _, err := MintKeyGrant(root, "edge-builder", nil, time.Hour); err == nil { t.Error("MintKeyGrant accepted an empty rung list") } _, scopedPub := testKeys(t) g := goodGrant(scopedPub) g.Rungs = []string{"prod"} sg, err := parseGrantBlob(forgeGrant(t, root, g), "test") if err != nil { t.Fatal(err) } if _, err := verifyGrant(rootPub, sg); err == nil { t.Error("verifyGrant honoured an unknown rung") } } // A grant signed by anything other than the root key the verifier is pinned // to fails, and says so as a GRANT failure — distinct from a pointer // signature failure, so an operator can tell which link of the chain broke. // // A tampered payload and a wrong signer are cryptographically the same event // ("this signature does not check out") and deliberately share one message; // what must never happen is either of them being honoured. // // Mutation-mindedness: remove the ed25519.Verify in verifyGrant and both // cases go green, and anyone able to write a bucket object could mint trust. func TestGrantSignatureMustBeByTheRootKey(t *testing.T) { root, rootPub := testKeys(t) notRoot, _ := testKeys(t) _, scopedPub := testKeys(t) // Signed by a key that is not the root. sg, err := parseGrantBlob(forgeGrant(t, notRoot, goodGrant(scopedPub)), "test") if err != nil { t.Fatal(err) } if _, err := verifyGrant(rootPub, sg); err == nil { t.Fatal("verifyGrant honoured a grant signed by a non-root key") } else if !strings.Contains(err.Error(), "key grant signature") { t.Errorf("refusal %q does not name the grant signature", err) } // Signed by the root, then the payload swapped for a wider scope. good := goodGrant(scopedPub) wider := good wider.Rungs = []string{RungCanary, RungEdge, RungBeta} tampered, err := parseGrantBlob(forgeGrant(t, root, good), "test") if err != nil { t.Fatal(err) } widerPayload, err := json.MarshalIndent(wider, "", " ") if err != nil { t.Fatal(err) } tampered.Payload = base64.StdEncoding.EncodeToString(widerPayload) if _, err := verifyGrant(rootPub, tampered); err == nil { t.Fatal("verifyGrant honoured a tampered grant payload") } else if !strings.Contains(err.Error(), "key grant signature") { t.Errorf("refusal %q does not name the grant signature", err) } } // A minted grant round-trips: the blob parses, verifies against the root // public key, and describes the key that was minted with it. func TestMintedGrantRoundTrips(t *testing.T) { root, rootPub := testKeys(t) key, blob := mintGrant(t, root, "edge-builder", []string{RungCanary, RungEdge}, 30*24*time.Hour) sg, err := parseGrantBlob(blob, "test") if err != nil { t.Fatalf("parseGrantBlob: %v", err) } g, err := verifyGrant(rootPub, sg) if err != nil { t.Fatalf("verifyGrant: %v", err) } if g.Schema != 1 || g.Name != "edge-builder" { t.Fatalf("grant = %+v", g) } want := base64.StdEncoding.EncodeToString(key.Public().(ed25519.PublicKey)) if g.Pub != want { t.Fatalf("grant pub = %q, want the minted key's public half %q", g.Pub, want) } if got := g.ExpiresAt.Sub(g.MintedAt); got != 30*24*time.Hour { t.Fatalf("grant lifetime = %v, want 720h", got) } if err := g.allows("edge", g.MintedAt); err != nil { t.Fatalf("minted edge grant refuses edge: %v", err) } } // The scoped seed is TAGGED. A scoped key and a root key are both 32 random // bytes, so nothing downstream could otherwise tell them apart — and the one // mistake that must never pass silently is a scoped seed dropped into the // root key's slot with no grant beside it. ParseSigningKey accepts the tag // and an untagged seed alike, so every existing root key keeps parsing. // // Mutation-mindedness: drop the prefix from MintKeyGrant's seed and the // promote-side "grant is missing" refusal loses the only signal it has. func TestScopedSeedIsTaggedAndStillParses(t *testing.T) { root, _ := testKeys(t) seed, _, err := MintKeyGrant(root, "edge-builder", []string{RungEdge}, time.Hour) if err != nil { t.Fatal(err) } if !strings.HasPrefix(seed, ScopedKeyPrefix) { t.Fatalf("minted seed %q is not tagged with %q", seed, ScopedKeyPrefix) } if !IsScopedSeed(seed) { t.Fatalf("IsScopedSeed(%q) = false", seed) } key, err := ParseSigningKey(seed, "test") if err != nil { t.Fatalf("ParseSigningKey on a tagged seed: %v", err) } // The same 32 bytes without the tag parse to the same key, and are not // mistaken for a scoped seed. plain := strings.TrimPrefix(seed, ScopedKeyPrefix) if IsScopedSeed(plain) { t.Error("an untagged seed was reported scoped") } same, err := ParseSigningKey(plain, "test") if err != nil { t.Fatalf("ParseSigningKey on an untagged seed: %v", err) } if !key.Equal(same) { t.Error("tagged and untagged forms of one seed parsed to different keys") } } // A grant blob that is not base64, not JSON, or not a grant at all fails with // a message naming where it came from — the operator pasted the wrong secret. func TestGrantBlobParseErrorsNameTheSource(t *testing.T) { for _, blob := range []string{"", "not base64!!", base64.StdEncoding.EncodeToString([]byte("{not json"))} { _, err := parseGrantBlob(blob, "CARLOS_RELEASE_GRANT") if err == nil { t.Fatalf("parseGrantBlob(%q) succeeded", blob) } if !strings.Contains(err.Error(), "CARLOS_RELEASE_GRANT") { t.Errorf("error %q does not name the source", err) } } } // A pointer dated before the grant existed is forged history: no real // promotion by a key can predate the key, so the floor refuses it outright // (2026-08-03 review, IMPORTANT 1 — before the floor, a scoped key could // sign a pointer dated years before its own mint and it verified). // // Mutation-mindedness: delete the at.Before(g.MintedAt) refusal in allows() // and the first half of this test goes green when it must not; the second // half pins that the exact mint instant — the earliest honest promotion — // stays allowed, so the floor cannot drift into refusing real history. func TestGrantRefusesAPointerPredatingTheGrant(t *testing.T) { _, scopedPub := testKeys(t) g := goodGrant(scopedPub) err := g.allows("edge", g.MintedAt.Add(-time.Second)) if err == nil { t.Fatal("grant honoured a pointer dated before the grant was minted") } if !strings.Contains(err.Error(), "predates") { t.Errorf("refusal %q does not say the pointer predates the key", err) } if err := g.allows("edge", g.MintedAt); err != nil { t.Errorf("grant refused its own mint instant: %v", err) } } // Duplicate rungs are collapsed at mint (2026-08-03 review, MINOR 6): // harmless to verify, noise in every listing of the grant forever. func TestMintDeduplicatesRungs(t *testing.T) { root, _ := testKeys(t) rootPub := root.Public().(ed25519.PublicKey) _, blob := mintGrant(t, root, "dupes", []string{"edge", "edge", "canary", "edge"}, time.Hour) sg, err := parseGrantBlob(blob, "test") if err != nil { t.Fatal(err) } g, err := verifyGrant(rootPub, sg) if err != nil { t.Fatal(err) } if len(g.Rungs) != 2 { t.Fatalf("rungs = %v, want the two distinct ones", g.Rungs) } }