carlos / platform Public

e2e: the shared job world runs with lifetimes on, as production runs every self-serve move

newJobWorld writes the cutover marker before its console opens and every
console it opens turns lifetimes on; newMemberWorld only adds the member's
token. The whole suite (89 top-level tests) passes this way.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev f7cfd3299c3ee0815b0fec10c225277103c1d06f parent 0b27dfb
2 files changed, +18 −19
  • internal/e2e/selfserve/job_world_test.go +5 −1
  • internal/e2e/selfserve/member_test.go +13 −18

CI failed — run details

CI log
=== gate ===
.amadan/test-gate.sh
gate: 2026-10-23T22:29:00Z on aarch64, 32 cpus, 61387 MB available, go1.26.8 linux/arm64
gate: +0s start launchctx
gate: +0s start vet
gate: +0s start gofmt
gate: +1s start rest
gate: +17s start internal_console@0
gate: +17s start internal_console@1
gate: +17s start internal_console@2
gate: +17s start internal_console@3
gate: +17s start internal_console@4
gate: +17s start internal_console@5
gate: +17s start internal_console@6
gate: +18s start internal_console@7
gate: +20s start root@0
gate: +20s start root@1
gate: +20s start root@2

amadan: step gate failed: signal: terminated

amadan: job failed at step gate — its output is above, not at the tail of this log
diff --git a/internal/e2e/selfserve/job_world_test.go b/internal/e2e/selfserve/job_world_test.go
index 2a42b0a36..c11f290da 100644
--- a/internal/e2e/selfserve/job_world_test.go
+++ b/internal/e2e/selfserve/job_world_test.go
@@ -234,7 +234,7 @@ func switchOf(off bool) string {
const jobConsole = "console-e2e-job"
// newJobWorld builds the bridge with a lifetime record (incarnation 1) and
-// a console beside it in self-serve mode.
+// a console beside it in self-serve mode with lifetimes on.
func newJobWorld(t *testing.T) *jobWorld {
t.Helper()
raw := release.NewDirStore(t.TempDir())
@@ -242,6 +242,10 @@ func newJobWorld(t *testing.T) *jobWorld {
w := &jobWorld{t: t, ctx: context.Background(), e: e, raw: raw, fs: &faultStore{Store: raw}, dir: t.TempDir(), acct: e.Account(), hits: map[string]int{},
failKinds: map[string]bool{}}
w.fs.failing = func() bool { return w.failing }
+ // Lifetimes on, as production runs every self-serve move (the request
+ // door admits only then): the cutover marker before the console opens.
+ w.writeCutoverMarker()
+ w.lifetimes = true
w.open()
// The boxes serve no HTTP: the health probe is the witness's answer,
// a pass unless a witness says otherwise.
diff --git a/internal/e2e/selfserve/member_test.go b/internal/e2e/selfserve/member_test.go
index 0679fb166..03a1cec55 100644
--- a/internal/e2e/selfserve/member_test.go
+++ b/internal/e2e/selfserve/member_test.go
@@ -21,37 +21,32 @@ import (
// an account owner's move-capable instance token on the console, over
// HTTP, as the member's own code would call the three self-serve doors and
// the status poll. The request door admits only on a console that has
-// turned lifetimes on, so a member world writes the cutover marker and
-// turns lifetimes on in every console it opens.
+// turned lifetimes on, which every job world's console has (newJobWorld).
const ownerAddr = "owner@example.com"
-// newMemberWorld is newJobWorld with lifetimes on and the member's token.
+// newMemberWorld is newJobWorld with the member's token.
func newMemberWorld(t *testing.T) *jobWorld {
t.Helper()
w := newJobWorld(t)
- w.lifetimesOn()
w.member()
return w
}
-// lifetimesOn writes the cutover marker and turns lifetimes on in this
-// console and every console the world opens after it.
-func (w *jobWorld) lifetimesOn() {
+// writeCutoverMarker writes the cutover marker (once), so every console
+// the world opens turns lifetimes on (open, console.TestHooks.LifetimesOn).
+func (w *jobWorld) writeCutoverMarker() {
w.t.Helper()
const key = "control/lifetimes-cutover.json"
- if _, _, err := w.raw.Get(w.ctx, key); err != nil {
- body, _ := json.Marshal(struct {
- At time.Time `json:"at"`
- By string `json:"by"`
- }{time.Now().UTC(), ownerAddr})
- if _, err := w.raw.Put(w.ctx, key, body, ""); err != nil && !errors.Is(err, release.ErrCASConflict) {
- w.t.Fatal(err)
- }
+ if _, _, err := w.raw.Get(w.ctx, key); err == nil {
+ return
}
- w.lifetimes = true
- if !console.TestHooks.LifetimesOn(w.ctx, w.srv) {
- w.t.Fatal("lifetimes did not turn on")
+ body, _ := json.Marshal(struct {
+ At time.Time `json:"at"`
+ By string `json:"by"`
+ }{time.Now().UTC(), ownerAddr})
+ if _, err := w.raw.Put(w.ctx, key, body, ""); err != nil && !errors.Is(err, release.ErrCASConflict) {
+ w.t.Fatal(err)
}
}