plan: woodstar โ flagship (recon complete, execution deferred behind multi-account)
Agent-authored recon + plan. Woodstar is the cleanest fit yet (same account, arm64-native, no secrets, no IMDS need, no canonical-host pinning) but needs W0: the edge routes by Host only and woodstar's client is same-origin across four path-prefixed services. Execution waits for multi-account so woodstar is born into its own account rather than migrated twice.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+381
−0
docs/superpowers/plans/2026-08-02-plan-woodstar-flagship.md+381 −0
diff --git a/docs/superpowers/plans/2026-08-02-plan-woodstar-flagship.md b/docs/superpowers/plans/2026-08-02-plan-woodstar-flagship.md| new file mode 100644 |
| index 000000000..d7adfe2a9 |
| --- /dev/null |
| +++ b/docs/superpowers/plans/2026-08-02-plan-woodstar-flagship.md |
| @@ -0,0 +1,381 @@ |
| +# ๐ค Plan: Woodstar โ CARLOS flagship migration |
| + |
| +> **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. |
| + |
| +> ๐ค Written by an LLM (Claude), per factor X. |
| + |
| +**Goal:** Woodstar's production instance (`woodstar.app` + `status.woodstar.app`) |
| +serving from the CARLOS flagship box (`i-092c0c1eea75723cb` / 99.81.104.219), |
| +riding carlos release channels, hostname unchanged โ passkeys and the iOS |
| +app's AASA binding are domain-bound, so `woodstar.app` must survive |
| +byte-identical. The **devbox stays put** (it is the dev/canary workflow, and |
| +it depends on Caddy wildcard DNS-01 certs the carlos edge cannot mint). |
| + |
| +**Playbook:** the kass + keymail migrations (plans B and |
| +2026-08-02-plan-keymail-flagship.md): ship `-target linux-arm64`, |
| +route-before-adopt, per-host live link, `/data` 0711 + `/data/<app>` 0700, |
| +rehearse on a COPY, never fork a litestream lineage, DNS flip HELD for Paul's |
| +explicit go, no full `carlos bootstrap` on the live box ever. |
| + |
| +## Where Woodstar lives today (recon 2026-08-02) |
| + |
| +- Repo: `/home/paulca/github.com/woodstarapp/woodstar` (origin/main |
| + `dfe406a`). Pure Go 1.25, **modernc.org/sqlite (no CGO)** โ cross-compiles |
| + to linux-arm64 with zero friction; both current boxes are already arm64 |
| + (t4g). The 16 MB `relay` file checked into the repo root is a stray |
| + **macOS** arm64 build, not a deploy artifact โ deploys always cross-compile |
| + (`scripts/deploy.sh`). No non-Go native deps anywhere in the serve path. |
| +- **Four services, four separate binaries** (`cmd/relay|media|indexer|notify`): |
| + - `relay` :7071 โ SQLite `relay.db`, WebSocket hub (`GET /subscribe`), |
| + embedded web client (go:embed), serves `/.well-known/woodstar.json` and |
| + `/.well-known/apple-app-site-association`. |
| + - `media` :7072 โ content-addressed blob store on disk (`-dir`), no DB. |
| + - `indexer` :7073 โ SQLite `indexer.db` (FTS), tails the relay firehose |
| + over HTTP (`-relay http://127.0.0.1:7071`). |
| + - `notify` :7074 โ SSE (`text/event-stream`), stateless, tails the relay. |
| +- **Boxes โ verified live, SAME account as the flagship (271376211898, |
| + eu-west-1, profile `keymail`; profile `woodstar` also reaches it):** |
| + - prod: `i-09e55d1b6c9598dff` (t4g.nano, EIP **52.30.232.124**, tag name |
| + `woodstar-canary` โ legacy name, it IS prod), hand-built: |
| + Caddy (route53 DNS-01, wildcard certs) fronts the four services on |
| + loopback with **path routing**: `/media*`โ7072, `/api/*`โ7073, |
| + `/stream/*`โ7074, everything elseโ7071; also serves |
| + `status.woodstar.app` as static files from `/opt/woodstar/status`. |
| + The `34.241.196.33` in `infra/prod-Caddyfile`'s comment is a stale IP |
| + from a previous box. |
| + - devbox: `i-0c388ec47cf98067a` (t4g.micro, EIP 34.253.20.182) โ |
| + `dev.woodstar.app` + per-branch canaries, fully scripted |
| + (`infra/devbox-init.sh`), disposable. **Not migrating.** |
| + - Units (from devbox-init.sh; prod mirrors it hand-built): |
| + `woodstar-relay|media|indexer|notify.service`, `User=woodstar` (static |
| + system user), loopback addrs, `WorkingDirectory` = the data dir. |
| + SSH `ec2-user@<ip>` with `~/.ssh/woodstar-canary.pem`; **no SSM agent |
| + registered** on either box (instance role is route53+S3 only) โ box-side |
| + work at cutover is over SSH, and SSH to these boxes is currently |
| + classifier-blocked for agents (Paul: allow rule or run those steps). |
| +- **Data:** SQLite ร2 (`relay.db`, `indexer.db`) + media dir. Litestream |
| + 0.3.13 sidecar (root, `/etc/litestream.yml`) streams both DBs to |
| + `s3://woodstar-backups-271376211898/prod/{relay,indexer}`; media backed up |
| + hourly by a root oneshot timer (`aws s3 sync`, additive, no --delete) to |
| + `.../prod/media`. Restore = manual `litestream restore` + `aws s3 sync` |
| + back (runbook in `scripts/litestream-setup.sh`) โ **no restore-on-boot** |
| + embedded in the app (unlike keymail), so the F4 silently-empty failure |
| + mode does not exist here; restore is explicit or it visibly didn't happen. |
| + Sizes (bucket, 2026-08-02): relay 188 KB, indexer 103 KB, media 6.5 MB. |
| + Tiny. |
| +- **Secrets: none.** The only runtime env is `WOODSTAR_APPLE_APP_ID` |
| + (verified live: prod serves AASA `J5NDF5PCD8.app.woodstar.ios`) โ an |
| + identifier, not a secret. No SES, no OAuth, no tokens, no SMTP. Nothing |
| + to stage in SSM. |
| +- **DNS:** Route53 zone `woodstar.app` (`Z07702842ZC4MUKZR07JB`) **in the |
| + same account**. Records: `woodstar.app` A + `*.woodstar.app` A โ |
| + 52.30.232.124 (TTL 300); `dev.woodstar.app` + `*.dev.woodstar.app` โ |
| + devbox. `status.woodstar.app` has NO explicit record โ it rides the |
| + wildcard. Registrar is Key-Systems LLC (not DNSimple 285 โ checked; NS |
| + delegated to Route53), irrelevant to cutover: the flip is two A-record |
| + changes in Route53, same account, no DNSimple involvement. |
| +- Infra: OpenTofu `infra/main.tf`, state |
| + `s3://woodstar-tfstate-271376211898/infra/terraform.tfstate`. Will drift |
| + at cutover (records changed outside its state) โ expected, same as kass |
| + and keymail. |
| + |
| +## CARLOS fit assessment |
| + |
| +- **Arch: clean.** Pure Go, CGO-free, deploys already build |
| + `GOOS=linux GOARCH=arm64`; prod runs on arm64 today. No x86-only |
| + artifacts, no native deps (the repo-root `relay` Mach-O stray is inert). |
| +- **IMDS: no allowance needed.** Zero AWS SDK / SigV4 / SES in the Go |
| + services (grepped clean). AWS credentials are used only by the litestream |
| + sidecar and the media-sync timer, both of which run as **root** on the |
| + flagship pattern (root is already through the uid-gate). The |
| + keymail-style `allow-imds-user.sh` step is NOT required. Corollary: no |
| + silently-empty-restore trap. |
| +- **Canonical-host pinning: none server-side.** The relay never derives or |
| + emits its own origin โ no `-host`/`-tls` flags, no absolute URLs minted. |
| + CORS is `*`, WS `CheckOrigin` always true. Passkeys are client-side only |
| + (`web/public/lib/passkey.js`: `rp: {name: "Woodstar"}`, no `id` โ RP ID |
| + defaults to the page's domain); the server stores wrapped-key blobs and |
| + never verifies WebAuthn origins. Hostname stays `woodstar.app` โ passkeys |
| + and the iOS AASA binding survive. **No K0-equivalent flag needed.** |
| +- **โ The one real gap (W0): path fan-out.** The deployed client is |
| + same-origin for all four services (`lib/api.js` DEFAULT_SERVICES); today |
| + Caddy path-routes one hostname to four backends. The carlos edge routes |
| + **by Host only** (`internal/registry` Route has no path; |
| + kinds instance|service|static). Without a front, `woodstar.app` โ relay |
| + alone serves a degraded app (no media, no search, no live notifications). |
| + Two options: |
| + - **W0a (recommended): teach the relay to front its satellites.** Small |
| + Go change: optional flags `-media-upstream`, `-indexer-upstream`, |
| + `-notify-upstream`; when set the relay reverse-proxies `/media`, |
| + `/media/*`, `/api/*`, `/stream/*` (exactly Caddy's `prod_routes` |
| + block). httputil.ReverseProxy passes WS upgrades and flushes |
| + `text/event-stream` immediately, so `/stream/*` SSE survives the extra |
| + hop. Unset = today's behavior byte-identical. Also improves the |
| + self-host story ("bin/relay alone serves a complete instance"). |
| + - W0b: teach the carlos edge path-prefix routing. Platform feature, |
| + bigger blast radius, benefits future multi-service tenants. Not needed |
| + for the timeline if W0a lands. |
| +- **Process/tenancy shape: static user `woodstar`, four bespoke hardened |
| + units** (the keymail pattern). Not `carlos-app@` DynamicUser: that |
| + template is per-route (`ExecStart=live/<host> serve`) and only the relay |
| + has a public route โ media/indexer/notify are route-less satellites, and |
| + the four units share loopback TCP + a data tree, which wants one stable |
| + uid. Units: `woodstar-{relay,media,indexer,notify}.service`, User=woodstar, |
| + harden-host.sh sandbox drop-ins, data under `/data/woodstar` (0700, |
| + /data 0711). |
| +- **App packaging vs the release model:** `carlos ship` is one-binary-per-app |
| + keyed by GOOS-GOARCH (multi-file ship = multi-TARGET of one binary; |
| + basename-keyed artifacts are invisible to adopt โ the kass lesson). Four |
| + binaries โ **four carlos apps**: `woodstar-relay`, `woodstar-media`, |
| + `woodstar-indexer`, `woodstar-notify` (+ `woodstar-status`, kind static). |
| + Alternative: merge into one `woodstar` binary with verbs (titogo/keymail |
| + shape) โ cleaner platform-side, but contradicts the repo's stated "one |
| + small self-hostable binary per service" design value. Paul's call (open |
| + question 2); the four-app shipment already staged is non-binding either |
| + way. |
| +- **Privileged ports: none.** No :25, no SMTP, nothing below 1024. Edge |
| + owns :80/:443; all four services go loopback (proposed 8451โ8454). |
| +- **Streaming through the edge:** two proxied hops post-W0a |
| + (edge โ relay โ notify) for SSE, one for WS (`/subscribe` terminates at |
| + the relay). Both supported by Go's ReverseProxy; verify live in W3 โ |
| + an explicit rehearsal checkbox, not an assumption. |
| +- **Wildcard loss (decision needed):** Caddy serves `*.woodstar.app` today |
| + with a DNS-01 wildcard cert; the carlos edge is per-host HTTP-01 with a |
| + registry-backed HostPolicy (wildcard.go deliberately not ported yet; |
| + titogo hit the same wall). Nothing live depends on prod subdomains today |
| + except `status.woodstar.app` (which gets its own route + cert) โ the |
| + `you.woodstar.app` per-user idea in `docs/` is aspirational (DESIGN ยง11). |
| + After cutover, random `*.woodstar.app` hosts will fail TLS instead of |
| + serving the app. Recommend: accept the loss, keep the wildcard A record |
| + pointed at the flagship (the :80 fallback redirect still catches typos), |
| + add explicit routes if a subdomain ever matters. |
| + |
| +## Box headroom verdict |
| + |
| +**Fits. No instance bump needed.** The ENTIRE prod stack (4 Go services + |
| +Caddy + litestream + AL2023) runs inside a **t4g.nano (512 MB)** today โ |
| +that is a hard upper bound on its footprint, and its data is ~7 MB total. |
| +Flagship measured 2026-08-02 ~09:35 UTC (SSM, read-only) with kass + |
| +keymail (relay + 18 instances) + console + edge + status loop all resident: |
| +**1179 MB available of 1858** (679 used). Expect Woodstar to add roughly |
| +100โ200 MB across the four services โ comfortably inside headroom, with |
| +keymail's mailbox-fleet growth remaining the number to watch on this box. |
| +(Exact per-process RSS on the woodstar prod box was NOT measured โ no SSM |
| +agent there and agent SSH is classifier-blocked; the nano bound makes the |
| +verdict safe regardless.) |
| + |
| +## Global constraints |
| + |
| +- NO DNS changes, no touching the running woodstar services, no production |
| + data writes until the explicitly gated steps; the cutover flip is **HELD |
| + for Paul's explicit go**. |
| +- Rehearsals must never point a litestream at the live |
| + `woodstar-backups-โฆ/prod/` prefixes (lineage fork). Rehearse from COPIES |
| + under `carlos-data-ie-271376211898`. |
| +- Never run old-box and flagship woodstar stacks against the same |
| + replication prefixes at once. |
| +- host.env / apps-env values with spaces double-quoted; SSM adopt (once SSM |
| + matters โ flagship has it) needs `set -a; . /etc/carlos/host.env; set +a` |
| + first; full `carlos bootstrap` never re-runs on the live flagship. |
| +- Woodstar's `infra/` tofu stack stays untouched until post-cutover |
| + retirement (it will drift when we flip records + stop units โ expected). |
| + |
| +--- |
| + |
| +### Task W0: relay front-proxy (the one code change) |
| + |
| +- [ ] In a **woodstar worktree** (its CLAUDE.md: never build in the main |
| + checkout; multiple sessions active): add optional |
| + `-media-upstream`, `-indexer-upstream`, `-notify-upstream` flags to |
| + `cmd/relay`. When set, the relay's mux reverse-proxies |
| + `/media` + `/media/{hash...}` โ media, `/api/` โ indexer, |
| + `/stream/` โ notify (mirror Caddy's `prod_routes` exactly, including |
| + `POST /media` uploads). Unset = today's behavior byte-identical. |
| + Tests: proxy wiring, SSE pass-through flush, WS `/subscribe` |
| + untouched. TDD per superpowers. |
| +- [ ] `make test` green; run the repo's harness if practical |
| + (`make e2e`; the browser drives need Playwright). |
| +- [ ] PR into woodstar main; note in the PR that dev/devbox behavior is |
| + unchanged (Caddy keeps doing the fan-out there). |
| +- [ ] After merge: rebuild all four binaries at the merged sha |
| + (`GOOS=linux GOARCH=arm64 CGO_ENABLED=0 -trimpath`) and re-ship |
| + (`carlos ship -app woodstar-<svc> -kind binary -version <sha> |
| + -target linux-arm64 <bin>`). The dfe406a shipment is |
| + pipeline-validation only; the cutover binaries are the W0 sha. |
| + |
| +### Task W1: flagship-side layout decision + prep (no tofu needed by default) |
| + |
| +- [ ] **Backup home decision (open question 3):** recommended โ replicate |
| + to the platform data bucket `carlos-data-ie-271376211898` under |
| + `woodstar/{relay,indexer,media}` (kass precedent; host role already |
| + has RW; **zero IAM/tofu change**). Alternative: keep |
| + `woodstar-backups-โฆ` as the target, which needs a host-role IAM |
| + policy in `platform-infrastructure/flagship` (a small `woodstar.tf` |
| + mirroring `keymail.tf`'s bucket-RW block). |
| +- [ ] Extend the flagship box litestream config (hand-written, root โ the |
| + generator still doesn't do nested layouts) with |
| + `/data/woodstar/relay.db` and `/data/woodstar/indexer.db` โ |
| + chosen bucket. DO NOT enable until cutover (lineage rule). |
| +- [ ] Media backup timer: `woodstar-media-backup.{service,timer}` (root, |
| + hourly, additive `aws s3 sync /data/woodstar/media s3://<chosen>/โฆ`) |
| + โ port of `scripts/litestream-setup.sh`'s unit, path-adjusted. |
| +- [ ] Units staged (not started): `woodstar-{relay,media,indexer,notify}.service` |
| + โ static user `woodstar`, harden drop-ins, `/data/woodstar` (0700), |
| + env file `/etc/carlos/apps/woodstar.env` (0600 root) carrying |
| + `WOODSTAR_APPLE_APP_ID=J5NDF5PCD8.app.woodstar.ios`. Loopback ports |
| + 8451 relay / 8452 media / 8453 indexer / 8454 notify; |
| + relay flags: `-addr 127.0.0.1:8451 -db /data/woodstar/relay.db |
| + -name woodstar -media-upstream http://127.0.0.1:8452 |
| + -indexer-upstream http://127.0.0.1:8453 |
| + -notify-upstream http://127.0.0.1:8454`; |
| + media `-dir /data/woodstar/media`; indexer/notify |
| + `-relay http://127.0.0.1:8451`. |
| +- [ ] No SSM secrets to stage (Woodstar has none). No IMDS allowance |
| + needed (no in-process AWS). |
| + |
| +### Task W2: verify prod box actuals (operator or SSH-allowed session) |
| + |
| +The prod box is hand-built and SSH-only (no SSM). Before rehearsing, |
| +confirm against assumptions (read-only): |
| +- [ ] `systemctl cat woodstar-relay` on 52.30.232.124 โ exact flags/env |
| + (esp. `WOODSTAR_APPLE_APP_ID`, `-name`, any surprise env). |
| +- [ ] `ps`/`free` โ real RSS per service (refines the headroom estimate). |
| +- [ ] `ls /opt/woodstar/data` โ confirm nothing beyond |
| + relay.db/indexer.db/media (e.g. no third DB the litestream.yml |
| + doesn't cover). |
| + |
| +### Task W3: flagship restore rehearsal (no prod impact, copies only) |
| + |
| +- [ ] Copy backups (server-side CopyObject, read-only on source): |
| + `s3://woodstar-backups-271376211898/prod/{relay,indexer,media}` โ |
| + `s3://carlos-data-ie-271376211898/woodstar-rehearsal/โฆ`. |
| +- [ ] On the flagship (SSM): restore both DBs |
| + (`litestream restore -o /data/woodstar-rehearsal/relay.db โฆ`) + |
| + `aws s3 sync` the media copy; `PRAGMA integrity_check` on both. |
| +- [ ] Transient units on rehearsal ports, W0 binaries, data dir |
| + `/data/woodstar-rehearsal`; route-before-adopt: |
| + `carlos add -app woodstar-relay -kind instance |
| + -addr 127.0.0.1:8451 -channel canary/woodstar-rehearsal |
| + woodstar-rehearsal.99.81.104.219.sslip.io` โ adopt โ LE cert on |
| + first hit. |
| +- [ ] Verify through the edge: client loads clean (WebKit |
| + `console-check.mjs` against the rehearsal URL โ the repo's own |
| + post-deploy law), feed renders restored posts, **media images load |
| + (`/media/*`), search returns (`/api/search`), SSE connects and |
| + streams (`/stream/*`), WS `/subscribe` connects** โ the four-hop |
| + checks are the point of the rehearsal. |
| +- [ ] `woodstar-status`: promote to a rehearsal channel, route |
| + `status-woodstar-rehearsal.โฆ.sslip.io` kind=static, verify 200. |
| +- [ ] Record freeze-to-serving time; tear down units + `/data/woodstar-rehearsal` |
| + + rehearsal routes; optionally delete the copied prefix (re-copy is |
| + pennies at 7 MB). |
| + |
| +### Task W4: cutover (HELD โ Paul's explicit go required) |
| + |
| +Pre-flight: W0 merged + shipped + promoted (`canary/woodstar` at most until |
| +bake), W1 staged, W2 checked, W3 green, `/data/woodstar` empty, TTLs |
| +already 300. |
| + |
| +1. Routes exist + adopted on flagship: `woodstar.app` โ 127.0.0.1:8451 |
| + (kind instance, app woodstar-relay), `status.woodstar.app` (kind |
| + static, app woodstar-status). Certs mint on first post-flip hit. |
| +2. **Stop** on old prod (SSH): the four `woodstar-*` units, then |
| + `woodstar-media-backup.timer`, run one final |
| + `woodstar-media-backup.service` pass, wait for litestream's final WAL |
| + frames (~30 s), then stop `litestream.service`. Verify newest LTX |
| + timestamps under `prod/{relay,indexer}` are post-stop. (Old litestream |
| + MUST be stopped before the flagship one starts if the same prefixes are |
| + reused; with the recommended fresh `carlos-data-ie` prefixes, do a final |
| + `litestream restore` on the flagship from `woodstar-backups` AFTER the |
| + old one stops โ order is stop-old โ restore-new โ start-new.) |
| +3. **Restore + start** on flagship: litestream restore both DBs into |
| + `/data/woodstar`, media sync, chown woodstar, integrity_check, start |
| + the four units + enable the flagship litestream config + media timer. |
| +4. Smoke pre-flip: loopback `/info` 200 (`{"name":"woodstar",โฆ}`), |
| + `/.well-known/apple-app-site-association` correct, feed query via |
| + `curl --resolve woodstar.app:443:99.81.104.219`. |
| +5. **Flip Route53** (zone Z07702842ZC4MUKZR07JB, same account): |
| + `woodstar.app` A and `*.woodstar.app` A โ 99.81.104.219. Watch the LE |
| + certs issue for woodstar.app + status.woodstar.app. |
| +6. Verify (Paul, browser): sign-in with an existing passkey at |
| + https://woodstar.app, post, image upload + display, search, live |
| + notification, DM; iOS app still validates AASA; status page 200. |
| +7. Old prod box: units left stopped, disk intact โ rollback body; freeze |
| + 30 days like kass/keymail. |
| + |
| +**Rollback** (before/at 6): stop flagship units + its litestream, restart |
| +the old box's units + litestream, flip the two A records back. Writes |
| +accepted by the flagship during the window live only in its lineage โ keep |
| +the window short, quiet hour. |
| + |
| +### Task W5: post-cutover |
| + |
| +- [ ] Promote W0 sha to stable after the 72 h supply-chain bake |
| + (canary channels bypass by design; stable does not). |
| +- [ ] Repoint `scripts/status-publish.sh` (or replace it with |
| + `carlos ship -kind static` + promote โ statuses become releases). |
| +- [ ] Note drift in woodstar `infra/` (records + stopped units outside its |
| + state); plan prod-instance retirement after the freeze. Keep zone, |
| + bucket, devbox, IAM as-is โ devbox workflow is untouched. |
| +- [ ] Decide `-status-named` opt-in for the fleet status page. |
| +- [ ] Update woodstar CLAUDE.md "The boxes" section post-retirement. |
| + |
| +## Special risks |
| + |
| +- **Degraded-not-broken failure shape:** if W0 fan-out is misconfigured the |
| + site still "works" (relay serves the client; media/search/notify |
| + silently 404/fail). The W3 four-path checks and the WebKit console check |
| + exist precisely to catch this โ do not skip them at cutover (step 4/6). |
| +- **SSE/WS through two proxies:** verified in rehearsal, not assumed. |
| +- **Wildcard subdomains lose TLS** post-cutover (edge is per-host |
| + HTTP-01). Accepted per assessment; revisit if `you.woodstar.app`-style |
| + features ship (that's the edge wildcard.go port, a platform feature). |
| +- **iOS binding:** `WOODSTAR_APPLE_APP_ID` must be in the flagship env |
| + BEFORE the flip โ a missing AASA breaks iOS passkey assertions |
| + (`J5NDF5PCD8.app.woodstar.ios`, verified live on prod). |
| +- **No restore-on-boot:** restore is explicit (step 3). The empty-DB trap |
| + is a no-show here, but the inverse risk exists: starting units before |
| + restoring gives the relay a FRESH founder-less DB and the first |
| + registrant becomes founder โ never start units on an empty |
| + `/data/woodstar` connected to the real hostname. |
| + |
| +## Prep already completed (2026-08-02, this session) |
| + |
| +- Recon above, all verified live read-only (EC2/Route53/S3 describes via |
| + profile `keymail`; SSM free/ps on the flagship; HTTPS GETs of |
| + /info + AASA on prod). No box, DNS, or service touched. |
| +- origin/main `dfe406a` cloned fresh and cross-built |
| + (`GOOS=linux GOARCH=arm64 CGO_ENABLED=0 -trimpath`): four static ELF |
| + aarch64 binaries. |
| +- **Shipped to `carlos-flagship-271376211898` (NOT promoted โ no channel, |
| + no route, no box touched):** |
| + - `apps/woodstar-relay/releases/dfe406a/linux-arm64` (+manifest) |
| + - `apps/woodstar-media/releases/dfe406a/linux-arm64` |
| + - `apps/woodstar-indexer/releases/dfe406a/linux-arm64` |
| + - `apps/woodstar-notify/releases/dfe406a/linux-arm64` |
| + - `apps/woodstar-status/releases/dfe406a/site.tar.gz` (kind static) |
| + These validate the pipeline; W0's merged sha supersedes them for cutover. |
| + |
| +## Open questions for Paul |
| + |
| +1. **W0 shape:** relay-side fan-out flags (W0a, recommended, small) or |
| + edge path routing (W0b, platform feature)? W0a can land this week. |
| +2. **Packaging:** keep four carlos apps (matches the repo's |
| + one-binary-per-service design) or merge to one `woodstar` binary with |
| + verbs (matches titogo/keymail platform shape)? Shipment staged as four; |
| + non-binding. |
| +3. **Backup home:** move replication to `carlos-data-ie-271376211898/woodstar/` |
| + (zero IAM change, kass precedent) or keep `woodstar-backups-โฆ` |
| + (needs a small host-role IAM addition)? Either way the old bucket keeps |
| + the pre-migration history. |
| +4. **Wildcard `*.woodstar.app`:** accept TLS loss for arbitrary subdomains |
| + (recommended; nothing live uses them) or prioritize the edge |
| + wildcard/DNS-01 port first? |
| +5. **Sequencing:** kass stable flip is 2026-08-05 02:30 UTC and titogo's |
| + TTL raise + keymail post-cutover tests are still open โ slot Woodstar |
| + after those settle, or interleave (it's small)? |
| +6. **Devbox:** confirmed staying as-is? (Canary workflow needs Caddy |
| + wildcard DNS-01; nothing on the flagship replaces that today.) |
| +7. **SSH access:** W2/W4 need commands on the prod box (no SSM). Add an |
| + allow rule for `ssh ec2-user@52.30.232.124` for the executing session, |
| + or Paul runs those steps by hand? |