-
released this
2026-08-04 11:58:59 +00:00 | 2 commits to main since this releasev0.1.9 — v0.4 Milestone Release: Operator Tier (Cohort Dashboard + Auth + Postgres)
Milestone: v0.4 (Operator tier — cohort dashboard, auth, Postgres)
Type: Feature milestone
Previous milestone: v0.3 (Mastery scoring + competency rubrics + verifiable credentials) — v0.1.5
This release: v0.1.9 (merged to main)What's in this milestone
The v0.4 operator tier — a cohort dashboard for training operators, operator auth, and Postgres backing store — layered on top of the v0.3 mastery layer. The learner-facing surface carries forward unchanged (SQLite, voice loop, mastery gates, VC issuance). v0.4 adds the operator surface: Postgres 16 in the existing LXC CT, operator auth (argon2id + signed cookies), a cohort aggregation pipeline (k-anonymity ≥ 10, 7-day windows), and a React cohort dashboard with 3 k-anonymized views.
Phases
Phase Tag Description P0 v0.1.6 Pre-execution — 8 activated REQs, research, plan, grill (6 MUST) P1 v0.1.7 Operator foundation — Postgres 16, asyncpg, auth, VC migration, bootstrap CLI P2 v0.1.8 Cohort dashboard — aggregation pipeline, 3-view dashboard, SPA fallback P3 v0.1.9 Final review + audit + milestone ship (= this milestone release) Requirements Covered (8/8)
REQ-ID Requirement Phase REQ-MT-01 Operator-tier Postgres store (5 tables, asyncpg pool, PgStore) P1 REQ-MT-02 Cohort aggregation pipeline (k-anon ≥10, async hook, nightly reconcile) P1+P2 REQ-AUTH-01 Operator auth (argon2id, signed cookies, rate limit, single role) P1 REQ-DASH-01 Cohort dashboard (3 views, React, k-anonymized, inline sparklines) P2 REQ-NFR-AUTH-01 argon2id + httpOnly + secure + SameSite + 5/min rate limit P1 REQ-NFR-MT-01 Postgres-in-LXC without destabilizing learner service P1 REQ-NFR-DASH-01 k-anonymity ≥ 10 (write-time suppression, differencing-attack tested) P2 REQ-NFR-DASH-02 Freshness ≤ 24h (nightly reconcile + on-session-end hook) P2 Key Decisions (D-050..D-057)
- D-050: Postgres via asyncpg pool over Docker internal DNS (min 1/max 10)
- D-051: VC key migration — fresh keypair in Postgres, v0.3 public key archived as superseded
- D-052: Operator bootstrap via CLI script from env-provided credentials
- D-053: Dashboard = 3 views (practice, mastery, failure-patterns) k-anon ≥10
- D-054: Aggregation = async fire-and-forget + nightly 03:00 CT reconcile
- D-055: Postgres backup = nightly pg_dump to volume, 7-day retention
- D-056: Auth = signed stateless HMAC cookies, no sessions table
- D-057: Auth = server-side on every /api/operator/* + React guard for UX
Grill Binding Decisions (6 MUST, all honored)
- G-008: backup-restore drill task
- G-011: verification endpoint two-store fallback explicit
- G-027: first-boot path (no v0.3 active key) handled
- G-031: R-AUTH-01 — k-anon defense-in-depth primary, config flag secondary
- G-038: differencing-attack test (10 vs 9 learners)
- G-041: SPA fallback via custom StaticFiles subclass (not catch-all route)
Tests
- Python: 317 passed, 36 skipped (Postgres-requiring), 0 failed
- Client (vitest): 17/17 passed
- Build + typecheck: clean
- 57 new tests in P1 + 45 new tests in P2
Review + Audit
- Multi-persona review: APPROVE_WITH_NOTES (6/6 personas PASS, 0 P0, 8 P1+ carry-forward)
- Audit: HEALTHY (reconstruction PASS, file/branch/commit discipline PASS, 8/8 REQ, 6/6 grill MUSTs)
P1+ Carry-Forward (8, non-blocking, for next milestone backlog)
- argon2id blocking event loop (R-AUTH-02, pilot-acceptable)
- rate-limit 429 mock test gap
- cookie secret length not validated
- credential status enum validation
- credential revocation audit log (operator_id of revoker)
- nightly scheduler DST timezone (UTC-5 fixed vs true America/Winnipeg)
- aggregation in-memory cache lost on restart
- f-string SQL code smell (set_credential_status)
Next Milestone
v0.5 (Live Assist on-the-job companion) per ROADMAP.md
Downloads