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

11 KiB
Raw Blame History

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

  • 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
  • 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

  • T005 [P] Ensure canonical capability registry exists and matches v1 contract in app/Support/Auth/Capabilities.php
  • 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
  • T007 Register tenant capability gates for the full registry using Capabilities::all() (no hand-maintained lists) in app/Providers/AuthServiceProvider.php
  • 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
  • T009 Create/update unit tests asserting least-privilege invariants (Owner can manage memberships, Manager cannot) in tests/Unit/Auth/CapabilityResolverTest.php
  • T012 [P] Add contract test that fails fast on unknown/typo capability strings passed to the capability system in tests/Unit/Auth/UnknownCapabilityGuardTest.php
  • 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.

  • T014 [US1] Create/update TenantMembershipsRelationManager for TenantResource in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • T015 [US1] Implement table columns (user name, email, role) in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • 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
  • T017 [US1] Implement "Change Role" action (Owner-only, server-authorized, requires confirmation + clear validation/feedback) in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • T018 [US1] Implement "Remove Member" action (Owner-only, server-authorized, requires confirmation + clear validation/feedback) in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • T019 [US1] Add "last owner" protection logic to change/remove actions (and cover policy edge-cases) in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • 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
  • 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.

  • 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
  • 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
  • T023 [US2] Add non-member 404 tests (direct URL, tenant switcher list, global search scoping) in tests/Feature/Filament/TenantScopingTest.php
  • 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/**
  • 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/**
  • 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
  • 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
  • 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
  • T030 [P] [US2] Backups enforcement: gate + UI rules for backup sets/schedules in app/Filament/Resources/BackupSetResource.php and app/Filament/Resources/BackupScheduleResource.php
  • T031 [P] [US2] Restore enforcement: gate + UI rules for restore creation/execution in app/Filament/Resources/RestoreRunResource.php and app/Jobs/ExecuteRestoreRunJob.php
  • 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
  • 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
  • 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
  • T035 [US2] Implement audit logging for membership changes (writes audit_logs.action + redacted metadata) in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
  • 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
  • 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
  • T038 [P] [US2] Role matrix tests (Readonly: 510 golden checks) in tests/Feature/Rbac/RoleMatrix/ReadonlyAccessTest.php
  • T039 [P] [US2] Role matrix tests (Operator: 510 golden checks) in tests/Feature/Rbac/RoleMatrix/OperatorAccessTest.php
  • T040 [P] [US2] Role matrix tests (Manager: 510 golden checks) in tests/Feature/Rbac/RoleMatrix/ManagerAccessTest.php
  • T041 [P] [US2] Role matrix tests (Owner: 510 golden checks) in tests/Feature/Rbac/RoleMatrix/OwnerAccessTest.php

Late enforcement follow-ups (post-sweep)

  • 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
  • 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
  • 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

  • T042 [P] Review all changed code for adherence to project conventions in app/ and tests/
  • T043 [P] Ensure all new UI text is translatable in resources/lang/*/*.php
  • T044 Run ./vendor/bin/sail bin pint --dirty to format all changed files in app/ and tests/
  • 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.