package release import ( "context" "errors" "os" "strings" "syscall" "testing" "github.com/carlosframework/platform/internal/hostwrite" ) type heldClaimWork struct { ids []hostwrite.Identity shut bool } func (w *heldClaimWork) With(_ context.Context, id hostwrite.Identity, fn func() error) error { w.ids = append(w.ids, id) if w.shut { return hostwrite.ErrUnavailable } return fn() } // TestMaterializeHeldUnderPublishesThroughTheClaimSelection (moves Plan 3 // Task 5, H13): with CARLOS_HOST_CLAIM on, the held release is staged as // adoption stages and live/ is pointed at it inside the claim // selection, under the identity naming exactly the pinned version, with the // caller's lock inside it. func TestMaterializeHeldUnderPublishesThroughTheClaimSelection(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") work := &heldClaimWork{} locked := 0 m, err := MaterializeHeldUnder(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t), work, func(publish func() error) error { locked++ return publish() }) if err != nil { t.Fatal(err) } if m == nil || m.Version != "v1" { t.Fatalf("manifest %+v", m) } if got, err := LiveVersion(opt, heldTestHost); err != nil || got != "v1" { t.Fatalf("LiveVersion = %q, %v", got, err) } if len(work.ids) != 1 || work.ids[0] != (hostwrite.Identity{Release: "v1"}) || locked != 1 { t.Fatalf("publication ran under %v with the lock taken %d times", work.ids, locked) } } // A refused selection never points live/; a missing selection is // refused before anything is staged. func TestMaterializeHeldUnderRefusals(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") if _, err := MaterializeHeldUnder(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t), nil, nil); !errors.Is(err, errHeldNoGuard) { t.Fatalf("no selection: %v", err) } if _, err := MaterializeHeldUnder(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t), &heldClaimWork{shut: true}, nil); !errors.Is(err, hostwrite.ErrUnavailable) { t.Fatalf("a refused selection: %v", err) } if got, _ := LiveVersion(opt, heldTestHost); got != "" { t.Fatalf("live/ names %q", got) } noOp := heldRoute() noOp.HoldOp = "" if _, err := MaterializeHeldUnder(ctx, s, heldPub, nr(t), opt, noOp, "v1", offGate(t), &heldClaimWork{}, nil); err == nil { t.Fatal("a row no move holds was staged") } } // Settings spec rev 11 §4.3a on the claim path: MaterializeHeldUnder stages // only a build a promotion record or a ratchet-admitted pointer authorizes, // bound to that digest. A build nothing authorizes, or a replayed record over // other bytes under the same name, is refused before an artifact byte is read // or written: nothing staged, no selection entered, live/ untouched. func TestMaterializeHeldUnderStagesOnlyAnAuthorizedBuild(t *testing.T) { t.Run("nothing authorizes it", func(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") shipRelease(t, s, "bab", "console", "v3", adoptPlatform, []byte("shipped, never promoted")) rec := &heldRecordingStore{Store: s} work := &heldClaimWork{} if _, err := MaterializeHeldUnder(ctx, rec, heldPub, nr(t), opt, heldRoute(), "v3", offGate(t), work, nil); !errors.Is(err, ErrHeldNotAuthorized) { t.Fatalf("MaterializeHeldUnder of a never-promoted build = %v; want ErrHeldNotAuthorized", err) } heldClaimNothingStaged(t, rec, work, opt, "v3", false) }) t.Run("a replayed record over other bytes", func(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") saved, _, err := s.Get(ctx, PromotionRecordKey("bab", "console", "v1")) if err != nil { t.Fatal(err) } if err := DeleteVersion(ctx, s, "bab", "console", "v1"); err != nil { t.Fatal(err) } shipRelease(t, s, "bab", "console", "v1", adoptPlatform, []byte("nobody promoted these")) if _, err := s.Put(ctx, PromotionRecordKey("bab", "console", "v1"), saved, ""); err != nil { t.Fatal(err) } rec := &heldRecordingStore{Store: s} work := &heldClaimWork{} if _, err := MaterializeHeldUnder(ctx, rec, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t), work, nil); !errors.Is(err, ErrManifestDigest) { t.Fatalf("MaterializeHeldUnder under a replayed record = %v; want ErrManifestDigest", err) } heldClaimNothingStaged(t, rec, work, opt, "v1", true) }) } // heldClaimNothingStaged fails the test if a claim-path held stage of version // read its artifact, staged it, entered the selection or pointed live/. // manifestRead says whether the stage was allowed to read the manifest (to // check a digest) before refusing. func heldClaimNothingStaged(t *testing.T, rec *heldRecordingStore, work *heldClaimWork, opt, version string, manifestRead bool) { t.Helper() rel := ReleasesPrefix("bab", "console") + version + "/" manifest := ManifestKey("bab", "console", version) rec.mu.Lock() for _, c := range rec.calls { key, ok := strings.CutPrefix(c, "get ") if !ok || !strings.HasPrefix(key, rel) { continue } if manifestRead && key == manifest { continue } rec.mu.Unlock() t.Fatalf("the refused held stage read %s", key) } rec.mu.Unlock() if _, err := os.Stat(VersionPath(opt, "bab", version, "console")); err == nil { t.Fatalf("%s was staged", version) } if len(work.ids) != 0 { t.Fatalf("the refused held stage entered the selection under %v", work.ids) } if got, _ := LiveVersion(opt, heldTestHost); got != "" { t.Fatalf("live/ names %q", got) } } // TestStageHeldVerifiedStagesWithoutPublishing (moves after claim Plan 12, // Task 7; Paul's T7 ruling of 2026-10-12): under the claim, T7 stages the // pinned release into the shared version store and verifies it, §4.1's // authorization and D3's admit before the stage and D3's bind on the staged // bytes after it, and never touches live/: the publication is the // landing's, at configured, under its held-release selection. func TestStageHeldVerifiedStagesWithoutPublishing(t *testing.T) { t.Run("staged, live untouched", func(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") m, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t)) if err != nil { t.Fatal(err) } if m == nil || m.Version != "v1" { t.Fatalf("manifest %+v", m) } if _, err := os.Stat(VersionPath(opt, "bab", "v1", "console")); err != nil { t.Fatalf("v1 was not staged: %v", err) } if _, err := os.Lstat(LiveLink(opt, heldTestHost)); !os.IsNotExist(err) { t.Fatalf("live/ was written: %v", err) } // Again: the stage is idempotent, and still publishes nothing. if _, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t)); err != nil { t.Fatal(err) } if _, err := os.Lstat(LiveLink(opt, heldTestHost)); !os.IsNotExist(err) { t.Fatalf("live/ was written: %v", err) } }) t.Run("proven, live left on the earlier build", func(t *testing.T) { e := newHeldProofEnv(t) t.Setenv("CARLOS_HOST_CLAIM", "1") e.require(t, "console") e.prove(t, e.pinnedSHA) if _, err := StageHeldVerified(e.ctx, e.store, heldPub, nr(t), e.opt, heldRoute(), "v1", e.gate); err != nil { t.Fatal(err) } if _, err := os.Stat(VersionPath(e.opt, "bab", "v1", "console")); err != nil || e.live() != "v0" { t.Fatalf("staged %v, live %q; want v1 staged and v0 live", err, e.live()) } }) t.Run("not proven", func(t *testing.T) { e := newHeldProofEnv(t) t.Setenv("CARLOS_HOST_CLAIM", "1") e.require(t, "console") if _, err := StageHeldVerified(e.ctx, e.store, heldPub, nr(t), e.opt, heldRoute(), "v1", e.gate); !errors.Is(err, ErrHeldNotProven) { t.Fatalf("an unproven release: %v", err) } if _, err := os.Stat(VersionPath(e.opt, "bab", "v1", "console")); err == nil || e.live() != "v0" { t.Fatalf("an unproven release was staged (%v) or live moved (%q)", err, e.live()) } }) t.Run("the staged bytes are not the proven ones", func(t *testing.T) { e := newHeldProofEnv(t) t.Setenv("CARLOS_HOST_CLAIM", "1") e.require(t, "console") e.prove(t, e.pinnedSHA) stale := []byte("not the shipped bytes") down := e.staleCopyDown(t, stale) if _, err := StageHeldVerified(e.ctx, down, heldPub, nr(t), e.opt, heldRoute(), "v1", e.gate); !errors.Is(err, ErrHeldNotProven) || e.live() != "v0" { t.Fatalf("other staged bytes: %v, live %q", err, e.live()) } r, _ := ReadRefusal(HeldRefusalBase(e.bake), heldTestHost) if r == nil || r.Kind != RefusalNotProven || r.MoveOp != heldRoute().HoldOp || !strings.Contains(r.Reason, etagOf(stale)) { t.Fatalf("refusal = %+v, want the move's not-proven record naming the staged hash", r) } }) t.Run("not authorized", func(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") shipRelease(t, s, "bab", "console", "v3", adoptPlatform, []byte("shipped, never promoted")) if _, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, heldRoute(), "v3", offGate(t)); !errors.Is(err, ErrHeldNotAuthorized) { t.Fatalf("a never-promoted build: %v", err) } if _, err := os.Stat(VersionPath(opt, "bab", "v3", "console")); err == nil { t.Fatal("an unauthorized build was staged") } }) t.Run("blocked", func(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") orig := materializeHeldStage t.Cleanup(func() { materializeHeldStage = orig }) materializeHeldStage = func(context.Context, Store, string, string, string, string, string, string) (*Manifest, error) { return nil, &os.PathError{Op: "mkdir", Path: opt, Err: syscall.EROFS} } if _, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t)); !errors.Is(err, ErrStageBlocked) { t.Fatalf("a read-only version store: %v", err) } }) t.Run("refusals", func(t *testing.T) { ctx, s, opt := heldFixture(t) if _, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", nil); !errors.Is(err, errHeldNoProofGate) { t.Fatalf("no gate: %v", err) } noOp := heldRoute() noOp.HoldOp = "" if _, err := StageHeldVerified(ctx, s, heldPub, nr(t), opt, noOp, "v1", offGate(t)); err == nil { t.Fatal("a row no move holds was staged") } if _, err := os.Stat(VersionPath(opt, "bab", "v1", "console")); err == nil { t.Fatal("a refused stage staged v1") } }) } // TestVerifyHeldLiveReadsUnderTheClaim (moves Task 7): the configured step's // reading of a release it published under the held-release selection is // VerifyHeldLive's, which writes nothing, so CARLOS_HOST_CLAIM does not // refuse it. A link on another version is still ErrHeldNotLive. func TestVerifyHeldLiveReadsUnderTheClaim(t *testing.T) { ctx, s, opt := heldFixture(t) t.Setenv("CARLOS_HOST_CLAIM", "1") lock := func(read func() error) error { return read() } if err := VerifyHeldLive(ctx, s, opt, heldRoute(), "v1", offGate(t), lock); !errors.Is(err, ErrHeldNotLive) { t.Fatalf("nothing published: %v, want ErrHeldNotLive", err) } if _, err := MaterializeHeldUnder(ctx, s, heldPub, nr(t), opt, heldRoute(), "v1", offGate(t), &heldClaimWork{}, nil); err != nil { t.Fatal(err) } if err := VerifyHeldLive(ctx, s, opt, heldRoute(), "v1", offGate(t), lock); err != nil { t.Fatalf("published under the selection: %v", err) } }