···844844});
845845```
846846847847+## Scope Authorization
848848+849849+The package provides Laravel-native authorization features for checking ATP OAuth scopes, similar to Laravel's Gate/Policy system.
850850+851851+### Setup
852852+853853+Have your User model implement the `HasAtpSession` interface:
854854+855855+```php
856856+use SocialDept\AtpClient\Contracts\HasAtpSession;
857857+858858+class User extends Authenticatable implements HasAtpSession
859859+{
860860+ public function getAtpDid(): ?string
861861+ {
862862+ return $this->atp_did; // or however you store the DID
863863+ }
864864+}
865865+```
866866+867867+### Route Middleware
868868+869869+Protect routes by requiring specific scopes. Uses AND logic (all listed scopes required):
870870+871871+```php
872872+use Illuminate\Support\Facades\Route;
873873+874874+// Requires transition:generic scope
875875+Route::post('/posts', [PostController::class, 'store'])
876876+ ->middleware('atp.scope:transition:generic');
877877+878878+// Requires BOTH scopes
879879+Route::post('/dm', [MessageController::class, 'store'])
880880+ ->middleware('atp.scope:transition:generic,transition:chat.bsky');
881881+```
882882+883883+### AtpScope Facade
884884+885885+Use the `AtpScope` facade for programmatic scope checks:
886886+887887+```php
888888+use SocialDept\AtpClient\Facades\AtpScope;
889889+890890+// Check if user has a scope
891891+if (AtpScope::can('transition:generic')) {
892892+ // ...
893893+}
894894+895895+// Check if user has any of the scopes
896896+if (AtpScope::canAny(['transition:generic', 'transition:chat.bsky'])) {
897897+ // ...
898898+}
899899+900900+// Check if user has all scopes
901901+if (AtpScope::canAll(['atproto', 'transition:generic'])) {
902902+ // ...
903903+}
904904+905905+// Authorize or fail (throws/aborts based on config)
906906+AtpScope::authorize('transition:generic');
907907+908908+// Check for a specific user
909909+AtpScope::forUser($did)->authorize('transition:generic');
910910+911911+// Get all granted scopes
912912+$scopes = AtpScope::granted();
913913+```
914914+915915+### Session Helper Methods
916916+917917+The Session class also has convenience methods:
918918+919919+```php
920920+$session = Atp::as($did)->session();
921921+922922+$session->can('transition:generic');
923923+$session->canAny(['transition:generic', 'transition:chat.bsky']);
924924+$session->canAll(['atproto', 'transition:generic']);
925925+$session->cannot('transition:chat.bsky');
926926+```
927927+928928+### Configuration
929929+930930+Configure authorization failure behavior in `config/client.php`:
931931+932932+```php
933933+'scope_authorization' => [
934934+ // What happens when scope check fails: 'abort', 'redirect', or 'exception'
935935+ 'failure_action' => ScopeAuthorizationFailure::Abort,
936936+937937+ // Redirect URL when failure_action is 'redirect'
938938+ 'redirect_to' => '/login',
939939+],
940940+```
941941+942942+Or via environment variables:
943943+944944+```env
945945+ATP_SCOPE_FAILURE_ACTION=abort
946946+ATP_SCOPE_REDIRECT=/login
947947+```
948948+847949## Available Commands
848950849951```bash