Documentation Index
Fetch the complete documentation index at: https://docs.emergence.ai/llms.txt
Use this file to discover all available pages before exploring further.
Multi-Tenancy
CRAFT implements multi-tenancy at every layer of the stack. Each organization is fully isolated through a combination of identity separation (Keycloak realms), authorization scoping (OpenFGA relationship tuples), and data partitioning (org_id filtering on every query). This page describes the architecture that makes this work.Isolation Layers
The platform enforces tenant isolation through four complementary mechanisms:Identity Isolation
Each organization is a separate Keycloak realm. Users, groups, sessions, and identity provider configurations are completely isolated between realms. A user in
acme-corp cannot see or interact with users in globex.Authorization Isolation
OpenFGA relationship tuples are scoped to specific resources. Permission checks always include the resource ID, ensuring a user in one organization cannot access resources in another even if they somehow obtain a valid token.
Data Isolation
Every database query includes an
organization_id filter derived from the JWT token. This is enforced at the application layer — queries without org_id filters are treated as security vulnerabilities.Service Isolation
Each platform service (Governance, Assets, Utils) owns its own PostgreSQL database. There are no cross-service foreign keys, preventing accidental data leakage through join queries.
How org_id Flows Through the System
The organization ID is the foundation of tenant isolation. It flows through every request:Authentication
The user authenticates against their organization’s Keycloak realm. The JWT token’s
iss (issuer) claim contains the realm name, which becomes the org_id.Token Validation
The Governance service validates the JWT using the realm’s JWKS public keys. The
org_id is extracted from the verified issuer claim and stored in the Auth object. Users in the master realm (platform developers) have org_id = null.Request Processing
Every API endpoint receives the
Auth object via dependency injection. The org_id is used to:- Filter list queries to return only the organization’s resources
- Scope write operations to associate new resources with the correct organization
- Validate access via OpenFGA permission checks
Dual Authorization Pattern
The platform uses a dual authorization pattern that combines database-level filtering with authorization checks:- List Operations
- Get-by-ID Operations
List endpoints apply both database filtering and permission checks:This defense-in-depth approach means that even if a permission check has a bug, the database query will not return another organization’s data.
Database Architecture
Each service owns an independent PostgreSQL database with no cross-service foreign keys:organization_id column:
| Column | Type | Purpose |
|---|---|---|
organization_id | VARCHAR | Tenant partition key, always populated from JWT |
project_id | VARCHAR | Project scope within the organization |
created_at | TIMESTAMPTZ | Record creation timestamp (via TimestampMixin) |
updated_at | TIMESTAMPTZ | Last modification timestamp (via TimestampMixin) |
Keycloak Realm Structure
When an organization is created, the Governance service provisions a complete Keycloak realm:Service Account Cross-Tenant Access
Service accounts (background workers, automated processes) authenticate via themaster realm and specify the target organization via headers:
| Header | Purpose |
|---|---|
X-Org-Id | Target organization for the operation |
X-On-Behalf-Of | Original user ID for audit trails |
- Token issued by
masterrealm - Client ID starts with
svc- serviceAccountrole inrealm_access.roles
Service Startup and Dependencies
The multi-tenant infrastructure requires a specific startup order:make docker-run handles the startup order automatically via Docker Compose health checks. For manual local development, start make run-deps first, wait for readiness, then start Governance before Assets or Utils.Next Steps
Organizations
Learn how organizations are provisioned with Keycloak realms.
Authentication
Understand the multi-realm JWT authentication flow.
Authorization
Explore OpenFGA permission inheritance across tenants.
Projects
See how projects provide the second level of scoping within tenants.

