200 lines
16 KiB
Markdown
200 lines
16 KiB
Markdown
---
|
|
description: "Task list for Workspace-first Managed Environment Core Cutover"
|
|
---
|
|
|
|
# Tasks: Workspace-first Managed Environment Core Cutover
|
|
|
|
**Input**: Design documents from `specs/279-workspace-managed-environment-core/`
|
|
**Prerequisites**: `specs/279-workspace-managed-environment-core/spec.md`, `specs/279-workspace-managed-environment-core/plan.md`, `specs/279-workspace-managed-environment-core/checklists/requirements.md`, `specs/279-workspace-managed-environment-core/checklists/constitution-scope-001-exception.md`, `specs/279-workspace-managed-environment-core/research.md`, `specs/279-workspace-managed-environment-core/data-model.md`, `specs/279-workspace-managed-environment-core/quickstart.md`, `specs/279-workspace-managed-environment-core/contracts/managed-environment-core-cutover.logical.openapi.yaml`
|
|
|
|
**Tests**: REQUIRED (Pest). Keep proof bounded to one managed-environment unit family, one managed-environment feature family, one narrow browser smoke, and one legacy-core guard family.
|
|
**Operations**: No new `OperationRun` family. Existing operation links must resolve the new managed-environment context correctly.
|
|
**RBAC**: Workspace membership remains the first `404` boundary. Managed-environment membership remains the second `404` boundary. In-scope capability denials stay `403`.
|
|
**Shared Pattern Reuse**: Reuse `WorkspaceContext`, existing panel-provider seams, current query helpers, `TenantOwnedModelFamilies`, and `OperationRunLinks`. Do not create an adapter layer or second context stack.
|
|
**Filament / Panel Guardrails**: Filament remains v5 on Livewire v4. Provider registration remains unchanged in `apps/platform/bootstrap/providers.php`. No new panel, no second public route family, and no new asset strategy are allowed.
|
|
**Organization**: Tasks are grouped by user story so core entity cutover, panel/context rebinding, and legacy-core removal remain independently reviewable.
|
|
**Review Outcome**: `documentation-required-exception`
|
|
**Workflow Outcome**: `keep`
|
|
**Test-governance Outcome**: `keep`
|
|
|
|
## Test Governance Checklist
|
|
|
|
- [x] Lane assignment stays `fast-feedback`, `confidence`, and one narrow `browser` lane.
|
|
- [x] New or changed tests stay in `apps/platform/tests/Unit/ManagedEnvironment/`, `apps/platform/tests/Feature/ManagedEnvironment/`, and one narrow browser smoke file only.
|
|
- [x] Fixture replacement stays explicit; no tenant compatibility fixtures remain as defaults.
|
|
- [x] Planned validation commands match `spec.md`, `plan.md`, and `quickstart.md` exactly.
|
|
- [x] The `/admin/t/{environment}` path retention is tracked as an exception note, not as an uncontrolled compatibility layer.
|
|
- [x] Any attempt to absorb Spec `280`-`287` work resolves as `split` or `reject-or-split`, not hidden scope.
|
|
|
|
## Phase 1: Setup (Shared Context)
|
|
|
|
**Purpose**: Confirm the current tenant-core seams and the bounded cutover inventory before runtime changes begin.
|
|
|
|
- [x] T001 Review `specs/279-workspace-managed-environment-core/spec.md`, `plan.md`, `checklists/requirements.md`, `research.md`, `data-model.md`, and `quickstart.md` together so the slice stays on the first reserved cutover only.
|
|
- [x] T001a Before any implementation-phase task starts, confirm `specs/279-workspace-managed-environment-core/checklists/constitution-scope-001-exception.md` still governs the cutover or replace it with the actual `.specify/memory/constitution.md` amendment reference; if neither exists, stop the implementation loop.
|
|
- [x] T002 [P] Confirm the current core seam in `apps/platform/app/Models/Tenant.php`, `Workspace.php`, and the current tenant-membership model family.
|
|
- [x] T003 [P] Confirm the current panel and current-context seam in `apps/platform/app/Providers/Filament/TenantPanelProvider.php`, `ChooseTenant.php`, `WorkspaceContext.php`, and the tenant-context helper traits.
|
|
- [x] T004 [P] Use `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php` plus a bounded schema grep to enumerate the cutover set that still relies on `tenant_id` as active managed-target truth.
|
|
- [x] T004a [P] Record explicit Spec `281` and `282` exclusions so provider-connection extraction and broader governance-artifact retargeting do not drift into the 279 implementation loop.
|
|
|
|
---
|
|
|
|
## Phase 2: Foundational (Blocking Prerequisites)
|
|
|
|
**Purpose**: Lock the new core entity, membership truth, and proving seams before panel and route rebinding begins.
|
|
|
|
**Critical**: No user-story work should begin until this phase is complete.
|
|
|
|
- [x] T005 [P] Add failing unit coverage in `apps/platform/tests/Unit/ManagedEnvironment/ManagedEnvironmentModelTest.php` for workspace relation, route key, selectability, and provider-neutral field rules.
|
|
- [x] T006 [P] Add failing unit coverage in `apps/platform/tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php` for current workspace plus managed-environment resolution.
|
|
- [x] T007 [P] Add failing feature coverage in `apps/platform/tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php` and `ManagedEnvironmentAuthorizationTest.php` for `404` versus `403` semantics.
|
|
- [x] T008 [P] Add failing feature coverage in `apps/platform/tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php` for chooser-to-shell context bootstrapping on the temporary `/admin/t/{environment}` path.
|
|
- [x] T009 [P] Add the narrow browser smoke in `apps/platform/tests/Browser/Spec279ManagedEnvironmentCoreCutoverSmokeTest.php` for workspace selection, managed-environment selection, and dashboard boot.
|
|
- [x] T010 Create the new `ManagedEnvironment` model, factory, migration(s), and managed-environment membership truth with no compatibility columns.
|
|
- [x] T011 Replace or rename the current environment-membership seam so current capability semantics apply to managed environments without broad RBAC redesign.
|
|
|
|
**Checkpoint**: The new managed-target root and proving seams exist before shared runtime context changes begin.
|
|
|
|
---
|
|
|
|
## Phase 3: User Story 1 - Resolve managed environments as the active target inside a workspace (Priority: P1)
|
|
|
|
**Goal**: `ManagedEnvironment` becomes the active managed-target root and current core paths stop depending on `Tenant`.
|
|
|
|
**Independent Test**: Create a workspace plus managed environment, resolve the route key and current context, and confirm no active `Tenant` model is needed in the core path.
|
|
|
|
### Tests for User Story 1
|
|
|
|
- [x] T012 [P] [US1] Extend the managed-environment unit and feature tests to cover archived/inactive environments and wrong-workspace resolution.
|
|
|
|
### Implementation for User Story 1
|
|
|
|
- [x] T013 [US1] Update `Workspace` and related root models so the primary managed-target relationship becomes `managedEnvironments()` rather than `tenants()`.
|
|
- [x] T014 [US1] Retarget the core schema and Eloquent relations from `tenant_id` to `managed_environment_id` across the cutover set identified in Phase 1, using destructive pre-production migrations only and keeping the explicit Spec `281` and `282` exclusions intact.
|
|
- [x] T015 [US1] Replace current route-model binding, current-target resolution, and membership-aware target lookup so they resolve `ManagedEnvironment` instead of `Tenant`.
|
|
- [x] T016 [US1] Remove active `App\Models\Tenant` core usage and replace tenant-specific factories, seeders, and policy anchors with managed-environment equivalents.
|
|
|
|
**Checkpoint**: The app has one active managed-target root entity and no mixed core noun in the main data path.
|
|
|
|
---
|
|
|
|
## Phase 4: User Story 2 - Keep current environment-scoped surfaces operable through the cutover (Priority: P1)
|
|
|
|
**Goal**: The current environment-scoped shell continues to work while binding `ManagedEnvironment` instead of `Tenant`.
|
|
|
|
**Independent Test**: Select a workspace, enter a managed environment through the retargeted chooser, and open the current environment dashboard through the temporary shell.
|
|
|
|
### Tests for User Story 2
|
|
|
|
- [x] T017 [P] [US2] Extend `ManagedEnvironmentPanelContextTest.php` to cover chooser state, shell context chips, and current-target route builders.
|
|
|
|
### Implementation for User Story 2
|
|
|
|
- [x] T018 [US2] Update the current tenant chooser page and related context UI so operators choose managed environments inside the active workspace.
|
|
- [x] T019 [US2] Update the current tenant-panel shell and shared tenant-context helper seams so the bound model becomes `ManagedEnvironment` while the `/admin/t/{environment}` path remains the only documented temporary exception and the final `Workspace` Filament-tenancy switch stays deferred to Spec `280`.
|
|
- [x] T020 [US2] Retarget tenant-scoped query helpers, global-search scoping, environment-bound widgets, and `OperationRunLinks` to the new managed-environment context.
|
|
- [x] T021 [US2] Keep broader workspace-first public routing, navigation, breadcrumbs, and copy cleanup explicitly out of scope and record any unavoidable temporary copy drift for Spec `280` or `286`.
|
|
|
|
**Checkpoint**: Existing environment-scoped operator surfaces still boot and scope correctly on the new core entity.
|
|
|
|
---
|
|
|
|
## Phase 5: User Story 3 - Remove active tenant-core drift from schema, policies, and tests (Priority: P2)
|
|
|
|
**Goal**: Core-owned code, tests, and guardrails stop reintroducing `Tenant` as platform-core truth.
|
|
|
|
**Independent Test**: Run the legacy-core guard suite and the grep validation to confirm no active `Tenant` core model or Filament tenant binding remains.
|
|
|
|
### Tests for User Story 3
|
|
|
|
- [x] T022 [P] [US3] Add failing guard coverage in `apps/platform/tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php` for active `App\Models\Tenant` imports, `->tenant(Tenant::class)` panel binding, and active `tenant_id` usage inside the T004 core-owned cutover inventory only.
|
|
|
|
### Implementation for User Story 3
|
|
|
|
- [x] T023 [US3] Update commands, fixtures, factories, policies, and support helpers that still instantiate or search the active managed target through `Tenant`.
|
|
- [x] T024 [US3] Add bounded search-based validation for lingering core `Tenant` references, document the only approved temporary `/admin/t/{environment}` path exception, and record the explicit Spec `281` and `282` residual allowlist for any remaining non-core `tenant_id` hits.
|
|
- [x] T025 [US3] Ensure `ManagedEnvironment` stays provider-neutral and that provider-specific identity remains in provider-owned seams only.
|
|
|
|
**Checkpoint**: The cutover leaves no uncontrolled tenant-core drift behind.
|
|
|
|
---
|
|
|
|
## Phase 6: Polish & Cross-Cutting Validation
|
|
|
|
**Purpose**: Validate the bounded cutover and stop before the broader reserved pack is absorbed.
|
|
|
|
- [x] T026 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Unit/ManagedEnvironment/ManagedEnvironmentModelTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php)`.
|
|
- [x] T027 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentAuthorizationTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php)`.
|
|
- [x] T028 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail artisan test --compact tests/Browser/Spec279ManagedEnvironmentCoreCutoverSmokeTest.php)`.
|
|
- [x] T029 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && (cd "$REPO_ROOT/apps/platform" && ./vendor/bin/sail bin pint --dirty --format agent)`.
|
|
- [x] T030 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings 'App\Models\Tenant' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/database"` and `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n -- '->tenant\(Tenant::class' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/database"` and confirm only approved removed-path output remains.
|
|
- [x] T031 [P] Review touched code to confirm Filament stays on Livewire v4, provider registration remains unchanged in `apps/platform/bootstrap/providers.php`, any touched globally searchable resource still has edit/view eligibility or remains out of global search, no new asset registration or deployment-step change is introduced, no second public route family appears, no provider-specific identity lands on `ManagedEnvironment`, and any touched destructive actions still preserve `->requiresConfirmation()` plus current authorization.
|
|
- [x] T032 [P] Record the final guardrail and test-governance outcome in the active feature close-out, including the temporary `/admin/t/{environment}` exception and the mandatory follow-up ownership for Spec `280`.
|
|
|
|
---
|
|
|
|
## Dependencies & Execution Order
|
|
|
|
### Phase Dependencies
|
|
|
|
- **Phase 1 (Setup)**: no dependencies; start immediately.
|
|
- **Phase 2 (Foundational)**: depends on Phase 1, including T001a with an actual constitution-amendment reference or approved-exception artifact path, and blocks all user-story work.
|
|
- **Phase 3 (US1)**: depends on Phase 2 and establishes the new managed-target truth.
|
|
- **Phase 4 (US2)**: depends on Phase 2 and should land after US1 so the shell binds the finished core entity.
|
|
- **Phase 5 (US3)**: depends on US1 and US2 so guard checks prove the final core path, not an intermediate state.
|
|
- **Phase 6 (Polish)**: depends on all desired user stories being complete.
|
|
|
|
### User Story Dependencies
|
|
|
|
- **US1 (P1)**: independently testable after Phase 2 and is the first required cutover slice.
|
|
- **US2 (P1)**: independently testable after Phase 2 but should ship with US1 so the current shell remains operable.
|
|
- **US3 (P2)**: independently testable after US1 and US2 and closes the lingering legacy-core drift.
|
|
|
|
### Within Each User Story
|
|
|
|
- Write the listed Pest coverage first and make it fail for the intended gap.
|
|
- Keep implementation inside current core-owned seams and do not widen into broader route/IA/provider/artifact/RBAC follow-up work.
|
|
- Re-run the narrowest relevant validation command after each story checkpoint before moving on.
|
|
|
|
---
|
|
|
|
## Implementation Strategy
|
|
|
|
### Suggested MVP Scope
|
|
|
|
- MVP = **US1 + US2 together**. The cutover is only reviewable if the new core entity exists and the current shell still boots on it.
|
|
|
|
### Incremental Delivery
|
|
|
|
1. Complete Phase 1 and Phase 2.
|
|
2. Deliver US1 so the managed-target core is replaced.
|
|
3. Deliver US2 so operators can still enter the environment-scoped shell.
|
|
4. Deliver US3 to remove lingering legacy drift and lock guardrails.
|
|
5. Finish with the focused validation and exception close-out in Phase 6.
|
|
|
|
### Team Strategy
|
|
|
|
1. Settle schema, model, and current-context rules first.
|
|
2. Parallelize failing unit and feature test authoring before runtime edits.
|
|
3. Serialize merges around panel-provider and context-helper files so the temporary route exception does not drift.
|
|
|
|
---
|
|
|
|
## Deferred Follow-Ups / Non-Goals
|
|
|
|
- workspace-first public route-family rewrite and environment dashboard split
|
|
- provider-profile extraction and provider-scope normalization
|
|
- governance artifact naming/route retargeting polish
|
|
- RBAC scope redesign and new capability families
|
|
- copy/localization neutralization
|
|
- long-lived cutover quality gates beyond feature-local guard checks
|
|
|
|
## Implementation Close-Out Notes
|
|
|
|
- Completed implementation keeps Filament v5 on Livewire v4 and leaves provider registration unchanged in `apps/platform/bootstrap/providers.php`.
|
|
- The current `/admin/t/{environment}` shell remains the only temporary route exception; it now binds `ManagedEnvironment` by slug.
|
|
- `ManagedEnvironment` is provider-neutral: Microsoft/Graph identity resolves through provider-owned seams such as `provider_connections`.
|
|
- Legacy-core guard coverage confirms no exact `use App\Models\Tenant;` import, no `->tenant(Tenant::class)` binding, and no `tenant_id` column in the first-slice core tables.
|
|
- Browser smoke path covered workspace-scoped managed-environment selection through `ChooseTenant::getUrl(panel: 'admin')` into `/admin/t/spec-279-production`.
|
|
- Validation completed with the planned unit, feature, browser, Pint, syntax, and bounded regression checks; the broad planned `App\Models\Tenant` grep still returns approved longer model names such as `TenantReview`, `TenantPermission`, and `TenantOnboardingSession`.
|