TenantAtlas/specs/280-workspace-tenancy-environment-routing/spec.md
ahmido 670c46dedd Spec 280: prepare workspace tenancy and environment routing cutover (#336)
## Summary
- add the implementation-ready spec-prep artifacts for Spec 280: Filament Workspace Tenancy & Environment Routing Cutover
- define the bounded scope, rollout constraints, route contract, and validation plan for the workspace-first routing cutover
- update the generated Copilot agent context for the active feature branch

## Testing
- not run; this branch adds spec-prep artifacts only and does not change application code

## Notes
- no application runtime, database, or frontend code changes are included in this PR
- target base branch requested: `platform-dev`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #336
2026-05-07 10:20:43 +00:00

54 KiB

Feature Specification: Filament Workspace Tenancy & Environment Routing Cutover

Feature Branch: 280-workspace-tenancy-environment-routing
Created: 2026-05-07
Status: Ready
Input: User description: "Work only in /Users/ahmeddarrazi/Documents/projects/wt-plattform on branch 280-workspace-tenancy-environment-routing. Update only spec-prep artifacts, no application code. Fill /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/280-workspace-tenancy-environment-routing/spec.md as the implementation-ready spec for candidate 280 - Filament Workspace Tenancy & Environment Routing Cutover from docs/product/spec-candidates.md and docs/product/roadmap.md."

Spec Candidate Check

  • Problem: TenantPilot's operator runtime is still split between the workspace-scoped admin panel under /admin and the temporary ManagedEnvironment-scoped Filament panel under /admin/t. That leaves the public route contract, breadcrumbs, chooser flow, middleware, and deep-link builders behind the core model cutover completed in Spec 279.
  • Today's failure: Verified repo seams such as TenantPanelProvider, ChooseTenant, WorkspaceRedirectResolver, EnsureWorkspaceSelected, EnsureFilamentTenantSelected, TenantPageCategory, OperationRunLinks, and many panel: 'tenant' links still route operators into /admin/t/{environment} or /admin/tenants/{environment}. Operators move from a workspace surface into a second panel with a different route language, while current operations remain canonical at workspace scope. The product therefore still communicates two different truths about where environment work actually lives.
  • User-visible improvement: Operators get one workspace-first admin runtime: workspace dashboard, workspace-scoped environment chooser, managed-environment dashboard, workspace-scoped operations hub, and breadcrumbs that consistently read Workspace -> Managed Environment -> domain page.
  • Smallest enterprise-capable version: Collapse the temporary /admin/t panel into the existing /admin admin panel, configure Workspace as the only Filament tenant, move environment pages under /admin/workspaces/{workspace}/environments/{environment}, make /admin/workspaces/{workspace}/operations the canonical operations route, reuse the existing workspace and environment dashboard builders, and remove the old route families without adding aliases or compatibility redirects.
  • Explicit non-goals: No provider extraction, no governance-artifact retargeting, no provider-neutral capability registry, no provider-neutral artifact taxonomy, no RBAC redesign, no UI copy neutralization beyond route/breadcrumb/context truth needed by this slice, no quality-gate pack beyond feature-local routing/tenancy proof, no customer-portal cutover, no second Filament tenancy at the environment level, and no compatibility routes or dual-panel end state.
  • Permanent complexity imported: One admin-panel tenancy flip from temporary environment-panel ownership to workspace tenancy, one canonical workspace-first environment route family, one route/breadcrumb/current-context contract update across chooser and deep-link seams, and focused feature/browser plus guard coverage. No new persistence, enum family, abstraction layer, or asset system is introduced.
  • Why now: Spec 279 already changed the core managed-target noun to ManagedEnvironment, and the verified controlling seam still shows the old shell in TenantPanelProvider with path('admin/t') and tenant(ManagedEnvironment::class, slugAttribute: 'slug'). Until 280 closes that shell, every later reserved cutover slice (281-287) sits on an intentionally temporary panel and route contract.
  • Why not local: This is not one page or one redirect. The temporary shell is encoded in provider registration, chooser flow, middleware, route categorization, current-context resolution, dashboard links, operations links, and resource URLs. A local fix would create the same hidden compatibility layer that the candidate and constitution reject.
  • Approval class: Core Enterprise
  • Red flags triggered: Many touched operator surfaces and a foundation-sounding cutover. Defense: the slice explicitly reuses existing workspace and environment dashboard builders, removes a temporary panel instead of adding framework machinery, forbids compatibility routes, and defers the remaining provider/artifact/RBAC/copy/quality follow-up to reserved Specs 281-287.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 11/12
  • Decision: approve

Spec Scope Fields

  • Scope: workspace
  • Primary Routes:
    • /admin remains the operator entrypoint only and resolves to workspace chooser or the currently selected workspace dashboard; it is not a second canonical environment dashboard route
    • /admin/workspaces/{workspace} becomes the canonical workspace dashboard route for the active workspace
    • /admin/workspaces/{workspace}/environments becomes the canonical workspace-scoped environment chooser route
    • /admin/workspaces/{workspace}/environments/{environment} becomes the canonical managed-environment dashboard route
    • /admin/workspaces/{workspace}/environments/{environment}/{domain...} becomes the canonical family for environment-scoped resources, diagnostics, and detail pages that today resolve through panel: 'tenant' or /admin/tenants/{environment}
    • /admin/workspaces/{workspace}/operations and /admin/workspaces/{workspace}/operations/{run} become the canonical operations collection/detail routes
    • /admin/w/{workspace}/managed-tenants, /admin/operations, and /admin/operations/{run} are removed rather than retained as redirects, aliases, or hidden fallback readers
    • /admin/t/{environment} and /admin/tenants/{environment}/required-permissions are removed rather than retained as aliases
  • Data Ownership:
    • Workspace remains the workspace-owned root context and becomes the only Filament tenant for operator admin routing
    • ManagedEnvironment remains the managed target nested inside a workspace and is resolved from workspace-first route parameters and current-context helpers, not from a second Filament tenant registration
    • no table ownership, artifact ownership, provider-profile ownership, or RBAC ownership changes are introduced in this slice
  • RBAC:
    • workspace membership remains the first isolation boundary
    • managed-environment access remains the second isolation boundary
    • wrong-workspace or wrong-environment access remains 404
    • in-scope actors missing capability remain 403
    • no new role family, capability family, or authorization plane is introduced

Canonical-view handling for workspace-scoped monitoring surfaces:

  • Default filter behavior when tenant-context is active: when an operator enters a workspace-scoped canonical view from a managed-environment dashboard or environment-scoped page, the canonical view opens prefiltered to that managed_environment_id inside the current workspace; widening to all environments remains explicit.
  • Explicit entitlement checks preventing cross-tenant leakage: route-bound {workspace} and {environment} values must match each other and the current actor's entitlements. Explicit environment query hints outside the current workspace or outside the actor's membership resolve as 404, while stale remembered filters are discarded instead of leaking or cross-loading another environment.

Cross-Cutting / Shared Pattern Reuse

  • Cross-cutting feature?: yes
  • Interaction class(es): navigation entry points, context selection, dashboard signals, breadcrumbs, page context bars, workspace-to-environment drillthroughs, operations deep links, and route builders
  • Systems touched: AdminPanelProvider, TenantPanelProvider, ChooseWorkspace, ChooseTenant, WorkspaceOverview, TenantDashboard, Monitoring\Operations, WorkspaceRedirectResolver, EnsureWorkspaceSelected, EnsureFilamentTenantSelected, ResolvesPanelTenantContext, TenantPageCategory, WorkspaceOverviewBuilder, TenantDashboardSummaryBuilder, OperationRunLinks, and RelatedNavigationResolver
  • Existing pattern(s) to extend: the existing /admin workspace panel, current workspace chooser flow, current WorkspaceOverview dashboard signals, current TenantDashboard environment signals, and the current tenant-safe operations link builders
  • Shared contract / presenter / builder / renderer to reuse: WorkspaceOverviewBuilder, TenantDashboardSummaryBuilder, WorkspaceContext, WorkspaceRedirectResolver, OperationRunLinks, RelatedNavigationResolver, and the existing Filament page/resource action-surface contracts
  • Why the existing shared path is sufficient or insufficient: these shared seams already own the user-facing signals and links that the final routing contract needs. What is insufficient today is not the dashboard or monitoring content itself, but the temporary second-panel route ownership and the mixed /admin/t versus /admin/tenants public path language.
  • Allowed deviation and why: none. This slice removes the temporary panel and route family instead of introducing another exception.
  • Consistency impact: workspace chooser, environment chooser, dashboard links, operations links, breadcrumbs, context bar signals, and page-level deep links must all speak the same workspace-first route language and the same Workspace -> Managed Environment -> domain page hierarchy.
  • Review focus: reviewers must verify that WorkspaceOverview and TenantDashboard are reused rather than replaced, that OperationRunLinks and related builders stop emitting panel: 'tenant' or /admin/t URLs, and that no second route language or compatibility redirect remains.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: yes, link semantics only
  • Shared OperationRun UX contract/layer reused: OperationRunLinks, RelatedNavigationResolver, the existing Monitoring\Operations page, and the existing canonical navigation context helpers
  • Delegated start/completion UX behaviors: workspace-safe route resolution for operations index/detail, workspace-to-environment back-link context, and environment-prefiltered operations drillthrough via managed_environment_id; no new toast, queue, dedupe, terminal-notification, or artifact-link behavior is introduced
  • Local surface-owned behavior that remains: environment dashboards and environment-scoped pages only supply the filter context and back-navigation label for the existing operations surface
  • Queued DB-notification policy: N/A
  • Terminal notification path: N/A
  • Exception required?: none

Provider Boundary / Platform Core Check

  • Shared provider/platform boundary touched?: yes
  • Boundary classification: mixed
  • Seams affected: panel tenancy, route nouns, chooser wording, page-category classification, breadcrumb context, current-context resolution, and deep-link builders that still encode temporary environment-panel ownership
  • Neutral platform terms preserved or introduced: workspace, managed environment, environment, operations, findings, backup sets, evidence, and required permissions
  • Provider-specific semantics retained and why: provider-owned Microsoft terms may remain in untouched provider copy, metadata, or class names such as TenantResource until Specs 281 and 286 handle provider extraction and copy neutralization. This slice only requires that routing, breadcrumbs, panel tenancy, chooser labels, and context signals touched by the cutover become workspace/environment truthful.
  • Why this does not deepen provider coupling accidentally: the slice removes a provider-shaped public shell instead of entrenching it. Workspace becomes the Filament tenant, ManagedEnvironment remains nested context, and no provider-profile fields or Microsoft-specific routing semantics are added to the platform-core route contract.
  • Follow-up path: Spec 281 for provider-profile extraction, Spec 282 for artifact retargeting, Spec 285 for workspace-first RBAC scope follow-through, Spec 286 for copy neutralization, and Spec 287 for explicit no-legacy enforcement

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
Workspace dashboard under the canonical workspace route yes Native Filament page plus shared dashboard builders navigation, dashboard signals, body CTA links page, URL, summary state no Reuses WorkspaceOverview and WorkspaceOverviewBuilder rather than introducing a second workspace summary surface
Workspace-scoped environment chooser yes Native Filament simple page context selection, navigation entry point page, URL, remembered context no Reuses the existing chooser flow instead of adding a second environment selector
Managed-environment dashboard under the workspace-first route yes Native Filament dashboard plus shared widgets/builders dashboard signals, header actions, page CTAs page, URL, detail state no Reuses TenantDashboard and its current widget/action family; routing and breadcrumbs change, not the signal source
Workspace operations hub under /admin/workspaces/{workspace}/operations yes Native Filament monitoring page operations links, back links, filter context page, table, URL/query no Reuses the existing operations surface and moves only the public route ownership/context contract
Environment-scoped page family migrated off /admin/t and /admin/tenants/{environment} yes Native Filament resources/pages navigation, breadcrumbs, current-context shell page, detail, URL/query no Local action contracts stay intact; this slice changes route ownership and breadcrumb shell only

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
Workspace dashboard under the canonical workspace route Primary Decision Surface Operator scans one workspace to decide which environment or workflow needs attention next workspace-wide signal counts, attention items, recent operations, and quick actions deeper environment detail remains one click away on the environment dashboard or operations hub Primary because it is the workspace landing surface after workspace selection Follows workspace-first operating flow instead of dropping straight into one environment panel Removes the current panel split and makes workspace scope explicit before environment work begins
Workspace-scoped environment chooser Primary Decision Surface Operator chooses the managed environment they intend to act in environment identity, lifecycle posture, and current workspace context deeper environment diagnostics stay on the environment dashboard Primary because environment selection is the next explicit decision after workspace selection Keeps selection inside the same workspace panel instead of jumping into a second panel Removes the cognitive break between workspace selection and environment work
Managed-environment dashboard under the workspace-first route Secondary Context Surface Operator confirms the chosen environment and decides which domain page to open next environment posture, chips, recommended action, and dashboard signals raw/support detail stays where it already belongs on downstream pages Secondary because it is an environment workbench, not the workspace-wide landing decision surface Aligns with today's dashboard-driven environment workflow, but under truthful workspace-first routing Reduces wrong-environment actions by keeping workspace and environment context visible together
Workspace operations hub under /admin/workspaces/{workspace}/operations Primary Decision Surface Operator reviews queued and completed operations for one workspace, optionally narrowed to one environment current workspace, active environment filter if present, operation status/outcome, and canonical back link deeper run detail stays on the run viewer Primary because operations already serve as the canonical monitoring surface Preserves the existing monitoring workflow while removing the need to infer environment context from a second panel Reduces duplicate monitoring entry points and keeps widening/narrowing explicit
Environment-scoped page family migrated off /admin/t and /admin/tenants/{environment} Secondary Context Surface Operator performs the chosen domain task inside one managed environment breadcrumb/context shell plus the existing page-local operational truth existing diagnostics remain page-local and unchanged Secondary because the decision is made on dashboard or operations surfaces; these pages carry the work forward Preserves each page's current workflow contract while making its scope truthful in navigation Removes path-language drift without creating new page-local decision systems

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
Workspace dashboard under the canonical workspace route operator-MSP, support-platform workspace-wide attention, recent operations, and one next-action entry point per-environment follow-up remains secondary raw evidence stays on downstream pages Open environment or Open operations depending on the top signal raw evidence and low-level diagnostics remain downstream workspace summary stays at workspace level and does not restate environment dashboards
Workspace-scoped environment chooser operator-MSP, support-platform current workspace plus selectable managed environments lifecycle posture only provider/raw detail hidden Open environment provider-specific raw metadata chooser states selection truth once, then hands off to the environment dashboard
Managed-environment dashboard under the workspace-first route operator-MSP, support-platform environment summary, posture, and recommended next action page-local diagnostics, support request detail, and additional widgets raw evidence stays on dedicated downstream surfaces primary follow-up action support/raw evidence remains downstream and capability-gated where already required dashboard shows the environment summary once and uses links for deeper evidence instead of repeating it
Workspace operations hub under /admin/workspaces/{workspace}/operations operator-MSP, support-platform workspace scope, optional environment filter, and operation follow-up state run-level diagnostics remain on the run viewer raw payloads remain on detail pages or related evidence surfaces Open operation or Back to environment low-level run evidence stays in detail the hub states scope once and uses detail pages for deep evidence
Environment-scoped page family migrated off /admin/t and /admin/tenants/{environment} operator-MSP, support-platform breadcrumb scope plus each page's existing core truth existing diagnostics stay on the page support/raw evidence remains unchanged and page-local the page's existing primary action unrelated raw/support detail remains gated as today the new shell adds context instead of duplicating page-local 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
Workspace dashboard under the canonical workspace route Dashboard / Context / Summary Workspace landing dashboard Open one environment or the operations hub body CTA cards and quick actions forbidden body-level quick actions only none /admin/workspaces/{workspace} /admin/workspaces/{workspace} active workspace Workspace workspace-wide attention and recent operations none
Workspace-scoped environment chooser Selector / Context / Entry Workspace environment selector Open the intended managed environment environment card/button allowed workspace switch remains secondary none /admin/workspaces/{workspace}/environments /admin/workspaces/{workspace}/environments/{environment} active workspace plus environment identity Managed Environment selectable environment identity and posture none
Managed-environment dashboard under the workspace-first route Dashboard / Detail / Workflow hub Environment dashboard Follow the recommended domain action dashboard CTA from widget or header action forbidden grouped header secondary actions plus body links none introduced by this slice /admin/workspaces/{workspace}/environments /admin/workspaces/{workspace}/environments/{environment} active workspace and active managed environment Managed Environment environment posture, next action, and dashboard signals none
Workspace operations hub under /admin/workspaces/{workspace}/operations List / Table / Monitoring Workspace monitoring hub Inspect a run or widen/narrow environment scope clickable row to run detail required header back-link and filter actions none /admin/workspaces/{workspace}/operations /admin/workspaces/{workspace}/operations/{run} active workspace and optional managed-environment filter Operations / Operation current scope, run state, and follow-up truth none
Environment-scoped page family migrated off /admin/t and /admin/tenants/{environment} List / Detail / Resource family Workspace-first environment resources and diagnostics Continue the chosen domain workflow preserve each surface's current inspect model preserve current contract preserve current contract preserve current contract /admin/workspaces/{workspace}/environments/{environment}/{domain} /admin/workspaces/{workspace}/environments/{environment}/{domain}/{record?} breadcrumb Workspace -> Managed Environment -> page Existing domain noun active workspace/environment context plus each page's existing truth none

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
Workspace dashboard under the canonical workspace route Workspace operator Decide which environment or workspace-wide workflow needs attention first Dashboard What in this workspace needs my attention next? workspace-wide attention, recent operations, quick actions deeper environment evidence stays downstream workspace attention, run activity, recovery posture none Open environment, Open operations none
Workspace-scoped environment chooser Workspace operator Decide which managed environment to enter Context-selection page Which managed environment am I about to work in? environment identity, posture, workspace context deeper diagnostics remain on the dashboard lifecycle posture, access posture none Open environment none
Managed-environment dashboard under the workspace-first route Environment operator Decide which environment-scoped page to open next Dashboard What in this environment needs action now? posture, dashboard chips, recommended action, summary widgets support diagnostics and deeper evidence remain downstream environment posture, readiness, attention state existing page-local semantics only Primary follow-up, More, Request support none added by this slice
Workspace operations hub under /admin/workspaces/{workspace}/operations Monitoring operator Review runs across the workspace or one environment Monitoring table/detail Which operations need follow-up, and for which environment? current scope, optional environment filter, run status/outcome, back link run detail, evidence, and related links remain secondary execution status, outcome, scope read-only Open operation, Back to environment, Show all environments none
Environment-scoped page family migrated off /admin/t and /admin/tenants/{environment} Environment operator Perform the selected domain workflow in one environment Resource/detail family Am I acting in the correct workspace and managed environment? breadcrumb scope and existing page truth page-local diagnostics unchanged preserve current domain-specific status families preserve current page-local mutation semantics preserve current page-local primary action preserve current page-local dangerous actions

Proportionality Review

  • New source of truth?: no
  • New persisted entity/table/artifact?: no
  • New abstraction?: no
  • New enum/state/reason family?: no
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: the operator runtime still communicates two conflicting truths: workspace-wide work begins on /admin, but environment work still lives on a temporary /admin/t panel and a second /admin/tenants/{environment} route family.
  • Existing structure is insufficient because: the current structure requires special-casing /admin/t and /admin/tenants in provider setup, middleware, route categorization, chooser flow, and deep-link builders. As long as that split remains, later provider/artifact/RBAC cutovers would be forced to build on a known temporary shell.
  • Narrowest correct implementation: reuse the current admin panel, workspace dashboard, environment dashboard, chooser flow, and operations surface, and change only the tenancy and public route ownership needed to remove the temporary shell.
  • Ownership cost: route and deep-link retargeting across chooser, middleware, builders, breadcrumbs, and tests; removal of one panel provider from the operator runtime; and focused browser/feature coverage to keep the route contract honest.
  • Alternative intentionally rejected: leaving the /admin/t panel in place with redirects, keeping /admin/tenants/{environment} as a second route family, or adding nested/dual Filament tenancy. Those options preserve the temporary shell instead of closing it.
  • Release truth: current-release truth; this slice removes temporary runtime structure rather than preparing future framework flexibility

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, redirect shims, dual-panel ownership, dual-context restore paths, 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: Feature, Browser
  • Validation lane(s): fast-feedback, confidence, browser
  • Why this classification and these lanes are sufficient: this slice changes panel tenancy, public routes, chooser flow, breadcrumbs, deep-link builders, and workspace/environment authorization semantics. Feature tests prove route ownership, filter context, and deny-as-not-found behavior; one narrow browser smoke proves the chooser-to-dashboard-to-operations flow still works end to end on the surviving admin panel.
  • New or expanded test families: one workspace-tenancy/routing feature family, one environment-routing/breadcrumb feature family, one operations canonical-context feature family, one legacy-route-removal or grep/guard family, and one narrow browser smoke for the workspace-to-environment flow
  • Fixture / helper cost impact: moderate. Tests must seed a workspace plus managed environments and reuse existing workspace/member/environment context helpers. The slice should not introduce new default-heavy fixtures, providers, or session helpers beyond what current workspace and managed-environment tests already require.
  • Heavy-family visibility / justification: one browser smoke only. No new heavy-governance or broad browser family is justified.
  • Special surface test profile: standard-native-filament, global-context-shell, monitoring-state-page
  • Standard-native relief or required special coverage: standard feature coverage is sufficient for provider registration, tenancy switch, route removal, and breadcrumb semantics. One browser smoke is required because the cutover changes the live operator entry flow across chooser, dashboard, and operations surfaces.
  • Reviewer handoff: reviewers must verify that AdminPanelProvider becomes the only operator panel, any provider-registration change remains in apps/platform/bootstrap/providers.php, TenantPanelProvider and /admin/t cease to own public operator routing, ChooseTenant and WorkspaceRedirectResolver stop emitting panel: 'tenant' destinations, OperationRunLinks and related navigation open the workspace operations hub with explicit environment filters, TenantPageCategory and the two middleware seams no longer treat /admin/t or /admin/tenants/{environment} as active route languages, WorkspaceOverview and TenantDashboard are reused rather than replaced, WorkspaceResource and TenantResource keep valid view/edit search destinations or disable search if that contract cannot be kept, destructive actions touched by the route move still require confirmation and server authorization, Livewire remains v4, and no new asset registration/deploy step appears.
  • Budget / baseline / trend impact: moderate feature-local increase only
  • Escalation needed: none
  • 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/Feature/Workspace/WorkspaceFilamentTenancyCutoverTest.php tests/Feature/ManagedEnvironment/WorkspaceFirstEnvironmentRoutingTest.php tests/Feature/Monitoring/WorkspaceOperationsEnvironmentContextTest.php tests/Feature/Navigation/WorkspaceEnvironmentBreadcrumbsTest.php tests/Feature/Guards/LegacyAdminTenantRouteRemovalGuardTest.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/Spec280WorkspaceTenancyEnvironmentRoutingSmokeTest.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 '/admin/t/' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/routes" "$REPO_ROOT/apps/platform/bootstrap"
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings '/admin/tenants/' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/routes" "$REPO_ROOT/apps/platform/bootstrap"
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings '/admin/w/' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/routes" "$REPO_ROOT/apps/platform/bootstrap"
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings '/admin/operations' "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/routes" "$REPO_ROOT/apps/platform/bootstrap"
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings "panel: 'tenant'" "$REPO_ROOT/apps/platform/app" "$REPO_ROOT/apps/platform/tests" "$REPO_ROOT/apps/platform/routes" "$REPO_ROOT/apps/platform/bootstrap"
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && REPO_ROOT="$(git rev-parse --show-toplevel)" && rg -n --fixed-strings 'TenantPanelProvider::class' "$REPO_ROOT/apps/platform/bootstrap/providers.php"

Scope Boundaries (required for this slice)

In Scope

  • make Workspace the only Filament tenant for the operator admin runtime
  • collapse the operator-facing /admin/t panel into the existing /admin admin panel
  • remove the public /admin/t/{environment} route family with no compatibility alias
  • remove the public /admin/tenants/{environment}/required-permissions family in favor of the workspace-first environment route family
  • introduce the canonical workspace-first environment route family rooted at /admin/workspaces/{workspace}/environments/{environment}
  • reuse WorkspaceOverview as the workspace dashboard and TenantDashboard as the managed-environment dashboard under the new route ownership
  • make /admin/workspaces/{workspace}/operations the canonical operations route and thread environment pages into it through explicit filters and back-navigation context
  • retarget chooser flow, middleware, route categorization, deep-link builders, breadcrumbs, and page-level context signals to the new route contract
  • ensure touched globally searchable resources preserve a valid view/edit destination or are disabled from global search in the same slice

Non-Goals

  • provider connection, provider scope, or Microsoft profile extraction owned by Spec 281
  • governance artifact retargeting to ManagedEnvironment owned by Spec 282
  • provider capability registry or provider-neutral artifact taxonomy owned by Specs 283 and 284
  • workspace-first RBAC redesign or capability-family changes owned by Spec 285
  • UI copy, IA, and localization neutralization beyond the route/breadcrumb/context truth needed here, owned by Spec 286
  • cutover quality-gate pack work beyond the routing/tenancy slice proof needed here, owned by Spec 287
  • customer portal, website, package-engine, or guided-operations work
  • compatibility routes, aliases, redirects that preserve /admin/t, dual panel ownership, dual-read/dual-write route logic, or hidden absorption of later reserved specs

Assumptions

  • Spec 279 already completed the core ManagedEnvironment cutover and remains prerequisite context only.
  • AdminPanelProvider remains the long-lived operator panel under /admin, and removing TenantPanelProvider from operator routing is acceptable in this pre-production environment.
  • The current workspace and environment dashboards already provide the operator signal content needed for the final route contract; 280 relocates and rekeys them instead of redesigning their signal models.
  • Internal class names or untouched provider copy may still use tenant until later reserved slices, but routing, breadcrumbs, chooser labels, and operator-facing context signals touched by this slice must be workspace/environment truthful.

Risks

  • Hidden /admin/t or panel: 'tenant' references in builders, widgets, or tests could leave a partial second route language behind after the cutover.
  • Operations deep links and back links could lose environment scope or workspace safety if they are retargeted page by page instead of through the shared link builders.
  • Collapsing panel ownership could break current context bootstrap if middleware and route categorization are not updated together.
  • The slice could sprawl into copy cleanup or RBAC redesign if reviewers do not hold the scope boundary against Specs 285 and 286.

Candidate Selection Gate Summary

  • Selected candidate: 280 - Filament Workspace Tenancy & Environment Routing Cutover
  • Source locations:
    • docs/product/spec-candidates.md under the reserved workspace-first / provider-neutral cutover pack
    • docs/product/roadmap.md under the same reserved cutover ordering and sequencing note
  • Why selected now: Spec 279 already changed the core managed-target noun, and the verified controlling seam still shows the temporary panel shell in TenantPanelProvider. 280 is the second reserved slot and closes that temporary public routing/tenancy contract before later provider and artifact follow-up work begins.
  • Why close alternatives were deferred:
    • 281 belongs to provider connection/profile extraction, not to route collapse
    • 282 belongs to artifact retargeting, not to public route ownership
    • 283 and 284 belong to provider-neutral packaging follow-through, not to the immediate shell removal
    • 285, 286, and 287 are explicit follow-up guardrail slices for RBAC, copy, and no-legacy enforcement
    • the already-existing mid-260/270 packages remain context only and are not the target of this reserved cutover slot
  • Smallest viable implementation slice: one surviving workspace-tenanted admin panel, one canonical workspace-first environment route family, one canonical workspace operations route family, and one bounded set of chooser/middleware/link/breadcrumb updates with no aliases
  • Documented deviation from raw candidate wording: add a workspace dashboard and add a managed-environment dashboard are satisfied by re-homing the existing WorkspaceOverview and TenantDashboard surfaces under their final route ownership rather than creating new summary systems.

Completed-Spec Guardrail Result

  • specs/265-decision-register-approval/ already exists with Status: Ready for implementation and remains separate context only
  • specs/267-artifact-lifecycle-retention/ already exists with Status: Ready for implementation and remains separate context only
  • specs/274-billing-subscription-truth/ already exists with Status: Ready for implementation and remains separate context only
  • specs/275-customer-facing-localization-adoption/ already exists with Status: Draft and remains separate context only
  • specs/276-support-access-governance/ already exists with Status: Ready for implementation and remains a separate prepared package
  • specs/277-stored-reports-surface/ already exists with Status: Ready for implementation and remains a separate prepared package
  • specs/278-cross-domain-indicator-audit/ already exists with Status: Implemented docs-only audit artifact; ready for manual review and remains separate historical context only
  • specs/279-workspace-managed-environment-core/ already exists with Status: Ready with approved feature-local exception, carries implementation-close-out history in tasks.md, and is prerequisite context only for this package

Deferred Adjacent Candidates

  • 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 - Enter an environment without leaving the workspace admin panel (Priority: P1)

As an operator, I want to choose a workspace and then open one managed environment inside the same admin panel so I never have to cross into a second panel or learn a second route language just to work on that environment.

Why this priority: this is the core cutover outcome. If the chooser still lands on /admin/t, the temporary shell remains active and the candidate is not complete.

Independent Test: select a workspace, open the environment chooser, choose one managed environment, and confirm the destination is the canonical workspace-first environment dashboard rather than /admin/t.

Acceptance Scenarios:

  1. Given an operator has selected a workspace, When they choose a managed environment, Then they land on /admin/workspaces/{workspace}/environments/{environment} inside the surviving admin panel.
  2. Given an operator enters a workspace/environment URL where the environment belongs to a different workspace or is not accessible, When the route resolves, Then the app returns 404 and reveals no environment data.

User Story 2 - Move from environment work into workspace operations with explicit scope (Priority: P1)

As an operator, I want environment dashboards and environment pages to open the workspace operations hub with an explicit environment filter so operations stay workspace-canonical without losing the narrower environment context I came from.

Why this priority: the candidate explicitly requires /admin/workspaces/{workspace}/operations to be canonical and environment pages to link into it via filters.

Independent Test: open one environment dashboard or environment page, follow its operations link, and confirm the workspace operations hub opens with the correct environment filter and return context.

Acceptance Scenarios:

  1. Given an operator is on one managed-environment dashboard, When they open operations, Then the destination is /admin/workspaces/{workspace}/operations with that environment's filter active.
  2. Given the operations hub is filtered to one environment, When the operator chooses to widen scope, Then the route stays workspace-canonical and the environment filter clears explicitly rather than switching panels.

User Story 3 - Read workspace-wide and environment-scoped signals on the correct surfaces (Priority: P2)

As an operator, I want the workspace dashboard to summarize workspace-wide signals and the managed-environment dashboard to summarize one environment's signals so I can decide at the right scope without reconstructing context from mixed pages.

Why this priority: the candidate requires both dashboards, and reusing the current builders is the narrowest honest way to deliver them.

Independent Test: open a workspace dashboard and an environment dashboard for the same workspace, then verify the workspace view aggregates workspace-wide signals while the environment view remains scoped to one environment and shows the full breadcrumb hierarchy.

Acceptance Scenarios:

  1. Given a workspace has multiple accessible environments, When the operator opens the workspace dashboard, Then it shows workspace-wide signals and recent operations rather than one environment's dashboard state.
  2. Given the operator opens one managed-environment dashboard, When the page renders, Then the breadcrumb and context shell show Workspace -> Managed Environment -> page and the signals remain scoped to that one environment.

User Story 4 - Keep search and authorization truthful after the route cutover (Priority: P3)

As an operator, I want globally searchable resources and direct URLs to open truthful destinations or disappear from search altogether so the route migration does not leave broken search results or unsafe hints behind.

Why this priority: WorkspaceResource and TenantResource are already search-eligible by repo truth, and route changes can quietly break that contract if the spec does not pin it down.

Independent Test: open touched global-search results and direct URLs for workspace and managed-environment surfaces, then confirm that authorized results open valid destinations and unauthorized paths remain not found.

Acceptance Scenarios:

  1. Given a touched searchable resource remains globally searchable, When an operator opens a search result, Then the destination is a valid page under the canonical workspace-first route family.
  2. Given a touched searchable surface cannot preserve a valid view or edit destination after the route move, When the cutover ships, Then that surface no longer appears in global search.

Edge Cases

  • A direct request to /admin/t/{environment}, /admin/tenants/{environment}/required-permissions, /admin/w/{workspace}/managed-tenants, /admin/operations, or /admin/operations/{run} must fail as not found rather than redirecting, aliasing, or silently restoring the old path family.
  • If a remembered environment belongs to a different workspace than the newly selected workspace, the environment context must clear before the operator is shown any environment-bound page.
  • Archived or otherwise non-selectable managed environments must not appear in the workspace-scoped chooser or resolve through the new route family.
  • Explicit environment filters on workspace-canonical pages must reject inaccessible environments as 404; stale remembered filters may be discarded, but explicit hostile hints may not quietly widen scope.
  • Any touched globally searchable resource without an intact view/edit destination under the new route contract must be disabled from global search in the same implementation slice.

Requirements

Constitution alignment (required): This slice changes routing, Filament tenancy, chooser flow, navigation, and deep-link behavior. It does not introduce Microsoft Graph calls, a new OperationRun lifecycle, or new persistence.

Constitution alignment (XCUT-001 / PROV-001 / UI-FIL-001): The slice must reuse the existing shared workspace dashboard, managed-environment dashboard, chooser flow, operations hub, and deep-link builders. No second panel, second route language, or local dashboard framework may appear.

Constitution alignment (RBAC-UX): Workspace membership stays the first boundary and managed-environment access stays the second boundary. Non-members remain 404, in-scope capability denials remain 403, and any touched destructive actions continue to require confirmation and server-side authorization.

Constitution alignment (TEST-GOV-001): Proof stays bounded to feature coverage, one narrow browser smoke, and explicit route/URL guard checks. No heavy-governance family is introduced.

Functional Requirements

  • FR-001: The operator admin runtime MUST configure Workspace as the only Filament tenant after this cutover.
  • FR-002: The system MUST stop using ManagedEnvironment as a Filament tenant and MUST remove the public /admin/t/{environment} route family rather than retaining it as a redirect, alias, or hidden fallback.
  • FR-003: The surviving /admin admin panel MUST own the canonical workspace-first environment route family rooted at /admin/workspaces/{workspace}/environments/{environment}.
  • FR-004: The admin entrypoint /admin MUST resolve to workspace selection or the current workspace dashboard only; it MUST NOT remain a second canonical environment dashboard route.
  • FR-005: The system MUST reuse the existing workspace overview surface as the canonical workspace dashboard and the existing managed-environment dashboard surface as the canonical environment dashboard, rather than creating replacement dashboard systems.
  • FR-006: The workspace-scoped chooser flow MUST open the new canonical environment dashboard route and MUST clear stale cross-workspace environment context before resolving any environment-bound page.
  • FR-007: The workspace dashboard, environment dashboard, and all environment-scoped pages touched by this slice MUST present navigation and breadcrumbs in the order Workspace -> Managed Environment -> domain page.
  • FR-008: /admin/workspaces/{workspace}/operations MUST be the canonical public operations collection route for the active workspace.
  • FR-009: Environment dashboards and environment-scoped pages MUST open the workspace operations hub through explicit filter/query context, not through environment-panel ownership.
  • FR-010: The operations detail route MUST remain inside the workspace route family so run detail does not depend on the removed /admin/t shell.
  • FR-011: Route builders, deep links, and related-navigation helpers that currently emit panel: 'tenant', /admin/t, or /admin/tenants/{environment} URLs MUST emit only the new canonical workspace-first routes.
  • FR-012: TenantPageCategory, EnsureWorkspaceSelected, EnsureFilamentTenantSelected, ResolvesPanelTenantContext, and related current-context seams MUST treat the workspace-first environment family as the only active environment-bound route language.
  • FR-013: The slice MUST preserve the current WorkspaceOverviewBuilder and TenantDashboardSummaryBuilder ownership of workspace-wide and environment-scoped summary signals.
  • FR-014: Any touched globally searchable resource MUST preserve a valid view or edit destination under the new route contract or be disabled from global search in the same slice.
  • FR-015: WorkspaceResource and TenantResource MUST remain globally searchable only if their view/edit destinations stay valid under the cutover route ownership.
  • FR-016: The slice MUST NOT introduce compatibility routes, aliases, dual-panel ownership, dual route readers, hidden /admin/t absorption, or spillover into reserved Specs 281-287.
  • FR-017: The legacy chooser route /admin/w/{workspace}/managed-tenants MUST be removed rather than preserved as a redirect, alias, or hidden fallback reader.
  • FR-018: The legacy operations routes /admin/operations and /admin/operations/{run} MUST be removed in favor of /admin/workspaces/{workspace}/operations and /admin/workspaces/{workspace}/operations/{run} with no redirects, aliases, or dual-route ownership.

Authorization and Safety Requirements

  • AR-001: Workspace membership MUST remain the first access boundary for /admin/workspaces/{workspace}/... routes.
  • AR-002: Managed-environment access MUST remain the second access boundary for /admin/workspaces/{workspace}/environments/{environment}/... routes.
  • AR-003: A mismatched {workspace} and {environment} pair MUST resolve as 404 even if the actor has access to one of them individually.
  • AR-004: Workspace-canonical pages that accept explicit environment filters MUST reject inaccessible environment hints as 404 and must not silently widen scope.
  • AR-005: Any destructive action touched while retargeting dashboard or page links MUST remain server-authorized and require confirmation.

Non-Functional Requirements

  • NFR-001: Filament remains v5 on Livewire v4.
  • NFR-002: Provider registration remains in apps/platform/bootstrap/providers.php; if TenantPanelProvider is removed from operator routing, no registration is moved to bootstrap/app.php.
  • NFR-003: Existing admin theme and asset registration remain unchanged; the slice introduces no new asset pipeline or deployment step beyond the current Filament asset practice.
  • NFR-004: The cutover must preserve Action Surface Contract, UI-FIL-001, and UX-001 expectations for touched Filament pages/resources without introducing ad hoc Blade/Tailwind design systems or redundant inspect actions.
  • NFR-005: The route cutover must stay reviewable as one bounded slice and must not silently absorb provider extraction, artifact retargeting, RBAC redesign, copy neutralization, or quality-gate work reserved for later specs.

UI Action Matrix (mandatory when Filament is changed)

Surface Location Header Actions Inspect Affordance (List/Table) Row Actions (max 2 visible) Bulk Actions (grouped) Empty-State CTA(s) View Header Actions Create/Edit Save+Cancel Audit log? Notes / Exemptions
Workspace dashboard WorkspaceOverview under /admin/workspaces/{workspace} none body CTA cards and quick actions only none none existing workspace zero-state CTA family only none N/A no new audit behavior Reuses WorkspaceOverviewBuilder; action-surface exemptions remain intact
Workspace-scoped environment chooser chooser surface under /admin/workspaces/{workspace}/environments none environment card/button opens the environment dashboard none none workspace switch or no-access guidance only none N/A no new audit behavior required by this slice Reuses the existing chooser pattern; selection must not jump into a second panel
Managed-environment dashboard TenantDashboard under /admin/workspaces/{workspace}/environments/{environment} Primary follow-up, More, Request support, Open support diagnostics N/A none none existing dashboard empty-state behavior only same as header actions N/A existing support-request audit behavior only Action hierarchy and support flows stay intact; route and breadcrumb ownership change only
Workspace operations hub Monitoring\Operations under /admin/workspaces/{workspace}/operations Scope operations, Back to ..., Show all environments clickable row to run detail none none existing operations empty-state only existing run-viewer contract only N/A no new audit behavior Filter and back-link context replace environment-panel routing; no new bulk or destructive actions

All other environment-scoped resources and diagnostic pages that today live under panel: 'tenant' or /admin/tenants/{environment} keep their current local action contracts. This slice changes their route ownership and breadcrumb shell only and must not introduce new redundant View actions, placeholder action groups, or new destructive actions.

Key Entities (include if feature involves data)

  • Workspace: the operator's primary admin context and the only Filament tenant after this cutover; owns the canonical workspace dashboard, environment chooser, and workspace operations hub.
  • Managed Environment: the environment-scoped managed target inside one workspace; owns the canonical environment dashboard route and remains the nested context for environment-scoped pages and explicit environment filters.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: All touched operator entry and drillthrough flows open workspace-first environment URLs, and no operator-visible /admin/t/ link remains on touched admin surfaces.
  • SC-002: An operator can go from workspace selection to one managed-environment dashboard and then into the workspace operations hub with preserved scope in three interactions or fewer.
  • SC-003: All touched environment-scoped pages present breadcrumb/context order Workspace -> Managed Environment -> page, and direct wrong-workspace or wrong-environment access reveals no data.
  • SC-004: Touched globally searchable resources either open a valid destination on first attempt under the new route family or no longer appear in global search.