# rvCSI — Edge RF Sensing Runtime Domain Model ## Domain-Driven Design Specification > Companion documents: [rvCSI Platform PRD](../prd/rvcsi-platform-prd.md) · [ADR-095 — rvCSI Edge RF Sensing Platform](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md) ### Domain Camera-free RF spatial sensing from WiFi Channel State Information (CSI). ### Core domain **RF field interpretation.** rvCSI converts noisy radio channel measurements into validated events and temporal embeddings that represent changes in physical space. CSI is treated as a *temporal delta stream* against learned baselines — not as exact vision. ### Supporting subdomains Hardware adapter management · packet parsing · signal processing · calibration · event extraction · temporal memory · agent integration · replay and audit. ### Generic subdomains Logging · configuration · CLI parsing · WebSocket streaming · package publishing · dashboard visualization. --- ## Ubiquitous Language | Term | Definition | |------|------------| | **CSI** | Channel State Information — per-subcarrier complex channel response measured by a WiFi receiver | | **Source** | A physical or replayed producer of CSI frames (a NIC, an ESP32 node, a PCAP file, a recorded capture) | | **Adapter** | A software module that knows how to receive and decode source-specific CSI and normalize it into a `CsiFrame` | | **Frame** | One CSI observation at a timestamp — the unit of ingestion | | **Window** | A bounded sequence of frames from one source/session, used for analysis | | **Baseline** | The learned normal RF-field state for a space | | **Delta** | The measured difference of the current field from baseline | | **Event** | A semantic interpretation of one or more windows (presence started, motion detected, anomaly, …) | | **Quality score** | Confidence, in [0, 1], that a signal/frame/window is usable | | **Calibration** | The process of learning a stable baseline for a space | | **Room signature** | A vector representation of a space under normal conditions | | **Drift** | Slow movement of the field away from baseline | | **Anomaly** | A significant, unexplained deviation from baseline | | **RF memory** | Persisted temporal vectors and events for a physical space (stored in RuVector) | | **Coherence** | Consistency among sources, windows, and learned baselines | | **Quarantine** | A holding store for rejected/corrupt frames, kept for audit rather than discarded | | **Adapter profile** | A capability descriptor for a source (chip, firmware/driver versions, supported channels/bandwidths, expected subcarrier counts, capture/injection/monitor-mode support) | | **Calibration version** | An immutable identifier for a particular learned baseline; every event references the calibration version it was detected against | | **Evidence window set** | The set of `WindowId`s an event references as its justification — an event with no evidence is invalid | --- ## Bounded Contexts ``` ┌─────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │ Capture │──▶│ Validation │──▶│ Signal │──▶│ Calibration │ │ context │ │ context │ │ context │ │ context │ └─────────────┘ └──────────────┘ └─────┬──────┘ └──────┬───────┘ │ │ ▼ │ ┌────────────┐ │ │ Event │◀──────────┘ │ context │ └─────┬──────┘ │ ┌─────────────┴─────────────┐ ▼ ▼ ┌────────────┐ ┌────────────┐ │ Memory │ │ Agent │ │ context │ │ context │ └────────────┘ └────────────┘ ``` - **Capture** upstreams raw input from sources. - **Validation** protects every downstream context — nothing crosses into SDK/DSP/memory/agents unvalidated. - **Signal** turns frames into windows. - **Calibration** gives windows a room-specific baseline. - **Event** converts deltas into meaning. - **Memory** stores time, similarity, drift, and coherence (RuVector). - **Agent** exposes safe actions and queries (MCP / TypeScript). --- ### 1. Capture context **Responsibility:** connect to CSI sources and produce raw frames. ``` ┌──────────────────────────────────────────────────────────────┐ │ Capture Context │ ├──────────────────────────────────────────────────────────────┤ │ ┌────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Source │ │ CaptureSession │ │ AdapterProfile │ │ │ │ (adapter │ │ (aggregate root)│ │ (capability │ │ │ │ plugin) │ │ │ │ descriptor) │ │ │ └────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ CsiSource trait: open · start · next_frame · stop · health │ └──────────────────────────────────────────────────────────────┘ ``` | Element | Kind | Notes | |---------|------|-------| | `Source` | Entity | A configured adapter instance bound to a device or file | | `CaptureSession` | Entity / **aggregate root** | Owns exactly one `AdapterProfile` and one runtime configuration | | `AdapterProfile` | Entity | Chip, firmware/driver versions, supported channels/bandwidths, expected subcarrier counts, capability flags | | `Channel`, `Bandwidth`, `FirmwareVersion`, `DriverVersion` | Value objects | Immutable | **Commands:** `StartCapture` · `StopCapture` · `RestartCapture` · `InspectSource` **Domain events:** `CaptureStarted` · `CaptureStopped` · `SourceDisconnected` · `AdapterUnsupported` --- ### 2. Validation context **Responsibility:** make frames safe and trustworthy before any language-boundary crossing. | Element | Kind | Notes | |---------|------|-------| | `ValidationPolicy` | Entity | Bounds, monotonicity rules, finiteness checks, quarantine on/off | | `QuarantineStore` | Entity | Holds rejected/corrupt frames for audit | | `ValidatedFrame` | **Aggregate root** | The frame once it has passed (or been degraded by) validation | | `ValidationError`, `QualityScore`, `FrameBounds` | Value objects | `QualityScore` ∈ [0, 1] | **Commands:** `ValidateFrame` · `QuarantineFrame` **Domain events:** `FrameAccepted` · `FrameRejected` · `QualityDropped` --- ### 3. Signal context **Responsibility:** DSP and window features. ``` Frame stream ─▶ SignalPipeline ─▶ WindowBuffer ─▶ CsiWindow (DC removal, phase unwrap, (mean amplitude, smoothing, Hampel filter, phase variance, variance, baseline subtraction, motion energy, motion energy, presence score) presence/quality scores) ``` | Element | Kind | Notes | |---------|------|-------| | `SignalPipeline` | Entity | Ordered DSP stages; reuses `wifi-densepose-signal` primitives | | `WindowBuffer` | Entity | Accumulates frames into bounded windows | | `CsiWindow` | **Aggregate root** | Frames from exactly one source/session | | `AmplitudeVector`, `PhaseVector`, `MotionEnergy`, `PresenceScore` | Value objects | | **Commands:** `ProcessFrame` · `BuildWindow` · `EstimateBaselineDelta` **Domain events:** `WindowReady` · `BaselineDeltaMeasured` --- ### 4. Calibration context **Responsibility:** learn and version the normal RF state and room signatures. | Element | Kind | Notes | |---------|------|-------| | `CalibrationProfile` | **Aggregate root** | Linked to source, room, adapter profile, configuration | | `RoomSignature` | Entity | Vector representation of a space under normal conditions | | `BaselineModel` | Entity | Statistical model of the baseline field; carries version history | | `CalibrationVersion`, `StabilityScore`, `RoomId` | Value objects | Calibration cannot complete if `StabilityScore` < threshold | **Commands:** `StartCalibration` · `CompleteCalibration` · `UpdateBaseline` · `RejectUnstableCalibration` **Domain events:** `CalibrationStarted` · `CalibrationCompleted` · `CalibrationFailed` · `BaselineUpdated` --- ### 5. Event context **Responsibility:** semantic event extraction with confidence and evidence. | Element | Kind | Notes | |---------|------|-------| | `EventDetector` | Entity | One per event family (presence, motion, breathing, anomaly, …) | | `EventStateMachine` | Entity | Holds the per-source detection state; emits transitions | | `CsiEvent` | **Aggregate root** | Must reference ≥ 1 evidence window; confidence ∈ [0, 1]; references calibration version | | `Confidence`, `EvidenceWindowSet`, `EventKind` | Value objects | | **Commands:** `DetectEvents` · `PublishEvent` · `SuppressEvent` **Domain events (the `CsiEventKind` enum):** `PresenceStarted` · `PresenceEnded` · `MotionDetected` · `MotionSettled` · `BaselineChanged` · `SignalQualityDropped` · `DeviceDisconnected` · `BreathingCandidate` · `AnomalyDetected` · `CalibrationRequired` --- ### 6. Memory context **Responsibility:** RuVector storage and retrieval — RF memory. | Element | Kind | Notes | |---------|------|-------| | `RfMemoryCollection` | Entity | A RuVector collection scoped to a deployment | | `TemporalEmbedding` | Entity | Frame / window / event embedding with timestamp | | `SensorGraph` | Entity | Graph of sources and their topological relationships | | `RoomMemory` | **Aggregate root** | Stored embeddings must be traceable to frame windows or event windows | | `EmbeddingVector`, `DriftScore`, `CoherenceScore` | Value objects | `DriftScore` must include the baseline version | **Commands:** `StoreWindowEmbedding` · `StoreEventEmbedding` · `QuerySimilarWindows` · `ComputeDrift` **Domain events:** `EmbeddingStored` · `DriftDetected` · `SimilarPatternFound` Data stored: frame embeddings · window embeddings · room baseline vectors · event vectors · drift snapshots · sensor-topology graph edges · source health records. Retention policy applies at collection level. No orphan embeddings. --- ### 7. Agent context **Responsibility:** MCP and TypeScript agent interaction — safe actions and queries. | Element | Kind | Notes | |---------|------|-------| | `AgentSubscription` | Entity | An agent's filtered stream of events | | `McpToolSession` | Entity | A tool invocation context with permissions | | `AgentSession` | **Aggregate root** | | | `ToolPermission`, `EventFilter`, `AgentIntent` | Value objects | `ToolPermission` distinguishes read vs. write-gated | **Commands:** `SubscribeToEvents` · `RequestStatus` · `RequestCalibration` · `QueryMemory` **Domain events:** `AgentSubscribed` · `ToolExecuted` · `PermissionDenied` **MCP tools** (read by default; write-gated marked `*`): `rvcsi_status` · `rvcsi_list_sources` · `rvcsi_start_capture *` · `rvcsi_stop_capture *` · `rvcsi_get_presence` · `rvcsi_get_recent_events` · `rvcsi_calibrate_room *` · `rvcsi_export_window *` · `rvcsi_query_ruvector` · `rvcsi_health_report`. --- ## Context Map | Upstream → Downstream | Relationship | ACL / contract | |-----------------------|--------------|----------------| | Capture → Validation | Customer/Supplier | Raw frames pass through `ValidationPolicy`; only `Accepted`/`Degraded` continue | | Validation → Signal | Conformist (Signal accepts `ValidatedFrame` as-is) | `CsiFrame` schema is the published language | | Signal → Calibration | Customer/Supplier | Windows + baseline-delta measurements feed baseline modeling | | Calibration → Event | Customer/Supplier | Detectors declare which `CalibrationVersion` they used | | Signal/Event → Memory | Published Language (`EmbeddingVector`, event metadata) | `rvcsi-ruvector` ACL translates to RuVector's API | | Event → Agent | Open Host Service (event stream + MCP tools) | `EventFilter` + `ToolPermission` enforced at the boundary | | Capture → Agent | Conformist (health/status only, via MCP read tools) | No raw frames cross to agents | The **`CsiFrame` schema is the shared kernel** between Capture, Validation, Signal, and the language-boundary (napi-rs) layer. It is the FFI-safe object; nothing device-specific leaks past it. --- ## Aggregates and Invariants ### `CaptureSession` aggregate **Invariant:** a capture session has exactly one source profile and one runtime configuration. 1. A session cannot emit frames before it is started. 2. A session cannot change channel without restart unless the adapter supports dynamic retune. 3. A session must emit `SourceDisconnected` before stopping due to device loss. ### `ValidatedFrame` aggregate **Invariant:** no frame crosses into SDK, DSP, memory, or agents unless its validation status is `Accepted` or `Degraded`. 1. Rejected frames go to quarantine when quarantine is enabled. 2. Degraded frames must carry quality-reason metadata. 3. Missing *optional* hardware metadata must not invalidate a frame. ### `CsiWindow` aggregate **Invariant:** a window contains frames from exactly one source and one session. 1. Mixed-source windows are not allowed. 2. Window start time must be strictly less than end time. 3. Window quality is bounded in [0, 1]. ### `CalibrationProfile` aggregate **Invariant:** a calibration profile is linked to source, room, adapter profile, and configuration. 1. Calibration cannot complete if `StabilityScore` is below threshold. 2. Baseline updates must preserve version history. 3. Event detectors must declare which calibration version they used. ### `CsiEvent` aggregate **Invariant:** an event must have evidence. 1. Every event references at least one evidence window. 2. Confidence is bounded in [0, 1]. 3. Event suppression must be explainable by policy. ### `RoomMemory` aggregate **Invariant:** stored embeddings are traceable to frame windows or event windows. 1. No orphan embeddings. 2. Retention policy applies at collection level. 3. Drift scores must include the baseline version. --- ## Data Model ```rust pub struct CsiFrame { pub frame_id: FrameId, pub session_id: SessionId, pub source_id: SourceId, pub adapter_kind: AdapterKind, pub timestamp_ns: u64, pub channel: u16, pub bandwidth_mhz: u16, pub rssi_dbm: Option, pub noise_floor_dbm: Option, pub antenna_index: Option, pub tx_chain: Option, pub rx_chain: Option, pub subcarrier_count: u16, pub i_values: Vec, pub q_values: Vec, pub amplitude: Vec, pub phase: Vec, pub validation: ValidationStatus, pub quality_score: f32, pub calibration_version: Option, } pub struct CsiWindow { pub window_id: WindowId, pub session_id: SessionId, pub source_id: SourceId, pub start_ns: u64, pub end_ns: u64, pub frame_count: u32, pub mean_amplitude: Vec, pub phase_variance: Vec, pub motion_energy: f32, pub presence_score: f32, pub quality_score: f32, } pub enum CsiEventKind { PresenceStarted, PresenceEnded, MotionDetected, MotionSettled, BaselineChanged, SignalQualityDropped, DeviceDisconnected, BreathingCandidate, AnomalyDetected, CalibrationRequired, } pub struct CsiEvent { pub event_id: EventId, pub kind: CsiEventKind, pub session_id: SessionId, pub source_id: SourceId, pub timestamp_ns: u64, pub confidence: f32, pub evidence_window_ids: Vec, pub metadata_json: String, } pub struct AdapterProfile { pub adapter_kind: AdapterKind, pub chip: Option, pub firmware_version: Option, pub driver_version: Option, pub supported_channels: Vec, pub supported_bandwidths_mhz: Vec, pub expected_subcarrier_counts: Vec, pub supports_live_capture: bool, pub supports_injection: bool, pub supports_monitor_mode: bool, } pub enum ValidationStatus { Accepted, Degraded, Rejected, Recovered } ``` --- ## Domain Services | Service | Input | Output | Responsibility | |---------|-------|--------|----------------| | `FrameValidationService` | `RawFrame`, `AdapterProfile`, `ValidationPolicy` | `ValidatedFrame` or `RejectedFrame` | Enforce bounds, finiteness, monotonicity; assign initial `QualityScore`; route rejects to quarantine; emit structured errors | | `SignalProcessingService` | `ValidatedFrame` stream | `CsiWindow` stream | Run the DSP pipeline; build bounded windows; compute motion energy, presence score, window quality | | `BaselineDeltaService` | `CsiWindow`, `BaselineModel` | `BaselineDelta` | Subtract the calibrated baseline; measure deviation magnitude | | `CalibrationService` | `CsiWindow` stream over a calibration window | `CalibrationProfile` (new version) or `CalibrationFailed` | Learn a stable baseline; compute `StabilityScore`; reject unstable calibrations; preserve version history | | `EventDetectionService` | `CsiWindow` + `BaselineDelta` + `CalibrationVersion` | `CsiEvent` stream | Drive per-source state machines; attach confidence + evidence windows + calibration version; apply suppression policy | | `EmbeddingService` | `CsiWindow` / `CsiEvent` | `TemporalEmbedding` | Produce frame/window/event vectors (v0: deterministic DSP feature vector; later: AETHER / on-device model) | | `RfMemoryService` | `TemporalEmbedding`, query | `EmbeddingStored` / similar windows / `DriftScore` | Store to RuVector; similarity search; drift computation against a baseline version | | `ReplayService` | A captured session bundle | A deterministic frame/window/event stream | Replay preserving timestamps, ordering, validation decisions, event output, calibration version, runtime config | | `AdapterRegistryService` | — | List of available adapters + `AdapterProfile`s | Discover sources (reuses ADR-049 interface detection); report health; flag unsupported firmware/driver state | | `AgentGatewayService` | MCP tool call / SDK subscription | Tool result / filtered event stream | Enforce `ToolPermission` (read vs. write-gated), apply `EventFilter`, audit `ToolExecuted` / `PermissionDenied` | --- ## Related - [rvCSI Platform PRD](../prd/rvcsi-platform-prd.md) — requirements, success criteria, scope - [ADR-095 — rvCSI Edge RF Sensing Platform](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md) — the fifteen architectural decisions - [RuvSense Domain Model](ruvsense-domain-model.md) — adjacent multistatic sensing context - [Signal Processing Domain Model](signal-processing-domain-model.md) — the DSP primitives `rvcsi-dsp` reuses - [ADR Index](../adr/README.md)