docs(portal): add "Going to prod" checklist (migration, SECRET_KEY, exposure)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -132,6 +132,32 @@ live data, all from cache.
|
|||||||
magic-link (passwordless email) and/or accounts, proper sessions, password
|
magic-link (passwordless email) and/or accounts, proper sessions, password
|
||||||
reset, and likely auth for the *internal* app too. Reverse-proxy + TLS posture.
|
reset, and likely auth for the *internal* app too. Reverse-proxy + TLS posture.
|
||||||
|
|
||||||
|
## Going to prod (M1)
|
||||||
|
|
||||||
|
1. **Run the migration on the prod DB** — `migrate_add_client_portal.py` adds
|
||||||
|
`projects.client_id` (the new tables auto-create via `create_all`). Skipping it
|
||||||
|
500s anything that touches `Project.client_id`. This is the silent killer.
|
||||||
|
```bash
|
||||||
|
docker compose exec web-app python3 backend/migrate_add_client_portal.py
|
||||||
|
```
|
||||||
|
2. **Set a real `SECRET_KEY`** in the prod env (compose). The portal signs session
|
||||||
|
cookies with it; the insecure dev default (it logs a warning at boot) is
|
||||||
|
forgeable. Non-negotiable for an internet-facing portal.
|
||||||
|
3. **SLMM_BASE_URL** — prod base compose already points at `:8100` (correct; the
|
||||||
|
`:9100` mismatch is a dev-only override quirk). For full live data (L1/L10 +
|
||||||
|
chart backfill) prod SLMM must be on the `dev` build with its migrations
|
||||||
|
(`migrate_add_ln_percentiles`, `migrate_add_monitor_enabled`) and **keepalive on**
|
||||||
|
for the client's units — otherwise the portal degrades gracefully (cards show
|
||||||
|
`--`, chart empty), it just isn't fully populated.
|
||||||
|
4. **Seed real clients** with the CLI (`backend/portal_admin.py`): `create-client`
|
||||||
|
→ `link-project` (a real sound project with an active SLM assignment) →
|
||||||
|
`mint-link` → send the client the printed URL (shown once).
|
||||||
|
5. **Exposure** — portal routes are auth-gated, but port 8001 still serves the
|
||||||
|
whole *internal* app with no auth. Before real clients are on it, the portal
|
||||||
|
should sit behind the reverse proxy with only `/portal/*` exposed (or the app
|
||||||
|
restricted). This is the point where the parked reverse-proxy/TLS work becomes
|
||||||
|
load-bearing.
|
||||||
|
|
||||||
## Security notes
|
## Security notes
|
||||||
|
|
||||||
- Portal is auth-gated from day one (even the interim gate) — never wide-open like
|
- Portal is auth-gated from day one (even the interim gate) — never wide-open like
|
||||||
|
|||||||
Reference in New Issue
Block a user