Isolate tenants and issue keys
AI DraftProvision tenant namespaces and delegate limited access.
Provision a namespace for each tenant, issue a key for its services, and delegate access to a specific collection. Keep cluster credentials in your provisioning service.
Choose the boundary
Resource scope
Namespace: acme
Allowed collections
incident-logs · policies
Northwind is outside this boundary.
Actions
What this key can do
Scope and actions must both allow the request.
A namespace separates one tenant’s collections from another’s. Decide the namespace after your application authenticates the customer. Do not accept a customer-supplied namespace without checking that relationship.
Use a cluster key to create the namespace. Set exist_ok: true when provisioning should return an existing namespace. Keep its immutable ID and name in your tenant record.
Issue a namespace key
POST https://engine.example.com/keys
POST /keys HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json
{
"name": "acme-service",
"scope": {
"kind": "namespace",
"namespace": "acme",
"actions": [
"read",
"write",
"search",
"query"
]
}
}201 Created · secret returned once
{
"id": "key_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
"name": "acme-service",
"prefix": "gek_",
"secret": "<NEW_ENGINE_API_KEY>",
"scope": {
"kind": "namespace",
"namespace": "acme",
"actions": [
"read",
"write",
"search",
"query"
]
},
"created_at": "2026-10-06T12:00:00Z"
}Replace <NEW_ENGINE_API_KEY> with the actual secret from the response. Store it immediately in the service’s secret store. Retain the separate key_ ID for management. A later list request cannot recover the secret.
A namespace key requires explicit actions. write includes read; search and query are independent. Include only the actions the tenant service needs.
Delegate collection access
A namespace key can issue a collection key in its own namespace. The new action list must be a subset of the creating key’s effective actions. A collection key cannot issue another key.
POST https://engine.example.com/keys
POST /keys HTTP/1.1
Host: engine.example.com
Authorization: Bearer <ACME_NAMESPACE_KEY>
Content-Type: application/json
{
"name": "incident-search",
"scope": {
"kind": "collection",
"namespace": "acme",
"collections": [
"incident-logs"
],
"actions": [
"search"
]
}
}The result has the same key shape as the namespace example, with the requested collection scope. This key can Search incident-logs. It cannot Query, read file content, write files, or access another collection.
| Request | Result with this Search-only key |
|---|---|
Search incident-logs | Allowed. |
Query incident-logs | 403 forbidden: missing query action. |
Read a file in incident-logs | 403 forbidden: missing read action. |
Search another collection | 404 not_found: outside resource scope. |
Create a collection | Forbidden for a collection key. |
Replace and revoke keys
Keys remain valid until revoked. Create a replacement key, update the service, and confirm its requests succeed. Then revoke the previous key with its management ID.
DELETE https://engine.example.com/keys/key_01J8Z3K4N5P6Q7R8S9T0V1W2X3
DELETE /keys/key_01J8Z3K4N5P6Q7R8S9T0V1W2X3 HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>204 No Content
HTTP/1.1 204 No ContentRevocation takes effect immediately. Requests using that secret return 401 unauthenticated. Deleting a key does not delete its namespace or files.
Read Authentication for the exact scope and action contracts. Add access rules when users within a tenant need different retrieval permissions.