carlos / platform Public

release: production memory on the bake clock — off ratchets, deletion never downgrades, replays refused

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VioXzogWf1Xi4Rswz2B6EK
Paul Campbell a28bbbce04a807c994c5f04f1f6539ae031ad700 parent 2a6ace9
2 files changed, +201 −0
  • internal/release/bake.go +100 −0
  • internal/release/bake_test.go +101 −0
diff --git a/internal/release/bake.go b/internal/release/bake.go
index 85b2cac26..dfb5c8a9e 100644
--- a/internal/release/bake.go
+++ b/internal/release/bake.go
@@ -86,6 +86,12 @@ type FirstSeen struct {
// channelClockKey.
Channels map[string]map[string]time.Time `json:"channels"`
+ // Production is the per-app production-flag memory (2026-08-04 console
+ // bake controls spec §4), keyed "<acct>|<app>" with clockSep — the same
+ // collision argument as channelClockKey. ADDITIVE: old clock files have
+ // no key, old binaries drop this one.
+ Production map[string]*prodMemory `json:"production,omitempty"`
+
path string // where Save persists; set by LoadFirstSeen
// migrated marks a clock LoadFirstSeenMigrating built from its
@@ -139,6 +145,9 @@ func LoadFirstSeen(path string) *FirstSeen {
if st.Channels == nil {
st.Channels = map[string]map[string]time.Time{}
}
+ if st.Production == nil {
+ st.Production = map[string]*prodMemory{}
+ }
if st.Jitter < 0 || st.Jitter >= 0.25 {
st.Jitter = 0
}
@@ -304,3 +313,94 @@ func Hold(st *FirstSeen, acct, app, channel, version string, holds map[string]ti
}
return ""
}
+
+// ---- production memory ------------------------------------------------------
+
+// prodMemory is one app's production-flag memory on this box. It exists to
+// hold two properties no bucket read can: DELETION IS NOT A DOWNGRADE (once
+// a verified production: true is seen, absence never clears it — anyone
+// with bucket write but no key can delete an object), and A STALE FLAG
+// CANNOT BE REPLAYED (an off from a past era, re-written by someone with
+// bucket access alone, must not roll back a newer on).
+type prodMemory struct {
+ // WasProduction latches on the first verified production: true.
+ WasProduction bool `json:"was_production,omitempty"`
+ // NewestSetAt is the replay floor: the newest set_at this box has
+ // honored. Anything at or below it is old news.
+ NewestSetAt time.Time `json:"newest_set_at,omitempty"`
+ // OffSetAt identifies the current off-flag edition; OffFirstSeen is when
+ // THIS BOX first saw it — the ratchet clock, the box's own observation,
+ // never the flag's timestamp (same argument as the bake clock itself).
+ OffSetAt time.Time `json:"off_set_at,omitempty"`
+ OffFirstSeen time.Time `json:"off_first_seen,omitempty"`
+}
+
+func prodKey(acct, app string) string { return acct + clockSep + app }
+
+// ObserveProduction folds one VERIFIED flag read into this box's memory.
+// nil (no object in the bucket) changes nothing — absence is not evidence.
+// Returns whether anything changed; the caller persists via Save. Never
+// call it with a flag that failed verification: like Observe, the memory
+// only ever ticks for signed documents.
+func (st *FirstSeen) ObserveProduction(acct, app string, flag *ProductionFlag, now time.Time) bool {
+ if flag == nil {
+ return false
+ }
+ key := prodKey(acct, app)
+ mem := st.Production[key]
+ if mem == nil {
+ mem = &prodMemory{}
+ }
+ // The replay floor. Equal set_at is the object already recorded — the
+ // every-pass re-read — so nothing changes; older is a replay and is
+ // ignored outright.
+ if !flag.SetAt.After(mem.NewestSetAt) {
+ return false
+ }
+ mem.NewestSetAt = flag.SetAt
+ if flag.Production {
+ mem.WasProduction = true
+ mem.OffSetAt, mem.OffFirstSeen = time.Time{}, time.Time{}
+ } else {
+ mem.OffSetAt = flag.SetAt
+ mem.OffFirstSeen = now.UTC().Truncate(time.Second)
+ }
+ st.Production[key] = mem
+ return true
+}
+
+// ProductionBake is the adopt pass's one question: does the supply-chain
+// window apply to this app on this box right now? Call ObserveProduction
+// first — this reads memory, plus flagErr, which is non-nil when a flag
+// object EXISTS but would not read or verify: that fails toward baking (an
+// attacker who can corrupt but not sign must not shorten anything).
+// hasBakeableHead is the spec §4 carve-out: with no held channel head
+// resolved this pass, an off-flag needs no ratchet — there is nothing at a
+// baked head to protect.
+func (st *FirstSeen) ProductionBake(acct, app string, flagErr error, hasBakeableHead bool, holds map[string]time.Duration, now time.Time) bool {
+ if flagErr != nil {
+ return true
+ }
+ mem := st.Production[prodKey(acct, app)]
+ if mem == nil {
+ return false // never declared production — the default
+ }
+ if mem.OffSetAt.IsZero() {
+ // The newest verified word is production: true — or the flag has
+ // vanished since, which never downgrades (WasProduction latches).
+ return mem.WasProduction
+ }
+ // The newest verified word is production: false.
+ if !mem.WasProduction {
+ return false // off, and never was on: nothing to ratchet
+ }
+ if !hasBakeableHead {
+ return false // the carve-out
+ }
+ // The ratchet: off is honored only after the stable window has elapsed
+ // on this box's own sighting of the off-flag, jittered like any hold —
+ // the flag defends itself with the mechanism it controls.
+ d := HoldFor(holds, RungStable)
+ eligible := mem.OffFirstSeen.Add(time.Duration(float64(d) * (1 + st.Jitter)))
+ return now.Before(eligible)
+}
diff --git a/internal/release/bake_test.go b/internal/release/bake_test.go
index 4b66e0004..a4ca340c1 100644
--- a/internal/release/bake_test.go
+++ b/internal/release/bake_test.go
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
+ "fmt"
"os"
"path/filepath"
"testing"
@@ -366,3 +367,103 @@ func TestHoldForEdgeIsZero(t *testing.T) {
t.Fatalf("edge hold = %v, want 0", d)
}
}
+
+// The box-side production memory (2026-08-04 console bake controls spec §4).
+// Scenario table, because the security content IS the state machine: the
+// default is off; on is instant; off ratchets on the box's own clock; a
+// DELETED flag never downgrades a box that saw true; a stale replayed off
+// cannot roll back a newer on.
+func TestProductionMemoryRatchet(t *testing.T) {
+ base := time.Date(2026, 8, 4, 12, 0, 0, 0, time.UTC)
+ flag := func(prod bool, setAt time.Time) *ProductionFlag {
+ return &ProductionFlag{Schema: 1, Account: "bab", App: "kass",
+ Production: prod, SetAt: setAt}
+ }
+ newClock := func() *FirstSeen {
+ st := LoadFirstSeen(filepath.Join(t.TempDir(), "clock.json"))
+ st.Jitter = 0 // determinism: eligibility is exactly firstSeen + hold
+ return st
+ }
+
+ t.Run("default is off", func(t *testing.T) {
+ st := newClock()
+ if st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base) {
+ t.Fatal("an app with no flag ever seen bakes")
+ }
+ })
+
+ t.Run("unverifiable flag fails toward baking", func(t *testing.T) {
+ st := newClock()
+ if !st.ProductionBake("bab", "kass", fmt.Errorf("sig"), true, DefaultHolds, base) {
+ t.Fatal("a corrupt flag read as the default instead of production")
+ }
+ })
+
+ t.Run("on is instant, deletion is not a downgrade", func(t *testing.T) {
+ st := newClock()
+ if !st.ObserveProduction("bab", "kass", flag(true, base), base) {
+ t.Fatal("first observation did not change the clock")
+ }
+ if !st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base) {
+ t.Fatal("production: true did not apply immediately")
+ }
+ // The object vanishes from the bucket (flag == nil every later pass):
+ // the box holds its verdict.
+ st.ObserveProduction("bab", "kass", nil, base.Add(time.Hour))
+ if !st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base.Add(time.Hour)) {
+ t.Fatal("deleting the flag object downgraded a box that saw true")
+ }
+ })
+
+ t.Run("off ratchets for the stable window", func(t *testing.T) {
+ st := newClock()
+ st.ObserveProduction("bab", "kass", flag(true, base), base)
+ off := flag(false, base.Add(time.Hour))
+ st.ObserveProduction("bab", "kass", off, base.Add(2*time.Hour)) // box sees it an hour late
+ hold := HoldFor(DefaultHolds, RungStable)
+ // Still baking just inside the window, measured from the box's OWN
+ // sighting (base+2h), not the flag's set_at (base+1h).
+ if !st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base.Add(2*time.Hour).Add(hold-time.Minute)) {
+ t.Fatal("off was honored before the ratchet elapsed")
+ }
+ if st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base.Add(2*time.Hour).Add(hold+time.Minute)) {
+ t.Fatal("off was not honored after the ratchet elapsed")
+ }
+ })
+
+ t.Run("no bakeable head skips the ratchet", func(t *testing.T) {
+ st := newClock()
+ st.ObserveProduction("bab", "kass", flag(true, base), base)
+ st.ObserveProduction("bab", "kass", flag(false, base.Add(time.Hour)), base.Add(time.Hour))
+ if st.ProductionBake("bab", "kass", nil, false, DefaultHolds, base.Add(time.Hour)) {
+ t.Fatal("carve-out: nothing at a held head, yet off still ratcheted")
+ }
+ })
+
+ t.Run("a stale off cannot be replayed over a newer on", func(t *testing.T) {
+ st := newClock()
+ staleOff := flag(false, base)
+ st.ObserveProduction("bab", "kass", staleOff, base)
+ st.ObserveProduction("bab", "kass", flag(true, base.Add(time.Hour)), base.Add(time.Hour))
+ // Attacker re-writes the old signed off object; the box refuses to
+ // regress below the newest set_at it has honored.
+ if st.ObserveProduction("bab", "kass", staleOff, base.Add(2*time.Hour)) {
+ t.Fatal("a replayed stale flag changed the clock")
+ }
+ if !st.ProductionBake("bab", "kass", nil, true, DefaultHolds, base.Add(100*time.Hour)) {
+ t.Fatal("a replayed stale off eventually turned the bake off")
+ }
+ })
+
+ t.Run("memory survives a save/load round trip", func(t *testing.T) {
+ st := newClock()
+ st.ObserveProduction("bab", "kass", flag(true, base), base)
+ if err := st.Save(); err != nil {
+ t.Fatal(err)
+ }
+ st2 := LoadFirstSeen(st.path)
+ if !st2.ProductionBake("bab", "kass", nil, true, DefaultHolds, base) {
+ t.Fatal("production memory did not survive persistence")
+ }
+ })
+}