carlos / platform Public

release: fast_track waives the bake window — root-only at mint and at verification

ChannelPointer.FastTrack and Promotion.FastTrack (both omitempty, additive
on the wire) plus the FastTrack verb: re-signs a channel's head in place
with the waiver set, same version and history, one new audit entry, and
never inherited onto the next promotion. Root-key-only in both directions —
signPointer refuses a scoped key's grant, verifyPointer refuses a
grant-bearing wrapper whose payload carries fast_track — since the window
defends subscribers against exactly the keys that are not the root.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VioXzogWf1Xi4Rswz2B6EK
Paul Campbell 2a6ace9a1588e18463850186875b2498ab28550d parent 809433b
2 files changed, +212 −2
  • internal/release/release.go +69 −2
  • internal/release/release_test.go +143 −0
diff --git a/internal/release/release.go b/internal/release/release.go
index e67ac5ab9..5fec54c66 100644
--- a/internal/release/release.go
+++ b/internal/release/release.go
@@ -81,6 +81,13 @@ type ChannelPointer struct {
// pointer written before the trail existed has no "audit" key, parses
// with none, and is not an error; that is most of the live fleet.
Audit []Promotion `json:"audit,omitempty"`
+ // FastTrack waives the supply-chain bake window for THIS version on THIS
+ // channel (2026-08-04 console bake controls spec §5). Root-key-only at
+ // mint AND at verification — a scoped key must never skip the window it
+ // bakes under. Set per write and never inherited: the next promotion
+ // starts clean. ADDITIVE: old pointers have no key; old binaries drop the
+ // field and keep baking, the safe direction.
+ FastTrack bool `json:"fast_track,omitempty"`
}
// Promotion is one entry in a channel pointer's audit trail. It rides inside
@@ -99,8 +106,11 @@ type Promotion struct {
Actor string `json:"actor,omitempty"`
// Hotfix records that the ladder was bypassed. This is the whole reason
// the field exists: a bypass nobody can see is a broken gate.
- Hotfix bool `json:"hotfix,omitempty"`
- At time.Time `json:"at"`
+ Hotfix bool `json:"hotfix,omitempty"`
+ // FastTrack records that this write waived the bake window — same
+ // reasoning as Hotfix: a bypass nobody can see is a broken gate.
+ FastTrack bool `json:"fast_track,omitempty"`
+ At time.Time `json:"at"`
}
// historyMax bounds a pointer's rollback history; auditMax bounds its
@@ -272,6 +282,9 @@ func signPointer(sg Signer, p *ChannelPointer) ([]byte, error) {
if err := sg.allows(p.Channel, p.PromotedAt); err != nil {
return nil, err
}
+ if p.FastTrack && sg.scope != nil {
+ return nil, fmt.Errorf("fast-track is root-key-only — key grant %q cannot waive the bake window", sg.scope.Name)
+ }
payload, err := json.MarshalIndent(p, "", " ")
if err != nil {
return nil, err
@@ -344,6 +357,9 @@ func verifyPointer(pub ed25519.PublicKey, wrapper []byte, wantApp, wantChannel s
if err := validatePointer(&p, wantApp, wantChannel); err != nil {
return nil, err
}
+ if p.FastTrack && sw.Grant != nil {
+ return nil, fmt.Errorf("channel pointer %s/%s: fast_track is root-key-only — a scoped key cannot waive the bake window", p.App, p.Channel)
+ }
if scope != nil {
// promoted_at, not the wall clock: adoption re-verifies every pass, so
// comparing expiry against now would make an expired grant take a
@@ -854,6 +870,57 @@ func (sg Signer) Rollback(ctx context.Context, s Store, acct, app, channel strin
return err
}
+// FastTrack re-signs a channel's current pointer with the bake-window
+// waiver set — same version, same history, one new audit entry (the
+// Rollback precedent: a write that is not a promotion stays out of the
+// ladder). Root key only: the window defends subscribers against exactly
+// the keys that are not the root, so this takes priv directly and never a
+// Signer. A head already waived is a no-op success. Returns the version
+// waived either way.
+//
+// signPointer re-stamps PromotedAt, which is correct here: the bake clock
+// keys on the box's own first sighting of the VERSION (bake.go), which this
+// write does not change, and the console suppresses its bakes-until
+// estimate for a waived head.
+func FastTrack(ctx context.Context, s Store, priv ed25519.PrivateKey, acct, app, channel, actor string) (string, error) {
+ sg := RootSigner(priv)
+ if !ValidAccount(acct) {
+ return "", fmt.Errorf("fast-track: invalid account %q", acct)
+ }
+ if !ValidApp(app) || !ValidChannel(channel) {
+ return "", fmt.Errorf("fast-track: invalid app/channel %s/%s", app, channel)
+ }
+ key := ChannelKey(acct, app, channel)
+ cur, etag, err := GetQualified(ctx, s, key)
+ if err != nil {
+ return "", fmt.Errorf("fast-track: %w", err)
+ }
+ old, err := verifyPointer(sg.verifyPub(), cur, app, channel)
+ if err != nil {
+ return "", fmt.Errorf("fast-track: existing pointer at %s: %w", key, err)
+ }
+ if old.FastTrack {
+ return old.Version, nil
+ }
+ rung, _ := Rung(channel)
+ next := &ChannelPointer{
+ App: app, Channel: channel, Version: old.Version,
+ History: old.History, FastTrack: true,
+ Audit: prependCapped(Promotion{
+ Version: old.Version, From: rung, To: rung, Actor: actor,
+ FastTrack: true, At: time.Now().UTC().Truncate(time.Second),
+ }, old.Audit, auditMax),
+ }
+ wrapper, err := signPointer(sg, next)
+ if err != nil {
+ return "", err
+ }
+ if _, err := s.Put(ctx, key, wrapper, etag); err != nil {
+ return "", err
+ }
+ return old.Version, nil
+}
+
// prependCapped puts v at the head of list, dropping the tail beyond max —
// the newest-first, bounded shape both the rollback history and the audit
// trail have.
diff --git a/internal/release/release_test.go b/internal/release/release_test.go
index a4385b872..8c0101cbe 100644
--- a/internal/release/release_test.go
+++ b/internal/release/release_test.go
@@ -537,3 +537,146 @@ func TestPointerWrittenBeforeAuditStillParses(t *testing.T) {
t.Fatalf("stable audit = %+v", sp.Audit)
}
}
+
+// 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{
+ 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, "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)
+ }
+}