Add public-release plan (phases 7-10)
Phases: public repo & Docker (7), guest-first optional accounts (8), production hardening (9), Render deploy (10). Confirmed decisions and per-phase open questions recorded in each file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFsGHju9szibJJa2YJcdbg
This commit is contained in:
co-authored by
Claude Fable 5
parent
db9f904222
commit
466d7bc0e4
@@ -0,0 +1,71 @@
|
||||
# Phase 8 — Optional accounts & multi-user
|
||||
|
||||
**Goal:** turn the single-user app into a multi-user one where **accounts are optional**:
|
||||
a visitor can start playing instantly as a guest, and can register (email + password) at any
|
||||
point to keep their adventures across devices/browsers. This is the largest phase — it touches
|
||||
every router and most tables.
|
||||
|
||||
## Decisions (confirmed)
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Auth method | **Email + password, optional** — guest sessions work without an account |
|
||||
| Signup policy | **Open signup** (rate-limited) |
|
||||
| LLM API keys | **BYOK + shared demo key** — users can paste their own key; users without one get limited turns on a server-funded key |
|
||||
|
||||
**Ask before implementing:**
|
||||
- Demo-key specifics: which provider/key funds it, model whitelist (free models only?),
|
||||
per-user turn/day cap, what the "out of demo turns" message says.
|
||||
- Guest data retention: how long before unclaimed guest data is deleted (suggestion: 30 days
|
||||
of inactivity).
|
||||
- Password reset: skip for v1, or implement email-based reset (requires an email provider)?
|
||||
|
||||
## Data model
|
||||
|
||||
- [ ] `User` table: id, email (nullable — null means guest), password_hash (nullable),
|
||||
created_at, last_seen_at, is_guest flag (derivable from email; keep explicit for clarity).
|
||||
- [ ] Add `user_id` FK to: `Adventure`, `Scenario`, `Script`, `Settings` (and anything else
|
||||
global today — audit `models.py`). Story cards/actions inherit scope via their parent.
|
||||
- [ ] Settings becomes **per-user** (endpoint URL, API key, models, memory-bank config).
|
||||
API key **encrypted at rest** (Fernet with a server-side `SECRET_KEY` env var).
|
||||
- [ ] Migration (in `migrations.py` style): create a "local user", assign all existing rows to
|
||||
it — a fresh clone/local install keeps working exactly as before.
|
||||
- [ ] Demo/starter scenarios: mark as `user_id = NULL` + `is_public` so everyone sees them
|
||||
(decide exact mechanism when implementing; seed via `seed_demo.py`).
|
||||
|
||||
## Auth & sessions
|
||||
|
||||
- [ ] Guest flow: first API call with no session → create guest User, set a signed, long-lived
|
||||
httpOnly session cookie. No signup wall anywhere.
|
||||
- [ ] Register: email + password (hashed with bcrypt/argon2) **upgrades the current guest user
|
||||
in place** — same user_id, data automatically kept.
|
||||
- [ ] Login: standard session issue; logging in from a fresh guest session with existing account
|
||||
discards the empty guest (or merges — ask if guest has data).
|
||||
- [ ] Session middleware/dependency: every router handler resolves `current_user`; **every query
|
||||
filtered by `user_id`** (this is the bulk of the diff — go router by router).
|
||||
- [ ] Rate limits on register/login endpoints (brute-force protection).
|
||||
- [ ] Local/self-hosted mode stays frictionless: single auto-created local user, no login UI
|
||||
unless `MULTI_USER=true` (env var) — resume demo runs multi-user, local clones don't care.
|
||||
|
||||
## Shared demo key (BYOK fallback)
|
||||
|
||||
- [ ] Server env vars: `DEMO_API_KEY`, `DEMO_ENDPOINT_URL`, `DEMO_MODEL_WHITELIST`,
|
||||
`DEMO_TURNS_PER_DAY`.
|
||||
- [ ] If a user has no API key configured: use demo key, restrict model picker to the whitelist,
|
||||
count turns per user per day, friendly error + "add your own key in Settings" when capped.
|
||||
- [ ] Turn counting includes memory-bank background calls (or disable memory bank on demo key —
|
||||
decide when implementing).
|
||||
|
||||
## Frontend
|
||||
|
||||
- [ ] Auth UI: register/login modal or page, "Save your progress" nudge for guests (subtle,
|
||||
e.g. in the header), logout, account menu.
|
||||
- [ ] `api.js`: send cookies (`credentials: include`), handle 401 → re-establish guest session.
|
||||
- [ ] Settings page: per-user; show demo-key status ("Using shared demo key — N turns left today").
|
||||
|
||||
## Exit criteria
|
||||
|
||||
Two different browsers hit the deployed app: each gets its own guest world (adventures invisible
|
||||
to the other), both can play immediately on the demo key. One registers mid-adventure and its
|
||||
data survives; logging in from the other browser shows the same account data. Local
|
||||
`start.ps1` / `docker compose up` still works with zero auth friction.
|
||||
Reference in New Issue
Block a user