Conduit
Conduit
Docsllms.txtHostingGitHubIntroduction

Getting Started

OverviewInstall ConduitMCP SetupYour First AppStart with AI

Learn

ArchitectureClient vs Admin APIConfiguration

Modules

OverviewAuthenticationAuthorizationDatabaseStorageCommunicationsChatRouterFunctions

Guides

Next.js IntegrationReBAC Team ScopingGitOps State Export

Deployment

Deployment OverviewDocker ComposeKubernetes and HelmLocal from SourceContainer Images

Reference

CLI ReferenceClient APIAdmin APIEnvironment VariablesMCP Tools

Resources

Migration v0.16 → v0.17Legacy DocumentationChangelogFAQGlossaryContributing

Authorization

ReBAC resources, relations, permissions, indexing, and scope.

The authorization module implements relationship-based access control (ReBAC, Zanzibar-style). Subjects (users, teams) link to resources via relation tuples; permissions resolve from those tuples with optional inheritance (owner->read). An internal index (ActorIndex + ObjectIndex) makes can checks fast; tuples are the source of truth.

Apps call the Client API to check the signed-in user's access. Operators define resources, grant tuples, and debug evaluations through the Admin API or MCP at provision time — never from browser code.

Use cases

Multi-tenant B2B

Team-owned records — documents belong to a Team, not just a user

Document sharing

Grant editor/viewer relations without duplicating ownership logic

Scoped creates

New records inherit team context via the scope query param

Runtime permission checks

Ask can this user edit this resource? before showing UI actions

Bulk sharing

Grant one relation to many resources via POST /relations/many

Operator debugging

Trace why access was granted with GET /permissions/evaluate

Capabilities

  • Resource definitions (relations + permissions)
  • Relation tuple CRUD
  • Bulk relation creation (/relations/many)
  • Permission inheritance (->)
  • scope on database creates
  • Client API /authorization/check
  • Admin API /permissions/can and /evaluate
  • Index reconstruction (soft / hard)
  • Built-in Team resource
  • Authorized schema integration
  • gRPC Can / access-list views

Example: Team-owned documents with scope

Walkthrough

  1. Enable authorization on the Document schema (conduitOptions.authorization.enabled)
  2. Ensure the user has edit permission on Team:abc (team member or owner)
  3. Create a document with scope=Team:abc as a query parameter
  4. Before PATCH, call GET /authorization/check?action=edit&resource=Document:docId
Create with scope
curl -X POST "http://localhost:3000/database/Document?scope=Team:507f1f77bcf86cd799439011" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Q1 roadmap","body":"Team-owned doc"}'
Check permission (Client API)
curl "http://localhost:3000/authorization/check?action=edit&resource=Document:DOC_ID" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

How it works

Mental model

ReBAC stores tuples and resolves permissions from a resource definition:

ResourceDefinition "Document"
  relations: { owner: [User, Team], editor: [User, Team] }
  permissions: { read: [editor, owner, owner->read], edit: [editor, owner] }

Tuple:   Team:abc#owner@Document:xyz
Format:  subject#relation@resource

Check:   can(Team:abc, edit, Document:xyz) → true via team inheritance

Every tuple is persisted as a Relationship document with a unique computedTuple (User:uid#owner@Document:id). Creating or deleting a tuple updates ActorIndex and ObjectIndex rows so can checks avoid graph walks at request time.

Three layers (do not confuse)

LayerControls
Document ReBACPer-document read/edit/delete on authorized schemas
Schema CMS permissionsWho can use Admin Panel CRUD on a schema
Route middlewareHTTP route authentication flags on custom endpoints

This page covers document ReBAC.

Resource definitions

A resource is a named type (e.g. Document, Team) with two JSON maps:

FieldShapeMeaning
relations{ relationName: [allowedSubjectTypes] }Who may hold each relation on instances of this type. Use * to allow any subject type.
permissions{ actionName: [roles] }Which relations (or inherited actions) grant each action. Use * for public access; [] for none.

Example:

{
  "name": "Document",
  "relations": {
    "owner": ["User", "Team"],
    "editor": ["User", "Team"]
  },
  "permissions": {
    "read": ["editor", "owner", "owner->read"],
    "edit": ["editor", "owner"],
    "delete": ["owner"]
  },
  "version": 0
}

When a resource definition changes, Conduit schedules a re-index for all tuples involving that type. Schemas with conduitOptions.authorization.enabled automatically register a resource definition matching the schema name.

Relation tuples

Grant access by writing tuples — not by copying permission logic into app code.

OperationWhen
CreateShare a document, add a team member relation, assign ownership on create
ReadAudit who has access; debug Admin Panel
DeleteRevoke sharing; cleanup on resource delete

Validation on create:

  • subject, relation, and resource must be Type:id identifiers
  • The target resource's definition must declare the relation
  • The subject's type must appear in that relation's allowed list (unless *)

Single-tuple create builds indexes synchronously. Bulk create writes all tuples, then enqueues async index jobs per tuple.

Inheritance (->)

owner->read in a permission rule means: a subject holding owner on this resource inherits the read permission defined on the owner subject's type. For teams, Authentication registers Team with member, owner, and permissions like read, edit, delete — so Team:tid#owner@Document:doc lets team members read via owner->read.

Ownership on create

When scope=Team:tid is set on POST /database/{Schema}:

  1. Pre-check: user must have edit on the scope resource
  2. Tuple created: Team:tid#owner@{Schema}:{docId} — not a direct User owner tuple

When scope is omitted, the authenticated user becomes User:uid#owner@{Schema}:{docId}.

Built-in Team resource

Authentication registers Team with relations member, owner, readAll, editAll and permissions read, edit, delete, invite, manageMembers, etc. Use these action names — do not invent new ones without extending the definition.

Permission resolution

can(subject, action, resource) resolves in order:

  1. Self-access — subject equals resource → allowed
  2. Direct permission tuple — explicit subject#action@resource grant
  3. Index lookup — ObjectIndex + ActorIndex graph for relation-derived permissions

The Admin /permissions/evaluate endpoint returns the same decision plus the resolution path (assigned direct grant vs inherited index chain) for debugging.

Index reconstruction

Indexes can drift after bulk imports, manual DB edits, or rare worker failures. Operators can rebuild them:

POST ADMIN_BASE_URL/authorization/indexer/reconstruct
Body: { "soft": true | false }   // default false
ModeBehaviorWhen to use
soft: trueDoes not wipe existing index documents. Enqueues index-build jobs for every stored relation tuple.First attempt after suspected drift; safer, idempotent
soft: false (default)Deletes all ActorIndex and ObjectIndex documents, then enqueues jobs for every relation tuple.Confirmed corruption; only with explicit operator confirmation

The endpoint returns "ok" immediately; reconstruction runs in the background (batched, 1000 relations per resource type at a time). During hard rebuild, permission checks may temporarily fail until workers finish — schedule maintenance windows for soft: false.

Surfaces

SurfaceBasePurpose
Client APICLIENT_BASE_URL/authorization/...Signed-in user checks (/check, /role/:resource)
Admin APIADMIN_BASE_URL/authorization/...Resource/relation CRUD, bulk grants, indexer, evaluate
gRPCgrpcSdk.authorizationCustom modules: can, createRelation, createRelations, access-list views
MCPAdmin-backed toolsProvision resources and tuples at deploy time

Configure

  1. Enable authorization module in deployment (patch_config_authorization or Helm values)
  2. Set conduitOptions.authorization.enabled: true on schemas via MCP patch_database_schemas_id
  3. Define custom resources with POST /authorization/resources or MCP post_authorization_resources
  4. Grant tuples with POST /authorization/relations (single) or POST /authorization/relations/many (bulk)

For team-owned records, always pass scope on database creates and verify access with /authorization/check before destructive UI actions.

Client API

User bearer token required (authMiddleware). The server derives the subject from the authenticated user — callers never pass arbitrary subject on these routes.

MethodPathQuery / paramsResponse
GET/authorization/checkaction (required), resource (required), scope (optional){ allowed: boolean }
GET/authorization/role/:resourcescope (optional){ roles: string[] }

/check flow:

  1. If scope is set, verify the user may use that scope (can(User:uid, action, scope))
  2. Evaluate can(scope ?? User:uid, action, resource)

/role/:resource flow:

  1. If scope is set, verify the user has read on the scope
  2. Return relation names where subject = scope ?? User:uid and resource = :resource
Check with team scope
curl "http://localhost:3000/authorization/check?action=edit&resource=Document:DOC_ID&scope=Team:TEAM_ID" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Roles on a resource
curl "http://localhost:3000/authorization/role/Document:DOC_ID" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Never use Client API routes to define resources or create tuples for other users — that is Admin API / provisioning work.

Admin API

Operator credentials on ADMIN_BASE_URL/authorization/... (masterkey, admin JWT, or cdt_ token). Use for provisioning, bulk grants, and debugging — not from app runtime code.

Resources

MethodPathBody / queryNotes
POST/authorization/resources{ name, relations, permissions, version? }Create definition; returns { status, resourceDefinition }
GET/authorization/resourcessearch, skip, limit, sortPaginated list
GET/authorization/resources/:id—By MongoDB id or resource name
PATCH/authorization/resources/:id{ relations, permissions, version? }Triggers re-index for that type
DELETE/authorization/resources/:id—Deletes definition and related index data
Define a resource (Admin API)
curl -X POST http://localhost:3030/authorization/resources \
-H "masterkey: YOUR_MASTERKEY" \
-H "Content-Type: application/json" \
-d '{
  "name": "Document",
  "relations": { "owner": ["User", "Team"], "editor": ["User", "Team"] },
  "permissions": { "read": ["editor", "owner", "owner->read"], "edit": ["editor", "owner"] }
}'

Relations

MethodPathBody / queryNotes
POST/authorization/relations{ subject, relation, resource }Single tuple; indexes built synchronously; idempotent if tuple exists
POST/authorization/relations/many{ subject, relation, resources: string[] }Bulk grant same relation to many resources; async index jobs; prefer single route for one tuple; batch ≤100 resources when possible
GET/authorization/relationssearch, subjectType, resourceType, skip, limit, sortList / filter tuples
GET/authorization/relations/:id—Single tuple by id
DELETE/authorization/relations/:id—Removes tuple and index edges
Bulk grant editor on many documents
curl -X POST http://localhost:3030/authorization/relations/many \
-H "masterkey: YOUR_MASTERKEY" \
-H "Content-Type: application/json" \
-d '{
  "subject": "User:507f1f77bcf86cd799439011",
  "relation": "editor",
  "resources": ["Document:aaa", "Document:bbb", "Document:ccc"]
}'

Permissions (admin checks)

Unlike Client /check, these accept an explicit subject and use permission (not action) as the query param name.

MethodPathQueryResponse
GET/authorization/permissions/cansubject, permission, resource, scope?{ allowed: boolean }
GET/authorization/permissions/evaluatesubject, permission, resource, scope?{ allowed, assigned?, paths?, subjectIndex?, objectIndex? }

/permissions/can — same boolean result as gRPC Can. When scope is set, verifies the subject has some relation or permission on the scope before evaluating against the target resource.

/permissions/evaluate — debugging aid. Returns whether access was directly assigned (assigned: true) or resolved via the index graph, plus paths (human-readable tuple chain) and raw subjectIndex / objectIndex documents.

Admin permission check
curl "http://localhost:3030/authorization/permissions/can?subject=User:UID&permission=edit&resource=Document:DOC_ID" \
-H "masterkey: YOUR_MASTERKEY"
Trace permission resolution
curl "http://localhost:3030/authorization/permissions/evaluate?subject=Team:TID&permission=read&resource=Document:DOC_ID" \
-H "masterkey: YOUR_MASTERKEY"

Indexer

MethodPathBodyNotes
POST/authorization/indexer/reconstruct{ soft?: boolean }Rebuild ActorIndex/ObjectIndex; see Index reconstruction
Soft index rebuild (preferred)
curl -X POST http://localhost:3030/authorization/indexer/reconstruct \
-H "masterkey: YOUR_MASTERKEY" \
-H "Content-Type: application/json" \
-d '{"soft": true}'

Admin vs Client API

Client APIAdmin API
HostRouter (:3000)Core (:3030)
AuthUser bearer tokenmasterkey, admin JWT, or cdt_ token
SubjectImplicit (User:{authenticatedId})Explicit subject query param
Check paramactionpermission (same semantics)
Define resourcesNoPOST/PATCH /authorization/resources
Manage tuplesNoPOST/GET/DELETE /authorization/relations
Bulk tuplesNoPOST /authorization/relations/many
Debug pathsNoGET /authorization/permissions/evaluate
Rebuild indexNoPOST /authorization/indexer/reconstruct

Application UI gates actions with Client /check. CI, MCP, and operators use Admin routes. See Client vs Admin API.

MCP

Enable ?modules=authorization in your MCP server URL.

ToolPurpose
get_authorization_resourcesList resource definitions
post_authorization_resourcesDefine resources, relations, permissions
post_authorization_relationsCreate a single relationship tuple
get_authorization_permissions_canAdmin-side check (permission, subject, resource)

MCP wraps Admin API operations — use at deploy time to provision definitions and seed tuples, not from application runtime.

Next steps

  • ReBAC team scoping guide
  • Database module
  • Authentication & teams
  • Client vs Admin API

Authentication

Users, local/OAuth login, tokens, teams, 2FA, and sudo for sensitive operations.

Database

Schemas, CRUD, custom endpoints, indexes, query trees, and GitOps export.

On this page

Use casesCapabilitiesExample: Team-owned documents with scopeHow it worksConfigureClient APIAdmin APIResourcesRelationsPermissions (admin checks)IndexerAdmin vs Client APIMCP