TenantAtlas/specs/279-workspace-managed-environment-core/research.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

5.0 KiB

Research: Workspace-first Managed Environment Core Cutover

Date: 2026-05-06
Branch: 279-workspace-managed-environment-core

Decision 1: Use one breaking in-place cutover with no Tenant compatibility layer

  • Decision: Replace Tenant as the active managed-target core directly instead of introducing alias models, dual-read paths, or dual-write migrations.
  • Rationale: The repo is still pre-production, the constitution explicitly rejects speculative compatibility paths, and the current coupling spans too many seams for an adapter layer to stay honest.
  • Alternatives considered:
    • Tenant wrapper over ManagedEnvironment: rejected because it would preserve the wrong core truth and spread mixed nouns.
    • dual columns (tenant_id plus managed_environment_id): rejected because it would violate the pre-production lean doctrine and make later specs harder, not easier.

Decision 2: Keep the current /admin/t/{environment} path temporarily as the only bounded exception

  • Decision: Allow the existing public /admin/t/{environment} path family to remain temporarily while rebinding it to ManagedEnvironment.
  • Rationale: The current cutover already replaces the core entity, memberships, query helpers, and panel binding. Folding the full workspace-first public route rewrite into the same slice would collapse Spec 280 into 279 and make the first cutover package too broad.
  • Alternatives considered:
    • immediate public route-family rewrite: rejected because it belongs to Spec 280 and would widen review scope too far.
    • second compatibility route family: rejected because the cutover must not carry two public path families at once.

Decision 3: Replace current tenant-context helpers in place instead of layering new adapters

  • Decision: Retarget or rename the existing tenant-context seams (WorkspaceContext, Filament panel binding, resource query helpers, global-search helpers, route builders) in place.
  • Rationale: The current helper seams are the correct ownership points. A new parallel ManagedEnvironmentContext layer wrapped around tenant helpers would create drift immediately.
  • Alternatives considered:
    • keep tenant helpers and add environment adapters: rejected because it creates a second context vocabulary.
    • local page-by-page context replacement: rejected because the problem is cross-cutting and shared.

Decision 4: Keep ManagedEnvironment provider-neutral and defer provider extraction to Spec 281

  • Decision: ManagedEnvironment owns neutral managed-target identity only. Provider-specific fields such as Entra tenant IDs, Graph configuration, domains, or consent details stay outside the new root entity.
  • Rationale: The whole point of the cutover is to stop provider-specific semantics from defining the platform core. The repo already has provider-owned seams that can carry this data until Spec 281 normalizes them.
  • Alternatives considered:
    • copy current Tenant provider fields to ManagedEnvironment: rejected because it would deepen Microsoft coupling.
    • extract provider profiles in the same slice: rejected because Spec 281 already owns that follow-up.

Decision 5: Retarget membership semantics without broad RBAC redesign

  • Decision: Replace current tenant-membership truth with managed-environment membership truth while preserving current workspace and capability semantics.
  • Rationale: The cutover needs environment-scoped access control to keep current pages safe, but a broader RBAC scope redesign is already reserved for Spec 285.
  • Alternatives considered:
    • leave memberships tenant-shaped temporarily: rejected because the active root model would still leak tenant-core assumptions.
    • widen capabilities or role families now: rejected because that would collapse Spec 285 into the core cutover.

Decision 6: Use unit + feature + browser + guard checks as the narrowest honest proof

  • Decision: Plan one managed-environment unit family, one feature family, one browser smoke, and one legacy-core guard family.
  • Rationale: The cutover changes both internal identity rules and end-to-end context selection. Feature tests alone are not enough to prove the shell/chooser still works, and browser coverage alone would hide legacy-core drift.
  • Alternatives considered:
    • feature tests only: rejected because the cutover changes end-to-end context entry.
    • heavy-governance or multi-browser rollout: rejected because the slice is core infrastructure, not new multi-surface behavior.

Final Research Outcome

  • 279 should remain the breaking core entity cutover only.
  • The only allowed public-path deviation is temporary /admin/t/{environment} retention while it binds ManagedEnvironment.
  • Existing tenant-context seams should be replaced in place, not wrapped.
  • ManagedEnvironment must stay provider-neutral.
  • Membership semantics move with the core entity, but broader RBAC redesign remains deferred.
  • Unit, feature, browser, and guard coverage together are the narrowest honest proof.