Match Project Role
The Match Project Role (matchProjectRole) access rule restricts API operations based on the user’s membership and role within a specific Project.
In collaborative platforms (such as task managers, code repositories, design boards, and team workspaces), organizations contain multiple projects, and users are assigned permissions on a per-project basis. A user might be an admin in Project Alpha, but only a viewer or non-member in Project Beta. Match Project Role provides fine-grained access control within these project containers.
1. Organizations vs. Projects: Hard vs. Soft Boundaries
Section titled “1. Organizations vs. Projects: Hard vs. Soft Boundaries”While both Match Organization Role and Match Project Role manage membership and role access, they serve fundamentally different architectural boundaries:
| Dimension | Organization (matchOrganizationRole) | Project (matchProjectRole) |
|---|---|---|
| Boundary Type | Hard Tenancy Boundary | Soft Collaboration Boundary |
| Data Isolation | Strict customer isolation. Cross-organization queries are prohibited. | Flexible team workspace. Supports cross-project aggregations. |
| Route Path Requirement | Must include the organization container in the URL (e.g. /{orgId}/...). | Can be nested (/projects/{projectId}/tasks) or aggregated (/tasks). |
| Cross-Resource Aggregation | ❌ Not permitted across organizations. | ✅ Permitted across all projects the user belongs to. |
The Soft Boundary Advantage: Cross-Project Aggregation
Section titled “The Soft Boundary Advantage: Cross-Project Aggregation”Because projects have soft boundaries, your API can expose two different styles of collection endpoints:
- Project-Scoped Endpoints (
GET /projects/:projectId/tasks): Retrieves tasks strictly belonging to the single project specified in:projectId. - Aggregated Endpoints (
GET /tasksorGET /orgs/:orgId/tasks): Allows a user to fetch all tasks assigned to them across every project they are a member of. The engine automatically filters the results:WHERE project_id IN (SELECT project_id FROM project_members WHERE user_id = :current_user_id)
2. How It Works
Section titled “2. How It Works”When a client makes a request to a project-scoped route:
- Project Context Resolution: The engine identifies the target project from the route path parameter (
:projectId) or via cross-project membership for aggregated routes. - Membership Verification: The engine checks whether the authenticated user is an active member of that project.
- Role Verification (Optional): If specific roles are configured, the engine checks whether the user holds one of the permitted project roles.
- Automatic Data Scoping: For collection queries (like listing tasks), the engine automatically scopes the database query to return only records belonging to matching projects.
| Property | Specification |
|---|---|
| Rule Type | matchProjectRole |
| Supported Strategies | All strategies (RBAC, OrganizationRBAC, EnterpriseRBAC) |
| Allowed Placement Levels | Exposed Entity Level, Action Level (Not allowed at global API Model Level) |
| Execution Phases | PRE_FETCH (create), FETCH (list, search), POST_FETCH (read, update, delete, link, unlink) |
3. Prerequisites in the Data Domain
Section titled “3. Prerequisites in the Data Domain”To use Match Project Role, your Data Domain must define the following semantic models:
Project: An entity representing the collaboration unit (project/workspace).User: An entity representing system users.ProjectMembers: A many-to-many (multiple: true) association connectingProjecttoUser.ProjectRole: An enum property attached to theProjectMembersassociation defining project roles (e.g.,['viewer', 'contributor', 'maintainer', 'admin']).ProjectResource: A one-to-many association fromProjectto each project-scoped sub-resource (e.g.Project.tasks,Project.milestones).
4. Configuration Options
Section titled “4. Configuration Options”When configuring Match Project Role in an Access Scenario, you define:
- Allowed Project Roles (
roles): A list of project roles permitted to execute this action (e.g.['maintainer', 'admin']).- Configured with specific roles: Access is granted only if the user is an active project member AND holds one of the specified roles in that project.
- Left empty / Unspecified: Any active member of the project is granted access, regardless of their specific project role.
5. How It Operates Across Route Types
Section titled “5. How It Operates Across Route Types”Listing Projects (GET /organizations/:orgId/projects or GET /projects)
Section titled “Listing Projects (GET /organizations/:orgId/projects or GET /projects)”When users list projects directly, the engine automatically injects a membership subquery:
WHERE id IN ( SELECT project_id FROM project_members WHERE user_id = :current_user_id)Users only see the projects they have explicitly joined or been invited to.
Nested Sub-Resource Routes (GET /projects/:projectId/tasks)
Section titled “Nested Sub-Resource Routes (GET /projects/:projectId/tasks)”When accessing resources nested under a single project:
- The engine extracts
:projectIdfrom the route. - It verifies that the caller is a member of that project with the required role.
- It automatically injects
WHERE project_id = :projectIdinto the database query, preventing cross-project data leakage.
Aggregated Cross-Project Routes (GET /tasks)
Section titled “Aggregated Cross-Project Routes (GET /tasks)”When an endpoint exposes tasks directly without a :projectId in the path, the engine automatically aggregates records across all projects where the user is an active member:
WHERE project_id IN ( SELECT project_id FROM project_members WHERE user_id = :current_user_id [AND role IN :allowed_roles])6. Recommended Modeling Patterns
Section titled “6. Recommended Modeling Patterns”Pattern 1: Standard Team Collaboration (Viewer Read / Contributor Write / Admin Manage)
Section titled “Pattern 1: Standard Team Collaboration (Viewer Read / Contributor Write / Admin Manage)”Configure progressive access tiers across project sub-resources (such as tasks or documents):
graph TD
subgraph "Task Entity (/projects/:projectId/tasks)"
List["GET (List)"] -->|Match Project Role: Any Member| M1["All Project Members"]
Read["GET /:id (Read)"] -->|Match Project Role: Any Member| M2["All Project Members"]
Create["POST (Create)"] -->|Match Project Role: contributor, maintainer, admin| W1["Contributors & Admins"]
Update["PATCH /:id (Update)"] -->|Match Project Role: contributor, maintainer, admin| W2["Contributors & Admins"]
Delete["DELETE /:id (Delete)"] -->|Match Project Role: admin| Adm["Project Admins Only"]
end
Pattern 2: Organization Admin Override + Project Member Access
Section titled “Pattern 2: Organization Admin Override + Project Member Access”In SaaS platforms, organization administrators often need full access to every project within their organization, even if they aren’t explicitly assigned to the project team:
Task.delete Scenarios:├── Scenario 1 (Organization Owner / Admin Override):│ └── Match Organization Role: ['admin', 'owner'] <- Org admins can delete tasks in any project└── Scenario 2 (Project Administrator): └── Match Project Role: ['admin'] <- Local project adminThe engine evaluates scenarios in order:
- If the caller is an Organization Admin, Scenario 1 matches and grants access immediately.
- Otherwise, the engine falls back to Scenario 2, checking if the caller is a Project Admin for that specific project.
7. HTTP Status Codes Summary
Section titled “7. HTTP Status Codes Summary”| Caller State | Endpoint Configuration | Resulting HTTP Status |
|---|---|---|
| Anonymous (No token) | Endpoint requires Match Project Role | 401 Unauthorized |
| Valid Member with Allowed Role | User is an active member with permitted project role | 200 OK / 201 Created |
| Valid Member with Insufficient Role | User is a member, but role is not in roles list (e.g. viewer trying to delete) | 403 Forbidden |
| Not a Member of Project | User belongs to the organization, but not to :projectId | 403 Forbidden |
| Invalid Project ID | Project :projectId does not exist in the database | 404 Not Found |
Next Steps
Section titled “Next Steps”- Match Organization Role: Enforce top-level tenancy boundaries.
- Match Resource Owner: Restrict operations to the direct author/creator of a record.
- Project Members Semantic Reference: Complete data modeling guide for project memberships.