carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package release_test
2
3import (
4 "context"
5 "encoding/json"
6 "testing"
7
8 "github.com/carlosframework/platform/internal/release"
9)
10
11// liveChannels is what production is running on RIGHT NOW.
12var liveChannels = []string{"canary/platform-adoption", "canary/keymail", "canary/console", "canary/rehearsal"}
13
14// The two channel names production is running on RIGHT NOW must never be
15// refused by the ladder — go.tito.io follows canary/platform-adoption and
16// keymail.dev follows canary/keymail. If these fail, production cannot deploy.
17func TestLiveProductionChannelsAreNeverRefused(t *testing.T) {
18 for _, ch := range liveChannels {
19 rung, ok := release.Rung(ch)
20 if !ok || rung != release.RungCanary {
21 t.Fatalf("Rung(%q) = %q,%v — want canary,true", ch, rung, ok)
22 }
23 // Promotion INTO a canary channel from anywhere must be allowed.
24 for _, from := range []string{"", "canary", "edge", "beta", "stable"} {
25 if err := release.PromotionAllowed(from, release.RungCanary); err != nil {
26 t.Errorf("PromotionAllowed(%q -> canary) refused: %v", from, err)
27 }
28 }
29 }
30}
31
32// The skip that matters: nothing reaches stable without beta, and the refusal
33// tells the operator the way out.
34func TestEdgeToStableIsRefusedAndNamesTheBypass(t *testing.T) {
35 err := release.PromotionAllowed(release.RungEdge, release.RungStable)
36 if err == nil {
37 t.Fatal("edge -> stable was allowed; the ladder means nothing")
38 }
39 if got := err.Error(); !contains(got, "-hotfix") {
40 t.Errorf("refusal %q does not name --hotfix", got)
41 }
42}
43
44// The other half of "production can still deploy": every live channel is
45// promoted with the ROOT key, and what lands is a wrapper with NO grant in
46// it, verifying against the root public key. Scoped signing is opt-in from
47// the first byte — nothing about the fleet's existing pointers changes until
48// someone deliberately mints a scoped key.
49//
50// Mutation-mindedness: make the grant field non-optional, attach an empty
51// grant to root-signed pointers, or route root signing through grant
52// handling, and this fails on the key list — before any signature check, and
53// for every channel production actually runs on.
54func TestLiveProductionChannelsStayRootSignedWithNoGrant(t *testing.T) {
55 ctx := context.Background()
56 s := release.NewDirStore(t.TempDir())
57 seedB64, pubB64, err := release.GenerateKey()
58 if err != nil {
59 t.Fatalf("GenerateKey: %v", err)
60 }
61 priv, err := release.ParseSigningKey(seedB64, "test")
62 if err != nil {
63 t.Fatal(err)
64 }
65 pub, err := release.ParsePublicKey(pubB64, "test")
66 if err != nil {
67 t.Fatal(err)
68 }
69 m := release.Manifest{
70 App: "kass", Version: "9f3c1ad", Kind: "binary",
71 Artifacts: map[string]release.Artifact{"linux-arm64": {}},
72 }
73 if err := release.Ship(ctx, s, release.OpsAccount, m, map[string][]byte{"linux-arm64": []byte("build")}); err != nil {
74 t.Fatalf("Ship: %v", err)
75 }
76
77 for _, ch := range liveChannels {
78 if err := release.Promote(ctx, s, priv, release.OpsAccount, "kass", ch, "9f3c1ad"); err != nil {
79 t.Fatalf("Promote %s: %v", ch, err)
80 }
81 raw, _, err := s.Get(ctx, release.ChannelKey(release.OpsAccount, "kass", ch))
82 if err != nil {
83 t.Fatalf("read %s: %v", ch, err)
84 }
85 var keys map[string]json.RawMessage
86 if err := json.Unmarshal(raw, &keys); err != nil {
87 t.Fatalf("%s: %v", ch, err)
88 }
89 if len(keys) != 2 || keys["payload"] == nil || keys["sig"] == nil {
90 t.Errorf("%s wrapper has keys %v, want exactly payload and sig", ch, keysOf(keys))
91 }
92 if _, err := release.Channel(ctx, s, pub, release.OpsAccount, "kass", ch); err != nil {
93 t.Errorf("%s does not verify against the root pubkey: %v", ch, err)
94 }
95 }
96}
97
98func keysOf(m map[string]json.RawMessage) []string {
99 out := make([]string, 0, len(m))
100 for k := range m {
101 out = append(out, k)
102 }
103 return out
104}
105
106func contains(s, sub string) bool {
107 for i := 0; i+len(sub) <= len(s); i++ {
108 if s[i:i+len(sub)] == sub {
109 return true
110 }
111 }
112 return false
113}
114