mirror of
https://github.com/ruvnet/RuView
synced 2026-08-06 19:51:43 +00:00
1ed0bc57ef
A cross-vendor pre-merge sweep found no merge blockers, but did surface an
error in ADR-271 that I wrote — and a coherence gap behind it.
ADR-271 P2 stated that capping the browser session at `sensing:read` was
"considered and rejected, because the dashboard genuinely performs admin
operations". That is wrong. `/oauth/start` (main.rs:9206) already requests
`SENSING_READ` and nothing else, deliberately, with a comment saying so. The
browser session is ALREADY read-only, so the breakage I claimed capping would
cause is simply the current behaviour.
Two consequences, now stated in the ADR instead of left to be discovered:
1. The UI's admin controls do not work from a browser OAuth session.
`model.service.js:136` issues DELETE /api/v1/models/{id}, which 401s. Admin
work needs the CLI (`login --admin`) or a pasted admin bearer. A gap in a new
feature, not a regression — the token-paste path is unchanged.
2. The ADMIN_REVERIFY_SECS step-up control added in the previous commit guards
a case that cannot currently arise. No browser session holds `sensing:admin`,
so the freshness branch never fires in production. Its tests pass because the
crate-internal seam mints an admin cookie the real flow never produces.
That second point is worth being blunt about: it is the same shape as several
defects this branch already fixed — correct code, green tests, unreachable call
site. The difference is that here the guard is deliberately ahead of the need
rather than mistakenly behind it, and saying which one it is matters.
So the constant is now named `BROWSER_SIGNIN_SCOPE` rather than inlined, with
the cost of widening it documented at the definition, and two tests:
`browser_sign_in_stays_read_only_until_someone_decides_otherwise` pins the
value, and `the_authorize_url_actually_carries_that_scope` proves it reaches the
wire — asserting on the constant alone would pass even if `begin` were called
with something else, which is exactly the isolation failure being guarded
against.
The ADR also records the coherent way to add browser-side admin if wanted:
escalate-on-demand via the RFC 6750 challenge, keeping least privilege by
default rather than asking every user to consent to delete capability to watch
a stream. Not bundled here — it needs a scope parameter and a UI affordance.
Sweep verdict: no merge blockers. Two other non-blocking risks it raised are
accurate and unchanged: concurrent JWKS refresh at the stale boundary is not
atomic (a duplicated idempotent GET, already documented as an accepted cost),
and the service worker's SHELL_ASSETS use root-relative paths while the UI
mounts under /ui, so offline shell precaching is incomplete — pre-existing,
unrelated to this branch.
Verified: workspace 176 suites clean.
Co-Authored-By: Ruflo & AQE
wifi-densepose-sensing-server
Lightweight Axum server for real-time WiFi sensing with RuVector signal processing.
Overview
wifi-densepose-sensing-server is the operational backend for WiFi-DensePose. It receives raw CSI
frames from ESP32 hardware over UDP, runs them through the RuVector-powered signal processing
pipeline, and broadcasts processed sensing updates to browser clients via WebSocket. A built-in
static file server hosts the sensing UI on the same port.
The crate ships both a library (wifi_densepose_sensing_server) exposing the training and inference
modules, and a binary (sensing-server) that starts the full server stack.
Integrates wifi-densepose-wifiscan for multi-BSSID WiFi scanning per ADR-022 Phase 3.
Features
- UDP CSI ingestion -- Receives ESP32 CSI frames on port 5005 and parses them into the internal
CsiFramerepresentation. - Vital sign detection -- Pure-Rust FFT-based breathing rate (0.1--0.5 Hz) and heart rate (0.67--2.0 Hz) estimation from CSI amplitude time series (ADR-021).
- RVF container -- Standalone binary container format for packaging model weights, metadata, and
configuration into a single
.rvffile with 64-byte aligned segments. - RVF pipeline -- Progressive model loading with streaming segment decoding.
- Graph Transformer -- Cross-attention bottleneck between antenna-space CSI features and the
COCO 17-keypoint body graph, followed by GCN message passing (ADR-023 Phase 2). Pure
std, no ML dependencies. - SONA adaptation -- LoRA + EWC++ online adaptation for environment drift without catastrophic forgetting (ADR-023 Phase 5).
- Contrastive CSI embeddings -- Self-supervised SimCLR-style pretraining with InfoNCE loss, projection head, fingerprint indexing, and cross-modal pose alignment (ADR-024).
- Sparse inference -- Activation profiling, sparse matrix-vector multiply, INT8/FP16 quantization, and a full sparse inference engine for edge deployment (ADR-023 Phase 6).
- Dataset pipeline -- Training dataset loading and batching.
- Multi-BSSID scanning -- Windows
netshintegration for BSSID discovery viawifi-densepose-wifiscan(ADR-022). - WebSocket broadcast -- Real-time sensing updates pushed to all connected clients at
ws://localhost:8765/ws/sensing. - Static file serving -- Hosts the sensing UI on port 8080 with CORS headers.
Modules
| Module | Description |
|---|---|
vital_signs |
Breathing and heart rate extraction via FFT spectral analysis |
rvf_container |
RVF binary format builder and reader |
rvf_pipeline |
Progressive model loading from RVF containers |
graph_transformer |
Graph Transformer + GCN for CSI-to-pose estimation |
trainer |
Training loop orchestration |
dataset |
Training data loading and batching |
sona |
LoRA adapters and EWC++ continual learning |
sparse_inference |
Neuron profiling, sparse matmul, INT8/FP16 quantization |
embedding |
Contrastive CSI embedding model and fingerprint index |
Quick Start
# Build the server
cargo build -p wifi-densepose-sensing-server
# Run with default settings (HTTP :8080, UDP :5005, WS :8765)
cargo run -p wifi-densepose-sensing-server
# Run with custom ports
cargo run -p wifi-densepose-sensing-server -- \
--http-port 9000 \
--udp-port 5005 \
--static-dir ./ui
Using as a library
use wifi_densepose_sensing_server::vital_signs::VitalSignDetector;
// Create a detector with 20 Hz sample rate
let mut detector = VitalSignDetector::new(20.0);
// Feed CSI amplitude samples
for amplitude in csi_amplitudes.iter() {
detector.push_sample(*amplitude);
}
// Extract vital signs
if let Some(vitals) = detector.detect() {
println!("Breathing: {:.1} BPM", vitals.breathing_rate_bpm);
println!("Heart rate: {:.0} BPM", vitals.heart_rate_bpm);
}
Architecture
ESP32 ──UDP:5005──> [ CSI Receiver ]
|
[ Signal Pipeline ]
(vital_signs, graph_transformer, sona)
|
[ WebSocket Broadcast ]
|
Browser <──WS:8765── [ Axum Server :8080 ] ──> Static UI files
Related Crates
| Crate | Role |
|---|---|
wifi-densepose-wifiscan |
Multi-BSSID WiFi scanning (ADR-022) |
wifi-densepose-core |
Shared types and traits |
wifi-densepose-signal |
CSI signal processing algorithms |
wifi-densepose-hardware |
ESP32 hardware interfaces |
wifi-densepose-wasm |
Browser WASM bindings for the sensing UI |
wifi-densepose-train |
Full training pipeline with ruvector |
wifi-densepose-mat |
Disaster detection module |
License
MIT OR Apache-2.0