> ## 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.

# Organizations

> Multi-tenant organization management with Keycloak realm isolation, default group provisioning, and OpenFGA permission bootstrapping.

# Organizations

Organizations are the top-level tenant boundary in CRAFT. Each organization maps 1:1 to a **Keycloak realm**, providing full identity isolation between tenants. When you create an organization, the platform provisions a complete identity and authorization environment automatically.

<Info>
  Every resource in the platform is scoped to an organization via `organization_id`. The org ID is never supplied by the client in request bodies -- it is always extracted from the JWT token's issuer claim, which identifies the Keycloak realm.
</Info>

## How Organizations Work

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#555555', 'fontFamily': 'sans-serif', 'edgeLabelBackground': '#ffffff'}}}%%
graph TB
    API["POST /organizations"]

    subgraph KC["Keycloak"]
        REALM["New Realm\n(org_id as realm name)"]
        GRP["Default Groups\norg-owners / org-admins / org-members"]
        MAP["Groups Mapper\n(claims in JWT)"]
    end

    subgraph OF["OpenFGA"]
        TUPLES["Permission Tuples\nowner / admin / member relations"]
    end

    DB[("Governance DB\norg record")]
    JWT["JWT tokens carry\norg_id from realm issuer"]

    API --> REALM
    REALM --> GRP --> MAP
    GRP --> TUPLES
    API --> DB
    MAP --> JWT

    classDef api fill:#E69F00,stroke:#555555,color:#000
    classDef kc fill:#56B4E9,stroke:#555555,color:#000
    classDef authz fill:#CC79A7,stroke:#555555,color:#000
    classDef db fill:#009E73,stroke:#555555,color:#000
    classDef token fill:#F0E442,stroke:#555555,color:#000
    class API api
    class REALM,GRP,MAP kc
    class TUPLES authz
    class DB db
    class JWT token
```

Creating an organization triggers a coordinated setup across three systems:

<Steps>
  <Step title="Keycloak Realm Creation">
    A new Keycloak realm is created using the organization ID as the realm name. This realm holds all users, groups, and identity provider configurations for the tenant.
  </Step>

  <Step title="Default Group Provisioning">
    Default groups are created within the realm to establish the role hierarchy:

    * `org-owners` -- Full organization control
    * `org-admins` -- Administrative access (user and project management)
    * `org-members` -- Standard membership with read access

    A groups mapper is configured so group memberships appear as claims in JWT tokens.
  </Step>

  <Step title="OpenFGA Permission Setup">
    Permission tuples are written to OpenFGA mapping each group to its corresponding relation:

    * `org-owners` -> `owner` relation on the organization
    * `org-admins` -> `admin` relation on the organization
    * `org-members` -> `member` relation on the organization

    This means any user added to `org-admins` in Keycloak automatically inherits `admin` permissions across the platform.
  </Step>

  <Step title="Database Record">
    An organization record is created in the Governance database with the org ID, name, description, and timestamps.
  </Step>
</Steps>

## Organization ID in JWT

The organization ID is derived from the Keycloak realm embedded in the token's `iss` (issuer) claim. When a user authenticates against a realm, the platform extracts the realm name as the `org_id`:

```text theme={null}
Token issuer: https://keycloak.example.com/realms/acme-corp
                                                  ^^^^^^^^^ org_id = "acme-corp"
```

This design means:

* The `org_id` is **cryptographically bound** to the token (it comes from the issuer verified by JWKS signature)
* Clients cannot forge or override the organization context
* Users in the `master` realm (platform developers) have `org_id = null`

## API Reference

The Organizations API is part of the Governance service (port 8000).

<AccordionGroup>
  <Accordion title="POST /governance/organizations" icon="plus">
    Creates a new organization with Keycloak realm, default groups, and OpenFGA permissions.

    **Access:** Platform developers only (master realm)

    ```json Request Body theme={null}
    {
      "id": "acme-corp",
      "name": "Acme Corporation",
      "description": "Production tenant for Acme Corp",
      "create_users": true
    }
    ```

    The `id` must follow Keycloak realm naming rules: alphanumeric characters, hyphens, and underscores only.

    When `create_users` is `true`, default users are created and added to the appropriate groups for immediate access.

    ```json Response (201 Created) theme={null}
    {
      "id": "acme-corp",
      "name": "Acme Corporation",
      "description": "Production tenant for Acme Corp",
      "created_at": "2026-04-01T12:00:00Z"
    }
    ```
  </Accordion>

  <Accordion title="GET /governance/organizations/{org_id}" icon="eye">
    Retrieves organization details by ID.

    **Access:** Users with `can_read` permission on the organization (owners, admins, or members).

    ```json Response (200 OK) theme={null}
    {
      "id": "acme-corp",
      "name": "Acme Corporation",
      "description": "Production tenant for Acme Corp",
      "created_at": "2026-04-01T12:00:00Z",
      "updated_at": "2026-04-02T08:30:00Z"
    }
    ```
  </Accordion>

  <Accordion title="DELETE /governance/organizations/{org_id}" icon="trash">
    Deletes an organization and cascades to all its projects. Removes OpenFGA permission tuples, the Keycloak realm (including all users and groups), and database records.

    **Access:** Platform developers only (master realm). Idempotent: returns 204 whether the organization was deleted or was already absent.
  </Accordion>
</AccordionGroup>

## Bootstrap Organization

During first startup, the Governance service automatically bootstraps a default organization:

<CodeGroup>
  ```yaml theme={null}
  bootstrap:
    organization:
      id: "emergence"
      name: "Emergence"
      description: "Emergence organization"
      create_admin_user: true
  ```
</CodeGroup>

When `create_admin_user` is `true` (the default), a user named `emergence` is created with:

* **Username:** `emergence`
* **Password:** `emergence` (change immediately in production)
* **Group:** `org-admins`
* **OpenFGA relation:** `admin` on the organization

<Warning>
  The bootstrap admin user is intended for development and initial setup. Always change the default password in production environments.
</Warning>

## Organization Permissions

Organizations define the following computed permissions in the OpenFGA schema:

| Permission            | Owner | Admin | Member |
| --------------------- | :---: | :---: | :----: |
| `can_read`            |  Yes  |  Yes  |   Yes  |
| `can_write`           |  Yes  |   --  |   --   |
| `can_delete`          |  Yes  |   --  |   --   |
| `can_manage_projects` |  Yes  |  Yes  |   --   |
| `can_manage_users`    |  Yes  |  Yes  |   --   |
| `can_read_secrets`    |  Yes  |  Yes  |   Yes  |
| `can_manage_secrets`  |  Yes  |  Yes  |   --   |
| `can_read_metadata`   |  Yes  |  Yes  |   Yes  |
| `can_manage_metadata` |  Yes  |  Yes  |   --   |

## Next Steps

<CardGroup cols={2}>
  <Card title="Projects" icon="folder" href="/platform/projects">
    Learn how projects scope resources within organizations.
  </Card>

  <Card title="Multi-Tenancy" icon="users" href="/platform/multi-tenancy">
    Understand the full tenant isolation architecture.
  </Card>

  <Card title="Authentication" icon="lock" href="/platform/authentication">
    See how Keycloak realms power the authentication flow.
  </Card>

  <Card title="Authorization" icon="shield-halved" href="/platform/authorization">
    Explore the OpenFGA permission model in depth.
  </Card>
</CardGroup>
