veza/docs/SOFT_LAUNCH_BETA_2026_CHECKLIST.md

151 lines
5.9 KiB
Markdown
Raw Permalink Normal View History

feat(soft-launch): cohort tooling + email template + monitor + checklist The soft-launch report doc (SOFT_LAUNCH_BETA_2026.md) had the narrative — cohort table, email body inline, monitoring list, acceptance gate. But the operational pieces were notes-to-self : "add migration if missing", "Typeform to-do", "schema TBD". The operator was supposed to assemble them on the day, which on a soft- launch day is the worst possible time. Added the missing 6 pieces so the day-of work is "tick boxes", not "build the tooling" : * migrations/990_beta_invites.sql — schema with code (16-char base32-ish), email, cohort label, used_at, expires_at + 30d default, sent_by FK with ON DELETE SET NULL. Three indexes : unique on code (signup-path lookup), cohort (post-launch attribution report), partial expires_at WHERE used_at IS NULL (cleanup cron). * scripts/soft-launch/validate-cohort.sh — sanity check on the operator's CSV : header form, malformed emails, duplicates, cohort distribution (≥50 total / ≥5 creators / ≥3 distinct labels), optional collision check against existing users. Exit codes 0 / 1 (block) / 2 (warn-but-proceed). Hard checks block, soft checks let the operator override with FORCE=1. * scripts/soft-launch/send-invitations.sh — split-phase : step 1 (default) inserts beta_invites rows + renders one .eml per recipient under scripts/soft-launch/out-<date>/ step 2 (SEND=1) dispatches via $SEND_CMD (msmtp by default) so the operator can review the rendered emls before sending 100 emails. Per-recipient transactional INSERT so a partial failure doesn't poison the table. Failed inserts logged with the offending email so the operator can rerun on the subset. * templates/email/beta_invite.eml.template — proper MIME multipart (text + HTML) eml ready for sendmail-compatible piping. French copy aligned with the éthique brand (no FOMO, no urgency manipulation, no "limited spots" framing). * scripts/soft-launch/monitor-checks.sh — polls the 6 acceptance- gate signals defined in SOFT_LAUNCH_BETA_2026.md §"Acceptance gate" : testers signed up, Sentry P1 events, status page, synthetic parcours, k6 nightly age, HIGH issues. Each gate independently emits ✅ / 🔴 / ⚪ (last for "couldn't check"). Verdict on stdout. LOOP=1 keeps polling every CHECK_INTERVAL seconds. Designed for cron + tmux, not for an interactive UI. * docs/SOFT_LAUNCH_BETA_2026_CHECKLIST.md — pre-flight gate that must reach 100% green before the first invitation goes out. T-72h section (database, cohort, email infra, redemption path, monitoring, comms), D-day section (last-hour, send, hour-1, every-4h), 18:00 UTC decision call section. Linked back to the bigger SOFT_LAUNCH_BETA_2026.md so the operator can navigate between the "what" (report) and the "how / has-everything- been-checked" (this checklist) without losing context. What still requires the operator on the day : - Build the cohort CSV (curate emails from real sources) - Create the Typeform feedback form ; paste its URL into the eml template once known - Configure msmtp / sendmail ($SEND_CMD) - Press the send button - Show up at 18:00 UTC for the decision call Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 20:38:12 +00:00
# Soft-launch beta — pre-flight checklist
> Operational checklist that must reach 100% green before the first
> invitation goes out. Companion to `docs/SOFT_LAUNCH_BETA_2026.md`
> (the bigger picture). This file is purely the "before you press
> send, has every gate been verified?" view.
The whole reason the soft-launch is "soft" is that it lets you catch
infrastructure surprises with 50 testers instead of 50 000. To get
that benefit, the infrastructure has to actually work BEFORE the
invitations land. This checklist is the gate.
## T-72h checklist (3 days before send)
### Database
- [ ] `migrations/990_beta_invites.sql` applied to staging.
Verify with :
```bash
psql "$STAGING_DATABASE_URL" -c "SELECT count(*) FROM beta_invites;"
```
Expected : `0` (table exists, empty).
- [ ] Same migration applied to prod (whenever prod tag goes out).
- [ ] Backup-freshness OK on both environments :
```bash
pgbackrest --stanza=veza info | head -20
```
Most recent full or diff < 24 h old.
### Cohort CSV
- [ ] CSV file built from the operator's chosen sources (mailing list +
contacts + community partners). Format per
`scripts/soft-launch/validate-cohort.sh` header.
- [ ] `validate-cohort.sh` returns exit 0 (or exit 2 with explicit
operator acknowledgement of the warnings).
- [ ] Distribution sanity : `≥ 5` creators, `≥ 20` listeners, `≥ 3`
distinct cohort labels, `≥ 50` total rows.
### Email infrastructure
- [ ] SMTP credentials live in the operator's machine `~/.msmtprc`
(or whatever `SEND_CMD` resolves to).
- [ ] `templates/email/beta_invite.eml.template` reviewed — wording,
cohort variable, code variable.
- [ ] Test send to operator's own email :
```bash
echo "ops@veza.fr,test-cohort,ops@veza.fr" > /tmp/me.csv
DATABASE_URL=$STAGING_DATABASE_URL FRONTEND_URL=https://staging.veza.fr \
SEND=1 bash scripts/soft-launch/send-invitations.sh /tmp/me.csv
```
Verify the eml renders correctly in your mail client (links
clickable, fonts loaded, no `{{TO_ADDR}}` literals leaking).
### Backend invite-redemption path
- [ ] Visit `https://staging.veza.fr/signup?invite=<test-code>`.
Expected : signup form pre-fills the code, refuses to submit
without it, marks the invite as `used_at = NOW()` after success.
- [ ] Try an invalid code → form rejects with a clear error message.
- [ ] Try the same code twice → second attempt rejects (one-time use).
- [ ] Try an expired code → form rejects with "expired".
### Acceptance-gate monitoring
- [ ] Run `monitor-checks.sh` once on staging — every gate either ✅
or ⚪ (unknown), no 🔴.
```bash
DATABASE_URL=$STAGING_DATABASE_URL \
SENTRY_AUTH_TOKEN=... \
PROM_URL=https://prom.veza.fr \
bash scripts/soft-launch/monitor-checks.sh
```
- [ ] Schedule the cron run (or tmux session) so the gate state is
visible during the bêta window without manual re-run.
### Communications
- [ ] Discord `#beta-feedback` channel created, ground rules pinned.
- [ ] Typeform feedback form created ; URL pasted into
`templates/email/beta_invite.eml.template` if not already in the
cohort label.
- [ ] Status page maintenance window declared for the duration —
"elevated alerting may occur during beta period."
- [ ] Operators on duty for the day rota'd in the calendar (every 4 h
shift, primary + backup).
## D-day checklist (the day of send)
### Last hour before send
- [ ] Most recent k6 nightly green (within 30 h).
- [ ] No pending high-severity Sentry issue.
- [ ] No PagerDuty incident open.
- [ ] HAProxy + backend healthchecks green :
```bash
curl -s https://staging.veza.fr/api/v1/health | jq .status
```
- [ ] MinIO drives all online ; pgBackRest drill ran successfully in
the last 7 days.
### Send
- [ ] `validate-cohort.sh` exit code 0 (or 2 with explicit override).
- [ ] `send-invitations.sh` in DRY-RUN mode : eml output dir reviewed.
- [ ] `send-invitations.sh` with `SEND=1` : dispatch.log reviewed
after run, `0` failed dispatches.
- [ ] First three invitees received the email within 5 min (manual
check on three different domains : gmail / proton / one custom).
### Hour 1 post-send
- [ ] First sign-up landed (`SELECT count(*) FROM beta_invites WHERE
used_at IS NOT NULL;` returns ≥ 1).
- [ ] No spike in 5xx on Grafana "Veza API Overview".
- [ ] Discord `#beta-feedback` has at least one "I'm in" message.
### Every 4 h during the bêta window
- [ ] Re-run `monitor-checks.sh` (or the cron wakes you).
- [ ] Triage any HIGH-severity report within 1 h (per
`docs/SOFT_LAUNCH_BETA_2026.md` §"Issue triage matrix").
- [ ] Update the issues-reported table in
`docs/SOFT_LAUNCH_BETA_2026.md` so the decision call has fresh data.
## D+0 18:00 UTC — decision call
- [ ] Tech lead, product lead, on-call engineer all on the call.
- [ ] `monitor-checks.sh` final run shown live ; verdict screenshotted.
- [ ] Each acceptance-gate row from `SOFT_LAUNCH_BETA_2026.md`
§"Acceptance gate" walked through verbally.
- [ ] Unanimous GO or any one NO-GO documented in the meeting notes.
- [ ] Decision logged in `docs/SOFT_LAUNCH_BETA_2026.md` §"Take-aways".
If GO : the v2.0.0-public tag goes out the next morning.
If NO-GO : the meeting decides scope of fix-pass + new acceptance date.
## Linked artefacts
- `docs/SOFT_LAUNCH_BETA_2026.md` — the bigger picture (cohort
definition, email template inline, day timeline, monitoring list,
acceptance gate, decision protocol)
- `migrations/990_beta_invites.sql` — schema this depends on
- `scripts/soft-launch/validate-cohort.sh` — pre-send sanity check
- `scripts/soft-launch/send-invitations.sh` — batch insert + send
- `scripts/soft-launch/monitor-checks.sh` — live gate poll
- `templates/email/beta_invite.eml.template` — the email recipients
receive
- `docs/GO_NO_GO_CHECKLIST_v2.0.0_PUBLIC.md` — the v2.0.0 checklist
this unblocks