carlos / platform Public

activator: the adoption verb answers 500 for a launch state whose record the pinner could not read, the 500 guards are tested, the swapped sync is restored by t.Cleanup, and no test message prints a record (end sweep, task 5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 42f0cd8bdf95e7aea68326ef221a1fb2b79e648a parent b0a6a38
3 files changed, +46 −3
  • internal/activator/keyadoption.go +11 −1
  • internal/activator/keyadoption_linux_test.go +6 −1
  • internal/activator/keyadoption_test.go +29 −1
diff --git a/internal/activator/keyadoption.go b/internal/activator/keyadoption.go
index ce63f7c24..2eb6d4b4e 100644
--- a/internal/activator/keyadoption.go
+++ b/internal/activator/keyadoption.go
@@ -67,7 +67,9 @@ type AdoptionLaunch struct {
// some other key), or for a replica row (ruling 26); nothing recorded;
// - 404 with no launch state, 400 for a malformed body (a session or
// generation in it included), 401 without the bearer, 500 when the
-// durable write fails (nothing published).
+// durable write fails, or when the launch state is not a complete
+// writer binding for this host with a publisher (O6's programming
+// error); nothing written or published either way.
//
// Bodies are http.StatusText only: the helper treats every failure as
// non-fatal, and the status is all it reads.
@@ -112,6 +114,14 @@ func (b *ExecBackend) MountInstanceKeyAdoption(mux *http.ServeMux, rt registry.R
return
}
record := instancekey.AdoptionRecord(l.Writer, l.Source, l.KeySHA256)
+ // The record must be one the pinner can read back: a launch state
+ // with an incomplete writer (a zero session, say) is O6's
+ // programming error, answered as the other guard is, not a 204
+ // for a record nobody will ever accept.
+ if _, err := instancekey.ParseAdoption(record); err != nil {
+ fail(w, http.StatusInternalServerError)
+ return
+ }
if err := writeAdoptionRecord(l, rt.Host, record); err != nil {
fail(w, http.StatusInternalServerError)
return
diff --git a/internal/activator/keyadoption_linux_test.go b/internal/activator/keyadoption_linux_test.go
index a891e0913..e5b1b6114 100644
--- a/internal/activator/keyadoption_linux_test.go
+++ b/internal/activator/keyadoption_linux_test.go
@@ -25,6 +25,11 @@ func TestInstanceKeyAdoptionIsDurableBeforeItAnswers(t *testing.T) {
old := adoptionRecordSync
adoptionRecordSync = func(string) error { return errors.New("injected: EIO") }
adminTokenMu.Unlock()
+ t.Cleanup(func() { // whatever fails below, the next test gets the real sync
+ adminTokenMu.Lock()
+ adoptionRecordSync = old
+ adminTokenMu.Unlock()
+ })
if got := f.put(tok, adoptionBody(key, "platform")); got != http.StatusInternalServerError {
t.Fatalf("a failing directory sync: %d, want 500", got)
}
@@ -39,6 +44,6 @@ func TestInstanceKeyAdoptionIsDurableBeforeItAnswers(t *testing.T) {
}
rec, err := os.ReadFile(filepath.Join(f.launch.Dir, rt.Host+instancekey.AdoptionSuffix))
if err != nil || len(f.published) != 1 || string(rec) != string(f.published[0]) {
- t.Fatalf("after the retry: record %q (%v), %d published", rec, err, len(f.published))
+ t.Fatalf("after the retry: record %d bytes (%v), %d published", len(rec), err, len(f.published))
}
}
diff --git a/internal/activator/keyadoption_test.go b/internal/activator/keyadoption_test.go
index 7013744b0..4d775129e 100644
--- a/internal/activator/keyadoption_test.go
+++ b/internal/activator/keyadoption_test.go
@@ -84,7 +84,7 @@ func TestInstanceKeyAdoptionRecordsTheLaunchesWriter(t *testing.T) {
}
rec, err := os.ReadFile(recPath)
if err != nil || string(rec) != string(want) {
- t.Fatalf("report %d: record = %q, %v", i, rec, err)
+ t.Fatalf("report %d: record is %d bytes, want %d, %v", i, len(rec), len(want), err)
}
if st, _ := os.Stat(recPath); st.Mode().Perm() != 0o600 {
t.Fatalf("record mode = %o, want 600", st.Mode().Perm())
@@ -120,3 +120,31 @@ func TestInstanceKeyAdoptionRecordsTheLaunchesWriter(t *testing.T) {
t.Fatal("a record was published without a writer")
}
}
+
+// A launch state O6 built wrong (another host's writer, no publisher, or a
+// writer binding the pinner would refuse) is a 500, with nothing written
+// and nothing published: never a 204 for a record nobody can read.
+func TestInstanceKeyAdoptionRefusesAnIncompleteLaunchState(t *testing.T) {
+ tok := strings.Repeat("f", 64)
+ key := strings.Repeat("K", 43) + "="
+ rt := registry.Route{Host: "shop.example.com", Kind: "instance"}
+ for _, tc := range []struct {
+ name string
+ wreck func(*AdoptionLaunch)
+ }{
+ {"another host's writer", func(l *AdoptionLaunch) { l.Writer.Host = "other.example.com" }},
+ {"no publisher", func(l *AdoptionLaunch) { l.Publish = nil }},
+ {"a zero session", func(l *AdoptionLaunch) { l.Writer.Session = 0 }},
+ {"no incarnation", func(l *AdoptionLaunch) { l.Writer.Incarnation = "" }},
+ {"no generation", func(l *AdoptionLaunch) { l.Writer.Generation = "" }},
+ } {
+ f := newAdoptionFixture(t, rt, tok, key, instancekey.SourcePlatform)
+ tc.wreck(&f.launch)
+ if got := f.put(tok, adoptionBody(key, "platform")); got != http.StatusInternalServerError {
+ t.Fatalf("%s: %d, want 500", tc.name, got)
+ }
+ if _, err := os.Stat(filepath.Join(f.launch.Dir, rt.Host+instancekey.AdoptionSuffix)); !os.IsNotExist(err) || len(f.published) != 0 {
+ t.Fatalf("%s: a record was written or published", tc.name)
+ }
+ }
+}