← ClaudeAtlas

project-authzlisted

Use when adding, changing, or reviewing access control: Voters, #[IsGranted], security gates, Mercure topic authorization, or account enumeration policy.
ubermuda/loupe · ★ 2 · AI & Automation · score 65
Install: claude install-skill ubermuda/loupe
# Authorization ## Voters Invoke the `symfony-authorization` skill before you write or change a Voter, an `#[IsGranted]` attribute, or an `is_granted()` call. It documents the generic layer: - voter class shape - dotted attribute naming - `#[IsGranted]` placement and `subject:` resolution - voter scoping - read-vs-write separation - Twig `is_granted(constant(...))` - the rename checklist The rules below are project policy on top of that layer. Never use `IS_AUTHENTICATED_FULLY` in `#[IsGranted]`. Every access check names a Voter constant and a subject. `IS_AUTHENTICATED_FULLY` bypasses the Voter layer and cannot express resource-level ownership. ```php // ✗ — grants access to any authenticated user regardless of ownership #[IsGranted('IS_AUTHENTICATED_FULLY')] // ✓ — delegates to the Voter which checks ownership #[IsGranted(ProjectVoter::WORKSPACE_MANAGE, subject: 'workspace')] ``` Put `#[IsGranted]` on the class. gamache's `controller.isGrantedNotClassLevel` rule fails a method-level `#[IsGranted]` on a single-action controller. `denyAccessUnlessGranted()` inside `__invoke()` is forbidden. An imperative `denyAccessUnlessGranted()` call shows that you have not found the right (subject, permission) pair. Resolve both: - Subject: the most specific entity the route already resolves. `__invoke(Comment $comment)` gives the subject `'comment'`. The subject need not be the entity the policy checks, because the voter walks up to `comment.version.document.owner`. "The docume