Commit graph

3 commits

Author SHA1 Message Date
jedarden
285d9eb189 feat(sim): provision real per-node HMAC token by default (bf-4mle6)
spaxel-sim now mints a real per-node HMAC token via POST /api/provision
(--provision, default true), presented as X-Spaxel-Token and validated
server-side regardless of the migration window. This makes the
hardware-free build's acceptance durable and window-independent: the sim
connects and streams identically under SPAXEL_MIGRATION_WINDOW_HOURS=0,
24, or larger.

- cmd/sim/main.go: --provision (default) / --provision=false (legacy
  window-dependent dummy) / --token <t> (verbatim override);
  resolveTokens() + provisionNodeToken().
- PROGRESS.md: document the window-independent auth policy with the exact
  human-run command (window=0 + --provision), and supersede the bf-2hdbg
  "24h-window mask, not a fix" conclusion (RESOLVED by the bf-1o7qi
  header bridge + this provisioning change; historical text preserved).

Verified: go build/vet ./cmd/sim clean. Window-independent acceptance is
proven by the e2e harness under SPAXEL_MIGRATION_WINDOW_HOURS=0
(bf-qzrmq, 250056c) and the hello.Token validation bridge (bf-1o7qi,
9c38cbb) — both already committed.

The bf-4q5w IO-6 hard-gate harness code in
mothership/tests/e2e/e2e_test.go is intentionally NOT included here; it
belongs to the still-open bf-4q5w.

Co-Authored-By: Claude <noreply@anthropic.com>
Bead-Id: bf-42cao
2026-07-07 15:16:30 -04:00
jedarden
d048987d61 feat(ingestion): persist hello-announced node position in fleet registry (bf-24xp)
Some checks are pending
CI Benchmark - Fusion Loop Timing / Fusion Loop Timing Benchmark (push) Waiting to run
spaxel-sim computed good corner/perimeter geometry in createVirtualNodes but
the hello message sent on WebSocket connect did not include position, so the
mothership never learned the sim node's location and the fleet registry/DB row
was left at the nodes-table schema default (0,0,1) — co-located with every
other node.

Both sim CLIs (cmd/sim and mothership/cmd/sim) now announce pos_x/pos_y/pos_z
in the hello handshake, sourced from createVirtualNodes. HelloMessage gains
PosX/PosY/PosZ as *float64 (not plain float64) so an absent position is
distinguishable from a genuine (0,0,0): a real ESP32 omits these in hello
(its position is user-placed in the dashboard), whereas spaxel-sim announces
its computed geometry.

The connect/register path (server.HandleNodeWS -> FleetNotifier.OnNodeConnected
-> fleet.Manager) now carries the announced position through. The Manager
persists it via registry.SetNodePosition only when all three axes are present,
so a nil/partial announcement preserves any existing user-placed position
rather than clobbering it. The position then flows onward to the fusion engine
through the bf-3p6g connect/register sink (ForwardNodePosition ->
nodePositionSink -> fusionEngine.SetNodePosition), so a freshly connected sim
node is seeded at its announced location instead of (0,0,1).

The FleetNotifier interface change (OnNodeConnected gains three *float64
params) is propagated to every implementer — Manager (persists), FleetHealer
and SelfHealManager (read geometry from the registry, ignore), the guided-
troubleshoot notifier (tracks connect/disconnect only), and the cmd/mothership
multiFleetNotifier fan-out.

Tests: existing OnNodeConnected call sites updated to the new signature.
TestManagerOnNodeConnectedPersistsHelloPosition asserts a node connecting with
an announced position yields a registry row whose pos differs from (0,0,1) and
matches the sent coordinates, and that the same coordinates reach the fusion
engine. TestManagerOnNodeConnectedWithoutHelloPositionPreservesExisting
asserts the real-ESP32 case (nil announce) and partial-announce both leave an
existing user-placed position untouched.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-03 18:42:34 -04:00
jedarden
b34892edfc simulator: implement spaxel-sim CLI tool
Implemented the CSI simulator CLI tool for testing Spaxel without
hardware. The simulator connects to a running mothership via WebSocket
and streams synthetic CSI binary frames.

Features:
- Virtual nodes positioned at corners, evenly distributed
- Walker random walk with Gaussian velocity updates (σ=0.3 m/s per axis per 50ms)
- Synthetic CSI generation using propagation model (path-loss + Fresnel zones)
- Binary frame format matching ingestion/frame.go (24-byte header + n_sub*2 payload)
- RSSI calculation: clamp(-30 - path_loss_dB, -90, -30)
- BLE advertisement simulation every 5s when --ble flag is set
- Reject detection: exits non-zero on {type:'reject'} from mothership
- Per-second stats: frame counts and blob count (from GET /api/blobs poll)

CLI Interface:
  spaxel-sim --mothership ws://localhost:8080/ws/node --token <token> \
             --nodes 4 --walkers 1 --rate 20 --duration 60s --ble \
             --seed 42 --space '6x5x2.5'

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 00:17:42 -04:00