carlos / platform Public

console: region candidates with positive per-box eligibility incl. the secrets key (nearest-region §6.1, R9)

readEdgesSnapshot reports a failed listing and marks the snapshot
incomplete when any listed file cannot be read or parsed; readEdgesFiles
is now a wrapper over it. regionCandidates folds a snapshot into the home
and the coded regions: a region is eligible only through ONE box that is
reachable, hibernation-configured, serving the shared pool, accepting
inbound, and publishing the console's secrets fingerprint. Its AWS region
comes only from eligible boxes. NoKeyProven needs a complete read and
current writers only. appPolicy classifies the manifest as absent, known
or unreadable. O6, O7 and O13-O15 are verbatim from the approved record.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 43da46d51796c65cb316dd47f448bf369f3a4f8c parent 4d3bea5
3 files changed, +670 −7
  • internal/console/instancesplacement.go +38 −7
  • internal/console/regioncandidates.go +243 −0
  • internal/console/regioncandidates_test.go +389 −0
diff --git a/internal/console/instancesplacement.go b/internal/console/instancesplacement.go
index ba26f71d9..4415862ba 100644
--- a/internal/console/instancesplacement.go
+++ b/internal/console/instancesplacement.go
@@ -51,8 +51,15 @@ type edgesFilePlacementView struct {
// UNKNOWN, while false is a box that published the field and said no.
// Reading absence as no is what made an earlier version withdraw healthy
// regions mid-roll — see placements.
- HibernationConfigured *bool `json:"hibernation_configured"`
- Hosts map[string]json.RawMessage `json:"hosts"`
+ HibernationConfigured *bool `json:"hibernation_configured"`
+ // ServesSharedPool and AcceptsInbound: POINTERS, absent = a writer
+ // predating them (unknown). SecretsKeyFP: absent = no key, or a writer
+ // predating it; AcceptsInbound's presence tells the two apart
+ // (nearest-region spec §6.1, R9).
+ ServesSharedPool *bool `json:"serves_shared_pool"`
+ AcceptsInbound *bool `json:"accepts_inbound"`
+ SecretsKeyFP string `json:"secrets_key_fp"`
+ Hosts map[string]json.RawMessage `json:"hosts"`
}
// loadEdgesJoin folds every readable edges file into host → the boxes that
@@ -79,17 +86,39 @@ func loadEdgesJoin(ctx context.Context, s release.Store) map[string][]servedBy {
// readEdgesFiles is the shared best-effort read under both consumers:
// list, shape-filter, parse, skip anything unreadable or unversioned. A
// failed list is an empty answer, logged — the callers each degrade to
-// their pre-#337/#329 behaviour rather than failing the request.
+// their pre-#337/#329 behaviour rather than failing the request. It is
+// readEdgesSnapshot with the listing error folded into that empty answer.
func readEdgesFiles(ctx context.Context, s release.Store) []edgesFilePlacementView {
if s == nil {
return nil
}
- keys, err := s.List(ctx, edgesFilePrefix)
+ snap, err := readEdgesSnapshot(ctx, s)
if err != nil {
log.Printf("console: api instances: could not list %s for the placement join: %v", edgesFilePrefix, err)
return nil
}
- var out []edgesFilePlacementView
+ return snap.Files
+}
+
+// edgesSnapshot is one read of control/edges/. Complete is false when any
+// listed file could not be read or parsed: positive facts about the boxes
+// that WERE read still hold, but nothing may be concluded about "every
+// box" (R9's NoKeyProven, codex plan-R2 1).
+type edgesSnapshot struct {
+ Files []edgesFilePlacementView
+ Complete bool
+}
+
+// readEdgesSnapshot REPORTS a failed listing instead of answering empty:
+// the door must tell "could not read" (503, C28) from "no box publishes
+// this code" (codex R2-2). A single unreadable or malformed file is
+// skipped, as before, and marks the snapshot incomplete.
+func readEdgesSnapshot(ctx context.Context, s release.Store) (edgesSnapshot, error) {
+ keys, err := s.List(ctx, edgesFilePrefix)
+ if err != nil {
+ return edgesSnapshot{}, err
+ }
+ snap := edgesSnapshot{Complete: true}
for _, key := range keys {
name, ok := strings.CutPrefix(key, edgesFilePrefix)
if !ok || !strings.HasSuffix(name, ".json") || strings.Contains(name, "/") {
@@ -98,16 +127,18 @@ func readEdgesFiles(ctx context.Context, s release.Store) []edgesFilePlacementVi
body, _, err := s.Get(ctx, key)
if err != nil {
log.Printf("console: api instances: could not read %s for the placement join: %v", key, err)
+ snap.Complete = false
continue
}
var f edgesFilePlacementView
if err := json.Unmarshal(body, &f); err != nil || f.V < 1 || f.Box == "" {
log.Printf("console: api instances: skipping %s in the placement join: not a versioned edges file", key)
+ snap.Complete = false
continue
}
- out = append(out, f)
+ snap.Files = append(snap.Files, f)
}
- return out
+ return snap, nil
}
// placementCapability is what one placement code's boxes can do, folded
diff --git a/internal/console/regioncandidates.go b/internal/console/regioncandidates.go
new file mode 100644
index 000000000..9037dcfc2
--- /dev/null
+++ b/internal/console/regioncandidates.go
@@ -0,0 +1,243 @@
+package console
+
+import (
+ "context"
+ "errors"
+ "log"
+ "os"
+ "sort"
+ "sync"
+
+ "github.com/carlosframework/platform/internal/geo"
+ "github.com/carlosframework/platform/internal/provision"
+)
+
+// disagreeSaid and noPointSaid throttle two diagnostics to once per code.
+var disagreeSaid, noPointSaid sync.Map
+
+// regionCandidate is one region an automatic choice may land in (spec
+// §6.1). Code is in the record vocabulary: "" is the home.
+type regionCandidate struct {
+ Code string
+ Home bool
+ AWSRegion string
+ Reachable bool // some box publishing the code has a dial address
+ Hosting bool // ... and its activator configured (unknown counts, as in placements)
+ KeyOK bool // ... and holds the deployment's secrets key (R9)
+ Eligible bool // ONE box has all of it, every fact POSITIVELY true
+ NoKeyProven bool // R9: every reachable hosting box is a current writer, and none holds the key
+}
+
+// unavailableReason is "" for an eligible candidate, else the first bar it
+// fails (the C16 vocabulary).
+func (c regionCandidate) unavailableReason() string {
+ switch {
+ case c.Eligible:
+ return ""
+ case !c.Reachable:
+ return "absent"
+ case !c.Hosting:
+ return "not-hosting"
+ case !c.KeyOK:
+ return "no-secrets-key"
+ }
+ return "not-eligible"
+}
+
+func isTrue(b *bool) bool { return b != nil && *b }
+
+// regionCandidates folds an edges snapshot into candidates. expectedFP is
+// the console's own secrets fingerprint; "" means it cannot judge, and then
+// no coded region is KeyOK. The home is exempt from every eligibility fact.
+// A coded candidate's AWS region comes only from its ELIGIBLE boxes (codex
+// plan-R2 2); NoKeyProven needs a complete snapshot (codex plan-R2 1).
+func regionCandidates(snap edgesSnapshot, homeName, expectedFP string) []regionCandidate {
+ type acc struct {
+ c regionCandidate
+ regions map[string]int
+ hostingBoxes int
+ unknownWriter, keyFound bool
+ }
+ by := map[string]*acc{}
+ get := func(code string, home bool) *acc {
+ a, ok := by[code]
+ if !ok {
+ a = &acc{c: regionCandidate{Code: code, Home: home}, regions: map[string]int{}}
+ by[code] = a
+ }
+ return a
+ }
+ h := get("", true)
+ h.c.Reachable, h.c.Hosting, h.c.KeyOK, h.c.Eligible = true, true, true, true
+ for _, f := range snap.Files {
+ home := f.Placement == "" || (homeName != "" && f.Placement == homeName)
+ if !home && !provision.ValidRegion(f.Placement) {
+ continue // fleet/<name> and malformed codes are never candidates
+ }
+ code := f.Placement
+ if home {
+ code = ""
+ }
+ a := get(code, home)
+ if f.EIP == "" {
+ continue
+ }
+ if home {
+ if f.Region != "" {
+ a.regions[f.Region]++
+ }
+ continue
+ }
+ hosting := isTrue(f.HibernationConfigured) || f.HibernationConfigured == nil
+ keyOK := expectedFP != "" && f.SecretsKeyFP == expectedFP
+ eligible := isTrue(f.HibernationConfigured) && isTrue(f.ServesSharedPool) && isTrue(f.AcceptsInbound) && keyOK
+ a.c.Reachable = true
+ a.c.Hosting = a.c.Hosting || hosting
+ if hosting {
+ a.hostingBoxes++
+ a.c.KeyOK = a.c.KeyOK || keyOK
+ a.keyFound = a.keyFound || keyOK
+ a.unknownWriter = a.unknownWriter || f.AcceptsInbound == nil
+ }
+ a.c.Eligible = a.c.Eligible || eligible
+ if eligible && f.Region != "" {
+ a.regions[f.Region]++
+ }
+ }
+ out := make([]regionCandidate, 0, len(by))
+ for _, a := range by {
+ a.c.AWSRegion = majority(a.c.Code, a.regions)
+ a.c.NoKeyProven = !a.c.Home && snap.Complete && expectedFP != "" && a.hostingBoxes > 0 && !a.unknownWriter && !a.keyFound
+ if a.c.Eligible {
+ if _, ok := geo.LookupAWSRegion(a.c.AWSRegion); !ok {
+ if _, said := noPointSaid.LoadOrStore(a.c.Code, true); !said {
+ log.Printf("console: region %q has no point in the shipped AWS region table (AWS region %q), so region guesses leave it out", a.c.Code, a.c.AWSRegion)
+ }
+ }
+ }
+ out = append(out, a.c)
+ }
+ sort.Slice(out, func(i, j int) bool { return out[i].Code < out[j].Code })
+ return out
+}
+
+// regionCands is regionCandidates with this console's home and expected
+// secrets fingerprint.
+func (s *Server) regionCands(snap edgesSnapshot) []regionCandidate {
+ return regionCandidates(snap, s.cfg.HomeRegion, s.expectedSecretsFP())
+}
+
+// candsOrHome is the candidates from a fresh snapshot, or the home alone
+// when the listing fails (or there is no bucket): for displays and guesses
+// that must not fail.
+func (s *Server) candsOrHome(ctx context.Context) []regionCandidate {
+ if s.cfg.Releases == nil {
+ return homeOnlyCandidates()
+ }
+ snap, err := readEdgesSnapshot(ctx, s.cfg.Releases)
+ if err != nil {
+ return homeOnlyCandidates()
+ }
+ return s.regionCands(snap)
+}
+
+// majority picks the most common AWS region, ties to the lexically
+// smallest, and logs a disagreement once per code.
+func majority(code string, regions map[string]int) string {
+ best, n := "", 0
+ for r, c := range regions {
+ if c > n || (c == n && r < best) {
+ best, n = r, c
+ }
+ }
+ if len(regions) > 1 {
+ if _, said := disagreeSaid.LoadOrStore(code, true); !said {
+ log.Printf("console: boxes for region %q disagree on their AWS region %v; using %s", code, regions, best)
+ }
+ }
+ return best
+}
+
+func homeOnlyCandidates() []regionCandidate {
+ return []regionCandidate{{Code: "", Home: true, Reachable: true, Hosting: true, KeyOK: true, Eligible: true}}
+}
+
+func findCandidate(cands []regionCandidate, code string) (regionCandidate, bool) {
+ for _, c := range cands {
+ if c.Code == code {
+ return c, true
+ }
+ }
+ return regionCandidate{}, false
+}
+
+func eligibleCount(cands []regionCandidate) int {
+ n := 0
+ for _, c := range cands {
+ if c.Eligible {
+ n++
+ }
+ }
+ return n
+}
+
+type policyState int
+
+const (
+ policyAbsent policyState = iota
+ policyKnown
+ policyUnreadable
+)
+
+// regionPolicy is what the manifest and the fleet placement say about
+// where an instance may land (spec §6.1).
+type regionPolicy struct {
+ State policyState
+ M *provision.Manifest
+ Placed string
+}
+
+// appPolicy reads the manifest directly (never instanceManifest, which
+// answers the caller itself) and the fleet placement. Any failure is
+// policyUnreadable: an unrestricted policy is never invented.
+func (s *Server) appPolicy(ctx context.Context, acct *Account, app string) regionPolicy {
+ var p regionPolicy
+ if s.cfg.Releases == nil {
+ return regionPolicy{State: policyUnreadable} // no bucket: nothing to read, so nothing is allowed
+ }
+ m, err := provision.GetManifest(ctx, s.cfg.Releases, acct.Sqid, app)
+ switch {
+ case err == nil:
+ p.State, p.M = policyKnown, m
+ case errors.Is(err, os.ErrNotExist):
+ p.State = policyAbsent
+ default:
+ log.Printf("console: region policy %s/%s: read manifest: %v", acct.Sqid, app, err)
+ return regionPolicy{State: policyUnreadable}
+ }
+ reg, err := openRegistry(s.cfg.Registry)
+ if err != nil {
+ log.Printf("console: region policy %s/%s: open registry: %v", acct.Sqid, app, err)
+ return regionPolicy{State: policyUnreadable}
+ }
+ placed, err := s.appPlacement(reg, acct, app)
+ if err != nil {
+ log.Printf("console: region policy %s/%s: placement: %v", acct.Sqid, app, err)
+ return regionPolicy{State: policyUnreadable}
+ }
+ p.Placed = placed
+ return p
+}
+
+func (p regionPolicy) pooled() bool { return p.State == policyKnown && p.M.Pool != "" }
+
+// allows is the door's own allow-list predicate on a record-vocabulary code.
+func (p regionPolicy) allows(code string) bool {
+ switch p.State {
+ case policyKnown:
+ return instanceRegionAllowed(p.M.Regions, code)
+ case policyAbsent:
+ return true
+ }
+ return false
+}
diff --git a/internal/console/regioncandidates_test.go b/internal/console/regioncandidates_test.go
new file mode 100644
index 000000000..f81ab92fd
--- /dev/null
+++ b/internal/console/regioncandidates_test.go
@@ -0,0 +1,389 @@
+package console
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "io"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+
+ "github.com/carlosframework/platform/internal/provision"
+ "github.com/carlosframework/platform/internal/release"
+)
+
+// mustTestSecretsKey is Task 9's (regionconfig_test.go).
+var testKeyPub, testKeyFP = mustTestSecretsKey()
+
+func bp(b bool) *bool { return &b }
+
+type edgeOpts struct {
+ hib, shared, inbound *bool // nil = the writer predates the field
+ fp string
+}
+
+var eligibleBox = edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true), fp: testKeyFP}
+
+// edgeJSON writes one box's edges file the way internal/host does.
+func edgeJSON(box, eip, awsRegion, placement string, o edgeOpts) string {
+ m := map[string]any{"v": 1, "box": box, "eip": eip, "region": awsRegion, "hosts": map[string]any{}}
+ if placement != "" {
+ m["placement"] = placement
+ }
+ if o.hib != nil {
+ m["hibernation_configured"] = *o.hib
+ }
+ if o.shared != nil {
+ m["serves_shared_pool"] = *o.shared
+ }
+ if o.inbound != nil {
+ m["accepts_inbound"] = *o.inbound
+ }
+ if o.fp != "" {
+ m["secrets_key_fp"] = o.fp
+ }
+ b, _ := json.Marshal(m)
+ return string(b)
+}
+
+var (
+ homeBox = edgeJSON("ie-box", "5.6.7.8", "eu-west-1", "", eligibleBox)
+ ukEligible = edgeJSON("uk-box", "1.2.3.4", "eu-west-2", "uk", eligibleBox)
+ ukNoKey = edgeJSON("uk-box", "1.2.3.4", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)})
+ ukWrongKey = edgeJSON("uk-box", "1.2.3.4", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true), fp: "sha256:" + strings.Repeat("0", 64)})
+ ukOldWriter = edgeJSON("uk-box", "1.2.3.4", "eu-west-2", "uk", edgeOpts{})
+ auPoolOnly = edgeJSON("au-box", "9.9.9.9", "ap-southeast-2", "au", edgeOpts{hib: bp(true), shared: bp(false), inbound: bp(true), fp: testKeyFP})
+ usNoInbound = edgeJSON("us-box", "8.8.4.4", "us-east-1", "us", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(false), fp: testKeyFP})
+ nzNoHosting = edgeJSON("nz-box", "6.6.6.6", "ap-southeast-6", "nz", edgeOpts{hib: bp(false), shared: bp(true), inbound: bp(true), fp: testKeyFP})
+ jpNoEIP = edgeJSON("jp-box", "", "ap-northeast-1", "jp", eligibleBox)
+ fleetBoxFile = edgeJSON("fl-box", "4.4.4.4", "eu-west-2", "fleet/acme", eligibleBox)
+)
+
+// setEdges creates OR replaces edges files. putEdges is create-only (an
+// empty ifMatch on DirStore and S3), so it cannot change a box's file.
+func setEdges(t *testing.T, fx *consoleFixture, files map[string]string) {
+ t.Helper()
+ ctx := context.Background()
+ for name, body := range files {
+ key := "control/edges/" + name + ".json"
+ etag := ""
+ if _, cur, err := fx.rel.Get(ctx, key); err == nil {
+ etag = cur
+ } else if !errors.Is(err, os.ErrNotExist) {
+ t.Fatal(err)
+ }
+ if _, err := fx.rel.Put(ctx, key, []byte(body), etag); err != nil {
+ t.Fatalf("set %s: %v", key, err)
+ }
+ }
+}
+
+type failingList struct{ release.Store }
+
+func (failingList) List(context.Context, string) ([]string, error) {
+ return nil, errors.New("bucket unreachable")
+}
+
+func captureLog(w io.Writer) (restore func()) {
+ prev, flags := log.Writer(), log.Flags()
+ log.SetOutput(w)
+ return func() { log.SetOutput(prev); log.SetFlags(flags) }
+}
+
+// views is a COMPLETE snapshot of the given edges-file bodies.
+func views(t *testing.T, bodies ...string) edgesSnapshot {
+ t.Helper()
+ snap := edgesSnapshot{Complete: true}
+ for _, b := range bodies {
+ var f edgesFilePlacementView
+ if err := json.Unmarshal([]byte(b), &f); err != nil {
+ t.Fatal(err)
+ }
+ snap.Files = append(snap.Files, f)
+ }
+ return snap
+}
+
+func TestRegionCandidatesNeedPositiveEligibility(t *testing.T) {
+ ca := edgeJSON("ca-box", "7.7.7.7", "ca-central-1", "ca", edgeOpts{})
+ cands := regionCandidates(views(t, homeBox, ukEligible, auPoolOnly, usNoInbound, ca, nzNoHosting, jpNoEIP, fleetBoxFile), "ie", testKeyFP)
+ want := map[string]string{"": "", "uk": "", "au": "not-eligible", "us": "not-eligible",
+ "ca": "no-secrets-key", "nz": "not-hosting", "jp": "absent"}
+ if len(cands) != len(want) {
+ t.Fatalf("candidates = %+v, want exactly %v (no fleet code)", cands, want)
+ }
+ for code, reason := range want {
+ c, ok := findCandidate(cands, code)
+ if !ok {
+ t.Fatalf("no candidate %q", code)
+ }
+ if got := c.unavailableReason(); got != reason {
+ t.Errorf("%q: reason %q, want %q", code, got, reason)
+ }
+ }
+ if h, _ := findCandidate(cands, ""); !h.Home || h.AWSRegion != "eu-west-1" || !h.Eligible {
+ t.Errorf("home = %+v", h)
+ }
+}
+
+// R9: a box must hold the deployment's secrets key to receive placed
+// instances, and only a CURRENT writer can prove it does not.
+func TestRegionCandidatesSecretsKey(t *testing.T) {
+ cases := []struct {
+ name string
+ body string
+ expected string
+ reason string
+ noKeyProven bool
+ }{
+ {"matching key", ukEligible, testKeyFP, "", false},
+ {"no key, current writer", ukNoKey, testKeyFP, "no-secrets-key", true},
+ {"wrong key, current writer", ukWrongKey, testKeyFP, "no-secrets-key", true},
+ {"old writer: unknown", ukOldWriter, testKeyFP, "no-secrets-key", false},
+ {"console cannot judge", ukEligible, "", "no-secrets-key", false},
+ }
+ for _, c := range cases {
+ cand, _ := findCandidate(regionCandidates(views(t, homeBox, c.body), "ie", c.expected), "uk")
+ if got := cand.unavailableReason(); got != c.reason || cand.NoKeyProven != c.noKeyProven {
+ t.Errorf("%s: reason %q proven %v, want %q %v", c.name, got, cand.NoKeyProven, c.reason, c.noKeyProven)
+ }
+ }
+ // One box with the key and one without: the region is not PROVEN
+ // keyless, and is eligible through the box that holds it.
+ ukKeyless2 := edgeJSON("uk-box-2", "1.2.3.5", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)})
+ cand, _ := findCandidate(regionCandidates(views(t, homeBox, ukEligible, ukKeyless2), "ie", testKeyFP), "uk")
+ if !cand.Eligible || cand.NoKeyProven {
+ t.Errorf("mixed region = %+v", cand)
+ }
+}
+
+// codex plan-R2 1: a negative proof needs EVERY box. With one file
+// unreadable or malformed, a readable keyless box proves nothing.
+func TestNoKeyProvenNeedsACompleteRead(t *testing.T) {
+ incomplete := views(t, homeBox, ukNoKey)
+ incomplete.Complete = false
+ if c, _ := findCandidate(regionCandidates(incomplete, "ie", testKeyFP), "uk"); c.NoKeyProven {
+ t.Fatal("an incomplete read proved a region keyless")
+ }
+ ctx := context.Background()
+ for name, extra := range map[string]string{"malformed": "{not json", "unversioned": `{"box":"uk-box-2"}`} {
+ s := release.NewDirStore(t.TempDir())
+ for key, body := range map[string]string{"ie-box": homeBox, "uk-box": ukNoKey, "uk-box-2": extra} {
+ if _, err := s.Put(ctx, "control/edges/"+key+".json", []byte(body), ""); err != nil {
+ t.Fatal(err)
+ }
+ }
+ snap, err := readEdgesSnapshot(ctx, s)
+ if err != nil || snap.Complete {
+ t.Fatalf("%s: snapshot complete=%v err=%v, want incomplete", name, snap.Complete, err)
+ }
+ if c, _ := findCandidate(regionCandidates(snap, "ie", testKeyFP), "uk"); c.NoKeyProven {
+ t.Fatalf("%s: proved keyless with a box unassessed", name)
+ }
+ }
+ s := release.NewDirStore(t.TempDir())
+ for key, body := range map[string]string{"ie-box": homeBox, "uk-box": ukNoKey, "uk-box-2": ukEligible} {
+ if _, err := s.Put(ctx, "control/edges/"+key+".json", []byte(body), ""); err != nil {
+ t.Fatal(err)
+ }
+ }
+ snap, err := readEdgesSnapshot(ctx, failingGet{Store: s, key: "control/edges/uk-box-2.json"})
+ if err != nil || snap.Complete {
+ t.Fatalf("failed GET: complete=%v err=%v, want incomplete", snap.Complete, err)
+ }
+ if c, _ := findCandidate(regionCandidates(snap, "ie", testKeyFP), "uk"); c.NoKeyProven {
+ t.Fatal("a failed GET let the readable keyless box prove the region keyless")
+ }
+}
+
+type failingGet struct {
+ release.Store
+ key string
+}
+
+func (f failingGet) Get(ctx context.Context, key string) ([]byte, string, error) {
+ if key == f.key {
+ return nil, "", errors.New("read timeout")
+ }
+ return f.Store.Get(ctx, key)
+}
+
+// codex plan-R2 2: a candidate's coordinates come from its ELIGIBLE boxes
+// only; ties among them go to the lexically smallest AWS region.
+func TestCandidateLocationComesFromEligibleBoxes(t *testing.T) {
+ syd1 := edgeJSON("uk-syd-1", "2.2.2.1", "ap-southeast-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)})
+ syd2 := edgeJSON("uk-syd-2", "2.2.2.2", "ap-southeast-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(false), fp: testKeyFP})
+ c, _ := findCandidate(regionCandidates(views(t, homeBox, ukEligible, syd1, syd2), "ie", testKeyFP), "uk")
+ if !c.Eligible || c.AWSRegion != "eu-west-2" {
+ t.Fatalf("mixed eligibility located uk at %q, want the eligible box's eu-west-2", c.AWSRegion)
+ }
+ dub := edgeJSON("uk-dub", "2.2.2.3", "eu-west-1", "uk", eligibleBox)
+ if c, _ := findCandidate(regionCandidates(views(t, homeBox, ukEligible, dub), "ie", testKeyFP), "uk"); c.AWSRegion != "eu-west-1" {
+ t.Fatalf("eligible tie = %q, want the lexically smallest eu-west-1", c.AWSRegion)
+ }
+}
+
+func TestRegionCandidatesFoldTheHomesName(t *testing.T) {
+ coded := edgeJSON("ie2", "5.6.7.9", "eu-west-1", "ie", eligibleBox)
+ cands := regionCandidates(views(t, homeBox, coded), "ie", testKeyFP)
+ if len(cands) != 1 || !cands[0].Home {
+ t.Fatalf("candidates = %+v, want the home alone", cands)
+ }
+}
+
+// spec §6.3, §6.5: a candidate with no point is logged once per code, and
+// the line carries no caller coordinates (there are none to carry).
+func TestRegionCandidatesLogAMissingPointOnce(t *testing.T) {
+ var buf bytes.Buffer
+ restore := captureLog(&buf)
+ defer restore()
+ noPointSaid.Delete("odd") // the throttle is process-wide; -count=N reruns this test
+ odd := edgeJSON("odd-box", "3.3.3.3", "xx-nowhere-1", "odd", eligibleBox)
+ regionCandidates(views(t, homeBox, odd), "ie", testKeyFP)
+ regionCandidates(views(t, homeBox, odd), "ie", testKeyFP)
+ if n := strings.Count(buf.String(), `region "odd"`); n != 1 {
+ t.Fatalf("missing-point line logged %d times, want once: %s", n, buf.String())
+ }
+}
+
+func TestReadEdgesSnapshotReportsListFailure(t *testing.T) {
+ if _, err := readEdgesSnapshot(context.Background(), failingList{}); err == nil {
+ t.Fatal("a failed listing must be an error, not an empty answer (codex R2-2)")
+ }
+ snap, err := readEdgesSnapshot(context.Background(), release.NewDirStore(t.TempDir()))
+ if err != nil || len(snap.Files) != 0 || !snap.Complete {
+ t.Fatalf("an empty prefix = %+v %v, want complete and empty", snap, err)
+ }
+}
+
+func TestAppPolicyStates(t *testing.T) {
+ fx, _ := instanceFixture(t, "code-policy")
+ acct := &Account{ID: OpsAccountID, Sqid: "bab"}
+ ctx := context.Background()
+ if p := fx.srv.appPolicy(ctx, acct, "titogo"); p.State != policyAbsent || !p.allows("uk") {
+ t.Fatalf("no manifest = %+v", p)
+ }
+ m := titoManifest()
+ m.Pool, m.Regions = "", []string{"uk"}
+ enableInstances(t, fx, "titogo", m)
+ if p := fx.srv.appPolicy(ctx, acct, "titogo"); p.State != policyKnown || p.allows("") || !p.allows("uk") || p.pooled() {
+ t.Fatalf("known = %+v", p)
+ }
+ m.Pool = "tito"
+ enableInstances(t, fx, "titogo", m)
+ if !fx.srv.appPolicy(ctx, acct, "titogo").pooled() {
+ t.Fatal("a pooled manifest must read as pooled")
+ }
+ if err := fx.st.SetAppPlacement(OpsAccountID, "titogo", "fleet/acme"); err != nil {
+ t.Fatal(err)
+ }
+ if p := fx.srv.appPolicy(ctx, acct, "titogo"); p.Placed != "fleet/acme" {
+ t.Fatalf("placed = %q", p.Placed)
+ }
+ _, etag, err := fx.rel.Get(ctx, provision.ManifestKey("bab", "titogo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := fx.rel.Put(ctx, provision.ManifestKey("bab", "titogo"), []byte("{not json"), etag); err != nil {
+ t.Fatal(err)
+ }
+ if p := fx.srv.appPolicy(ctx, acct, "titogo"); p.State != policyUnreadable || p.allows("") {
+ t.Fatalf("unreadable = %+v, want unreadable and nothing allowed", p)
+ }
+ fx.srv.cfg.Releases = nil
+ if p := fx.srv.appPolicy(ctx, acct, "titogo"); p.State != policyUnreadable || p.allows("uk") {
+ t.Fatalf("no bucket = %+v, want unreadable and nothing allowed", p)
+ }
+}
+
+// splitCapability pairs two boxes in one region that between them publish
+// every eligibility fact while neither publishes them all (codex
+// plan-R3 4). Task 11 reuses it for the guess.
+var splitCapability = map[string][2]string{
+ "keyless ordinary box beside a keyed named-pool-only box": {
+ edgeJSON("uk-a", "1.2.3.4", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)}),
+ edgeJSON("uk-b", "1.2.3.5", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(false), inbound: bp(true), fp: testKeyFP}),
+ },
+ "keyed no-inbound box beside a keyless inbound box": {
+ edgeJSON("uk-a", "1.2.3.4", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(false), fp: testKeyFP}),
+ edgeJSON("uk-b", "1.2.3.5", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)}),
+ },
+ "keyed non-hosting box beside a keyless hosting box": {
+ edgeJSON("uk-a", "1.2.3.4", "eu-west-2", "uk", edgeOpts{hib: bp(false), shared: bp(true), inbound: bp(true), fp: testKeyFP}),
+ edgeJSON("uk-b", "1.2.3.5", "eu-west-2", "uk", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)}),
+ },
+}
+
+// Eligibility is ONE box's facts, never the region's union of them.
+func TestEligibilityNeverCombinesBoxes(t *testing.T) {
+ for name, boxes := range splitCapability {
+ cands := regionCandidates(views(t, homeBox, boxes[0], boxes[1]), "ie", testKeyFP)
+ if c, _ := findCandidate(cands, "uk"); c.Eligible || c.unavailableReason() == "" {
+ t.Errorf("%s: uk = %+v, want ineligible", name, c)
+ }
+ if n := eligibleCount(cands); n != 1 {
+ t.Errorf("%s: %d eligible candidates, want the home alone", name, n)
+ }
+ }
+}
+
+// candsOrHome answers from this console's home and secrets key, and falls
+// back to the home alone when the listing fails or there is no bucket.
+func TestCandsOrHomeUsesTheServerAndFallsBackToTheHome(t *testing.T) {
+ fx := newConsoleFixture(t)
+ ctx := context.Background()
+ fx.srv.cfg.HomeRegion, fx.srv.cfg.SecretsPub = "ie", testKeyPub
+ setEdges(t, fx, map[string]string{"ie-box": homeBox, "uk-box": ukEligible, "ie2": edgeJSON("ie2", "5.6.7.9", "eu-west-1", "ie", eligibleBox)})
+ cands := fx.srv.candsOrHome(ctx)
+ if len(cands) != 2 || eligibleCount(cands) != 2 {
+ t.Fatalf("candidates = %+v, want the home (ie folded in) and uk, both eligible", cands)
+ }
+ fx.srv.cfg.SecretsPub = ""
+ if c, _ := findCandidate(fx.srv.candsOrHome(ctx), "uk"); c.Eligible || c.unavailableReason() != "no-secrets-key" {
+ t.Fatalf("no console key: uk = %+v, want no-secrets-key", c)
+ }
+ for name, store := range map[string]release.Store{"failed listing": failingList{Store: fx.rel}, "no bucket": nil} {
+ fx.srv.cfg.Releases = store
+ if cands := fx.srv.candsOrHome(ctx); len(cands) != 1 || !cands[0].Home || !cands[0].Eligible {
+ t.Errorf("%s: candidates = %+v, want the home alone", name, cands)
+ }
+ }
+}
+
+// O6, O7 and O13 to O15 are this file's diagnostics, taken verbatim from
+// the approved copy record and compared as quoted literals.
+func TestRegionCandidatesCopyMatchesTheRecord(t *testing.T) {
+ raw, err := os.ReadFile("../../docs/superpowers/plans/2026-10-02-nearest-region-copy.json")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var rec struct {
+ Entries []struct {
+ ID, File, Text string
+ } `json:"entries"`
+ }
+ if err := json.Unmarshal(raw, &rec); err != nil {
+ t.Fatal(err)
+ }
+ src, err := os.ReadFile("regioncandidates.go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var ids []string
+ for _, e := range rec.Entries {
+ if e.File != "internal/console/regioncandidates.go" {
+ continue
+ }
+ ids = append(ids, e.ID)
+ if !strings.Contains(string(src), strconv.Quote(e.Text)) {
+ t.Errorf("%s: regioncandidates.go has no literal %s", e.ID, strconv.Quote(e.Text))
+ }
+ }
+ if got := strings.Join(ids, ","); got != "O6,O7,O13,O14,O15" {
+ t.Errorf("the record maps %s to regioncandidates.go, want O6,O7,O13,O14,O15", got)
+ }
+}