182 lines
16 KiB
Markdown
182 lines
16 KiB
Markdown
---
|
|
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
|
|
|
|
- [x] Lane assignment stays `fast-feedback` and `confidence` and remains the narrowest sufficient proof.
|
|
- [x] New or changed tests stay in focused `Feature` families only unless a bounded implementation seam proves a unit test is necessary.
|
|
- [x] Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default.
|
|
- [x] Planned validation commands cover closure, removal, chooser recovery, and historical viewer legitimacy without widening into browser or heavy-governance lanes.
|
|
- [x] The declared surface test profiles remain `standard-native-filament`, `global-context-shell`, and `shared-detail-family` only.
|
|
- [x] 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.
|
|
|
|
- [x] 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`, and `specs/274-billing-subscription-truth/spec.md` together so the slice stays grounded in current lifecycle and commercial truth.
|
|
- [x] 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`, and `apps/platform/app/Filament/Resources/TenantResource.php`.
|
|
- [x] 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`, and `apps/platform/app/Filament/Pages/ChooseTenant.php`.
|
|
- [x] 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.
|
|
|
|
- [x] T005 [P] Add failing feature coverage in `apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.php` and `apps/platform/tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.php` to lock close/reopen behavior, historical readability, and pre-enqueue blocking.
|
|
- [x] T006 [P] Add failing feature coverage in `apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php` and `apps/platform/tests/Feature/Filament/Pages/WorkspaceContextClosureRecoveryTest.php` to lock admin read-only posture, chooser recovery, and cleared-context behavior.
|
|
- [x] T007 [P] Add failing feature coverage in `apps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.php` to lock remove/restore behavior, chooser exclusion, and tenant-context denial rules.
|
|
- [x] T008 Create `apps/platform/database/migrations/*_add_workspace_closure_fields.php` and `apps/platform/database/migrations/*_add_managed_environment_workspace_removal_fields.php` so existing records can store explicit closure and removal truth.
|
|
- [x] T009 Update `apps/platform/app/Models/Workspace.php` and `apps/platform/app/Models/ManagedEnvironment.php` with casts, bounded helper methods, and relationship accessors for the new lifecycle truth.
|
|
- [x] T010 Implement `apps/platform/app/Services/Workspaces/WorkspaceLifecycleService.php` as 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.
|
|
- [x] T011 Extend `apps/platform/app/Services/Audit/WorkspaceAuditLogger.php` and the current tenant audit logging path with stable action IDs and metadata for close/reopen and remove/restore.
|
|
- [x] T012 Update the relevant policy and capability seams so close/reopen and remove/restore enforce server-side authorization with the required `404` versus `403` behavior.
|
|
|
|
**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
|
|
|
|
- [x] T013 [P] [US1] Extend `apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.php` to 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.
|
|
- [x] T014 [P] [US1] Extend `apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php` to 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
|
|
|
|
- [x] T015 [US1] Update `apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php` and `apps/platform/app/Filament/System/Pages/Ops/ViewRun.php` so 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.
|
|
- [x] T016 [US1] Update `apps/platform/app/Support/Workspaces/WorkspaceContext.php`, `apps/platform/app/Http/Middleware/EnsureWorkspaceSelected.php`, `apps/platform/app/Filament/Pages/ChooseWorkspace.php`, and `apps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.php` so closed workspaces clear invalid remembered context, route through explicit recovery messaging, and block the in-scope tenant start surface before enqueue.
|
|
- [x] T017 [US1] Update `apps/platform/app/Filament/Resources/Workspaces/Pages/ViewWorkspace.php` and `apps/platform/app/Filament/Pages/Settings/WorkspaceSettings.php` so the admin plane shows read-only closure posture, defers in-scope blocked-state checks to `apps/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
|
|
|
|
- [x] T018 [P] [US2] Extend `apps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.php` to 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-`OperationRun` behavior on `apps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.php`.
|
|
- [x] T019 [P] [US2] Extend `apps/platform/tests/Feature/System/Ops/ClosedWorkspaceHistoricalAccessTest.php` to prove historical viewers remain readable when the referenced tenant is removed from the workspace.
|
|
|
|
### Implementation for User Story 2
|
|
|
|
- [x] T020 [US2] Update `apps/platform/app/Filament/Resources/TenantResource.php` and 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.
|
|
- [x] 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 in `apps/platform/app/Support/Workspaces/WorkspaceContext.php`, and `apps/platform/app/Filament/Widgets/Tenant/TenantReviewPackCard.php` so removed tenants are no longer valid active context and cannot enqueue new runs.
|
|
- [x] T022 [US2] Update `apps/platform/app/Filament/System/Pages/Directory/ViewTenant.php` and `apps/platform/app/Filament/System/Pages/Ops/ViewRun.php` so 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
|
|
|
|
- [x] T023 [P] [US3] Extend `apps/platform/tests/Feature/System/Directory/ViewWorkspaceClosureTest.php`, `apps/platform/tests/Feature/Filament/Resources/Workspaces/WorkspaceClosureStatusTest.php`, and `apps/platform/tests/Feature/Filament/Resources/TenantResource/TenantWorkspaceRemovalTest.php` to prove distinct posture labels, centralized badge mapping, disclosure ordering, blocked-action explanations, and one dominant next action.
|
|
|
|
### Implementation for User Story 3
|
|
|
|
- [x] T024 [US3] Update posture rendering on `apps/platform/app/Filament/System/Pages/Directory/ViewWorkspace.php`, `apps/platform/app/Filament/Resources/Workspaces/Pages/ViewWorkspace.php`, and `apps/platform/app/Filament/Pages/Settings/WorkspaceSettings.php` so `Suspended read-only` remains distinct from `Closed` and uses shared badge semantics rather than local mappings.
|
|
- [x] 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 so `Removed from workspace` remains 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.
|
|
|
|
- [x] 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`.
|
|
- [x] 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`.
|
|
- [x] T028 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`.
|
|
- [x] 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.
|
|
- [x] 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
|
|
|
|
1. Complete Phase 1 and Phase 2.
|
|
2. Deliver US1 so explicit workspace closure and chooser recovery exist.
|
|
3. Deliver US2 so tenants can be removed or restored without losing history.
|
|
4. Deliver US3 so posture language across the affected surfaces becomes unambiguous.
|
|
5. Finish with the focused validation and drift-review tasks in Phase 6.
|
|
|
|
### Team Strategy
|
|
|
|
1. Settle persistence and bounded service shape first.
|
|
2. Parallelize failing tests within each story before runtime edits.
|
|
3. Serialize merges around `WorkspaceContext`, `TenantOperabilityService`, `ViewWorkspace`, and `TenantResource` so 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 |