Files
ruvnet--RuView/v2/crates
Dragan Spiridonov 499cec7914 feat(auth): ruview-auth — offline Cognitum OAuth access-token verification (ADR-271)
RuView's `/api/v1/*` is gated today by `RUVIEW_API_TOKEN`: one shared secret,
no expiry, no per-user attribution. This adds the verifier half of replacing
that with Cognitum identity — RuView as an OAuth **resource server**, so a user
signs in to their own sensing server with their Cognitum account.

Note the direction: RuView does not call Cognitum. It never obtains a token for
its own use; it verifies tokens users present. Every other Cognitum OAuth
integration in the org (meta-proxy, musica, metaharness, the dashboard CLI) is
the client side of a plane RuView doesn't have. The one existing resource-server
verifier is `meta-llm/src/auth/oauthBearer.ts`, and this crate is a port of its
accept-rule — divergence would be a bug, not a preference: a token meta-llm
rejects must not be one RuView accepts.

Verification is OFFLINE, and that is a requirement rather than an optimisation.
RuView runs on Pi-class hardware that loses WAN, and identity publishes no
introspection endpoint even when the network is up. So: ES256 over identity's
published JWKS, cached by `kid`.

What it accepts, mirroring oauthBearer.ts:
  typ == "access" AND NOT setup AND NOT workload AND account_id non-empty AND
  exp in the future AND iss matches verbatim AND the required scope is held.

Long-lived setup (365-day) and workload credentials are refused outright for
identity's own stated reason: their revocation lives in `oauth_setup_tokens`,
and RuView — like meta-llm — has no database to check it. A 15-minute access
token needs no revocation round-trip because it expires faster than revocation
propagates; a 365-day one does.

Scope is the capability boundary, and it has to be. Cognitum access tokens carry
no `aud`, and `client_id` cannot substitute because clients borrow each other's
registrations (musica ships DEFAULT_CLIENT_ID = "meta-proxy"). `sensing:read`
covers streams and inference; `sensing:admin` covers training, model delete and
recording delete. No hierarchy — admin does not imply read; consent means what
it said. Registered in identity migration 0016 (cognitum-one/dashboard#116).

Design notes:
- `ureq`, not `reqwest`: the sensing server deliberately chose ureq as "the
  smallest" HTTP client, and pulling reqwest in here would reverse that for the
  whole graph. Transport sits behind a `JwksFetcher` trait, so a host can supply
  its own and take no HTTP dependency at all (feature `ureq-transport`, default).
- A JWKS refetch failure is survivable while a key set is already cached: a key
  that verified a minute ago has not stopped being valid because the network
  blipped, and failing closed there logs every user out of their own sensing
  server whenever their internet wobbles. We fail closed in exactly one case —
  no key set has ever been fetched.
- Unknown `kid` forces one refetch so rotation is picked up without waiting out
  the TTL, rate-limited so junk-kid tokens can't become a request amplifier
  aimed at identity.
- Expiry is reported distinctly from a bad signature: on an RTC-less Pi that is
  usually a clock-sync fault, and an operator must be able to tell them apart.
- Test keypairs are generated at runtime, never committed. This repo tracks zero
  `.pem` files and committed key material shouldn't start here — it also means
  no fixture can drift out of sync with the JWKS it's served by.

Tests: 41 green (19 unit + 21 matrix + 1 doctest) under BOTH
`cargo test --no-default-features` (the repo's canonical gate) and default
features. The matrix signs real ES256 tokens rather than asserting on strings,
and covers alg:none, forged signature, spliced payload, unknown kid, expired,
leeway boundaries both sides, wrong issuer, issuer differing only by a trailing
slash, missing/!=access typ, setup and workload smuggled onto typ=access,
missing and empty account_id, and scope escalation.

The highest-value case is `g2_a_genuinely_valid_token_from_another_cognitum_
product_cannot_reach_the_sensing_surface`: a correctly signed, unexpired,
right-issuer, right-typ token with client_id=meta-proxy and scope=inference is
rejected. Nothing about its signature or identity claims distinguishes it — only
scope does. A naive verifier accepts it, and an `inference` token becomes a key
to someone's home sensor.

No wiring into the sensing server yet; this crate is verification only, with no
login flow and no outbound Cognitum calls.

Co-Authored-By: Ruflo & AQE
2026-07-22 15:08:40 +02:00
..

WiFi-DensePose Rust Crates

License: MIT OR Apache-2.0 Rust 1.85+ Workspace RuVector v2.0.4 Tests

See through walls with WiFi. No cameras. No wearables. Just radio waves.

A modular Rust workspace for WiFi-based human pose estimation, vital sign monitoring, and disaster response using Channel State Information (CSI). Built on RuVector graph algorithms and the WiFi-DensePose research platform by rUv.


Performance

Operation Python v1 Rust v2 Speedup
CSI Preprocessing ~5 ms 5.19 us ~1000x
Phase Sanitization ~3 ms 3.84 us ~780x
Feature Extraction ~8 ms 9.03 us ~890x
Motion Detection ~1 ms 186 ns ~5400x
Full Pipeline ~15 ms 18.47 us ~810x
Vital Signs N/A 86 us (11,665 fps) --

Crate Overview

Core Foundation

Crate Description crates.io
wifi-densepose-core Types, traits, and utilities (CsiFrame, PoseEstimate, SignalProcessor) crates.io
wifi-densepose-config Configuration management (env, TOML, YAML) crates.io
wifi-densepose-db Database persistence (PostgreSQL, SQLite, Redis) crates.io

Signal Processing & Sensing

Crate Description RuVector Integration crates.io
wifi-densepose-signal SOTA CSI signal processing (6 algorithms from SpotFi, FarSense, Widar 3.0) ruvector-mincut, ruvector-attn-mincut, ruvector-attention, ruvector-solver crates.io
wifi-densepose-vitals Vital sign extraction: breathing (6-30 BPM) and heart rate (40-120 BPM) -- crates.io
wifi-densepose-wifiscan Multi-BSSID WiFi scanning for Windows-enhanced sensing -- crates.io

Neural Network & Training

Crate Description RuVector Integration crates.io
wifi-densepose-nn Multi-backend inference (ONNX, PyTorch, Candle) with DensePose head (24 body parts) -- crates.io
wifi-densepose-train Training pipeline with MM-Fi dataset, 114->56 subcarrier interpolation All 5 crates crates.io

Disaster Response

Crate Description RuVector Integration crates.io
wifi-densepose-mat Mass Casualty Assessment Tool -- survivor detection, triage, multi-AP localization ruvector-solver, ruvector-temporal-tensor crates.io

Hardware & Deployment

Crate Description crates.io
wifi-densepose-hardware ESP32, Intel 5300, Atheros CSI sensor interfaces (pure Rust, no FFI) crates.io
wifi-densepose-wasm WebAssembly bindings for browser-based disaster dashboard crates.io
wifi-densepose-sensing-server Axum server: ESP32 UDP ingestion, WebSocket broadcast, sensing UI crates.io

Applications

Crate Description crates.io
wifi-densepose-api REST + WebSocket API layer crates.io
wifi-densepose-cli Command-line tool for MAT disaster scanning crates.io

Architecture

                          wifi-densepose-core
                         (types, traits, errors)
                                  |
              +-------------------+-------------------+
              |                   |                   |
    wifi-densepose-signal   wifi-densepose-nn   wifi-densepose-hardware
    (CSI processing)        (inference)         (ESP32, Intel 5300)
    + ruvector-mincut       + ONNX Runtime          |
    + ruvector-attn-mincut  + PyTorch (tch)   wifi-densepose-vitals
    + ruvector-attention    + Candle          (breathing, heart rate)
    + ruvector-solver            |
              |                  |             wifi-densepose-wifiscan
              +--------+---------+            (BSSID scanning)
                       |
          +------------+------------+
          |                         |
  wifi-densepose-train    wifi-densepose-mat
  (training pipeline)     (disaster response)
  + ALL 5 ruvector        + ruvector-solver
                          + ruvector-temporal-tensor
                                |
              +-----------------+-----------------+
              |                 |                 |
    wifi-densepose-api  wifi-densepose-wasm  wifi-densepose-cli
    (REST/WS)           (browser WASM)       (CLI tool)
              |
    wifi-densepose-sensing-server
    (Axum + WebSocket)

RuVector Integration

All RuVector crates at v2.0.4 from crates.io:

RuVector Crate Used In Purpose
ruvector-mincut signal, train Dynamic min-cut for subcarrier selection & person matching
ruvector-attn-mincut signal, train Attention-weighted min-cut for antenna gating & spectrograms
ruvector-temporal-tensor train, mat Tiered temporal compression (4-10x memory reduction)
ruvector-solver signal, train, mat Sparse Neumann solver for interpolation & triangulation
ruvector-attention signal, train Scaled dot-product attention for spatial features & BVP

Signal Processing Algorithms

Six state-of-the-art algorithms implemented in wifi-densepose-signal:

Algorithm Paper Year Module
Conjugate Multiplication SpotFi (SIGCOMM) 2015 csi_ratio.rs
Hampel Filter WiGest 2015 hampel.rs
Fresnel Zone Model FarSense (MobiCom) 2019 fresnel.rs
CSI Spectrogram Standard STFT 2018+ spectrogram.rs
Subcarrier Selection WiDance (MobiCom) 2017 subcarrier_selection.rs
Body Velocity Profile Widar 3.0 (MobiSys) 2019 bvp.rs

Quick Start

As a Library

use wifi_densepose_core::{CsiFrame, CsiMetadata, SignalProcessor};
use wifi_densepose_signal::{CsiProcessor, CsiProcessorConfig};

// Configure the CSI processor
let config = CsiProcessorConfig::default();
let processor = CsiProcessor::new(config);

// Process a CSI frame
let frame = CsiFrame { /* ... */ };
let processed = processor.process(&frame)?;

Vital Sign Monitoring

use wifi_densepose_vitals::{
    CsiVitalPreprocessor, BreathingExtractor, HeartRateExtractor,
    VitalAnomalyDetector,
};

let mut preprocessor = CsiVitalPreprocessor::new(56); // 56 subcarriers
let mut breathing = BreathingExtractor::new(100.0);    // 100 Hz sample rate
let mut heartrate = HeartRateExtractor::new(100.0);

// Feed CSI frames and extract vitals
for frame in csi_stream {
    let residuals = preprocessor.update(&frame.amplitudes);
    if let Some(bpm) = breathing.push_residuals(&residuals) {
        println!("Breathing: {:.1} BPM", bpm);
    }
}

Disaster Response (MAT)

use wifi_densepose_mat::{DisasterResponse, DisasterConfig, DisasterType};

let config = DisasterConfig {
    disaster_type: DisasterType::Earthquake,
    max_scan_zones: 16,
    ..Default::default()
};

let mut responder = DisasterResponse::new(config);
responder.add_scan_zone(zone)?;
responder.start_continuous_scan().await?;

Hardware (ESP32)

use wifi_densepose_hardware::{Esp32CsiParser, CsiFrame};

let parser = Esp32CsiParser::new();
let raw_bytes: &[u8] = /* UDP packet from ESP32 */;
let frame: CsiFrame = parser.parse(raw_bytes)?;
println!("RSSI: {} dBm, {} subcarriers", frame.metadata.rssi, frame.subcarriers.len());

Training

# Check training crate (no GPU needed)
cargo check -p wifi-densepose-train --no-default-features

# Run training with GPU (requires tch/libtorch)
cargo run -p wifi-densepose-train --features tch-backend --bin train -- \
    --config training.toml --dataset /path/to/mmfi

# Verify deterministic training proof
cargo run -p wifi-densepose-train --features tch-backend --bin verify-training

Building

# Clone the repository
git clone https://github.com/ruvnet/wifi-densepose.git
cd wifi-densepose/v2

# Check workspace (no GPU dependencies)
cargo check --workspace --no-default-features

# Run all tests
cargo test --workspace --no-default-features

# Build release
cargo build --release --workspace

Feature Flags

Crate Feature Description
wifi-densepose-nn onnx (default) ONNX Runtime backend
wifi-densepose-nn tch-backend PyTorch (libtorch) backend
wifi-densepose-nn candle-backend Candle (pure Rust) backend
wifi-densepose-nn cuda CUDA GPU acceleration
wifi-densepose-train tch-backend Enable GPU training modules
wifi-densepose-mat ruvector (default) RuVector graph algorithms
wifi-densepose-mat api (default) REST + WebSocket API
wifi-densepose-mat distributed Multi-node coordination
wifi-densepose-mat drone Drone-mounted scanning
wifi-densepose-hardware esp32 ESP32 protocol support
wifi-densepose-hardware intel5300 Intel 5300 CSI Tool
wifi-densepose-hardware linux-wifi Linux commodity WiFi
wifi-densepose-wifiscan wlanapi Windows WLAN API async scanning
wifi-densepose-core serde Serialization support
wifi-densepose-core async Async trait support

Testing

# Unit tests (all crates)
cargo test --workspace --no-default-features

# Signal processing benchmarks
cargo bench -p wifi-densepose-signal

# Training benchmarks
cargo bench -p wifi-densepose-train --no-default-features

# Detection benchmarks
cargo bench -p wifi-densepose-mat

Supported Hardware

Hardware Crate Feature CSI Subcarriers Cost
ESP32-S3 Mesh (3-6 nodes) hardware/esp32 52-56 ~$54
Intel 5300 NIC hardware/intel5300 30 ~$50
Atheros AR9580 hardware/linux-wifi 56 ~$100
Any WiFi (Windows/Linux) wifiscan RSSI-only $0

Architecture Decision Records

Key design decisions documented in docs/adr/:

ADR Title Status
ADR-014 SOTA Signal Processing Accepted
ADR-015 MM-Fi + Wi-Pose Training Datasets Accepted
ADR-016 RuVector Training Pipeline Accepted (Complete)
ADR-017 RuVector Signal + MAT Integration Accepted
ADR-021 Vital Sign Detection Pipeline Accepted
ADR-022 Windows WiFi Enhanced Sensing Accepted
ADR-024 Contrastive CSI Embedding Model Accepted
  • WiFi-DensePose -- Main repository (Python v1 + Rust v2)
  • RuVector -- Graph algorithms for neural networks (5 crates, v2.0.4)
  • rUv -- Creator and maintainer

License

All crates are dual-licensed under MIT OR Apache-2.0.

Copyright (c) 2024 rUv