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

61 lines
5.0 KiB
Markdown

# 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.