Commit Graph

6 Commits

Author SHA1 Message Date
4fc68cacf1 Add a Recordings page to browse, play and delete motion clips
- /recordings lists clips newest first with camera, time and size, plays
  them in the browser and deletes after a confirmation.
- /api/recordings lists clips; /api/recordings/clip serves one with Range
  support so seeking works, and deletes it. A clip is named by folder and
  file name, both matched against fixed patterns and resolved inside the
  recordings folder, so no request can reach another file.
- Each camera's page links to its own clips.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 17:16:14 -05:00
41021a62ad Add live video: WHEP relay route and WebRTC player
- POST/DELETE /api/cameras/[id]/live/whep check the session, resolve the
  camera from the registry, and relay WebRTC signaling to MediaMTX on
  localhost. The browser never sees MediaMTX's address, its error text or
  a camera login; video flows browser↔MediaMTX, not through Next.
- LivePlayer negotiates with the browser's own RTCPeerConnection and
  shows connecting, reconnecting and failed states with Retry.
- The camera page gains a Live section; the pop-out plays live video and
  falls back to snapshot polling if it can't. Both offer Main/Sub.
- Stop a leftover MediaMTX from a server that didn't exit cleanly: record
  its pid and, on startup, stop it only if that pid is still our binary
  with our config.
- Export vrek log: both cameras watched live on main and sub (4 of the
  goal's 6 checks).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 16:40:21 -05:00
5d181f3b3b Enforce admin login: login, first-run setup, proxy and access checks
Completes securing the web front end (vrek gol-wqf95dq, iss-r5vrjx7).

- /login: Server Action with a generic error, same-site-only redirect
  back to ?next=, and throttling of failed logins (10 per address and
  100 overall per 15 min). The header shows "Signed in as" with
  Sign out (iss-nj9wmwp).
- First run with no admin: instrumentation prints a one-time setup
  code, shared with the app through globalThis. /setup requires it,
  and 5 wrong codes rotate it. "Skip for now" runs unsecured for the
  browser session behind a red warning banner on every page
  (iss-9nxdndr).
- src/proxy.ts: optimistic redirects to /login or /setup, 401 for
  the API, and the 12 h sliding session refresh. requirePageAccess()
  and apiAccessDenied() re-check in the page and all 6 route handlers
  (iss-76d5wrb).
- An expired session now shows "Your session has ended" instead of
  the camera-login form.
- README documents in-app setup, skipping and signing in.

Verified with unit tests (383, 99.9% line coverage), end to end
against `next start`, and manually in a browser by the user.
Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 11:58:20 -05:00
4931c3af83 Reach 99.8% test coverage and enforce a 95% floor
- Route tests for camera info, snapshot and credentials (vrek
  iss-nc2tj7c): input validation, store-only-after-verify, reconnects
  after login changes, and fixed error messages with no upstream text.
- Providers and layout tests (iss-nc5w0j8).
- Discovery tests for onvif.ts (iss-3bg4r6e): multicast parsing,
  unicast sweep batching and subnet limits, de-duplication and
  merging. They run on a fake network, replacing onvif Discovery,
  node:dgram and node:os, per new vrek principle pri-e14bahk
  (replaceable transport; tests never touch the real network).
- coverage.thresholds.lines = 95, so `npm run coverage` fails below
  the goal (iss-zjpc22k).

200 tests, 99.77% line coverage. Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:17:55 -05:00
71d02195ce Add Vitest test suite with coverage reporting
Sets up Vitest (jsdom, Testing Library, v8 coverage) per the Next 16
testing guide, using Vite's native tsconfig path resolution instead of
vite-tsconfig-paths. A server-only stub and a temp-data helper let
server modules run in isolation. @types/node moves to ^24 to match the
Node 24 runtime (a vitest 5 peer requirement).

First 68 tests cover the discover route (including iss-dbwgww8: no raw
errors in responses), the credential store, the camera registry,
camera-route helpers and the refresh-rate schema. Line coverage is
31.2%, toward the 95% goal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 08:49:50 -05:00
f39d16a8c0 Add ONVIF camera app with a server-rendered camera dashboard
Discovers ONVIF cameras (Hikvision/Annke) over WS-Discovery, keeps a
server-side registry and an encrypted credential store, and serves
info, snapshot and credentials routes for each camera.

The home page is now a Server Component that lists known cameras from
the registry on load, without a scan (vrek iss-a0hz0py). The snapshot
refresh rate lives in the URL (?refresh=), and a scan refreshes the
server-rendered list.

Route input is validated with zod (iss-rjqy3hy), and /api/discover no
longer returns raw error messages (iss-dbwgww8). Adds
@tanstack/react-query and zod as dependencies, with a QueryClient
provider in the root layout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 08:40:32 -05:00