ruvector/examples/rvf/examples/serverless_function.rs
rUv c7a5f228c9 feat(rvf): RuVector Format — Universal Cognitive Container SDK (#166)
* feat(rvf): add RuVector Format universal substrate specification

Research and design for RVF — a streaming, progressive, adaptive, quantum-secure
binary format for vector intelligence. Covers append-only segment model, two-level
tail manifests, temperature tiering, progressive HNSW indexing, epoch-based overlay
system, SIMD-optimized query paths, WASM microkernel for Cognitum tiles, domain
profiles (RVDNA, RVText, RVGraph, RVVision), and post-quantum cryptography.

https://claude.ai/code/session_01DDqjGE51JpsRE3DgUjFyjW

* feat(rvf): add deletion, filtered search, concurrency, and operations specs

Fill four specification gaps in the RVF format design:
- spec/07: Vector deletion lifecycle, JOURNAL_SEG wire format, deletion bitmaps
- spec/08: Filtered search with META_SEG, METAIDX_SEG, filter expression language
- spec/09: Writer locking, reader-writer coordination, versioning, space reclamation
- spec/10: Batch operations API, error codes, network streaming protocol

Also fixes the segment header field conflict between spec/01 and wire/binary-layout.md
(checksum_algo/compression now u8, adds uncompressed_len at 0x38).

https://claude.ai/code/session_01DDqjGE51JpsRE3DgUjFyjW

* feat(rvf): add RuVector Format SDK, 40 examples, MCP server, and documentation

Complete RVF implementation including:
- 12 Rust crates (rvf-types, rvf-wire, rvf-manifest, rvf-index, rvf-quant,
  rvf-crypto, rvf-runtime, rvf-import, rvf-wasm, rvf-node, rvf-server,
  plus integration tests)
- 40 runnable examples covering core storage, agentic AI, production
  patterns, vertical domains, exotic capabilities, runtime targets,
  network/security, POSIX/systems, and network operations
- TypeScript SDK (npm/packages/rvf) with RvfDatabase class
- MCP server (npm/packages/rvf-mcp-server) with stdio and SSE transports
- Node.js N-API bindings (npm/packages/rvf-node)
- WASM package (npm/packages/rvf-wasm)
- ADR-029 (canonical format), ADR-030 (computational container),
  ADR-031 (example repository)
- DNA-style lineage provenance, computational containers (KERNEL_SEG,
  EBPF_SEG), witness chains, TEE attestation, domain profiles
- Superseded ADR annotations for ADR-001, ADR-005, ADR-006, ADR-018-021

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(rvf): add CLI, WASM store, generate_all, and 46 output .rvf files

- Add rvf-cli crate (665 lines, 9 subcommands: create/ingest/query/delete/status/inspect/compact/derive/serve)
- Add WASM control plane store (alloc_setup, segment, store modules) for ~46 KB binary
- Add generate_all.rs example producing 46 persistent .rvf files in output/
- Add Node.js N-API bindings for lineage, kernel/eBPF, and inspection
- Add npm TypeScript backend/database/types for RVF integration
- Update READMEs with CLI sections, MCP server docs, and crate map (13 crates)
- All 40 examples verified passing

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(rvf): add Claude Code appliance, improve Quick Start, fix API docs

- Add claude_code_appliance.rs: self-booting RVF with SSH + Claude Code
  install (curl -fsSL https://claude.ai/install.sh | bash), 3 SSH users,
  eBPF filter, 20-package manifest, witness chain, lineage snapshot
- Improve Quick Start: Install section (crate/CLI/npm/WASM/MCP), WASM
  browser example, generate_all reference, expanded Rust crate deps
- Fix embed_kernel/embed_ebpf API docs to match actual signatures
  (u8 params with `as u8` cast, 6-param kernel, Option<&[u8]> btf)
- Update generate_all.rs: add claude_code_appliance generator (47 files)
- Regenerate all 47 output .rvf files

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(rvf): add RVCOW branching, real kernel/eBPF/launcher, 795 tests

Vector-native copy-on-write branching (ADR-031) with four new segment
types (COW_MAP 0x20, REFCOUNT 0x21, MEMBERSHIP 0x22, DELTA 0x23),
real Linux microkernel builder, QEMU microVM launcher, real eBPF
programs, and 128-byte KernelBinding for tamper-evident kernel-manifest
linkage.

New crates:
- rvf-kernel: Docker-based kernel build, real cpio/newc initramfs builder,
  SHA3-256 verification, prebuilt kernel support (37 tests)
- rvf-launch: QEMU microVM launcher with QMP shutdown, KVM/TCG detection,
  virtio-blk/net port forwarding, kernel extraction (8 tests)
- rvf-ebpf: 3 real BPF C programs (xdp_distance, socket_filter,
  tc_query_route) with clang compilation support (17 tests)

RVCOW runtime:
- CowEngine with read/write paths, write coalescing, snapshot-freeze
- CowMap (flat-array), MembershipFilter (bitmap), CowCompactor
- 3x read performance via pread optimization (1.3us/vector)
- Branch creation: 2.6ms for 10K vectors, child = 162 bytes

Security: 20-finding audit, 7 fixes applied including division-by-zero
guards, integer overflow checks, and KernelBinding::from_bytes_validated().

CLI: 8 new commands (launch, embed-kernel, embed-ebpf, filter, freeze,
verify-witness, verify-attestation, rebuild-refcounts), serve wired to
real rvf-server.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(rvf): update README, add crate/npm READMEs, publish to crates.io and npm

- Rewrite README with cognitive container terminology, grouped features,
  4 comparison tables (vs Docker, Vector DBs, Git LFS, SQLite), updated
  benchmarks, architecture diagram, and 45 examples
- Add READMEs for rvf-kernel, rvf-launch, rvf-ebpf, rvf-import crates
- Add READMEs for @ruvector/rvf, rvf-node, rvf-wasm, rvf-mcp-server npm packages
- Fix Cargo.toml metadata (homepage, readme, categories, keywords) and
  add version specs to all path dependencies for crates.io publishing
- Fix clippy warnings in rvf-kernel/initramfs.rs and rvf-launch/lib.rs
- Published to crates.io: rvf-types, rvf-wire, rvf-manifest, rvf-quant,
  rvf-index, rvf-crypto (remaining crates pending rate limit)
- Published to npm: @ruvector/rvf, @ruvector/rvf-node, @ruvector/rvf-wasm,
  @ruvector/rvf-mcp-server

Co-Authored-By: claude-flow <ruv@ruv.net>

* chore: add rvf-kernel, rvf-ebpf, rvf-launch, rvf-server, rvf-import, rvf-cli to workspace

Include all 15 RVF crates plus integration tests and benchmarks in the
root workspace members list so cargo publish can resolve them by name.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(rvf): add published packages, cognitive container branding, grouped capabilities

- Add Published Packages section with 13 crates.io + 4 npm tables
- Add Platform Support table (Linux, macOS, Windows, WASM, no_std)
- Expand capability table from 9 to 15 rows in 4 groups
- Rewrite all "How" descriptions in plain language
- Update .rvf diagram to show all 20 segment types
- Rename ADRs: computational container -> cognitive container
- Add emojis to all section headers

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat: update root README with RVF cognitive containers, expanded capabilities

- Update intro: "gets smarter + ships as cognitive container"
- Add self-booting microservice row to Pinecone comparison table
- Expand capabilities from 34 to 42 features with dedicated RVF section
- Update "Think of it as" to include Docker comparison and RVF explanation
- Add RVF collapsed group to Ecosystem (13 crates, 4 npm, install commands)
- Add RVF to Platform & Edge section with install commands
- Add RVF npm packages (4) and Rust crates (13) to package reference
- Add RVF rows to feature comparison table (6 new rows)
- Add ADR-030/031 to ADR list
- Add RVF to Installation table, Project Structure
- Update attention mechanisms count from 39 to 40+
- Update npm count to 49+, Rust crates to 83
- Update footer with crates.io and RVF links

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat: expand comparison table with emojis, cost, audit, branching, single-file

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs: rewrite comparison table in plain language

Co-Authored-By: claude-flow <ruv@ruv.net>

* chore: clean up empty code change sections in the changes log

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-14 13:14:49 -05:00

346 lines
14 KiB
Rust

//! Serverless Cold-Start Optimized
//!
//! Category: Runtime Targets
//!
//! Demonstrates how RVF files are optimized for serverless function
//! cold starts. The manifest-based tail scan enables sub-5ms boot:
//! the runtime reads only the last segment (manifest) to discover the
//! full file layout, then progressively loads vectors on demand.
//!
//! Lifecycle demonstrated:
//! 1. Deployment: create an RVF file with vectors (done once)
//! 2. Cold start: open existing file (manifest tail scan)
//! 3. Handle request: query with filter
//! 4. Audit: add witness chain entry for each request
//! 5. Warm request: query again (vectors already loaded)
//!
//! RVF segments used: VEC_SEG, MANIFEST_SEG (via RvfStore), wire-level
//! tail_scan (via rvf_wire::find_latest_manifest), WITNESS_SEG (via
//! rvf_crypto)
//!
//! Run with:
//! cargo run --example serverless_function
use std::time::Instant;
use rvf_runtime::{
FilterExpr, MetadataEntry, MetadataValue, QueryOptions, RvfOptions, RvfStore, SearchResult,
};
use rvf_runtime::filter::FilterValue;
use rvf_runtime::options::DistanceMetric;
use rvf_crypto::{create_witness_chain, verify_witness_chain, shake256_256, WitnessEntry};
use rvf_wire::tail_scan::find_latest_manifest;
use tempfile::TempDir;
/// Simple pseudo-random number generator (LCG) for deterministic results.
fn random_vector(dim: usize, seed: u64) -> Vec<f32> {
let mut v = Vec::with_capacity(dim);
let mut x = seed.wrapping_add(1);
for _ in 0..dim {
x = x.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
v.push(((x >> 33) as f32) / (u32::MAX as f32) - 0.5);
}
v
}
fn main() {
println!("=== RVF Serverless Cold-Start Optimized ===\n");
let dim = 128;
let num_vectors = 500;
let k = 5;
// ====================================================================
// 1. DEPLOYMENT PHASE: Create the RVF file with vectors
// ====================================================================
println!("--- 1. Deployment Phase: Create RVF Store ---");
let tmp_dir = TempDir::new().expect("failed to create temp dir");
let store_path = tmp_dir.path().join("serverless.rvf");
let options = RvfOptions {
dimension: dim as u16,
metric: DistanceMetric::L2,
..Default::default()
};
let mut store = RvfStore::create(&store_path, options).expect("failed to create store");
// Insert vectors with metadata (representing a product catalog)
// field_id 0: category (String: "electronics", "clothing", "food", "books")
// field_id 1: price_tier (U64: 1=budget, 2=mid, 3=premium)
let categories = ["electronics", "clothing", "food", "books"];
let vectors: Vec<Vec<f32>> = (0..num_vectors)
.map(|i| random_vector(dim, i as u64))
.collect();
let batch_size = 100;
let num_batches = num_vectors / batch_size;
for batch_idx in 0..num_batches {
let start = batch_idx * batch_size;
let end = start + batch_size;
let batch_vecs: Vec<&[f32]> = vectors[start..end]
.iter()
.map(|v| v.as_slice())
.collect();
let batch_ids: Vec<u64> = (start as u64..end as u64).collect();
let mut metadata = Vec::with_capacity(batch_size * 2);
for i in start..end {
metadata.push(MetadataEntry {
field_id: 0,
value: MetadataValue::String(categories[i % 4].to_string()),
});
metadata.push(MetadataEntry {
field_id: 1,
value: MetadataValue::U64(((i * 3 + 1) % 3 + 1) as u64),
});
}
store
.ingest_batch(&batch_vecs, &batch_ids, Some(&metadata))
.expect("failed to ingest batch");
}
let deploy_status = store.status();
println!(" Vectors: {}", deploy_status.total_vectors);
println!(" Segments: {}", deploy_status.total_segments);
println!(" File size: {} bytes ({:.1} KB)", deploy_status.file_size, deploy_status.file_size as f64 / 1024.0);
println!(" Epoch: {}", deploy_status.current_epoch);
// Close the store (represents deployment upload)
store.close().expect("failed to close store");
println!(" Store closed (deployment artifact ready).");
// ====================================================================
// 2. COLD START: Reopen the store (demonstrates function boot)
// ====================================================================
println!("\n--- 2. Cold Start: Manifest Tail Scan ---");
// Read the raw file to demonstrate tail scan timing
let file_bytes = std::fs::read(&store_path).expect("failed to read file");
let scan_start = Instant::now();
let (manifest_offset, manifest_header) = find_latest_manifest(&file_bytes)
.expect("manifest not found");
let scan_elapsed = scan_start.elapsed();
println!(" File size: {} bytes", file_bytes.len());
println!(" Manifest found: offset {} (seg_id={})", manifest_offset, manifest_header.segment_id);
println!(" Manifest payload: {} bytes", manifest_header.payload_length);
println!(" Tail scan time: {:?}", scan_elapsed);
println!(" Scan strategy: backward from EOF at 64-byte boundaries");
// Now open via RvfStore (which internally does the same tail scan + boot)
let cold_start = Instant::now();
let cold_store = RvfStore::open(&store_path).expect("failed to open store");
let cold_elapsed = cold_start.elapsed();
let cold_status = cold_store.status();
println!("\n Full cold start (open + load vectors):");
println!(" Time: {:?}", cold_elapsed);
println!(" Vectors loaded: {}", cold_status.total_vectors);
println!(" Epoch: {}", cold_status.current_epoch);
// ====================================================================
// 3. HANDLE REQUEST: Query with filter
// ====================================================================
println!("\n--- 3. Request: Filtered Query ---");
let mut witness_entries: Vec<WitnessEntry> = Vec::new();
let base_timestamp = 1_700_000_000_000_000_000u64;
// Request 1: Find electronics in premium tier
let query1 = random_vector(dim, 42);
let filter1 = FilterExpr::And(vec![
FilterExpr::Eq(0, FilterValue::String("electronics".to_string())),
FilterExpr::Eq(1, FilterValue::U64(3)), // premium
]);
let opts1 = QueryOptions {
filter: Some(filter1),
..Default::default()
};
let req1_start = Instant::now();
let results1 = cold_store.query(&query1, k, &opts1).expect("query failed");
let req1_elapsed = req1_start.elapsed();
println!(" Request 1: electronics + premium tier");
println!(" Query time: {:?}", req1_elapsed);
println!(" Results: {} of {}", results1.len(), k);
print_results_with_meta(&results1, &categories);
// Record witness entry for request 1
let action1 = format!(
"SEARCH:filter=electronics+premium:k={}:results={}",
k,
results1.len()
);
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(action1.as_bytes()),
timestamp_ns: base_timestamp,
witness_type: 0x02, // COMPUTATION
});
// ====================================================================
// 4. WARM REQUEST: Query again (index already loaded)
// ====================================================================
println!("\n--- 4. Warm Request (Vectors Already Loaded) ---");
// Request 2: Find food items in budget tier
let query2 = random_vector(dim, 77);
let filter2 = FilterExpr::And(vec![
FilterExpr::Eq(0, FilterValue::String("food".to_string())),
FilterExpr::Eq(1, FilterValue::U64(1)), // budget
]);
let opts2 = QueryOptions {
filter: Some(filter2),
..Default::default()
};
let req2_start = Instant::now();
let results2 = cold_store.query(&query2, k, &opts2).expect("query failed");
let req2_elapsed = req2_start.elapsed();
println!(" Request 2: food + budget tier");
println!(" Query time: {:?} (warm path)", req2_elapsed);
println!(" Results: {} of {}", results2.len(), k);
print_results_with_meta(&results2, &categories);
// Record witness entry for request 2
let action2 = format!(
"SEARCH:filter=food+budget:k={}:results={}",
k,
results2.len()
);
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(action2.as_bytes()),
timestamp_ns: base_timestamp + 1_000_000_000,
witness_type: 0x02, // COMPUTATION
});
// Request 3: Unfiltered query
let query3 = random_vector(dim, 123);
let req3_start = Instant::now();
let results3 = cold_store
.query(&query3, k, &QueryOptions::default())
.expect("query failed");
let req3_elapsed = req3_start.elapsed();
println!("\n Request 3: unfiltered (all categories)");
println!(" Query time: {:?} (warm path)", req3_elapsed);
println!(" Results: {} of {}", results3.len(), k);
print_results_with_meta(&results3, &categories);
// Record witness entry for request 3
let action3 = format!(
"SEARCH:unfiltered:k={}:results={}",
k,
results3.len()
);
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(action3.as_bytes()),
timestamp_ns: base_timestamp + 2_000_000_000,
witness_type: 0x02, // COMPUTATION
});
// ====================================================================
// 5. AUDIT: Witness chain for request tracking
// ====================================================================
println!("\n--- 5. Witness Audit Trail ---");
let chain_bytes = create_witness_chain(&witness_entries);
println!(
" Created witness chain: {} entries, {} bytes",
witness_entries.len(),
chain_bytes.len()
);
match verify_witness_chain(&chain_bytes) {
Ok(verified) => {
println!(
" Chain integrity: VALID ({} entries verified)\n",
verified.len()
);
println!(
" {:>5} {:>8} {:>20} {:>32}",
"Index", "Type", "Timestamp (ns)", "Action Hash (first 16 bytes)"
);
println!(" {:->5} {:->8} {:->20} {:->32}", "", "", "", "");
for (i, entry) in verified.iter().enumerate() {
let wtype = match entry.witness_type {
0x01 => "PROV",
0x02 => "SEARCH",
_ => "????",
};
let hash_hex: String = entry
.action_hash[..16]
.iter()
.map(|b| format!("{:02x}", b))
.collect();
println!(
" {:>5} {:>8} {:>20} {}",
i, wtype, entry.timestamp_ns, hash_hex
);
}
}
Err(e) => println!(" Chain integrity: FAILED ({:?})", e),
}
// ====================================================================
// 6. Progressive loading concept (Layer A instant results)
// ====================================================================
println!("\n--- 6. Progressive Loading Concept ---");
println!(" In production serverless with large RVF files:");
println!(" Layer A (manifest + entry points): instant, < 1ms");
println!(" -> Provides coarse routing to correct partition");
println!(" Layer B (hot region adjacency): fast, < 5ms");
println!(" -> Covers frequently-accessed vectors");
println!(" Layer C (full HNSW graph): deferred, < 50ms");
println!(" -> Full recall, loaded in background");
println!(" This example uses flat scan (all layers loaded at open).");
println!(" For large datasets, progressive loading enables instant");
println!(" results even before the full index is in memory.");
// ====================================================================
// Summary
// ====================================================================
println!("\n=== Serverless Function Summary ===\n");
println!(" {:>28} {:>16}", "Metric", "Value");
println!(" {:->28} {:->16}", "", "");
println!(" {:>28} {:>16}", "Vectors", num_vectors);
println!(" {:>28} {:>16}", "Dimensions", dim);
println!(" {:>28} {:>14.1} KB", "File size", deploy_status.file_size as f64 / 1024.0);
println!(" {:>28} {:>16?}", "Tail scan time", scan_elapsed);
println!(" {:>28} {:>16?}", "Full cold start", cold_elapsed);
println!(" {:>28} {:>16?}", "Request 1 (cold, filtered)", req1_elapsed);
println!(" {:>28} {:>16?}", "Request 2 (warm, filtered)", req2_elapsed);
println!(" {:>28} {:>16?}", "Request 3 (warm, unfiltered)", req3_elapsed);
println!(" {:>28} {:>16}", "Witness entries", witness_entries.len());
cold_store.close().expect("failed to close store");
println!("\nDone.");
}
fn print_results_with_meta(results: &[SearchResult], categories: &[&str]) {
println!(" {:>6} {:>12} {:>14} {:>10}", "ID", "Distance", "Category", "Price Tier");
println!(" {:->6} {:->12} {:->14} {:->10}", "", "", "", "");
for r in results {
let cat = categories[(r.id as usize) % 4];
let tier = match ((r.id as usize) * 3 + 1) % 3 + 1 {
1 => "budget",
2 => "mid",
3 => "premium",
_ => "?",
};
println!(
" {:>6} {:>12.6} {:>14} {:>10}",
r.id, r.distance, cat, tier
);
}
}