woodstar runbook: D0/D2.1-3 done, account bdm, sha 1aa534e, Bluesky-native #77 ruling
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+58
−26
docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md+58 −26
diff --git a/docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md b/docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md| index 88478728a..154d00a31 100644 |
| --- a/docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md |
| +++ b/docs/superpowers/plans/2026-08-16-woodstar-cutover-runbook.md |
| @@ -22,7 +22,10 @@ per spec `docs/superpowers/specs/2026-08-12-woodstar-carloku-migration-design.md |
| | Delegation zone | `acme.oncarlos.com` (oncarlos.com zone `Z04313755ASMHAWD536L`, Route53, keymail account — edge publishes TXT here via `CARLOS_DNS_PROVIDER=route53` suffix-walk) | |
| | Delegation CNAME | `_acme-challenge.woodstar.app` → `_acme-challenge.woodstar.app.acme.oncarlos.com` — **DONE 2026-08-16** (stale Caddy TXT leftovers deleted in the same change batch) | |
| | Old-box cert headroom | apex + wildcard both expire **2026-10-21**; old-box renewal is blocked by the delegation CNAME from its ~Sept 21 renewal window — cutover must land before then, rollback keeps existing certs | |
| -| W0 build sha | woodstar `origin/main` (`0bdcb07` at runbook time; re-read at D2 — always build ALL SIX binaries from ONE sha, `GOOS=linux GOARCH=arm64`, from a CLEAN checkout: `git status --porcelain` empty, never the stale local tree) | |
| +| W0 build sha | woodstar `origin/main` `1aa534e` — **BUILT + SHIPPED + PROMOTED 2026-08-17** (all six binaries + status, one sha, `GOOS=linux GOARCH=arm64`, clean worktree; channel `canary/woodstar`). A later re-ship repeats D2.3 verbatim at the newer sha | |
| +| Account | `woodstar` = sqid **`bdm`** on console.carloku.com (Paul owner) — settled 2026-08-17 | |
| +| Channel | `canary/woodstar` (the canary/keymail pattern; all seven apps ride it) | |
| +| Old-box SSH | `ssh -i ~/.ssh/woodstar-canary.pem ec2-user@52.30.232.124` (key per woodstar `scripts/status-publish.sh`) | |
| | Ports (loopback only) | relay 8451, media 8452, indexer 8453, notify 8454, unfurl 8455, apbridge 8456 | |
| | Data | `/data/woodstar` 0700 owner `woodstar` (`/data` stays 0711) | |
| | App env file | `/etc/carlos/apps/woodstar.env` 0600 root: `WOODSTAR_APPLE_APP_ID=J5NDF5PCD8.app.woodstar.ios` — in place BEFORE the flip or iOS passkeys break | |
| @@ -30,6 +33,29 @@ per spec `docs/superpowers/specs/2026-08-12-woodstar-carloku-migration-design.md |
| | Replicated DBs | relay.db, indexer.db, apbridge.db — **unfurl.db deliberately excluded** (cache, repo rule); `apbridge.seed` = federation identity flat FILE, copied not litestreamed | |
| | Apps (7) | `woodstar-relay/-media/-indexer/-notify/-unfurl/-apbridge` (kind binary, linux-arm64) + `woodstar-status` (kind static) | |
| +## Bluesky-native (#77) ruling — 2026-08-17 |
| + |
| +woodstar #77 (merged the morning of 2026-08-17) added `atbridge`, |
| +Woodstar's own AT Proto PDS, replacing Bridgy: a seventh service |
| +(:7077), its own `atbridge.db` + `atbridge.seed`, a `pds.woodstar.app` |
| +exact host, an apex `/at/*` leg, and wildcard |
| +`/.well-known/atproto-did` moving apbridge→atbridge — **on the |
| +devbox/canary only**. Probed live 2026-08-17: |
| +`pds.woodstar.app/xrpc/_health` 302s to `woodstar.app/pds` (the |
| +wildcard profile redirect), i.e. prod has NO pds host and NO atbridge; |
| +prod's atproto-did still answers from apbridge (Bridgy-era did:plc). |
| + |
| +**Ruling (spec §11 applied — parity with live behavior, no new |
| +features ride the migration):** the cutover moves the SIX-service |
| +topology exactly as prod runs it today. The W0 fan-out's |
| +atproto-did→apbridge routing is therefore CORRECT parity, and no |
| +`-atbridge-upstream` leg is needed for the migration. The PDS prod |
| +rollout is woodstar's own post-migration work, done ON CARLOS through |
| +the product surface (new app `woodstar-atbridge`, `pds.woodstar.app` |
| +exact route, fan-out `-atbridge-upstream` + atproto-did repoint as a |
| +woodstar PR, `atbridge.db` litestream + `atbridge.seed` backup) — see |
| +D5. D1.1 verifies the six-unit assumption on the box. |
| + |
| ## Standing constraints (spec §7, restated) |
| - No DNS A-record changes and no touching running woodstar services |
| @@ -49,12 +75,10 @@ per spec `docs/superpowers/specs/2026-08-12-woodstar-carloku-migration-design.md |
| ## D0 — Platform preconditions (no prod impact beyond two unit restarts) |
| State at runbook time: track live (box binary `c42ec0c`, console |
| -`3f28e9f`, both contain Plans B+C); delegation CNAME done. One item |
| -open: |
| +`3f28e9f`, both contain Plans B+C); delegation CNAME done. |
| -- [ ] **D0.1 — set the delegation zone on the flagship** (this exact |
| - command was permission-blocked for the authoring session; run it or |
| - approve its retry): |
| +- [x] **D0.1 — set the delegation zone on the flagship** — DONE |
| + 2026-08-17 (Paul ran it; both units restarted `active`): |
| ```bash |
| cd ~/github.com/carlosframework/platform-infrastructure && \ |
| @@ -70,9 +94,11 @@ aws --profile keymail ssm send-command --instance-ids i-092c0c1eea75723cb \ |
| `/etc/carlos/host.env` (verified 2026-08-16), so the one line covers |
| door and issuance. Inert until a claim opts in. |
| -- [ ] **D0.2 — verify:** `curl -sI https://console.carloku.com/ | grep |
| - -i x-carlos-version` still answers (post-restart); box journal shows |
| - NO `CARLOS_ACME_DELEGATION_ZONE … invalid` line from either unit. |
| +- [x] **D0.2 — verify:** DONE 2026-08-17 — console 200 |
| + (`x-carlos-version: 5bef643`), edge boot line reads |
| + `wildcard certs on (static [], apps domain "oncarlos.com", |
| + delegation zone "acme.oncarlos.com")`, no invalid-zone line, all six |
| + existing `*.oncarlos.com` wildcards reloaded from cache. |
| ## D1 — Old-box pre-flight (SSH, read-only, any time) |
| @@ -81,10 +107,12 @@ record it in the session and in this file's margin notes. |
| - [ ] **D1.1 — units:** `systemctl cat woodstar-*.service` (expect |
| six). Capture EVERY ExecStart flag and Environment line verbatim — |
| - especially apbridge's `-domain`/`-seed`/`-bridgy`/`-bsky-api` and |
| - any relay `-passkey-rp`/`-media`/`-imports` values. Six units are |
| - the target; a seventh unit or a flag the spec never mentioned is a |
| - FINDING — stop and record it before D2. |
| + especially apbridge's `-domain`/`-seed` + Bridgy-era flags and any |
| + relay `-passkey-rp`/`-media`/`-imports` values. Six units are the |
| + target (the #77 ruling above: NO `woodstar-atbridge.service` on |
| + prod — if one appears, the ruling's premise is stale; stop and |
| + re-probe). Any other seventh unit or unspec'd flag is a FINDING — |
| + stop and record it before D2.4. |
| - [ ] **D1.2 — sizes:** per-service RSS (`systemctl status`), total |
| `du -sh /opt/woodstar/data` — re-confirm the t4g.nano-scale verdict. |
| - [ ] **D1.3 — data dir:** `ls -la /opt/woodstar/data` — expect |
| @@ -106,16 +134,13 @@ record it in the session and in this file's margin notes. |
| ## D2 — Flagship tenant build-out (pre-flip, real hostnames NOT routed yet) |
| -- [ ] **D2.1 — account decision (Paul, one line):** which console |
| - account owns the seven apps. Recommendation: a dedicated `woodstar` |
| - account (own statements, own tokens), same pattern as tito=bae on |
| - the tito console. Needed before any `carlos apps create`. |
| -- [ ] **D2.2 — apps:** `carlos apps create` × 7 under that account |
| +- [x] **D2.1 — account:** `woodstar` (`bdm`) on console.carloku.com, |
| + Paul owner — existed already, confirmed 2026-08-17. |
| +- [x] **D2.2 — apps:** all seven created 2026-08-17 under `bdm` |
| (six binary + `woodstar-status` static). |
| -- [ ] **D2.3 — build + ship:** from a clean woodstar checkout at |
| - origin/main: six `CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build` |
| - binaries, `carlos ship` + promote each on its app's canary channel. |
| - Status site: `carlos ship -kind static` of the status content. |
| +- [x] **D2.3 — build + ship:** DONE 2026-08-17 — six binaries + the |
| + repo's `status/` site, all at `1aa534e`, shipped and promoted to |
| + `canary/woodstar`. |
| - [ ] **D2.4 — box-side (SSM, root):** system user `woodstar` |
| (sysusers), `/data/woodstar` 0700, `/etc/carlos/apps/woodstar.env` |
| (0600, the AASA line), six hardened units |
| @@ -134,9 +159,10 @@ record it in the session and in this file's margin notes. |
| **`-media` AND `-media-upstream` are BOTH required** (importer vs |
| fan-out — final-review catch). apbridge keeps |
| - `-domain woodstar.app -seed /data/woodstar/apbridge.seed` + D1's |
| - `-bridgy`/`-bsky-api` values. Units installed but **NOT started** |
| - (founder trap) — except as D3 rehearses on copies. |
| + `-domain woodstar.app -seed /data/woodstar/apbridge.seed` plus |
| + whatever Bridgy-era flags D1.1 captured, verbatim. Units installed |
| + but **NOT started** (founder trap) — except as D3 rehearses on |
| + copies. |
| - [ ] **D2.5 — routes via product surface:** relay's primary route as |
| a declared route record (#137 vocabulary) on the flagship; |
| `status.woodstar.app` attach for `woodstar-status` (first-route |
| @@ -213,9 +239,15 @@ keep the window short. Old box afterwards: units stopped, disk intact, |
| frozen 30 days. (Old-box certs stay valid to 2026-10-21 regardless of |
| the delegation CNAME.) |
| -## D5 — Post-cutover (spec §9) |
| +## D5 — Post-cutover (spec §9 + the #77 ruling) |
| - [ ] Promote the W0 sha to stable after the 72 h supply-chain bake. |
| +- [ ] **PDS prod rollout (woodstar's own project, on CARLOS):** app |
| + `woodstar-atbridge` + `pds.woodstar.app` exact route via the door; |
| + a woodstar PR adding the relay fan-out `-atbridge-upstream` (`/at/*` |
| + leg) and moving wildcard atproto-did apbridge→atbridge; |
| + `atbridge.db` into litestream + `atbridge.seed` into the backup set. |
| + Wildcard DNS already covers the pds hostname. |
| - [ ] Repoint status publishing: `carlos ship -kind static` + promote |
| replaces `scripts/status-publish.sh`. |
| - [ ] Note woodstar `infra/` tofu drift; retire the old prod instance |