# Phase 4 — Security Administration & Privilege-Escalation Protection

## Status

Phase 4 hardens role administration and staff role assignment on top of the Spatie runtime and canonical permission catalog established in Phases 2 and 3.

Branch isolation remains independent. A functional role permission never expands the set of branches a user may access.

## New security permissions

The canonical catalog now includes:

- `roles.create` — create custom roles;
- `roles.delete` — delete unused custom roles;
- `roles.assign` — change user role assignments within the actor's delegation ceiling;
- `roles.assign-system` — assign protected system roles within that ceiling;
- `roles.assign-super-admin` — assign or remove the Super Administrator role.

`roles.view` and `roles.update` continue to control role visibility and custom-role editing.

Super Administrator receives these capabilities through the global `Gate::before` bypass and does not require explicit pivot grants.

Branch Administrator receives only `roles.assign` and `roles.assign-system`. This preserves its existing ability to staff its assigned branches while adding a strict privilege ceiling. It does not receive role CRUD or super-admin delegation.

## Delegation ceiling

`AuthorizationDelegationService` is the single runtime contract for role delegation.

For non-super-administrators, a role can be assigned or removed only when all of the following are true:

1. the actor has `roles.assign`;
2. system roles additionally require `roles.assign-system`;
3. the Super Administrator role additionally requires `roles.assign-super-admin`;
4. every permission granted by the target role is already held by the actor.

This prevents an administrator from granting authority that exceeds their own effective authority.

Custom roles with stronger permissions are automatically excluded from the staff role selector for actors below that ceiling.

## Self-escalation protection

A non-super-administrator cannot add a role to their own account, even if the role would otherwise be within their delegation ceiling.

Removing roles from the current account is still subject to the same delegation checks and the super-admin continuity rule.

## Super Administrator protection

A Super Administrator account cannot be managed by an actor who lacks `roles.assign-super-admin`.

The last active Super Administrator cannot be:

- stripped of the Super Administrator role; or
- changed from `active` to `inactive`.

A second active Super Administrator must exist before either action is permitted.

## System roles

All roles seeded by `DefaultRoleMatrix` are protected system roles.

System roles:

- cannot be edited through role administration;
- cannot be deleted through role administration;
- retain application-owned names and default permission matrices;
- may be assigned only under the delegation rules above.

This prevents runtime edits from being silently overwritten by later authorization seeding.

## Custom roles

Authorized users may create custom roles with:

- a permanent lowercase identifier;
- a human display name;
- an optional description;
- an explicit permission set.

A delegated role administrator can select only permissions they already hold. Super Administrator may select any catalog permission.

Custom roles may be edited, but their identifier is immutable after creation.

A custom role cannot be deleted while assigned to any staff user.

## Staff role assignment

Staff create/update forms receive their role options from `AuthorizationDelegationService` rather than querying every role directly.

If an existing user has a role above the actor's delegation ceiling, that role is displayed as protected and is automatically preserved during unrelated staff edits.

Role changes and branch assignments remain separate:

- role delegation controls what functional authority may be assigned;
- `BranchAccessService` controls which branch IDs the actor may assign and access.

## Audit trail

Successful sensitive changes record dedicated audit actions:

- `authorization.role.created`;
- `authorization.role.updated`;
- `authorization.role.deleted`;
- `authorization.user.roles.assigned`;
- `authorization.user.roles.updated`.

Role audit data records permission/role names rather than credentials or other secrets.

Existing staff create/update audit records remain in place.

## CI and regression guarantees

Phase 4 tests verify:

1. the catalog contains the new security permissions;
2. all Phase 2 access remains unchanged except the reviewed Branch Administrator delegation additions;
3. Branch Administrator can delegate ordinary operational roles within its authority;
4. Branch Administrator cannot delegate Super Administrator;
5. a role containing authority beyond the actor's permission set cannot be delegated;
6. non-super users cannot add roles to their own account;
7. the last active Super Administrator cannot be demoted or deactivated;
8. system roles are immutable;
9. custom-role creation/deletion is audited;
10. assigned custom roles cannot be deleted;
11. the existing Spatie bridge, branch isolation, authorization inventory, MySQL, production configuration, and release-verification suites remain green.

## Not part of Phase 4

Later phases still cover:

- replacing legacy `permission:` middleware with Laravel `can:` consistently;
- customer/loan/collateral policy migration;
- maker-checker workflow authorization;
- granular replacement of legacy broad permissions;
- UI-wide permission cleanup;
- permanent static authorization audits and final legacy pivot removal.
