Authorization System
This document is the canonical reference for procedure authorization in Studio.
Scope
This system governs authorization for API procedures through procedure metadata and middleware evaluation.
Core implementation points:
- packages/api-procedure-core/metadata.ts
- packages/api-procedure-core/middleware.ts
- packages/api-trpc-context/context.ts
- packages/api-trpc-context/policy-registry.ts
- packages/providers-common/graph/modules.ts
- packages/auth-model/policy-expression.ts
Metadata Model
Procedure metadata uses two top-level sections:
- execution: runtime hints (for example, requiresTransaction)
- authorization: access-control contract
Authorization fields:
- requiresAuth?: boolean
- requiresAdmin?: boolean
- requiresRoles?: string[]
- requiresPermissions?: string[]
- requireAllRoles?: boolean
- requireAllPermissions?: boolean
- expression?: PolicyExpression
- policyRef?: string
- policyPreset?: string
- resolverInput?: Record<string, unknown>
- policyOverride?: PolicyExpression
- strict?: boolean
- allowSystemBypass?: boolean
- route?: { targetPreset: string }
Policy expression syntax is shared from auth-model and supports:
- all
- any
- not
- hasRole
- hasPermission
- principalType
- claimEquals
- claimIn
Resolution Order
When authorization metadata is present, middleware applies this sequence:
- Require authentication if any authorization requirement is present.
- Apply system bypass only when allowSystemBypass is true and principal type is system.
- Evaluate explicit admin/role/permission gates.
- Resolve policy expression from metadata resolver:
- policyRef map
- policyPreset map
- resolvePolicyExpression callback
- Apply policyOverride if provided (override takes precedence over resolved expression).
- Evaluate resulting expression and deny on false.
- If strict is true and no policy expression resolved, deny deterministically.
- Apply route targetPreset into request metadata.
- For admin target presets, elevate require and graph resolution through admin container when available.
Strict Error Contract
For unresolved strict policy metadata, middleware denies with deterministic FORBIDDEN errors:
- policyRef unresolved: Unresolved policy reference: {policyRef}
- policyPreset unresolved: Unresolved preset handle: {policyPreset}
For expression denials:
- policy expression false: Authorization policy denied access
- direct expression false: Authorization expression denied access
Authentication failure:
- Authentication required
Policy Handles and Presets
Policy references and presets are resolved from request metadata, assembled from:
- bootstrap policy registry from installed graph modules
- per-request resolver maps
- optional resolvePolicyExpression callback
Graph module codegen can emit policy handle constants. Predicate policy objects can also declare preset values used by resolver metadata.
Route Presets and Elevation
When authorization.route.targetPreset is set:
- targetPreset is propagated to requestMetadata.routing.targetPreset
- admin-like targets trigger best-effort elevation via admin container
- if elevation is unavailable, middleware falls back to existing context services
Current admin target detection:
- admin
- app.admin
- any target ending with .admin
Migration Guide
Legacy capability-style metadata is replaced by authorization and execution blocks.
Before:
- metadata.capabilities.requiresAdmin
- metadata.requiresTransaction mixed with auth semantics
After:
- metadata.authorization.requiresAdmin
- metadata.execution.requiresTransaction
Recommended migration order:
- Move transaction/runtime flags into execution.
- Move auth flags into authorization.
- Replace direct role/permission gates with policyRef or policyPreset where possible.
- Enable strict mode for procedures that require deterministic policy handle resolution.
Validation and Tests
Primary tests for authorization system behavior:
- integration-tests/api-procedure-core-authorization.workflow.test.ts
- packages/api-procedure-core/metadata.test.ts
- packages/api-trpc-context/policy-registry.test.ts
- packages/graph-module-compile/tests/policy-handles.test.ts
- packages/graph-module-model/tests/predicate-policy.test.ts
Integration suite command:
- pnpm test:integration:node
Notes
- This document describes current runtime behavior.
- Additional diagnostic event schemas can be layered without changing procedure metadata shape.