Commit graph

21 commits

Author SHA1 Message Date
jedarden
31659a5ccc fix: resolve TestTimeoutDoesNotDisable hang in trigger tests
Replace httptest.Server with raw net.Listen to avoid Close() blocking
on active connections after a timeout, which caused the test to hang
indefinitely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 12:34:35 -04:00
jedarden
0377426926 fix: wire anomaly detection & security mode API endpoints
- Add missing CountAnomaliesSince method to mockDetectorProvider
  in security_test.go to satisfy the DetectorProvider interface
- Fix variable shadowing bug in anomaly.go QueryAnomalyEvents
  where incomplete rename from 'events' to 'result' caused
  append(events, &e) to reference the package instead of the slice

All security mode endpoints verified:
- GET /api/anomalies?since=24h — lists recent anomaly events
- POST /api/security/arm + /api/security/disarm — arm/disarm
- GET /api/security/status — {armed, learning_until, anomaly_count_24h}
- Anomaly events push to dashboard WS as 'alert' messages
- Arm/disarm state persists across restarts via learning_state table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 12:10:01 -04:00
jedarden
5db3110a2a feat: implement automation triggers CRUD REST endpoints
Add full CRUD endpoints for triggers with OpenAPI-style godoc comments:
- GET/POST /api/triggers (list all, create new)
- PUT/DELETE /api/triggers/{id} (update, delete)
- POST /api/triggers/{id}/test (fire trigger once for testing)

Both TriggersHandler (simple) and VolumeTriggersHandler (3D geometry)
implement all endpoints with table-driven tests covering validation,
persistence, and round-trip lifecycle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 11:38:34 -04:00
jedarden
e44dd345f6 feat: implement comprehensive /healthz endpoint
Add complete health check implementation for Docker HEALTHCHECK and
Traefik health routing with:

Response fields:
- status: "ok" or "degraded"
- uptime_s: seconds since mothership boot
- version: mothership version string
- nodes_online: count of connected nodes
- db: "ok" or "failing" (SELECT 1 with 100ms timeout)
- load_level: 0-3 from load shedding state
- reason: human-readable explanation (only when degraded)

HTTP status codes:
- 200 for healthy (status="ok")
- 503 for degraded (status="degraded")

Degraded conditions:
- Database unreachable
- Load level 3 sustained for >60 seconds
- No nodes connected after 5 minutes uptime

Docker HEALTHCHECK updated to verify status="ok" response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 11:09:36 -04:00
jedarden
9f53218f16 fix: correct no-op trigger update test expectation
The "no-op update returns current" test case was missing wantEnable: true,
causing a false negative since the seeded trigger has Enabled: true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 10:21:02 -04:00
jedarden
3d3cb41d25 feat: add security mode persistence and tracker blob lifecycle events
- Add GetArmedAt() method to persist armed timestamp across restarts
- Add blob appear/disappear callbacks to tracker for security events
- Add security handler for arm/disarm API endpoints
- Update /api/security endpoint to return armed_at timestamp
- Add tracker tests for blob lifecycle callbacks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 10:14:51 -04:00
jedarden
01547269cc feat: verify dashboard WebSocket feed supports events, alerts, BLE, triggers, health
All 5 new message types (event, alert, ble_scan, trigger_state,
system_health) were already implemented in hub.go with broadcast methods,
called from main.go/ingestion/volume_triggers/events, and handled in
app.js. Also includes security mode persistence from anomaly DB and
OpenAPI docs for triggers endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:54:14 -04:00
jedarden
fe68bb5fdc feat: implement BLE Devices REST endpoints with OpenAPI docs
- GET /api/ble/devices: list all BLE devices with filtering
- PUT /api/ble/devices/{mac}: update device label and assign to person
- Added comprehensive OpenAPI-style godoc comments
- Supports filtering by registered/discovered/archived status
- Includes device history and aliases endpoints
2026-04-07 09:36:32 -04:00
jedarden
56c28bce63 feat: implement BLE Devices REST endpoints with OpenAPI docs
- Add GET /api/ble/devices to list known devices with filtering
- Add PUT /api/ble/devices/{mac} to set label and assign to person
- Add comprehensive OpenAPI-style godoc comments for all BLE endpoints
- Add table-driven tests for BLE handler endpoints

Endpoints support:
  - Filtering by registration status (registered/discovered)
  - Time window filtering (hours parameter)
  - Device labels and person assignment
  - Sighting history per device

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:30:55 -04:00
jedarden
a873663cfc feat: implement Replay/Time-Travel REST endpoints
Add OpenAPI-style godoc comments and comprehensive table-driven tests
for replay endpoints:
- GET /api/replay/sessions - list recording sessions and replay store info
- POST /api/replay/start - start replay at timestamp (speed 1/2/5)
- POST /api/replay/stop - stop replay, return to live
- POST /api/replay/seek - seek within session
- POST /api/replay/tune - update pipeline parameters mid-replay

Improvements:
- Fix writeJSON calls to use proper 3-argument signature
- Add detailed request/response type documentation
- Add mockRecordingStore for isolated unit testing
- Add 12 table-driven test cases covering all endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:19:36 -04:00
jedarden
86a373debb feat: implement Notifications REST endpoints
- GET /api/notifications/config to get all delivery channel settings
- POST /api/notifications/config to set channel configurations
- POST /api/notifications/test to send test notifications
- Support for ntfy, pushover, gotify, webhook, and mqtt channel types
- Config validation for each channel type
- Table-driven tests for all endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:11:01 -04:00
jedarden
72b340d03a feat: implement Settings REST endpoints
Implement GET and POST/PATCH /api/settings endpoints with:

- GET /api/settings: Returns all configurable settings as JSON with
  default values merged in for any settings not explicitly set

- POST/PATCH /api/settings: Partial update with merge semantics,
  only updating the keys provided in the request body

- SQLite persistence: Settings stored in settings table with
  JSON-encoded values, loaded on startup

- Comprehensive validation: All known settings validated with
  proper range checks (fusion_rate_hz, grid_cell_m, delta_rms_threshold,
  tau_s, fresnel_decay, n_subcarriers, breathing_sensitivity,
  motion_threshold, dwell_seconds, vacant_seconds, max_tracked_blobs,
  replay_retention_hours, replay_max_mb, security_mode,
  events_archive_days)

- OpenAPI-style godoc comments: Documentation for all endpoints
  using swagger annotations

- Table-driven tests: Comprehensive test coverage for all
  functionality including GET, POST, PATCH, validation,
  persistence, and error cases

- Helper utilities: Extracted writeJSON, writeJSONError,
  writeJSONData to utils.go for reuse

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:04:55 -04:00
jedarden
5b24192186 feat: add trigger_state WebSocket message type to /ws/dashboard feed
Broadcasts { type: 'trigger_state', trigger: { id, name, last_fired, enabled } }
on trigger fire, enable, and disable events. Handled in app.js onmessage
and forwarded to window.Automations.updateTriggerState().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 08:41:17 -04:00
jedarden
b99599c403 fix: resolve Phase 6 build integration issues
- Fix unclosed brace in main.go (if zonesMgr block swallowed 1831 lines)
- Add missing resolveBlobIdentity helper function
- Apply worker changes to zones, automation, sleep, briefing, ingestion, localization, db

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 02:31:02 -04:00
jedarden
ad1e17ddf2 feat: implement SQLite Online Backup API streaming endpoint
Use modernc.org/sqlite's Online Backup API (NewBackup/Step/Commit)
with in-memory destination and Serialize for consistent hot backups
without temp files. Streams zip directly to HTTP response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 02:15:51 -04:00
jedarden
09aee3f558 fix: improve webhook fault tolerance tests
- Route test requests through chi router instead of calling handlers directly
- Fix weekday test to use correct day mapping
- Use context cancellation for timeout test instead of long sleep
- Move mockServer.Close() after assertions to prevent goroutine leak

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:15:11 -04:00
jedarden
543d66b697 feat: implement webhook action firing & fault tolerance for automations
Backend:
- HTTP client with 5s timeout, fire-and-forget webhook delivery
- Payload schema: {trigger_id, trigger_name, condition, blob_id, person, position, zone, dwell_s, timestamp_ms}
- 4xx response: disable trigger, set error_message, push WS alert to dashboard
- 5xx/timeout: log warning, increment error_count, do NOT disable
- error_count resets on first 2xx response
- POST /api/triggers/{id}/test endpoint with synthetic payload
- POST /api/triggers/{id}/enable clears error state and re-enables
- GET /api/triggers/{id}/webhook-log for last N firings
- Audit log via webhook_log table (migration_007)

Dashboard:
- Error badge (ERR) on trigger cards when error_message is set
- Disabled badge when trigger disabled due to 4xx
- Warning badge for transient error_count > 0
- Test Webhook button with real-time response display
- Webhook Log button showing last N firings
- Re-enable button to clear error state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 23:04:49 -04:00
jedarden
e74834a3bf feat: implement webhook action firing & fault tolerance for automations
Backend: HTTP client with 5s timeout, fire-and-forget webhook delivery,
4xx disables trigger with error message, 5xx/timeout increments error count,
test endpoint, enable/disable endpoints, webhook_log audit table,
WebSocket alert broadcasting on trigger errors.

Dashboard: error badge on trigger cards, Test Webhook button, webhook log
view, Re-enable button, real-time error alerts via WebSocket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:39:51 -04:00
jedarden
22b745f274 feat: webhook action firing & fault tolerance for automations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 20:29:53 -04:00
jedarden
27755fc98d feat: implement dashboard activity timeline view
Add comprehensive activity timeline view for the Spaxel dashboard:

- Timeline sidebar with scrollable chronological event list (newest first)
- Event types with distinct icons/colors: zone_entry/exit (green/orange),
  portal_crossing (blue), anomaly/security_alert (red), learning_milestone (purple), system (grey)
- Each event shows: timestamp, description, person name, zone name
- Click event → jump to that moment in replay mode
- Filter bar: filter by person, zone, event type, time range (today/7d/30d)
- Search box with debounced text filter (300ms)
- Inline feedback (thumbs up/down) on presence detection events
- POST /api/feedback endpoint for feedback submission
- GET /api/events endpoint with pagination and filtering
- Live updates: 'event' messages from WebSocket feed
- New events prepend without layout shift using DOM insertion
- Loading states, empty state, and "load more" pagination

Acceptance criteria met:
- 200 events render within 200ms
- New events prepend without layout shift
- Clicking event seeks replay to that moment
- Feedback shows toast confirmation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 12:01:19 -04:00
jedarden
f6d1c6f606 feat: implement REST API endpoints for settings, zones, portals, triggers, notifications, replay
- Added SettingsHandler with GET/PATCH /api/settings for configurable settings
- Added ZonesHandler with full CRUD for zones (GET/POST/PUT/DELETE /api/zones)
- Added PortalsHandler with full CRUD for portals (GET/POST/PUT/DELETE /api/portals)
- Added TriggersHandler with full CRUD for automation triggers including test endpoint
- Added NotificationsHandler for notification channel config and test notifications
- Added ReplayHandler for CSI replay sessions (start/stop/seek/tune endpoints)
- All endpoints follow OpenAPI-style patterns with appropriate godoc comments
- Settings persist to SQLite across restarts
- Zone/portal updates reflected in live 3D view via WebSocket

Endpoints implemented:
  GET/PATCH  /api/settings
  GET/POST/PUT/DELETE /api/zones
  GET/POST/PUT/DELETE /api/portals
  GET/POST/PUT/DELETE /api/triggers
  POST /api/triggers/{id}/test
  GET/PATCH /api/notifications/config
  POST /api/notifications/test
  GET/POST /api/replay/sessions
  POST /api/replay/start
  POST /api/replay/stop
  POST /api/replay/seek
  POST /api/replay/tune

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 11:22:02 -04:00