Commit graph

102 commits

Author SHA1 Message Date
jedarden
d3778ee5e8 fix: resolve merge conflict debris in main.go portal routes
The Phase 5→6 merge left garbled duplicate portal API code and
missing closing braces. Fixed the zones PUT handler closure, added
missing zones DELETE handler, cleaned up duplicate portal code, and
replaced non-existent GetZoneName() calls with GetZone().Name lookups.

The phase6 build tag and Phase 5 main.go.bak were already removed
in prior work — this commit fixes the remaining compilation errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:58:41 -04:00
Argo Workflows CI
29325eca4f ci: auto-bump version to 0.1.29 2026-04-07 04:15:46 +00: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
Argo Workflows CI
f469129849 ci: auto-bump version to 0.1.28 2026-04-07 03:42:56 +00:00
jedarden
35df775726 fix: timezone bug in occupancy reconciliation + test fixes
- Use time.Now().In(m.tz) instead of time.Now() in reconcileOccupancy
  to correctly compute midnight in the configured timezone
- Fix ReconcileTick to only mark reconciled on exact blob count match
  (diff==0), keeping diff==1 as uncertain per spec
- Fix timestamp units consistency (UnixNano → UnixMilli) in crossing
  event recording and retrieval
- Fix reconciliation query to use from_zone/to_zone columns
- Reset m.reconciled=false in tests that create uncertain occupancy
  after manager construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 23:42:30 -04:00
Argo Workflows CI
3a5a00e39b ci: auto-bump version to 0.1.27 2026-04-07 03:05:47 +00: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
Argo Workflows CI
437e1865f8 ci: auto-bump version to 0.1.26 2026-04-07 02:01:01 +00:00
jedarden
757d7240dc feat: implement snapshot-on-connect + incremental update protocol for dashboard WebSocket
- Hub sends full snapshot (type=snapshot) on new client connect before adding
  to broadcast list, preventing race with delta messages
- tickDelta at 10 Hz computes byte-level diffs of cached JSON fields, broadcasts
  only changed fields with no type field
- Dashboard sets awaitingSnapshot on WS open, drops incremental updates until
  snapshot received, rebuilds full state from snapshot
- Fix zone snapshot building (nil→ok check, SizeX fields)
- Remove unused broadcastBLEScan function
- Add drainSnapshot helper and fix TestHub_LinkEvents to account for snapshot
- Add TestHub_SnapshotOnConnect, TestHub_SnapshotBeforeDelta, TestHub_DeltaOmitsTypeField

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 22:00:36 -04:00
Argo Workflows CI
dbc18e2793 ci: auto-bump version to 0.1.25 2026-04-07 01:40:08 +00: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
Argo Workflows CI
2d22782ba4 ci: auto-bump version to 0.1.24 2026-04-07 01:29:45 +00:00
jedarden
eb5b43f279 feat: add migration_007 for webhook_log, trigger_state tables and trigger error columns
Formalizes the webhook audit infrastructure (webhook_log table, trigger_state
persistence, error_message/error_count columns) that was previously created
via ALTER TABLE in Store.init(). All webhook action firing, fault tolerance,
test endpoint, enable/disable, and dashboard UI were already implemented
in prior commits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:29:17 -04:00
Argo Workflows CI
61512fdb88 ci: auto-bump version to 0.1.23 2026-04-07 01:27:37 +00:00
jedarden
f7df7740bf feat: implement 7-day pattern learning algorithm for anomaly detection
Welford's online algorithm for per-zone, per-hour, per-day-of-week
occupancy modeling with cold start suppression, outlier protection,
security mode override, and SQLite persistence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:27:10 -04:00
Argo Workflows CI
d6b1a902d2 ci: auto-bump version to 0.1.22 2026-04-07 00:58:46 +00:00
jedarden
7c0bea764f fix: resolve compilation and test failures in analytics anomaly tests
- Change testAlertHandler.mu from sync.Mutex to sync.RWMutex to match
  RLock/RUnlock calls in alertCount/webhookCount/escalationCount
- Add proper mutex locking in SendAlert/SendWebhook/SendEscalation
- Fix TestAnomaly_UnknownBLEDevice: use security mode so score (0.8)
  exceeds security threshold (0.4) instead of normal threshold (0.6)
- Fix TestAnomaly_UnusualDwell: use security mode for threshold check
- Fix TestAnomaly_SecurityModeThreshold: remove normal mode call that
  creates cooldown and prevents security mode detection
- Fix TestAnomaly_AlertChainNormalMode/SecurityMode: add waitForGoroutines()
  before checking alerts sent via goroutines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 20:58:25 -04:00
Argo Workflows CI
491def9a2e ci: auto-bump version to 0.1.21 2026-04-07 00:30:23 +00: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
Argo Workflows CI
adfab41cfa ci: auto-bump version to 0.1.20 2026-04-07 00:14:57 +00:00
jedarden
3bb58c0aa2 feat: add 7-day pattern learning algorithm for anomaly detection
Implement Welford's online algorithm for per-zone, per-hour-of-day,
per-day-of-week occupancy modeling with SQLite persistence, cold start
suppression, outlier protection, and security mode override.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 20:14:33 -04:00
Argo Workflows CI
d68b9553cd ci: auto-bump version to 0.1.19 2026-04-06 22:47:18 +00:00
jedarden
9791cd3a4f fix: correct paho v1.5.0 API mismatches in mqtt/client.go
- SetCleanOnConnect → SetCleanSession
- OnDisconnect field + OnConnectionLost → SetConnectionLostHandler
- Remove redundant type assertions in type switch cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:47:11 -04:00
jedarden
32bde5c743 fix: remove unused imports and variables in falldetect/detector.go
Remove unused "math" import, unused startZ/endZ variables, and fix
Position struct json tags to pass go vet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:47:11 -04:00
Argo Workflows CI
07db05202f ci: auto-bump version to 0.1.18 2026-04-06 22:40:19 +00:00
jedarden
ae20b4ace6 fix: type-assert result["metrics"] before indexing in sleep/handler.go 2026-04-06 18:39:56 -04:00
Argo Workflows CI
eb04b87a21 ci: auto-bump version to 0.1.17 2026-04-06 22:36:08 +00:00
jedarden
622f8eaa49 fix: rename shadowed color variable to clr in notify/service.go
The local variable `color` shadowed the `image/color` package import,
causing compilation failures on lines that referenced `color.RGBA`
after the variable was declared.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:35:42 -04:00
Argo Workflows CI
c208a7d222 ci: auto-bump version to 0.1.16 2026-04-06 22:35:02 +00:00
jedarden
0a8a3288c0 fix: replace unused linkID with blank identifier in spatial_weights.go
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:34:53 -04:00
Argo Workflows CI
80db6c6026 ci: auto-bump version to 0.1.15 2026-04-06 22:31:55 +00:00
jedarden
7c7b9266fc fix: correct oui import path in apdetector
github.com/jedarden/spaxel → github.com/spaxel/mothership

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:31:49 -04:00
Argo Workflows CI
99b9062516 ci: auto-bump version to 0.1.14 2026-04-06 22:06:56 +00:00
jedarden
4595eafab0 feat: implement install secret generation with one-time print
Auto-generate 256-bit installation secret on first run using crypto/rand,
print it exactly once to stdout, and store in SQLite for subsequent startups.
Support SPAXEL_INSTALL_SECRET env var override. Expose via GET /api/auth/install-secret
endpoint (admin session or first-run state). Derive per-node provisioning tokens
via HMAC-SHA256(install_secret, node_mac).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 18:06:33 -04:00
Argo Workflows CI
835301ce58 ci: auto-bump version to 0.1.13 2026-04-06 19:21:26 +00:00
jedarden
3781ab7f86 feat: implement BLE device discovery & registration dashboard panel
Implements a comprehensive 'People & Devices' panel for BLE device management:

Frontend (dashboard/js/ble-panel.js, dashboard/css/ble-panel.css):
- Device list sorted by sighting frequency (rssi_count)
- Registration modal with label, person assignment, color picker, device type
- Auto-type hints with icons (iPhone, Apple Watch, Fitbit, Tile, AirTag)
- Pre-registration form for manual MAC address entry
- Unregistered count badge on panel toggle
- Device details modal with sighting history

Backend (mothership/internal/ble/handler.go):
- GET /api/ble/devices with registered/discovered filters and hours parameter
- PUT /api/ble/devices/{mac} for updates (label, device_type, person_id)
- GET /api/ble/devices/{mac}/history for sighting timeline
- POST /api/ble/devices/preregister for manual device entry
- GET /api/people and POST /api/people for person management

Database (mothership/internal/ble/registry.go):
- Enhanced ble_devices table with person_id, device_type, manufacturer fields
- ble_device_sightings table for history timeline
- Auto-detection of device types from manufacturer data (Apple, Fitbit, Garmin, Tile)
- RSSI tracking and averaging

Integration (dashboard/index.html, mothership/cmd/mothership/main.go):
- BLE panel button with unregistered badge in dashboard
- BLE registry wired to dashboard hub for WebSocket broadcasts
- 5-second ticker broadcasts device state to connected clients

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 15:21:11 -04:00
Argo Workflows CI
d2e0ea2111 ci: auto-bump version to 0.1.12 2026-04-06 18:33:39 +00:00
jedarden
374b61a559 feat: implement BLE address rotation detection & identity continuity
Backend (mothership/ble/):
- RotationDetector with manufacturer data fingerprinting, time+RSSI proximity
- ble_device_aliases table for tracking rotated MAC addresses
- Identity matcher integration with alias resolution for blob-to-device scoring
- 5-minute grace period fallback when rotation is unresolved
- REST API: GET /api/ble/devices/{mac}/aliases, POST /api/ble/merge, POST /api/ble/split

Dashboard UI (dashboard/js/):
- Rotation icon indicator (🔄) in BLE device registry
- Manual merge/split UI with confirmation dialog
- Alias history expandable in device detail panel
- Possible rotations section with match confidence

Acceptance:
- Identity continuity across address rotation with >90% precision
- No duplicate person tracks created on rotation event
- Alias history queryable via GET /api/ble/devices/{mac}/aliases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:33:27 -04:00
Argo Workflows CI
75a5b58bdb ci: auto-bump version to 0.1.11 2026-04-06 18:03:32 +00:00
jedarden
d2e5b4d4a0 feat: implement passive radar auto-detection of router AP
Automatically detect the home router as a passive radar TX source,
eliminating need for a dedicated active TX node.

Firmware changes:
- During hello message, include ap_bssid and ap_channel from esp_wifi_sta_get_ap_info()

Mothership changes:
- On hello: extract ap_bssid; if >=80% of nodes report same BSSID create virtual node entry with virtual=1
- OUI lookup: embedded IEEE OUI registry as Go map compiled via go:embed; display router brand
- Detect AP BSSID change (router reboot/replacement) and emit system alert
- SQLite nodes table: add virtual BOOL, node_type TEXT, ap_bssid TEXT, ap_channel INT columns

Dashboard changes:
- Show "I detected your router (ASUS). Place it on the floor plan..." notification
- Render virtual AP nodes with distinct router icon in 3D view
- Drag-to-place virtual node (distinct router icon) in 3D editor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:03:03 -04:00
Argo Workflows CI
8a65625f84 ci: auto-bump version to 0.1.10 2026-04-06 17:31:34 +00:00
jedarden
34a2247fd9 feat: implement detection explainability overlay with per-link contributions, Fresnel visualization, and BLE match display
- Add explainability.js module with sidebar panel, X-ray overlay, Fresnel zone rendering
- Add explainability handler with /api/explain/{blobID} endpoint
- Fix viz3d.js CONFIG reference by adding FRESNEL_CONFIG constant
- Integrate explainability into fusion engine and ingestion server

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 13:31:17 -04:00
Argo Workflows CI
635be60084 ci: auto-bump version to 0.1.9 2026-04-06 17:16:48 +00:00
jedarden
e83b54a9ec feat: implement dashboard PIN authentication and session management
Backend (mothership/internal/auth/):
- SQLite auth table with pin_bcrypt and install_secret (singleton row)
- GET /api/auth/status — return {pin_configured: bool}
- POST /api/auth/setup — sets PIN (bcrypt cost 12) on first run only
- POST /api/auth/login — verifies PIN, issues session cookie (7-day expiry)
- POST /api/auth/logout — clears cookie and deletes session from SQLite
- Session middleware: all /api/* and /ws/* require valid session
- Rolling window: extends session by 7 days if within 24h of expiry
- Install secret generation for node token derivation

Dashboard (dashboard/js/auth.js):
- On load: GET /api/auth/status check
- First-run setup page: enter PIN + confirm PIN → POST /api/auth/setup → reload
- Login page: shown on 401; PIN entry → POST /api/auth/login → reload
- Logout button in settings panel → POST /api/auth/logout → redirect

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 13:16:04 -04:00
Argo Workflows CI
60ada3ccb0 ci: auto-bump version to 0.1.8 2026-04-06 16:01:33 +00: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
Argo Workflows CI
cbb931f4aa ci: auto-bump version to 0.1.7 2026-04-06 15:22:13 +00: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
Argo Workflows CI
201922a13e ci: auto-bump version to 0.1.6 2026-04-06 15:05:21 +00:00
jedarden
f9632c7df4 fix: resolve deadlock in database migration engine
Fixed a deadlock in the Migrator where Pending() and Migrate() methods
called CurrentVersion() while holding the lock, but CurrentVersion()
also tried to acquire the same lock. Created internal currentVersionLocked()
method for lock-safe access.

Also fixed unused imports in migrations.go and fixed NOT NULL constraint
in TestMigrateFromV1 test.

All tests pass including:
- TestMigrateIdempotent: running migrations on already-migrated DB is no-op
- TestMigrateFromV1: migrating from v1 to current version
- TestMigrationRollback: failed migrations roll back cleanly
- TestPreMigrationBackup: backups created before schema changes
- TestPendingMigrations: pending migrations correctly identified
- TestCurrentVersion: version queries work for all DB states
- TestBackupPruning: old backups pruned correctly
- TestOpenDBFullSequence: full 7-phase startup sequence

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