TenantAtlas/specs/279-workspace-managed-environment-core/spec.md
Ahmed Darrazi 1123b122d9
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 7m13s
feat: cut over tenant core to managed environments
2026-05-07 08:35:42 +02:00

34 KiB
Raw Blame History

Feature Specification: Workspace-first Managed Environment Core Cutover

Feature Branch: 279-workspace-managed-environment-core
Created: 2026-05-06
Status: Ready with approved feature-local exception
Input: User description: "Use the next unspecced reserved cutover slot from the roadmap/spec-candidate pack and prepare the Workspace-first Managed Environment Core Cutover package as the next bounded implementation-ready spec."

Spec Candidate Check

  • Problem: TenantPilot still treats Tenant as the active managed-target core across models, route binding, Filament tenancy, memberships, query helpers, and operator context. That blocks the planned workspace-first / provider-neutral evolution because the platform core still assumes the managed target is a Microsoft-shaped tenant instead of a generic managed environment inside a workspace.
  • Today's failure: Current repo seams such as TenantPanelProvider, Tenant, ProviderConnection::tenant(), tenant-owned query helpers, Filament::getTenant() usage, and many tenant_id foreign keys force every new workspace-first or provider-neutral change to either deepen Tenant coupling or add compatibility shims the constitution explicitly rejects.
  • User-visible improvement: Operators and future features get one consistent managed-target identity inside a workspace. Context selection, authorization boundaries, route binding, and current environment-scoped surfaces stop depending on Tenant as platform-core truth.
  • Smallest enterprise-capable version: Replace Tenant as the active managed-target core with ManagedEnvironment, retarget current core foreign-key anchors and context helpers to managed_environment_id, keep the existing panel bootable by temporarily rebinding the current /admin/t/{environment} path family to ManagedEnvironment, and defer the public workspace-first route/IA rewrite, provider-profile extraction, artifact retargeting refinements, and RBAC scope redesign to follow-up specs 280-287.
  • Explicit non-goals: No dual-read or dual-write compatibility layer, no legacy Tenant alias model, no production-data backfill strategy, no full workspace-first public route-family rewrite, no provider-profile extraction, no artifact-language rewrite, no package engine, no guided-operations layer, and no speculative multi-provider framework.
  • Permanent complexity imported: One new managed-target root entity, one breaking schema cutover from tenant_id to managed_environment_id, one renamed environment-membership seam, existing context-helper replacement, and focused unit/feature/browser plus guard-test coverage.
  • Why now: 279 is the first unspecced reserved slot in the roadmap-backed cutover pack, and every later cutover spec (280-287) depends on this core replacement. Waiting adds more Tenant- and Microsoft-specific coupling to the platform core.
  • Why not local: The problem spans schema, Eloquent relations, route binding, Filament tenancy, current-context resolution, authorization helpers, commands, and tests. A local rename or adapter would immediately drift.
  • Approval class: Core Enterprise
  • Red flags triggered: New persisted truth, new state family, many touched seams, and a foundation-sounding cutover. Defense: this is current-release architecture truth, not speculative extensibility; it explicitly forbids compatibility shims and defers broader route, copy, provider, and artifact follow-through to the next reserved specs.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 1 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 9/12
  • Decision: approve

Spec Scope Fields

  • Scope: workspace
  • Primary Routes:
    • existing workspace chooser route under /admin
    • existing tenant chooser surface, retargeted to managed-environment selection
    • current environment-scoped panel routes under /admin/t/{environment} as a temporary bounded exception until Spec 280 replaces the public path family
    • current admin resource/detail routes that bind the managed target model directly or derive environment context from it
  • Data Ownership:
    • Workspace remains the primary SaaS and organization context
    • ManagedEnvironment becomes the new managed-target root record inside a workspace
    • current core-owned managed-target anchors and context-owned relations retarget from tenant_id to managed_environment_id; provider-connection extraction and broader governance-artifact retargeting remain follow-up work for Specs 281 and 282
  • RBAC:
    • workspace membership remains the first isolation boundary
    • current tenant-membership semantics are retargeted to managed-environment membership semantics without widening role scope in this spec
    • wrong-workspace and non-member access remain 404
    • in-scope actors missing a capability remain 403

Canonical-view handling for current admin surfaces:

  • Default filter behavior when tenant-context is active: current canonical admin views continue to prefilter to the active managed environment whenever they currently prefilter to the active tenant; broader workspace-first canonical-view semantics remain Spec 280 follow-up work
  • Explicit entitlement checks preventing cross-tenant leakage: any route, query helper, or global-search path that currently resolves tenant scope must resolve the active managed environment plus current workspace membership before revealing environment-bound records

Cross-Cutting / Shared Pattern Reuse

  • Cross-cutting feature?: yes
  • Interaction class(es): context selection, route links, global-search scoping, current-target chips, resource query helpers, and environment-bound deep links
  • Systems touched: TenantPanelProvider, WorkspaceContext, ChooseTenant, ResolvesPanelTenantContext, InteractsWithTenantOwnedRecords, ScopesGlobalSearchToTenant, TenantOwnedModelFamilies, OperationRunLinks, current tenant widgets, and tenant-scoped resources/pages
  • Existing pattern(s) to extend: workspace-first context storage, current Filament panel-provider seams, current deny-as-not-found membership enforcement, and existing environment-bound route builders
  • Shared contract / presenter / builder / renderer to reuse: existing WorkspaceContext, panel-provider registration, current resource query scoping helpers, OperationRunLinks, and the existing workspace capability resolver
  • Why the existing shared path is sufficient or insufficient: those seams are sufficient as cutover points, but insufficient because they still encode Tenant as the platform-core managed target
  • Exception type: Cross-panel Canonical Route Exception
  • Allowed deviation and why: one bounded deviation is allowed: the current /admin/t/{environment} shell may remain temporarily while binding ManagedEnvironment instead of Tenant, even though the source-pack end state moves Filament tenancy to Workspace in Spec 280. This temporary bridge exists only to keep the runtime operable while Tenant is removed from the core. No second compatibility route family is allowed.
  • Reason block: only one canonical surface makes sense during the cutover. Keeping the existing shell avoids a second public route family, keeps shell transition explicit, preserves truthful scope signals, and leaves final canonical Workspace tenancy to Spec 280.
  • Dedicated proof: apps/platform/tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php, apps/platform/tests/Browser/Spec279ManagedEnvironmentCoreCutoverSmokeTest.php, and specs/279-workspace-managed-environment-core/checklists/constitution-scope-001-exception.md
  • Consistency impact: route keys, chooser labels, context bars, global-search scope resolution, tenant-owned query helpers, and deep-link builders must all agree on ManagedEnvironment as the active managed target
  • Review focus: reviewers must verify that the cutover replaces current shared seams in place, that the temporary /admin/t path is the only documented exception, and that no alias model or second context stack appears

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: yes, link semantics only
  • Shared OperationRun UX contract/layer reused: OperationRunLinks and the existing OperationRun URL-resolution helpers
  • Delegated start/completion UX behaviors: tenant/workspace-safe environment link resolution only; no new queued toasts, start events, completion notifications, or dedupe messaging are added in this slice
  • Local surface-owned behavior that remains: none; existing surfaces continue to use the central OperationRun link helpers after their context model is retargeted
  • Queued DB-notification policy: N/A
  • Terminal notification path: N/A
  • Exception required?: yes - the temporary /admin/t/{environment} path retention described above. This is a bounded route exception only and does not permit a second compatibility family.

Provider Boundary / Platform Core Check

  • Shared provider/platform boundary touched?: yes
  • Boundary classification: mixed
  • Seams affected: managed-target identity, provider-connection foreign-key anchors, current context model, operator vocabulary, route binding, and current target selection
  • Neutral platform terms preserved or introduced: workspace, managed environment, provider connection, target scope, operation, finding, review, and governance artifact
  • Provider-specific semantics retained and why: Microsoft-specific identifiers such as entra_tenant_id, Graph consent details, and portal metadata may remain in provider-owned tables or provider metadata until Spec 281 extracts and normalizes them. They must not live on ManagedEnvironment.
  • Why this does not deepen provider coupling accidentally: the core cutover explicitly forbids Microsoft-specific identity, Graph, or Intune fields on ManagedEnvironment and replaces Tenant as the shared core noun
  • Follow-up path: Spec 281 for provider-profile extraction, Spec 284 for provider-neutral artifact-source taxonomy, and Spec 286 for copy/localization cleanup

UI / Surface Guardrail Impact

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Managed-environment chooser replacing current tenant chooser yes Native Filament page context selection, navigation entry point page, URL/query no Keeps the existing chooser family and retargets it to managed environments
Current environment-scoped panel routes under /admin/t/{environment} yes Native Filament panel shell route links, context bar, global search, resource scope shell, page, detail, URL/query yes Temporary path retention only until Spec 280 owns the public route-family rewrite
Admin directory/resource surfaces that currently list Tenant records yes Native Filament resources/pages detail links, current-target summaries page, detail no Core noun and route binding change here; broader IA and copy polish remain deferred

Decision-First Surface Role

Surface Decision Role Human-in-the-loop Moment Immediately Visible for First Decision On-Demand Detail / Evidence Why This Is Primary or Why Not Workflow Alignment Attention-load Reduction
Managed-environment chooser Primary Decision Surface Operator selects the current managed target inside the active workspace environment name, display name, lifecycle posture, and current workspace provider-specific diagnostics stay secondary and remain follow-up work Primary because current environment selection is the first explicit decision before any environment-scoped workflow begins Keeps the existing current-target selection workflow intact Removes ambiguity between workspace scope and managed-target scope
Current environment-scoped panel shell Secondary Context Surface Operator verifies they are acting in the correct managed environment while using existing pages active workspace plus active managed-environment identity deeper provider or governance detail remains on the current pages Not primary because it carries context while work happens elsewhere Aligns with existing panel-shell behavior instead of inventing a new workbench Reduces wrong-target actions during the cutover

Audience-Aware Disclosure

Surface Audience Modes In Scope Decision-First Default-Visible Content Operator Diagnostics Support / Raw Evidence One Dominant Next Action Hidden / Gated By Default Duplicate-Truth Prevention
Managed-environment chooser operator-MSP, support-platform environment identity, display name, lifecycle posture, and workspace context provider-health detail and migration notes remain secondary raw provider metadata stays hidden Enter environment provider-specific raw metadata chooser cards show selection truth once and defer diagnostics
Current environment-scoped panel shell operator-MSP, support-platform active workspace and active managed-environment context deeper per-page diagnostics remain where they already live raw payloads remain page-local and secondary existing page action any migration/debug hints stay lower-priority shell surfaces should not repeat full page-level summaries

UI/UX Surface Classification

Surface Action Surface Class Surface Type Likely Next Operator Action Primary Inspect/Open Model Row Click Secondary Actions Placement Destructive Actions Placement Canonical Collection Route Canonical Detail Route Scope Signals Canonical Noun Critical Truth Visible by Default Exception Type / Justification
Managed-environment chooser Selector / Context / Entry Context-selection page Enter the intended managed environment card/list selection optional current pattern workspace switch remains secondary none /admin/choose-environment (logical) environment entry path active workspace plus environment identity Managed environment selected target identity and lifecycle posture none
Current environment-scoped panel shell Shell / Context / Navigation Filament panel shell Continue into the current environment page current shell context forbidden page-local links stay secondary none /admin/t/{environment} (temporary) existing page routes under the shell active workspace plus active managed environment Managed environment current environment identity temporary route retention until Spec 280

Operator Surface Contract

Surface Primary Persona Decision / Operator Action Supported Surface Type Primary Operator Question Default-visible Information Diagnostics-only Information Status Dimensions Used Mutation Scope Primary Actions Dangerous Actions
Managed-environment chooser TenantPilot operator Decide which managed environment inside the current workspace should become active Context-selection page Which managed environment am I about to act in? environment identity, workspace context, lifecycle posture provider-specific diagnostics and migration detail lifecycle, access posture none Enter environment none
Current environment-scoped panel shell TenantPilot operator Confirm that all current environment-bound pages resolve the right managed target Panel shell Am I in the correct workspace and managed environment? active workspace and active managed-environment identity page-local diagnostics only access posture, lifecycle none existing page action none

Proportionality Review

  • New source of truth?: yes
  • New persisted entity/table/artifact?: yes
  • New abstraction?: no new generic abstraction; existing tenant-context seams are replaced or neutralized in place
  • New enum/state/reason family?: yes, bounded managed-environment kind and lifecycle posture fields
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: the product cannot become workspace-first or provider-neutral while the core managed target, current context, and route binding still assume Tenant
  • Existing structure is insufficient because: the current Tenant model mixes managed-target identity, provider-specific metadata, current-context behavior, and Filament tenant binding across the app
  • Narrowest correct implementation: a single breaking core cutover to ManagedEnvironment with one documented temporary route-path exception and no compatibility aliases
  • Ownership cost: broad schema and relation retargeting, command and test updates, temporary exception tracking for /admin/t/{environment}, and explicit follow-up ownership for Specs 280-287
  • Alternative intentionally rejected: dual-read/dual-write aliases, a Tenant wrapper around ManagedEnvironment, or one giant combined route/IA/provider/artifact rewrite. Those options either violate the constitution or make the first cutover slice too broad to review safely.
  • Release truth: current-release truth with explicit follow-up slices for the remaining cutover pack

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, dual-read/dual-write shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.

Canonical replacement is preferred over preservation.

Testing / Lane / Runtime Impact

  • Test purpose / classification: Unit, Feature, Browser
  • Validation lane(s): fast-feedback, confidence, browser
  • Why this classification and these lanes are sufficient: the cutover changes core model truth, route/model binding, and Filament context selection. Unit tests prove model and context rules, feature tests prove scope and routing semantics, and one browser smoke proves the workspace-to-environment selection flow stays operable after the cutover.
  • New or expanded test families: one managed-environment unit family, one managed-environment feature family, and one narrow browser smoke
  • Fixture / helper cost impact: moderate; existing tenant fixtures and helper families must be replaced with managed-environment equivalents rather than layered adapters
  • Heavy-family visibility / justification: none
  • Special surface test profile: standard-native-filament, global-context-shell, exception-coded-surface
  • Standard-native relief or required special coverage: standard Filament feature coverage is sufficient for chooser and panel-context semantics; one browser smoke is required because the cutover changes end-to-end context selection and panel bootstrapping
  • Reviewer handoff: reviewers must verify that ManagedEnvironment replaces Tenant in core-owned paths, the temporary /admin/t exception is the only path deviation, the legacy-core guard proves tenant_id removal inside the declared core-owned cutover inventory while keeping Specs 281 and 282 exclusions explicit, ManagedEnvironment carries no Microsoft-specific identity fields, any touched globally searchable resource still satisfies Filaments edit/view eligibility rule or remains out of global search, no new asset registration or deployment-step change appears, and provider registration remains in apps/platform/bootstrap/providers.php
  • Budget / baseline / trend impact: moderate feature-local increase only
  • Escalation needed: document-in-feature for the temporary /admin/t path exception; follow-up-spec already assigned for the remaining cutover pack
  • Active feature PR close-out entry: Guardrail
  • Planned validation commands:
    • 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)
    • 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)
    • 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)
    • 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)
    • 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"
    • 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"

Scope Boundaries (required for this slice)

In Scope

  • introduce ManagedEnvironment as the active managed-target root inside a workspace
  • introduce the breaking schema/model cutover away from Tenant and tenant_id in core-owned paths
  • retarget current context selection, route binding, query helpers, memberships, and the current tenant-panel shell bridge to ManagedEnvironment while keeping the final Workspace Filament-tenancy switch deferred to Spec 280
  • keep the current environment-scoped panel operable through the documented temporary /admin/t/{environment} exception until Spec 280
  • update factories, seeders, policies, guards, route binding, and tests so core-owned paths no longer rely on App\Models\Tenant
  • ensure ManagedEnvironment carries no Microsoft-specific identity, Graph, or Intune fields

Non-Goals

  • final workspace-first public route family and navigation IA rewrite
  • provider-profile extraction and provider-scope normalization
  • governance artifact naming and route retargeting polish
  • RBAC scope redesign or new capability families
  • copy/localization neutralization beyond the minimum core cutover terms
  • quality-gate automation beyond the feature-local guard tests needed for this slice
  • package execution, guided operations, virtual consultant, or any new provider implementation

Assumptions

  • the repo remains pre-production, so destructive in-place replacement is acceptable and compatibility shims are not
  • the temporary /admin/t/{environment} path retention is the only allowed path exception for this slice
  • broader workspace-first IA, provider extraction, artifact retargeting, and RBAC scoping remain explicitly deferred to Specs 280-287
  • current workspace membership and capability semantics stay materially unchanged in this slice; only the managed-target noun and foreign-key anchors move

Risks

  • the implementation could accidentally combine the core cutover with the public route/IA rewrite, which would make review and rollback reasoning too broad
  • lingering Tenant references in commands, tests, or helper traits could hide cutover drift and produce mixed context behavior
  • provider-specific identity could accidentally land on ManagedEnvironment if current Tenant fields are copied forward without discipline
  • the temporary /admin/t exception could become permanent if Spec 280 is not treated as mandatory follow-up

Candidate Selection Gate Summary

  • Selected candidate: 279 - Workspace-first Managed Environment Core Cutover
  • Source locations:
    • docs/product/spec-candidates.md under the Workspace-first / ManagedEnvironment Core Cutover candidate pack
    • docs/product/roadmap.md under the planned cutover pack ordering
  • Why selected now: 279 is the first unspecced reserved slot in the cutover pack and is the prerequisite for the remaining reserved follow-ups
  • Why close alternatives were deferred:
    • 280 depends on the core entity and context replacement from 279
    • 281 depends on the new managed-target root before provider-profile extraction makes sense
    • 282 depends on managed_environment_id becoming the core anchor first
    • 283-287 are later normalization and guardrail layers, not the initial breaking cutover
  • Smallest viable implementation slice: core entity replacement, foreign-key retargeting, current-context replacement, and one bounded path exception only
  • Documented deviation from raw candidate wording: this package defers the public workspace-first route-family rewrite and final Workspace Filament-tenancy end state to Spec 280. To keep the implementation bounded and the runtime operable, 279 allows the current /admin/t/{environment} shell to remain temporarily while rebinding it to ManagedEnvironment.

Completed-Spec Guardrail Result

  • specs/276-support-access-governance/ already exists and remains a separate prepared package
  • specs/277-stored-reports-surface/ already exists and remains a separate prepared package
  • specs/278-cross-domain-indicator-audit/ already exists and carries completed docs-only close-out history
  • specs/247-plans-entitlements-billing-readiness/, specs/251-commercial-entitlements-billing-state/, specs/252-platform-localization-v1/, specs/262-lifecycle-governance-taxonomy/, and specs/264-cross-tenant-promotion-execution/ remain context only and are not rewritten by this package

Deferred Adjacent Candidates

  • 280 - Filament Workspace Tenancy & Environment Routing Cutover
  • 281 - Provider Connection, Provider Scope & Microsoft Profile Extraction
  • 282 - Governance Artifact Retargeting to ManagedEnvironment
  • 283 - Provider Capability Registry v1
  • 284 - Provider-neutral Artifact Source Taxonomy v1
  • 285 - Workspace-first RBAC & Environment Access Scoping
  • 286 - UI Copy, IA & Localization Neutralization
  • 287 - Cutover Quality Gates & No-Legacy Enforcement

User Scenarios & Testing

User Story 1 - Resolve managed environments as the active target inside a workspace (Priority: P1)

As a platform operator, I want the active managed target to be a ManagedEnvironment inside my current workspace so the platform core stops depending on Tenant as its primary identity model.

Why this priority: every later cutover slice depends on the managed-target root being replaced first.

Independent Test: Seed a workspace plus one managed environment, resolve the record through route binding and current-context helpers, and confirm the core paths no longer require App\Models\Tenant.

Acceptance Scenarios:

  1. Given a workspace has a managed environment, When the current environment is resolved by route key, Then the app returns the ManagedEnvironment record and current workspace context instead of a Tenant model.
  2. Given a wrong-workspace or non-member actor, When they try to resolve the same managed environment, Then the app responds with 404 and leaks no environment-bound data.

User Story 2 - Keep current environment-scoped surfaces operable through the cutover (Priority: P1)

As an operator using the current admin panel, I want the existing environment-scoped shell to keep working while the core noun changes so the cutover is reviewable without bundling the full route/IA rewrite.

Why this priority: the cutover is not implementation-ready unless the current panel still boots on the new core entity.

Independent Test: Select a workspace, enter a managed environment from the retargeted chooser, and open the current environment dashboard through the temporary /admin/t/{environment} shell.

Acceptance Scenarios:

  1. Given an operator selected a workspace, When they choose a managed environment, Then the current panel shell loads with that managed environment as the active bound model.
  2. Given the same environment-scoped shell, When a page or deep link resolves the active target, Then route builders, query helpers, and current-target chips use ManagedEnvironment consistently.

User Story 3 - Remove active tenant-core drift from schema, policies, and tests (Priority: P2)

As a maintainer, I want core-owned schema, policies, factories, and guard tests to use ManagedEnvironment and managed_environment_id so later specs do not inherit mixed core nouns.

Why this priority: lingering tenant-core drift would make the follow-up cutover pack unstable and ambiguous.

Independent Test: Run the managed-environment unit/feature suite and the legacy-core guard checks, then confirm no active App\Models\Tenant or ->tenant(Tenant::class) binding remains in core-owned paths.

Acceptance Scenarios:

  1. Given the cutover implementation is complete, When factories, policies, and tests create the managed target, Then they use ManagedEnvironment and managed-environment memberships rather than Tenant.
  2. Given the final core-owned paths are searched or guard-tested, When forbidden legacy core patterns are checked, Then no active Tenant core model or Filament tenant binding remains.

Edge Cases

  • The current public /admin/t/{environment} path may remain temporarily, but it must bind ManagedEnvironment and must not coexist with a second compatibility route family.
  • Microsoft-specific external terms such as Microsoft Entra Tenant ID may remain only in provider-owned metadata or provider profiles, not on ManagedEnvironment.
  • Archived or inactive managed environments must not become selectable current context by default.
  • Old tenant-specific factories, seeders, and fixtures must be removed or replaced in the same cutover PR rather than kept for convenience.

Requirements (mandatory)

Constitution alignment (required): This feature changes core data ownership, route binding, context selection, and existing operator-facing shell behavior. It adds no Microsoft Graph calls and no new OperationRun family. Any security-relevant mutation that is not represented by OperationRun still uses existing audit behavior where applicable.

Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001): The feature introduces a new persisted root entity because the current product truth needs a provider-neutral managed-target core now. A narrower alias or adapter would preserve the wrong truth and would violate the repos pre-production lean doctrine.

Constitution alignment (XCUT-001): Current context-selection, route-building, query-scoping, and shell-context seams must be replaced in place. No second local environment-context language is allowed.

Constitution alignment (PROV-001): ManagedEnvironment must remain provider-neutral. Provider-specific identity stays in provider-owned seams and follow-up Spec 281.

Constitution alignment (SCOPE-001 exception/update prerequisite): The current constitution still requires tenant-owned tables to use workspace_id plus tenant_id as NOT NULL. This package intentionally replaces active core-owned managed-target keys with managed_environment_id. Implementation is gated by the explicit exception record in specs/279-workspace-managed-environment-core/checklists/constitution-scope-001-exception.md until the constitution itself is amended.

Functional Requirements

  • FR-001: The package MUST introduce ManagedEnvironment as the active managed-target root record inside a workspace.
  • FR-002: The package MUST remove active core dependence on App\Models\Tenant and retarget core-owned foreign keys from tenant_id to managed_environment_id.
  • FR-003: ManagedEnvironment MUST NOT contain Microsoft-specific identity, Graph, or Intune fields.
  • FR-004: Current workspace-plus-target context resolution MUST bind ManagedEnvironment instead of Tenant.
  • FR-005: Current environment membership and capability checks MUST continue to enforce 404 for non-members and 403 for in-scope capability denials.
  • FR-006: The current environment-scoped panel shell may retain the /admin/t/{environment} path temporarily, but it MUST bind ManagedEnvironment and MUST remain the only documented path exception in this slice.
  • FR-007: Current tenant-scoped query helpers, global-search scoping, route builders, and current-target UI seams MUST resolve ManagedEnvironment consistently.
  • FR-008: Tests, factories, policies, and seeders in core-owned paths MUST use ManagedEnvironment naming and IDs after the cutover.
  • FR-009: The package MUST not introduce dual columns, alias models, dual-write logic, or compatibility routes.
  • FR-010: The package MUST explicitly defer the remaining workspace-first route-family rewrite, provider extraction, artifact retargeting, RBAC scope redesign, copy neutralization, and long-lived cutover quality gates to Specs 280-287.

Authorization and Safety Requirements

  • AR-001: Workspace membership remains the first access boundary and must still deny non-members as 404.
  • AR-002: Managed-environment membership remains the second access boundary and must still deny wrong-environment access as 404.
  • AR-003: No new destructive action semantics are introduced. Any touched existing destructive actions must preserve ->requiresConfirmation() and current authorization checks.

Non-Functional Requirements

  • NFR-001: Filament remains v5 on Livewire v4.
  • NFR-002: Provider registration stays in apps/platform/bootstrap/providers.php; no new panel provider registration location is introduced.
  • NFR-003: Any existing globally searchable resource touched by the cutover must continue to satisfy Filaments edit/view-page requirement or remain out of global search.
  • NFR-004: No new asset registration or filament:assets deployment change is introduced in this slice.
  • NFR-005: The cutover must remain reviewable as one bounded implementation loop and must not silently absorb the broader Spec 280-287 work.