TenantAtlas/specs/065-tenant-rbac-v1/tasks.md
2026-01-28 22:04:45 +01:00

89 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tasks for Feature: Tenant RBAC v1
This document outlines the implementation tasks for the Tenant RBAC v1 feature, ordered by dependency.
## Phase 1: Setup & Database
- [X] T001 Verify `tenant_memberships` schema matches spec (uuid PK, role enum, minimal provenance fields) in `database/migrations/2026_01_25_022729_create_tenant_memberships_table.php`
- [X] T002 Verify `TenantMembership` pivot model + relationships exist and are correct in `app/Models/TenantMembership.php`, `app/Models/User.php`, and `app/Models/Tenant.php`
## Phase 2: Foundational RBAC Core
- [X] T005 [P] Ensure canonical capability registry exists and matches v1 contract in `app/Support/Auth/Capabilities.php`
- [X] T006 [P] Ensure role → capability mapping matches least-privilege semantics (Owner-only membership manage) and references only registry constants in `app/Services/Auth/RoleCapabilityMap.php`
- [X] T007 Register tenant capability gates for the full registry using `Capabilities::all()` (no hand-maintained lists) in `app/Providers/AuthServiceProvider.php`
- [X] T008 Add/confirm request-scope cache for membership + capabilities and add a test asserting repeated capability checks do not execute additional membership queries (query count assertion) in `tests/Unit/Auth/CapabilityResolverQueryCountTest.php`
- [X] T009 Create/update unit tests asserting least-privilege invariants (Owner can manage memberships, Manager cannot) in `tests/Unit/Auth/CapabilityResolverTest.php`
- [X] T012 [P] Add contract test that fails fast on unknown/typo capability strings passed to the capability system in `tests/Unit/Auth/UnknownCapabilityGuardTest.php`
- [X] T013 [P] (Optional, recommended) Add guard test forbidding role-string checks outside the mapper (e.g. `'owner'`, `'manager'`) in `tests/Unit/Auth/NoRoleStringChecksTest.php`
## Phase 3: User Story 1 - Membership Management UI
**Goal**: As a Tenant Owner, I want to manage members and their roles.
**Independent Test Criteria**: An owner can add, edit, and remove members. Non-owners cannot. The last owner cannot be removed or demoted.
- [X] T014 [US1] Create/update `TenantMembershipsRelationManager` for `TenantResource` in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T015 [US1] Implement table columns (user name, email, role) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T016 [US1] Ensure "Add Member" action is Owner-only and requires existing user (no placeholder user creation) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T017 [US1] Implement "Change Role" action (Owner-only, server-authorized, requires confirmation + clear validation/feedback) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T018 [US1] Implement "Remove Member" action (Owner-only, server-authorized, requires confirmation + clear validation/feedback) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T019 [US1] Add "last owner" protection logic to change/remove actions (and cover policy edge-cases) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T020 [US1] Add DB-only render guard test for Members UI: use `Http::preventStrayRequests()` (and prevent queued work) while rendering/hydrating members relation manager; assert no outbound HTTP and no jobs dispatched in `tests/Feature/Filament/TenantMembersDbOnlyRenderTest.php`
- [X] T021 [US1] Create feature test for membership management UI and authorization in `tests/Feature/Filament/TenantMembersTest.php`
## Phase 4: User Story 2 - Authorization Enforcement
**Goal**: As a user, my actions are authorized based on my role, and I cannot access unauthorized resources.
**Independent Test Criteria**: Routes and actions are protected based on the defined capability matrix.
- [X] T022 [US2] Harden tenant scoping to enforce FR-011 in the Filament tenant middleware chain (registered in `app/Providers/Filament/AdminPanelProvider.php`) with 404 (not 403) semantics for all `/admin/t/{tenant}/**` routes; enforce global search scoping by overriding global search queries on each Resource (or a shared trait) to restrict results to the current tenant and deny non-members (tests assert non-member sees zero results and result URLs still 404) in `app/Filament/Resources/*Resource.php`
- [X] T022 [US2] Harden tenant scoping to enforce FR-011 in the Filament tenant middleware chain (registered in `app/Providers/Filament/AdminPanelProvider.php`) with 404 (not 403) semantics for all `/admin/t/{tenant}/**` routes; enforce global search scoping by overriding global search queries on each Resource (or a shared trait) to restrict results to the current tenant and deny non-members (tests assert non-member sees zero results and result URLs still 404) in `app/Filament/Resources/*Resource.php`
- [X] T023 [US2] Add non-member 404 tests (direct URL, tenant switcher list, global search scoping) in `tests/Feature/Filament/TenantScopingTest.php`
- [X] T024 [US2] Discovery sweep (required): produce a mutation/start-action hitlist across Filament (Resources/RelationManagers/Actions/BulkActions) in `specs/065-tenant-rbac-v1/enforcement-hitlist.md`
- [ ] T025 [US2] Enforcement pass (required): for each hitlist entry add server-side authorization + UI visibility/disabled rules + confirmations for destructive actions in `app/Filament/**`
- [ ] T026 [US2] Replace role-based authorization helpers (e.g. `TenantRole::can*()` calls) with capability Gates across tenant-plane UI/actions (deny non-member as 404 per middleware; otherwise prefer authorization failures as 403) in `app/Filament/**` and `app/Policies/**`
- [X] T025 [US2] Enforcement pass (required): for each hitlist entry add server-side authorization + UI visibility/disabled rules + confirmations for destructive actions in `app/Filament/**`
- [X] T026 [US2] Replace role-based authorization helpers (e.g. `TenantRole::can*()` calls) with capability Gates across tenant-plane UI/actions (deny non-member as 404 per middleware; otherwise prefer authorization failures as 403) in `app/Filament/**` and `app/Policies/**`
- [X] T027 [P] [US2] Providers enforcement: gate + UI rules for provider CRUD / run ops / credential rotate in `app/Filament/Resources/ProviderConnectionResource.php` and `app/Filament/Resources/ProviderConnectionResource/Pages/*.php`
- [X] T028 [P] [US2] Tenants + tenant settings enforcement: gate + UI rules for tenant pages/actions in `app/Filament/Resources/TenantResource.php` and `app/Filament/Resources/TenantResource/Pages/*.php`
- [X] T029 [P] [US2] Policies enforcement: gate + UI rules (sync/delete/version views) in `app/Filament/Resources/PolicyResource.php` and `app/Filament/Resources/PolicyResource/Pages/*.php`
- [X] T030 [P] [US2] Backups enforcement: gate + UI rules for backup sets/schedules in `app/Filament/Resources/BackupSetResource.php` and `app/Filament/Resources/BackupScheduleResource.php`
- [X] T031 [P] [US2] Restore enforcement: gate + UI rules for restore creation/execution in `app/Filament/Resources/RestoreRunResource.php` and `app/Jobs/ExecuteRestoreRunJob.php`
- [X] T032 [P] [US2] Drift/Findings enforcement: gate + UI rules for drift findings browsing/ack (if present) in `app/Filament/Resources/FindingResource.php` and `app/Filament/Resources/FindingResource/Pages/*.php`
- [X] T033 [P] [US2] Inventory enforcement: gate + UI rules for inventory browsing/sync runs in `app/Filament/Resources/InventoryItemResource.php` and `app/Filament/Resources/InventorySyncRunResource.php`
- [X] T034 [US2] Add canonical audit action_ids for membership changes (`tenant_membership.add|role_change|remove|last_owner_blocked`) in `app/Support/Audit/AuditActionId.php`
- [X] T035 [US2] Implement audit logging for membership changes (writes `audit_logs.action` + redacted metadata) in `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`
- [X] T036 [US2] Add audit logging tests (entry written, action_id stable, metadata minimal + redacted; includes explicit data-minimization assertions: no secrets/tokens, minimal identity fields) in `tests/Feature/Audit/TenantMembershipAuditLogTest.php`
- [X] T037 [US2] Add denial diagnostics: log structured context for authorization denials (capability, tenant_id, actor_user_id) without secrets in `app/Services/Auth/CapabilityResolver.php` (or a dedicated listener) and cover one representative denial path in `tests/Feature/Rbac/DenialDiagnosticsTest.php`
- [X] T038 [P] [US2] Role matrix tests (Readonly: 510 golden checks) in `tests/Feature/Rbac/RoleMatrix/ReadonlyAccessTest.php`
- [X] T039 [P] [US2] Role matrix tests (Operator: 510 golden checks) in `tests/Feature/Rbac/RoleMatrix/OperatorAccessTest.php`
- [X] T040 [P] [US2] Role matrix tests (Manager: 510 golden checks) in `tests/Feature/Rbac/RoleMatrix/ManagerAccessTest.php`
- [X] T041 [P] [US2] Role matrix tests (Owner: 510 golden checks) in `tests/Feature/Rbac/RoleMatrix/OwnerAccessTest.php`
### Late enforcement follow-ups (post-sweep)
- [X] T046 Gate tenant registration + tenant create/edit/delete for non-managers (prevent cross-tenant privilege escalation via Register Tenant) in `app/Filament/Pages/Tenancy/RegisterTenant.php`, `app/Filament/Resources/TenantResource.php`, and `app/Filament/Resources/TenantResource/Pages/*.php`
- [X] T047 Gate policy version maintenance actions (archive/restore/prune/force delete) to `Capabilities::TENANT_MANAGE` with UI disable + server-side abort in `app/Filament/Resources/PolicyVersionResource.php`
- [X] T048 Add regression tests for readonly tenant + policy version maintenance restrictions in `tests/Feature/Rbac/*.php` and update existing bootstrap test in `tests/Feature/TenantRBAC/TenantBootstrapAssignTest.php`
## Phase 5: Polish & Finalization
- [X] T042 [P] Review all changed code for adherence to project conventions in `app/` and `tests/`
- [X] T043 [P] Ensure all new UI text is translatable in `resources/lang/*/*.php`
- [X] T044 Run `./vendor/bin/sail bin pint --dirty` to format all changed files in `app/` and `tests/`
- [X] T045 Run the full test suite with `./vendor/bin/sail artisan test --compact` to ensure no regressions
## Dependencies
- **US1 (Membership Management)** depends on **Phase 1** and **Phase 2**.
- **US2 (Authorization Enforcement)** depends on **Phase 1** and **Phase 2**. US1 should be completed first to allow for testing with different roles.
## Parallel Execution
- Within **Phase 2**, tasks T005, T006, T008, and T012 can be worked on in parallel.
- Within **Phase 4**, the domain enforcement tasks (T024T030) can be split across agents once T022 (hitlist) is stable.
## Implementation Strategy
The implementation will follow an MVP-first approach. The initial focus will be on completing Phase 1 and 2 to establish the core data model and RBAC logic. Then, Phase 3 will be implemented to provide the essential UI for managing memberships. Phase 4 will be a sweep to enforce the new authorization rules across the application.