Tenant isolation
A namespace is a physical store. By default every capability that is scoped to a
namespace shares it, so if two tenants both hold tokens for kv/scratchpad,
they read and write the same data. That's fine for a single-tenant
deployment, but in a multi-tenant one it's a data-leak.
Tenant isolation scopes each request's storage to the caller's capability
tenant, so two tenants sharing a namespace name get physically separate data.
# config.yaml
tenant_isolation: true
Behavior
- Off (default). Storage is byte-for-byte identical to how it worked before isolation existed. A single-tenant deployment is unaffected and existing data keeps working. This is why it's opt-in.
- On. Every block's storage key is prefixed with the caller's tenant
(from the capability token). Enforcement lives in one place (the service
layer, before the driver is ever touched), so a driver can't leak across
tenants even by accident. All tokens must carry a
tenant.
tenant "acme" ─┐
├─ kv.put("scratchpad", "k", …) → stored under acme
tenant "beta" ─┘ → stored under beta (separate)
Tenant A cannot read, scan, overwrite, or delete tenant B's records in the same namespace, and vice-versa.
Coverage
Isolation covers all six blocks: kv, episodic, lease, graph, artifact, and
semantic. The first five qualify the storage namespace string; the semantic
block, which is bound per-namespace, carries a tenant column so (tenant, id)
is a record's identity and every search/delete/expire is tenant-scoped. Two
tenants can reuse the same semantic record id without colliding.
Enabling it on an existing deployment
Turning isolation on changes where data is addressed. Data written before enabling it lives under the un-prefixed namespace and won't be visible to tenant-scoped reads afterward, which is the point (it was previously shared). Enable it from the start of a multi-tenant deployment, or migrate deliberately.
The tenant comes from the capability token, so issue every token with one:
mindctl token issue --tenant acme --agent a1 --ns 'kv/*' --ops '*'
See Capabilities for how tokens carry the tenant.