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)
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.How Projects Work
When a project is created, the platform performs several coordinated actions:1
Database Record
A project record is created in the Governance database, linked to the parent organization by
organization_id.2
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.3
Default Group Permissions
Default project groups receive appropriate permissions:
project-owners->ownerrelationproject-admins->adminrelationproject-developers->developerrelationproject-operators->operatorrelationproject-viewers->viewerrelation
The X-Project-ID Header
All resource APIs (Assets, Utils) require theX-Project-ID header to scope requests:
Why not put project_id in the JWT?
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.How is the header validated?
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.What about list operations?
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.API Reference
The Projects API is part of the Governance service (port 8000).GET /governance/projects
GET /governance/projects
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 numberlimit(default: 20, max: 100) — Items per page
Response (200 OK)
POST /governance/projects
POST /governance/projects
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 If
can_manage_projects on the organization (owners or admins).Request Body
external_id is omitted, a UUID is generated for the project ID.Response (201 Created)
GET /governance/projects/{project_id}
GET /governance/projects/{project_id}
Retrieves detailed information about a specific project.Access: Users with
can_read permission on the project.Response (200 OK)
Project Permissions
Projects define a richer role set than organizations, supporting fine-grained access control for resource management:Service Accounts
Projects support service relations for background workers and automated processes:
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 for setup instructions and token management.
Next Steps
Organizations
Understand how organizations provide the top-level tenant boundary.
Authorization
Explore the OpenFGA permission model and permission inheritance.
Data Connections
Manage database and storage connections within projects.
Agent Registry
Register and discover agents scoped to projects.

