Data isolation
Mneva's isolation model is structural, not procedural. There is no shared row, no shared table, no cross-tenant WHERE clause anyone could forget.
One brain per tenant
Every customer's brain is its own SQLite database file on the engine box:
/var/lib/mneva/tenants/
registry.json (id, name, key, created_at — no contents)
t_3194131b2393.db (tenant A's brain — memories, beliefs, predictions, dreams, evidence)
t_3194131b2393.db-shm (WAL shared memory)
t_3194131b2393.db-wal (WAL log)
t_80744acd0d9b.db (tenant B — entirely separate file)
...
When a request comes in with x-mneva-key: mnv_..., the engine looks up the tenant in the registry, resolves it to a database file path, and opens that file. There is no cross-tenant query path.
This is harder to get wrong than a shared table with tenant_id columns. A bug in a query cannot leak data between tenants because the query is running against the wrong physical database — and would have to be redirected at file-system level, not at SQL level.
What gets stored
Inside each tenant brain:
memories— text + 1024-d embedding + caution score + timestampbeliefs— text + confidence + SPRT state + supersession chainbelief_evidence— every supporting/refuting event with note and timestamppredictions— prediction + domain + confidence + (when resolved) outcome + actual + surprisedreams— wander-produced thoughts + source memory ids + noveltyagent_observations— multi-agent outside viewstenant_activity— per-minute tool-call counter (forstate)
Plain text. No PII required — Mneva does not ask for it. If you store PII inside the text of a memory, that's on you (and you should think hard about whether you want to).
What we never store
- The full API key (only the last 4 chars, as a display hint)
- Card data (Square tokenizes in the browser; we see only the nonce)
- Cleartext passwords
- IP addresses associated with content (nginx logs them for ops; they aren't joined to your brain data)
- Cross-tenant aggregations of memory content
At scale
SQLite-per-tenant is the current isolation model. At scale (tens of thousands of active tenants), this becomes schema-per-tenant in Postgres — the same contract, different physical store. The customer-facing API does not change.
Self-hosters can run the engine against the bundled SQLite or substitute Postgres; see Self-hosting.