Add notification image proxy, expand README, fix compose env-file handling

- Proxy notification image_url server-side (GET /api/v1/notifications/:id/image)
  instead of loading it directly in the browser, so LAN-only image sources
  (e.g. Frigate snapshots) still load for clients off that network
- Tighten CSP img-src to 'self' now that images are same-origin
- Update threat model / architecture docs to match the new image-fetch design
- Expand README: Home Assistant quick-start, Pocket ID/OIDC walkthrough,
  Pangolin note, backup automation, new troubleshooting entries
- Fix docker-compose.yml: document that --env-file .env must be passed
  explicitly (Compose's implicit .env lookup was unreliable with -f from
  a different directory)
- Fix image-proxy tests to build a real session cookie (AUTH_MODE=oidc
  applies inside the test container too, so requireAuth needs one)
This commit is contained in:
siliconsolder committed 2026-09-07 18:49:45 +00:00
1 parent a82c29a69d
commit 079013730b
10 files changed
+332 -32

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@ These are the "major implementation decisions" the process asks to pause on:
| 2 | ORM / migrations | **Drizzle ORM + drizzle-kit** | Typesafe, SQL-first, no native binary/engine (unlike Prisma) — simpler in a small Alpine container, plain-SQL migration files you can read and back up. |
| 3 | Realtime "instant in UI" delivery | **Server-Sent Events (SSE)**, in-process pub/sub, no Redis | Single-instance app; SSE is one-way (all we need), works over plain HTTP through a reverse proxy, avoids the complexity of a WebSocket + no new infra. |
| 4 | VAPID key storage | **Postgres `system_settings` table**, generated on first boot if absent | Already-durable volume; no separate key file to remember to back up — `pg_dump` covers it automatically. |
| 5 | Attachments / image handling | **No server-side fetch or proxy.** `image_url`/`external_url` are stored as plain URLs and loaded directly by the browser (`<img src>`), never fetched by the server. | Eliminates SSRF risk entirely for this feature per the security requirements, at the cost of not supporting file uploads in v1 (can be added later as an explicit, scoped feature). |
| 5 | Attachments / image handling | `external_url` is stored as a plain URL and rendered as `<a href>`, never fetched server-side. `image_url` **is** fetched server-side and proxied (`GET /api/v1/notifications/:id/image`) so a LAN-only image source still loads for a client off that LAN — narrowly scoped (no client-supplied URL, requires a scoped token to have set it, timeout + size cap), not a general-purpose fetch proxy. See `02-threat-model.md`'s SSRF section. | A homelab client (phone on cellular) still needs to see camera snapshots from LAN-only sources like Frigate; a pure direct-browser-load design can't do that. Doesn't support arbitrary file uploads in v1 (can be added later as an explicit, scoped feature). |
| 6 | Webhook mapping | MVP ships a **fixed simple mapping** (`{topic, title, message, url?}` JSON body, or ntfy-style headers), not a configurable templating engine | Spec says "goal is easy migration, not full protocol cloning"; a mapping UI is called out as a later enhancement. |
| 7 | Topic access control | Topics are **visible to all authenticated users by default**; an admin can mark a topic `restricted` and grant per-user access | Matches "single/small household" simplicity principle while still satisfying "users can browse allowed topics." |