docs: client portal design + milestone plan (M1 live view → M4 full auth) #61
@@ -175,3 +175,34 @@ live data, all from cache.
|
|||||||
- `SECRET_KEY` must be a real secret in prod (env, not committed).
|
- `SECRET_KEY` must be a real secret in prod (env, not committed).
|
||||||
- Cookies: `HttpOnly`, `SameSite=Lax`, `Secure` once behind TLS.
|
- Cookies: `HttpOnly`, `SameSite=Lax`, `Secure` once behind TLS.
|
||||||
- Tokens stored hashed; raw shown once. Revocation is immediate.
|
- Tokens stored hashed; raw shown once. Revocation is immediate.
|
||||||
|
|
||||||
|
## Security hardening backlog ("Fest 2026")
|
||||||
|
|
||||||
|
The to-do for the dedicated hardening pass, roughly highest-impact first. Until
|
||||||
|
then the portal runs on security-by-obscurity (open port + interim links) — fine
|
||||||
|
for a not-in-use demo, not for real clients.
|
||||||
|
|
||||||
|
**Exposure (the big one):** port 8001 serves the *entire operator app* (roster,
|
||||||
|
projects, `/admin/*`, device config, the SLMM proxy) with **zero auth**, so an
|
||||||
|
open port exposes far more than the read-only portal.
|
||||||
|
- [ ] Reverse proxy (NPM/Caddy/Nginx) in front, exposing **only `/portal/*`** to
|
||||||
|
the internet; keep the operator app reachable on the LAN only.
|
||||||
|
- [ ] TLS everywhere (Let's Encrypt). Then set portal cookies `Secure`.
|
||||||
|
- [ ] Don't port-forward the raw app; if a quick gate is wanted before M4, an
|
||||||
|
auth proxy (Authelia / Authentik) can front the portal without writing auth.
|
||||||
|
|
||||||
|
**Config musts:**
|
||||||
|
- [ ] Set a real `SECRET_KEY` env (signs session cookies; default is public).
|
||||||
|
- [ ] `PORTAL_OPEN_LINKS=false` in any internet-facing env (it defaults off now).
|
||||||
|
|
||||||
|
**M4 — real auth** (replaces the interim token behind `get_current_client`):
|
||||||
|
- [ ] Magic-link email and/or accounts; proper sessions + password reset.
|
||||||
|
- [ ] Authenticate the **operator** app too (it currently has none).
|
||||||
|
- [ ] Gate the operator-only endpoints that are presently unauthenticated:
|
||||||
|
`/projects/{id}/portal-preview`, `/projects/{id}/portal-link*`,
|
||||||
|
`/portal/open/*`.
|
||||||
|
|
||||||
|
**Smaller items from the pre-merge code review:**
|
||||||
|
- [ ] Keepalive isn't auto-turned-off when the last alert rule on a unit is
|
||||||
|
deleted (intentional "never auto-off"; revisit if it wastes cellular).
|
||||||
|
- [ ] Consider rate-limiting the scoped portal endpoints once public.
|
||||||
|
|||||||
Reference in New Issue
Block a user