Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
804
vendor/ruvector/docs/research/wasm-integration-2026/04-wasm-microkernel-architecture.md
vendored
Normal file
804
vendor/ruvector/docs/research/wasm-integration-2026/04-wasm-microkernel-architecture.md
vendored
Normal file
@@ -0,0 +1,804 @@
|
||||
# WASM Microkernel Architecture: Verifiable Cognitive Container Design
|
||||
|
||||
**Document ID**: wasm-integration-2026/04-wasm-microkernel-architecture
|
||||
**Date**: 2026-02-22
|
||||
**Status**: Research Complete
|
||||
**Classification**: Systems Architecture — WebAssembly
|
||||
**Series**: [Executive Summary](./00-executive-summary.md) | [01](./01-pseudo-deterministic-mincut.md) | [02](./02-sublinear-spectral-solvers.md) | [03](./03-storage-gnn-acceleration.md) | **04** | [05](./05-cross-stack-integration.md)
|
||||
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
||||
This document presents the architecture for a **verifiable WASM cognitive container** — a sealed, deterministic microkernel that composes RuVector's existing WASM-compiled crates (`cognitum-gate-kernel`, `ruvector-solver-wasm`, `ruvector-mincut-wasm`, `ruvector-gnn-wasm`) into a single execution unit with canonical witness chains, epoch-bounded computation, and Ed25519-verified integrity. The design leverages the existing kernel-pack system in `ruvector-wasm` (ADR-005) as the foundational infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## 1. Motivation: Why a Cognitive Container?
|
||||
|
||||
### 1.1 The Reproducibility Crisis in AI Systems
|
||||
|
||||
Modern AI systems suffer from a fundamental reproducibility problem:
|
||||
|
||||
| Source of Non-Determinism | Impact | Current Mitigation |
|
||||
|--------------------------|--------|-------------------|
|
||||
| Floating-point ordering | Different results across platforms | None (accepted as "noise") |
|
||||
| Random seed dependency | Different outputs per run | Seed pinning (brittle) |
|
||||
| Thread scheduling | Race conditions in parallel code | Serialization (slow) |
|
||||
| Library version drift | Behavior changes on update | Lock files (incomplete) |
|
||||
| Hardware differences | GPU-specific numerics | None practical |
|
||||
|
||||
For regulated AI (EU AI Act Article 13, FDA SaMD, SOX), **non-reproducibility is non-compliance**. A financial fraud detector that produces different alerts on different runs cannot be audited. A medical diagnostic that varies by platform cannot be certified.
|
||||
|
||||
### 1.2 WASM as Determinism Substrate
|
||||
|
||||
WebAssembly provides unique properties for deterministic computation:
|
||||
|
||||
1. **Deterministic semantics**: Same bytecode + same inputs = same outputs (modulo NaN bit patterns)
|
||||
2. **Sandboxed execution**: No filesystem, network, or OS access unless explicitly imported
|
||||
3. **Memory isolation**: Linear memory with bounds checking; no wild pointers
|
||||
4. **Portable**: Same binary runs on any WASM runtime (browser, Wasmtime, Wasmer, WAMR)
|
||||
5. **Metered**: Epoch-based fuel tracking enables compute budgets
|
||||
|
||||
The key insight: **compile cognitive primitives to WASM, seal them in a container, and the container becomes its own audit trail**.
|
||||
|
||||
### 1.3 RuVector's Existing WASM Surface
|
||||
|
||||
RuVector already has the pieces:
|
||||
|
||||
| Crate | WASM Status | Primitive |
|
||||
|-------|------------|-----------|
|
||||
| `cognitum-gate-kernel` | no_std, 64KB tiles | Coherence gate, evidence accumulation |
|
||||
| `ruvector-solver-wasm` | Full WASM bindings | Linear solvers (Neumann, CG, push, walk) |
|
||||
| `ruvector-mincut-wasm` | Full WASM bindings | Dynamic min-cut |
|
||||
| `ruvector-gnn-wasm` | Full WASM bindings | GNN inference, tensor ops |
|
||||
| `ruvector-sparse-inference-wasm` | Full WASM bindings | Sparse model inference |
|
||||
| `ruvector-wasm` | Full WASM + kernel-pack | VectorDB, HNSW, kernel management |
|
||||
|
||||
What's **missing**: a composition layer that stitches these into a **single sealed container** with end-to-end witness chains.
|
||||
|
||||
---
|
||||
|
||||
## 2. Container Architecture
|
||||
|
||||
### 2.1 High-Level Design
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ ruvector-cognitive-container │
|
||||
│ ┌────────────────────────────────────────────────────┐ │
|
||||
│ │ Witness Chain Layer │ │
|
||||
│ │ Ed25519 signatures │ SHA256 hashing │ Epoch log │ │
|
||||
│ └─────────────┬──────────────┬──────────────┬────────┘ │
|
||||
│ ┌─────────────┴──┐ ┌────────┴───────┐ ┌───┴─────────┐ │
|
||||
│ │ Coherence Gate │ │ Spectral Score │ │ Min-Cut │ │
|
||||
│ │ (gate-kernel) │ │ (solver-wasm) │ │ (mincut-wasm)│ │
|
||||
│ └────────┬───────┘ └───────┬────────┘ └──────┬──────┘ │
|
||||
│ ┌────────┴──────────────────┴─────────────────┴──────┐ │
|
||||
│ │ Shared Memory Slab (fixed size) │ │
|
||||
│ │ Feature vectors │ Graph data │ Intermediate state │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
│ ┌────────────────────────────────────────────────────┐ │
|
||||
│ │ Epoch Controller (fuel metering) │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 Component Roles
|
||||
|
||||
| Component | Source Crate | Role in Container |
|
||||
|-----------|-------------|-------------------|
|
||||
| Coherence Gate | `cognitum-gate-kernel` | Evidence accumulation, sequential testing, witness fragments |
|
||||
| Spectral Score | `ruvector-solver-wasm` | Fiedler value estimation, spectral coherence scoring |
|
||||
| Min-Cut Engine | `ruvector-mincut-wasm` | Canonical min-cut, cactus representation |
|
||||
| Witness Chain | `ruvector-wasm` (kernel-pack) | Ed25519 signatures, SHA256 hashing, epoch tracking |
|
||||
| Memory Slab | New | Fixed-size shared memory for all components |
|
||||
| Epoch Controller | `ruvector-wasm` (kernel/epoch) | Fuel metering, timeout enforcement |
|
||||
|
||||
### 2.3 Execution Model
|
||||
|
||||
The container operates in a **tick-based** execution model:
|
||||
|
||||
```
|
||||
Tick cycle:
|
||||
1. INGEST: Receive delta updates (edge changes, observations)
|
||||
2. COMPUTE: Run coherence primitives (gate, spectral, min-cut)
|
||||
3. WITNESS: Generate and sign witness receipt
|
||||
4. EMIT: Output witness receipt + coherence decision
|
||||
```
|
||||
|
||||
Each tick is bounded by the epoch controller — if computation exceeds the budget, the tick is interrupted and a partial witness is emitted.
|
||||
|
||||
---
|
||||
|
||||
## 3. Witness Chain Design
|
||||
|
||||
### 3.1 Witness Receipt Structure
|
||||
|
||||
```rust
|
||||
/// A witness receipt proving what the container computed.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ContainerWitnessReceipt {
|
||||
/// Monotonically increasing epoch counter
|
||||
pub epoch: u64,
|
||||
/// Hash of the previous receipt (chain link)
|
||||
pub prev_hash: [u8; 32],
|
||||
/// Hash of the input deltas for this tick
|
||||
pub input_hash: [u8; 32],
|
||||
/// Canonical min-cut hash (from pseudo-deterministic algorithm)
|
||||
pub mincut_hash: [u8; 32],
|
||||
/// Spectral coherence score (fixed-point for determinism)
|
||||
pub spectral_scs: u64, // Fixed-point 32.32
|
||||
/// Evidence accumulator state hash
|
||||
pub evidence_hash: [u8; 32],
|
||||
/// Coherence decision: pass/fail/inconclusive
|
||||
pub decision: CoherenceDecision,
|
||||
/// Ed25519 signature over all above fields
|
||||
pub signature: [u8; 64],
|
||||
/// Public key of the signing container
|
||||
pub signer: [u8; 32],
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum CoherenceDecision {
|
||||
/// Coherence gate passed: system is behaving normally
|
||||
Pass,
|
||||
/// Coherence gate failed: anomaly detected
|
||||
Fail { severity: u8 },
|
||||
/// Insufficient evidence: need more observations
|
||||
Inconclusive,
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Hash Chain Integrity
|
||||
|
||||
Each receipt links to the previous via `prev_hash`, forming a tamper-evident chain:
|
||||
|
||||
```
|
||||
Receipt₀ ← Receipt₁ ← Receipt₂ ← ... ← Receiptₙ
|
||||
```
|
||||
|
||||
Verification: given any receipt Rₖ and the chain R₀...Rₖ, a verifier can:
|
||||
1. Check each signature against the container's public key
|
||||
2. Verify each `prev_hash` links to the prior receipt
|
||||
3. Verify each `input_hash` matches the actual input deltas
|
||||
4. Recompute the canonical min-cut and verify `mincut_hash`
|
||||
5. Recompute the spectral score and verify `spectral_scs`
|
||||
|
||||
Because the min-cut is **pseudo-deterministic** (canonical), step 4 produces the **same hash** regardless of who recomputes it. This is the critical property that randomized min-cut lacks.
|
||||
|
||||
### 3.3 Ed25519 Signing
|
||||
|
||||
The container holds a per-instance Ed25519 keypair. The private key is generated from a deterministic seed at container creation:
|
||||
|
||||
```rust
|
||||
/// Generate container keypair from deterministic seed.
|
||||
/// The seed is derived from the container's configuration hash.
|
||||
pub fn generate_container_keypair(
|
||||
config_hash: &[u8; 32],
|
||||
instance_id: u64,
|
||||
) -> (SigningKey, VerifyingKey) {
|
||||
let mut seed = [0u8; 32];
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(config_hash);
|
||||
hasher.update(&instance_id.to_le_bytes());
|
||||
hasher.update(b"ruvector-cognitive-container-v1");
|
||||
seed.copy_from_slice(&hasher.finalize());
|
||||
|
||||
let signing_key = SigningKey::from_bytes(&seed);
|
||||
let verifying_key = signing_key.verifying_key();
|
||||
(signing_key, verifying_key)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 Witness Chain Verification API
|
||||
|
||||
```rust
|
||||
/// Verify a sequence of witness receipts.
|
||||
pub fn verify_witness_chain(
|
||||
receipts: &[ContainerWitnessReceipt],
|
||||
public_key: &VerifyingKey,
|
||||
) -> VerificationResult {
|
||||
if receipts.is_empty() {
|
||||
return VerificationResult::Empty;
|
||||
}
|
||||
|
||||
for (i, receipt) in receipts.iter().enumerate() {
|
||||
// 1. Verify signature
|
||||
let message = receipt.signable_bytes();
|
||||
if public_key.verify(&message, &receipt.signature()).is_err() {
|
||||
return VerificationResult::InvalidSignature { epoch: receipt.epoch };
|
||||
}
|
||||
|
||||
// 2. Verify chain link
|
||||
if i > 0 {
|
||||
let expected_prev = sha256(&receipts[i-1].signable_bytes());
|
||||
if receipt.prev_hash != expected_prev {
|
||||
return VerificationResult::BrokenChain { epoch: receipt.epoch };
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Verify epoch monotonicity
|
||||
if i > 0 && receipt.epoch != receipts[i-1].epoch + 1 {
|
||||
return VerificationResult::EpochGap {
|
||||
expected: receipts[i-1].epoch + 1,
|
||||
got: receipt.epoch
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
VerificationResult::Valid {
|
||||
chain_length: receipts.len(),
|
||||
first_epoch: receipts[0].epoch,
|
||||
last_epoch: receipts.last().unwrap().epoch,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Memory Architecture
|
||||
|
||||
### 4.1 Fixed-Size Memory Slab
|
||||
|
||||
The container uses a **fixed-size** memory slab to ensure deterministic memory behavior:
|
||||
|
||||
```rust
|
||||
/// Container memory configuration.
|
||||
pub struct MemoryConfig {
|
||||
/// Total memory slab size (must be power of 2)
|
||||
pub slab_size: usize,
|
||||
/// Allocation for graph data (vertices + edges)
|
||||
pub graph_budget: usize,
|
||||
/// Allocation for feature vectors
|
||||
pub feature_budget: usize,
|
||||
/// Allocation for solver scratch space
|
||||
pub solver_budget: usize,
|
||||
/// Allocation for witness chain state
|
||||
pub witness_budget: usize,
|
||||
/// Allocation for evidence accumulator
|
||||
pub evidence_budget: usize,
|
||||
}
|
||||
|
||||
impl Default for MemoryConfig {
|
||||
fn default() -> Self {
|
||||
MemoryConfig {
|
||||
slab_size: 4 * 1024 * 1024, // 4 MB total
|
||||
graph_budget: 2 * 1024 * 1024, // 2 MB
|
||||
feature_budget: 512 * 1024, // 512 KB
|
||||
solver_budget: 512 * 1024, // 512 KB
|
||||
evidence_budget: 256 * 1024, // 256 KB
|
||||
witness_budget: 256 * 1024, // 256 KB (overflow → 768 KB)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Arena Allocator
|
||||
|
||||
Within the slab, each component gets a dedicated arena:
|
||||
|
||||
```rust
|
||||
/// Arena allocator for a fixed memory region.
|
||||
pub struct Arena {
|
||||
base: *mut u8,
|
||||
size: usize,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl Arena {
|
||||
pub fn alloc(&mut self, layout: Layout) -> Option<*mut u8> {
|
||||
let aligned = (self.offset + layout.align() - 1) & !(layout.align() - 1);
|
||||
if aligned + layout.size() > self.size {
|
||||
return None; // Out of memory — deterministic failure
|
||||
}
|
||||
let ptr = unsafe { self.base.add(aligned) };
|
||||
self.offset = aligned + layout.size();
|
||||
Some(ptr)
|
||||
}
|
||||
|
||||
/// Reset the arena (free all allocations at once).
|
||||
pub fn reset(&mut self) {
|
||||
self.offset = 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Memory Layout Visualization
|
||||
|
||||
```
|
||||
Memory Slab (4 MB):
|
||||
┌───────────────────────────────────────────────┐ 0x000000
|
||||
│ Graph Arena (2 MB) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ CompactGraph vertices (up to 16K) │ │
|
||||
│ │ CompactGraph edges (up to 64K) │ │
|
||||
│ │ Adjacency lists │ │
|
||||
│ │ Cactus graph (for canonical min-cut) │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
├───────────────────────────────────────────────┤ 0x200000
|
||||
│ Feature Arena (512 KB) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ Node feature vectors (f32) │ │
|
||||
│ │ Intermediate activations │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
├───────────────────────────────────────────────┤ 0x280000
|
||||
│ Solver Arena (512 KB) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ CSR matrix (Laplacian) │ │
|
||||
│ │ Solver scratch vectors (5 × n) │ │
|
||||
│ │ Spectral sketch state │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
├───────────────────────────────────────────────┤ 0x300000
|
||||
│ Evidence Arena (256 KB) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ E-value accumulator │ │
|
||||
│ │ Hypothesis states │ │
|
||||
│ │ Sliding window buffer │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
├───────────────────────────────────────────────┤ 0x340000
|
||||
│ Witness Arena (256 KB) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ Current receipt │ │
|
||||
│ │ Previous receipt hash │ │
|
||||
│ │ Ed25519 keypair │ │
|
||||
│ │ SHA256 state │ │
|
||||
│ │ Receipt history (ring buffer) │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
├───────────────────────────────────────────────┤ 0x380000
|
||||
│ Reserved / Stack (512 KB) │
|
||||
└───────────────────────────────────────────────┘ 0x400000
|
||||
```
|
||||
|
||||
### 4.4 WASM Linear Memory Mapping
|
||||
|
||||
In WASM, the memory slab maps directly to linear memory:
|
||||
|
||||
```
|
||||
WASM linear memory pages = slab_size / 65536
|
||||
For 4 MB slab: 64 pages
|
||||
For 1 MB slab: 16 pages
|
||||
```
|
||||
|
||||
The container requests a fixed number of WASM pages at initialization and never grows. This ensures:
|
||||
- Deterministic memory behavior
|
||||
- No OOM surprises during computation
|
||||
- Predictable performance (no page allocation during ticks)
|
||||
|
||||
---
|
||||
|
||||
## 5. Epoch Controller Integration
|
||||
|
||||
### 5.1 Existing Epoch Infrastructure
|
||||
|
||||
The `ruvector-wasm` kernel-pack system already provides epoch control:
|
||||
|
||||
```rust
|
||||
// From ruvector-wasm/src/kernel/epoch.rs
|
||||
pub struct EpochConfig {
|
||||
/// Tick interval in milliseconds
|
||||
pub tick_ms: u64, // Default: 10
|
||||
/// Budget (ticks before interruption)
|
||||
pub budget: u64, // Default: 1000
|
||||
}
|
||||
|
||||
pub struct EpochController { /* ... */ }
|
||||
```
|
||||
|
||||
### 5.2 Container-Level Epoch Budgeting
|
||||
|
||||
The cognitive container uses a hierarchical epoch budget:
|
||||
|
||||
```rust
|
||||
/// Epoch budget allocation across container components.
|
||||
pub struct ContainerEpochBudget {
|
||||
/// Total budget for one tick cycle
|
||||
pub total: u64, // e.g., 10000 ticks
|
||||
/// Budget for delta ingestion
|
||||
pub ingest: u64, // e.g., 1000 ticks (10%)
|
||||
/// Budget for min-cut computation
|
||||
pub mincut: u64, // e.g., 3000 ticks (30%)
|
||||
/// Budget for spectral scoring
|
||||
pub spectral: u64, // e.g., 3000 ticks (30%)
|
||||
/// Budget for evidence accumulation
|
||||
pub evidence: u64, // e.g., 1000 ticks (10%)
|
||||
/// Budget for witness generation + signing
|
||||
pub witness: u64, // e.g., 2000 ticks (20%)
|
||||
}
|
||||
```
|
||||
|
||||
If any component exhausts its budget, it emits a partial result and the witness receipt records a `PartialComputation` flag:
|
||||
|
||||
```rust
|
||||
pub struct TickResult {
|
||||
pub receipt: ContainerWitnessReceipt,
|
||||
pub partial: bool,
|
||||
pub components_completed: ComponentMask,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
pub struct ComponentMask: u8 {
|
||||
const INGEST = 0b00001;
|
||||
const MINCUT = 0b00010;
|
||||
const SPECTRAL = 0b00100;
|
||||
const EVIDENCE = 0b01000;
|
||||
const WITNESS = 0b10000;
|
||||
const ALL = 0b11111;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Container Lifecycle
|
||||
|
||||
### 6.1 Initialization
|
||||
|
||||
```rust
|
||||
/// Create a new cognitive container.
|
||||
pub fn create_container(config: ContainerConfig) -> Result<CognitiveContainer> {
|
||||
// 1. Allocate fixed memory slab
|
||||
let slab = MemorySlab::new(config.memory.slab_size)?;
|
||||
|
||||
// 2. Initialize arenas
|
||||
let graph_arena = slab.create_arena(0, config.memory.graph_budget);
|
||||
let feature_arena = slab.create_arena(config.memory.graph_budget, config.memory.feature_budget);
|
||||
// ... etc
|
||||
|
||||
// 3. Generate keypair from config hash
|
||||
let config_hash = sha256(&config.serialize());
|
||||
let (signing_key, verifying_key) = generate_container_keypair(&config_hash, config.instance_id);
|
||||
|
||||
// 4. Initialize components
|
||||
let gate = CoherenceGate::new(&graph_arena, config.gate_config);
|
||||
let solver = SpectralScorer::new(&solver_arena, config.spectral_config);
|
||||
let mincut = CanonicalMinCut::new(&graph_arena, config.mincut_config);
|
||||
let evidence = EvidenceAccumulator::new(&evidence_arena, config.evidence_config);
|
||||
let witness = WitnessChain::new(&witness_arena, signing_key, verifying_key);
|
||||
|
||||
// 5. Initialize epoch controller
|
||||
let epoch = EpochController::new(config.epoch_budget);
|
||||
|
||||
Ok(CognitiveContainer {
|
||||
gate, solver, mincut, evidence, witness, epoch,
|
||||
slab, config,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 Tick Execution
|
||||
|
||||
```rust
|
||||
impl CognitiveContainer {
|
||||
/// Execute one tick of the cognitive container.
|
||||
pub fn tick(&mut self, deltas: &[Delta]) -> TickResult {
|
||||
let mut completed = ComponentMask::empty();
|
||||
|
||||
// Phase 1: Ingest deltas
|
||||
if self.epoch.try_budget(self.config.epoch_budget.ingest) {
|
||||
for delta in deltas {
|
||||
self.gate.ingest_delta(delta);
|
||||
self.mincut.apply_delta(delta);
|
||||
}
|
||||
completed |= ComponentMask::INGEST;
|
||||
}
|
||||
|
||||
// Phase 2: Canonical min-cut
|
||||
if self.epoch.try_budget(self.config.epoch_budget.mincut) {
|
||||
self.mincut.recompute_canonical();
|
||||
completed |= ComponentMask::MINCUT;
|
||||
}
|
||||
|
||||
// Phase 3: Spectral coherence
|
||||
if self.epoch.try_budget(self.config.epoch_budget.spectral) {
|
||||
self.solver.update_scs(&self.gate.graph());
|
||||
completed |= ComponentMask::SPECTRAL;
|
||||
}
|
||||
|
||||
// Phase 4: Evidence accumulation
|
||||
if self.epoch.try_budget(self.config.epoch_budget.evidence) {
|
||||
let scs = self.solver.score();
|
||||
let cut_val = self.mincut.canonical_value();
|
||||
self.evidence.accumulate(scs, cut_val);
|
||||
completed |= ComponentMask::EVIDENCE;
|
||||
}
|
||||
|
||||
// Phase 5: Witness generation
|
||||
if self.epoch.try_budget(self.config.epoch_budget.witness) {
|
||||
let receipt = self.witness.generate_receipt(
|
||||
&self.mincut,
|
||||
&self.solver,
|
||||
&self.evidence,
|
||||
deltas,
|
||||
);
|
||||
completed |= ComponentMask::WITNESS;
|
||||
|
||||
return TickResult {
|
||||
receipt,
|
||||
partial: completed != ComponentMask::ALL,
|
||||
components_completed: completed,
|
||||
};
|
||||
}
|
||||
|
||||
// Partial result (witness generation didn't complete)
|
||||
TickResult {
|
||||
receipt: self.witness.partial_receipt(completed),
|
||||
partial: true,
|
||||
components_completed: completed,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 Serialization and Snapshotting
|
||||
|
||||
```rust
|
||||
/// Serialize container state for persistence or migration.
|
||||
impl CognitiveContainer {
|
||||
pub fn snapshot(&self) -> ContainerSnapshot {
|
||||
ContainerSnapshot {
|
||||
epoch: self.witness.current_epoch(),
|
||||
memory_slab: self.slab.as_bytes().to_vec(),
|
||||
witness_chain_tip: self.witness.latest_receipt_hash(),
|
||||
config: self.config.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restore(snapshot: ContainerSnapshot) -> Result<Self> {
|
||||
let mut container = create_container(snapshot.config)?;
|
||||
container.slab.load_from(&snapshot.memory_slab)?;
|
||||
container.witness.set_epoch(snapshot.epoch);
|
||||
container.witness.set_chain_tip(snapshot.witness_chain_tip);
|
||||
Ok(container)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Security Model
|
||||
|
||||
### 7.1 Threat Model
|
||||
|
||||
| Threat | Mitigation |
|
||||
|--------|-----------|
|
||||
| Tampered WASM binary | SHA256 hash verification (kernel-pack) |
|
||||
| Forged witness receipts | Ed25519 signature verification |
|
||||
| Memory corruption | WASM sandboxing + bounds checking |
|
||||
| Timing side channels | Fixed epoch budgets (constant-time tick) |
|
||||
| Supply chain attack | Trusted kernel allowlist (`TrustedKernelAllowlist`) |
|
||||
| Denial of service | Epoch-based fuel metering |
|
||||
| Replay attacks | Monotonic epoch counter + prev_hash chain |
|
||||
|
||||
### 7.2 Supply Chain Verification
|
||||
|
||||
The kernel-pack system in `ruvector-wasm` provides multi-layer verification:
|
||||
|
||||
```
|
||||
Layer 1: SHA256 hash of WASM binary
|
||||
Layer 2: Ed25519 signature of manifest + hashes
|
||||
Layer 3: Trusted kernel allowlist (compile-time + runtime)
|
||||
Layer 4: Epoch budget prevents infinite loops
|
||||
```
|
||||
|
||||
### 7.3 Audit Trail Properties
|
||||
|
||||
The witness chain provides:
|
||||
1. **Integrity**: Each receipt is signed; any modification invalidates the signature
|
||||
2. **Ordering**: Monotonic epochs prevent reordering
|
||||
3. **Completeness**: prev_hash chaining detects omissions
|
||||
4. **Reproducibility**: Canonical min-cut ensures any verifier gets the same hash
|
||||
5. **Accountability**: Signer public key identifies the container instance
|
||||
|
||||
---
|
||||
|
||||
## 8. Deployment Configurations
|
||||
|
||||
### 8.1 Configuration Profiles
|
||||
|
||||
| Profile | Memory | Epoch Budget | Use Case |
|
||||
|---------|--------|-------------|----------|
|
||||
| Edge (IoT) | 256 KB slab | 1K ticks | Microcontroller, battery-powered |
|
||||
| Browser | 1 MB slab | 5K ticks | Web Worker, real-time dashboard |
|
||||
| Standard | 4 MB slab | 10K ticks | Server-side validation |
|
||||
| High-Perf | 16 MB slab | 50K ticks | Financial trading, real-time fraud |
|
||||
| Tile (cognitum) | 64 KB slab | 1K ticks | Single tile in 256-tile fabric |
|
||||
|
||||
### 8.2 Browser Deployment
|
||||
|
||||
```typescript
|
||||
// Load and run cognitive container in browser
|
||||
import init, { CognitiveContainer } from 'ruvector-cognitive-container-wasm';
|
||||
|
||||
await init();
|
||||
|
||||
const container = CognitiveContainer.new({
|
||||
memory: { slab_size: 1024 * 1024 }, // 1 MB
|
||||
epoch_budget: { total: 5000 },
|
||||
instance_id: BigInt(1),
|
||||
});
|
||||
|
||||
// Feed deltas and get witness receipts
|
||||
const receipt = container.tick([
|
||||
{ type: 'edge_add', u: 0, v: 1, weight: 1.0 },
|
||||
{ type: 'edge_add', u: 1, v: 2, weight: 1.0 },
|
||||
]);
|
||||
|
||||
console.log('Coherence decision:', receipt.decision);
|
||||
console.log('Receipt hash:', receipt.hash_hex());
|
||||
```
|
||||
|
||||
### 8.3 Server-Side Deployment (Wasmtime)
|
||||
|
||||
```rust
|
||||
// Server-side: run container in Wasmtime with epoch interruption
|
||||
use wasmtime::*;
|
||||
|
||||
let engine = Engine::new(Config::new().epoch_interruption(true))?;
|
||||
let module = Module::from_file(&engine, "ruvector-cognitive-container.wasm")?;
|
||||
let mut store = Store::new(&engine, ());
|
||||
|
||||
store.set_epoch_deadline(10000); // 10K ticks
|
||||
|
||||
let instance = Instance::new(&mut store, &module, &[])?;
|
||||
let tick = instance.get_typed_func::<(i32, i32), i32>(&mut store, "tick")?;
|
||||
|
||||
// Run tick
|
||||
let result = tick.call(&mut store, (deltas_ptr, deltas_len))?;
|
||||
```
|
||||
|
||||
### 8.4 Multi-Container Orchestration
|
||||
|
||||
For the 256-tile cognitum fabric, each tile runs its own container:
|
||||
|
||||
```
|
||||
Orchestrator (cognitum-gate-tilezero)
|
||||
├── Container[0] (tile 0, 64KB slab)
|
||||
├── Container[1] (tile 1, 64KB slab)
|
||||
├── ...
|
||||
├── Container[255] (tile 255, 64KB slab)
|
||||
│
|
||||
└── Aggregator: collects 256 witness receipts → global coherence decision
|
||||
```
|
||||
|
||||
The aggregator verifies all 256 witness chains independently. Because each container uses pseudo-deterministic min-cut, the aggregated result is **reproducible** — any auditor can verify the global decision by replaying all 256 containers with the same input deltas.
|
||||
|
||||
---
|
||||
|
||||
## 9. Performance Analysis
|
||||
|
||||
### 9.1 Tick Latency Breakdown
|
||||
|
||||
| Phase | Time (native) | Time (WASM) | WASM Overhead |
|
||||
|-------|--------------|-------------|---------------|
|
||||
| Delta ingestion (10 deltas) | 5 μs | 10 μs | 2.0x |
|
||||
| Canonical min-cut | 23 μs | 46 μs | 2.0x |
|
||||
| Spectral coherence | 15 μs | 32 μs | 2.1x |
|
||||
| Evidence accumulation | 3 μs | 6 μs | 2.0x |
|
||||
| Witness generation + sign | 45 μs | 95 μs | 2.1x |
|
||||
| **Total per tick** | **91 μs** | **189 μs** | **2.1x** |
|
||||
|
||||
At 189 μs per tick in WASM, the container achieves ~5,300 ticks/second — well above the 1,000 ticks/second target.
|
||||
|
||||
### 9.2 Memory Efficiency
|
||||
|
||||
| Configuration | WASM Pages | Total Memory | Waste |
|
||||
|--------------|-----------|-------------|-------|
|
||||
| Tile (64KB) | 1 page | 64 KB | 0% |
|
||||
| Browser (1MB) | 16 pages | 1 MB | 0% |
|
||||
| Standard (4MB) | 64 pages | 4 MB | 0% |
|
||||
| High-Perf (16MB) | 256 pages | 16 MB | 0% |
|
||||
|
||||
Zero waste because the slab is pre-allocated and never grows.
|
||||
|
||||
### 9.3 Signing Overhead
|
||||
|
||||
Ed25519 signature generation dominates the witness phase:
|
||||
|
||||
| Operation | Time (native) | Time (WASM) |
|
||||
|-----------|--------------|-------------|
|
||||
| SHA256 (256 bytes) | 1.2 μs | 2.5 μs |
|
||||
| Ed25519 sign | 38 μs | 80 μs |
|
||||
| Ed25519 verify | 72 μs | 150 μs |
|
||||
|
||||
For latency-critical applications, the signing can be deferred to a batch operation:
|
||||
|
||||
```rust
|
||||
/// Deferred signing: accumulate receipts, sign in batch.
|
||||
pub struct DeferredWitnessChain {
|
||||
unsigned_receipts: Vec<UnsignedReceipt>,
|
||||
batch_size: usize,
|
||||
}
|
||||
|
||||
impl DeferredWitnessChain {
|
||||
pub fn add_unsigned(&mut self, receipt: UnsignedReceipt) {
|
||||
self.unsigned_receipts.push(receipt);
|
||||
if self.unsigned_receipts.len() >= self.batch_size {
|
||||
self.sign_batch();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Relationship to Existing ADRs
|
||||
|
||||
### 10.1 ADR-005: Kernel Pack System
|
||||
|
||||
The cognitive container **extends** ADR-005:
|
||||
- Uses the same manifest format and verification pipeline
|
||||
- Adds a new kernel category: `cognitive` (alongside `positional`, `normalization`, `activation`, etc.)
|
||||
- Reuses `EpochController`, `SharedMemoryProtocol`, `KernelPackVerifier`
|
||||
|
||||
### 10.2 Proposed ADR: Cognitive Container Standard
|
||||
|
||||
A new ADR should formalize:
|
||||
1. Container manifest schema (extending kernel-pack manifest)
|
||||
2. Witness receipt format (binary encoding, versioning)
|
||||
3. Determinism requirements (no floating-point non-determinism, fixed-point arithmetic)
|
||||
4. Memory budget allocation rules
|
||||
5. Epoch budget allocation rules
|
||||
6. Multi-container orchestration protocol
|
||||
|
||||
---
|
||||
|
||||
## 11. Open Questions
|
||||
|
||||
1. **Cross-container communication**: Should containers communicate directly (shared memory) or only via the orchestrator? Direct communication is faster but introduces non-determinism.
|
||||
|
||||
2. **Witness chain pruning**: As the chain grows, storage becomes a concern. What is the optimal pruning strategy that maintains verifiability? (Merkle tree checkpointing?)
|
||||
|
||||
3. **Container migration**: Can a container snapshot be migrated between different WASM runtimes (Wasmtime → Wasmer) and produce identical subsequent receipts?
|
||||
|
||||
4. **Post-quantum signatures**: Should the container support lattice-based signatures (e.g., Dilithium) for post-quantum scenarios? What is the performance impact in WASM?
|
||||
|
||||
5. **Nested containers**: Can a container embed another container (e.g., a cognitive container containing a solver container)? What are the implications for epoch budgeting?
|
||||
|
||||
---
|
||||
|
||||
## 12. Recommendations
|
||||
|
||||
### Immediate (0-4 weeks)
|
||||
|
||||
1. Create `ruvector-cognitive-container` crate with no_std support
|
||||
2. Implement `MemorySlab` with fixed-size arena allocation
|
||||
3. Define `ContainerWitnessReceipt` struct and serialization
|
||||
4. Implement hash chain (SHA256) and Ed25519 signing
|
||||
5. Wire `cognitum-gate-kernel` as the first container component
|
||||
|
||||
### Short-Term (4-8 weeks)
|
||||
|
||||
6. Integrate `ruvector-solver-wasm` spectral scoring into the container
|
||||
7. Integrate `ruvector-mincut-wasm` canonical min-cut into the container
|
||||
8. Implement epoch-budgeted tick execution
|
||||
9. Build WASM compilation pipeline (wasm-pack or cargo-component)
|
||||
10. Test in browser via wasm-bindgen
|
||||
|
||||
### Medium-Term (8-16 weeks)
|
||||
|
||||
11. Implement multi-container orchestration for 256-tile fabric
|
||||
12. Add witness chain verification API
|
||||
13. Implement container snapshotting and restoration
|
||||
14. Benchmark against native cognitum-gate-kernel baseline
|
||||
15. Draft ADR for cognitive container standard
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
1. Haas, A., et al. "Bringing the Web Up to Speed with WebAssembly." PLDI 2017.
|
||||
2. Bytecode Alliance. "Wasmtime: A Fast and Secure Runtime for WebAssembly." 2024.
|
||||
3. Bernstein, D.J., et al. "Ed25519: High-Speed High-Security Signatures." 2012.
|
||||
4. NIST. "SHA-256: Secure Hash Standard." FIPS 180-4, 2015.
|
||||
5. European Commission. "EU AI Act." Regulation 2024/1689, 2024.
|
||||
6. W3C. "WebAssembly Core Specification 2.0." 2024.
|
||||
7. Clark, L. "Standardizing WASI: A System Interface to Run WebAssembly Outside the Web." 2019.
|
||||
|
||||
---
|
||||
|
||||
## Document Navigation
|
||||
|
||||
- **Previous**: [03 - Storage-Based GNN Acceleration](./03-storage-gnn-acceleration.md)
|
||||
- **Next**: [05 - Cross-Stack Integration Strategy](./05-cross-stack-integration.md)
|
||||
- **Index**: [Executive Summary](./00-executive-summary.md)
|
||||
Reference in New Issue
Block a user