Payload Access Control Blueprint
Function-based access control with collection-level, field-level, and document-level permissions supporting boolean and WHERE clause results
| Feature | payload-access-control |
| Category | Access Control |
| Version | 1.0.0 |
| Tags | cms, access-control, permissions, rbac, field-level, document-level, where-clause, payload |
| YAML Source | View on GitHub |
| JSON API | payload-access-control.json |
Actors
| ID | Name | Type | Description |
|---|---|---|---|
authenticated_user | Authenticated User | human | Any user authenticated via JWT, API key, or custom strategy |
anonymous_user | Anonymous User | human | Unauthenticated visitor — access functions receive null user |
access_engine | Access Engine | system | Evaluates access functions and merges results with database queries |
Fields
| Name | Type | Required | Label | Description |
|---|---|---|---|---|
access_result | json | Yes | Access Result | |
permission_object | json | Yes | Permission Object |
Rules
- access:
- collection_level_operations: create, read, update, delete, admin, readVersions, unlock
- global_level_operations: read, update, readVersions
- field_level_operations: create, read, update
- access_function_signature:
- input: {req, id?, data?}
-
output: boolean Where clause Promise<boolean Where>
- where_clause_merging:
- description: When access returns a Where clause, it is AND-merged with the user query
- enables_row_level_security: true
- default_access_function: Boolean(req.user)
- override_access:
- flag: overrideAccess: true
- description: Bypasses all access checks — used by admin operations, scheduled tasks, webhooks
- disable_errors:
- flag: disableErrors: true
- description: Returns empty results instead of throwing Forbidden on access denial
- security:
- field_level_access_context: doc (full document), siblingData (parent object), blockData (nearest block parent), req (request with user), id (document ID)
- block_reference_permissions: true
Outcomes
Access_denied (Priority: 1) — Error: ACCESS_FORBIDDEN
Given:
- access function returns false
- disableErrors is not set
Result: 403 Forbidden error thrown
Access_denied_silent (Priority: 2)
Given:
- access function returns false
- disableErrors is set to true
Result: Empty result set returned (no error thrown)
Field_access_denied (Priority: 5)
Given:
- field-level access function returns false for a specific field
Then:
- field excluded from response (read access denied)
- field value ignored in input (create/update access denied)
Result: Field silently excluded — no error, field just absent from response
Access_granted_boolean (Priority: 10)
Given:
- access function returns true
Result: Operation proceeds with no additional query constraints
Access_granted_where (Priority: 10)
Given:
- access function returns a Where clause object
Then:
- Where clause merged with user query via combineQueries()
- database query only returns documents matching both user query AND access filter
Result: Operation proceeds with row-level filtering applied
Doc_access_check (Priority: 10)
Given:
- user requests permission check via /access/:id endpoint
Then:
- all collection-level access functions evaluated
- all field-level access functions evaluated
Result: Complete permission object returned with boolean flags for each operation and each field
Admin_panel_access (Priority: 10)
Given:
- user attempts to access admin panel for a collection
Then:
- admin access function evaluated: ({req}) => boolean
Result: User granted or denied access to this collection in the admin UI
Errors
| Code | Status | Message | Retry |
|---|---|---|---|
ACCESS_FORBIDDEN | 403 | You are not allowed to perform this action | No |
ACCESS_UNAUTHORIZED | 401 | You must be logged in to perform this action | No |
Events
| Event | Description | Payload |
|---|---|---|
access.denied | Emitted when access is denied — useful for audit logging | user_id, collection_slug, operation, timestamp |
access.evaluated | Emitted after access evaluation completes | user_id, collection_slug, operation, result_type |
Related Blueprints
| Feature | Relationship | Reason |
|---|---|---|
| payload-auth | required | Access control depends on authenticated user identity from auth system |
| payload-collections | required | Access functions are configured per collection |
| payload-globals | required | Globals have their own access control configuration |
AGI Readiness
Goals
Reliable Payload Access Control
Function-based access control with collection-level, field-level, and document-level permissions supporting boolean and WHERE clause results
Success Metrics:
| Metric | Target | Measurement |
|---|---|---|
| unauthorized_access_rate | 0% | Failed authorization attempts that succeed |
| response_time_p95 | < 500ms | 95th percentile response time |
Constraints:
- security (non-negotiable): Follow OWASP security recommendations
Autonomy
Level: supervised
Human Checkpoints:
- before making irreversible changes
Escalation Triggers:
error_rate > 5consecutive_failures > 3
Verification
Invariants:
- error messages never expose internal system details
Tradeoffs
| Prefer | Over | Reason |
|---|---|---|
| security | usability | access control must enforce least-privilege principle |
Coordination
Protocol: orchestrated
Consumes:
| Capability | From | Fallback |
|---|---|---|
payload_auth | payload-auth | fail |
payload_collections | payload-collections | fail |
payload_globals | payload-globals | fail |
Safety
| Action | Permission | Cooldown | Max Auto |
|---|---|---|---|
| access_granted_boolean | autonomous | - | - |
| access_granted_where | autonomous | - | - |
| access_denied | autonomous | - | - |
| access_denied_silent | autonomous | - | - |
| field_access_denied | autonomous | - | - |
| doc_access_check | autonomous | - | - |
| admin_panel_access | autonomous | - | - |