veza/docs/SOFT_LAUNCH_BETA_2026_CHECKLIST.md
senke 112c64a22b
Some checks are pending
Veza CI / Backend (Go) (push) Waiting to run
Veza CI / Frontend (Web) (push) Waiting to run
Veza CI / Rust (Stream Server) (push) Waiting to run
Veza CI / Notify on failure (push) Blocked by required conditions
E2E Playwright / e2e (full) (push) Waiting to run
Security Scan / Secret Scanning (gitleaks) (push) Waiting to run
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 22:38:12 +02:00

5.9 KiB

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