-
released this
2026-08-04 11:43:39 +00:00 | -2 commits to main since this releasev0.1.8 — v0.4 Phase 2: Cohort Dashboard + Aggregation
Milestone: v0.4 (Operator tier — cohort dashboard, auth, Postgres)
Phase: 2 (cohort dashboard + aggregation — feature)
Previous: v0.1.7 (phase 1 — operator foundation)What's in this release
Cohort aggregation pipeline + auth-gated operator API + React cohort dashboard with 3 k-anonymized views.
Requirements Covered (4)
REQ-ID Requirement REQ-DASH-01 Cohort dashboard — 3 views (practice/mastery/failure-patterns), React, k-anon ≥10 REQ-NFR-DASH-01 k-anonymity ≥ 10 enforced (write-time suppression, display, e2e test) REQ-NFR-DASH-02 Freshness ≤ 24h (nightly reconcile + on-session-end hook) REQ-MT-02 Cohort aggregation pipeline (hook + nightly + k-anon suppression) Key features
- Aggregation pipeline: async fire-and-forget on-session-end hook (non-blocking, C-8) + nightly reconciliation at 03:00 CT; k-anonymity ≥ 10 write-time suppression (cell_suppressed=TRUE, value=NULL for cells < 10); idempotent upsert; no raw PII in Postgres
- 4 operator API endpoints (auth-gated): GET /api/operator/cohort (practice volume), /mastery (progression), /failure-patterns, GET+POST /credentials (VC management)
- React cohort dashboard: BrowserRouter for /operator/*, login form, dashboard shell with auth gate (GET /api/operator/me on mount), 3 k-anonymized view components, inline SVG sparklines (zero-dep), suppressed-cell display ("— (<10 learners)"), freshness indicator
- SPA fallback: SpaStaticFiles custom subclass (G-041 binding) — NOT a catch-all route; serves index.html for client-side routes; API routes + StaticFiles assets unaffected; voice UI at / unchanged
- G-038 differencing-attack test: 10 learners in window A, 9 in B → B suppressed, dropped learner not recoverable via subtraction (unit + API e2e)
Tests
317 passed, 36 skipped (Postgres-requiring), 0 failed (Python)
17/17 vitest passed (Dashboard auth gate, login, sparkline, suppressedLabel, formatFreshness, no-PII)
npm build + typecheck cleanGrill MUSTs honored (2/2 P2-applicable)
- G-038: differencing-attack test (unit + API e2e)
- G-041: SPA fallback via custom StaticFiles subclass (not catch-all route)
P1+ flagged for P3 review (4)
- Credential revocation audit log (operator_id of revoker)
- Nightly scheduler timezone (UTC-5 vs true DST)
- Aggregation in-memory cache lost on restart
- set_credential_status f-string interpolation (code smell)
Next
v0.1.9 (P3 — final review + audit + milestone ship to main = v0.4 milestone release)
Downloads