12 KiB
| description |
|---|
| Task breakdown for Spec 080 implementation |
Tasks: Workspace-Managed Tenant Administration Migration (Spec 080)
Input: Design documents from /specs/080-workspace-managed-tenant-admin/ (plan.md, spec.md, contracts/routes.md, research.md, data-model.md, quickstart.md)
Non-negotiables (repo rules)
- Filament v5 + Livewire v4.0+ only.
- Laravel 11+: Filament panel providers are registered in
bootstrap/providers.php. - RBAC-UX semantics: non-member/non-entitled → 404; member missing capability on mutation → 403.
- Removed tenant-scoped management routes must not be registered (404, no redirects).
- Tests are REQUIRED (Pest).
Phase 1: Setup (Panel Scaffolding)
Purpose: Introduce the tenant operations panel without changing behavior yet.
- T001 Create tenant operations panel provider in app/Providers/Filament/TenantPanelProvider.php
- T002 Register new provider in bootstrap/providers.php (add App\Providers\Filament\TenantPanelProvider::class)
Checkpoint: App boots with both panels registered.
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Establish the manage vs operate separation mechanisms (routing + middleware + discovery boundaries).
- T003 Refactor workspace panel to be tenantless in app/Providers/Filament/AdminPanelProvider.php (remove ->tenant(...), ->tenantRoutePrefix('t'), tenant menu/searchable menu)
- T004 Update workspace panel middleware stack in app/Providers/Filament/AdminPanelProvider.php (remove ensure-filament-tenant-selected and App\Support\Middleware\DenyNonMemberTenantAccess for workspace panel)
- T005 Configure tenant panel tenancy + middleware in app/Providers/Filament/TenantPanelProvider.php (enable ->tenant(App\Models\Tenant::class, slugAttribute: 'external_id'), enforce canonical path
/admin/t/{tenant}/..., and add ensure-filament-tenant-selected + DenyNonMemberTenantAccess) - T006 Constrain resource/page discovery so management artifacts do not get registered in tenant panel in app/Providers/Filament/TenantPanelProvider.php (use dedicated discovery roots like app/Filament/Tenant/**)
- T007 [P] Add a dedicated base feature test file tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (placeholder tests + factories usage notes)
- T030 [P] [FOUNDATION] Add route-shape regression tests in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php asserting tenant routes resolve as
/admin/t/{tenant}and/admin/t/{tenant}/diagnosticsand never/admin/t/t/{tenant}/...
Checkpoint: Workspace panel does not require tenant context; tenant panel is isolated by discovery roots.
Phase 3: User Story 1 — Manage tenants from workspace scope (Priority: P1) 🎯 MVP
Goal: Tenants management is canonical under /admin/tenants* without needing tenant scope.
Independent Test: As a workspace member, GET /admin/tenants returns 200; non-member returns 404.
Tests (Pest) — US1
- T008 [P] [US1] Add access tests for workspace-managed tenant list in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (member 200, non-member 404)
- T009 [P] [US1] Add access tests for workspace-managed tenant view route in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (member 200, non-member 404)
- T031 [P] [US1] Add access tests for workspace-managed memberships route in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (
/admin/tenants/{tenant}/memberships, member 200, non-member 404)
Implementation — US1
- T010 [US1] Move/rename management routes to match /admin/tenants* in app/Filament/Resources/TenantResource.php (ensure resource slug becomes tenants under workspace panel)
- T011 [US1] Ensure TenantResource is registered only in workspace panel (update app/Providers/Filament/AdminPanelProvider.php registration/discovery strategy)
- T012 [US1] Ensure tenant route parameter identity uses Tenant.external_id in app/Models/Tenant.php (route key name) OR in TenantResource route binding configuration
- T032 [US1] Ensure memberships management surface exists only under workspace scope in app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php and app/Filament/Resources/TenantResource.php (
/admin/tenants/{tenant}/memberships)
Checkpoint: /admin/tenants works in the workspace panel.
Phase 4: User Story 2 — Operate inside tenant scope only when entitled (Priority: P2)
Goal: Operational pages remain under /admin/t/{tenant}/* and return 404 when user is not entitled.
Independent Test: Entitled user can access GET /admin/t/{tenant} and GET /admin/t/{tenant}/diagnostics; non-entitled user gets 404.
Tests (Pest) — US2
- T013 [P] [US2] Add tenant entitlement tests for concrete operational routes in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (
/admin/t/{tenant}and/admin/t/{tenant}/diagnostics: entitled 200, non-entitled 404)
Implementation — US2
- T014 [US2] Register/relocate tenant operational dashboard page into tenant panel in app/Filament/Pages/TenantDashboard.php and app/Providers/Filament/TenantPanelProvider.php
- T015 [US2] Ensure tenant selection redirects into tenant panel routes in app/Filament/Pages/ChooseTenant.php (redirect should target /admin/t/{tenant}/...)
Checkpoint: The contracted operational routes are reachable only when entitled.
Phase 5: User Story 3 — Remove tenant-scoped management CRUD routes (Priority: P3)
Goal: Tenant-scoped management URLs do not resolve because resources/pages are not registered in tenant panel.
Independent Test: Requests to removed routes return 404 (route does not exist).
Tests (Pest) — US3
- T016 [P] [US3] Add 404 regression tests for removed routes in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (e.g. /admin/t/{tenant}/provider-connections, /admin/t/{tenant}/required-permissions)
- T033 [P] [US3] Add tenant navigation regression test in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php ensuring tenant panel sidebar does not expose tenant-management entries (Tenants, Provider Connections, Memberships)
Implementation — US3
- T017 [US3] Ensure management resources are not discovered/registered in tenant panel (verify TenantResource + ProviderConnectionResource not in tenant discovery roots in app/Providers/Filament/TenantPanelProvider.php)
- T018 [US3] Ensure required permissions page is not registered in tenant panel in app/Providers/Filament/TenantPanelProvider.php (and/or relocate page class under workspace-managed location)
- T034 [US3] Ensure tenant panel navigation is operate-only by construction in app/Providers/Filament/TenantPanelProvider.php (no TenantResource/ProviderConnectionResource/TenantMemberships registration)
Checkpoint: Removed tenant-scoped management paths return 404 (no redirects).
Phase 6: User Story 4 — Management actions enforce capability semantics (Priority: P2)
Goal: Workspace members can view management pages; mutations are forbidden (403) unless capability is present.
Independent Test: A representative management mutation returns 403 for a workspace member missing capability.
Tests (Pest) — US4
- T019 [P] [US4] Add mutation authorization test asserting 403 (member missing capability) in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
- T035 [P] [US4] Add audit assertion test for tenant membership mutation in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (writes redacted AuditLog with stable action ID)
Implementation — US4
- T020 [US4] Audit management mutations in app/Services/Intune/AuditLogger.php (or existing audit service) for provider connection + membership changes with stable action IDs
- T021 [US4] Ensure destructive-like actions use ->requiresConfirmation() in app/Filament/Resources/TenantResource.php and app/Filament/Resources/ProviderConnectionResource.php
Checkpoint: 403 vs 404 semantics match spec for mutations.
Phase 7: User Story 5 — Global search isolation (Priority: P2)
Goal: Tenant management entities are searchable only in workspace panel; tenant panel global search does not expose them.
Independent Test: Workspace panel global search can resolve TenantResource results; tenant panel global search does not include TenantResource/ProviderConnectionResource.
Tests (Pest) — US5
- T022 [P] [US5] Add global search scoping tests in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (workspace panel finds tenant; tenant panel does not expose management resources)
Implementation — US5
- T023 [US5] Ensure TenantResource has a View/Edit page for global search compliance in app/Filament/Resources/TenantResource/Pages/*
- T024 [US5] Ensure tenant panel does not register tenant-management resources/pages (verify discovery roots + resource registration in app/Providers/Filament/TenantPanelProvider.php)
Checkpoint: Global search results do not leak across scopes.
Phase 8: Polish & Cross-Cutting
Purpose: Link rewiring, consistency, formatting, and minimal regression validation.
- T025 [P] Rewire internal CTAs from tenant-scoped management URLs to workspace-managed routes in app/Filament/Pages/Workspaces/ManagedTenantsLanding.php and app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
- T026 [P] Update required permissions viewer to be workspace-managed + DB-only in app/Filament/Pages/TenantRequiredPermissions.php (accept tenant via route param, avoid Tenant::current())
- T027 [P] Update provider connections to support workspace-managed per-tenant routes in app/Filament/Resources/ProviderConnectionResource.php (query should use route tenant param when not in tenancy)
- T038 [P] Add Provider Connections CTA on tenant view page in app/Filament/Resources/TenantResource/Pages/ViewTenant.php (links to /admin/tenants/{tenant}/provider-connections)
- T036 [P] Add workspace navigation regression test in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php to assert Tenants + Monitoring entries are present in workspace panel after panel split
- T037 [P] Extend RBAC regression coverage for panel boundaries in tests/Feature/TenantRBAC/* (deny-as-not-found across workspace/tenant routing boundaries)
- T028 Run formatting on touched files with vendor/bin/sail bin pint --dirty (formats app/** and tests/**)
- T029 Run focused tests with vendor/bin/sail artisan test --compact tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
- T039 Run formatting on touched files again (post-T038) with vendor/bin/sail bin pint --dirty
- T040 Re-run focused spec tests (post-T038) with vendor/bin/sail artisan test --compact tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
Dependencies & Execution Order
User Story Dependency Graph
- Setup (Phase 1) → Foundational (Phase 2) → US1 (MVP)
- US2 depends on Phase 2
- US3 depends on Phase 2 (route removal works once panel discovery boundaries are in place)
- US4 depends on US1 (needs workspace management routes/actions)
- US5 depends on Phase 2 + US1 (workspace management resources must exist)
- Polish tasks depend on US1–US5 completion for stable regression assertions (T036, T037).
Parallel Opportunities
- After Phase 2 completes:
- US1 tests (T008–T009, T031) can be written in parallel with US1 implementation (T010–T012, T032).
- US2 (T013–T015) can proceed in parallel with US1.
- US3 tests (T016, T033) can be added early as regression guards.
Parallel Example: US1
- Write tests: T008 + T009 in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
- Implement routes: T010 in app/Filament/Resources/TenantResource.php
Implementation Strategy
MVP Scope
- Complete Phase 1 + Phase 2 + US1 (T001–T012)
- Validate with T029 and manual checks from quickstart.md
Incremental Delivery
- Add US2 + US3 next (routing guarantees + entitlement semantics)
- Then US4 (mutation semantics + audit) and US5 (global search isolation)