TenantAtlas/specs/065-tenant-rbac-v1/tasks.md
ahmido d90fb0f963 065-tenant-rbac-v1 (#79)
PR Body
Implements Spec 065 “Tenant RBAC v1” with capabilities-first RBAC, tenant membership scoping (Option 3), and consistent Filament action semantics.

Key decisions / rules

Tenancy Option 3: tenant switching is tenantless (ChooseTenant), tenant-scoped routes stay scoped, non-members get 404 (not 403).
RBAC model: canonical capability registry + role→capability map + Gates for each capability (no role-string checks in UI logic).
UX policy: for tenant members lacking permission → actions are visible but disabled + tooltip (avoid click→403).
Security still enforced server-side.
What’s included

Capabilities foundation:
Central capability registry (Capabilities::*)
Role→capability mapping (RoleCapabilityMap)
Gate registration + resolver/manager updates to support tenant-scoped authorization
Filament enforcement hardening across the app:
Tenant registration & tenant CRUD properly gated
Backup/restore/policy flows aligned to “visible-but-disabled” where applicable
Provider operations (health check / inventory sync / compliance snapshot) guarded and normalized
Directory groups + inventory sync start surfaces normalized
Policy version maintenance actions (archive/restore/prune/force delete) gated
SpecKit artifacts for 065:
spec.md, plan/tasks updates, checklists, enforcement hitlist
Security guarantees

Non-member → 404 via tenant scoping/membership guards.
Member without capability → 403 on execution, even if UI is disabled.
No destructive actions execute without proper authorization checks.
Tests

Adds/updates Pest coverage for:
Tenant scoping & membership denial behavior
Role matrix expectations (owner/manager/operator/readonly)
Filament surface checks (visible/disabled actions, no side effects)
Provider/Inventory/Groups run-start authorization
Verified locally with targeted vendor/bin/sail artisan test --compact …
Deployment / ops notes

No new services required.
Safe change: behavior is authorization + UI semantics; no breaking route changes intended.

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #79
2026-01-28 21:09:47 +00:00

89 lines
11 KiB
Markdown
Raw Permalink 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.