526 lines
23 KiB
Markdown
526 lines
23 KiB
Markdown
# Soul Signature — Technical Specification
|
||
|
||
**Status:** Research Specification (Pre-Implementation)
|
||
**Date:** 2026-05-24
|
||
**Author:** ruv
|
||
|
||
---
|
||
|
||
## 1. Overview
|
||
|
||
A Soul Signature is a typed, content-addressed RVF graph encoding seven
|
||
electromagnetic observables extracted from a person in a WiFi-DensePose sensing
|
||
zone. The graph is stored as a single `.rvf` binary blob using the existing RVF
|
||
container format (`v2/crates/wifi-densepose-sensing-server/src/rvf_container.rs`)
|
||
extended with two new segment types defined below. A human-readable JSON sidecar
|
||
accompanies the blob for inspection and provenance.
|
||
|
||
The signature is probabilistic, not deterministic. Matching computes a weighted
|
||
cosine similarity across graph dimensions, producing a score in [0, 1] with a
|
||
calibrated false-accept rate (FAR). The FAR at a given threshold is an open
|
||
research question; the AETHER person re-identification baseline (ADR-024 §2.8:
|
||
>80% mAP at 5 subjects) is the lower bound for the primary embedding channel.
|
||
|
||
---
|
||
|
||
## 2. Design Principles
|
||
|
||
### 2.1 Per-Individual
|
||
|
||
The signature encodes features that are structurally unique to one person at the
|
||
sensing resolution of commodity WiFi hardware. Discriminative dimensions include:
|
||
cardiac timing (R-R interval structure), respiratory mechanics (tidal depth,
|
||
inspiration-to-expiration ratio), skeletal proportions (limb ratios from 17-keypoint
|
||
pose, ADR-079), gait cadence variability, and the RF backscatter profile shaped by
|
||
body mass distribution and geometry.
|
||
|
||
### 2.2 Passive at Enrollment Time
|
||
|
||
No explicit action from the subject is required at recognition time after
|
||
enrollment. Recognition fires whenever an enrolled person is detected in a sensing
|
||
zone. Enrollment itself requires a 60-second structured protocol (see
|
||
`scanning-process.md`). This is a deliberate asymmetry: passive recognition +
|
||
active enrollment — which is the same model used by FaceID (passive unlock after
|
||
initial face setup).
|
||
|
||
The passivity of post-enrollment recognition is a privacy concern addressed in full
|
||
in `security.md` §4.
|
||
|
||
### 2.3 Multi-Modal
|
||
|
||
Seven orthogonal channels contribute. Orthogonality matters: if one channel
|
||
degrades (e.g., cardiac is masked by motion), the remaining six carry the match.
|
||
No single channel is necessary for a positive identification above threshold;
|
||
the fused score is a weighted aggregate.
|
||
|
||
### 2.4 Persistent Across Time
|
||
|
||
The stored signature is valid over weeks to months for adults with stable anatomy
|
||
and health. Re-scan cadence is prescribed in `scanning-process.md`. The
|
||
`longitudinal.rs` module (ADR-030 Tier 4) provides the drift detection that
|
||
flags when a re-scan is necessary.
|
||
|
||
### 2.5 Defensible False-Accept Rate
|
||
|
||
The security model is not "unbreakable." It is "attacker cost exceeds value of
|
||
attack for the threat model in §security." See `security.md` §3.
|
||
|
||
---
|
||
|
||
## 3. Signature as a Typed RVF Graph
|
||
|
||
### 3.1 Container Format
|
||
|
||
The soul signature reuses the RVF binary container defined in
|
||
`v2/crates/wifi-densepose-sensing-server/src/rvf_container.rs` (lines 1–660).
|
||
Existing segment types used:
|
||
|
||
| Segment type | Const | Purpose in soul signature |
|
||
|---|---|---|
|
||
| `SEG_MANIFEST` | `0x05` | Graph metadata: schema version, enroll timestamp, device ID, person_id (opaque u64) |
|
||
| `SEG_VEC` | `0x01` | AETHER 128-dim embedding weights (backbone + projection head) |
|
||
| `SEG_META` | `0x07` | JSON overlay: all non-vector node attributes |
|
||
| `SEG_WITNESS` | `0x0A` | Ed25519 signature over `(content_hash_sha256 || timestamp_ns || enrolled_by_device_id)` |
|
||
| `SEG_EMBED` | `0x0C` | AETHER embedding config + projection head weights (ADR-024 Phase 7) |
|
||
| `SEG_LORA` | `0x0D` | Per-environment LoRA deltas for environment-adapted query |
|
||
|
||
Two new segment types are proposed for the soul signature extension:
|
||
|
||
| Segment type | Const | Purpose |
|
||
|---|---|---|
|
||
| `SEG_SOUL_GRAPH` | `0x10` | JSON-serialized graph: node list + edge list + attribute schemas |
|
||
| `SEG_SOUL_INDEX` | `0x11` | Per-node HNSW index serialization for fast graph-level query |
|
||
|
||
The `SegmentHeader` structure is unchanged. Each segment is 64-byte aligned
|
||
(field `alignment_pad` at offset `0x3C`). CRC32 content hash at offset `0x28`
|
||
covers the payload, providing tamper detection per the existing implementation
|
||
at `rvf_container.rs:line 70`.
|
||
|
||
### 3.2 Node Types
|
||
|
||
Each node is a typed struct. Serialized into SEG_META as a JSON object with a
|
||
`node_type` discriminator string. Vector fields (f32 arrays) are co-located in
|
||
a SEG_VEC segment indexed by the node's `vec_segment_id` field.
|
||
|
||
#### Node: AETHER_Embedding
|
||
|
||
Primary identity anchor. The contrastive CSI embedding from ADR-024.
|
||
|
||
```rust
|
||
pub struct AetherEmbeddingNode {
|
||
pub node_type: &'static str, // "AETHER_Embedding"
|
||
pub vec_segment_id: u64, // references SEG_VEC containing 128 f32s
|
||
pub embedding_dim: usize, // 128
|
||
pub backbone: String, // "csi-to-pose-transformer"
|
||
pub pretrain_method: String, // "simclr+vicreg"
|
||
pub alignment_score: f32, // Lowman alignment metric at enrollment time
|
||
pub uniformity_score: f32, // Hypersphere uniformity at enrollment time
|
||
pub enrollment_frames: u32, // Number of CSI windows averaged into this node
|
||
pub environment_id: String, // SHA-256 of field model eigenstate at enrollment
|
||
pub confidence: f32, // HNSW search confidence against person_track index
|
||
}
|
||
```
|
||
|
||
Stored size: 128 × 4 = 512 bytes in SEG_VEC; JSON metadata ~200 bytes in SEG_META.
|
||
Per ADR-024 §2.8, the person re-identification target is >80% mAP at 5 subjects.
|
||
At 10+ subjects the accuracy is open research; baseline TBD.
|
||
|
||
#### Node: Cardiac_HR_Profile
|
||
|
||
Extracted from the ADR-039 vitals pipeline (magic `0xC511_0002`, fields offset 6-11:
|
||
breathing_rate at `u16 LE` BPM×100, heart_rate at `u32 LE` BPM×10000).
|
||
For the soul signature, cardiac extraction uses the ADR-021 bandpass pipeline
|
||
(0.8–2.0 Hz) over a minimum 30-second rest window.
|
||
|
||
```rust
|
||
pub struct CardiacHRProfileNode {
|
||
pub node_type: &'static str, // "Cardiac_HR_Profile"
|
||
pub baseline_bpm: f32, // mean HR over enrollment window (40–180 BPM range)
|
||
pub hrv_sdnn_ms: f32, // SDNN: std dev of R-R intervals (ms)
|
||
pub hrv_rmssd_ms: f32, // RMSSD: root mean square successive differences
|
||
pub hrv_lf_power: f32, // LF band power (0.04–0.15 Hz), normalized
|
||
pub hrv_hf_power: f32, // HF band power (0.15–0.4 Hz), normalized
|
||
pub hrv_lf_hf_ratio: f32, // LF/HF ratio (autonomic balance marker)
|
||
pub sinus_rhythm_class: u8, // 0=regular, 1=irregular, 2=indeterminate
|
||
pub confidence: f32, // from ADR-021 VitalCoherenceGate PERMIT fraction
|
||
pub window_seconds: u32, // duration of the measurement window
|
||
}
|
||
```
|
||
|
||
WiFi CSI-based HRV extraction is an active research area. The SDNN and RMSSD values
|
||
are discriminative at group level (Zhao et al. 2017, Widar 3.0 2019) but per-person
|
||
uniqueness has not been independently validated at scale. Status: open research.
|
||
|
||
#### Node: Cardiac_Waveform_Morphology
|
||
|
||
Wavelet decomposition of the bandpass-filtered cardiac phase signal. Captures the
|
||
shape of the cardiac waveform, not just its rate. More discriminative than HR alone
|
||
but requires higher SNR and longer measurement window.
|
||
|
||
```rust
|
||
pub struct CardiacWaveformMorphologyNode {
|
||
pub node_type: &'static str, // "Cardiac_Waveform_Morphology"
|
||
pub vec_segment_id: u64, // references SEG_VEC: 64 f32 wavelet coefficients
|
||
pub wavelet_family: String, // "db4" (Daubechies 4, standard for cardiac)
|
||
pub decomposition_levels: u8, // 4 levels
|
||
pub snr_db: f32, // measured SNR at enrollment; low-SNR nodes down-weighted
|
||
pub confidence: f32,
|
||
}
|
||
```
|
||
|
||
Wavelet coefficient dimension: 64 floats = 256 bytes in SEG_VEC. Waveform
|
||
morphology from CSI is highly environment-dependent; the ADR-030 field model
|
||
subtraction must run before this measurement is taken to isolate body perturbation
|
||
from room standing-wave artifacts.
|
||
|
||
#### Node: Respiratory_Pattern
|
||
|
||
Extracted by the ADR-021 BreathingExtractor (0.1–0.5 Hz bandpass) plus the
|
||
ADR-030 persistence layer that accumulates statistics over the enrollment window.
|
||
|
||
```rust
|
||
pub struct RespiratoryPatternNode {
|
||
pub node_type: &'static str, // "Respiratory_Pattern"
|
||
pub baseline_bpm: f32, // mean RR (normal adult: 12–20 BPM)
|
||
pub depth_amplitude_normalized: f32, // tidal depth proxy from CSI variance
|
||
pub inspiration_expiration_ratio: f32, // I:E ratio (1:1.5 to 1:3 typical)
|
||
pub hrv_rsa_power: f32, // respiratory sinus arrhythmia spectral power
|
||
pub apnea_index: f32, // events per hour of significant pauses
|
||
pub waveform_regularity: f32, // coefficient of variation of breath intervals
|
||
pub confidence: f32,
|
||
pub window_seconds: u32,
|
||
}
|
||
```
|
||
|
||
Note: the `apnea_index` field is a biophysical proxy signal (pause events in
|
||
the signal), not a clinical AHI score. It is provided for signature
|
||
discriminability, not diagnostic use.
|
||
|
||
#### Node: Gait_Timing
|
||
|
||
Extracted from the 17-keypoint Kalman pose tracker (`pose_tracker.rs`, ADR-029
|
||
Sect 2.7) during the gait phase of the enrollment protocol. The tracker uses
|
||
ruvector-mincut for person separation and AETHER re-ID for identity continuity.
|
||
|
||
```rust
|
||
pub struct GaitTimingNode {
|
||
pub node_type: &'static str, // "Gait_Timing"
|
||
pub cadence_steps_per_min: f32, // steps per minute
|
||
pub stride_period_variance: f32, // coefficient of variation of stride period
|
||
pub double_support_pct: f32, // fraction of gait cycle in double support
|
||
pub asymmetry_index: f32, // |left_stride - right_stride| / mean_stride
|
||
pub step_width_m: f32, // lateral distance between foot strikes (proxy)
|
||
pub velocity_variance: f32, // gait speed variability
|
||
pub confidence: f32,
|
||
pub stride_count: u32, // number of strides captured during enrollment
|
||
}
|
||
```
|
||
|
||
Gait biometrics from WiFi CSI are documented in WiGait (Adib et al., SIGCOMM
|
||
2015) and WiDraw (Wang et al., MobiCom 2014). Discrimination across 10+ subjects
|
||
in the same household is an open research question for the WiFi-only modality.
|
||
|
||
#### Node: Skeletal_Proportions
|
||
|
||
Derived from the ADR-079 camera + CSI paired keypoint pipeline when available,
|
||
or from CSI-only pose estimation (ADR-023 CsiToPoseTransformer) in camera-free
|
||
deployments. Encodes body geometry as ratios (not absolute values) for scale
|
||
invariance.
|
||
|
||
```rust
|
||
pub struct SkeletalProportionsNode {
|
||
pub node_type: &'static str, // "Skeletal_Proportions"
|
||
pub torso_to_leg_ratio: f32, // torso height / leg length
|
||
pub shoulder_to_hip_ratio: f32, // shoulder width / hip width
|
||
pub upper_to_lower_arm_ratio: f32, // upper arm / forearm
|
||
pub upper_to_lower_leg_ratio: f32, // thigh / shin
|
||
pub head_to_torso_ratio: f32, // head height / torso height
|
||
pub arm_span_to_height_ratio: f32, // Vitruvian ratio (close to 1.0 for most adults)
|
||
pub confidence: f32,
|
||
pub keypoint_source: String, // "camera_paired" | "csi_only" | "fused"
|
||
}
|
||
```
|
||
|
||
CSI-only skeletal proportion estimation has ~15–25% error on individual ratio
|
||
values (open research; baseline from ADR-023 MPJPE ~91.7 mm at best, per
|
||
Person-in-WiFi 3D, CVPR 2024). Camera-paired values (ADR-079) are substantially
|
||
more accurate. The node degrades gracefully when only CSI is available.
|
||
|
||
#### Node: Subcarrier_Reflection_Profile
|
||
|
||
The per-subcarrier amplitude attenuation and phase shift profile measured when
|
||
the subject stands still at three orientations (0°, 90°, 180° rotation). This
|
||
encodes the body's RF backscatter cross-section shape, which is determined by
|
||
body mass distribution, limb geometry, and clothing/material factors.
|
||
|
||
```rust
|
||
pub struct SubcarrierReflectionProfileNode {
|
||
pub node_type: &'static str, // "Subcarrier_Reflection_Profile"
|
||
pub vec_segment_id: u64, // SEG_VEC: 56 × 3 × 2 = 336 f32s
|
||
// (56 subcarriers × 3 orientations ×
|
||
// [amplitude_attenuation, phase_shift])
|
||
pub n_subcarriers: u8, // 56 (HT-LTF) or up to 242 (HE-LTF, ADR-110 C6)
|
||
pub n_orientations: u8, // 3
|
||
pub frequency_mhz: u32, // center frequency at measurement time
|
||
pub environment_id: String, // references field model used for subtraction
|
||
pub confidence: f32,
|
||
}
|
||
```
|
||
|
||
This node directly exploits the ADR-030 field model: the empty-room baseline
|
||
eigenstate is subtracted before computing the reflection profile, isolating the
|
||
person's contribution. Without ADR-030 field subtraction, the profile is too
|
||
environment-coupled to be transferable across rooms. With MERIDIAN (ADR-027),
|
||
the hardware-normalizer layer maps ESP32-S3 (52 subcarriers HT-LTF) and
|
||
ESP32-C6 (242 subcarriers HE-LTF per ADR-110) into a canonical 56-subcarrier
|
||
representation before this measurement.
|
||
|
||
Stored: 336 × 4 = 1,344 bytes in SEG_VEC.
|
||
|
||
#### Node: Body_Field_Coupling
|
||
|
||
The AETHER attention map cells weighted by the ADR-030 room eigenmode structure.
|
||
Encodes how strongly the person's body couples to each dominant electromagnetic
|
||
mode of the room. This is the most physics-grounded node: it captures the
|
||
person's interaction with the actual electromagnetic geometry of the space.
|
||
|
||
```rust
|
||
pub struct BodyFieldCouplingNode {
|
||
pub node_type: &'static str, // "Body_Field_Coupling"
|
||
pub vec_segment_id: u64, // SEG_VEC: n_eigenmodes × n_keypoints f32s
|
||
pub n_eigenmodes: u8, // top-K SVD modes from field_model.rs (default K=8)
|
||
pub n_keypoints: u8, // 17 (COCO)
|
||
pub eigenmode_energy_fractions: Vec<f32>, // fraction of total variance per mode
|
||
pub environment_id: String, // must match SubcarrierReflectionProfile env
|
||
pub confidence: f32,
|
||
}
|
||
```
|
||
|
||
This node is only valid when the same room's field model is available. For
|
||
cross-room recognition, MERIDIAN's environment-disentangled embedding (ADR-027)
|
||
is used instead. The BodyFieldCoupling node provides additional discriminative
|
||
power in single-room deployments and degrades to optional in multi-room contexts.
|
||
|
||
---
|
||
|
||
### 3.3 Edge Types
|
||
|
||
Edges are stored in the SEG_SOUL_GRAPH JSON array. Each edge has a typed
|
||
relationship that constrains how the nodes may be used in matching.
|
||
|
||
| Edge type | Source node(s) | Target node(s) | Semantics |
|
||
|---|---|---|---|
|
||
| `derived_from` | FieldModel_Residual (implicit) | AetherEmbedding | The embedding was computed after field model subtraction |
|
||
| `correlates_with` | Cardiac_HR_Profile | Respiratory_Pattern | Cardiorespiratory coupling at measurement time; correlation coefficient stored as edge weight |
|
||
| `temporally_colocated` | Any pair | Any pair | Both nodes were measured in the same time window; ensures consistency |
|
||
| `temporally_after` | Post-gait node | Pre-gait node | Nodes acquired sequentially during enrollment protocol |
|
||
| `requires_field_model` | SubcarrierReflectionProfile | BodyFieldCoupling | Matching this node requires the same room's ADR-030 field model |
|
||
| `fuses` | AetherEmbedding | SubcarrierReflectionProfile | MERIDIAN-normalized fusion: both mapped to environment-invariant space |
|
||
| `attested_by` | Any leaf node | WitnessChain | Ed25519 witness covers this node's content hash |
|
||
| `derived_by_keypoint_tracker` | GaitTiming | SkeletalProportions | Both extracted from the same pose_tracker.rs output |
|
||
| `environment_normalized` | Any node with `environment_id` | MERIDIAN manifest | MERIDIAN (ADR-027) was applied; signature is cross-room capable |
|
||
|
||
---
|
||
|
||
### 3.4 The Aggregator vs. the Stored Profile
|
||
|
||
Two distinct graph instances exist in the runtime:
|
||
|
||
**Online Aggregator** — a mutable, in-memory graph that accumulates measurements
|
||
across multiple sensing windows. Nodes are incrementally updated with Welford
|
||
online statistics (`field_model.rs::WelfordStats`). Confidence fields grow toward
|
||
1.0 as more frames accumulate. The aggregator never writes to disk during
|
||
normal operation.
|
||
|
||
**Stored Profile** — an immutable, content-addressed `.rvf` file on disk. It is
|
||
generated from the aggregator at the end of the enrollment protocol, when all node
|
||
confidence fields exceed their minimum thresholds. The stored profile is the
|
||
canonical soul signature.
|
||
|
||
```
|
||
Online Aggregator (RAM) Stored Profile (disk / secure enclave)
|
||
+----------------------+ +---------------------------+
|
||
| AETHER_Embedding | enrollment | signature-<sha256>.rvf |
|
||
| accumulated over | completion | SEG_MANIFEST |
|
||
| 60-second protocol +-------------> | SEG_VEC (embedding + refl)|
|
||
| Confidence: 0.0→1.0 | when all | SEG_META (all node attrs) |
|
||
| | gates pass | SEG_EMBED (AETHER config) |
|
||
| Cardiac_HR_Profile | | SEG_WITNESS (Ed25519) |
|
||
| accumulated 30s rest | | SEG_SOUL_GRAPH (graph) |
|
||
+----------------------+ +---------------------------+
|
||
```
|
||
|
||
The aggregator pattern ensures that a partial scan (e.g., subject leaves after
|
||
20 seconds) never produces a stored profile — the quality gates prevent premature
|
||
commitment (see `scanning-process.md §5`).
|
||
|
||
---
|
||
|
||
### 3.5 Serialization
|
||
|
||
**Binary container:** RVF blob, per `rvf_container.rs`. All numeric data is
|
||
little-endian, f32 IEEE 754. Segment alignment: 64 bytes. CRC32 (IEEE 802.3
|
||
polynomial) over each segment payload.
|
||
|
||
**Content addressing:** The file name is:
|
||
```
|
||
signature-<sha256-hex-of-rvf-bytes>.rvf
|
||
```
|
||
SHA-256 is computed over the complete concatenated RVF byte stream after
|
||
`RvfBuilder::build()`. This is a different hash from the per-segment CRC32;
|
||
the CRC32 provides corruption detection within segments, the SHA-256 provides
|
||
content-based addressing and enables deduplication.
|
||
|
||
**JSON-LD sidecar:** An optional `signature-<sha256>.json` file with the same
|
||
base name. Structure:
|
||
|
||
```json
|
||
{
|
||
"@context": "https://ruv.net/soul-signature/v1",
|
||
"schema_version": "0.1.0",
|
||
"person_id": "<opaque_u64_hex>",
|
||
"enrolled_at": "2026-05-24T00:00:00Z",
|
||
"enrolled_by_device_id": "<mac_or_device_fingerprint>",
|
||
"rvf_sha256": "<content_hash>",
|
||
"nodes": [
|
||
{ "node_type": "AETHER_Embedding", "confidence": 0.92, ... },
|
||
{ "node_type": "Cardiac_HR_Profile", "confidence": 0.85, ... },
|
||
...
|
||
],
|
||
"edges": [...],
|
||
"witness": {
|
||
"algorithm": "Ed25519",
|
||
"public_key": "<hex>",
|
||
"signature": "<hex>",
|
||
"signed_fields": ["rvf_sha256", "enrolled_at", "enrolled_by_device_id"]
|
||
}
|
||
}
|
||
```
|
||
|
||
The JSON-LD sidecar is human-readable and intended for audit and provenance.
|
||
It does not contain raw biometric vectors; those stay in the RVF blob.
|
||
|
||
**ISO/IEC 19794-4 alignment:** The soul signature's graph-based vector template
|
||
is conceptually analogous to the ISO/IEC 19794-4 finger image data format
|
||
and ISO/IEC 19794-2 minutiae data. The node/edge schema is not binary-compatible
|
||
with ISO 19794, but the design intent (typed attribute records, quality scores,
|
||
creator provenance) follows the same standard's principles. Future work may
|
||
include a conformance layer if regulatory certification is sought.
|
||
|
||
---
|
||
|
||
### 3.6 Matching Algorithm
|
||
|
||
Given a stored profile `P` and a query embedding `Q` derived from a live sensing
|
||
window, the match score is computed as a weighted sum of per-channel cosine
|
||
similarities:
|
||
|
||
```
|
||
match_score = sum_i ( w_i * cosine_sim(P.channel_i, Q.channel_i) )
|
||
/ sum_i ( w_i * availability(P.channel_i, Q.channel_i) )
|
||
```
|
||
|
||
Where `availability` is 1.0 if both nodes are present and 0.0 if either is absent
|
||
(graceful degradation when a channel cannot be measured in the query window).
|
||
|
||
Default weights (open research; these are design intent, not validated):
|
||
|
||
| Channel | Weight | Rationale |
|
||
|---|---|---|
|
||
| AETHER_Embedding | 0.35 | Primary identity anchor; best-studied channel |
|
||
| Subcarrier_Reflection_Profile | 0.20 | Body geometry; angle-stable |
|
||
| Cardiac_HR_Profile | 0.15 | Physiologically stable in healthy adults |
|
||
| Gait_Timing | 0.15 | Well-studied biometric; discriminative |
|
||
| Respiratory_Pattern | 0.10 | More variable than cardiac |
|
||
| Skeletal_Proportions | 0.05 | Proxy for body shape; CSI-only is noisy |
|
||
| Body_Field_Coupling | 0.00 (single-room) / 0.10 (cross-room disabled) | Valid only when room field model available |
|
||
| Cardiac_Waveform_Morphology | 0.05 (supplementary) | High SNR requirement |
|
||
|
||
The threshold for a positive match is a deployment-specific parameter with a
|
||
documented FAR/FRR trade-off. The AETHER channel alone achieves >80% mAP at 5
|
||
subjects (ADR-024 §2.8 target). The fused multi-channel score is expected to
|
||
exceed this; the exact improvement is open research, baseline TBD.
|
||
|
||
---
|
||
|
||
### 3.7 Rust Type Sketch
|
||
|
||
The following sketch shows how the soul signature types would integrate with
|
||
the existing codebase. This is a design sketch, not implemented code.
|
||
|
||
```rust
|
||
// In a future: v2/crates/wifi-densepose-sensing-server/src/soul_signature.rs
|
||
|
||
pub const SEG_SOUL_GRAPH: u8 = 0x10;
|
||
pub const SEG_SOUL_INDEX: u8 = 0x11;
|
||
|
||
/// Complete soul signature as a graph container.
|
||
pub struct SoulSignature {
|
||
/// Content-addressed identifier: SHA-256 of the RVF blob bytes.
|
||
pub content_hash: [u8; 32],
|
||
/// Opaque person identifier (never PII directly).
|
||
pub person_id: u64,
|
||
/// Unix timestamp of enrollment completion (nanoseconds).
|
||
pub enrolled_at_ns: u64,
|
||
/// Device that performed enrollment.
|
||
pub enrolled_by_device_id: String,
|
||
/// All graph nodes, typed.
|
||
pub nodes: SoulNodes,
|
||
/// All graph edges.
|
||
pub edges: Vec<SoulEdge>,
|
||
/// Ed25519 witness chain (per ADR-110).
|
||
pub witness: WitnessChain,
|
||
}
|
||
|
||
pub struct SoulNodes {
|
||
pub aether_embedding: Option<AetherEmbeddingNode>,
|
||
pub cardiac_hr: Option<CardiacHRProfileNode>,
|
||
pub cardiac_waveform: Option<CardiacWaveformMorphologyNode>,
|
||
pub respiratory: Option<RespiratoryPatternNode>,
|
||
pub gait_timing: Option<GaitTimingNode>,
|
||
pub skeletal_proportions: Option<SkeletalProportionsNode>,
|
||
pub subcarrier_reflection: Option<SubcarrierReflectionProfileNode>,
|
||
pub body_field_coupling: Option<BodyFieldCouplingNode>,
|
||
}
|
||
|
||
pub struct SoulEdge {
|
||
pub edge_type: SoulEdgeType,
|
||
pub source_node_type: String,
|
||
pub target_node_type: String,
|
||
pub weight: f32, // edge attribute (e.g., correlation coefficient)
|
||
}
|
||
|
||
pub enum SoulEdgeType {
|
||
DerivedFrom,
|
||
CorrelatesWith,
|
||
TemporallyColocated,
|
||
TemporallyAfter,
|
||
RequiresFieldModel,
|
||
Fuses,
|
||
AttestedBy,
|
||
DerivedByKeypointTracker,
|
||
EnvironmentNormalized,
|
||
}
|
||
|
||
impl SoulSignature {
|
||
/// Serialize to an RVF binary blob.
|
||
pub fn to_rvf(&self) -> Vec<u8>;
|
||
/// Deserialize from an RVF binary blob.
|
||
pub fn from_rvf(data: &[u8]) -> Result<Self, SoulError>;
|
||
/// Compute the weighted match score against a query.
|
||
pub fn match_score(&self, query: &SoulQuery, weights: &MatchWeights) -> f32;
|
||
/// Check whether all required nodes meet minimum confidence thresholds.
|
||
pub fn is_complete(&self, policy: &CompletenessPolicy) -> bool;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.8 What the Signature Is NOT
|
||
|
||
- Not a fingerprint of the room (that is the ADR-030 field model, a separate object).
|
||
- Not a waveform recording (the enrolled vectors are statistics and embeddings, not raw CSI).
|
||
- Not invertible to the original CSI stream (the AETHER projection head's information bottleneck prevents reconstruction; see ADR-024 §4 Negative consequences).
|
||
- Not a single scalar. Reducing to one number for threshold comparison is a deployment decision; the underlying object is a 7-channel graph.
|
||
- Not equal to a stored pose. The AETHER embedding captures body dynamics over many windows, not a single body pose at one instant.
|