## Summary - add explicit workspace closure and tenant removal lifecycle truth with a bounded `WorkspaceLifecycleService` - surface closure and removal posture across admin/system pages, chooser recovery, and canonical historical viewers - block new review-pack and operation starts for closed workspaces or removed tenants while preserving memberships, audit, and history - add focused Pest coverage plus the Spec 292 artifacts for the implemented slice ## Testing - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Directory/ViewWorkspaceClosureTest.php tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.php tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.php tests/Feature/Filament/Pages/WorkspaceContextClosureRecoveryTest.php` - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - manual integrated-browser smoke for admin tenant remove/restore plus chooser recovery and system workspace close/reopen Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #337
16 KiB
| description |
|---|
| Task list for Workspace & Tenant Closure Lifecycle v1 |
Tasks: Workspace & Tenant Closure Lifecycle v1
Input: Design documents from specs/292-workspace-tenant-closure/
Prerequisites: specs/292-workspace-tenant-closure/spec.md, specs/292-workspace-tenant-closure/plan.md
Tests: REQUIRED (Pest). Keep proof bounded to focused Feature coverage for system directory, admin workspace and tenant surfaces, chooser recovery, and canonical historical viewers.
Operations: Reuse the existing OperationRun start UX and canonical run viewers. No new run type, no queue family, and no local blocked-run substitute are allowed.
RBAC: Wrong-plane or non-member access remains 404; in-scope actors missing capability remain 403. Closure/removal posture is never an authorization shortcut.
Shared Pattern Reuse: Reuse WorkspaceContext, TenantOperabilityService, WorkspaceCommercialLifecycleResolver, BadgeCatalog / BadgeRenderer, current audit infrastructure, and current Filament action-surface patterns.
Filament / Panel Guardrails: Filament remains v5 on Livewire v4. Provider registration remains unchanged in apps/platform/bootstrap/providers.php. No new panel, no new globally searchable resource, and no new asset strategy are allowed.
Organization: Tasks are grouped by user story so workspace closure, tenant removal, and posture clarity remain independently implementable and testable.
Test Governance Checklist
- Lane assignment stays
fast-feedbackandconfidenceand remains the narrowest sufficient proof. - New or changed tests stay in focused
Featurefamilies only unless a bounded implementation seam proves a unit test is necessary. - Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default.
- Planned validation commands cover closure, removal, chooser recovery, and historical viewer legitimacy without widening into browser or heavy-governance lanes.
- The declared surface test profiles remain
standard-native-filament,global-context-shell, andshared-detail-familyonly. - Any drift toward purge, export, billing workflow, or a second mutation plane resolves as
reject-or-split, not hidden scope.
Phase 1: Setup (Shared Context)
Purpose: Confirm the current lifecycle, chooser, and history seams before any runtime change begins.
- T001 Review
specs/292-workspace-tenant-closure/spec.md,specs/292-workspace-tenant-closure/plan.md,specs/262-lifecycle-governance-taxonomy/spec.md,specs/143-tenant-lifecycle-operability-context-semantics/spec.md, andspecs/274-billing-subscription-truth/spec.mdtogether so the slice stays grounded in current lifecycle and commercial truth. - T002 [P] Confirm the current system and admin surface seams in
apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php,apps/platform/app/Filament/System/Pages/Directory/ViewTenant.php,apps/platform/app/Filament/System/Pages/Ops/ViewRun.php,apps/platform/app/Filament/Resources/Workspaces/Pages/ViewWorkspace.php, andapps/platform/app/Filament/Resources/TenantResource.php. - T003 [P] Confirm the chooser and context seams in
apps/platform/app/Support/Workspaces/WorkspaceContext.php,apps/platform/app/Http/Middleware/EnsureWorkspaceSelected.php,apps/platform/app/Support/Middleware/EnsureFilamentTenantSelected.php,apps/platform/app/Filament/Pages/ChooseWorkspace.php, andapps/platform/app/Filament/Pages/ChooseTenant.php. - T004 [P] Confirm the current lifecycle and audit seams in
apps/platform/app/Services/Tenants/TenantOperabilityService.php,apps/platform/app/Services/Entitlements/WorkspaceCommercialLifecycleResolver.php,apps/platform/app/Services/Audit/WorkspaceAuditLogger.php, and the current tenant audit logging path.
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Add the bounded lifecycle truth and write-side seam before surface behavior changes.
Critical: No user-story work should begin until this phase is complete.
- T005 [P] Add failing feature coverage in
apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.phpandapps/platform/tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.phpto lock close/reopen behavior, historical readability, and pre-enqueue blocking. - T006 [P] Add failing feature coverage in
apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.phpandapps/platform/tests/Feature/Filament/Pages/WorkspaceContextClosureRecoveryTest.phpto lock admin read-only posture, chooser recovery, and cleared-context behavior. - T007 [P] Add failing feature coverage in
apps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.phpto lock remove/restore behavior, chooser exclusion, and tenant-context denial rules. - T008 Create
apps/platform/database/migrations/*_add_workspace_closure_fields.phpandapps/platform/database/migrations/*_add_managed_environment_workspace_removal_fields.phpso existing records can store explicit closure and removal truth. - T009 Update
apps/platform/app/Models/Workspace.phpandapps/platform/app/Models/ManagedEnvironment.phpwith casts, bounded helper methods, and relationship accessors for the new lifecycle truth. - T010 Implement
apps/platform/app/Services/Workspaces/WorkspaceLifecycleService.phpas the one bounded orchestration seam for close/reopen and remove/restore plus audit-safe state transitions, and keep membership rows preserved rather than recreated or deleted. - T011 Extend
apps/platform/app/Services/Audit/WorkspaceAuditLogger.phpand the current tenant audit logging path with stable action IDs and metadata for close/reopen and remove/restore. - T012 Update the relevant policy and capability seams so close/reopen and remove/restore enforce server-side authorization with the required
404versus403behavior.
Checkpoint: Workspace and tenant lifecycle truth exists, audit is wired, and write-side behavior is centralized before UI or chooser changes land.
Phase 3: User Story 1 - Close a workspace without losing history (Priority: P1)
Goal: Authorized platform users can close and reopen workspaces explicitly while preserving readable history.
Independent Test: Close a workspace from the system detail page, confirm chooser and action gating update, verify historical viewers remain readable, and reopen the workspace.
Tests for User Story 1
- T013 [P] [US1] Extend
apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.phpto prove confirmation, impact summary, reason capture, clear guard-failure reasons on unsafe close attempts, canonical success or error notification copy, audit metadata, membership preservation, reopen behavior, and blocked mutation or start behavior. - T014 [P] [US1] Extend
apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.phpto prove admin read-only posture, distinct closed versus suspended copy, and the absence of a second workspace-closure mutation plane.
Implementation for User Story 1
- T015 [US1] Update
apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.phpandapps/platform/app/Filament/System/Pages/Ops/ViewRun.phpso the system surfaces render closure posture, impact summary, and keep closed-workspace history readable with canonical success or error notification copy and clear guard-failure messaging on unsafe attempts. - T016 [US1] Update
apps/platform/app/Support/Workspaces/WorkspaceContext.php,apps/platform/app/Http/Middleware/EnsureWorkspaceSelected.php,apps/platform/app/Filament/Pages/ChooseWorkspace.php, andapps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.phpso closed workspaces clear invalid remembered context, route through explicit recovery messaging, and block the in-scope tenant start surface before enqueue. - T017 [US1] Update
apps/platform/app/Filament/Resources/Workspaces/Pages/ViewWorkspace.phpandapps/platform/app/Filament/Pages/Settings/WorkspaceSettings.phpso the admin plane shows read-only closure posture, defers in-scope blocked-state checks toapps/platform/app/Services/Workspaces/WorkspaceLifecycleService.php, and does not expose closure mutation controls.
Checkpoint: Workspace closure becomes an explicit, auditable, read-only posture with preserved historical access.
Phase 4: User Story 2 - Remove a tenant from a workspace without deleting tenant history (Priority: P1)
Goal: Workspace owners can remove and restore tenants from the active workspace set without losing historical legitimacy.
Independent Test: Remove a tenant from the tenant-management surface, confirm chooser and tenant-context routes treat it as non-operable, verify historical viewers still render, and restore the tenant.
Tests for User Story 2
- T018 [P] [US2] Extend
apps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.phpto prove confirmation, impact summary, reason capture, clear guard-failure reasons on unsafe remove attempts, canonical success or error notification copy, audit metadata, membership preservation, restore behavior, chooser exclusion, tenant-context denial, and representative removed-tenant blocked-start no-OperationRunbehavior onapps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.php. - T019 [P] [US2] Extend
apps/platform/tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.phpto prove historical viewers remain readable when the referenced tenant is removed from the workspace.
Implementation for User Story 2
- T020 [US2] Update
apps/platform/app/Filament/Resources/TenantResource.phpand the resource's view-page action surface so remove/restore actions, impact summaries, canonical success or error notification copy, posture badges, and grouped destructive actions follow the spec contract. - T021 [US2] Update
apps/platform/app/Services/Tenants/TenantOperabilityService.php,apps/platform/app/Support/Middleware/EnsureFilamentTenantSelected.php,apps/platform/app/Support/Middleware/DenyNonMemberTenantAccess.php,apps/platform/app/Filament/Pages/ChooseTenant.php, tenant-memory handling inapps/platform/app/Support/Workspaces/WorkspaceContext.php, andapps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.phpso removed tenants are no longer valid active context and cannot enqueue new runs. - T022 [US2] Update
apps/platform/app/Filament/System/Pages/Directory/ViewTenant.phpandapps/platform/app/Filament/System/Pages/Ops/ViewRun.phpso removed tenants remain historically visible with explicit posture and no false not-found behavior.
Checkpoint: Tenant removal becomes explicit, reversible, and historically safe without remaining an active workspace context.
Phase 5: User Story 3 - Distinguish suspended read-only, closed, and removed clearly (Priority: P2)
Goal: Operators can tell which lifecycle posture is blocking them and what next action remains legitimate.
Independent Test: Render admin, system, chooser, and historical surfaces for suspended-read-only, closed, and removed states and verify distinct copy and badges.
Tests for User Story 3
- T023 [P] [US3] Extend
apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.php,apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php, andapps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.phpto prove distinct posture labels, centralized badge mapping, disclosure ordering, blocked-action explanations, and one dominant next action.
Implementation for User Story 3
- T024 [US3] Update posture rendering on
apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php,apps/platform/app/Filament/Resources/Workspaces/Pages/ViewWorkspace.php, andapps/platform/app/Filament/Pages/Settings/WorkspaceSettings.phpsoSuspended read-onlyremains distinct fromClosedand uses shared badge semantics rather than local mappings. - T025 [US3] Update posture rendering on
apps/platform/app/Filament/Resources/TenantResource.php,apps/platform/app/Filament/System/Pages/Directory/ViewTenant.php, and chooser recovery messaging soRemoved from workspaceremains distinct from archive and provider-missing semantics, and keep decision content first with diagnostics secondary.
Checkpoint: Lifecycle posture becomes explicit and non-ambiguous across the affected operator and history surfaces.
Phase 6: Polish & Cross-Cutting Validation
Purpose: Validate the bounded slice and stop without widening scope.
- T026 [P] Run
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/Directory/ViewWorkspaceClosureTest.php tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.php. - T027 [P] Run
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.php tests/Feature/Filament/Pages/WorkspaceContextClosureRecoveryTest.php. - T028 [P] Run
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent. - T029 [P] Review touched code to confirm Filament stays on Livewire v4, provider registration remains unchanged in
apps/platform/bootstrap/providers.php, no globally searchable resource or wider discovery path is added, no asset strategy changes appear, and no second closure-mutation plane slipped in. - T030 [P] Record the final guardrail and test-governance outcome in the implementation close-out without reopening purge, export, billing, or portal scope.
Dependencies & Execution Order
Phase Dependencies
- Phase 1 (Setup): no dependencies; start immediately.
- Phase 2 (Foundational): depends on Phase 1 and blocks all user stories.
- Phase 3 (US1): depends on Phase 2 and establishes explicit workspace closure truth plus chooser recovery.
- Phase 4 (US2): depends on Phase 2 and should land after or alongside US1 so tenant removal composes with the new workspace posture rules.
- Phase 5 (US3): depends on Phases 3 and 4 because it clarifies the final shared posture language.
- Phase 6 (Polish): depends on all desired user stories being complete.
User Story Dependencies
- US1 (P1): independently testable after Phase 2 and delivers the central workspace-closure capability.
- US2 (P1): independently testable after Phase 2 and delivers the central tenant-removal capability.
- US3 (P2): depends on the completed runtime posture rules from US1 and US2.
Within Each User Story
- Write the listed Pest coverage first and make it fail for the intended gap.
- Keep implementation inside the existing model, service, middleware, Filament, and audit seams named above.
- Re-run the narrowest relevant validation command after each story checkpoint before moving on.
Implementation Strategy
Suggested MVP Scope
- MVP = US1 + US2 together. The feature is only trustworthy when workspace closure and tenant removal both exist and historical readability remains intact.
Incremental Delivery
- Complete Phase 1 and Phase 2.
- Deliver US1 so explicit workspace closure and chooser recovery exist.
- Deliver US2 so tenants can be removed or restored without losing history.
- Deliver US3 so posture language across the affected surfaces becomes unambiguous.
- Finish with the focused validation and drift-review tasks in Phase 6.
Team Strategy
- Settle persistence and bounded service shape first.
- Parallelize failing tests within each story before runtime edits.
- Serialize merges around
WorkspaceContext,TenantOperabilityService,ViewWorkspace, andTenantResourceso posture language stays coherent.
Deferred Follow-Ups / Non-Goals
- export-before-delete workflow
- retention and purge governance
- customer self-serve workspace offboarding or billing-driven closure
- provider-level lifecycle expansion beyond the current separate specs
- lifecycle dashboard or workbench surfaces