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

6.1 KiB

Data Model: Workspace-first Managed Environment Core Cutover

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

Overview

This slice introduces one new managed-target root record and replaces the current tenant-core anchor. Workspace remains the primary SaaS context. ManagedEnvironment becomes the environment-scoped root record under a workspace. Current environment-scoped records retarget from tenant_id to managed_environment_id in core-owned paths only, with no compatibility columns.

New Persisted Truth

1. Managed Environment

Persistence: new managed_environments table
Ownership: managed-target root scoped to one workspace
Lifecycle: current-release core entity

Field Type Nullable Notes
id bigint no Internal primary key
workspace_id bigint no Required parent workspace
slug string no Neutral route key inside the workspace
name string no Internal canonical name
display_name string yes Operator-facing label when it differs from name
kind string no Bounded current-release category for the managed target
lifecycle_status string no Selectability and lifecycle posture for current context
metadata jsonb yes Provider-neutral environment metadata only
created_at timestamp yes Standard timestamp
updated_at timestamp yes Standard timestamp

Rules:

  • ManagedEnvironment must not store Microsoft-specific identity, Graph, or Intune fields.
  • metadata may store only neutral presentation or lifecycle hints such as internal labels, neutral tags, or operator notes; it must not store provider tenant IDs, domains, Graph scopes, consent identifiers, or raw provider profiles.
  • The route key should be neutral and operator-safe.
  • Archived or inactive environments are not selectable current context by default.

2. Managed Environment Membership

Persistence: renamed or replaced environment-membership table
Ownership: environment-scoped access truth

Field Type Nullable Notes
id bigint no Internal primary key
user_id bigint no Member actor
managed_environment_id bigint no Environment scope
role string no Existing role semantics preserved in this slice
source string yes Existing source semantics preserved where still needed
source_ref string yes Existing external source reference if still used
created_by_user_id bigint yes Existing audit-facing author field if still used
created_at timestamp yes Standard timestamp
updated_at timestamp yes Standard timestamp

Rules:

  • This slice preserves current membership semantics; it only changes the scoped target noun and foreign key.
  • Workspace membership remains the first access boundary.

Retargeted Existing Truth

3. Workspace Relation

Workspace changes from hasMany(Tenant::class) to hasMany(ManagedEnvironment::class).

4. Environment-scoped Foreign-Key Contract

Current environment-scoped records move from tenant_id to managed_environment_id in core-owned paths only.

This package intentionally treats the precise table list as implementation inventory driven by current repo truth through TenantOwnedModelFamilies plus schema grep. The retargeting set is limited to current core-owned model families that use tenant_id as the active managed-target key in:

  • current root-selection, membership, and current-context families
  • current panel/query/helper seams that need the new managed-target key to resolve scope honestly
  • current commands, fixtures, and tests that resolve active target scope directly through tenant_id

Rules:

  • no dual columns
  • no tenant_id plus managed_environment_id overlap
  • no alias relationships that keep both nouns active

Derived Runtime Contracts

5. Current Context Contract

Persistence: existing context/session helpers, retargeted
Owner: workspace + managed-environment selection flow

Field Type Required Notes
current_workspace_id int yes Existing primary SaaS context
current_managed_environment_id int yes Replaces current tenant-scoped active target
current_managed_environment_slug string yes Route-safe current target key

Rules:

  • The app must not keep an active current-tenant contract in parallel.
  • Existing chooser and panel-shell flows resolve through workspace plus managed environment together.

6. Temporary Environment Shell Route Contract

Persistence: none, route-model binding only
Owner: current environment-scoped panel shell

Field Type Required Notes
path_family string yes Temporarily /admin/t/{environment}
bound_model string yes ManagedEnvironment
exception_owner string yes Spec 279, closed by Spec 280

Rules:

  • this is the only allowed public-path exception in this slice
  • the path family must not coexist with a second compatibility route family
  • the route parameter meaning changes from tenant to managed environment immediately

Boundaries Explicitly Preserved

  • Workspace remains the primary SaaS context.
  • Provider-specific identity remains outside ManagedEnvironment.
  • Provider-connection extraction and broader governance-artifact retargeting remain follow-up work for Specs 281 and 282.
  • Broader workspace-first route-family and breadcrumb rewrite remain Spec 280.
  • Provider-profile extraction remains Spec 281.
  • Artifact retargeting polish remains Spec 282.
  • RBAC redesign remains Spec 285.
  • Copy/localization neutralization remains Spec 286.

Cutover Invariants

  • No active App\Models\Tenant remains in core-owned paths after implementation.
  • No ->tenant(Tenant::class) Filament tenant binding remains.
  • No tenant_id compatibility columns remain in the cutover set.
  • No Microsoft-specific identity fields land on ManagedEnvironment.
  • The only temporary exception is the public /admin/t/{environment} path family until Spec 280.