# Admin Console — Specification

Build checklist for The Word Quest admin console and the local Firestore-shaped store under [`database/`](database/). Firebase Auth / Firestore come later; this document is the product inventory and data model so screens can be built safely against a stable seam.

## Principles

- **Live game stays on static files** — [`../../app/data/`](../../app/data/) and LocalStorage via [`../../app/js/profile-store.js`](../../app/js/profile-store.js) remain the runtime path until Firebase lands.
- **`database/` is the CMS / ops model** — mutable content, users, orgs, flags, maps, audits. Seeded from `data/` and sample fixtures.
- **One client API** — [`js/database-client.js`](js/database-client.js) exposes Firestore-shaped `getDoc` / `setDoc` / `query`. Swap the backend later without rewriting screens.
- **Admin gating (pre-Firebase)** — `/admin` is deployer-known (same as [`path-waypoints.html`](path-waypoints.html)). Later: Firebase Auth + custom claims from `_meta/rbac.json`.
- **Every mutating admin action writes an audit log** once User Ops ships.

## Architecture

```
Admin screens  →  database-client.js  →  database/**/*.json  (+ LocalStorage overlay for writes)
                                      →  (later) Firestore
Live game      →  data/ + ProfileStore (unchanged for now)
```

Path mapping: `users/{uid}/progress/main` → `database/users/{uid}/progress/main.json`.

---

## Pillar A — Game studio

| Screen | Purpose | Collections |
|---|---|---|
| Game registry | List games; enable/disable; categories; caps; content `version` | `games` |
| Physics / feel tunables | Per-game key/value config (gravity, speed, sensitivity, timers, session length); preview + revert | `gameConfigs` |
| Map / level builder | Tile/wall editor (C&C-style where supported); draft → QA → live rotation | `maps`, `mapRotations` |
| Path layout editor | Fold path-waypoints into studio; island waypoints + gateway/boss options | `pathLayouts` |
| Feature flags / kill switches | Global or per-game disable without full redeploy | `featureFlags` |
| Content versioning | Review/bump `pathVersion` / game `version` and migrators ([GAME_SPECIFICATION.md](../GAME_SPECIFICATION.md) §3c) | `games`, `_meta` |
| Asset / tile QA | Spot-check tiles, allowlists, photo manifests | (reads assets + `games`) |

**Existing tool to fold in:** [`path-waypoints.html`](path-waypoints.html) → `pathLayouts/{islandId}`.

---

## Pillar B — Pedagogy / content CMS

| Screen | Purpose | Collections |
|---|---|---|
| Word browser | Search/filter by island, POS, difficulty, quality flags | `words` |
| Word editor | Definitions, examples, synonyms, antonyms, misspellings; schema validation | `words` |
| Island assignment | Move/swap words; bulk rebalance | `words`, `islands` |
| Import / export / diff | Round-trip vs shipped [`../../app/data/islands/`](../../app/data/islands/) | `words`, `contentDrafts` |
| Allowlist manager | Per-game `allowed-words` curation | `wordLists` |
| Progress analytics | Mastery, exposures, struggle words, island completion | `analyticsDaily` |
| Learner deep-dive | Per-player word table (admin upgrade of [`../../app/dashboard/`](../../app/dashboard/)) | `users/*/progress` |
| Curriculum packs | School/teacher subsets without forking the global catalog | `curriculumPacks` |
| Mascot / copy | Phrases and coach tips | (seed from `data/mascot`; optional later collection) |

---

## Pillar C — Users, orgs, compliance, billing

| Screen | Purpose | Collections |
|---|---|---|
| User directory | Search; lock/unlock/delete; GDPR export + erase | `users`, `auditLogs` |
| Player profile editor | Amend progress, path state, blocked games/categories; apply migration patches | `users/*/progress`, `users/*/pathState` |
| Relationship graph | Parent ↔ child ↔ teacher invites; accept/revoke; permission matrix | `relationships`, `invites` |
| Schools | CRUD school, seats, classes, roster import, teacher assignment | `schools`, `classes` |
| Roles & claims | `platformAdmin`, `schoolAdmin`, `teacher`, `parent`, `learner` | `users`, `_meta/rbac` |
| Audit log | Who changed what | `auditLogs` |
| Fair-use / abuse | Rate limits, reports, lock suggestions | `users`, `auditLogs` |
| Promotions / billing stubs | Coupons, plans, entitlements (Stripe later) | `promotions`, `entitlements` |
| Support tools | Read-only impersonation default; reset; resend invite | `users`, `invites` |

---

## Pillar D — Platform essentials

1. **Ops home / health** — content version, flag state, kill switches, last seed/deploy notes.
2. **Release & content publish** — draft → review → publish for words, maps, configs.
3. **Migration console** — dry-run / apply profile migrators to one user or cohort.
4. **Moderation / safety** — report queue placeholders, age gates.
5. **Communications** — in-app banners targeted by school/role.
6. **A/B / experiments** — cohorts on tunables or map pools.
7. **Telemetry dictionary** — named events games must emit.
8. **Admin RBAC matrix** — `_meta/rbac.json`.
9. **Backup / restore** — export/import `database/` snapshots; overlay export from the client.
10. **Seed / sync tools** — [`../tools/seed-database.mjs`](../tools/seed-database.mjs); later CMS → static island JSON for CDN.

---

## Roles (RBAC)

Documented in [`database/_meta/rbac.json`](database/_meta/rbac.json). Summary:

| Role | Scope |
|---|---|
| `platformAdmin` | Full read/write all collections; publish; GDPR erase; flags |
| `schoolAdmin` | Own school, classes, roster, school-scoped analytics |
| `teacher` | Assigned classes; view learner progress; curriculum packs (own) |
| `parent` | Linked children; view progress; category/game bans for children |
| `learner` | Own profile/progress only (no admin UI) |

Impersonation: `platformAdmin` only; default **read-only**; write impersonation requires explicit elevation + audit.

---

## Collections (Firestore-shaped)

| Collection | Doc id | Notes |
|---|---|---|
| `games` | gameId | Registry entry (name, enabled, categories, caps, version) |
| `gameConfigs` | gameId | Tunables blob + defaults |
| `maps` | mapId | Builder output; `status`: draft \| qa \| live \| archived |
| `mapRotations` | gameId | Ordered live map ids |
| `pathLayouts` | islandId (`1`…`10`) | Waypoints + optional gateway/boss overrides |
| `featureFlags` | flagId | `{ enabled, scope, targets? }` |
| `words` | wordId (e.g. `i1_w1`) | Full vocab document |
| `islands` | islandId | Meta without embedded word arrays |
| `wordLists` | listId | Allowlists / curated sets |
| `curriculumPacks` | packId | School/teacher subsets |
| `contentDrafts` | draftId | Unpublished CMS edits |
| `analyticsDaily` | `YYYY-MM-DD` or scoped id | Pre-aggregates |
| `users` | uid | Account, roles, lock state |
| `users/{uid}/progress` | `main` | Progress blob (ProfileStore-compatible shape) |
| `users/{uid}/pathState` | islandId | Per-island path plan |
| `relationships` | relId | parent/child/teacher edges |
| `invites` | inviteId | Pending links |
| `schools` | schoolId | Org (`type`: day_school \| afternoon_school \| other) |
| `classes` | classId | Belongs to school |
| `tutorPractices` | practiceId | Solo private-tutor org |
| `parentalControls` | childUid | Time limits, locks, device policy |
| `playSessions` | sessionId | Metered learner play intervals |
| `deviceSightings` | sightingId | UA sightings per child |
| `userAgentCatalog` | catalogId | Admin-maintained UA labels |
| `lessons` | lessonId | Reusable teacher lesson templates |
| `lessonRuns` | runId | Delivered lesson instances |
| `homework` | homeworkId | Assignments |
| `learnerNotes` | noteId | Per-teacher learner customisation |
| `entitlements` | entId | Plan seats / unlocks |
| `promotions` | promoId | Coupons / campaigns |
| `auditLogs` | logId | Append-oriented admin events |

Portal product detail: [`../portal/PORTAL_SPEC.md`](../portal/PORTAL_SPEC.md).

Indexes to implement in Firestore later: see [`database/_meta/indexes.json`](database/_meta/indexes.json).

---

## Phased delivery

1. **Scaffold (this pass)** — this doc, `database/`, `database-client.js`, seed tool.
2. **Admin shell** — nav, RBAC stubs, audit writer, overlay export UI.
3. **Pedagogy CMS** — highest leverage on existing island JSON.
4. **User / org / relationships** — before parent/teacher launch.
5. **Game tunables + map builder** — game-by-game.
6. **Firebase swap** — Auth + claims + Firestore backend; retire LocalStorage overlay as source of truth.

## Out of scope until later

- Firebase project, Security Rules, Cloud Functions.
- Full admin UI for every screen.
- Migrating the live game off `data/` / LocalStorage.
- Wiring every game’s physics to remote `gameConfigs` (schema first).

## Related paths

| Path | Role |
|---|---|
| [`database/README.md`](database/README.md) | Store conventions |
| [`js/database-client.js`](js/database-client.js) | Client API |
| [`../tools/seed-database.mjs`](../tools/seed-database.mjs) | Seed / refresh samples |
| [`../../app/js/profile-store.js`](../../app/js/profile-store.js) | Live progress seam (maps to `users/*/progress`) |
| [`path-waypoints.html`](path-waypoints.html) | Current path editor |
