read and/or write access. Each user then loads the index with their own per-user key and is restricted to the permissions they were granted.
Key model. Each index is encrypted under a 32-byte Key-Encryption-Key (KEK) — the
index_key. The root KEK holder mints per-user wrapped keys; the set of wraps that exist is the permission set — there is no separate permission flag. A read-only user simply has no write wrap. Managing users (create / delete / list) is always gated on the root KEK.Minting User Keys
The root holder callscreate_user_keys (Python) / CreateUserKeys (C++), supplying the new user’s 16-byte identifier, their 32-byte per-user KEK, the permissions to grant, and the root index KEK as the admin gate.
user_id and user_kek to that user out-of-band — together they are that user’s credentials for the index.
Loading the Index as a User
A user loads the index with their own KEK as theindex_key and passes their user_id. From then on, every operation is gated to the permissions they hold — a read-only user’s upsert/delete is rejected, raising RuntimeError in Python (std::runtime_error in C++).
In Python, you can also override the key per operation with
index_key= and user_id= keyword arguments — required in stateless/service deployments that reload the index per request. In C++, every key-bearing method takes a trailing KeyContext; construct it as cyborg::KeyContext{user_kek, user_id} for an RBAC user, or pass a bare KEK for the root holder.Listing and Revoking Users
User management is always gated on the root KEK.list_user_keys returns each user’s id and whether they have read/write; delete_user_keys revokes a user (idempotent).
API Reference
For full signatures and exceptions, refer to the API Reference:Python API Reference
API reference for
create_user_keys / list_user_keys / delete_user_keys in PythonC++ API Reference
API reference for
CreateUserKeys / ListUserKeys / DeleteUserKeys in C++