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

# Projects

> Logical resource groupings within organizations, providing project-level scoping, permission inheritance, and the X-Project-ID header convention.

# Projects

Projects are the second level of resource scoping in CRAFT. Every resource (agents, data connections, artifacts, files) belongs to a project, and every project belongs to an organization. Projects provide:

* **Logical separation** of resources within a single organization
* **Permission inheritance** from the parent organization via OpenFGA
* **Access control** through project-level roles (`owner`, `admin`, `developer`, `operator`, `viewer`)

<Info>
  The `project_id` is never embedded in the JWT token. It is supplied via the `X-Project-ID` request header, allowing users to switch project context without re-authenticating.
</Info>

## How Projects Work

When a project is created, the platform performs several coordinated actions:

<Steps>
  <Step title="Database Record">
    A project record is created in the Governance database, linked to the parent organization by `organization_id`.
  </Step>

  <Step title="OpenFGA Parent Link">
    A relationship tuple is written to OpenFGA linking the project to its organization: `project:{project_id}#organization@organization:{org_id}`. This establishes permission inheritance -- organization-level roles automatically grant access to the project.
  </Step>

  <Step title="Default Group Permissions">
    Default project groups receive appropriate permissions:

    * `project-owners` -> `owner` relation
    * `project-admins` -> `admin` relation
    * `project-developers` -> `developer` relation
    * `project-operators` -> `operator` relation
    * `project-viewers` -> `viewer` relation
  </Step>
</Steps>

## The X-Project-ID Header

All resource APIs (Assets, Utils) require the `X-Project-ID` header to scope requests:

```bash theme={null}
# List data connections in a specific project
curl -H "Authorization: Bearer $TOKEN" \
     -H "X-Project-ID: my-analytics-project" \
     https://api.example.com/assets/data
```

This design choice has important implications:

<AccordionGroup>
  <Accordion title="Why not put project_id in the JWT?">
    Users often work across multiple projects in the same session. Embedding `project_id` in the JWT would require re-authentication to switch projects. The header-based approach allows instant project switching with the same token.
  </Accordion>

  <Accordion title="How is the header validated?">
    The `require_permission()` dependency reads the `X-Project-ID` header and checks OpenFGA to verify the authenticated user has the required permission on that project. If the user lacks access, a 403 is returned.
  </Accordion>

  <Accordion title="What about list operations?">
    List queries always filter by both `auth.org_id` (from JWT) and `project_id` (from header). This dual filter ensures data isolation even if a permission check has a gap.
  </Accordion>
</AccordionGroup>

## API Reference

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

<AccordionGroup>
  <Accordion title="GET /governance/projects" icon="list">
    Lists all projects in the user's organization with pagination. Results are filtered to only include projects the user has `can_read` permission on.

    **Query Parameters:**

    * `page` (default: 1) -- Page number
    * `limit` (default: 20, max: 100) -- Items per page

    ```json Response (200 OK) theme={null}
    {
      "data": [
        {
          "id": "analytics-prod",
          "name": "Analytics Production",
          "description": "Production analytics project",
          "organization_id": "acme-corp",
          "created_at": "2026-04-01T12:00:00Z"
        }
      ],
      "pagination": {
        "page": 1,
        "limit": 20,
        "total": 1,
        "total_pages": 1
      }
    }
    ```
  </Accordion>

  <Accordion title="POST /governance/projects" icon="plus">
    Creates a new project within the user's organization (determined from JWT). The project is automatically linked to the organization and default groups receive permissions.

    **Access:** Users with `can_manage_projects` on the organization (owners or admins).

    ```json Request Body theme={null}
    {
      "name": "Analytics Production",
      "description": "Production analytics project",
      "external_id": "analytics-prod",
      "create_users": false
    }
    ```

    If `external_id` is omitted, a UUID is generated for the project ID.

    ```json Response (201 Created) theme={null}
    {
      "id": "analytics-prod",
      "external_id": "analytics-prod",
      "name": "Analytics Production",
      "organization_id": "acme-corp",
      "created_at": "2026-04-01T12:00:00Z"
    }
    ```
  </Accordion>

  <Accordion title="GET /governance/projects/{project_id}" icon="eye">
    Retrieves detailed information about a specific project.

    **Access:** Users with `can_read` permission on the project.

    ```json Response (200 OK) theme={null}
    {
      "name": "Analytics Production",
      "description": "Production analytics project",
      "organization_id": "acme-corp",
      "created_at": "2026-04-01T12:00:00Z",
      "updated_at": "2026-04-02T08:30:00Z"
    }
    ```
  </Accordion>
</AccordionGroup>

## Project Permissions

Projects define a richer role set than organizations, supporting fine-grained access control for resource management:

| Permission             | Owner | Admin | Developer | Operator | Viewer |
| ---------------------- | :---: | :---: | :-------: | :------: | :----: |
| `can_read`             |  Yes  |  Yes  |    Yes    |    Yes   |   Yes  |
| `can_write`            |  Yes  |  Yes  |    Yes    |    Yes   |   --   |
| `can_delete`           |  Yes  |  Yes  |     --    |    --    |   --   |
| `can_create_resources` |  Yes  |  Yes  |    Yes    |    --    |   --   |
| `can_read_secrets`     |  Yes  |  Yes  |    Yes    |    Yes   |   --   |
| `can_manage_secrets`   |  Yes  |  Yes  |    Yes    |    --    |   --   |
| `can_read_metadata`    |  Yes  |  Yes  |    Yes    |    Yes   |   --   |
| `can_manage_metadata`  |  Yes  |  Yes  |    Yes    |    --    |   --   |

<Tip>
  Project permissions also inherit from the parent organization. An organization `owner` or `admin` automatically has `can_read`, `can_write`, `can_delete`, and `can_create_resources` on all projects in their organization, even without explicit project-level role assignment.
</Tip>

## Service Accounts

Projects support **service relations** for background workers and automated processes:

| Service Relation   | Grants                                                                                                        |
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
| `service_reader`   | `can_read`, `can_read_secrets`, `can_read_metadata`                                                           |
| `service_writer`   | `can_read`, `can_write`, `can_read_secrets`, `can_manage_secrets`, `can_read_metadata`, `can_manage_metadata` |
| `service_deleter`  | `can_read`, `can_delete`                                                                                      |
| `service_executor` | `can_execute` (for MCP servers, API servers, data connections)                                                |

Service accounts authenticate via the master realm with a `svc-` client ID prefix and are granted contextual tuples scoped to specific projects. See [Service Accounts](/platform/service-accounts) for setup instructions and token management.

## Next Steps

<CardGroup cols={2}>
  <Card title="Organizations" icon="building" href="/platform/organizations">
    Understand how organizations provide the top-level tenant boundary.
  </Card>

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

  <Card title="Data Connections" icon="database" href="/platform/data-connections">
    Manage database and storage connections within projects.
  </Card>

  <Card title="Agent Registry" icon="robot" href="/platform/agents">
    Register and discover agents scoped to projects.
  </Card>
</CardGroup>
