Authorization answers one question: can this security context perform this permission against this optional resource?
Authorizer checks matching policies first and falls back to permissions already present in the context.
$result = $authorizer->decide($context, 'posts.update', $post);The result is an AuthorizationResult.
AuthorizationResult wraps an AccessDecision.
Allowmeans the action is granted.Denymeans the action is rejected.Abstainmeans a policy intentionally did not decide.
The authorizer treats final abstention as denial unless the context permission fallback grants the permission.
When multiple policies support a permission, a denial wins immediately. This keeps explicit safety decisions from being overwritten by a later grant.
$authorizer->can($context, 'billing.view');
$authorizer->cannot($context, 'billing.delete');
$authorizer->authorize($context, 'billing.update');authorize() returns the granted result or throws AccessDeniedException.
Results can carry context:
AuthorizationResult::deny(
reason: 'Only owners can delete this post.',
permission: 'posts.delete',
resource: $post,
policy: 'post-owner',
);Use result objects when callers need reason text, policy names, or resource-aware reporting.