From 603b82188b9d21add84d0032cd061bf9085504ac Mon Sep 17 00:00:00 2001 From: ruvnet Date: Wed, 19 Aug 2026 17:47:37 +0000 Subject: [PATCH] deploy: c929bbc8b36d75cbfcfa8b447190e2c9a9a79d79 --- ...ctivation-and-governed-spatial-exchange.md | 47 +++++- ...6-tenant-scoped-ruvector-spatial-memory.md | 137 ++++++++++++++++++ ...ned-action-intents-and-witness-receipts.md | 133 +++++++++++++++++ api-docs/user-guide.md | 52 +++++++ 4 files changed, 362 insertions(+), 7 deletions(-) create mode 100644 api-docs/adr/ADR-326-tenant-scoped-ruvector-spatial-memory.md create mode 100644 api-docs/adr/ADR-327-governed-action-intents-and-witness-receipts.md diff --git a/api-docs/adr/ADR-325-cognitum-spaces-activation-and-governed-spatial-exchange.md b/api-docs/adr/ADR-325-cognitum-spaces-activation-and-governed-spatial-exchange.md index 98aaa77a..2d34690d 100644 --- a/api-docs/adr/ADR-325-cognitum-spaces-activation-and-governed-spatial-exchange.md +++ b/api-docs/adr/ADR-325-cognitum-spaces-activation-and-governed-spatial-exchange.md @@ -1,6 +1,6 @@ # ADR-325: Cognitum Spaces activation and governed spatial exchange -- **Status**: Accepted — read path implemented; write path remains policy-gated +- **Status**: Accepted — legacy read live; versioned hierarchy, local memory, and governed-action implementation validated on feature branches; deployment pending - **Date**: 2026-08-17 - **Deciders**: ruv - **Tags**: cognitum-spaces, oauth, spatial-state, privacy, ruvector, policy, autogenous @@ -423,10 +423,43 @@ Identity metadata deliberately advertises `spaces:read` for RuView but not publisher surface. RuView therefore has no OAuth write, command, policy-approval, or actuator capability. -This evidence does not claim implementation of sites/buildings/floors/zones, -entities, semantic event or alert resources, tenant-scoped RuVector spatial -history, MQTT reconciliation, governed actions, commands, or actuators. Those -remain separately reviewed milestones. +This production evidence does not claim deployment of sites/buildings/floors/ +zones, entities, semantic event or alert resources, tenant-scoped RuVector +spatial history, MQTT reconciliation, governed actions, commands, or actuators. +The first three are implemented and locally validated in the 2026-08-19 feature +branches described below, but remain non-production until their workflow and +readback gates pass. Commands and actuators remain out of scope. + +## Feature-branch implementation evidence (2026-08-19) + +- Cognitum API ADR-101 implements all eight `/v1/spatial` collections, coherent + transactional hierarchy checks, stable pagination, event/alert retention, + strict P2/P3 admission, API-key-only writes, and OAuth/API-key reads. The + Firestore emulator passed both the legacy and versioned verification scripts, + including cross-resource message replay denial. +- `ruview-cognitum-spaces` adds a strictly decoded, paged, read-only client for + every versioned collection. `wifi-densepose spaces --resource ...` exposes it + while preserving the legacy flat command. The focused client suite and the + CLI no-default-features test gate pass. +- The contributor metaharness now accepts `resource`, `limit`, and opaque + `cursor` on `ruview_spaces_list`, fixes the API origin, strips API-key + compatibility authority, and revalidates hierarchy/event/alert contracts. + Full metaharness, security, brain, flywheel, manifest, audit, and pack gates + pass for the `@ruvnet/ruview` 0.5.0 release candidate. +- ADR-326 adds `ruview-spatial-memory`: one RuVector HNSW index per authenticated + tenant/workspace, replay/derivation/retention gates, cascading erasure, + bounded explanations, and XChaCha20-Poly1305 snapshots with reload-verified + key rotation. Its focused crate suite passes with `SYNTHETIC` evidence. +- ADR-327 extends `ruview-policy` with typed observe/recommend/execute intents, + exact host grants, signed approvals, nonce/idempotency defense, the existing + ADR-321 assurance matrix, and signed hash-chained receipts. `spaces:read` is + explicitly denied as execution authority. Its focused crate suite passes. +- The required whole-workspace Rust command was attempted twice on Windows: + parallel compilation ended in a compiler-process stack-buffer-overrun and a + single-job retry reached the configured timeout without a source/test + diagnostic. This is not recorded as a green gate; Linux CI remains required. +- No OAuth write/action scope, actuator callback, MQTT deployment claim, sensing + accuracy claim, or real-hardware claim is introduced. ## Consequences @@ -445,8 +478,8 @@ remain separately reviewed milestones. - Two credential types coexist during migration and must stay visibly distinct. - OAuth depends on Identity JWKS availability and correct key rotation. -- The current API exposes spaces only; the full hierarchy/events/alerts model - remains staged work. +- Production currently exposes the legacy spaces slice; the implemented full + hierarchy/events/alerts model remains staged until deployment/readback. - OAuth workspace IDs will return only documents populated with `workspaceId`; legacy owner-only documents require an explicit migration, never a broad query. - The RuView client exposes no write, command, or agent execution surface. The diff --git a/api-docs/adr/ADR-326-tenant-scoped-ruvector-spatial-memory.md b/api-docs/adr/ADR-326-tenant-scoped-ruvector-spatial-memory.md new file mode 100644 index 00000000..370988f0 --- /dev/null +++ b/api-docs/adr/ADR-326-tenant-scoped-ruvector-spatial-memory.md @@ -0,0 +1,137 @@ +# ADR-326: Tenant-scoped RuVector spatial memory and anomaly explanations + +- **Status**: Accepted — implementation complete; repository-wide and deployment gates pending +- **Date**: 2026-08-19 +- **Decision owners**: RuView maintainers +- **Extends**: ADR-312, ADR-319, ADR-325 +- **Implements**: ruvnet/RuView#1640 +- **Tags**: cognitum-spaces, ruvector, memory, tenant-isolation, explanation, privacy + +## Context + +ADR-325 requires anomaly explanations grounded in tenant-local spatial history, +but the deployed client only returns a current list. A global vector index would +be unsafe: filtering nearest-neighbor results after the search can reveal that a +different tenant has a close match, even when identifiers are removed. A memory +record can also launder returned RuView-derived state into a second independent +observation, reset freshness, or form circular evidence. + +Spatial memory must be useful without storing OAuth/API credentials, raw CSI/CIR, +RF tensors, pose frames, vital waveforms, recordings, identity observations, or +unbounded agent transcripts. Persistence also needs explicit retention, +deletion, provenance, and key-rotation behavior. + +## Decision + +### 1. Partition before similarity + +`ruview-spatial-memory` owns a `SpatialMemory` map keyed by the exact authenticated +`(tenant_id, workspace_id)` pair. Each partition owns its own RuVector HNSW index. +Ingest and search resolve the partition first; no global ANN query exists. Site, +space, schema version, and time-window constraints narrow within the selected +partition before results are returned. + +### 2. Bounded semantic records + +An accepted record contains: + +- tenant/workspace/site/space and stable record identity; +- source ID, message ID, record ID, monotonic event sequence, schema version; +- original `observed_at`/`expires_at` and a retention deadline; +- a bounded finite semantic feature vector, uncertainty, and evidence label; +- provenance and witness digests, plus bounded derivation references; +- explicit observation/inference classification. + +Credentials and P0/P1 fields have no representation in the type. Strings, +features, references, record counts, and query `k` are bounded. Non-finite +features and uncertainty fail closed. + +### 3. Lineage and replay + +The partition rejects: + +- changed reuse of `(source_id, message_id)`; +- a non-increasing sequence for the same source; +- duplicate derivation references; +- self-reference, missing/forward parents, and therefore every cycle; +- expired input or a provenance/witness substitution. + +A recollection keeps its original lineage, timestamp, uncertainty, and evidence +label. It cannot increment corroborating-source count or become independent +support for its own ancestor. + +### 4. Persistent encrypted storage + +Snapshots are encrypted with XChaCha20-Poly1305 under a caller-supplied 256-bit +key and a non-secret key ID. The authenticated associated data binds the storage +format and key ID. The envelope is bounded and versioned; plaintext spatial +records are never written to disk. Loading requires a keyring containing the +named key. Rotation decrypts with the old key, atomically creates a new +generation under the new key ID, reload-verifies that generation, and leaves +the source intact. Snapshots never overwrite an existing path implicitly. + +Deletion supports a tenant/workspace partition, a record, and retention cutoff. +Every deletion rebuilds that partition's HNSW index so removed records cannot be +returned from stale graph nodes. + +### 5. Explanations + +`explain` compares a bounded query vector with nearest tenant-local history and +returns the exact authenticated partition, generation time, ordered record IDs, +RuVector distances, original uncertainty/evidence labels, and provenance/witness +digests. Its basis explicitly says that similarity is not causation. The API +does not expose the vectors or invent a causal explanation. + +History provides context, not authority. An explanation cannot authorize an +action, increase certificate class, or replace a policy decision. + +## Consequences + +### Positive + +- Cross-tenant ANN leakage is structurally unavailable. +- Explanations cite the exact tenant-local records used. +- Replay/cycle/provenance substitution are rejected before indexing. +- Encrypted persistence has explicit key IDs and rotation behavior. + +### Costs and limitations + +- Partition-local HNSW uses more indexes than a global graph. +- Deletes and key rotation rebuild indexes. +- No detection-quality or latency claim is made; tests are `SYNTHETIC` unless a + reproducer explicitly marks a measurement. +- Cloud Cognitum does not receive the local encrypted memory file. + +## Validation + +- cross-tenant and cross-workspace nearest-neighbor denial; +- duplicate record/message, stale-sequence, self/duplicate/missing-parent, and + provenance-substitution tests; +- expiry, retention deletion, whole-partition deletion, sealed round-trip, + tamper rejection, wrong-key rejection, and key-rotation tests; +- explanation citations and retained evidence/provenance labels; +- no forbidden raw-field or credential representation; +- the focused `ruview-spatial-memory` crate suite passes with `SYNTHETIC` + evidence on 2026-08-19; +- the whole-workspace Windows gate was non-terminal (compiler crash in parallel, + timeout when serialized), so Linux CI, a RustSec advisory scan, and package + review remain release gates. + +## Alternatives considered + +**One global HNSW followed by filtering.** Rejected: ranking itself crosses the +tenant boundary. + +**Cloud vector memory.** Rejected as the default: it expands the privacy and +credential boundary without being needed for local explanations. + +**Plain JSONL persistence.** Rejected because tenant spatial history is sensitive +even when raw sensing is excluded. + +## References + +- ADR-312: Long-term spatial memory +- ADR-319: Witness chain +- ADR-325: Cognitum Spaces activation and governed exchange +- Cognitum API ADR-101 +- ruvnet/RuView#1640 diff --git a/api-docs/adr/ADR-327-governed-action-intents-and-witness-receipts.md b/api-docs/adr/ADR-327-governed-action-intents-and-witness-receipts.md new file mode 100644 index 00000000..d2032a3a --- /dev/null +++ b/api-docs/adr/ADR-327-governed-action-intents-and-witness-receipts.md @@ -0,0 +1,133 @@ +# ADR-327: Governed action intents, approvals, replay protection, and witness receipts + +- **Status**: Accepted — implementation complete; repository-wide and deployment gates pending +- **Date**: 2026-08-19 +- **Decision owners**: RuView maintainers +- **Extends**: ADR-318, ADR-319, ADR-321, ADR-325 +- **Implements**: ruvnet/RuView#1641 +- **Tags**: policy, governed-action, approval, idempotency, witness, cognitum-spaces + +## Context + +The current `ruview-policy` crate evaluates assurance for an action class, but it +does not define a complete action intent, tenant/workspace binding, policy +version, approval, nonce/idempotency replay behavior, or signed terminal receipt. +An agent recommendation can therefore be mistaken for execution authority, and +`spaces:read` could be accidentally treated as a general capability. + +The system needs a framework that can prove why an action was allowed or denied +without adding any actuator. Real actuation remains a separate integration and +requires its own threat model and device evidence. + +## Decision + +### 1. Typed intent and registered policy + +A governed `ActionIntent` binds: + +- intent ID, tenant, workspace, action name/class, and exact target; +- requested policy version and parameter/evidence digests; +- creation/expiry, replay nonce, and requesting principal; +- the recommendation/explanation that motivated review, never a hidden command. + +The gate accepts only a registered action policy. Unknown action, action-class +mismatch, policy-version mismatch, target mismatch, invalid timestamps, and +missing exact host authority deny before assurance is evaluated. Tenant and +workspace are part of the signed intent/receipt and nonce key. `spaces:read` is +explicitly tested as insufficient for an `alerts:execute` rule. + +### 2. Assurance and approval + +The existing ADR-321 certificate/domain/uncertainty/evidence gate remains the +assurance authority. The registered policy declares a bounded minimum of +distinct enrolled approvers. An absent, rejected, duplicated, expired, +wrong-intent, wrong-policy-version, or unverifiable approval denies. Approval +resolution fails closed. + +Agents observe, explain, or recommend by default. `evaluate` returns a decision +receipt; it does not call an actuator. An executor may consume an `allow` receipt +only if a separate adapter verifies the receipt, target, expiry, and its own +device-specific authority. + +### 3. Replay and idempotency + +The bounded in-memory gate stores terminal receipts by intent ID and tracks +nonces by `(tenant, workspace, nonce)`. + +- exact intent replay returns the original terminal receipt; +- changed reuse of an intent ID returns a fail-closed idempotency error; +- reuse of a nonce by another intent returns a fail-closed replay error; +- expired intents and approvals deny; +- failed or denied attempts are terminal and auditable. + +The current state store is bounded and in-memory, intended for local/runtime use +rather than cross-process replay protection. A production executor must place +the same intent/nonce/receipt invariants behind a transactional durable store; +this ADR does not claim that adapter exists. + +### 4. Witnessed terminal receipt + +Every evaluated observe/recommend/execute request produces a canonical receipt +containing the intent digest, decision/reason, policy version, tenant/workspace, +decision/expiry time, intent ID and nonce, approval count, and previous receipt +digest. The receipt is signed through the `ruview-attest` signer interface and +can be independently verified. Hash chaining makes removal/reordering visible. +Malformed input, ID conflict, nonce replay, capacity exhaustion, and sequence +exhaustion are errors before receipt creation and must be audited by the host. + +The reference keyed-BLAKE3 signer remains `SYNTHETIC` evidence only, as documented +by ADR-319. Production asymmetric signing and key custody must be supplied by the +deployment adapter; no symmetric test MAC is represented as hardware identity. + +## Consequences + +### Positive + +- Recommendation, authorization, and execution are distinct typed stages. +- Default-deny covers missing policy, stale evidence, unavailable approval, and replay. +- Every decision has a terminal, verifiable explanation. +- `spaces:read` cannot silently expand into consequence. + +### Costs and limitations + +- Executors must implement a separate receipt-verifying adapter. +- Distributed replay protection needs a transactional durable store. +- This ADR implements no actuator, command transport, pairing mutation, or device control. +- Simulator tests are not hardware validation. + +## Validation + +- unknown/missing policy, stale intent, policy-version/target mismatch, + insufficient authority, and `spaces:read`-only denial; +- certificate/domain/uncertainty/evidence denial matrix from ADR-321; +- missing/rejected/expired/duplicate/wrong-intent approval tests; +- exact idempotent replay, changed reuse, nonce replay, and bounded-store tests; +- receipt signature, canonical digest, chain linkage, and tamper rejection; +- tests proving evaluation exposes no actuator callback or network/file side effect. + +The focused `ruview-policy` suite passes on 2026-08-19. The reference signer +tests are `SYNTHETIC`; they are not hardware-identity evidence. The non-terminal +whole-workspace Windows gate still requires authoritative Linux CI evidence. + +Any future actuator adds a separate ADR, credential boundary, failure/rollback +plan, allow/deny integration tests, and captured target-device evidence. + +## Alternatives considered + +**Let agents call actuators after a recommendation.** Rejected: recommendation +quality is not authorization. + +**Treat OAuth scopes as action policy.** Rejected: `spaces:read` expresses read +consent only and carries no target-specific assurance or approval. + +**Emit receipts only for successful actions.** Rejected: denial and unavailable +approval are security-relevant terminal facts. + +## References + +- ADR-318: Capability certificates +- ADR-319: Witness chain +- ADR-321: Decision policy action authorization +- ADR-325: Cognitum Spaces activation and governed exchange +- ADR-326: Tenant-scoped RuVector spatial memory +- ruvnet/RuView#1641 diff --git a/api-docs/user-guide.md b/api-docs/user-guide.md index 9b1a51ce..9e5b5a9a 100644 --- a/api-docs/user-guide.md +++ b/api-docs/user-guide.md @@ -22,6 +22,7 @@ WiFi DensePose turns commodity WiFi signals into real-time human pose estimation - [ESP32-S3 (Full CSI)](#esp32-s3-full-csi) - [ESP32 Multistatic Mesh (Advanced)](#esp32-multistatic-mesh-advanced) - [Connect Mesh Data to the Dashboard and Observatory](#connect-mesh-data-to-the-dashboard-and-observatory) + - [Cognitum Spaces activation](#cognitum-spaces-activation) - [Cognitum Seed Integration (ADR-069)](#cognitum-seed-integration-adr-069) 5. [REST API Reference](#rest-api-reference) 6. [WebSocket Streaming](#websocket-streaming) @@ -425,6 +426,57 @@ curl http://localhost:3000/api/v1/sensing/latest If the ESP32 nodes are provisioned with `--target-ip `, that IP must be the machine running `sensing-server`. Only one process can receive UDP `:5005` at a time, so leave the standalone hardware `aggregator` off while the dashboard or Observatory is live. +### Cognitum Spaces activation + +Cognitum Spaces gives RuView a tenant/workspace-scoped semantic world model +without uploading raw RF/CSI, recordings, pose frames, vital waveforms, or +identity observations. It represents sites, buildings, floors, bounded +rooms/spaces, zones, anonymous entities, semantic events, and alerts. + +Activate the public RuView OAuth client with Authorization Code + PKCE: + +```bash +wifi-densepose login --spaces +wifi-densepose whoami +wifi-densepose spaces --resource sites --limit 50 +wifi-densepose spaces --resource events --limit 25 +``` + +The login requests `sensing:read spaces:read`. That consent is read-only: it +does not grant publication, pairing, policy approval, command, or actuator +authority. Versioned collections are `sites`, `buildings`, `floors`, +`spaces`, `zones`, `entities`, `events`, and `alerts`. A returned +`nextCursor` is opaque and valid only for the same collection. + +The dependency-free contributor harness exposes the same read path: + +```bash +npx @ruvnet/ruview@0.5.0 spaces --resource alerts --limit 25 +npx @ruvnet/ruview@0.5.0 mcp start +``` + +Its MCP tool is `ruview_spaces_list`. MCP reads are OAuth-only, use the fixed +Cognitum API origin, and require the explicit guarded-tool opt-in. The harness +does not accept an arbitrary credential path or API origin. + +For service compatibility, `wifi-densepose spaces` can read +`COGNITUM_SPACES_API` at request time. API-key access to a versioned collection +also requires `--workspace `; OAuth derives the workspace from the +signed token. Never print or commit either credential. + +Every response is bounded and revalidated. Raw-sensing aliases, malformed +hierarchy, non-anonymous person/track entities, invalid timestamps, stale +confidence, and oversized structures fail closed. Empty data means no +authorized state is present; it does not prove that a physical site is empty. + +RuVector spatial memory remains physically separated by tenant and workspace. +Agents observe or recommend by default. Any consequential execution requires a +separate policy/grant/approval decision and produces a signed, hash-chained +receipt; the Spaces read token can never satisfy that gate. + +See ADR-325, ADR-326, and ADR-327 for the activation, memory, and governed-action +decisions. + ### Cognitum Seed Integration (ADR-069) Connect an ESP32-S3 to a [Cognitum Seed](https://cognitum.one) (Pi Zero 2 W, ~$15) for persistent vector storage, kNN similarity search, cryptographic witness chain, and AI-accessible sensing via MCP proxy.