docs: changelog [Unreleased] — add the client portal feature
Documents the read-only client portal under [Unreleased] alongside the SLM live-monitoring work: per-client scoping + interim auth, live location view with the auto-closing WS stream, locations overview map + rollup, the alerts config→surface→24/7 track, operator sharing tools, the field-instrument design + light/dark toggle, the security posture, and upgrade notes (migration, SECRET_KEY, SLMM alert-engine pairing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,62 @@ The two builds must ship **together**. Note the `docker-compose.yml` container
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Client portal *(new — read-only client-facing view)*
|
||||||
|
|
||||||
|
A scoped, read-only portal at **`/portal/*`** where a client sees only *their*
|
||||||
|
locations, live. Built inside Terra-View (no new service), reusing the cached
|
||||||
|
SLMM feed; every route resolves the client through one swappable
|
||||||
|
`get_current_client` gate, so the interim magic/open-link auth can be replaced
|
||||||
|
(M4) without touching routes or templates. Strictly read-only — no device control.
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
- **Per-client scoping + interim auth.** New `Client`, `ClientAccessToken`, and a
|
||||||
|
`Project.client_id` FK. A signed (HMAC) session cookie carries the access-token
|
||||||
|
id, re-validated against the DB each request (revoke kills live sessions, with
|
||||||
|
server-side expiry). Entry via a magic link (`/portal/enter/{token}`) or a
|
||||||
|
dev-only plain link (`/portal/open/{id}`, `PORTAL_OPEN_LINKS`, **default off**).
|
||||||
|
- **Live location view.** KPI cards (Lp/Leq/Lmax/L1/L10) + chart populate
|
||||||
|
instantly from cache, then upgrade to a real **~1 Hz WebSocket stream** scoped to
|
||||||
|
the client's unit (a scrubbed bridge to the SLMM fan-out feed). The stream
|
||||||
|
**auto-closes when the tab is hidden** (Page Visibility) and after a 15-min idle
|
||||||
|
cap, so an abandoned tab can't pin the device at 1 Hz / burn cellular.
|
||||||
|
- **Locations overview.** Live status map (level-colored dots, dark/light CARTO
|
||||||
|
tiles) + a status rollup (live/offline counts, "loudest now"). Leq is the
|
||||||
|
headline metric.
|
||||||
|
- **Alerts (config → surface → 24/7).** Threshold-rule config on the SLM detail
|
||||||
|
page (proxying SLMM's alert CRUD); breach **history + ack** internally and a
|
||||||
|
read-only, scrubbed history + current-alarm banner + **"your alert limits"** panel
|
||||||
|
in the portal; enabling a rule pins that device's monitor on so alerts evaluate
|
||||||
|
round-the-clock.
|
||||||
|
- **Operator sharing tools.** A **"View client portal"** preview button and a
|
||||||
|
**"Copy client link"** modal (mint / list / revoke magic links) on the project
|
||||||
|
page, plus a `backend/portal_admin.py` CLI.
|
||||||
|
- **Field-instrument design.** Distinctive themed portal — Hanken Grotesk UI +
|
||||||
|
IBM Plex Mono readouts, panel system, pulsing live dot, staggered reveal — with a
|
||||||
|
**light/dark toggle** (light default, persisted, no-flash).
|
||||||
|
|
||||||
|
#### Security
|
||||||
|
|
||||||
|
- All scoping enforced server-side (404-not-403, no existence leak); client
|
||||||
|
endpoints return **scrubbed** projections (no device-health/internal ids); WS
|
||||||
|
frames whitelisted; operator-set strings HTML-escaped before injection (XSS).
|
||||||
|
Pre-merge code review hardened cookie expiry, open-links default, and the slug
|
||||||
|
collision. Remaining hardening (reverse proxy, TLS, `SECRET_KEY`, M4 auth) is
|
||||||
|
tracked in `docs/CLIENT_PORTAL.md` → "Security hardening backlog".
|
||||||
|
|
||||||
|
#### Upgrade Notes
|
||||||
|
|
||||||
|
- **Migration:** `docker compose exec web-app python3 backend/migrate_add_client_portal.py`
|
||||||
|
(adds `projects.client_id`; the `clients` / `client_access_tokens` tables
|
||||||
|
auto-create).
|
||||||
|
- Set a real **`SECRET_KEY`** in any internet-facing env (signs session cookies),
|
||||||
|
and keep **`PORTAL_OPEN_LINKS=false`** there.
|
||||||
|
- Portal alerts depend on the **SLMM `dev`** alert engine (rules/events/evaluator +
|
||||||
|
cooldown + keepalive coupling) — same build pairing as above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [0.13.3] - 2026-06-05
|
## [0.13.3] - 2026-06-05
|
||||||
|
|
||||||
Calibration sync from SFM events. Closes the manual data-entry loop on calibration dates — Terra-View now pulls `device.calibration_date` from each seismograph's most recent event sidecar once a day and updates `RosterUnit.last_calibrated` when the device reports something fresher than what's stored. Manual edits still win when they're newer than the latest event; a fresh event arriving later supersedes the manual edit. Adds a "Sync now" button under Settings → Advanced → Calibration Defaults for on-demand runs, and a `docs/ROADMAP.md` to track in-flight + deferred work.
|
Calibration sync from SFM events. Closes the manual data-entry loop on calibration dates — Terra-View now pulls `device.calibration_date` from each seismograph's most recent event sidecar once a day and updates `RosterUnit.last_calibrated` when the device reports something fresher than what's stored. Manual edits still win when they're newer than the latest event; a fresh event arriving later supersedes the manual edit. Adds a "Sync now" button under Settings → Advanced → Calibration Defaults for on-demand runs, and a `docs/ROADMAP.md` to track in-flight + deferred work.
|
||||||
|
|||||||
Reference in New Issue
Block a user