package release import ( "bytes" "context" "crypto/ed25519" "encoding/base64" "encoding/json" "errors" "fmt" "os" "strings" "testing" "time" "github.com/carlosframework/platform/internal/caps" ) // testKeys mints a signing pair through the exported key helpers, so the // round trip seed -> base64 -> key is exercised too. func testKeys(t *testing.T) (ed25519.PrivateKey, ed25519.PublicKey) { t.Helper() seedB64, pubB64, err := GenerateKey() if err != nil { t.Fatalf("GenerateKey: %v", err) } priv, err := ParseSigningKey(seedB64, "test") if err != nil { t.Fatalf("ParseSigningKey: %v", err) } pub, err := ParsePublicKey(pubB64, "test") if err != nil { t.Fatalf("ParsePublicKey: %v", err) } return priv, pub } // shipRelease ships a one-artifact binary release keyed by plat. func shipRelease(t *testing.T, s Store, acct, app, version, plat string, body []byte) { t.Helper() m := Manifest{ App: app, Version: version, Kind: "binary", Artifacts: map[string]Artifact{plat: {}}, } if err := Ship(context.Background(), s, acct, m, map[string][]byte{plat: body}); err != nil { t.Fatalf("Ship %s/%s: %v", app, version, err) } } func TestShipThenPromoteThenChannelRoundTrip(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1abc", "linux-amd64", []byte("binary bytes v1")) if err := Promote(ctx, s, priv, "bab", "myapp", "canary/x", "v1abc"); err != nil { t.Fatalf("Promote: %v", err) } ptr, err := Channel(ctx, s, pub, "bab", "myapp", "canary/x") if err != nil { t.Fatalf("Channel: %v", err) } if ptr.App != "myapp" || ptr.Channel != "canary/x" || ptr.Version != "v1abc" { t.Fatalf("pointer = %+v", ptr) } if ptr.PromotedAt.IsZero() || len(ptr.History) != 0 { t.Fatalf("pointer = %+v, want stamped PromotedAt and empty history", ptr) } // The manifest round-trips with the sha256 Ship computed. m, err := GetManifest(ctx, s, "bab", "myapp", "v1abc") if err != nil { t.Fatalf("GetManifest: %v", err) } art := m.Artifacts["linux-amd64"] if art.SHA256 != etagOf([]byte("binary bytes v1")) || art.Size != int64(len("binary bytes v1")) { t.Fatalf("artifact = %+v", art) } body, _, err := s.Get(ctx, ArtifactKey("bab", "myapp", "v1abc", art.File)) if err != nil || string(body) != "binary bytes v1" { t.Fatalf("artifact bytes = %q, %v", body, err) } } func TestShipImmutable(t *testing.T) { s := NewDirStore(t.TempDir()) // Re-shipping identical bytes is an idempotent no-op... shipRelease(t, s, "bab", "myapp", "v1abc", "linux-amd64", []byte("same")) shipRelease(t, s, "bab", "myapp", "v1abc", "linux-amd64", []byte("same")) // ...but the same version with DIFFERENT content is refused. m := Manifest{App: "myapp", Version: "v1abc", Kind: "binary", Artifacts: map[string]Artifact{"linux-amd64": {}}} err := Ship(context.Background(), s, "bab", m, map[string][]byte{"linux-amd64": []byte("different")}) if err == nil { t.Fatalf("Ship accepted different content under an existing version") } } func TestPromoteRequiresShippedVersion(t *testing.T) { s := NewDirStore(t.TempDir()) priv, _ := testKeys(t) err := Promote(context.Background(), s, priv, "bab", "myapp", "stable", "ghost1") if err == nil || !errors.Is(err, os.ErrNotExist) { t.Fatalf("Promote of unshipped version: err = %v, want os.ErrNotExist-wrapped", err) } } func TestTamperedPointerRejected(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1abc", "linux-amd64", []byte("bin")) if err := Promote(ctx, s, priv, "bab", "myapp", "stable", "v1abc"); err != nil { t.Fatalf("Promote: %v", err) } key := ChannelKey("bab", "myapp", "stable") raw, etag, err := s.Get(ctx, key) if err != nil { t.Fatalf("Get pointer: %v", err) } var sw signedWrapper if err := json.Unmarshal(raw, &sw); err != nil { t.Fatalf("unmarshal wrapper: %v", err) } // Flip a byte in the signature. sig := []byte(sw.Sig) if sig[10] == 'A' { sig[10] = 'B' } else { sig[10] = 'A' } tampered, _ := json.Marshal(signedWrapper{Payload: sw.Payload, Sig: string(sig)}) if _, err := s.Put(ctx, key, tampered, etag); err != nil { t.Fatalf("plant tampered pointer: %v", err) } if _, err := Channel(ctx, s, pub, "bab", "myapp", "stable"); err == nil { t.Fatalf("Channel accepted a pointer with a flipped signature byte") } // Flip a byte in the payload instead (signature intact) — the signature // covers the exact base64 payload bytes, so this must fail too. payload := []byte(sw.Payload) if payload[10] == 'A' { payload[10] = 'B' } else { payload[10] = 'A' } raw2, etag2, _ := s.Get(ctx, key) _ = raw2 tampered2, _ := json.Marshal(signedWrapper{Payload: string(payload), Sig: sw.Sig}) if _, err := s.Put(ctx, key, tampered2, etag2); err != nil { t.Fatalf("plant tampered payload: %v", err) } if _, err := Channel(ctx, s, pub, "bab", "myapp", "stable"); err == nil { t.Fatalf("Channel accepted a pointer with a flipped payload byte") } // And a validly-signed pointer copied from ANOTHER channel's key is a // cross-channel replay — rejected because app/channel live under the // signature. if err := Promote(ctx, s, priv, "bab", "myapp", "canary/evil", "v1abc"); err != nil { t.Fatalf("Promote canary: %v", err) } canaryRaw, _, _ := s.Get(ctx, ChannelKey("bab", "myapp", "canary/evil")) _, curEtag, _ := s.Get(ctx, key) if _, err := s.Put(ctx, key, canaryRaw, curEtag); err != nil { t.Fatalf("plant replayed pointer: %v", err) } if _, err := Channel(ctx, s, pub, "bab", "myapp", "stable"); err == nil { t.Fatalf("Channel accepted a pointer replayed from another channel") } } func TestPromoteHistoryCapTen(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) for i := 1; i <= 12; i++ { v := fmt.Sprintf("v%02d", i) shipRelease(t, s, "bab", "myapp", v, "linux-amd64", []byte("bin "+v)) if err := Promote(ctx, s, priv, "bab", "myapp", "stable", v); err != nil { t.Fatalf("Promote %s: %v", v, err) } } ptr, err := Channel(ctx, s, pub, "bab", "myapp", "stable") if err != nil { t.Fatalf("Channel: %v", err) } if ptr.Version != "v12" { t.Fatalf("Version = %s, want v12", ptr.Version) } if len(ptr.History) != 10 { t.Fatalf("History has %d entries, want 10: %v", len(ptr.History), ptr.History) } if ptr.History[0] != "v11" || ptr.History[9] != "v02" { t.Fatalf("History = %v, want newest-first v11..v02", ptr.History) } } func TestRollbackSwapsAndReturns(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-amd64", []byte("one")) shipRelease(t, s, "bab", "myapp", "v2", "linux-amd64", []byte("two")) if err := Promote(ctx, s, priv, "bab", "myapp", "stable", "v1"); err != nil { t.Fatalf("Promote v1: %v", err) } // Nothing to roll back to yet. if err := Rollback(ctx, s, priv, "bab", "myapp", "stable"); err == nil { t.Fatalf("Rollback with empty history succeeded") } if err := Promote(ctx, s, priv, "bab", "myapp", "stable", "v2"); err != nil { t.Fatalf("Promote v2: %v", err) } if err := Rollback(ctx, s, priv, "bab", "myapp", "stable"); err != nil { t.Fatalf("Rollback: %v", err) } ptr, err := Channel(ctx, s, pub, "bab", "myapp", "stable") if err != nil { t.Fatalf("Channel: %v", err) } if ptr.Version != "v1" || len(ptr.History) != 1 || ptr.History[0] != "v2" { t.Fatalf("after rollback: %+v, want v1 with history [v2]", ptr) } // A second rollback returns to where you were (the swap semantics). if err := Rollback(ctx, s, priv, "bab", "myapp", "stable"); err != nil { t.Fatalf("second Rollback: %v", err) } ptr, _ = Channel(ctx, s, pub, "bab", "myapp", "stable") if ptr.Version != "v2" || len(ptr.History) != 1 || ptr.History[0] != "v1" { t.Fatalf("after second rollback: %+v, want v2 with history [v1]", ptr) } } func TestChannelWrongKeyRejected(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, _ := testKeys(t) _, otherPub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-amd64", []byte("one")) if err := Promote(ctx, s, priv, "bab", "myapp", "stable", "v1"); err != nil { t.Fatalf("Promote: %v", err) } if _, err := Channel(ctx, s, otherPub, "bab", "myapp", "stable"); err == nil { t.Fatalf("Channel verified against the wrong public key") } } func TestValidChannel(t *testing.T) { for c, want := range map[string]bool{ "stable": true, "beta": true, "canary/feature-x": true, "canary/..": false, "a/b/c": false, "": false, "sta ble": false, } { if got := ValidChannel(c); got != want { t.Errorf("ValidChannel(%q) = %v, want %v", c, got, want) } } } // Guard against the PromotedAt stamp being mistaken for a trust input // anywhere: the bake clock must run off the box's own sightings, and the // stamp is informational. This just pins that signPointer stamps it. func TestSignStampsPromotedAt(t *testing.T) { priv, pub := testKeys(t) p := &ChannelPointer{Account: "bab", App: "myapp", Channel: "stable", Version: "v1"} before := time.Now().Add(-time.Second) raw, err := signPointer(RootSigner(priv), p) if err != nil { t.Fatalf("signPointer: %v", err) } got, err := verifyPointer(pub, raw, "bab", "myapp", "stable") if err != nil { t.Fatalf("verifyPointer: %v", err) } if got.PromotedAt.Before(before) { t.Fatalf("PromotedAt = %v, want stamped at signing time", got.PromotedAt) } } // The ladder, end to end through the store: a build walks edge -> beta -> // stable, a skip is refused with the bypass named, -hotfix places it anyway, // canary is never refused, and repeating a promotion is a no-op success. func TestPromoteOnLadderEnforcesOrdering(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-arm64", []byte("bin v1")) shipRelease(t, s, "bab", "myapp", "v2", "linux-arm64", []byte("bin v2")) promote := func(version, channel string, opt PromoteOptions) (PromoteResult, error) { return PromoteOnLadder(ctx, s, priv, "bab", "myapp", channel, version, opt) } // A fresh build enters at edge, then climbs one rung at a time. if _, err := promote("v1", "edge", PromoteOptions{}); err != nil { t.Fatalf("v1 -> edge: %v", err) } res, err := promote("v1", "beta", PromoteOptions{}) if err != nil { t.Fatalf("v1 edge -> beta: %v", err) } if res.From != RungEdge || res.To != RungBeta || res.NoOp { t.Fatalf("v1 edge -> beta: result = %+v", res) } if _, err := promote("v1", "stable", PromoteOptions{}); err != nil { t.Fatalf("v1 beta -> stable: %v", err) } if p, err := Channel(ctx, s, pub, "bab", "myapp", "stable"); err != nil || p.Version != "v1" { t.Fatalf("stable = %+v, %v; want v1", p, err) } // A build that has been nowhere cannot land on stable, and the refusal // says how to override it. _, err = promote("v2", "stable", PromoteOptions{}) if err == nil { t.Fatalf("v2 (on no rung) -> stable was allowed") } if !strings.Contains(err.Error(), "-hotfix") { t.Fatalf("refusal = %q, want it to name --hotfix", err) } if p, _ := Channel(ctx, s, pub, "bab", "myapp", "stable"); p.Version != "v1" { t.Fatalf("stable moved to %s on a refused promotion", p.Version) } // The skip is refused too — that is what the ladder is for. if _, err := promote("v2", "edge", PromoteOptions{}); err != nil { t.Fatalf("v2 -> edge: %v", err) } if _, err := promote("v2", "stable", PromoteOptions{}); err == nil { t.Fatalf("v2 edge -> stable (a skip) was allowed") } // -hotfix places it anyway, and says so. res, err = promote("v2", "stable", PromoteOptions{Hotfix: true}) if err != nil { t.Fatalf("v2 -> stable --hotfix: %v", err) } if !res.Hotfix || res.To != RungStable { t.Fatalf("hotfix result = %+v", res) } if p, _ := Channel(ctx, s, pub, "bab", "myapp", "stable"); p.Version != "v2" { t.Fatalf("stable = %s after hotfix, want v2", p.Version) } // Repeating a promotion is a no-op success, never an error — even though // v1 now sits on beta while stable has moved past it. res, err = promote("v1", "beta", PromoteOptions{}) if err != nil { t.Fatalf("re-promoting v1 to the beta it already holds: %v", err) } if !res.NoOp { t.Fatalf("re-promotion result = %+v, want NoOp", res) } } // Production runs on canary/* channels right now: ordering must never refuse // one, whatever the build is already on. func TestPromoteOnLadderNeverRefusesCanary(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-arm64", []byte("bin v1")) for _, channel := range []string{"canary/keymail", "canary/platform-adoption", "canary/rehearsal"} { if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", channel, "v1", PromoteOptions{}); err != nil { t.Fatalf("promote v1 -> %s: %v", channel, err) } if p, err := Channel(ctx, s, pub, "bab", "myapp", channel); err != nil || p.Version != "v1" { t.Fatalf("%s = %+v, %v", channel, p, err) } } // ...including a build that has already reached stable. if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "edge", "v1", PromoteOptions{Hotfix: true}); err != nil { t.Fatalf("hotfix v1 -> edge: %v", err) } if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "canary/late", "v1", PromoteOptions{}); err != nil { t.Fatalf("promote a build that is on edge back onto a canary: %v", err) } } // VersionRung answers "how mature is this build" from the channel pointers // that exist, and reports the HIGHEST rung when several point at it. func TestVersionRungReportsHighestRung(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-arm64", []byte("bin v1")) if rung, err := VersionRung(ctx, s, pub, "bab", "myapp", "v1"); err != nil || rung != "" { t.Fatalf("VersionRung with no pointers = %q, %v; want \"\"", rung, err) } if err := Promote(ctx, s, priv, "bab", "myapp", "canary/x", "v1"); err != nil { t.Fatalf("Promote: %v", err) } if rung, err := VersionRung(ctx, s, pub, "bab", "myapp", "v1"); err != nil || rung != RungCanary { t.Fatalf("VersionRung on canary = %q, %v", rung, err) } if err := Promote(ctx, s, priv, "bab", "myapp", "beta", "v1"); err != nil { t.Fatalf("Promote: %v", err) } if rung, err := VersionRung(ctx, s, pub, "bab", "myapp", "v1"); err != nil || rung != RungBeta { t.Fatalf("VersionRung on canary+beta = %q, %v; want the highest", rung, err) } // A channel that is not a rung says nothing about maturity. shipRelease(t, s, "bab", "myapp", "v2", "linux-arm64", []byte("bin v2")) if err := Promote(ctx, s, priv, "bab", "myapp", "wip", "v2"); err != nil { t.Fatalf("Promote: %v", err) } if rung, err := VersionRung(ctx, s, pub, "bab", "myapp", "v2"); err != nil || rung != "" { t.Fatalf("VersionRung of a build on a non-rung channel = %q, %v; want \"\"", rung, err) } } // Every promotion is recorded on the pointer it moves: what moved, from which // rung to which, who did it, whether it bypassed the ladder, and when. func TestPromotionRecordsAnAuditEntry(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-arm64", []byte("bin v1")) shipRelease(t, s, "bab", "myapp", "v2", "linux-arm64", []byte("bin v2")) if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "edge", "v1", PromoteOptions{Actor: "paul@keymail.dev"}); err != nil { t.Fatalf("v1 -> edge: %v", err) } if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "beta", "v1", PromoteOptions{Actor: "paul@keymail.dev"}); err != nil { t.Fatalf("v1 -> beta: %v", err) } p, err := Channel(ctx, s, pub, "bab", "myapp", "beta") if err != nil { t.Fatalf("Channel beta: %v", err) } if len(p.Audit) != 1 { t.Fatalf("beta audit = %+v, want one entry", p.Audit) } got := p.Audit[0] if got.Version != "v1" || got.From != RungEdge || got.To != RungBeta || got.Actor != "paul@keymail.dev" || got.Hotfix || got.At.IsZero() { t.Fatalf("audit entry = %+v", got) } // A hotfix says so, and the trail keeps what came before it, newest first. if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "beta", "v2", PromoteOptions{Actor: "james@keymail.dev", Hotfix: true}); err != nil { t.Fatalf("v2 -> beta --hotfix: %v", err) } p, err = Channel(ctx, s, pub, "bab", "myapp", "beta") if err != nil { t.Fatalf("Channel beta: %v", err) } if len(p.Audit) != 2 { t.Fatalf("beta audit = %+v, want two entries", p.Audit) } if !p.Audit[0].Hotfix || p.Audit[0].Version != "v2" || p.Audit[0].Actor != "james@keymail.dev" { t.Fatalf("newest audit entry = %+v, want the hotfix", p.Audit[0]) } if p.Audit[1].Version != "v1" || p.Audit[1].Hotfix { t.Fatalf("older audit entry = %+v, want v1's ordinary promotion", p.Audit[1]) } // A no-op repeat records nothing: nothing happened. if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "beta", "v2", PromoteOptions{Actor: "james@keymail.dev"}); err != nil { t.Fatalf("repeat promotion: %v", err) } if p, _ := Channel(ctx, s, pub, "bab", "myapp", "beta"); len(p.Audit) != 2 { t.Fatalf("a no-op repeat appended an audit entry: %+v", p.Audit) } // Rollback is not a promotion, but it must not lose the trail either. if err := Rollback(ctx, s, priv, "bab", "myapp", "beta"); err != nil { t.Fatalf("Rollback: %v", err) } if p, _ := Channel(ctx, s, pub, "bab", "myapp", "beta"); len(p.Audit) != 2 { t.Fatalf("rollback dropped the audit trail: %+v", p.Audit) } } // The audit trail is additive: pointers written before it existed — and there // are live ones in production buckets — must still verify and parse, with no // audit data and no error. This is the exact payload the pre-audit signPointer // produced, signed the same way. func TestPointerWrittenBeforeAuditStillParses(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "myapp", "v1", "linux-arm64", []byte("bin v1")) old := `{ "schema": 1, "app": "myapp", "channel": "beta", "version": "v1", "promoted_at": "2026-07-01T10:00:00Z", "history": [ "v0" ] }` b64 := base64.StdEncoding.EncodeToString([]byte(old)) wrapper, err := json.MarshalIndent(signedWrapper{ Payload: b64, Sig: base64.StdEncoding.EncodeToString(ed25519.Sign(priv, []byte(b64))), }, "", " ") if err != nil { t.Fatalf("marshal wrapper: %v", err) } if _, err := s.Put(ctx, ChannelKey("bab", "myapp", "beta"), wrapper, ""); err != nil { t.Fatalf("plant pre-audit pointer: %v", err) } p, err := Channel(ctx, s, pub, "bab", "myapp", "beta") if err != nil { t.Fatalf("Channel on a pre-audit pointer: %v", err) } if p.Version != "v1" || len(p.History) != 1 || p.History[0] != "v0" { t.Fatalf("pre-audit pointer = %+v", p) } if p.Audit != nil { t.Fatalf("pre-audit pointer has audit data: %+v", p.Audit) } // It still answers "which rung is this build on", and still promotes — // the trail simply starts at the next promotion. if rung, err := VersionRung(ctx, s, pub, "bab", "myapp", "v1"); err != nil || rung != RungBeta { t.Fatalf("VersionRung on a pre-audit pointer = %q, %v", rung, err) } if _, err := PromoteOnLadder(ctx, s, priv, "bab", "myapp", "stable", "v1", PromoteOptions{Actor: "paul@keymail.dev"}); err != nil { t.Fatalf("promote a pre-audit build: %v", err) } sp, err := Channel(ctx, s, pub, "bab", "myapp", "stable") if err != nil { t.Fatalf("Channel stable: %v", err) } if len(sp.Audit) != 1 || sp.Audit[0].From != RungBeta || sp.Audit[0].To != RungStable { t.Fatalf("stable audit = %+v", sp.Audit) } } // TestShipRefusesAnUnknownCapability: validateManifest's capability gate runs // at SHIP, where a human is standing at a terminal to read the refusal — not // only on the box hours later. The refusal has to name the offending value, // because "invalid capabilities" tells an operator nothing about which line // of their block to fix. func TestShipRefusesAnUnknownCapability(t *testing.T) { s := NewDirStore(t.TempDir()) m := Manifest{ App: "myapp", Version: "v1abc", Kind: "binary", Artifacts: map[string]Artifact{"linux-arm64": {}}, // 8080 is not a capability: only privileged ports are, and a high // port needs no help from the platform. Capabilities: &caps.Set{V: 1, Ports: []caps.Port{{Port: 8080, Name: "http"}}}, } err := Ship(context.Background(), s, "bab", m, map[string][]byte{"linux-arm64": []byte("bin")}) if err == nil { t.Fatal("Ship accepted a capability block the box would refuse — the ship and adopt gates have diverged") } if !strings.Contains(err.Error(), "8080") { t.Fatalf("refusal %q does not name the offending port", err) } // And nothing was written: the gate runs before a single byte moves. if _, err := GetManifest(context.Background(), s, "bab", "myapp", "v1abc"); err == nil { t.Fatal("a refused ship still wrote a manifest") } } // TestShipRefusesAnUnsupportedCapabilityVersion pins the other half of §3b's // fail-closed direction at ship time: a block this binary does not speak is // refused with a message naming the fix, rather than shipped for a box to // choke on later. func TestShipRefusesAnUnsupportedCapabilityVersion(t *testing.T) { s := NewDirStore(t.TempDir()) m := Manifest{ App: "myapp", Version: "v1abc", Kind: "binary", Artifacts: map[string]Artifact{"linux-arm64": {}}, Capabilities: &caps.Set{V: caps.Version + 1, Daemon: true}, } err := Ship(context.Background(), s, "bab", m, map[string][]byte{"linux-arm64": []byte("bin")}) if err == nil { t.Fatal("Ship accepted a capability block version this binary does not speak") } if !strings.Contains(err.Error(), "update the platform binary") { t.Fatalf("refusal %q does not name the fix", err) } } // TestShipRoundTripsACapabilityBlock: a valid declaration survives the whole // immutable-manifest round trip — marshalled by Ship, re-decoded through // caps.Set's strict door by GetManifest — with every field intact. This is // the trust chain the design turns on: the declaration rides the same signed // pointer -> immutable manifest -> sha256 path as the bytes it describes. func TestShipRoundTripsACapabilityBlock(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() want := &caps.Set{ V: 1, Command: "relay", Daemon: true, Children: true, RuntimeDir: "keymail", Ports: []caps.Port{{Port: 25, Name: "mx"}}, Data: &caps.Data{Replicate: caps.DataReplicateApp}, HostRole: true, } m := Manifest{ App: "keymail", Version: "v1abc", Kind: "binary", Artifacts: map[string]Artifact{"linux-arm64": {}}, Capabilities: want, } if err := Ship(ctx, s, "bab", m, map[string][]byte{"linux-arm64": []byte("bin")}); err != nil { t.Fatalf("Ship: %v", err) } got, err := GetManifest(ctx, s, "bab", "keymail", "v1abc") if err != nil { t.Fatalf("GetManifest: %v", err) } if got.Capabilities == nil { t.Fatal("the capability block did not survive the round trip") } // Compared through the canonical JSON encoding, not reflect.DeepEqual: // caps.Set carries an unexported notes slice, so a decoded Set is not // DeepEqual-safe against a literal once those notes are non-empty. a, _ := json.Marshal(want) b, _ := json.Marshal(got.Capabilities) if string(a) != string(b) { t.Fatalf("capabilities round-tripped as %s, want %s", b, a) } } // Fast-track (2026-08-04 console bake controls spec §5): re-sign the head // with the bake waiver — same version, same history, one new audit entry — // and never from a scoped key, at mint or at verification. func TestFastTrackWaivesTheHeadInPlace(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "kass", "v1", "linux-amd64", []byte("b1")) shipRelease(t, s, "bab", "kass", "v2", "linux-amd64", []byte("b2")) if err := Promote(ctx, s, priv, "bab", "kass", "stable", "v1"); err != nil { t.Fatal(err) } if err := Promote(ctx, s, priv, "bab", "kass", "stable", "v2"); err != nil { t.Fatal(err) } ver, err := FastTrack(ctx, s, priv, "bab", "kass", "stable", "paul@keymail.dev") if err != nil { t.Fatalf("FastTrack: %v", err) } if ver != "v2" { t.Fatalf("FastTrack waived %q, want the head v2", ver) } p, err := Channel(ctx, s, pub, "bab", "kass", "stable") if err != nil { t.Fatal(err) } if !p.FastTrack || p.Version != "v2" { t.Fatalf("pointer = version %s fast_track %v, want v2 waived", p.Version, p.FastTrack) } // History survives — a fast-tracked head must stay rollbackable. if len(p.History) == 0 || p.History[0] != "v1" { t.Fatalf("history = %v, want v1 preserved", p.History) } // The waiver is recorded on the trail it waives. if len(p.Audit) == 0 || !p.Audit[0].FastTrack || p.Audit[0].Actor != "paul@keymail.dev" { t.Fatalf("audit[0] = %+v, want a fast_track entry naming the actor", p.Audit) } // Idempotent: a second fast-track is a no-op success. if _, err := FastTrack(ctx, s, priv, "bab", "kass", "stable", "paul@keymail.dev"); err != nil { t.Fatalf("repeated FastTrack: %v", err) } // The NEXT promotion starts clean — fast_track is per write, never // inherited (spec §5). shipRelease(t, s, "bab", "kass", "v3", "linux-amd64", []byte("b3")) if err := Promote(ctx, s, priv, "bab", "kass", "stable", "v3"); err != nil { t.Fatal(err) } if p, _ := Channel(ctx, s, pub, "bab", "kass", "stable"); p.FastTrack { t.Fatal("fast_track survived onto the next promotion") } } // Root only, both directions (mint AND verification, like the grant cap): // a scoped signer cannot SIGN a fast-tracked pointer, and a hand-built // grant-bearing wrapper whose payload carries fast_track does not VERIFY. func TestFastTrackIsRootOnly(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "kass", "v1", "linux-amd64", []byte("b1")) if err := Promote(ctx, s, priv, "bab", "kass", "edge", "v1"); err != nil { t.Fatal(err) } seed, grantB64, err := MintKeyGrant(priv, "builder", []string{RungEdge}, maxGrantTTL) if err != nil { t.Fatal(err) } key, err := ParseSigningKey(seed, "test") if err != nil { t.Fatal(err) } scoped, err := ScopedSigner(key, grantB64, pub) if err != nil { t.Fatal(err) } // Mint side: the scoped signer refuses the payload. if _, err := signPointer(scoped, &ChannelPointer{ Account: "bab", App: "kass", Channel: "edge", Version: "v1", FastTrack: true, }); err == nil || !strings.Contains(err.Error(), "root") { t.Fatalf("a scoped signer signed a fast-tracked pointer (err=%v)", err) } // Verify side: build the wrapper by hand, exactly as a patched-out mint // check would, and watch verification refuse it. payload, _ := json.Marshal(ChannelPointer{Schema: 1, App: "kass", Channel: "edge", Version: "v1", FastTrack: true, PromotedAt: timeNowTestHelper()}) b64 := base64.StdEncoding.EncodeToString(payload) sg, err := parseGrantBlob(grantB64, "test") if err != nil { t.Fatal(err) } wrapper, _ := json.Marshal(signedWrapper{ Payload: b64, Sig: base64.StdEncoding.EncodeToString(ed25519.Sign(key, []byte(b64))), Grant: sg, }) if _, err := verifyPointer(pub, wrapper, "bab", "kass", "edge"); err == nil || !strings.Contains(err.Error(), "root") { t.Fatalf("a scoped-signed fast_track pointer verified (err=%v)", err) } } // The wire change is additive both ways: a pre-change pointer still parses // (no fast_track key at all), and a fast-tracked pointer parses in a struct // that predates the field — the old binary simply keeps baking. func TestFastTrackIsAdditiveOnTheWire(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, _ := testKeys(t) shipRelease(t, s, "bab", "kass", "v1", "linux-amd64", []byte("b1")) if err := Promote(ctx, s, priv, "bab", "kass", "stable", "v1"); err != nil { t.Fatal(err) } if _, err := FastTrack(ctx, s, priv, "bab", "kass", "stable", ""); err != nil { t.Fatal(err) } raw, _, err := GetQualified(ctx, s, ChannelKey("bab", "kass", "stable")) if err != nil { t.Fatal(err) } var sw signedWrapper if err := json.Unmarshal(raw, &sw); err != nil { t.Fatal(err) } payload, err := base64.StdEncoding.DecodeString(sw.Payload) if err != nil { t.Fatal(err) } // The old binary's shape: every pre-fast_track field, nothing else. var old struct { Schema int `json:"schema"` App string `json:"app"` Channel string `json:"channel"` Version string `json:"version"` } if err := json.Unmarshal(payload, &old); err != nil { t.Fatalf("an old struct shape failed to parse a fast-tracked payload: %v", err) } if old.Version != "v1" { t.Fatalf("old shape read version %q", old.Version) } } func TestManifestLabelNotesAdditive(t *testing.T) { // A manifest written before label/notes existed must still parse (the // production buckets are full of them) … old := []byte(`{"schema":1,"app":"km","version":"de2766f8","kind":"binary","artifacts":{"linux-arm64":{"file":"linux-arm64","sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","size":1}}}`) var m Manifest if err := json.Unmarshal(old, &m); err != nil { t.Fatalf("old manifest no longer parses: %v", err) } if m.Label != "" || m.Notes != "" { t.Fatalf("absent fields decoded non-empty: %q %q", m.Label, m.Notes) } // … and a label-free manifest must MARSHAL byte-identically to before, // or idempotent re-ship of an old release breaks on its own metadata. out, err := json.Marshal(m) if err != nil { t.Fatal(err) } if bytes.Contains(out, []byte("label")) || bytes.Contains(out, []byte("notes")) { t.Fatalf("empty label/notes leaked into marshal: %s", out) } } func TestValidateManifestLabelNotesLimits(t *testing.T) { base := func() *Manifest { return &Manifest{Schema: 1, App: "km", Version: "0.5.0-1", Kind: "binary", Artifacts: map[string]Artifact{"linux-arm64": {File: "linux-arm64", SHA256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Size: 1}}} } m := base() m.Label = "fixing modals" m.Notes = "- rounded the corners\n- fixed the focus trap" if err := validateManifest(m); err != nil { t.Fatalf("valid label/notes refused: %v", err) } m = base() m.Label = strings.Repeat("x", MaxLabelLen+1) if err := validateManifest(m); err == nil { t.Fatal("overlong label accepted") } m = base() m.Label = "two\nlines" if err := validateManifest(m); err == nil { t.Fatal("multi-line label accepted") } m = base() m.Notes = strings.Repeat("x", MaxNotesLen+1) if err := validateManifest(m); err == nil { t.Fatal("overlong notes accepted") } } func TestPromoteRetryRenewsPromotedAt(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "console", "v1", adoptPlatform, []byte("b")) if _, err := PromoteOnLadder(ctx, s, priv, "bab", "console", "canary/x", "v1", PromoteOptions{}); err != nil { t.Fatal(err) } before, _ := Channel(ctx, s, pub, "bab", "console", "canary/x") time.Sleep(1100 * time.Millisecond) // PromotedAt is truncated to the second res, err := PromoteOnLadder(ctx, s, priv, "bab", "console", "canary/x", "v1", PromoteOptions{}) if err != nil || !res.NoOp { t.Fatalf("plain repeat = %+v, %v; want the existing no-op", res, err) } same, _ := Channel(ctx, s, pub, "bab", "console", "canary/x") if !same.PromotedAt.Equal(before.PromotedAt) { t.Fatal("a plain repeat rewrote the pointer") } if _, err := PromoteOnLadder(ctx, s, priv, "bab", "console", "canary/x", "v1", PromoteOptions{Retry: true}); err != nil { t.Fatalf("retry: %v", err) } after, _ := Channel(ctx, s, pub, "bab", "console", "canary/x") if after.Version != "v1" || !after.PromotedAt.After(before.PromotedAt) { t.Fatalf("after retry = %+v, want v1 with a later PromotedAt", after) } } // A retry that decided on v1, then finds the channel moved to v2 before its // write, must refuse and leave v2 in place. The guarded write is called // directly with the version the retry saw, so the window is deterministic. func TestPromoteRetryWriteRefusesWhenTheChannelMoved(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "console", "v1", adoptPlatform, []byte("a")) shipRelease(t, s, "bab", "console", "v2", adoptPlatform, []byte("b")) sg := RootSigner(priv) if err := sg.Promote(ctx, s, "bab", "console", "canary/x", "v2"); err != nil { t.Fatal(err) } err := sg.promote(ctx, s, "bab", "console", "canary/x", "v1", nil, "v1", Promotion{Retry: true}) if err == nil || !strings.Contains(err.Error(), "v2") || !strings.Contains(err.Error(), "v1") { t.Fatalf("guarded retry write = %v, want a refusal naming both versions", err) } cp, cerr := Channel(ctx, s, pub, "bab", "console", "canary/x") if cerr != nil || cp.Version != "v2" { t.Fatalf("channel after refused retry = %+v, %v; want v2 untouched", cp, cerr) } // And a retry whose expectation holds still writes. if err := sg.promote(ctx, s, "bab", "console", "canary/x", "v2", nil, "v2", Promotion{Retry: true}); err != nil { t.Fatalf("guarded retry write with a matching version: %v", err) } } // Final review F7: the guarded write's own pointer was stamped this very // second. The retry must still produce a strictly later PromotedAt. func TestPromoteRetryStampsAfterTheGuardedPointer(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, s, "bab", "console", "v1", adoptPlatform, []byte("a")) sg := RootSigner(priv) if err := sg.Promote(ctx, s, "bab", "console", "canary/x", "v1"); err != nil { t.Fatal(err) } before, _ := Channel(ctx, s, pub, "bab", "console", "canary/x") if err := sg.promote(ctx, s, "bab", "console", "canary/x", "v1", nil, "v1", Promotion{Retry: true}); err != nil { t.Fatalf("retry: %v", err) } after, _ := Channel(ctx, s, pub, "bab", "console", "canary/x") if !after.PromotedAt.After(before.PromotedAt) { t.Fatalf("retry stamped %v over %v, want strictly later", after.PromotedAt, before.PromotedAt) } } // getHook runs onGet before every Get, so a test can land a competing write // between a caller's first pointer read and its guarded one. type getHook struct { Store onGet func(key string) } func (h *getHook) Get(ctx context.Context, key string) ([]byte, string, error) { h.onGet(key) return h.Store.Get(ctx, key) } // Final review F7, the race itself: PromoteOnLadder's first read sees an old // pointer (no wait needed), then a concurrent retry renews it before the // guarded read. The stamp is judged against the pointer the write is // conditional on, so it is still strictly later than the competitor's. func TestConcurrentRetriesNeverShareAStamp(t *testing.T) { inner := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) shipRelease(t, inner, "bab", "console", "v1", adoptPlatform, []byte("a")) sg := RootSigner(priv) if err := sg.Promote(ctx, inner, "bab", "console", "canary/x", "v1"); err != nil { t.Fatal(err) } time.Sleep(1100 * time.Millisecond) // the first read's pointer is a second old key := ChannelKey("bab", "console", "canary/x") var competitor time.Time gets := 0 s := &getHook{Store: inner} s.onGet = func(k string) { if k != key { return } gets++ if gets == 2 { // sg.promote's guarded read if err := sg.promote(ctx, inner, "bab", "console", "canary/x", "v1", nil, "v1", Promotion{Retry: true}); err != nil { t.Errorf("competing retry: %v", err) } cp, _ := Channel(ctx, inner, pub, "bab", "console", "canary/x") competitor = cp.PromotedAt } } if _, err := sg.PromoteOnLadder(ctx, s, "bab", "console", "canary/x", "v1", PromoteOptions{Retry: true}); err != nil { t.Fatalf("retry: %v", err) } if gets < 2 || competitor.IsZero() { t.Fatalf("the competing retry never ran (gets=%d)", gets) } after, _ := Channel(ctx, inner, pub, "bab", "console", "canary/x") if !after.PromotedAt.After(competitor) { t.Fatalf("retry stamped %v, the competitor %v: want strictly later", after.PromotedAt, competitor) } } func TestPromoteRetryNeverChangesTheVersion(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, _ := testKeys(t) shipRelease(t, s, "bab", "console", "v1", adoptPlatform, []byte("a")) shipRelease(t, s, "bab", "console", "v2", adoptPlatform, []byte("b")) if _, err := PromoteOnLadder(ctx, s, priv, "bab", "console", "canary/x", "v1", PromoteOptions{}); err != nil { t.Fatal(err) } _, err := PromoteOnLadder(ctx, s, priv, "bab", "console", "canary/x", "v2", PromoteOptions{Retry: true}) if err == nil || !strings.Contains(err.Error(), "renews a promotion") { t.Fatalf("retry onto a different version = %v, want a refusal", err) } }