ruv
b41681e079
fix(firmware): make QEMU mock CSI boot successfully on Windows
...
Tested on Windows with Espressif QEMU 9.0.0 — firmware boots,
generates mock CSI frames, runs edge processing. 14/16 validation
checks pass.
Fixes:
- Guard wifi_init_sta() with CONFIG_CSI_MOCK_SKIP_WIFI_CONNECT
(QEMU has no RF PHY, WiFi init stalled at calibration)
- Guard stream_sender_init_with() (UDP needs network stack)
- Guard ota_update_init_ex() (HTTP server needs network)
- Guard display_task_start() with CONFIG_DISPLAY_ENABLE
(no I2C hardware in QEMU)
- Add mock_csi_init() call in main.c when CONFIG_CSI_MOCK_ENABLED
- Add #include "sdkconfig.h" to mock_csi.c (ESP-IDF not auto-including)
- Suppress unused s_bad_mac warning
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-14 13:33:07 -04:00
ruv
e574cbe129
fix(qemu): resolve 23 bugs from deep code review
...
CRITICAL:
- inject_fault.py: make nvs_corrupt write actual bytes via --flash arg;
heap_exhaust and corrupt_frame now pause VM with honest WARNING about
GDB stub requirement for real memory writes
- firmware-qemu.yml: remove github.run_id from cache key (was causing
100% cache miss rate, rebuilding QEMU every run)
- mock_csi.c: change scenario_elapsed_ms() to int64_t (uint32 wrapped
at ~49 days)
HIGH:
- qemu-mesh-test.sh: pass --results flag to validate_mesh_test.py
(was passing positional arg to named-only parameter)
- test/Makefile: separate corpus directories per fuzz target
(corpus_serialize/, corpus_edge/, corpus_nvs/)
- qemu-snapshot-test.sh: replace log truncation with tail-based
extraction (truncation created sparse file while QEMU held fd)
MEDIUM:
- mock_csi.c: reset s_mac_filter_initialized in mock_csi_init()
- mock_csi.c: fix LFSR polynomial comment (32,31,29,1 not 32,22,2,1)
- sdkconfig.coverage: add FreeRTOS timer stack 4096 and WDT tuning
- firmware-qemu.yml: replace continue-on-error with FUZZER_CRASH env
- qemu-chaos-test.sh: rename heap_pressure to heap_exhaust for consistency
- validate_qemu_output.py: fix docstring "14 checks" -> "16 checks"
- generate_nvs_matrix.py: deduplicate temp file cleanup paths
LOW:
- mock_csi.c: remove M_PI float suffix, fix overflow burst flag
- qemu-snapshot-test.sh: fix now_ms() for macOS date +%s%N
- ADR-061: fix scenario 8 RSSI range to -90...-10 dBm
- launch.json: remove contradictory compound debug config
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-14 11:28:57 -04:00
ruv
fb2d1afb0c
feat(firmware): complete ADR-061 QEMU testing platform (all 9 layers)
...
Fix 9 bugs (LFSR bias, MAC filter init, scenario loop, NVS boundary
values), add 7 new files completing Layers 3 (mesh), 4 (GDB), 5
(coverage), 8 (snapshots), 9 (chaos testing), expand CI with fuzz
and NVS validation jobs, update README with full platform overview.
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-14 11:08:59 -04:00
ruv
ffeaa46bc6
feat(firmware): QEMU ESP32-S3 testing platform (ADR-061)
...
Implement full QEMU emulation framework for firmware testing without
physical hardware:
Mock CSI Generator (mock_csi.c):
- 10 test scenarios: empty room, static/walking person, fall, multi-person,
channel sweep, MAC filter, ring overflow, boundary RSSI, zero-length
- Physics-based signal model with breathing modulation and Doppler
- LFSR pseudo-random noise, CONFIG_CSI_MOCK_ENABLED Kconfig guard
- Scenario 255 runs all sequentially
QEMU Runner & CI:
- qemu-esp32s3-test.sh: build, merge flash image, run QEMU, validate
- validate_qemu_output.py: 14 automated checks (boot, NVS, edge, vitals,
crash detection) with colored output and severity-based exit codes
- generate_nvs_matrix.py: 14 NVS provisioning configs for matrix testing
- firmware-qemu.yml: GitHub Actions CI with 4-scenario matrix
Fuzz Testing:
- 3 libFuzzer targets: CSI serialize, NVS config validation, ring buffer
- Host-compilable ESP-IDF stubs (no ESP-IDF dependency for fuzzing)
- 6 seed corpus files for guided fuzzing
- Makefile with ASAN + UBSAN sanitizers
Documentation:
- firmware/esp32-csi-node/README.md: comprehensive QEMU testing guide
- Root README.md: collapsed QEMU testing section
Build verified: normal firmware build (RC=0) with mock_csi excluded.
Closes #259
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-13 09:17:07 -04:00
rUv
d793c1f49f
feat(firmware): --channel and --filter-mac provisioning (ADR-060)
...
- provision.py: add --channel (CSI channel override) and --filter-mac
(AA:BB:CC:DD:EE:FF format) arguments with validation
- nvs_config: add csi_channel, filter_mac[6], filter_mac_set fields;
read from NVS on boot
- csi_collector: auto-detect AP channel when no NVS override is set;
filter CSI frames by source MAC when filter_mac is configured
- ADR-060 documents the design and rationale
Fixes #247 , fixes #229
2026-03-13 08:27:08 -04:00
ruv
952f27a1ce
fix(firmware): enable CSI in sdkconfig and add build guard (ADR-057)
...
The committed sdkconfig had CONFIG_ESP_WIFI_CSI_ENABLED disabled, causing
all builds to crash at runtime with "CSI not enabled in menuconfig".
Root cause: sdkconfig.defaults.template existed but ESP-IDF only reads
sdkconfig.defaults (no .template suffix).
Fixes:
- Add sdkconfig.defaults with CONFIG_ESP_WIFI_CSI_ENABLED=y
- Add #error compile guard in csi_collector.c to prevent recurrence
- Fix NVS encryption default (requires eFuse, breaks clean builds)
Verified: Docker build + flash to ESP32-S3 + CSI callbacks confirmed.
Closes #241
Relates to #223 , #238 , #234 , #210 , #190
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-12 13:49:20 -04:00
ruv
47223a98be
fix: security hardening — replace fake HMAC, add path traversal protection, OTA auth (ADR-050)
...
Sprint 1 security fixes from quality engineering analysis (issue #170 ):
- Replace XOR-fold fake HMAC with real HMAC-SHA256 (hmac + sha2 crates) in secure_tdm.rs
- Add path traversal sanitization on DELETE /api/v1/models/:id and /api/v1/recording/:id
- Default bind address changed from 0.0.0.0 to 127.0.0.1 (configurable via --bind-addr / SENSING_BIND_ADDR)
- Add PSK authentication to ESP32 OTA firmware upload endpoint (ota_update.c)
- Flip WASM signature verification to default-on (CONFIG_WASM_SKIP_SIGNATURE opt-out vs opt-in)
- Add 6 new security tests: HMAC key/message sensitivity, determinism, wrong-key rejection, bit-flip detection, enforcing mode
- Add clap env feature for environment variable configuration
All 106 hardware crate tests pass. Sensing server compiles clean.
Closes #170
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-06 13:11:04 -05:00
ruv
c45690ed4e
fix: use montserrat_14 for display_ui big label (montserrat_20 not in Kconfig)
...
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-05 11:45:59 -05:00
ruv
8b57a6f64c
docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display
...
- Update ADR count from 44 to 48
- Add adaptive classifier (ADR-048) to Intelligence features
- Add Observatory visualization (ADR-047) and AMOLED display (ADR-045) to Deployment features
- Update screenshot to v2-screen.png
- Add ADR-045 (AMOLED), ADR-046 (Android TV), ADR-047 (Observatory), DDD deployment model
- Add AMOLED display firmware (display_hal, display_task, display_ui, LVGL config)
- Add Observatory UI (13 Three.js modules, CSS, HTML entry point)
- Add trained adaptive model JSON
- Update .gitignore for managed_components, recordings, .swarm
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-05 10:20:48 -05:00
rUv
ce171696b2
fix: rate-limit CSI sends and add ENOMEM backoff to prevent crash ( #132 )
...
The CSI callback fires for every WiFi frame in promiscuous mode
(100-500+ fps). Each call invoked sendto() synchronously, exhausting
lwIP packet buffers (errno 12 = ENOMEM). The rapid-fire failures
cascaded into a LoadProhibited guru meditation crash.
Two fixes:
1. csi_collector.c: Rate-limit UDP sends to 50 Hz (20ms interval).
CSI frames arriving between sends are dropped — the sensing
pipeline only needs 20-50 Hz.
2. stream_sender.c: When sendto fails with ENOMEM, suppress further
sends for 100ms to let lwIP reclaim buffers. Logs the backoff
event and resumes automatically.
Closes #127
2026-03-03 16:00:40 -05:00
ruv
4b1005524e
feat: complete vendor repos, add edge intelligence and WASM modules
...
- Add 154 missing vendor files (gitignore was filtering them)
- vendor/midstream: 564 files (was 561)
- vendor/sublinear-time-solver: 1190 files (was 1039)
- Add ESP32 edge processing (ADR-039): presence, vitals, fall detection
- Add WASM programmable sensing (ADR-040/041) with wasm3 runtime
- Add firmware CI workflow (.github/workflows/firmware-ci.yml)
- Add wifi-densepose-wasm-edge crate for edge WASM modules
- Update sensing server, provision.py, UI components
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-02 23:53:25 -05:00
rUv
915943cef4
feat: ESP32 CSI MAC address filtering with NVS/Kconfig support ( #101 )
...
* feat: add MAC address filter for ESP32 CSI collection
In multi-AP environments, CSI frames from different access points get
mixed together, corrupting the sensing signal. Add transmitter MAC
filtering so only frames from a specified AP are processed.
Implementation:
- csi_collector: filter in wifi_csi_callback by comparing info->mac
against configured MAC; log transmitter MAC in periodic debug output
- csi_collector_set_filter_mac(): runtime API to enable/disable filter
- Kconfig: CSI_FILTER_MAC option (format "AA:BB:CC:DD:EE:FF")
- NVS: "filter_mac" 6-byte blob overrides Kconfig at runtime
- nvs_config: parse Kconfig MAC string at boot, load NVS override
- main: apply filter from config after csi_collector_init()
When no filter is configured (default), behavior is unchanged —
all transmitter MACs are accepted for backward compatibility.
Fixes #98
Co-Authored-By: claude-flow <ruv@ruv.net>
* chore: add CLAUDE.local.md to .gitignore
Local machine configuration (ESP-IDF paths, COM port, build
instructions) should not be committed to the repository.
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-02 17:08:27 -05:00
ruv
303871275b
feat: ADR-029/031 TDM sensing protocol, channel hopping, and NVS config
...
Implement the hardware and firmware portions of RuvSense (ADR-029) and
RuView (ADR-031) for multistatic WiFi sensing:
Rust (wifi-densepose-hardware):
- TdmSchedule: uniform slot assignments with configurable cycle period,
guard intervals, and processing window (default 4-node 20 Hz)
- TdmCoordinator: manages sensing cycles, tracks per-slot completion,
cumulative clock drift compensation (±10 ppm over 50 ms = 0.5 us)
- SyncBeacon: 16-byte wire format for cycle synchronization with
drift correction offsets
- TdmSlotCompleted event for aggregator notification
- 18 unit tests + 4 doctests, all passing
Firmware (C, ESP32):
- Channel-hop table in csi_collector.c (s_hop_channels, configurable
via csi_collector_set_hop_table)
- Timer-driven channel hopping via esp_timer at dwell intervals
- NDP frame injection stub via esp_wifi_80211_tx()
- Backward-compatible: hop_count=1 disables hopping entirely
- NVS config extension: hop_count, chan_list, dwell_ms, tdm_slot,
tdm_node_count with bounds validation and Kconfig fallback defaults
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-01 21:33:48 -05:00
ruv
7872987ee6
fix(docker): Update Dockerfile paths from src/ to v1/src/
...
The source code was moved to v1/src/ but the Dockerfile still
referenced src/ directly, causing build failures. Updated all
COPY paths, uvicorn module paths, test paths, and bandit scan
paths. Also added missing v1/__init__.py for Python module
resolution.
Fixes #33
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-02-28 13:38:21 -05:00
rUv
92a5182dc3
feat(adr-018): ESP32-S3 firmware, Rust aggregator, and live CSI pipeline
...
Complete end-to-end WiFi CSI capture pipeline verified on real hardware:
- ESP32-S3 firmware: WiFi STA + promiscuous mode CSI collection,
ADR-018 binary serialization, UDP streaming at ~20 Hz
- Rust aggregator CLI binary (clap): receives UDP frames, parses with
Esp32CsiParser, prints per-frame summary (node, seq, rssi, amp)
- UDP aggregator module with per-node sequence tracking and drop detection
- CsiFrame bridge to detection pipeline (amplitude/phase/SNR conversion)
- Python ESP32 binary parser with UDP reader
- Presence detection confirmed: motion score 10/10 from live CSI variance
Hardware verified: ESP32-S3-DevKitC-1 (CP2102, MAC 3C:0F:02:EC:C2:28),
Docker ESP-IDF v5.2 build, esptool 5.1.0 flash, 20 Rust + 6 Python tests pass.
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-02-28 13:22:04 -05:00