feat(platform-api): split lightweight platform service from Lab image
New platform/api/ service owns students, cohorts, curriculum, progress, scenario attempts, and student/admin sessions. No k3s, no --privileged, no terminal runtime — starts instantly, unlike the old identity service which booted an unused k3s cluster just to serve roster/progress APIs. Provisioner calls (student and admin) are consolidated here too, in provisioner-client.js, so it's the only service that talks to the Provisioner directly.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# RootNode Academy — Platform API (Phase 2B)
|
||||
|
||||
Lightweight service: no k3s, no `--privileged`, no Lab terminal runtime. See
|
||||
`docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` for the design; this is the operational reference.
|
||||
|
||||
## Configuration reference
|
||||
|
||||
| Variable | Required | Meaning |
|
||||
|---|---|---|
|
||||
| `PLATFORM_DB_URL` | no (defaults to local dev Postgres) | Postgres connection string |
|
||||
| `PROVISIONER_URL` | no | Provisioner base URL |
|
||||
| `PROVISIONER_SHARED_SECRET` | **yes** | Internal Provisioner auth — process refuses to start without it |
|
||||
| `ADMIN_PASSWORD` | **yes** | Instructor login credential — process refuses to start without it. Verified via scrypt+timing-safe compare, never stored or logged in plaintext |
|
||||
| `PLATFORM_API_PORT` | no | Listen port, default 4300 |
|
||||
| `FRONTEND_DIST_DIR` | no | Where the built frontend lives — set by the Dockerfile, override for local non-Docker dev |
|
||||
| `SCENARIOS_DIR` / `BUNDLES_DIR` / `CURRICULUM_PATH_FILE` | no | Override the default `scenarios/` locations, mainly for local dev outside Docker |
|
||||
|
||||
## Local dev
|
||||
|
||||
```bash
|
||||
cd platform
|
||||
echo "PROVISIONER_SHARED_SECRET=$(openssl rand -hex 32)" > .env
|
||||
echo "ADMIN_PASSWORD=$(openssl rand -hex 12)" >> .env
|
||||
docker compose -f docker-compose.dev.yml build
|
||||
docker compose -f docker-compose.dev.yml up -d
|
||||
```
|
||||
|
||||
Everything is reachable through the Gateway at `http://localhost:4200` — students at `/`,
|
||||
instructors at `/admin`. Platform API itself isn't meant to be hit directly by a browser (same
|
||||
boundary as the Provisioner relative to Platform API), though nothing stops you from curling
|
||||
it directly at `:4300` for local debugging.
|
||||
|
||||
## SQLite migration
|
||||
|
||||
One-time cutover, run against the real data volume:
|
||||
|
||||
```bash
|
||||
docker run --rm -v <identity-data-volume>:/data \
|
||||
-e SQLITE_PATH=/data/progress.db -e PLATFORM_DB_URL=postgres://postgres:postgres@<host>:5433/rootnode_platform \
|
||||
<platform-api-image> node migrate-sqlite.js
|
||||
```
|
||||
|
||||
Always backs up the SQLite file first, is safe to re-run, and writes a JSON report — see
|
||||
`docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` §2/§3 for the full guarantees and rollback
|
||||
procedure.
|
||||
|
||||
## Tests
|
||||
|
||||
`platform/test/e2e-phase2a.js` (student-flow regression, cookie-based) and
|
||||
`platform/test/e2e-phase2b.js` (the classroom acceptance workflow: cohort → students →
|
||||
curriculum → Prepare Labs → complete scenarios → reset → destroy-labs → progress survives).
|
||||
Both need the full stack up and `ADMIN_PASSWORD` set — see `platform/README.md`.
|
||||
|
||||
## Known limitations
|
||||
|
||||
See `docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md` §13 — in-memory sessions (a restart logs
|
||||
everyone out), exam mode's live bookkeeping stays Lab-local, single shared admin credential
|
||||
rather than per-instructor accounts.
|
||||
Reference in New Issue
Block a user