From 2842ec996cb52705e4784ae395045b624410102c Mon Sep 17 00:00:00 2001 From: Matt Mabrey Date: Wed, 23 Sep 2026 15:06:02 -0700 Subject: [PATCH] Add session notes for 2026-09-23 (CR-019 / D18 work) --- docs/waves/notes-2026-09-23.md | 85 ++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/waves/notes-2026-09-23.md diff --git a/docs/waves/notes-2026-09-23.md b/docs/waves/notes-2026-09-23.md new file mode 100644 index 0000000..24dfa5f --- /dev/null +++ b/docs/waves/notes-2026-09-23.md @@ -0,0 +1,85 @@ +# Session notes — 2026-09-23 + +Working notes for the `feat/waves-11-13` line (CR-019, CR-020 reserved, D18), +written up before merge. Not a spec document — `wave-11.md`, `wave-13.md` and +`decisions-2026-09-17.md` are the source of truth for scope and acceptance +criteria. This is the "what actually happened building it" record. + +## What shipped today + +**CR-019 (wave 11) — usage/activity metrics, T11.1 through T11.6 complete:** + +- `UsageEvent` table + migration (T11.1), a capture endpoint wired into + `auth-guard.js` so every protected page pings it once per load, plus a + `login` event at Okta sign-in (T11.2). +- `GET /api/usage/summary` (T11.3) — active users by day/week/month, + per-user last-active, per-tool breakdown, filterable by date/project/ + user/tool, all combinable. +- `GET /api/usage/export` (T11.4) — raw and sanitized CSV. Sanitized mode + replaces the username with an HMAC-SHA256 pseudonym (keyed with + `auth.SECRET_KEY`), stable per user across rows and across separate + export calls, so an external tool (Power BI etc.) can still group by + user without ever seeing a real name. +- A new "Activity & usage" card in the admin console (T11.5): real filter + controls, the summary tables, both export buttons. Client-side gated + admin-only same as the rest of the console; the API underneath is + independently gated server-side regardless. +- Retired the old per-browser "Usage logs" panel and `wp-usage.js` + entirely (T11.6) — it had no reader left and was never a real data + source for the new report anyway. The scattered `track()` call sites in + the creator and wizard were left in place calling a documented no-op, + rather than deleting ~45 individual call sites for the same effect. + +Only **T11.7 (final wave verification)** is left before wave 11 is fully +closed out — everything under it has already been verified per-task, so +this is a consolidation pass, not new work. + +**D18 (wave 13) — Okta/AD deprovisioning, T13.1 only:** + +- Session lifetime changed from one flat `AUTH_SESSION_HOURS` to a sliding + idle timeout (`AUTH_IDLE_MINUTES`, default 30) capped by a hard ceiling + from original sign-in (`AUTH_SESSION_HOURS`, default 8, meaning changed + from "session length" to "absolute ceiling"). Both defaults are flagged + in `.env.example` and `DEPLOYMENT.md` as proposed, not confirmed against + the tenant's actual Okta SSO policy. +- **T13.2 onward (the actual Okta Management API sync job) is paused** — + explicit call from Matt: no Okta API credential yet, come back to it + later. Not started, not blocked on anything code-side. + +**CR-020 (wave 12, bulk user editing):** not started. Reserved, scoped in +`wave-12.md`, no code touched. + +## Environment work (not itself a task, but load-bearing) + +- Fixed a CRLF/LF mismatch that was making every tracked file look modified + to this session's git client (`core.autocrlf true`, repo-local, no file + content changed). +- This machine had no Python. Installed it via `winget` (`Python.Python.3.12`) + and set up a `.venv` in the repo with `server/requirements.txt` installed, + specifically so `tests/baseline_shots.py` could run locally — this + sandbox has no headless-capable browser and can't download one (network + allowlist), so the 390px/1440px screenshot verification CLAUDE.md asks + for had to run on Matt's own machine instead, using the browser already + installed there (Edge). +- Established a repeatable local verification loop for every task: throwaway + SQLite, fake-Okta sign-in, promote to admin, `seed_demo.py` + + `smoketest.py` (27/27 passing throughout), plus `baseline_shots.py` for + anything touching `html/`. + +## Standing constraints, still in effect + +- Everything stays local on this branch line. No `git push` at any point + today. +- One task per PR discipline was kept even though all of it landed on one + branch — each commit corresponds to exactly one task ID, in wave order, + each individually verified before the next started. + +## Before merging + +- Run T11.7 (full wave-11 verification pass) and record it in `wave-11.md`. +- Decide where this branch actually merges to — `feat/waves-11-13` has all + of today's commits already; this notes branch was cut from it so it can + fast-forward back in, or merge as its own PR if the notes should be + reviewed separately from the code. +- T13.2+ and all of wave 12 remain explicitly out of scope until Matt says + otherwise.