carlos / platform Public

provision: census overlays for self-serve moves plan 2, Task 1 (PROPOSED-self-serve-moves-2)

A new root-read overlay, loaded after plan 1's with the preceding seal
verified first, re-pins eight accepted-legacy units (the cli_tokens moves
column, its writer and readers, the tokens page, serve and the request
door's dispatch) and three envelopes; the seal moves. A new record-write
inventory wraps plan 1's and re-pins handleAPIInstanceMoveRequest's digest;
TestPlan9B8RecordWriteCensus takes it. No record envelope changes. The
proposal note records the Task 1 dispositions for Paul's ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 6c4490ccee4b47c5e40222735eaec321c83cf028 parent 46863d1
5 files changed, +82 −1
  • docs/superpowers/notes/census-proposal-self-serve-moves-2.md +7 −0
  • internal/provision/plan14_root_reads_test.go +14 −0
  • internal/provision/plan9_b8_census_test.go +1 −1
  • internal/provision/self_serve_moves2_census_test.go +39 −0
  • internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv +21 −0
diff --git a/docs/superpowers/notes/census-proposal-self-serve-moves-2.md b/docs/superpowers/notes/census-proposal-self-serve-moves-2.md
new file mode 100644
index 000000000..89d0373ee
--- /dev/null
+++ b/docs/superpowers/notes/census-proposal-self-serve-moves-2.md
@@ -0,0 +1,7 @@
+# Self-serve moves plan 2: census proposal
+
+Status: proposed, marked PROPOSED-self-serve-moves-2. Not an accepted ruling; the census rulings on this plan are Paul's to make.
+
+The root-read overlay is `internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv`, loaded after the self-serve-moves-1 overlay and before `compareRootReads`, with the preceding seal verified first. The record-write overlay is `plan14SelfServeMoves2WriteCensusInventory` in `internal/provision/self_serve_moves2_census_test.go`, built over plan 1's inventory; `TestPlan9B8RecordWriteCensus` takes it. Later tasks of the plan extend both.
+
+Task 1 (the move-capable token and the self-serve gate) changes no record envelope and adds no root read, class or task. Eight accepted-legacy units are re-pinned in place, each with `rev3=PROPOSED-self-serve-moves-2` and a reviewed one-line basis, and take new frozen fingerprints, so the seal moves. Five are console SQL running as `carlos-console`: `migrateCLIAuth` adds the `cli_tokens` column `moves INTEGER NOT NULL DEFAULT 0` through the idempotent ALTER list; `claimRawNewAppToken` writes it (true only from the owner-only mint door); `CLITokens` and `ServicePrincipals` list it; `CLIPrincipal` reads it (honoured for kind=app rows only) and returns the stored `token_hash` as `Principal.TokenID`. The tokens page template (`settings.html`) marks a move-capable app token and reads nothing of its own. `serve` reads `CARLOS_SELF_SERVE_MOVES` into `Config.SelfServeMoves`, an environment string, beside plan 1's workers. `Server.handleAPIInstanceMoveRequest` keeps its census-ruling-region-ha-2a body; with Phase 1 off it now sends self-serve mode to `selfServeMoveRequest` (the self-serve gate, binding SQL only, no bucket or record read; its Task 1 body answers the family's 404) and every other request to the legacy body. Its read sites are unchanged and their offsets moved. The cmd/console, internal/console and internal/console/templates envelopes are re-pinned. In the record-write inventory the same door stays a record-writer (`key:SetRecordMove,lit:instances`) and takes a new digest; no record write is added, moved or made raw. The cut and abort doors' dispatch is not a census unit. A green census checks these proposed rows against the code; Paul's ruling is still outstanding.
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go
index f8d72b2e0..0064cf111 100644
--- a/internal/provision/plan14_root_reads_test.go
+++ b/internal/provision/plan14_root_reads_test.go
@@ -1293,6 +1293,20 @@ func TestPlan14RootReadCensus(t *testing.T) {
// whose unknown-label keep now follows the name's precedence checks,
// and moves it once more.
seal = "e3beb6d4a83363991ddd2d6e856aebc8d3ca69c4cb02f6b1a30449f104224dd0"
+ // Self-serve moves plan 2 (the door, the token and the job): verify the
+ // preceding seal first. All rows await a human ruling under
+ // rev3=PROPOSED-self-serve-moves-2.
+ if errs := checkRootReadLegacy(inv, seal); len(errs) != 0 {
+ t.Fatal(errs)
+ }
+ if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv"), &inv, true); err != nil {
+ t.Fatal(err)
+ }
+ // Task 1 (the move-capable token and the self-serve gate) re-pins eight
+ // accepted-legacy units (the cli_tokens moves column, its writer and
+ // readers, the tokens page, serve and the request door's dispatch),
+ // which moves the seal.
+ seal = "993491db8d9259f16ceea696eb94c823dac50cf24309854c66354f4a828e5665"
errs := append(compareRootReads(got, inv), checkRootReadLegacy(inv, seal)...)
errs = append(errs, checkRootReadDeclarations(got, inv)...)
if len(errs) > 0 {
diff --git a/internal/provision/plan9_b8_census_test.go b/internal/provision/plan9_b8_census_test.go
index da2572358..3a63fe6c7 100644
--- a/internal/provision/plan9_b8_census_test.go
+++ b/internal/provision/plan9_b8_census_test.go
@@ -366,7 +366,7 @@ func TestPlan9B8RecordWriteCensus(t *testing.T) {
if len(got) < 100 {
t.Fatalf("census found only %d units under %s; the walk is broken", len(got), root)
}
- inventory := plan14SelfServeMoves1WriteCensusInventory()
+ inventory := plan14SelfServeMoves2WriteCensusInventory()
problems := append(censusDiff(inventory, got), censusPolicy(inventory)...)
if len(problems) > 0 {
t.Fatalf("record-write census rejected %d site(s); update the explicit inventory only after reviewing the source:\n %s", len(problems), strings.Join(problems, "\n "))
diff --git a/internal/provision/self_serve_moves2_census_test.go b/internal/provision/self_serve_moves2_census_test.go
new file mode 100644
index 000000000..500ceed6e
--- /dev/null
+++ b/internal/provision/self_serve_moves2_census_test.go
@@ -0,0 +1,39 @@
+package provision
+
+// plan14SelfServeMoves2WriteCensusInventory is the record-write inventory for
+// the self-serve moves plan 2 (the move-capable token, the door,
+// reservations, reports and the job), built over plan 1's inventory without
+// editing it. Marked PROPOSED-self-serve-moves-2
+// (docs/superpowers/notes/census-proposal-self-serve-moves-2.md); not an
+// accepted ruling. Later tasks of the plan extend this function.
+//
+// Task 1 (the move-capable token and the self-serve gate): no record write
+// is added, moved or made raw.
+// - apiinstancemove.go:Server.handleAPIInstanceMoveRequest stays a
+// record-writer (SetRecordMove, the instances literal) and is re-pinned:
+// with Phase 1 off it now sends self-serve mode to selfServeMoveRequest,
+// whose gate reads no record and whose Task 1 body writes nothing, and
+// every other request to the legacy body, whose writes are unchanged.
+func plan14SelfServeMoves2WriteCensusInventory() []censusEntry {
+ removed := []struct{ file, unit string }{
+ {"internal/console/apiinstancemove.go", "Server.handleAPIInstanceMoveRequest"},
+ }
+ added := []censusEntry{
+ {"internal/console/apiinstancemove.go", "Server.handleAPIInstanceMoveRequest", "record-writer", "key:SetRecordMove,lit:instances", "6be4b2d5ed59e3e42c47589039daba2cdb4081db45e0258d8889ef8477290591"},
+ }
+ entries := plan14SelfServeMoves1WriteCensusInventory()
+ for _, r := range removed {
+ found := false
+ for i, entry := range entries {
+ if entry.File == r.file && entry.Unit == r.unit {
+ entries = append(entries[:i], entries[i+1:]...)
+ found = true
+ break
+ }
+ }
+ if !found {
+ panic("self-serve moves 2 removal of an unlisted unit " + r.file + ":" + r.unit)
+ }
+ }
+ return append(entries, added...)
+}
diff --git a/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv b/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv
new file mode 100644
index 000000000..b6146a39a
--- /dev/null
+++ b/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv
@@ -0,0 +1,21 @@
+# Census overlay self-serve-moves-2, marked rev3=PROPOSED-self-serve-moves-2 (not an accepted ruling; docs/superpowers/notes/census-proposal-self-serve-moves-2.md). Loaded after the self-serve-moves-1 overlay.
+# Task 1 (the move-capable token and the self-serve gate), rev3=PROPOSED-self-serve-moves-2: no record envelope changes and no root read, class or task is added. Eight accepted-legacy units are re-pinned in place with reviewed bases and take new frozen fingerprints (the seal moves): the cli_tokens moves column (migrateCLIAuth), its writer and readers (claimRawNewAppToken, CLITokens, ServicePrincipals, CLIPrincipal), the tokens page template, serve (CARLOS_SELF_SERVE_MOVES) and the request door's dispatch. Envelopes re-pinned: cmd/console, internal/console (selfserve_gate.go, the shared instance rails, the mint door's moves field) and internal/console/templates.
+@legacy c50698b41f928d59a9be3f5913eb7f04813ef0f3841f1a4dd8bc9c35635477d7 cmd/console/main.go serve legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=the console (cmd/console serve under console.service, user carlos-console): plan 1's body (Task 0 starts the lifetimes cutover watch, Task 3 the lifetime recovery pass and Task 5 the incarnation migration pass, off unless CARLOS_LIFETIMES_MIGRATE=1) and plan 2 Task 1 reads CARLOS_SELF_SERVE_MOVES into Config.SelfServeMoves, an environment string; the same three data path literals; no privileged reader is added data-literal@4077,data-literal@5178,data-literal@5415 9b46448d569c9244988b281e181acc3031bbfff5cb227d4a16cf6f2e0add7683
+cmd/console/main.go serve legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=the console (cmd/console serve under console.service, user carlos-console): plan 1's body (Task 0 starts the lifetimes cutover watch, Task 3 the lifetime recovery pass and Task 5 the incarnation migration pass, off unless CARLOS_LIFETIMES_MIGRATE=1) and plan 2 Task 1 reads CARLOS_SELF_SERVE_MOVES into Config.SelfServeMoves, an environment string; the same three data path literals; no privileged reader is added data-literal@4077,data-literal@5178,data-literal@5415 9b46448d569c9244988b281e181acc3031bbfff5cb227d4a16cf6f2e0add7683
+@legacy 74173dd0410354dc3c0e4d80bec910c2107355d36b6b7bf30e719fdf6c20a1a9 internal/console/apiinstancemove.go Server.handleAPIInstanceMoveRequest legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=the console (cmd/console serve under console.service, user carlos-console): the census-ruling-region-ha-2a body unchanged; with Phase 1 off the dispatch sends self-serve mode to selfServeMoveRequest (the self-serve gate: binding SQL only, no bucket read, no record read; Task 1's body answers the family's 404) and every other request to the legacy body as before; read sites unchanged, offsets moved file:Exec@10257,file:Exec@10434,file:Exec@10585,file:Exec@11585,file:Exec@9178,file:Exec@9266,file:Read@7664,file:Read@9976 6be4b2d5ed59e3e42c47589039daba2cdb4081db45e0258d8889ef8477290591
+internal/console/apiinstancemove.go Server.handleAPIInstanceMoveRequest legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=the console (cmd/console serve under console.service, user carlos-console): the census-ruling-region-ha-2a body unchanged; with Phase 1 off the dispatch sends self-serve mode to selfServeMoveRequest (the self-serve gate: binding SQL only, no bucket read, no record read; Task 1's body answers the family's 404) and every other request to the legacy body as before; read sites unchanged, offsets moved file:Exec@10257,file:Exec@10434,file:Exec@10585,file:Exec@11585,file:Exec@9178,file:Exec@9266,file:Read@7664,file:Read@9976 6be4b2d5ed59e3e42c47589039daba2cdb4081db45e0258d8889ef8477290591
+@legacy 5aa23d2f21436a1f9ad50c36a41b12e53bbd234e3fafb2eaaab7b4597d83d4b4 internal/console/authstore.go Store.CLITokens legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: lists one address's live cli_tokens rows from the console SQLite store, now with the moves column; no bucket or root action file:Query@78 5c231bb3848378ec9ec9edf92d35e57927557b521d4bfed415f24ace0fb78689
+internal/console/authstore.go Store.CLITokens legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: lists one address's live cli_tokens rows from the console SQLite store, now with the moves column; no bucket or root action file:Query@78 5c231bb3848378ec9ec9edf92d35e57927557b521d4bfed415f24ace0fb78689
+@legacy df6a292cfade2a09a3c3dd053a14422e81e9a9bb60159587e08703e74d379616 internal/console/authstore.go Store.claimRawNewAppToken legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: inserts one kind=app cli_tokens row in the console SQLite store, now carrying the moves flag the owner-only mint door passes (false from every other caller); no bucket or root action file:Exec@250 0d0b97575ddc30f3c719f9086c119f7b41b1905273cc43e659d74f9a35aceafb
+internal/console/authstore.go Store.claimRawNewAppToken legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: inserts one kind=app cli_tokens row in the console SQLite store, now carrying the moves flag the owner-only mint door passes (false from every other caller); no bucket or root action file:Exec@250 0d0b97575ddc30f3c719f9086c119f7b41b1905273cc43e659d74f9a35aceafb
+@legacy c6ec99512ae5e3fd22970777250cea10613b962fa5571a5018d8f2ae13f88670 internal/console/authstore.go Store.migrateCLIAuth legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: adds the cli_tokens moves column (INTEGER NOT NULL DEFAULT 0) through the idempotent ALTER list of the console SQLite schema; no bucket or root action file:Exec@1447,file:Exec@2781,file:Exec@3219,file:Exec@4061 8296753ea866108c636bd38f14a6aa2567b1a90e84058432f64b4670f8415e9b
+internal/console/authstore.go Store.migrateCLIAuth legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: adds the cli_tokens moves column (INTEGER NOT NULL DEFAULT 0) through the idempotent ALTER list of the console SQLite schema; no bucket or root action file:Exec@1447,file:Exec@2781,file:Exec@3219,file:Exec@4061 8296753ea866108c636bd38f14a6aa2567b1a90e84058432f64b4670f8415e9b
+@legacy 59de61d661031430ef7c3959864ee91e6d32aef6c2a9a159707177a3f4f1bb95 internal/console/svcprincipal.go Store.CLIPrincipal legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: resolves a bearer token from one cli_tokens row, now also reading moves (honoured for kind=app rows only) and returning the stored token_hash as the principal's TokenID; the best-effort last_used update is unchanged; no bucket or root action file:Exec@3264,file:QueryRow@275 256c3548cf7b700fc8870104d8c31eefaf986b77f8ff59de2e07ee6dc7ae01f1
+internal/console/svcprincipal.go Store.CLIPrincipal legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: resolves a bearer token from one cli_tokens row, now also reading moves (honoured for kind=app rows only) and returning the stored token_hash as the principal's TokenID; the best-effort last_used update is unchanged; no bucket or root action file:Exec@3264,file:QueryRow@275 256c3548cf7b700fc8870104d8c31eefaf986b77f8ff59de2e07ee6dc7ae01f1
+@legacy 8da18b83613677c37544c2361552daa9f84df94d35a5b6be8c423c30e55b2b0f internal/console/svcprincipal.go Store.ServicePrincipals legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: lists one account's live app and service cli_tokens rows from the console SQLite store, now with the moves column; no bucket or root action file:Query@87 6497829090bbca886acbd1a2fec6f2130ad9d0e9eb8474f36642f3f20abc41b6
+internal/console/svcprincipal.go Store.ServicePrincipals legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: lists one account's live app and service cli_tokens rows from the console SQLite store, now with the moves column; no bucket or root action file:Query@87 6497829090bbca886acbd1a2fec6f2130ad9d0e9eb8474f36642f3f20abc41b6
+@legacy 058a42b1f720a95b9590b30f143ba9892bb169f1c43a386caabdf1fca6b32829 internal/console/templates/settings.html external legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the tokens page template marks a move-capable app token beside its app; it renders the rows its handler read and reads nothing of its own file:external@0 4e903910a7001a43e9f206a7d43cdf9d1fbf1e0af331f6b08f194b21681e05e4
+internal/console/templates/settings.html external legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the tokens page template marks a move-capable app token beside its app; it renders the rows its handler read and reads nothing of its own file:external@0 4e903910a7001a43e9f206a7d43cdf9d1fbf1e0af331f6b08f194b21681e05e4
+@coverage cmd/console b5a2b44792eeca719204eed8f55cf3c8d91f67e17532727f7adedda313470b37
+@coverage internal/console 661b25c54e6c811451ff88511266c61f6dbaee5fe3cd7e9f29282b52b1a8f58c
+@coverage internal/console/templates d3e4b3b103e9a9966a8c91e6683c241b2e53ce55a24f6511c53266586b7f1c5d