store_memory or recall_memory.
Deployment shape
At runtime, sovseal occupies two distinct zones: an on-device agent process that holds all plaintext and keys, and a remote replication endpoint that holds nothing but ciphertext.recall_memory makes an outbound HTTP request.
store_memory write lifecycle
When your agent calls store_memory, seven things happen in sequence before the call returns — and one more happens asynchronously afterward.
1
Payload canonicalization
The SDK receives the payload object, orders all keys alphabetically, and serializes the result into a stable JSON byte array. This step ensures that semantically identical payloads produce identical cryptographic hashes regardless of how the object was originally constructed.
2
Local embedding
The canonicalized payload is passed to the local
Transformers.js model, producing a 384-dimensional floating-point dense vector. This step runs entirely on-device using ONNX Runtime. No text is sent to a remote embedding API.3
Encryption boundary
The SDK encrypts the serialized JSON bytes using AES-256-GCM with a 96-bit random IV generated on-device. This yields ciphertext and a 128-bit authentication tag. The plaintext and the encryption key never leave the local trust boundary.
4
Lineage attachment
The SDK queries the local index for the current HEAD snapshot ID, then computes the new snapshot ID as:This creates a hash-linked chain of records. Any modification to a past record breaks the chain forward from that point.
5
Local commit
The vector, path hash (
sha256(path)), ciphertext, nonce, auth tag, parent pointer, and snapshot ID are committed atomically to the on-device LanceDB index. LanceDB calls fsync to ensure disk durability before the commit returns.6
Return to the agent
The
store_memory call resolves in under 5ms. Your agent continues without blocking on any network round-trip.7
Write-behind replication (async)
A background worker picks up the local record, batches it with any pending records, and sends the ciphertext and metadata only to the replication endpoint. If the network is unavailable, the worker retries with exponential backoff. The agent is not blocked at any point during this process.
recall_memory read lifecycle
When your agent calls recall_memory, the entire operation completes locally. There is no network path for reads.
1
Query embedding
The query string is embedded locally using the same
Transformers.js model. If the query matches a recent search, the embedding is served from a 256-entry LRU cache, bypassing the model entirely.2
Vector lookup
The SDK runs a vector similarity search (L2 distance) across the local LanceDB index. This operation is 0 RTT and works completely offline — there is no fallback to a remote query.
3
Decryption and auth-tag verification
The SDK retrieves the matching record from LanceDB, uses the local device key to decrypt the ciphertext, and validates the AES-GCM 128-bit authentication tag. A tag mismatch means the ciphertext was tampered with and fails closed — the record is not returned.
4
VSR anchor validation
The SDK re-derives the snapshot ID by hashing the decrypted payload together with the stored parent snapshot ID and compares it against the snapshot ID in the index. A mismatch means either the payload was substituted or the lineage was broken; in either case the read fails closed.
5
Return to the agent
Plaintext is returned to your agent in ~6ms p50. The agent never sees a record that failed either the auth-tag check or the VSR anchor check.
Encryption boundary and key custody
Plaintext and cryptographic keys exist only inside your agent process’s memory space. The diagram below shows exactly where the trust boundary falls.Key custody details
Your master key is held in the OS keychain — macOS Keychain, Windows Credential Manager, or Linux libsecret — not in a plaintext config file.- Generated with a CSPRNG on first run; never written to disk in the clear.
- Purpose-bound subkeys are derived on demand via HKDF-SHA256:
k_restfor local at-rest encryption andk_syncfor replication. ~/.sovseal/config.json(mode0600) holds identity and routing only —project_id,api_key,endpoint— and contains no key material.- Headless fallback: Set
SOVSEAL_KEY_FALLBACK=fileto store the master key at~/.sovseal/(mode0600). Without this flag, a missing keychain fails closed rather than falling back silently. - The server verifies your key by hashing it alone (
sha256(key)) and comparing against the storedkey_hashcolumn — it never sees the raw key.
Local embedding pipeline
sovseal generates embeddings on-device to ensure that no plaintext is sent to a remote embedding API.
The cold start happens once — when the MCP server or SDK first loads the ONNX model. After warmup, query latency is sub-25ms p99.
Write-behind replication and partition recovery
Replication runs on a non-blocking background queue. The agent always gets control back before any network I/O occurs.- Batching: The sync worker polls every
SOVSEAL_SYNC_INTERVAL_MS(default 2000ms), draining up to 5,000 pending rows per cycle into AES-256-GCM blocks capped at 64 KB ciphertext each. - Offline buffering: Transient failures leave rows
pending; the next poll cycle retries automatically. Records stay queued in the local LanceDB store —store_memorycalls are never blocked by replication. - Split-brain halt: If the worker detects another writer already holds a different block at the same
sequence_number, it halts sync entirely for that agent rather than guessing which version is correct — see Replication & Sync for the full conflict-resolution behavior. - Crash safety: In-flight replication jobs are tracked in the on-device outbox table. If the agent process crashes, unacknowledged sync events are reloaded on restart and replicated successfully.