TenantAtlas/specs/279-workspace-managed-environment-core/tasks.md
ahmido e64bae9cfc feat: cut over tenant core to managed environments (#335)
## Summary
- replace the legacy Tenant and TenantMembership core models with ManagedEnvironment and ManagedEnvironmentMembership
- propagate the managed environment naming and key changes across Filament resources, pages, controllers, jobs, models, and supporting runtime paths
- add feature 279 spec artifacts and focused managed-environment test coverage for model behavior, route binding, panel context, authorization, and legacy guardrails

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentAuthorizationTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentModelTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- branch pushed from commit `1123b122`
- browser smoke test file was added but not run in this pass

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #335
2026-05-07 06:38:14 +00:00

16 KiB

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

  • Lane assignment stays fast-feedback, confidence, and one narrow browser lane.
  • New or changed tests stay in apps/platform/tests/Unit/ManagedEnvironment/, apps/platform/tests/Feature/ManagedEnvironment/, and one narrow browser smoke file only.
  • Fixture replacement stays explicit; no tenant compatibility fixtures remain as defaults.
  • Planned validation commands match spec.md, plan.md, and quickstart.md exactly.
  • The /admin/t/{environment} path retention is tracked as an exception note, not as an uncontrolled compatibility layer.
  • 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.

  • 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.
  • 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.
  • T002 [P] Confirm the current core seam in apps/platform/app/Models/Tenant.php, Workspace.php, and the current tenant-membership model family.
  • 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.
  • 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.
  • 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.

  • 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.
  • T006 [P] Add failing unit coverage in apps/platform/tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php for current workspace plus managed-environment resolution.
  • T007 [P] Add failing feature coverage in apps/platform/tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php and ManagedEnvironmentAuthorizationTest.php for 404 versus 403 semantics.
  • 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.
  • T009 [P] Add the narrow browser smoke in apps/platform/tests/Browser/Spec279ManagedEnvironmentCoreCutoverSmokeTest.php for workspace selection, managed-environment selection, and dashboard boot.
  • T010 Create the new ManagedEnvironment model, factory, migration(s), and managed-environment membership truth with no compatibility columns.
  • 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

  • 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

  • T013 [US1] Update Workspace and related root models so the primary managed-target relationship becomes managedEnvironments() rather than tenants().
  • 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.
  • T015 [US1] Replace current route-model binding, current-target resolution, and membership-aware target lookup so they resolve ManagedEnvironment instead of Tenant.
  • 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

  • T017 [P] [US2] Extend ManagedEnvironmentPanelContextTest.php to cover chooser state, shell context chips, and current-target route builders.

Implementation for User Story 2

  • T018 [US2] Update the current tenant chooser page and related context UI so operators choose managed environments inside the active workspace.
  • 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.
  • T020 [US2] Retarget tenant-scoped query helpers, global-search scoping, environment-bound widgets, and OperationRunLinks to the new managed-environment context.
  • 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

  • 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

  • T023 [US3] Update commands, fixtures, factories, policies, and support helpers that still instantiate or search the active managed target through Tenant.
  • 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.
  • 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.

  • 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).
  • 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).
  • 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).
  • 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).
  • 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.
  • 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.
  • 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.