Skip to content

Commit ec7a070

Browse files
committed
chore: doc
1 parent c4c6757 commit ec7a070

1 file changed

Lines changed: 74 additions & 11 deletions

File tree

docs/prod-branch.md

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# The `prod` branch — public AMA deployment
22

3-
**Status:** temporary. Exists only for the window between the M4 AMA cutover and the moment one
4-
remaining client finishes the AMA they are currently running on the canary bot.
3+
**Status:** temporary, with a target end date. Exists only for the window between the M4 AMA cutover
4+
and **2026-08-13**, when the one remaining client finishes the AMA they are running on the canary
5+
bot. On that date this deployment folds _into_ the canary one (see [Convergence](#convergence)) —
6+
that direction is decided, not open.
57

68
## Why there are two deployments
79

@@ -90,14 +92,75 @@ out of `canary.automoderator.app`.
9092

9193
## Convergence
9294

93-
When the client finishes their AMA:
95+
**Direction: this deployment folds into the canary one on 2026-08-13.** The canary deployment
96+
(`chatsift-v3`, `/home/deploys/repos/canary`, branch `main`) survives and takes over the public AMA
97+
token; `chatsift-prod` is deleted.
9498

95-
1. Migrate their now-historical AMA rows from the canary database to this one. Historical rows are
96-
far safer to move than in-flight ones — that timing is the entire point of this arrangement.
97-
2. Shut down the canary deployment's `ama-bot` and retire `canary.automoderator.app` /
98-
`api-canary.automoderator.app`, or keep them as a genuine canary.
99-
3. Decide whether ModMail and the monitoring stack move into this deployment, or this deployment's
100-
AMA folds back into the canary one. Whichever database you keep sets the migration direction.
101-
That decision does not have to be made now.
99+
That direction is chosen because it moves the least, and moves the safest things:
102100

103-
Once converged, delete this branch rather than merging it.
101+
- **The client's rows never move at all.** They are already in the surviving database. The
102+
alternative direction would mean migrating them a second time.
103+
- The surviving deployment keeps the awkward, stateful pieces in place — the #216 partner ModMail
104+
instances and their per-partner tokens, Prometheus history, Grafana dashboards, Dozzle's bcrypt
105+
users volume. Re-homing those is strictly more work than moving a few days of AMA rows.
106+
- Only public-AMA data created between the cutover and 2026-08-13 has to move, and AMA sessions are
107+
short-lived events, so that is a small set. This deployment runs no `modmail-bot`, so every ModMail
108+
table in its database is empty — nothing to reconcile there.
109+
110+
### The one real cost: identity-column collisions
111+
112+
Every AMA table keys on `INTEGER GENERATED BY DEFAULT AS IDENTITY`, so both databases have rows
113+
numbered from 1 and the merge needs an id remap across the whole FK graph:
114+
115+
```
116+
ama_sessions (id)
117+
├── ama_prompt_data .ama_id → sessions.id (UNIQUE; own identity id)
118+
├── ama_question_tags .ama_id → sessions.id (own identity id; UNIQUE (id, ama_id))
119+
└── ama_questions .ama_id → sessions.id (own identity id; UNIQUE (id, ama_id))
120+
├── ama_question_askers .question_id → questions.id (own identity id)
121+
└── ama_question_tag_assignments (question_id, ama_id) → ama_questions (id, ama_id)
122+
(tag_id, ama_id) → ama_question_tags (id, ama_id)
123+
```
124+
125+
`GENERATED BY DEFAULT` rather than `ALWAYS` is what makes this tractable: explicit ids can be
126+
inserted without disabling anything. Pick a per-table offset above the surviving database's current
127+
`max(id)`, shift every prod id and every referencing FK by that same offset, insert parent-first in
128+
the order above, then `ALTER TABLE … ALTER COLUMN id RESTART WITH …` on each sequence.
129+
130+
`scripts/import-legacy-ama.mjs` is the precedent to follow: it emits a single `BEGIN`/`COMMIT` around
131+
a plpgsql `DO` block to stdout for review rather than connecting to a database, and is applied with
132+
`psql -v ON_ERROR_STOP=1`. Do the same here.
133+
134+
Unique constraints to be aware of while merging:
135+
136+
- `ama_sessions.share_token` and `ama_prompt_data.prompt_message_id` — random tokens and Discord
137+
snowflakes respectively, so collisions are not a practical concern.
138+
- `dashboard_grants (guild_id, user_id)` — the one genuine risk if any guild ended up with both bots.
139+
Insert with `ON CONFLICT DO NOTHING`.
140+
141+
### Steps
142+
143+
1. Confirm the client's AMA is `ended`, then stop **both** `ama-bot` containers so nothing writes
144+
mid-merge.
145+
2. Dump this deployment's AMA tables plus `dashboard_grants`, remap ids as above, apply to the canary
146+
database inside one transaction.
147+
3. In the canary checkout, set `AMA_BOT_TOKEN` to the **public** `@AMA#5595` token and merge this
148+
branch's `.env.public` changes into `main``API_URL_PROD`, `FRONTEND_URL_PROD`, and `CORS`, but
149+
**keep `API_PORT=7004`**, since the surviving deployment is already on that port.
150+
4. In `chatsift/caddy`, repoint `api.automoderator.app` from `:7005` to `:7004` and delete the
151+
`api-canary.automoderator.app` block.
152+
5. `./compose up -d` in the canary checkout; `./compose down -v` in the prod one; delete
153+
`/home/deploys/repos/prod`.
154+
6. Delete this branch. Its `docker-compose.yml` trim is throwaway, but note that step 3 means the
155+
`.env.public` half of it **does** belong on `main` — don't discard the branch before that lands.
156+
157+
### After the fold
158+
159+
- **The client's historical AMA messages become uneditable.** They were authored by the canary
160+
application, and the surviving API holds only the public token, so `updateQuestion`, `mergeShared`,
161+
and `updateAMA`'s prompt edit will get a 403 on those specific old rows. The session is over, so
162+
this is cosmetic — but it is permanent, and worth saying out loud rather than discovering later.
163+
- **The client needs `@AMA#5595` invited** to their guild for any future AMA; the canary application
164+
will no longer be running anywhere.
165+
- Their dashboard session survives the move to `automoderator.app` without a re-login, because the
166+
cookie is scoped to the bare `ROOT_DOMAIN` and both deployments share an `ENCRYPTION_KEY`.

0 commit comments

Comments
 (0)