title: Signing Policy Reference description: How Guardrails evaluates permissions, roles, and custom resolvers.
tags:
- approvals
- signing
- permissions
- roles
Signing Policy Reference
Guardrails relies on a signing policy to decide whether an authenticated initiator can approve a step. The evaluation order is predictable so you can design flows with confidence.
Permission checks
- Permissions come first. The signer rules list
permissionsplus apermissions_mode(allorany). - Guardrails looks for permission helpers on the user:
- If the user exposes Spatie-style methods (
hasPermissionTo), those are used. - Otherwise, Guardrails inspects token abilities (e.g.
currentAccessToken()->abilities).
- If the user exposes Spatie-style methods (
- For
all, the initiator must satisfy every listed permission. Forany, a single match is enough.
Permissions work out of the box—no extra configuration required.
Role checks
Roles are optional. If you include them in a step:
- With Spatie roles available (
hasRole), Guardrails uses the package directly. - Without Spatie, Guardrails falls back to a resolver:
- By default, it inspects common patterns (an Eloquent relationship or
rolesattribute). - You can take full control via the
guardrails.signing.resolve_roles_usingconfig key. Set it to a closure that receives the authenticated user and returns an array of role identifiers.
- By default, it inspects common patterns (an Eloquent relationship or
// config/guardrails.php
'signing' => [
'resolve_roles_using' => static function ($user) {
return $user->teams->pluck('slug')->all();
},
],
Initiator overlap
Flows can demand overlap with the initiator using same_permission_as_initiator or same_role_as_initiator. Guardrails compares the initiator’s permissions or roles against the signer’s set after running the checks above. If no overlap exists, the signer is rejected.
Tokens and abilities
When using Laravel Sanctum or similar token guards, Guardrails will treat token abilities as permissions. Make sure the token includes the required ability names.
Guardrails uses the configured auth guard (default:
auth.defaults.guard). You can change it viaGUARDRAILS_AUTH_GUARDorconfig/guardrails.php. The helperOVAC\Guardrails\Support\AuthexposesguardName(),guard(), anduser()if you need to mirror Guardrails’ guard selection in custom code.
Guard selection & per-step overrides
Flow::make()seeds the guard fromconfig('guardrails.auth.guard'), falling back to your app’s default guard. This keeps flows aligned with how you authenticate reviewers.- You can override the guard for a specific step by chaining
guard('other-guard')before callingsignedBy(). See the Controller Interception Guide for a full example.
Troubleshooting
- Unexpected denials? Log the signer meta to confirm the permissions/roles being evaluated.
- Custom guards? Double-check the resolver returns plain strings; nested arrays or objects will be ignored.
- Mixed ecosystems? You can use both permissions and roles in the same step; Guardrails requires that both pass according to their respective modes.
Related configuration
guardrails.permissions.viewandguardrails.permissions.signgate the built-in API routes.guardrails.signing.resolve_roles_usingsupplies a custom resolver.
For examples of defining signer rules, see the Model Guarding Guide and Controller Interception Guide.