Commit Graph

51 Commits

Author SHA1 Message Date
root
4ef7fa2d75 fix(health): derive /health version from package.json (kills the manual server.js bump gotcha)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:58:44 +10:00
root
b17cdb7f77 fix(sv): Backups card byte formatter — tenths for GB, MB under 1G
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:49:00 +10:00
root
b967c0bfdd feat(sv): Backups card — offsite DR status (Core-4 -> Farm) + /api/backups (2.6.0)
migration 026 backup_runs; POST ingest (owner) from offsite-backup.sh, GET for the
Sacred Valley card showing last run, per-guest sizes, Farm free, schedule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 17:47:17 +10:00
root
16e324102e fix(icons): serve icons no-cache so updates propagate (2.5.2)
Icon route used Cache-Control: public, max-age=86400, so changed icons stayed
stuck in CF + browser caches for a day. Switch to no-cache (revalidate; Express
ETag => 304 when unchanged) so icon edits show up immediately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 11:25:54 +10:00
root
18eba2d911 fix(devices): recolor bundled icons to theme light + larger size (2.5.1)
Tabler icons use currentColor which doesn't inherit through <img>, so they
rendered black on the dark theme. Bake --text (#e8e6ed) into the 15 bundled
SVGs and bump icon sizes (tile 20->30px, picker 22->28px).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 11:19:27 +10:00
root
b16456fc1b fix(server): bump hardcoded /health VERSION to 2.5.0 (deploy gate)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 09:26:39 +10:00
root
4efeca74b2 feat(api): /api/icon-sets — list/serve/upload(zip,url)/delete
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 08:39:20 +10:00
root
1b960ec52b feat(sv): Storage · capacity card — ZFS pools, dropped pools, per-CT disk
Read-only Proxmox storage health (same PROXMOX_RO_TOKEN as the cluster card):
ZFS pool health+usage, dropped zfspool storages (the donatello/leonardo SATA
signal), and per-LXC rootfs fill, with a HEALTHY/WATCH/ATTENTION roll-up.
Closes the monitoring gap from the 2026-06-09 audit (C1 + H2 were invisible).
Pure normalizeStorage() unit-tested (4 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 03:27:15 +10:00
root
91a45b4b6c feat(apps): MagicMirror as a Void app (#/mirror, mirror.hynesy.com)
Embed MagicMirror² (CT 111) via the shared embedView factory, exposed at
mirror.hynesy.com through Traefik + CF Access. Traefik mirror-frame middleware
swaps MM's X-Frame-Options for a CSP frame-ancestors allowing the Void origins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 00:42:40 +10:00
root
95fa0c1828 chore(release): 2.2.0 — Kutt Links app
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 00:10:50 +10:00
root
26463b5eb6 feat(devices): Scan Now + Manual Add (IP option, MAC colon-mask) → 2.1.4
'Scan Now' triggers POST /api/devices/scan from the band header. '+ Add by MAC'
renamed '+ Manual Add' with an optional IP field (addBody/addManual accept ip)
and a MAC input that auto-inserts colons as you type. Frontend test 4/4; DB-backed
api/repo tests written (run with the suite — skipped locally to avoid colliding
with a concurrent test run on void_test).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:58:19 +10:00
root
88ef5786ee feat(devices): manually add a device by MAC (offline pre-register) → 2.1.3
'+ Add by MAC' in the band header → POST /api/devices → lan_devices.addManual
(status=known, present=false; enriched on next scan). Repo + API + frontend tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:12:47 +10:00
root
7a5fd88c07 feat(devices): edit known devices (rename/regroup/delete) → 2.1.2
Known device tiles get a ✎ edit affordance using the existing PATCH/DELETE
/api/devices/:mac endpoints. Previously devices could only be named at promote time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:02:06 +10:00
root
607b76ff82 feat(apps): OBD2 placeholder rail item (launchpad for the parked OBD2 project)
Adds an OBD2 item to the Apps rail; with no records UI deployed yet it links to
the OBD2 Telemetry project + tasks and the research/wiki page rather than
embedding. Swap to embedView once LubeLogger/Tracktor is up. → 2.1.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 22:05:21 +10:00
root
5f1b789250 chore(release): 2.1.0 — LAN device discovery; retire static devices.json 2026-06-08 21:11:08 +10:00
root
0fe25d96ec feat(devices): /api/devices band + discovered review/edit endpoints 2026-06-08 21:04:41 +10:00
root
9aacc58c35 chore(release): 2.0.0 — drop -alpha; Void 1 retired, CTs renamed
Void 2 reaches GA. Void 1 (CT 301) was stopped, fully backed up (vzdump +
off-CT data tarball), and destroyed; CT 310/311 renamed void-db/void-app;
the legacy void1 registry tile removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:09:11 +10:00
root
29a9185788 chore(release): 2.0.0-alpha.27 — fold-in Apps section 2026-06-08 15:07:20 +10:00
root
73b572a092 chore(release): 2.0.0-alpha.23 — local/remote-aware service tiles
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 11:04:56 +10:00
root
4e78b16188 fix(sw): ship self-unregistering tombstone to kill stale Void 1 service worker 2026-06-06 00:32:46 +10:00
root
358b826247 chore: release 2.0.0-alpha.21 (docs-kind spaces + long-page embedding) 2026-06-05 23:49:48 +10:00
root
494793874d chore: release 2.0.0-alpha.20 (page ordering + sectioned space view) 2026-06-05 22:37:28 +10:00
root
34d0c417f4 chore: release 2.0.0-alpha.19 (Whisper GPU sharing, mobile Send button, Chaptarr)
Version + changelog were left at alpha.18 (the cutover) while four
subsequent changes shipped to prod. Bump to alpha.19 and document:
GPU->CPU Whisper fallback + in-container driver, Ollama VRAM unload
before STT, mobile chat Send button, Chaptarr in the service registry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:50:41 +10:00
root
147b4f514c feat(cutover): Plan 8b — point void.hynesy.com at Void 2 (alpha.18)
CF Access multi-aud: CF_ACCESS_AUD now accepts a comma-separated
allow-list so requests through either the void.hynesy.com or
void2-app.hynesy.com CF Access app are honoured as owner. Fails
closed; unlisted auds rejected. Adds multi-aud test.

Void 1 (CT 301) becomes legacy but stays running untouched as an
instant rollback. -alpha tag kept pending owner sign-off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 00:50:57 +10:00
root
191790098a chore: release 2.0.0-alpha.17 (settings, projects, terminal, AI usage, The Void space, UI polish)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 00:39:52 +10:00
root
4a55c24700 feat(terminal): proxy /terminal (+WebSocket) through the Void app to ttyd
Makes the embedded Terminal work via the raw LAN IP too (bypasses Traefik's
/terminal route). ttyd base-path preserved; firewall on CT300 opened to the app host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:44:31 +10:00
root
c32871d9d0 fix(ui): no-cache static assets (stop stale CSS/JS after deploys); live nav-active sync; breadcrumb sized+themed to match back button
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:23:00 +10:00
root
80ad482d82 chore: release 2.0.0-alpha.16 (Little Blue + action framework)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 21:48:15 +10:00
root
6ceb27fa2f chore: release 2.0.0-alpha.15 (Yerin online)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 21:14:38 +10:00
root
6b26b79a84 chore: release 2.0.0-alpha.14 (MCP HTTP transport)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:13:20 +10:00
root
6041f845e9 feat(mcp): mount /mcp Streamable HTTP endpoint
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:09:30 +10:00
root
f780043f2d feat(ui): 2.0.0-alpha.13 — finer per-card width scaling (12-col grid + -/+ stepper)
clock/weather etc. default to 1/6 width; sizes store an integer span 1-12
(legacy s/m/l still accepted by /api/dashboard/layout).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:23:37 +10:00
root
ae3a45251d feat(ui): 2.0.0-alpha.12 — editable Sacred Valley layout
Edit-layout mode: per-card resize (S/M/L), show/hide with a hidden-cards tray,
drag-to-reorder via a dedicated grip handle, and reset-to-default. Persists via
the existing /api/dashboard/layout (order/sizes/hidden) — no backend change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:15:08 +10:00
root
ce26895d8e feat: 2.0.0-alpha.11 — DB-backed service registry + LAN auto-discovery
- monitored_services table (mig 015) replaces config/services.json (now a boot seed)
- owner CRUD over /api/health/services; GET is DB-backed; cron+worker read the DB
- discover.lan worker: pure-Node TCP sweep + HTTP-title probe -> disabled 'discovered'
  candidates (never clobbers curated entries); POST /api/health/discover + GET .../discovered
- dashboard: Scan button + Discovered(N) section with one-click promote

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 07:55:08 +10:00
root
4e943ada12 feat(auth): 2.0.0-alpha.10 — Cloudflare Access SSO as owner auth
A cryptographically-verified CF Access JWT (signature vs team JWKS + audience +
email allow-list) now counts as the owner, so browser requests through the CF
tunnel don't need the owner token copied onto each device. Fails closed → owner
token remains the fallback (LAN-direct + dev/tests unaffected). Opt-in via
CF_ACCESS_TEAM_DOMAIN / CF_ACCESS_AUD / CF_ACCESS_OWNER_EMAILS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 10:25:58 +10:00
root
925cb0d7d6 chore: 2.0.0-alpha.9 — security & correctness hardening (Void 3.0 quick wins)
- Q3: prod void DB role NOSUPERUSER (vector marked trusted; deploy/README documents it)
- Q4: buildChildEnv allow-list for the claude subprocess (no OWNER_TOKEN/DATABASE_URL/secrets leak)
- Q5: pending-change approve claims-before-applying + reopens on failure (no re-approvable dup)
- Q6: /capture/upload validates space_id (UUID+existence); pg pool statement_timeout 30s
- Q9: disabled failing syncoid-donatello timer on Z

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 07:54:57 +10:00
root
1eadd41990 chore: version 2.0.0-alpha.8 — Sacred Valley (Plan 6) 2026-06-02 23:02:26 +10:00
root
b0d54a24cc feat(health): local icon cache /api/icons/:slug.png (no CDN leak)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 22:58:35 +10:00
root
28e66c6946 chore: version 2.0.0-alpha.7 — security hardening + Yerin security agent
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 00:24:34 +10:00
root
16497bd9db chore: version 2.0.0-alpha.6 — companion on Claude CLI subprocess (Max subscription)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 22:22:53 +10:00
root
c7a94f26d1 chore: version 2.0.0-alpha.5 + plan-5 completion doc
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:41:46 +10:00
root
7707b7eb00 chore: version 2.0.0-alpha.4 + changelog + plan-4 completion doc
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:25:31 +10:00
root
13fac102dd feat(cron): daily sync.source_doc enqueue
node-cron schedules runSync at 03:00 local time; runSync enqueues
sync.source_doc for every source_docs row with sync_source='url'.
Started from server.js's CLI gate alongside the job queue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:14:07 +10:00
root
a02a96ea5f chore: version 2.0.0-alpha.3 + changelog
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 04:00:32 +10:00
root
d7f9bde5e9 feat(api): karakeep webhook (HMAC-verified)
POST /api/ingest/karakeep accepts Karakeep webhook payloads. HMAC
signature on the raw body captured by express.json's verify hook.
Mounted on app before mountApi so it bypasses agentOrOwner — the
shared secret IS the auth.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 03:55:57 +10:00
root
53ffd705c4 feat(jobs): echo worker + CLI bootstrap
Job queue starts only in the CLI gate (not inside createApp), so tests
manage their own queue lifecycle. waitForJob() takes a (name, id) pair
to match pg-boss v10's getJobById signature.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 03:28:06 +10:00
root
8ae9bced24 chore: version 2.0.0-alpha.2 + changelog
Search view: read ?q from hash, call /api/search, group hits by kind
with rank + space_id; sidebar filters for kinds and space_id; updates
on Enter or filter change.

Bumps package.json + server.js VERSION to 2.0.0-alpha.2 and pins the
/health version assertion to match.

CHANGELOG: full Plan 2 entry covering API surface, capability tiering,
audit chain extension (approve/reject events), and the SPA shell.

Security: adds safeHref() to dom.js and applies it everywhere an
API-supplied URL becomes href / src (reference media block + reference
source_url anchor + resource url anchor). javascript: and other
non-http(s)/mailto schemes from agent-suggested content can no longer
execute in the owner's browser.

Plan 2 surface is feature-complete: 22/22 tasks landed, 185 tests
across 43 files, SPA renders end-to-end including the suggest -> approve
agent flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 02:26:56 +10:00
root
59ad86425d feat(ui): static shell + router + api wrapper
Three-column grid (sidebar / main / right rail) with Cradle aesthetic:
blackflame accent on Cinzel display headings + Cormorant Garamond body
in cards, system UI for chrome. Hash-based router covers all entity
routes plus search, inbox, sacred-valley. api.js stores OWNER_TOKEN in
localStorage and prompts via a modal on 401. dom.js provides safe el()
+ mount() builders so no component ever assigns innerHTML from API data
(the only exception is an explicit, scary-named html: opt-in for
sanitizer output, used later by the markdown editor).

state.js is a tiny event bus for shared chrome state (pending count).
Components and views are loaded as ES modules — sidebar / topbar /
rightrail + 9 view stubs that the later Phase E tasks fill in.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 02:12:18 +10:00
root
1208b3bd40 fix(api): drop err.message from 500 response body (CWE-209)
Catch-all error handlers in lib/api/errors.js and server.js were
echoing raw err.message to clients. Replace with a fixed generic
message; the full error continues to be logged server-side via pino.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 20:45:08 +10:00
root
75afedaef0 feat(api): error + validate + pagination plumbing
Add lib/api/{errors,validate,pagination,index}.js: typed ApiError
subclasses, errorMiddleware, zod-backed validate(), parsePagination
with caps, and a mountApi() that owns /api routing + 404 + error tail.
server.js delegates /api to mountApi and drops the inline /api/spaces
smoke (returns in Task 2).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 16:37:06 +10:00