# Post-RBAC Legacy Authorization Bridge Retired

## Final state

The temporary legacy authorization bridge has been retired. Spatie Laravel Permission is the only runtime authorization assignment source:

- `model_has_roles` — canonical user-role assignments.
- `role_has_permissions` — canonical role-permission assignments.
- `model_has_permissions` — retained by Spatie schema and expected to remain empty for normal application authorization.

The legacy comparison pivots are removed by `2026_08_14_170000_retire_legacy_authorization_bridge.php`:

- `role_user`
- `permission_role`

The application no longer mirrors canonical writes into those tables and no longer contains the bridge synchronizer, bridge Artisan command, bridge seeder, readiness command, or deprecated bridge-wrapper seeders.

## Destructive migration safety gate

The retirement migration re-validates the live database immediately before dropping either legacy pivot. The migration aborts if any of the following is true:

1. a required canonical or legacy authorization table is missing;
2. `permission_role` is not an exact ordered match for `role_has_permissions`;
3. `role_user` is not an exact ordered match for `App\\Models\\User` rows in `model_has_roles`;
4. any direct assignment exists in `model_has_permissions`;
5. `model_has_roles` contains an unexpected model type;
6. a role or permission uses a guard other than `web`.

This makes the parity requirement an execution-time condition rather than relying only on the earlier readiness report.

## Rollback

The retirement migration has a restorative `down()` path:

1. recreate `permission_role` with its original foreign keys and composite primary key;
2. recreate `role_user` with its original foreign keys and composite primary key;
3. backfill `permission_role` from canonical `role_has_permissions`;
4. backfill `role_user` from canonical `model_has_roles` for `App\\Models\\User`.

For a production rollback, database rollback/restore and application rollback must be coordinated. If the old application version is restored, recreate/backfill the legacy pivots first (or restore the verified pre-deployment backup) before old bridge code is allowed to run.

## Permanent regression guard

`AuthorizationLegacyBridgeRetirementTest` protects the retired state by verifying:

- both legacy pivot tables are absent after current migrations;
- canonical Spatie assignment tables remain present;
- the assignment service can write user roles and role permissions without legacy tables;
- direct model permissions remain empty in the fresh baseline;
- application, routes, seeders, and CI workflows contain no retired bridge synchronizer/seeder/command/mirror-write signatures.

Historical migrations are intentionally not scanned or rewritten. They remain the immutable record of how the system moved from legacy pivots to Spatie before the final retirement migration removed them.

## Deliberate exclusions

This retirement does not change:

- deprecated permission-name aliases that may still have independent compatibility value;
- the intentional `super-administrator` `Gate::before` break-glass behavior;
- branch access wrappers or branch isolation behavior;
- Spatie's canonical role/permission tables and cache semantics.
