Implements Spec 080: split Filament into workspace-managed `/admin/*` (manage) vs tenant operations `/admin/t/{tenant}/*` (operate).
Highlights:
- Adds tenant operations panel (`tenant`) at `/admin/t` with tenancy by `Tenant.external_id`
- Keeps management resources in workspace panel (`admin`) under `/admin/tenants/*`
- Moves Provider Connections to workspace-managed routes: `/admin/tenants/{tenant}/provider-connections`
- Adds discoverability CTA on tenant view (Actions → Provider connections)
- Adds/updates Pest regression tests for routing boundaries, 404/403 RBAC-UX semantics, and global search isolation
- Includes full Spec Kit artifacts under `specs/080-workspace-managed-tenant-admin/`
Validation:
- `vendor/bin/sail bin pint --dirty`
- `vendor/bin/sail artisan test --compact tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php`
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #97
201 lines
12 KiB
Markdown
201 lines
12 KiB
Markdown
---
|
||
|
||
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.
|
||
|
||
- [X] T001 Create tenant operations panel provider in app/Providers/Filament/TenantPanelProvider.php
|
||
- [X] 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).
|
||
|
||
- [X] T003 Refactor workspace panel to be tenantless in app/Providers/Filament/AdminPanelProvider.php (remove ->tenant(...), ->tenantRoutePrefix('t'), tenant menu/searchable menu)
|
||
- [X] 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)
|
||
- [X] 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)
|
||
- [X] 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/**)
|
||
- [X] T007 [P] Add a dedicated base feature test file tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (placeholder tests + factories usage notes)
|
||
- [X] 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}/diagnostics` and 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
|
||
|
||
- [X] T008 [P] [US1] Add access tests for workspace-managed tenant list in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (member 200, non-member 404)
|
||
- [X] T009 [P] [US1] Add access tests for workspace-managed tenant view route in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php (member 200, non-member 404)
|
||
- [X] 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
|
||
|
||
- [X] T010 [US1] Move/rename management routes to match /admin/tenants* in app/Filament/Resources/TenantResource.php (ensure resource slug becomes tenants under workspace panel)
|
||
- [X] T011 [US1] Ensure TenantResource is registered only in workspace panel (update app/Providers/Filament/AdminPanelProvider.php registration/discovery strategy)
|
||
- [X] 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
|
||
- [X] 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
|
||
|
||
- [X] 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
|
||
|
||
- [X] T014 [US2] Register/relocate tenant operational dashboard page into tenant panel in app/Filament/Pages/TenantDashboard.php and app/Providers/Filament/TenantPanelProvider.php
|
||
- [X] 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
|
||
|
||
- [X] 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)
|
||
- [X] 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
|
||
|
||
- [X] 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)
|
||
- [X] 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)
|
||
- [X] 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
|
||
|
||
- [X] T019 [P] [US4] Add mutation authorization test asserting 403 (member missing capability) in tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
|
||
- [X] 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
|
||
|
||
- [X] T020 [US4] Audit management mutations in app/Services/Intune/AuditLogger.php (or existing audit service) for provider connection + membership changes with stable action IDs
|
||
- [X] 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
|
||
|
||
- [X] 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
|
||
|
||
- [X] T023 [US5] Ensure TenantResource has a View/Edit page for global search compliance in app/Filament/Resources/TenantResource/Pages/*
|
||
- [X] 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.
|
||
|
||
- [X] 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
|
||
- [X] 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())
|
||
- [X] 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)
|
||
- [X] 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)
|
||
- [X] 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
|
||
- [X] T037 [P] Extend RBAC regression coverage for panel boundaries in tests/Feature/TenantRBAC/* (deny-as-not-found across workspace/tenant routing boundaries)
|
||
- [X] T028 Run formatting on touched files with vendor/bin/sail bin pint --dirty (formats app/** and tests/**)
|
||
- [X] T029 Run focused tests with vendor/bin/sail artisan test --compact tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php
|
||
- [X] T039 Run formatting on touched files again (post-T038) with vendor/bin/sail bin pint --dirty
|
||
- [X] 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)
|