carlos / platform Public

docs: nearest-region plan rev 5, after Astra's plan round 4, proved in scratch

R9a holds in the pooled and fleet branches, and canary --region needs both
knowledge flags; refusal lists name only what the same door accepts (one
predicate for app regions, instanceChoices for instances, b variants when
empty); the new-app form stays byte-identical with no picker, tested against
the base tree's rendering. /tmp/g is written as the operator's rule for
socket-test packages, through a socktest function that deletes its own run
directory. Each fix was run failing then passing in a throwaway worktree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 7db8869f54db21c711a3d63cd61d0ec739fedb6e parent 56756f0
1 file changed, +442 −95
  • docs/superpowers/plans/2026-10-02-nearest-region-default.md +442 −95
diff --git a/docs/superpowers/plans/2026-10-02-nearest-region-default.md b/docs/superpowers/plans/2026-10-02-nearest-region-default.md
index 1307f13ef..8d4bebf9e 100644
--- a/docs/superpowers/plans/2026-10-02-nearest-region-default.md
+++ b/docs/superpowers/plans/2026-10-02-nearest-region-default.md
@@ -2,7 +2,7 @@
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-**Revision:** 4.
+**Revision:** 5.
- Rev 1 (9513d52c) was reviewed by Astra
(`CODEX-PLAN-NEAREST-REGION-R1.md`, beside this file): not ready, with
@@ -12,10 +12,12 @@
- Rev 3 answers Astra's round 2 (`CODEX-PLAN-NEAREST-REGION-R2.md`).
- Rev 4 answers Astra's round 3 (`CODEX-PLAN-NEAREST-REGION-R3.md`) and
carries spec rev 6.1's R9a note (`region_known`, `placement_known`).
+- Rev 5 answers Astra's round 4 (`CODEX-PLAN-NEAREST-REGION-R4.md`) and
+ carries spec rev 6.2 (`instance_domain`, approved by Paul 2026-10-03).
- The code blocks the findings touched were **proved**: extracted verbatim
into a throwaway worktree at the branch base, built and vetted, and each
prescribed test was run before and after its implementation step.
-- The three dispositions tables, with the proof results, are at the end.
+- The four dispositions tables, with the proof results, are at the end.
**Goal:** Give every new app a region at creation, preselected from a timezone-then-IP guess, and have new instances default to that region. Never place an instance automatically on a box that cannot open the deployment's secrets. Existing apps, older CLIs and DNS stay unchanged.
@@ -50,8 +52,8 @@ home.
- `net/http` and `html/template`.
**Spec:** `docs/superpowers/specs/2026-10-01-nearest-region-default-design.md`
-(rev 6.1, approved by Paul 2026-10-02, including the R9 amendment and the
-R9a note). Read it
+(rev 6.2, approved by Paul 2026-10-02, including the R9 amendment, the R9a
+note and the rev 6.2 `instance_domain` note approved 2026-10-03). Read it
beside this plan. Section numbers below (§N) are the spec's.
## Global Constraints
@@ -104,13 +106,31 @@ beside this plan. Section numbers below (§N) are the spec's.
- Use the default Go build cache (`~/.cache/go-build`, writable inside the
sandbox). Do not set `GOCACHE`, `GOMODCACHE` or `GOTMPDIR`.
- Scratch goes under `$TMPDIR`, which is on disk.
- - The one exception: Unix-socket tests (`internal/host`, `internal/edge`)
- need a short socket path. Run those with `TMPDIR=/tmp/g`, creating
- `/tmp/g` if it is absent. Never delete it or anything in it you did not
- create. This is the brief's explicit instruction, not an invention: a
- Unix socket path is capped at 108 bytes, and the on-disk `$TMPDIR` here
- (`/home/paulca/.cache/tmp/claude-1001/...`) leaves too little room for
- Go's test directories and the socket names under them.
+ - **Operator rule for this machine (socket tests).** The operator
+ instructs that ONLY the Unix-socket test packages run with `TMPDIR`
+ under `/tmp/g`: `internal/host`, `internal/activator`,
+ `internal/edge`, and any other package whose tests bind a Unix socket
+ (today also `internal/agentsock`, `internal/instancectl`,
+ `internal/instanceexec`, `internal/unixdial` and `internal/vet`). A
+ Unix socket path is capped at 108 bytes, and the on-disk `TMPDIR` here
+ (`/home/paulca/.cache/tmp/claude-1001/...`) is too deep for Go's test
+ directories plus the socket names under them. The directory is small
+ and is deleted after the run. `/tmp/g` is shared, so each run makes its
+ own directory under it and deletes only that; nothing else in `/tmp/g`
+ is touched. Everything else uses the on-disk `TMPDIR`. CI is
+ unaffected: it has no such path limit and sets nothing here. Every
+ socket-test command in this plan goes through this function:
+
+ ```bash
+ socktest() { # go test args...; TMPDIR is a fresh short dir, deleted after
+ mkdir -p /tmp/g || return 1
+ local d rc
+ d="$(mktemp -d /tmp/g/nr.XXXXXX)" || return 1
+ TMPDIR="$d" go test "$@"; rc=$?
+ rm -rf "$d"
+ return "$rc"
+ }
+ ```
- Console tests need an on-disk `TMPDIR` (the sandbox's `$TMPDIR` is one),
because an empty `/tmp/.git` breaks Go's VCS stamping.
- **CLI tests that shell out to the carlos binary** build their env through
@@ -251,6 +271,10 @@ plan and marked "plan".
| C17 | same | `this app's region %s is not one its instances may use. Allowed: %s. Pass a region to choose one.` |
| C18 | same | `region %s is not one this platform runs in. Choose from: %s.` |
| C19 | same | `region %s can't take new apps right now. Choose from: %s.` |
+| C16b (plan) | same | `this app's region %s can't take new instances right now (%s), and no other region this app may use can either. Try again later.` (C16 when no region would pass) |
+| C17b (plan) | same | `this app's region %s is not one its instances may use, and no region they may use can take new instances right now. Try again later.` (C17 when no allowed region would pass) |
+| C18b (plan) | same | `region %s is not one this platform runs in. Run the command without --region.` (C18 when no region would pass) |
+| C19b (plan) | same | `region %s can't take new apps right now. Run the command without --region.` (C19 when no region would pass) |
| C20 | same | `could not read this app's region. Try again.` |
| C26 | same | `this app's region %s is also one of this instance's replica placements. Pass a region for the instance, or drop %s from replicas.` |
| C27 | same | `could not read this app's instance policy, so there is no region suggestion. Try again.` |
@@ -539,7 +563,7 @@ func TestEdgesFileEligibilityFollowsTheReconcileConfig(t *testing.T) {
- [ ] **Step 6: Run them to verify they fail**
-Run: `TMPDIR=/tmp/g go test ./internal/host -run 'TestEdgesFile(RawWireBodyEligibilityFields|EligibilityFollowsTheReconcileConfig)' -count=1`
+Run: `socktest ./internal/host -run 'TestEdgesFile(RawWireBodyEligibilityFields|EligibilityFollowsTheReconcileConfig)' -count=1`
Expected: FAIL, unknown fields `ServesSharedPool` and `AcceptsInbound`, and
`edgesFileEligibility` undefined.
@@ -606,7 +630,7 @@ sed -i 's/"hibernation_configured":false,"generation":"` +/"hibernation_configur
test "$(grep -c '"serves_shared_pool":false,"accepts_inbound":false' internal/host/edgesfile_test.go)" = 4
```
-Run: `mkdir -p /tmp/g && TMPDIR=/tmp/g go test ./internal/host ./internal/provision -count=1`
+Run: `socktest ./internal/host -count=1 && go test ./internal/provision -count=1`
Expected: PASS. Without the golden update, those three tests fail on exactly
the two new keys (seen in the round-3 proof).
@@ -807,7 +831,7 @@ imports.
- [ ] **Step 6: Run it to verify it fails**
-Run: `mkdir -p /tmp/g && TMPDIR=/tmp/g go test ./internal/host -run TestEdgesFileSecretsKeyFingerprint -count=1`
+Run: `socktest ./internal/host -run TestEdgesFileSecretsKeyFingerprint -count=1`
Expected: FAIL, unknown field `SecretsKeyFP`.
- [ ] **Step 7: Implement the field, the helper and the loop wiring**
@@ -862,7 +886,7 @@ In `edgesFileLoop`'s ident literal, add:
Run:
```bash
-mkdir -p /tmp/g && TMPDIR=/tmp/g go test ./internal/host ./internal/appconfig -count=1
+socktest ./internal/host -count=1 && go test ./internal/appconfig -count=1
fail=0
for t in darwin/arm64 darwin/amd64 linux/arm64 windows/amd64 windows/arm64; do
CGO_ENABLED=0 GOOS=${t%/*} GOARCH=${t#*/} go build ./... || { echo "FAILED $t"; fail=1; }
@@ -2031,23 +2055,23 @@ Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
---
-### Task 7: Console API messages (C16 to C20, C26 to C29, C31, reasons; from the record)
+### Task 7: Console API messages (C16 to C20, C16b to C19b, C26 to C29, C31, reasons; from the record)
**Files:**
- Create: `internal/console/regionmsgs.go`
- Test: `internal/console/regionmsgs_test.go`
**Interfaces:**
-- Consumes: the record's C16 to C20, C26 to C29, C31, and the four `R-*`
- entries (Task 0).
+- Consumes: the record's C16 to C20, C16b to C19b, C26 to C29, C31, and
+ the four `R-*` entries (Task 0).
- Produces:
```go
func reasonText(reason string) string // absent | not-hosting | no-secrets-key | not-eligible
-func msgAppRegionUnavailable(code, reason string, can []string) string // C16
-func msgAppRegionNotAllowed(code string, allowed []string) string // C17
-func msgRegionUnknown(code string, choices []string) string // C18
-func msgRegionNotArmed(code string, choices []string) string // C19
+func msgAppRegionUnavailable(code, reason string, can []string) string // C16; C16b when can is empty
+func msgAppRegionNotAllowed(code string, allowed []string) string // C17; C17b when empty
+func msgRegionUnknown(code string, choices []string) string // C18; C18b when empty
+func msgRegionNotArmed(code string, choices []string) string // C19; C19b when empty
const msgAppRegionUnreadable // C20
func msgReplicaOverlap(code string) string // C26
const msgPolicyUnreadable // C27
@@ -2056,6 +2080,10 @@ func msgPlacementDiscrepancy(host, app, code string) string // C29
func msgNoSecretsKey(code string) string // C31
```
+Each list a refusal carries names only what the door would accept (codex
+plan-R4 2), so it can be empty. An empty list never renders as a list: the
+`b` variant drops the list sentence.
+
- [ ] **Step 1: Write the failing test**
```go
@@ -2079,6 +2107,11 @@ func TestRegionMessagesRender(t *testing.T) {
msgAppRegionUnconfirmed("uk"),
msgPlacementDiscrepancy("a.go.tito.io", "blog", "uk"),
msgNoSecretsKey("uk"),
+ // codex plan-R4 2: the empty-list variants, C16b to C19b.
+ msgAppRegionUnavailable("uk", "absent", nil),
+ msgAppRegionNotAllowed("uk", nil),
+ msgRegionUnknown("zz", nil),
+ msgRegionNotArmed("uk", nil),
}
for _, s := range all {
if s == "" || strings.Contains(s, "—") || strings.Contains(s, "%!") {
@@ -2088,6 +2121,11 @@ func TestRegionMessagesRender(t *testing.T) {
if !strings.Contains(all[0], reasonText("absent")) || !strings.Contains(all[0], "ie, au") {
t.Errorf("C16 = %q, want the readable reason and the list", all[0])
}
+ for _, s := range all[len(all)-4:] {
+ if strings.Contains(s, ": .") || strings.Contains(s, ": ,") {
+ t.Errorf("an empty list rendered as a list: %q", s)
+ }
+ }
seen := map[string]bool{}
for _, r := range []string{"absent", "not-hosting", "no-secrets-key", "not-eligible"} {
txt := reasonText(r)
@@ -2134,25 +2172,39 @@ func reasonText(reason string) string {
return reason
}
-// C16
+// C16, or C16b when no region would pass (codex plan-R4 2: a list names
+// only what the door takes, so it can be empty).
func msgAppRegionUnavailable(code, reason string, can []string) string {
+ if len(can) == 0 {
+ return fmt.Sprintf("this app's region %s can't take new instances right now (%s), and no other region this app may use can either. Try again later.",
+ code, reasonText(reason))
+ }
return fmt.Sprintf("this app's region %s can't take new instances right now (%s). Pass a region to place this instance elsewhere. Regions that can: %s.",
code, reasonText(reason), strings.Join(can, ", "))
}
-// C17
+// C17, or C17b when no allowed region would pass.
func msgAppRegionNotAllowed(code string, allowed []string) string {
+ if len(allowed) == 0 {
+ return fmt.Sprintf("this app's region %s is not one its instances may use, and no region they may use can take new instances right now. Try again later.", code)
+ }
return fmt.Sprintf("this app's region %s is not one its instances may use. Allowed: %s. Pass a region to choose one.",
code, strings.Join(allowed, ", "))
}
-// C18
+// C18, or C18b when no region would pass.
func msgRegionUnknown(code string, choices []string) string {
+ if len(choices) == 0 {
+ return fmt.Sprintf("region %s is not one this platform runs in. Run the command without --region.", code)
+ }
return fmt.Sprintf("region %s is not one this platform runs in. Choose from: %s.", code, strings.Join(choices, ", "))
}
-// C19
+// C19, or C19b when no region would pass.
func msgRegionNotArmed(code string, choices []string) string {
+ if len(choices) == 0 {
+ return fmt.Sprintf("region %s can't take new apps right now. Run the command without --region.", code)
+ }
return fmt.Sprintf("region %s can't take new apps right now. Choose from: %s.", code, strings.Join(choices, ", "))
}
@@ -3796,6 +3848,10 @@ type regionReq struct {
ip net.IP // request-local, person requests only
}
func (s *Server) validateExplicitRegion(ctx context.Context, raw string) (code string, ref *doorRefusal)
+type explicitGate struct{ caps map[string]placementCapability; published bool; cands []regionCandidate }
+func (s *Server) readExplicitGate(ctx context.Context) explicitGate
+func (g explicitGate) refusal(code string) string // "", unknown, not-armed, no-key
+func (s *Server) explicitChoices(g explicitGate) []string
func (s *Server) resolveNewAppRegion(ctx context.Context, rq regionReq, adopting bool) (region, source string)
func (s *Server) placeOf(code string, cands []regionCandidate) string
func (s *Server) personIP(r *http.Request) net.IP
@@ -3805,6 +3861,12 @@ func (s *Server) claimApp(ctx context.Context, acct *Account, name, addr, placem
`handleAPICreateApp`'s response gains `region`, `region_name`,
`region_source` and `regions_available`.
+C18 and C19 list exactly the codes `validateExplicitRegion` would accept
+now, through one predicate, `explicitGate.refusal`: the home's name, plus
+each published code that is shape-valid, armed and hosting, and not proved
+keyless (R9). They never list a code the same door then refuses (codex
+plan-R4 2), and the test submits every listed code and expects it to pass.
+
- [ ] **Step 1: Write the failing tests**
```go
@@ -3815,6 +3877,7 @@ import (
"bytes"
"context"
"encoding/json"
+ "fmt"
"net/http"
"strings"
"testing"
@@ -3893,10 +3956,15 @@ func TestAPICreateAppLocatesOnlyAPerson(t *testing.T) {
func TestAPICreateAppRefusesBadExplicitRegions(t *testing.T) {
fx, token := regionFixture(t)
- setEdges(t, fx, map[string]string{"nz-box": nzNoHosting})
+ // nz cannot host; au's current-writer box lacks the key (R9).
+ auNoKey := edgeJSON("au-box", "9.9.9.8", "ap-southeast-2", "au", edgeOpts{hib: bp(true), shared: bp(true), inbound: bp(true)})
+ setEdges(t, fx, map[string]string{"nz-box": nzNoHosting, "au-box": auNoKey})
+ // codex plan-R4 2: each list names exactly what this door would take.
+ choices := []string{"ie", "uk"}
cases := []struct{ name, region, want string }{
- {"xa", "Bad/Code", msgRegionUnknown("Bad/Code", []string{"ie", "nz", "uk"})},
- {"xb", "nz", msgRegionNotArmed("nz", []string{"ie", "uk"})},
+ {"xa", "Bad/Code", msgRegionUnknown("Bad/Code", choices)},
+ {"xb", "nz", msgRegionNotArmed("nz", choices)},
+ {"xc", "au", msgNoSecretsKey("au")},
}
for _, c := range cases {
status, res := postJSON(t, newAppURL(fx), map[string]string{"name": c.name, "region": c.region}, token)
@@ -3907,9 +3975,16 @@ func TestAPICreateAppRefusesBadExplicitRegions(t *testing.T) {
t.Errorf("a refused region still claimed %s", c.name)
}
}
+ // Every advertised choice is accepted by the same door, same fixture.
+ for i, code := range choices {
+ name := fmt.Sprintf("alt%d", i)
+ if status, res := postJSON(t, newAppURL(fx), map[string]string{"name": name, "region": code}, token); status != http.StatusOK {
+ t.Errorf("advertised %q refused: %d %v", code, status, res)
+ }
+ }
// R9: a region whose current-writer boxes lack the key.
setEdges(t, fx, map[string]string{"uk-box": ukNoKey})
- if status, res := postJSON(t, newAppURL(fx), map[string]string{"name": "xc", "region": "uk"}, token); status != http.StatusBadRequest || errOf(res) != msgNoSecretsKey("uk") {
+ if status, res := postJSON(t, newAppURL(fx), map[string]string{"name": "xd", "region": "uk"}, token); status != http.StatusBadRequest || errOf(res) != msgNoSecretsKey("uk") {
t.Fatalf("keyless uk = %d %v, want C31", status, res)
}
}
@@ -4030,36 +4105,68 @@ type regionReq struct {
// validateExplicitRegion checks a person's explicit region as the instance
// door checks one (spec §8.1): ValidRegion; armed and hosting unless the
// gate is dormant; not provably without the secrets key (R9). The home's
-// name normalizes to "".
+// name normalizes to "". A refusal lists exactly the codes this same check
+// would accept now (codex plan-R4 2).
func (s *Server) validateExplicitRegion(ctx context.Context, raw string) (string, *doorRefusal) {
code := s.homeRegionIn(strings.TrimSpace(raw))
if code == "" {
return "", nil
}
- caps, published := placements(ctx, s.cfg.Releases)
- if !provision.ValidRegion(code) {
- return "", &doorRefusal{http.StatusBadRequest, msgRegionUnknown(code, s.namedCodes(caps))}
+ gate := s.readExplicitGate(ctx)
+ switch gate.refusal(code) {
+ case "":
+ return code, nil
+ case "unknown":
+ return "", &doorRefusal{http.StatusBadRequest, msgRegionUnknown(code, s.explicitChoices(gate))}
+ case "not-armed":
+ return "", &doorRefusal{http.StatusBadRequest, msgRegionNotArmed(code, s.explicitChoices(gate))}
+ }
+ return "", &doorRefusal{http.StatusBadRequest, msgNoSecretsKey(code)}
+}
+
+// explicitGate is one read of what an explicit app region must pass.
+type explicitGate struct {
+ caps map[string]placementCapability
+ published bool
+ cands []regionCandidate // nil when the edges read failed: R9 cannot refuse
+}
+
+func (s *Server) readExplicitGate(ctx context.Context) explicitGate {
+ g := explicitGate{}
+ g.caps, g.published = placements(ctx, s.cfg.Releases)
+ if snap, err := readEdgesSnapshot(ctx, s.cfg.Releases); err == nil {
+ g.cands = s.regionCands(snap)
}
- if published && !(caps[code].Reachable && caps[code].Hosting) {
- return "", &doorRefusal{http.StatusBadRequest, msgRegionNotArmed(code, s.namedCodes(hostingCaps(caps)))}
+ return g
+}
+
+// refusal is "" when an explicit, record-vocabulary code passes, else
+// which bar it fails: "unknown", "not-armed" or "no-key".
+func (g explicitGate) refusal(code string) string {
+ switch {
+ case code == "":
+ return ""
+ case !provision.ValidRegion(code):
+ return "unknown"
+ case g.published && !(g.caps[code].Reachable && g.caps[code].Hosting):
+ return "not-armed"
}
- if files, err := readEdgesSnapshot(ctx, s.cfg.Releases); err == nil {
- if c, ok := findCandidate(s.regionCands(files), code); ok && c.NoKeyProven {
- return "", &doorRefusal{http.StatusBadRequest, msgNoSecretsKey(code)}
- }
+ if c, ok := findCandidate(g.cands, code); ok && c.NoKeyProven {
+ return "no-key"
}
- return code, nil
+ return ""
}
-// namedCodes lists the home's name plus every valid code in caps, sorted.
-func (s *Server) namedCodes(caps map[string]placementCapability) []string {
+// explicitChoices is the home's name plus every published code that
+// refusal passes, sorted: never a code this door would refuse.
+func (s *Server) explicitChoices(g explicitGate) []string {
set := map[string]bool{}
if s.cfg.HomeRegion != "" {
set[s.cfg.HomeRegion] = true
}
- for code := range caps {
- if provision.ValidRegion(code) {
- set[code] = true
+ for code := range g.caps {
+ if c := s.homeRegionIn(code); c != "" && g.refusal(c) == "" {
+ set[c] = true
}
}
out := make([]string, 0, len(set))
@@ -4070,16 +4177,6 @@ func (s *Server) namedCodes(caps map[string]placementCapability) []string {
return out
}
-func hostingCaps(caps map[string]placementCapability) map[string]placementCapability {
- out := map[string]placementCapability{}
- for code, c := range caps {
- if c.Reachable && c.Hosting {
- out[code] = c
- }
- }
- return out
-}
-
// resolveNewAppRegion is spec §5.5 and §5.6 for a NEW row.
func (s *Server) resolveNewAppRegion(ctx context.Context, rq regionReq, adopting bool) (region, source string) {
if !s.appRegionsOn() {
@@ -4204,6 +4301,11 @@ Add to the response map:
Run: `go test ./internal/console -count=1`
Expected: PASS, including every existing claim test.
+Then a mutation check (codex plan-R4 2): in `explicitChoices`, also accept
+codes whose refusal is `no-key`. Run
+`go test ./internal/console -run TestAPICreateAppRefusesBadExplicitRegions -count=1`.
+It must FAIL (`au` is listed). Revert, and re-run: PASS.
+
- [ ] **Step 7: Commit**
```bash
@@ -4256,17 +4358,46 @@ import (
"html"
"net/http"
"net/url"
+ "regexp"
"strings"
"testing"
)
func has(body, plain string) bool { return strings.Contains(body, html.EscapeString(plain)) }
+// newAppFormGolden is the base tree's own rendering of the create-app form
+// (the branch base, switch off), with the session's CSRF value blanked.
+const newAppFormGolden = `<form class="signin" method="post" action="/a/bab/apps/new">
+ <input type="hidden" name="csrf" value="CSRF">
+ <label class="visually-hidden" for="app-name">App name</label>
+ <input id="app-name" type="text" name="name" placeholder="my-app" autofocus
+ required pattern="[A-Za-z][A-Za-z0-9-]{0,31}" maxlength="32">
+ <button type="submit">Create app</button>
+</form>`
+
+// newAppForm is the rendered <form>…</form>, CSRF value blanked.
+func newAppForm(t *testing.T, body string) string {
+ t.Helper()
+ i := strings.Index(body, `<form class="signin"`)
+ if i < 0 {
+ t.Fatalf("no create-app form in %s", body)
+ }
+ j := strings.Index(body[i:], "</form>") + i + len("</form>")
+ return regexp.MustCompile(`name="csrf" value="[^"]*"`).ReplaceAllString(body[i:j], `name="csrf" value="CSRF"`)
+}
+
+// codex plan-R4 3, spec §10 and §16: whenever there is no picker, the form
+// is today's form byte for byte: with the switch off, and with the switch
+// on but only one eligible region.
func TestNewAppPageWithoutPickerIsUnchanged(t *testing.T) {
- fx := newConsoleFixture(t) // switch off
- _, _, body := get(t, signInPaul(t, fx), fx.u("/apps/new"))
- if strings.Contains(body, `name="region"`) {
- t.Fatal("switch off rendered a region picker")
+ off := newConsoleFixture(t)
+ one, _ := regionFixture(t)
+ setEdges(t, one, map[string]string{"uk-box": ukNoKey}) // the home alone is eligible
+ for name, fx := range map[string]*consoleFixture{"switch off": off, "one eligible region": one} {
+ _, _, body := get(t, signInPaul(t, fx), fx.u("/apps/new"))
+ if got := newAppForm(t, body); got != newAppFormGolden {
+ t.Errorf("%s: form =\n%q\nwant\n%q", name, got, newAppFormGolden)
+ }
}
}
@@ -4497,12 +4628,18 @@ In `claimOK`, replace the audit line:
s.audit(acct, name, addr, "create", detail)
```
-- [ ] **Step 5: Add the picker to `app_new.html`**
+- [ ] **Step 5: Add the picker to `app_new.html`, leaving the no-picker form byte-identical**
-Inside the `<form>`, after the name `<input>` and before the button:
+Replace the last line of the name `<input>` and the button line (two lines,
+`app_new.html:13-14`) with the block below. The `{{with}}` opens on the
+input's own line and `{{end}}` closes on the script's, so with no picker the
+template emits exactly today's bytes: no blank line, no extra spaces (codex
+plan-R4 3; spec §10, §16). `TestNewAppPageWithoutPickerIsUnchanged` compares
+the rendered form with the base tree's own rendering, with the switch off
+and with the switch on but one eligible region.
```html
- {{with .RegionPicker}}
+ required pattern="[A-Za-z][A-Za-z0-9-]{0,31}" maxlength="32">{{with .RegionPicker}}
<label for="app-region">{{$.RegionCopy.PickerLabel}}</label>
<select id="app-region" name="region">
<option value="@auto" selected>{{.Auto}}</option>
@@ -4530,8 +4667,8 @@ Inside the `<form>`, after the name `<input>` and before the button:
})
.catch(function () {});
})();
- </script>
- {{end}}
+ </script>{{end}}
+ <button type="submit">Create app</button>
```
`html/template` renders the `{{printf …}}` in script context as a JS string
@@ -4542,6 +4679,11 @@ literal, so the approved C3 shape is used whatever its wording.
Run: `go test ./internal/console -count=1`
Expected: PASS.
+Then a mutation check: put the block on its own lines instead
+(` {{with .RegionPicker}}` after the input, ` {{end}}` before the
+button). `TestNewAppPageWithoutPickerIsUnchanged` must FAIL in both cases
+(an extra `" \n"`). Restore, and re-run: PASS.
+
- [ ] **Step 7: Commit**
```bash
@@ -4561,6 +4703,7 @@ Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
- `:763-799`, where the fill goes;
- the armed gate, at `:827-852`;
- `:1066`, where the response is written.
+- Create: `internal/console/regionchoices.go` (`instanceChoices`)
- Test: `internal/console/regionfill_test.go`
**Interfaces:**
@@ -4568,7 +4711,16 @@ Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
`findCandidate`, `NoKeyProven`).
- Produces: `apiRecordView.RegionFrom string`
(`json:"region_from,omitempty"`) and `apiRecordView.RegionName string`
- (`json:"region_name,omitempty"`).
+ (`json:"region_name,omitempty"`), and
+ `func (s *Server) instanceChoices(ctx context.Context, allowed []string, cands []regionCandidate, except string) []string`.
+
+C16 and C17 list what an EXPLICIT request for the same socket-backed
+instance would pass now, not what automatic eligibility would pick (codex
+plan-R4 2): the manifest's allow-list as the door reads it (every code
+normalized through `homeRegionIn` first, so a home NAME in the allow-list
+counts as the home only if `""` is allowed), the armed gate's reachable and
+hosting bars, and R9's refusal. The refused region itself is left out. When
+nothing passes, the message is C16b or C17b.
- [ ] **Step 1: Write the failing tests**
@@ -4582,6 +4734,7 @@ package console
import (
"encoding/json"
"errors"
+ "fmt"
"net/http"
"regexp"
"strings"
@@ -4716,9 +4869,10 @@ func TestAppDerivedRefusals(t *testing.T) {
m := titoManifest()
m.Pool, m.Regions = "", []string{"au"}
enableInstances(t, fx, "titogo", m)
+ // au publishes no box, so nothing the allow-list names can pass: C17b.
if status, _, out := create(t, u, token, `{"host":"y.go.tito.io"}`); status != http.StatusBadRequest ||
- !strings.Contains(out, msgAppRegionNotAllowed("uk", []string{"au"})) {
- t.Fatalf("allow-list = %d %s, want C17", status, out)
+ !strings.Contains(out, msgAppRegionNotAllowed("uk", nil)) {
+ t.Fatalf("allow-list = %d %s, want C17b", status, out)
}
m.Regions = nil
enableInstances(t, fx, "titogo", m)
@@ -4802,6 +4956,40 @@ func TestPersistedRecordsMatchTheirGoldens(t *testing.T) {
}
}
}
+
+// codex plan-R4 2: C16's and C17's lists name exactly the regions an
+// explicit create of this same instance would pass: the allow-list, the
+// armed gate and R9 (not automatic eligibility), never the region refused.
+// Each advertised region is then submitted, and must be accepted.
+func TestAppRegionRefusalsAdvertiseOnlyWhatPasses(t *testing.T) {
+ auEligible := edgeJSON("au-box", "9.9.9.9", "ap-southeast-2", "au", eligibleBox)
+ for _, c := range []struct {
+ name string
+ ukBox string
+ regions []string
+ want func(choices []string) string
+ choices []string
+ }{
+ // uk is the app's region, keyless; the home is outside the allow-list.
+ {"C16", ukNoKey, []string{"uk", "au", "nz"}, func(ch []string) string { return msgAppRegionUnavailable("uk", "no-secrets-key", ch) }, []string{"au"}},
+ // uk is eligible but outside the allow-list; "ie" there is the
+ // home's NAME, which the door reads as "" and so refuses.
+ {"C17", ukEligible, []string{"au", "nz", "ie"}, func(ch []string) string { return msgAppRegionNotAllowed("uk", ch) }, []string{"au"}},
+ } {
+ fx, token, u := fillFixture(t, "uk")
+ setEdges(t, fx, map[string]string{"uk-box": c.ukBox, "au-box": auEligible, "nz-box": nzNoHosting})
+ m := titoManifest()
+ m.Pool, m.Regions = "", c.regions
+ enableInstances(t, fx, "titogo", m)
+ status, _, out := create(t, u, token, `{"host":"y.go.tito.io"}`)
+ if want := c.want(c.choices); status != http.StatusBadRequest || !strings.Contains(out, want) {
+ t.Errorf("%s = %d %s, want %q", c.name, status, out, want)
+ }
+ for i, code := range c.choices {
+ mustCreate(t, u, token, fmt.Sprintf(`{"host":"alt%d.go.tito.io","region":%q}`, i, code))
+ }
+ }
+}
```
The `legacy` golden is the base tree's own output: the same request (an
@@ -4811,7 +4999,7 @@ unmodified door at the branch base, its stored bytes read back with
- [ ] **Step 2: Run them to verify they fail**
-Run: `go test ./internal/console -run 'TestFill|TestAppDerived|TestExplicitCreateIntoAKeylessRegion|TestReplicaCreateNamesItsPlace|TestPersistedRecords' -count=1`
+Run: `go test ./internal/console -run 'TestFill|TestAppDerived|TestExplicitCreateIntoAKeylessRegion|TestReplicaCreateNamesItsPlace|TestPersistedRecords|TestAppRegionRefusals' -count=1`
Expected: FAIL.
- [ ] **Step 3: Implement the fill, replacing `apiinstances.go:772`**
@@ -4856,18 +5044,14 @@ Expected: FAIL.
if c, ok := findCandidate(cands, region); ok {
reason = c.unavailableReason()
}
+ // Each list names only what an explicit request for this same
+ // instance would pass (codex plan-R4 2): instanceChoices.
if reason != "" {
- var can []string
- for _, c := range cands {
- if c.Eligible {
- can = append(can, s.homeRegionOut(c.Code))
- }
- }
- jsonError(w, http.StatusBadRequest, msgAppRegionUnavailable(s.homeRegionOut(region), reason, can))
+ jsonError(w, http.StatusBadRequest, msgAppRegionUnavailable(s.homeRegionOut(region), reason, s.instanceChoices(ctx, m.Regions, cands, region)))
return
}
if !instanceRegionAllowed(m.Regions, region) {
- jsonError(w, http.StatusBadRequest, msgAppRegionNotAllowed(s.homeRegionOut(region), m.Regions))
+ jsonError(w, http.StatusBadRequest, msgAppRegionNotAllowed(s.homeRegionOut(region), s.instanceChoices(ctx, m.Regions, cands, region)))
return
}
for _, rep := range req.Replicas {
@@ -4879,6 +5063,53 @@ Expected: FAIL.
}
```
+Create `internal/console/regionchoices.go`:
+
+```go
+package console
+
+import (
+ "context"
+ "sort"
+
+ "github.com/carlosframework/platform/internal/provision"
+)
+
+// instanceChoices lists, under their names, the regions an EXPLICIT
+// request for this same socket-backed instance would pass right now (codex
+// plan-R4 2): the manifest's allow-list as the door reads it (each code
+// normalized through homeRegionIn first), the armed gate's reachable and
+// hosting bars, and R9's refusal. These are the explicit door's rules, not
+// automatic eligibility. except, the region just refused, is left out.
+func (s *Server) instanceChoices(ctx context.Context, allowed []string, cands []regionCandidate, except string) []string {
+ caps, published := placements(ctx, s.cfg.Releases)
+ codes := map[string]bool{"": true}
+ for c := range caps {
+ codes[s.homeRegionIn(c)] = true
+ }
+ for _, c := range allowed {
+ codes[s.homeRegionIn(c)] = true
+ }
+ var out []string
+ for code := range codes {
+ if code == except || !instanceRegionAllowed(allowed, code) {
+ continue
+ }
+ if code != "" {
+ if !provision.ValidRegion(code) || (published && !(caps[code].Reachable && caps[code].Hosting)) {
+ continue
+ }
+ if c, ok := findCandidate(cands, code); ok && c.NoKeyProven {
+ continue
+ }
+ }
+ out = append(out, s.homeRegionOut(code))
+ }
+ sort.Strings(out)
+ return out
+}
+```
+
- [ ] **Step 4: Add the R9 explicit refusal to the armed gate**
Inside `if placed == "" && region != "" {` (`:827`), after the closing brace
@@ -4934,6 +5165,12 @@ Then a mutation check on the R9 gate's scope. Change
run `go test ./internal/console -run TestExplicitCreateIntoAKeylessRegion -count=1`.
It must FAIL on the static or addr-backed create. Revert, and re-run: PASS.
+Then the list mutation (codex plan-R4 2): in `instanceChoices`, drop the
+`!instanceRegionAllowed(allowed, code)` condition. Run
+`go test ./internal/console -run TestAppRegionRefusalsAdvertiseOnlyWhatPasses -count=1`.
+It must FAIL on both C16 and C17 (the home `ie` is listed). Revert, and
+re-run: PASS.
+
Then the steering mutation (codex plan-R3 5): right after the
`rec := provision.Record{...}` literal, add
`if regionFrom == "app" { rec.Steering = "latency" }`, and run
@@ -4943,7 +5180,7 @@ It must FAIL on the app-defaulted record. Revert, and re-run: PASS.
- [ ] **Step 7: Commit**
```bash
-git add internal/console/apiinstances.go internal/console/regionfill_test.go
+git add internal/console/apiinstances.go internal/console/regionchoices.go internal/console/regionfill_test.go
git commit -m "console: instance door fills the app region, proves eligibility, refuses keyless regions (nearest-region §7, R9)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>"
@@ -5004,6 +5241,11 @@ A pooled default's `available` is the allow-list's verdict on the home,
because a no-region pooled create lands there (codex plan-R3 2). The
`pooled` reason stays, so the Instances tab still shows no line for it.
+R9a holds in the pooled and fleet branches too (codex plan-R4 1, spec rev
+6.2): with the stored region unread, `effective` stays empty and
+`available` omitted, and `reason` (`pooled` or `fleet`) is the only
+placement fact stated. Task 22's canary check therefore needs BOTH flags.
+
- [ ] **Step 1: Write the failing tests**
```go
@@ -5179,6 +5421,39 @@ func TestAppDefaultInstanceDomain(t *testing.T) {
}
}
+// codex plan-R4 1, spec R9a: an unread stored region leaves region, name,
+// source and effective empty and available omitted, even when a fleet or a
+// pooled manifest would otherwise decide them. The placement the console
+// did read stays visible in reason.
+func TestAppDefaultUnreadRegionHidesEffective(t *testing.T) {
+ acct := &Account{ID: OpsAccountID, Sqid: "bab"}
+ for _, c := range []struct {
+ name string
+ setup func(t *testing.T, fx *consoleFixture)
+ reason string
+ }{
+ {"pooled", func(t *testing.T, fx *consoleFixture) {
+ m := titoManifest()
+ m.Pool, m.Regions = "tito", nil
+ enableInstances(t, fx, "titogo", m)
+ }, "pooled"},
+ {"fleet", func(t *testing.T, fx *consoleFixture) {
+ if err := fx.st.SetAppPlacement(OpsAccountID, "titogo", "fleet/acme"); err != nil {
+ t.Fatal(err)
+ }
+ }, "fleet"},
+ } {
+ fx, _, _ := fillFixture(t, "uk")
+ c.setup(t, fx)
+ fx.srv.appRegionOf = func(int64, string) (string, string, error) { return "", "", errors.New("db gone") }
+ d := fx.srv.appDefault(t.Context(), acct, "titogo")
+ if d.RegionKnown || !d.PlacementKnown || d.Region != "" || d.Name != "" || d.Source != "" ||
+ d.Effective != "" || d.Available != nil || d.Reason != c.reason {
+ t.Errorf("%s with an unread region = %+v, want only placement_known and reason %q", c.name, d, c.reason)
+ }
+ }
+}
+
func TestRegionGuessEndpoint(t *testing.T) {
fx, token, _ := fillFixture(t, "")
status, _, out := rawReq(t, http.MethodPost, guessURL(fx), token, `{"tz":"Europe/London"}`)
@@ -5261,7 +5536,8 @@ func TestRegionGuessHintsNeverLeak(t *testing.T) {
- [ ] **Step 2: Run them to verify they fail**
Run: `go test ./internal/console -run 'TestRegionsKeeps|TestAppDefault|TestRegionGuess|TestPooledAvailability' -count=1`
-Expected: FAIL.
+Expected: FAIL. `TestAppDefaultUnreadRegionHidesEffective` is the R9a case
+for pooled and fleet apps.
- [ ] **Step 3: Implement `regiondefault.go`**
@@ -5322,12 +5598,22 @@ func (s *Server) appDefault(ctx context.Context, acct *Account, app string) appD
v.Reason = "policy-unreadable"
return v
case pol.Placed != "":
- v.Effective, v.Reason = pol.Placed, "fleet"
+ // R9a: with the stored region unread, effective stays empty even
+ // though the fleet is known; reason still says fleet (codex
+ // plan-R4 1).
+ v.Reason = "fleet"
+ if rerr == nil {
+ v.Effective = pol.Placed
+ }
return v
case pol.pooled():
// A no-region pooled create lands on the home, so it is available
- // only when the home passes the allow-list (codex plan-R3 2).
- v.Effective, v.Reason, v.Available = s.homeRegionOut(""), "pooled", boolp(pol.allows(""))
+ // only when the home passes the allow-list (codex plan-R3 2). R9a
+ // again: nothing about effective is stated when the region is unread.
+ v.Reason = "pooled"
+ if rerr == nil {
+ v.Effective, v.Available = s.homeRegionOut(""), boolp(pol.allows(""))
+ }
return v
case rerr != nil:
// The stored region is unknown, so where a create lands is too.
@@ -6769,6 +7055,12 @@ or one whose read fails, is invisible to it. The single GET answers 404 only
when the record does not exist (`GetRecord`'s `os.ErrNotExist`); any other
failure is a 502, which refuses with C30c.
+`--region` needs both knowledge flags (spec R9a, rev 6.2): the fleet check
+reads `effective`, which is empty when the stored region was not read. A
+false `region_known` refuses with C30b like a false `placement_known`
+(codex plan-R4 1), and the e2e has a fleet-placed case with the region
+unread that must refuse with zero writes.
+
After the PUT, the host built from the PUT's domain must equal the host the
check read. If it does not (an operator re-homed the manifest between the
two), the command stops with C30c before any record write.
@@ -6813,6 +7105,8 @@ func TestCanaryRegionCheck(t *testing.T) {
older := apiRegionsResult{Regions: names, Default: "ie"} // no app_default
unread := apiRegionsResult{Regions: names, Default: "ie", AppDefault: &apiAppDefault{Region: "uk", Effective: "uk", RegionKnown: true, Reason: "policy-unreadable"}}
noDomain := apiRegionsResult{Regions: names, Default: "ie", AppDefault: &apiAppDefault{Region: "uk", Effective: "uk", RegionKnown: true, PlacementKnown: true}}
+ regionUnknownFleet := apiRegionsResult{Regions: names, Default: "ie", AppDefault: &apiAppDefault{PlacementKnown: true, Reason: "fleet", InstanceDomain: "go.tito.io"}}
+ regionUnknown := apiRegionsResult{Regions: names, Default: "ie", AppDefault: &apiAppDefault{PlacementKnown: true, InstanceDomain: "go.tito.io"}}
boom := errors.New("timeout")
const host = "c.blog.go.tito.io"
existingUK := apiInstanceRecord{Host: host, Region: "uk"}
@@ -6844,6 +7138,10 @@ func TestCanaryRegionCheck(t *testing.T) {
// from a list; a failed read or an unknown domain refuses.
{"record read failed", plain, nil, []apiInstanceRecord{existingUK}, boom, "uk", canaryRegionUnconfirmed("c")},
{"no instance domain", noDomain, nil, nil, nil, "uk", canaryRegionUnconfirmed("c")},
+ // codex plan-R4 1, R9a: with the stored region unread, effective is
+ // empty, so a fleet cannot be seen; the flag is refused either way.
+ {"region unknown, fleet", regionUnknownFleet, nil, nil, nil, "uk", canaryFleetUnknown("blog")},
+ {"region unknown", regionUnknown, nil, nil, nil, "uk", canaryFleetUnknown("blog")},
}
for _, c := range cases {
get, asked := records(c.readErr, c.recs...)
@@ -6930,7 +7228,8 @@ In `canary.go`:
// (codex R4-2, plan-R2 4, plan-R3 1):
// - the flag needs a console that can say whether a fleet governs; a
// failed read, an older console with no app_default, or one that
-// could not read the placement, refuses it on every run (C30b),
+// could not read the placement or the stored region (either flag
+// false, R9a), refuses it on every run (C30b),
// because the create door would silently replace it with the fleet;
// - a fleet-placed app refuses the flag every time (C30);
// - the canary's OWN record is then read by host, through get (one
@@ -6945,7 +7244,9 @@ func canaryRegionCheck(res apiRegionsResult, readErr error, app, name, asked str
if asked == "" {
return "", nil
}
- if readErr != nil || res.AppDefault == nil || !res.AppDefault.PlacementKnown {
+ // Both flags: effective is only stated when the stored region was read
+ // too (R9a), and the fleet check below reads effective (codex plan-R4 1).
+ if readErr != nil || res.AppDefault == nil || !res.AppDefault.PlacementKnown || !res.AppDefault.RegionKnown {
return "", errors.New(canaryFleetUnknown(app))
}
if strings.HasPrefix(res.AppDefault.Effective, "fleet/") {
@@ -7084,6 +7385,9 @@ func TestCanaryRegionRefusesBeforeAnyWrite(t *testing.T) {
// (a list skips it), the canary's own record still decides.
{"existing canary past the list cap", "", "ie", false, true, 520, false, canaryRegionMismatch(existing, "uk")},
{"existing canary unreadable", "", "ie", false, true, 0, true, canaryRegionUnconfirmed("probe")},
+ // codex plan-R4 1: a fleet-placed app whose stored region the console
+ // could not read; R9a leaves effective empty, and the flag is refused.
+ {"fleet, region unknown", "region-unknown", "uk", true, false, 0, false, canaryFleetUnknown("titogo")},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
@@ -7405,7 +7709,7 @@ func TestServiceGateAgainstARealBackhaul(t *testing.T) {
}
```
-Run: `mkdir -p /tmp/g && TMPDIR=/tmp/g go test ./internal/edge -run TestServiceGateAgainstARealBackhaul -count=1`
+Run: `socktest ./internal/edge -run TestServiceGateAgainstARealBackhaul -count=1`
Expected: PASS. If the first gate fails because the backhaul does not carry
`X-Carlos-Version` through, the gate is right and the probe instance must set
that header. Read `internal/edge`'s response copy path before changing
@@ -7646,13 +7950,13 @@ for t in darwin/arm64 darwin/amd64 linux/arm64 windows/amd64 windows/arm64; do
done
[ "$fail" = 0 ] || exit 1
(cd launchctx && go vet ./... && go test ./... -count=1)
-# Unix-socket packages need a short path; /tmp/g is the one place this plan
-# uses /tmp, and only for that (it is RAM-backed tmpfs, not disk).
-mkdir -p /tmp/g
-TMPDIR=/tmp/g go test ./internal/host/... ./internal/edge/... -count=1
-# Everything else on the on-disk TMPDIR the environment provides (inside
-# the sandbox, $TMPDIR is on disk): console tests need it.
-go test $(go list ./... | grep -v -e /internal/host -e /internal/edge) -count=1 -timeout 30m
+# The operator rule (Global Constraints): the Unix-socket test packages run
+# through socktest, in a fresh short directory under /tmp/g that is deleted
+# after the run; everything else uses the on-disk TMPDIR, which the console
+# tests need. socktest is the function defined there.
+sock='/internal/(host|activator|edge|agentsock|instancectl|instanceexec|unixdial|vet)(/|$)'
+socktest $(go list ./... | grep -E "$sock") -count=1
+go test $(go list ./... | grep -vE "$sock") -count=1 -timeout 30m
```
Expected: the script exits 0, with no `FAILED` line, and
@@ -7751,7 +8055,7 @@ to the follow-on spec.
## Self-review
-1. **Spec coverage (rev 6.1).**
+1. **Spec coverage (rev 6.2).**
| Spec | Covered in |
| --- | --- |
@@ -7765,7 +8069,7 @@ to the follow-on spec.
| §6.5 | Task 5's log test, Task 12's log tests, Task 15's redirect test |
| §7, including the R9 explicit refusal | Task 14 |
| §8 | Tasks 12, 13, 14, 20, 22 |
- | §9, including R9a's knowledge flags | Tasks 12, 14, 15, 13 |
+ | §9, including R9a's knowledge flags and rev 6.2's `instance_domain` | Tasks 12, 14, 15, 13, 22 |
| §9.6 | Tasks 21, 22, with the older-console e2e cases |
| §10 | Tasks 13, 16 |
| §11 | Tasks 19 to 22 |
@@ -7791,7 +8095,8 @@ to the follow-on spec.
- These are defined once and used consistently: `regionCandidate`
(`KeyOK`, `NoKeyProven`), `regionReq`, `appDefaultView`/`apiAppDefault`,
`apiRegionsResult.nameOf`, `canaryRegionCheck(res, readErr, app, name, asked, get)`,
- `instanceGet`, `platformInstanceDomain`,
+ `instanceGet`, `platformInstanceDomain`, `explicitGate`,
+ `instanceChoices`,
`deployRegionPreflight(res, readErr, …)`,
`instanceCreatedLine(rec, envSuffix)` and `KeyFingerprint`.
4. **Review Focus.** Five items, each with a test in its owning task: Tasks
@@ -7949,3 +8254,45 @@ For Paul, outside the findings:
- C30c is new copy, in Task 0's inventory for the copy review.
- C25's draft still says `carlos canary remove`; the real verb is
`carlos canary rm` (noted in Task 0).
+
+## Review dispositions (Astra, plan round 4, on 5600586a with spec 8baddbaa)
+
+Astra judged `instance_domain` sound, including the check of the PUT's
+answer against the preflight host, and Paul approved it on 2026-10-03. Spec
+rev 6.2 (56756f09) records it in §9.3 beside R9a, with the R9a consequence
+finding 1 found.
+
+The proof was done as in rounds 2 and 3. A throwaway worktree was cut at the
+branch base (e8406ce6), rev 4's blocks were replayed and committed there as
+the baseline (Task 13 included this time), and the region tests were green
+on it. Each fix's tests were written first and run failing, then the fix
+was applied and they were run passing. The changed blocks were then
+compared with the scratch files byte for byte; every one matched. The
+scratch worktrees and branch were deleted afterwards.
+
+| # | sev | finding | disposition | proof |
+| --- | --- | --- | --- | --- |
+| R1-17 | P2 (partly) | `/tmp/g` exception, and the scripts' `/tmp` fallbacks | **resolved as an operator rule.** Global Constraints now states the operator's rule for this machine: only the Unix-socket test packages (`internal/host`, `internal/activator`, `internal/edge`, and the other packages whose tests bind a Unix socket, listed there) run with `TMPDIR` under `/tmp/g`, because socket paths are capped at 108 bytes and the on-disk `TMPDIR` is too deep. The directory is small and is deleted after the run, and everything else uses the on-disk `TMPDIR`. CI is unaffected. Every socket-test command goes through one `socktest` function, which makes a fresh `/tmp/g/nr.XXXXXX` and deletes it after the run, so nothing else in the shared `/tmp/g` is touched. Task 25 splits the packages the same way. The two shipped scripts keep `${TMPDIR:-/tmp}`: they run on operator machines and in CI, where an unset `TMPDIR` means the system default, and on this machine `TMPDIR` is always set, so they never reach `/tmp` here. | `socktest` over the eight socket packages: `/tmp/g` listing identical before and after. `host`, `instancectl`, `instanceexec`, `unixdial`, `vet`, `agentsock` `ok`. `edge` (1 test) and `activator` (2 to 3 exec-backend tests, 2s timeouts) fail identically on the unmodified base, so they are this machine's, not the branch's |
+| R4-1 | P1 | Pooled and fleet branches broke R9a when the stored region was unread | **accepted.** Task 15: in both branches `effective` and `available` are set only after a successful region read; `reason` (`pooled`, `fleet`) still says what the placement is. Task 22: `canary --region` needs both flags, because its fleet check reads `effective`; a false `region_known` refuses with C30b. Spec rev 6.2 states this. | `TestAppDefaultUnreadRegionHidesEffective` FAIL before (pooled: `effective:ie`, `available` set; fleet: `effective:fleet/acme`), PASS after. `TestCanaryRegionCheck`'s two region-unknown cases FAIL before, PASS after. e2e `fleet, region unknown`: rev 4's CLI goes past the check; after, it refuses with C30b twice, 0 writes, no manifest |
+| R4-2 | P2 | Refusals listed choices the door then refused | **accepted.** Task 12: one predicate, `explicitGate.refusal`, decides both acceptance and the C18/C19 lists (home's name, plus published codes that are valid, armed and hosting, and not proved keyless). Task 14: a new `instanceChoices` lists, for C16 and C17, what an explicit request for the same socket-backed instance would pass: the allow-list as the door reads it, the armed gate and R9, minus the refused region. An empty list gets a new `b` variant (C16b to C19b, in Task 0 for copy review) instead of "Choose from: .". | Both tests submit every advertised code under the same fixture and expect acceptance. Before: C18/C19 listed `au` (keyless) and `nz` (not hosting); C16 listed `ie, au` with `Regions:["uk","au","nz"]`; C17 listed `au, nz, ie`. After: `ie, uk`; `au`; `au`, each accepted. Mutations: an allow-list-blind `instanceChoices`, and an app list that takes `no-key` codes, each FAIL. `TestAppDerivedRefusals` now expects C17b (its `au` publishes no box) |
+| R4-3 | P2 | The unchanged-form contract was untested and broken | **accepted.** The picker block now opens on the name input's line and closes on the script's line, so with no picker the template emits today's bytes. `TestNewAppPageWithoutPickerIsUnchanged` compares the rendered form with the base tree's own rendering (CSRF blanked), with the switch off and with one eligible region. | FAIL before in both cases (an extra `" \n"` before the button); PASS after. The picker tests still pass |
+
+Whole-package results on the rev 5 scratch tree:
+
+- `go build ./...`, `go vet ./...` and `gofmt -l` clean; all five
+ cross-compile targets built.
+- `go test ./internal/console`: `ok` (142.0s). `internal/geo`,
+ `internal/appconfig`, `internal/provision` and `cmd/console`: `ok`.
+ `internal/host` through `socktest`: `ok`.
+- Every new and changed root test, run by name: PASS, including the 7
+ canary e2e cases and the replica output test.
+- A scan of the prose literals rev 5 adds to product code found exactly
+ C16b to C19b.
+
+For Paul, outside the findings:
+
+- C16b, C17b, C18b and C19b are new copy, in Task 0's inventory.
+- Spec rev 6.2 also writes down that `canary --region` needs
+ `region_known` as well as `placement_known`. It follows from R9a, which
+ leaves `effective` empty without the stored region, rather than being a
+ new ruling.