carlos / platform Public

docs: fix Task 8 rollout notes — never s3 rm --recursive the generations prefix

Review Critical: the old-key deletion step's \`s3 rm --recursive\` on
control/registry-snapshots/ deletes the NEW per-box generation trees too
(control/registry-snapshots/<box>/<stamp>.db) — S3 prefixes aren't
directories, and the step's own precondition ("both deployments run this
build") guarantees that live per-box DR history exists exactly when an
operator would run it. Replaced with a delimited list-then-delete: query
Contents (direct children only = the old flat <stamp>.db keys) and
CommonPrefixes (the per-box trees to leave alone) separately, delete only
what Contents listed, explain why --recursive is forbidden here.

Review Minor, folded in: made the "verify each box has snapshotted"
precondition executable — an \`aws s3 ls\` per deployment with the expected
shape (one <box>.db + one <box>.json per live box) and a sidecar-eyeball
instruction, instead of leaving it as unstructured prose.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 7db3f3e921853295c74232416c07be28683c73ba parent c4ba844
1 file changed, +63 −13
  • docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md +63 −13
diff --git a/docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md b/docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md
index ce724a806..a2bc2c735 100644
--- a/docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md
+++ b/docs/superpowers/plans/2026-08-20-multi-region-writer-map-and-certs.md
@@ -556,24 +556,74 @@ checklist for the rollout that follows.
`control/registry-snapshot.{db,json}` + `control/registry-snapshots/`
keys with per-box ones; the old keys are abandoned in place, not
migrated, and stay live in both deployment buckets until every box in
- both deployments has converged onto a release containing this branch
- (verify each box has written its own `control/registry-snapshot/<box>.db`
- before deleting the fixed keys — there is no CLI/console surface for
- this today, so it's a direct-bucket check, consistent with CLAUDE.md's
- carve-out for platform-internal infra work). Exact commands, one pair
- of buckets (flagship profile `keymail`, tito profile `titogo` —
- coordinates per CLAUDE.md/session memory):
+ both deployments has converged onto a release containing this branch.
+
+ **Verify first, per deployment** (no CLI/console surface for this
+ today, so it's a direct-bucket check, consistent with CLAUDE.md's
+ carve-out for platform-internal infra work):
+
+ ```bash
+ aws --profile keymail s3 ls s3://carlos-flagship-271376211898/control/registry-snapshot/
+ aws --profile titogo s3 ls s3://carlos-tito-platform-665106592142/control/registry-snapshot/
+ ```
+
+ Expect exactly one `<box>.db` + one `<box>.json` per box currently live
+ in that deployment (a single-box deployment shows one pair). Open each
+ `.json` and eyeball its `Box`/`CreatedAt` fields match the box that
+ should have written it before touching anything below.
+
+ **Deletion — do NOT use `s3 rm --recursive` on
+ `control/registry-snapshots/`.** S3 prefixes are not directories:
+ `--recursive` on that prefix deletes everything under it, including the
+ NEW per-box generation trees at `control/registry-snapshots/<box>/<stamp>.db`
+ — and the precondition above ("both deployments run this build")
+ guarantees those trees hold live, real DR history at exactly the moment
+ this step runs. A recursive delete here destroys precisely what the
+ per-box scheme exists to protect. Instead, list only the DIRECT
+ children of the prefix (the old flat `<stamp>.db` objects have no
+ further `/` in their key; the new per-box trees do) with a delimited
+ list, review that the output is old flat keys only — `CommonPrefixes`
+ in the same listing are the per-box trees, and must not appear in what
+ gets deleted — then delete exactly those keys plus the two fixed
+ top-level keys:
```bash
# flagship (carlos-flagship-271376211898)
- aws --profile keymail s3 rm s3://carlos-flagship-271376211898/control/registry-snapshot.db
- aws --profile keymail s3 rm s3://carlos-flagship-271376211898/control/registry-snapshot.json
- aws --profile keymail s3 rm s3://carlos-flagship-271376211898/control/registry-snapshots/ --recursive
+ BUCKET=carlos-flagship-271376211898
+ # Review: Contents = old flat <stamp>.db keys to delete. CommonPrefixes
+ # (query separately) = per-box trees to LEAVE ALONE.
+ aws --profile keymail s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'Contents[].Key' --output text
+ aws --profile keymail s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'CommonPrefixes[].Prefix' --output text
+ # Delete only the direct-child keys the first query listed:
+ aws --profile keymail s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'Contents[].Key' --output text | tr '\t' '\n' | \
+ while read -r key; do
+ [ -n "$key" ] && aws --profile keymail s3 rm "s3://$BUCKET/$key"
+ done
+ aws --profile keymail s3 rm "s3://$BUCKET/control/registry-snapshot.db"
+ aws --profile keymail s3 rm "s3://$BUCKET/control/registry-snapshot.json"
# tito (carlos-tito-platform-665106592142)
- aws --profile titogo s3 rm s3://carlos-tito-platform-665106592142/control/registry-snapshot.db
- aws --profile titogo s3 rm s3://carlos-tito-platform-665106592142/control/registry-snapshot.json
- aws --profile titogo s3 rm s3://carlos-tito-platform-665106592142/control/registry-snapshots/ --recursive
+ BUCKET=carlos-tito-platform-665106592142
+ aws --profile titogo s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'Contents[].Key' --output text
+ aws --profile titogo s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'CommonPrefixes[].Prefix' --output text
+ aws --profile titogo s3api list-objects-v2 --bucket "$BUCKET" \
+ --prefix control/registry-snapshots/ --delimiter / \
+ --query 'Contents[].Key' --output text | tr '\t' '\n' | \
+ while read -r key; do
+ [ -n "$key" ] && aws --profile titogo s3 rm "s3://$BUCKET/$key"
+ done
+ aws --profile titogo s3 rm "s3://$BUCKET/control/registry-snapshot.db"
+ aws --profile titogo s3 rm "s3://$BUCKET/control/registry-snapshot.json"
```
2. **teamtito runbook PR is owed at that same moment** (Task 1 ledger).