Commit Graph

62 Commits

Author SHA1 Message Date
18a19fdf81 Extract interface checks in unicast sweep into checkAddr()
Moves the IPv4/internal/link-local/prefix-size checks out of
localSubnetHosts() into a helper. No behaviour change: the 30 discovery
tests pass and onvif.ts stays at 100% coverage.
2026-09-19 12:07:59 -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
462141aa35 Add admin login foundations: scrypt admin file, CLI, sessions
Groundwork for securing the web front end (vrek gol-wqf95dq). The app
does not enforce login yet.

- src/lib/admin-file.ts: the admin file at ADMIN_AUTH_FILE (default
  .data/admin.json). scrypt hashing (N=2^16, random salt, bounded
  parameters, constant-time compare), zod-validated reads where a
  malformed file is an error, and atomic 0600 writes that won't
  replace an existing admin without overwrite. Plain Node, so the
  CLI can share it (iss-mffqscg).
- src/lib/admin-auth.ts: server-only app layer; failed logins always
  cost one hash.
- scripts/create-admin.mts + `npm run admin:create`: create or reset
  the admin outside the app, interactive (hidden, confirmed) or piped
  (iss-7xmka20). The README documents it, a no-npm Node one-liner,
  the file format, and password reset.
- src/lib/session-token.ts and session.ts: stateless HMAC-signed
  session cookie, keyed from the password hash so a password change
  ends every session, with a 12 h sliding window (iss-e27nb70,
  dec-f0xar8r).

281 tests, 99.8% line coverage. Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:46:40 -05:00
a174d7a2d6 Keep runtime data out of Next's output file tracing
next build warned that the env-dependent registry and credential-store
paths made Turbopack trace the whole project (vrek iss-jvxcd1n).
Marking only the readFile calls cleared the warning, but it still
traced .data/cameras.json and the encrypted .data/credentials.json,
which a standalone deployment would copy from the build machine.

A /* turbopackIgnore: true */ on each default path.join(process.cwd(),
".data", ...) fixes both. The traced files for every route now include
nothing from src/, public/ or .data/. The env-var overrides the tests
use still work. Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:23:34 -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
31026559b7 Test camera.ts: connection handling, errors and snapshot auth
Adds 47 tests for camera.ts (vrek iss-qak2mz8), bringing it to 100%
line coverage. A scripted stand-in for the onvif Cam class drives the
connect outcomes: profiles, warnings, inactive devices, and login
errors. Snapshots run over real HTTP against a local server with real
Digest and Basic 401 challenges. Also covers isAllowedHost edge cases.

Overall line coverage is 72.4% (143 tests). Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:07:53 -05:00
33c12ea70c Stop camera routes echoing raw error messages
cameraErrorResponse now returns fixed text for each error class and
logs the original server-side. Upstream ONVIF/SOAP responses, socket
errors and credential-file paths no longer reach the browser (vrek
iss-tz5s098). CameraAuthError gains a missingLogin flag so the UI can
still tell "no login saved" apart from "login rejected".

Tests throw errors carrying a fake password and file path, and check
neither appears in any response. Closes the dashboard migration (vrek
iss-qbh3541). Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:03:46 -05:00
870b4cd2af Move dashboard client onto React Query hooks
Adds src/app/camera-queries.ts: React Query hooks over our own routes,
with each camera's queries keyed ['camera', id]. The camera card,
snapshot polling, login form and network scan use these hooks instead
of hand-rolled fetch/useEffect state (vrek iss-2fm6x2y, iss-ksxmctm,
iss-m032zwq, iss-8hfq2y2).

- Snapshot polling pauses in hidden tabs, never overlaps a slow
  frame, and stops after a failure until Retry. Each frame's object
  URL is created and revoked in one effect, so none leak under Strict
  Mode.
- Saving or forgetting a login resets only that camera's queries.
- New "Forget saved login" action, shown for stored logins.
- Fix: a scan timeout typed below 1 s now clamps to 1 s instead of
  falling back to 5 s.

Adds jsdom component tests (test/dom.tsx helpers): 93 tests, line
coverage 54.3%. Refreshes the vrek export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 09:01:34 -05:00
97a6b59cfe Track vrek export, MCP config and IDE VCS mapping
Commits .vrek/log.ndjson, the vrek export of goals, principles,
decisions, issues and evidence (restore with vrek_import), plus
.mcp.json, which wires the vrek MCP server, and .idea/vcs.xml. The
SQLite database and its -wal/-shm files are local state and are
gitignored; the export is refreshed and committed periodically.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 08:52:49 -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
5e73d3ffe0 Initial commit from Create Next App 2026-09-19 07:15:19 -05:00