memvid-core.
This unlocks:
- Strict multi-tenant isolation (no cross-tenant leakage)
- RBAC (roles/groups/principals) at frame/chunk level
- A single
.mv2per environment with metadata-based enforcement (recommended)
Mental Model
- A frame is the atomic unit of retrieval in Memvid. When you ingest a PDF, Memvid creates many frames (chunks).
- ACL is evaluated per frame, so “chunk-level ACL” means “frame-level ACL metadata”.
- ACL is not keyword-based: it does not guess who can see content. You decide the policy at ingest time.
ACL Metadata (Ingest-Time)
Attach the following keys in the framemetadata (stored on disk in the frame’s extra_metadata):
| Key | Type | Required | Meaning |
|---|---|---|---|
acl_tenant_id | string | Yes (recommended) | Tenant boundary for strict isolation |
acl_visibility | "public" | "restricted" | Yes | public is readable by anyone in-tenant; restricted requires a match |
acl_read_roles | string[] | If restricted | Allowed roles |
acl_read_groups | string[] | If restricted | Allowed group IDs |
acl_read_principals | string[] | If restricted | Allowed subject/principal IDs |
acl_policy_version | string | Yes | Policy schema version (currently "v1") |
acl_resource_id | string | Optional | Stable lineage identifier (optional) |
In Node/Python SDKs you can provide
string[] values directly for acl_read_*. The SDK will normalize and persist them in a canonical form for the core evaluator.ACL strings are normalized (trimmed + lowercased). Treat role/group/principal identifiers as case-insensitive.Example: Role-Restricted Chunk
ACL Context (Query-Time)
At query time you provide the caller identity viaacl_context / aclContext:
| Field | Type | Meaning |
|---|---|---|
tenant_id / tenantId | string | Tenant boundary (required for enforcement) |
subject_id / subjectId | string | The current user (principal) |
roles | string[] | User roles |
group_ids / groupIds | string[] | User group IDs |
audit: evaluate ACL but do not block results (migration/testing)enforce: filter results; deny-by-default for missing/invalid ACL metadata
Creating an ACL-Scoped API Key (Dashboard)
In the Memvid dashboard:- Go to API Keys and click Create Key
- Enable ACL scope
- Set Tenant ID (required for strict isolation)
- Optionally set Roles, Group IDs, and Subject ID
- Choose enforcement mode:
auditorenforce
End-to-End (Node.js)
End-to-End (Python)
Chunk-Level Guarding (Example Policy)
You decide which chunks are restricted to which readers at ingest time. Example policy:- Pages 1-20:
role=finance - Pages 21-30:
role=hr - Pages 31+:
principal=matt
put_many() / putMany() with per-chunk metadata (rather than a single put_file() metadata applied to all chunks).
If you use
put_file(...) with metadata=..., the same ACL metadata is applied to every produced chunk. That’s perfect for document-level ACL, but not enough for section/page-level ACL.Single .mv2 vs One .mv2 Per Tenant
Single .mv2 per environment (recommended):
- Store all tenants in one file
- Always set
acl_tenant_idon every frame - Always pass
acl_context.tenant_idat retrieval - Use
restricted+ allow-lists for sensitive frames
.mv2 per tenant (simpler operations, more files):
- Easier isolation boundaries
- More operational overhead (more files to manage, ticketing/capacity per file)