diff --git a/Battl Builders Beta %E2%80%94 Go-Live %26 Invite Playbook.-.md b/Battl Builders Beta %E2%80%94 Go-Live %26 Invite Playbook.-.md new file mode 100644 index 0000000..01fcf3e --- /dev/null +++ b/Battl Builders Beta %E2%80%94 Go-Live %26 Invite Playbook.-.md @@ -0,0 +1,165 @@ +# 🚀 Battl Builders Beta — Go-Live & Invite Playbook + +This document describes how the Battl Builders beta signup system works in **capture-only mode**, and exactly what needs to be flipped when we are ready to invite users. + +--- + +## 1. Current State — Capture-Only Mode + +**Goal:** +Collect beta signups publicly without sending emails or granting access. + +### What happens on signup +- A user record is created (or updated) in `users` +- User is stored as: + - `role = BETA` + - `is_active = false` +- No auth tokens are created +- No emails are sent + +This allows us to: +- Share the signup link publicly +- Collect interest safely +- Avoid accidental early access + +--- + +## 2. Environment Variables (Docker) + +### Capture-only flag +Controls whether beta signup only stores users or also generates tokens and emails. + +APP_BETA_CAPTUREONLY=true + +### Email kill-switch (recommended) +Global safeguard to disable outbound email. + +APP_EMAIL_OUTBOUND_ENABLED=false + +Even if APP_BETA_CAPTUREONLY is false, this flag will still prevent emails. + +--- + +## 3. Docker Compose Example + +services: + battl-builder-api: + image: battl-builder-api:latest + environment: + - SPRING_PROFILES_ACTIVE=prod + - APP_BETA_CAPTUREONLY=true + - APP_EMAIL_OUTBOUND_ENABLED=false + - APP_PUBLICBASEURL=https://battl.builders + +Restart containers after changing environment variables. + +--- + +## 4. Cloudflare DNS Notes + +Cloudflare is used for DNS only. + +Ensure: +- battl.builders → frontend (Next.js) +- api.battl.builders → Spring API (or same domain if proxied) + +The public base URL must match the frontend domain: + +APP_PUBLICBASEURL=https://battl.builders + +This value is used when generating magic login links. + +--- + +## 5. Go-Live Checklist (Invite Day) + +### Step 1 — Disable capture-only mode +Allows token creation and email sending. + +APP_BETA_CAPTUREONLY=false + +### Step 2 — Enable outbound email + +APP_EMAIL_OUTBOUND_ENABLED=true + +Restart the API container after changing environment variables. + +--- + +## 6. Inviting Existing Beta Users (CLI) + +Eligible beta users: +- role = BETA +- is_active = false + +### Dry Run (recommended) +Creates tokens and logs output but does not send emails. + +./mvnw spring-boot:run -Dspring-boot.run.arguments="--app.beta.invite.run=true --app.beta.invite.dryRun=true --app.beta.invite.limit=25 --app.beta.invite.tokenMinutes=60" + +### Send Real Invites + +./mvnw spring-boot:run -Dspring-boot.run.arguments="--app.beta.invite.run=true --app.beta.invite.dryRun=false --app.beta.invite.limit=0 --app.beta.invite.tokenMinutes=60" + +Notes: +- limit=0 invites all eligible beta users +- tokenMinutes controls magic link expiration + +--- + +## 7. What Happens After Invite + +When a user clicks their magic link: +- Token is validated and consumed +- User is promoted from BETA to USER +- User becomes active +- JWT is issued +- User is logged in immediately +- last_login_at and login_count are updated + +No manual cleanup required. + +--- + +## 8. Post-Invite Operating Modes + +### Option A — Manual invite waves (recommended) +Continue collecting beta signups without auto-emailing. + +APP_BETA_CAPTUREONLY=true +APP_EMAIL_OUTBOUND_ENABLED=true + +### Option B — Continuous auto-invites +Every new signup receives a magic link immediately. + +APP_BETA_CAPTUREONLY=false +APP_EMAIL_OUTBOUND_ENABLED=true + +--- + +## 9. Useful Admin Queries + +View waiting beta users: + +select id, email, created_at +from users +where role = 'BETA' + and is_active = false +order by created_at asc; + +--- + +## 10. Summary + +Capture-Only Mode: +- Public signup enabled +- Users stored as inactive BETA +- No emails +- No tokens + +Invite Mode: +- Flip 2 environment variables +- Run 1 CLI command +- Users self-promote on first login + +This setup is intentional, safe, and production-ready.