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

# CRAFT Security Overview

> CRAFT security architecture: Keycloak authentication, OpenFGA authorization, secrets management (ESO or Infisical), multi-tenant isolation, and OpenTelemetry observability.

# Security Overview

Security is embedded into every layer of CRAFT. The security model is built on four pillars: **authentication** (who you are), **authorization** (what you can do), **secrets management** (protecting credentials), and **multi-tenant isolation** (keeping organizations separate).

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#555555', 'fontFamily': 'sans-serif', 'edgeLabelBackground': '#ffffff'}}}%%
flowchart LR
    EXT["External Request"]
    TLS["TLS / Gateway"]
    AUTHN["Keycloak AuthN<br/>JWT Validation"]
    AUTHZ["OpenFGA AuthZ<br/>Permission Check"]
    HANDLER["Request Handler"]
    DB["PostgreSQL<br/>org_id-scoped queries"]
    DATA["Data"]
    EXT --> TLS --> AUTHN --> AUTHZ --> HANDLER --> DB --> DATA
    style EXT fill:#CC79A7,stroke:#555555,color:#000
    style TLS fill:#0072B2,stroke:#555555,color:#fff
    style AUTHN fill:#D55E00,stroke:#555555,color:#000
    style AUTHZ fill:#D55E00,stroke:#555555,color:#000
    style HANDLER fill:#E69F00,stroke:#555555,color:#000
    style DB fill:#009E73,stroke:#555555,color:#000
    style DATA fill:#009E73,stroke:#555555,color:#000
```

## Security Architecture

<Tabs>
  <Tab title="Authentication (AuthN)">
    **Technology:** Keycloak with multi-realm JWT and OIDC/PKCE

    Keycloak provides the identity layer for the entire platform. Each organization is a separate Keycloak **realm**, providing complete identity isolation between tenants.

    | Feature                | Details                                                       |
    | ---------------------- | ------------------------------------------------------------- |
    | **Protocol**           | OpenID Connect (OIDC) with PKCE for browser clients           |
    | **Token format**       | JWT containing `org_id` (from realm), groups, and user claims |
    | **Multi-realm**        | Each organization = one Keycloak realm (realm ID = org ID)    |
    | **SSO support**        | Enterprise SSO via SAML or OIDC identity provider federation  |
    | **Session management** | Token refresh, revocation, and session timeout policies       |

    <Note>
      The `project_id` is never stored in the JWT. It is passed via the `X-Project-ID` HTTP header or as a path parameter, allowing users to switch project context without re-authenticating.
    </Note>
  </Tab>

  <Tab title="Authorization (AuthZ)">
    **Technology:** OpenFGA with Relationship-Based Access Control (ReBAC)

    OpenFGA provides fine-grained authorization based on relationships between entities rather than static role assignments. This enables permission inheritance and computed permissions.

    ### Roles

    | Role        | Scope                  | Description                                          |
    | ----------- | ---------------------- | ---------------------------------------------------- |
    | `owner`     | Organization           | Full control over the organization and all resources |
    | `admin`     | Organization / Project | Administrative access to manage users and settings   |
    | `member`    | Project                | Standard access to project resources                 |
    | `developer` | Project                | Create and modify agents, connections, and workflows |
    | `operator`  | Project                | Deploy, schedule, and monitor resources              |
    | `viewer`    | Project                | Read-only access to all resources                    |

    ### Computed Permissions

    Permissions are **computed at query time** from role relationships, not statically assigned:

    | Permission           | Derived From                      |
    | -------------------- | --------------------------------- |
    | `can_read`           | All roles (viewer and above)      |
    | `can_write`          | member, developer, admin, owner   |
    | `can_delete`         | admin, owner                      |
    | `can_execute`        | developer, operator, admin, owner |
    | `can_manage_secrets` | admin, owner                      |

    ### Permission Inheritance

    Permissions flow downward through the resource hierarchy:

    ```mermaid theme={null}
    %%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#555555', 'fontFamily': 'sans-serif', 'edgeLabelBackground': '#ffffff'}}}%%
    flowchart LR
    Org["Organization"] --> Proj["Project"] --> Res["Resource<br/>(Agent, Data Connection, etc.)"]

    classDef level fill:#0072B2,stroke:#555555,color:#fff
    class Org,Proj,Res level
    ```

    A user who is an `admin` of an organization automatically has admin-level computed permissions on all projects and resources within it.

    <Warning>
      Solutions must never implement their own permission checks. All authorization is delegated to the Governance service via the `require_permission()` decorator or SDK calls. If Governance is unavailable, all downstream services return 403.
    </Warning>
  </Tab>

  <Tab title="Secrets Management">
    The platform supports two secrets backends, choose based on your deployment environment. See [Secrets Management](/security/secrets-management) for a full comparison.

    | Layer                     | Options                            | Scope                                    | Examples                                               |
    | ------------------------- | ---------------------------------- | ---------------------------------------- | ------------------------------------------------------ |
    | **Application (cloud)**   | ESO + GCP Secret Manager           | Platform services, synced to K8s Secrets | Data connection credentials, API keys                  |
    | **Application (on-prem)** | Infisical                          | Platform services                        | Data connection credentials, API keys, encryption keys |
    | **Infrastructure**        | GCP Secret Manager (via Terraform) | Terraform-managed resources              | Database passwords, service account keys               |

    **Key properties:**

    * Secrets are never exposed in API responses
    * Per-organization namespace isolation (Infisical) or IAM-scoped access (GCP SM)
    * Credentials are injected at runtime only when needed
    * Auto-rotation supported: ESO + Stakater Reloader (cloud), Infisical rotation policies (self-hosted)

    <Tip>
      Never commit secrets or credentials to configuration files or source code. Use the platform Secrets API for application secrets and GCP Secret Manager or your cloud provider's equivalent for infrastructure secrets.
    </Tip>
  </Tab>

  <Tab title="Multi-Tenant Isolation">
    Multi-tenancy provides complete isolation between organizations at every layer of the stack:

    | Layer              | Isolation Mechanism                                                      |
    | ------------------ | ------------------------------------------------------------------------ |
    | **Authentication** | Separate Keycloak realm per organization                                 |
    | **Authorization**  | Per-organization OpenFGA relationship tuples                             |
    | **Data**           | All database queries filtered by `org_id` from JWT                       |
    | **Secrets**        | Per-organization isolation (Infisical namespaces or GCP SM IAM bindings) |
    | **Storage**        | Tenant-scoped object storage paths                                       |

    ### Security Invariants

    These rules are enforced across all platform services:

    1. The `org_id` **always** comes from the authenticated JWT token, never from request parameters
    2. **List operations** filter by both `org_id` (from JWT) AND `project_id` (from header) at the database level
    3. **Write operations** stamp the `org_id` from the JWT onto new resources
    4. **No cross-service foreign keys** exist between databases
    5. A missing org\_id filter on a list query is treated as a **security vulnerability**

    <Info>
      Platform services run entirely within your infrastructure. External data egress depends on the integrations and model providers you configure -- for example, LLM calls via LiteLLM are sent to the provider you choose (Gemini, GPT, Claude, or a self-hosted model). You control what data leaves your environment.
    </Info>
  </Tab>
</Tabs>

## Dual Authorization Pattern

The platform enforces authorization through a dual pattern that combines database filtering with OpenFGA checks:

| Operation Type           | Database Filter                        | OpenFGA Check                                     |
| ------------------------ | -------------------------------------- | ------------------------------------------------- |
| **List operations**      | Filter by `auth.org_id` + `project_id` | `require_permission()` for project access         |
| **Get-by-ID operations** | Not needed                             | `require_permission()` handles authorization      |
| **Create operations**    | Stamp `auth.org_id` on resource        | `require_permission()` for project write access   |
| **Delete operations**    | Not needed                             | `require_permission()` for resource delete access |

<Note>
  This dual pattern prevents two classes of vulnerabilities: (1) listing resources across organizations (database filter) and (2) accessing specific resources without permission (OpenFGA check).
</Note>

## Authentication Flow

<Steps>
  <Step title="User Login">
    The user authenticates via OIDC/PKCE flow against their organization's Keycloak realm. The browser receives a JWT token containing `org_id` and group memberships.
  </Step>

  <Step title="API Request">
    The client includes the JWT in the `Authorization: Bearer <token>` header and the active project in the `X-Project-ID` header.
  </Step>

  <Step title="Token Validation">
    The Governance service validates the JWT signature, expiry, and issuer. It extracts `org_id` from the realm claim.
  </Step>

  <Step title="Permission Check">
    OpenFGA evaluates the user's relationship to the requested resource. Computed permissions are resolved at query time based on role inheritance.
  </Step>

  <Step title="Request Processing">
    If authorized, the request proceeds with the authenticated context. Database queries are scoped to `org_id` and `project_id`.
  </Step>
</Steps>

## Network Security

| Control                | Implementation                                                                                                 |
| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
| **SSRF protection**    | Webhook and data connection endpoints validate target URLs against allowlists                                  |
| **HMAC signatures**    | Webhook payloads will be signed with HMAC for integrity verification (planned -- not yet released)             |
| **TLS**                | All inter-service communication uses TLS in production                                                         |
| **Private networking** | Cloud deployments use private VPC networking; self-managed clusters should use equivalent network segmentation |
| **Firewall rules**     | Terraform-managed ingress/egress rules                                                                         |

## Observability and Audit

The platform provides comprehensive observability for security monitoring:

| Component      | Technology            | Purpose                                         |
| -------------- | --------------------- | ----------------------------------------------- |
| **Traces**     | OpenTelemetry + Tempo | Distributed request tracing across services     |
| **Metrics**    | OpenTelemetry + Mimir | Service health, latency, and throughput metrics |
| **Logs**       | OpenTelemetry + Loki  | Structured logging with correlation IDs         |
| **Dashboards** | Grafana               | Visualization and alerting for all telemetry    |

<Info>
  All telemetry is exported via the **OTLP** (OpenTelemetry Protocol) standard -- a vendor-neutral protocol compatible with any OTLP-capable backend. You choose your observability stack; the Grafana LGTM bundle (Loki, Grafana, Tempo, Mimir) is included by default but never required.
</Info>

## Security Best Practices

<AccordionGroup>
  <Accordion title="For Platform Operators" icon="gear">
    * Enable TLS for all ingress and inter-service communication
    * Configure Keycloak password policies and brute-force detection
    * Set up regular secret rotation (Infisical rotation policies or ESO + Stakater Reloader)
    * Monitor OpenFGA permission check latency and error rates
    * Review audit logs for unauthorized access attempts
    * Use private networking for database and cache connections
  </Accordion>

  <Accordion title="For Solution Developers" icon="code">
    * Never implement permission checks directly -- always use `require_permission()`
    * Always use `auth.org_id` from JWT, never from request parameters
    * Never store secrets in configuration files or environment variables in source control
    * Use the Governance SDK for all authentication and authorization operations
    * Validate webhook signatures before processing events (when webhook feature is released)
    * Use parameterized queries to prevent SQL injection (enforced by SQLAlchemy ORM)
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/security/authentication">
    Deep dive into Keycloak configuration and OIDC flows.
  </Card>

  <Card title="Data Classification" icon="tags" href="/security/data-classification">
    Understand data classification and handling policies.
  </Card>

  <Card title="Network Security" icon="shield" href="/security/network-security">
    Learn about network-level security controls and firewall configuration.
  </Card>

  <Card title="RBAC Configuration" icon="lock" href="/guides/rbac-configuration">
    Step-by-step guide for configuring roles and permissions.
  </Card>
</CardGroup>
