TenantAtlas/specs/080-workspace-managed-tenant-admin/tasks.md
ahmido 3f09fd50f6 feat(spec-080): workspace-managed tenant administration migration (#97)
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
2026-02-07 19:45:13 +00:00

12 KiB
Raw Blame History

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}/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

  • 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 US1US5 completion for stable regression assertions (T036, T037).

Parallel Opportunities

  • After Phase 2 completes:
    • US1 tests (T008T009, T031) can be written in parallel with US1 implementation (T010T012, T032).
    • US2 (T013T015) 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 (T001T012)
  • 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)