## 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
29 KiB
Implementation Plan: Filament Workspace Tenancy & Environment Routing Cutover
Branch: 280-workspace-tenancy-environment-routing | Date: 2026-05-07 | Spec: spec.md
Input: Feature specification from specs/280-workspace-tenancy-environment-routing/spec.md
Summary
Prepare the second reserved workspace-first cutover slice that removes the temporary /admin/t operator shell, makes Workspace the only Filament tenant, and moves environment work under the canonical workspace-first route family rooted at /admin/workspaces/{workspace}/environments/{environment}. The narrow implementation path reuses the existing AdminPanelProvider, WorkspaceOverview, ManagedTenantsLanding and ChooseTenant chooser flow, TenantDashboard, Monitoring\Operations, WorkspaceOverviewBuilder, TenantDashboardSummaryBuilder, OperationRunLinks, and related navigation/context helpers while explicitly deferring Specs 281 through 287.
This plan stays intentionally bounded. Filament remains v5 on Livewire v4, provider registration remains in apps/platform/bootstrap/providers.php, no new persistence or provider extraction is introduced, no compatibility route or second panel survives, no artifact retargeting or RBAC redesign is absorbed, and no broad quality-gate or copy-neutralization work moves into this slice.
Inherited Baseline / Explicit Delta
Inherited baseline
- Spec
279already replaced the core managed-target noun withManagedEnvironmentand kept the/admin/t/{environment}shell as a temporary bridge. apps/platform/app/Providers/Filament/AdminPanelProvider.phpcurrently owns the defaultadminpanel,/admin,ChooseWorkspace,ChooseTenant,WorkspaceOverview,TenantRequiredPermissions, and the canonical workspace-scoped operations surface.apps/platform/app/Providers/Filament/TenantPanelProvider.phpstill ownsid('tenant'),path('admin/t'), andtenant(ManagedEnvironment::class, slugAttribute: 'slug'), so the operator runtime still has a second panel and second route language.apps/platform/bootstrap/providers.phpstill registers bothAdminPanelProviderandTenantPanelProvider.apps/platform/app/Support/Workspaces/WorkspaceRedirectResolver.phpstill branches toChooseTenantorTenantDashboard::getUrl(panel: 'tenant', tenant: $tenant).apps/platform/app/Filament/Pages/ChooseTenant.php,apps/platform/app/Filament/Pages/Workspaces/ManagedTenantsLanding.php,apps/platform/app/Http/Middleware/EnsureWorkspaceSelected.php,apps/platform/app/Support/Middleware/EnsureFilamentTenantSelected.php,apps/platform/app/Support/Tenants/TenantPageCategory.php, andapps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.phpstill encode/admin/t,/admin/tenants/{environment}, or explicit tenant-panel assumptions.apps/platform/app/Support/OperationRunLinks.php,apps/platform/app/Support/Navigation/RelatedNavigationResolver.php, andapps/platform/app/Filament/Pages/Monitoring/Operations.phpstill emit or expect tenant-panel destinations and workspace-canonical operations routes under/admin/operations.- Route ownership in
apps/platform/routes/web.phpstill exposes/admin,/admin/operations,/admin/operations/{run},/admin/w/{workspace}/managed-tenants,/admin/tenants/{tenant}/required-permissions, and the Filament-generated/admin/t/{tenant}/...family at the same time.
Explicit delta in this plan
- Collapse the operator-facing
tenantpanel into the existingadminpanel and makeWorkspacethe only Filament tenant. - Replace the public
/admin/t/{environment}and/admin/tenants/{environment}/required-permissionsroute families with one canonical workspace-first environment family. - Remove the legacy chooser route
/admin/w/{workspace}/managed-tenantsand the legacy operations routes/admin/operationsplus/admin/operations/{run}with no redirects, aliases, or hidden fallback readers. - Re-home the existing workspace dashboard, environment chooser, environment dashboard, and operations hub under
/admin/workspaces/{workspace}/...without creating replacement dashboards or new panel abstractions. - Update middleware, route categorization, current-context resolution, breadcrumbs, context-bar signals, and page/deep-link builders as one route-contract change rather than page-by-page exceptions.
- Keep all provider extraction, governance-artifact retargeting, provider-neutral capability work, RBAC redesign, copy-neutralization, and broad no-legacy/quality-gate follow-through deferred to Specs
281through287.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, existing workspace and environment authorization/context helpers, existing Filament panel providers and page/resource action-surface contracts
Storage: PostgreSQL, no new persistence or schema change in this slice
Testing: Pest feature tests, one Pest browser smoke, and focused grep/guard checks for legacy route language
Validation Lanes: fast-feedback, confidence, browser
Target Platform: Laravel monolith in apps/platform
Project Type: web application
Performance Goals: preserve current dashboard and operations responsiveness while changing only route ownership, panel tenancy, and context resolution; no new queue, polling, or asset load path
Constraints: no compatibility redirects or aliases, no second Filament tenant at the environment level, no new persistence, no provider extraction, no artifact retargeting, no RBAC redesign, no broad copy neutralization, no quality-gate pack work, provider registration stays in apps/platform/bootstrap/providers.php, and Filament remains v5 on Livewire v4
Scale/Scope: one operator-panel tenancy flip, one canonical workspace-first environment route family, one workspace-first operations route family, and one bounded set of chooser/middleware/link/breadcrumb/current-context updates
Likely Affected Repo Surfaces
apps/platform/app/Providers/Filament/AdminPanelProvider.phpapps/platform/app/Providers/Filament/TenantPanelProvider.phpapps/platform/bootstrap/providers.phpapps/platform/app/Filament/Pages/ChooseWorkspace.phpapps/platform/app/Filament/Pages/ChooseTenant.phpapps/platform/app/Filament/Pages/Workspaces/ManagedTenantsLanding.phpapps/platform/app/Filament/Pages/WorkspaceOverview.phpapps/platform/app/Filament/Pages/TenantDashboard.phpapps/platform/app/Filament/Pages/TenantRequiredPermissions.phpapps/platform/app/Filament/Pages/Monitoring/Operations.phpapps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.phpapps/platform/app/Http/Middleware/EnsureWorkspaceSelected.phpapps/platform/app/Support/Middleware/EnsureFilamentTenantSelected.phpapps/platform/app/Support/Tenants/TenantPageCategory.phpapps/platform/app/Support/Workspaces/WorkspaceRedirectResolver.phpapps/platform/app/Support/OperationRunLinks.phpapps/platform/app/Support/Navigation/RelatedNavigationResolver.phpapps/platform/app/Filament/Resources/TenantResource.phpapps/platform/app/Filament/Resources/Workspaces/WorkspaceResource.phpapps/platform/routes/web.php- feature, browser, and guard coverage under
apps/platform/tests/Feature,apps/platform/tests/Browser, and existing grep/guard patterns
Filament v5 / Panel Notes
- Livewire v4.0+ compliance: this slice keeps Filament v5 on Livewire v4 and changes only panel tenancy, route ownership, and current-context handling.
- Provider registration location: any provider registration change stays in
apps/platform/bootstrap/providers.php; nothing moves tobootstrap/app.php. - Global search rule: touched searchable resources must keep a valid view or edit destination or be disabled from global search in the same implementation slice. Current repo truth shows
WorkspaceResourceandTenantResourceas the search-eligible surfaces that need explicit review. - Destructive actions: no new destructive actions are introduced. Any touched existing destructive actions must preserve
->requiresConfirmation()plus current server-side authorization. - Asset strategy: no new asset registration or deployment step is planned. Existing admin theme/asset handling remains unchanged.
Workspace-first Routing Fit
- Reuse the existing
adminpanel instead of creating a third panel or a nested-environment Filament tenancy model. - Treat
WorkspaceOverviewas the canonical workspace dashboard under/admin/workspaces/{workspace}rather than leaving/adminas a second environment-like dashboard route. - Treat the current chooser stack as two reuse candidates:
ChooseWorkspaceremains the workspace chooser, whileManagedTenantsLandingplusChooseTenantform the environment-selection seams to retarget to/admin/workspaces/{workspace}/environments. - Treat
TenantDashboardas the surviving managed-environment dashboard surface, but move its route ownership and breadcrumb/context shell under the workspace-first family. - Treat
Monitoring\Operationsas the only operations hub, but move its public collection and detail routes under the workspace-first family and preserve explicitmanaged_environment_idfilter context when entered from environment pages. - Update
EnsureWorkspaceSelected,EnsureFilamentTenantSelected,TenantPageCategory, andResolvesPanelTenantContexttogether so the same route family defines tenant-bound versus workspace-scoped behavior. - Remove
/admin/tand/admin/tenants/{environment}/required-permissionsoutright in line with LEAN-001 instead of adding redirects or dual readers. - Remove
/admin/w/{workspace}/managed-tenantsand/admin/operationsplus/admin/operations/{run}outright in line with LEAN-001 instead of leaving a second chooser or operations route language behind.
UI / Surface Guardrail Plan
- Guardrail scope: changed surfaces
- Native vs custom classification summary: native Filament
- Shared-family relevance: workspace dashboard, environment chooser, managed-environment dashboard, operations hub, related navigation builders, breadcrumbs, context bars
- State layers in scope: shell, page, detail, URL-query
- Audience modes in scope: operator-MSP, support-platform
- Decision/diagnostic/raw hierarchy plan: decision-first on workspace dashboard and environment chooser, diagnostics-second on environment dashboard and operations detail, raw/support evidence remains on downstream pages only
- Raw/support gating plan: unchanged capability-gated downstream evidence; this slice changes route truth and scope signals, not evidence disclosure
- One-primary-action / duplicate-truth control: workspace dashboard stays the workspace decision surface, environment chooser stays the one dominant selection step, and environment dashboard keeps one primary follow-up action while breadcrumbs/context bars carry scope once instead of duplicating summaries
- Handling modes by drift class or surface: review-mandatory
- Repository-signal treatment: review-mandatory until grep/guard proof shows
/admin/tandpanel: 'tenant'are gone from touched operator surfaces - Special surface test profiles: standard-native-filament, global-context-shell, monitoring-state-page
- Required tests or manual smoke: functional-core, state-contract, manual-smoke
- Exception path and spread control: none; this slice removes the prior shell exception rather than introducing a new one
- Active feature PR close-out entry: Guardrail
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched: Filament panel providers, chooser pages, workspace dashboard, environment dashboard, operations page, context-bar/navigation builders, middleware/current-context helpers, route classifiers, global-search destinations
- Shared abstractions reused:
WorkspaceOverviewBuilder,TenantDashboardSummaryBuilder,WorkspaceContext,WorkspaceRedirectResolver,OperationRunLinks,RelatedNavigationResolver, existing Filament page/resource action-surface declarations - New abstraction introduced? why?: none planned; this slice should replace temporary routing/panel ownership in place
- Why the existing abstraction was sufficient or insufficient: existing builders and dashboards already own the correct operator truth, but the surrounding panel and route shell still speak a temporary environment-panel language that must be removed
- Bounded deviation / spread control: none; implementation must converge on the shared builders and one route language rather than growing another local escape hatch
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, shared link semantics only
- Central contract reused:
OperationRunLinks,RelatedNavigationResolver,Monitoring\Operations,CanonicalNavigationContext - Delegated UX behaviors: workspace-safe URL resolution for the operations collection/detail routes, explicit environment prefiltering via
managed_environment_id, and environment-to-operations back-link context - Surface-owned behavior kept local: environment dashboards and environment-scoped pages supply only the filter context and back-navigation label for the existing operations surface
- Queued DB-notification policy:
N/A - Terminal notification path:
N/A - Exception path: none
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes
- Provider-owned seams: provider-specific copy or metadata left on untouched classes such as
TenantResource, provider connection details, Microsoft-specific profile/permission semantics deferred to later specs - Platform-core seams: panel tenancy, workspace-first route nouns, chooser wording, breadcrumb/context hierarchy, current-context resolution, workspace/environment-safe deep-link builders
- Neutral platform terms / contracts preserved:
workspace,managed environment,environment,operations,findings,backup sets,evidence,required permissions - Retained provider-specific semantics and why: untouched provider-owned class names or copy may still use
tenantuntil Specs281and286; this slice only makes the public routing and context contract truthful now - Bounded extraction or follow-up path: Specs
281,282,285,286, and287
Constitution Check
GATE: Must pass before implementation begins and again after the design artifacts are complete.
- Inventory-first / snapshot truth: PASS. This slice changes routing, tenancy, and navigation only; inventory and snapshot semantics remain untouched.
- Read/write separation: PASS. No new write workflow or remote-call behavior is introduced.
- Graph contract path: PASS. No Graph call, endpoint, or contract-registry work is introduced.
- Deterministic capabilities: PASS. Current capability derivation remains; the slice only changes route and panel ownership around existing checks.
- RBAC-UX plane separation: PASS.
/adminand/systemremain separate. - Workspace isolation: PASS. Workspace membership remains the first route boundary and must stay deny-as-not-found for non-members.
- Managed-environment isolation: PASS. Wrong-workspace or inaccessible environment resolution remains
404, including explicit hostile filter hints. - Destructive action discipline: PASS by non-expansion. Touched destructive actions keep existing
->requiresConfirmation()and server-side authorization. - Global search safety: PASS with implementation condition.
WorkspaceResourceandTenantResourcemust keep valid view/edit destinations or be disabled from global search. - OperationRun / Ops-UX: PASS. The slice reuses the shared operations hub and changes only route/link semantics.
- Data minimization: PASS. No new data or provider-specific persistence is introduced.
- Test governance: PASS. Proof stays bounded to focused feature coverage, one browser smoke, and grep/guard checks.
- Proportionality / no premature abstraction: PASS. The slice removes a temporary second panel and route family instead of adding framework machinery.
- Persisted truth / behavioral state: PASS. No new persistence, state family, DTO layer, taxonomy, or abstraction is introduced.
- UI semantics / shared pattern first / Filament-native UI: PASS. Existing native Filament surfaces and shared builders remain the first path.
- Provider boundary: PASS. The plan removes provider-shaped routing from platform-core navigation instead of deepening it.
Gate evaluation: PASS.
Post-design re-check: PASS while research.md, data-model.md, quickstart.md, contracts/workspace-tenancy-environment-routing.logical.openapi.yaml, and checklists/requirements.md remain aligned and continue to defer Specs 281 through 287 explicitly.
Test Governance Check
- Test purpose / classification by changed surface: Feature, Browser
- Affected validation lanes: fast-feedback, confidence, browser
- Why this lane mix is the narrowest sufficient proof: the cutover changes public routes, panel tenancy, chooser flow, breadcrumbs, navigation helpers, and deny-as-not-found semantics. Feature tests prove route ownership and authorization boundaries, while one browser smoke proves the surviving admin-panel flow from workspace selection to environment dashboard to workspace operations.
- Narrowest proving command(s):
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"
- Fixture / helper / factory / seed / context cost risks: moderate because proof needs workspace membership, managed-environment membership, and remembered-context behaviors without widening helper defaults
- Expensive defaults or shared helper growth introduced?: no; reuse current workspace/environment helpers and keep any new fixture setup opt-in
- Heavy-family additions, promotions, or visibility changes: none
- Surface-class relief / special coverage rule: standard-native-filament relief for most pages; one browser smoke is still required because the entry flow crosses chooser, dashboard, and operations surfaces
- Closing validation and reviewer handoff: rerun the exact commands above, verify that
TenantPanelProviderno longer owns public operator routing, confirm/admin/t,/admin/tenants/{environment}/required-permissions,/admin/w/{workspace}/managed-tenants, and/admin/operationsplus/admin/operations/{run}are gone with no redirect/alias fallback, confirmChooseTenant,ManagedTenantsLanding, andWorkspaceRedirectResolveropen workspace-first destinations, confirmOperationRunLinksandRelatedNavigationResolveremit workspace-first operations URLs with explicit environment context, confirmTenantPageCategory,EnsureWorkspaceSelected,EnsureFilamentTenantSelected, andResolvesPanelTenantContextno longer treat the removed route families as active language, confirmWorkspaceResourceandTenantResourcestill satisfy the global-search destination rule or are disabled, confirm destructive actions touched by the move still require confirmation, and confirm no new asset or deploy step appears - Budget / baseline / trend follow-up: contained feature-local increase only
- Review-stop questions: did a compatibility route or dual-panel fallback appear, did legacy
panel: 'tenant'links survive, did/admin/t,/admin/tenants/{environment},/admin/w/{workspace}/managed-tenants, or/admin/operationsremain reachable, did wrong-workspace or hostile filter access stop being404, did the operations hub lose explicit environment context, did the slice absorb deferred Spec281-287work - Escalation path:
reject-or-splitif the implementation introduces compatibility routes, provider extraction, RBAC redesign, or broad copy/quality-gate work - Active feature PR close-out entry: Guardrail
- Why no dedicated follow-up spec is needed: the remaining adjacent work is already reserved as Specs
281through287; routine routing/tenancy proof stays inside this feature
Review Checklist Status
- Review checklist artifact:
checklists/requirements.md - Review outcome class:
implementation-ready - Workflow outcome:
keep - Test-governance outcome:
keep - Escalation rule: if implementation keeps
/admin/t, keepspanel: 'tenant'links, adds compatibility redirects, or absorbs deferred provider/artifact/RBAC/copy/quality-gate work, flip the workflow outcome tosplitorreject-or-split
Rollout Considerations
- Land the panel-tenancy flip, route-family rewrite, and current-context helper update as one bounded implementation slice so workspace/environment truth changes atomically.
- Remove the temporary
tenantpanel from operator routing instead of leaving a dormant compatibility shell behind. - Retarget chooser flow and shared link builders before polishing individual environment pages so route truth changes at the shared seams first.
- Keep direct route guards and grep checks in the same change set so
/admin/t,/admin/tenants/{environment},/admin/w/{workspace}/managed-tenants,/admin/operations, andpanel: 'tenant'do not re-enter the codebase quietly.
Risk Controls
- Reject any implementation that leaves
/admin/t/{environment},/admin/tenants/{environment}/required-permissions,/admin/w/{workspace}/managed-tenants, or/admin/operationsplus/admin/operations/{run}reachable through redirects, aliases, or hidden fallback readers. - Reject any implementation that introduces nested or dual Filament tenancy rather than making
Workspacethe only Filament tenant. - Reject any implementation that rebuilds dashboard signal systems instead of reusing
WorkspaceOverviewBuilderandTenantDashboardSummaryBuilder. - Reject any implementation that retargets operations links page by page instead of through
OperationRunLinksand related navigation helpers. - Reject any implementation that widens scope into provider extraction, artifact retargeting, RBAC redesign, copy neutralization, or no-legacy quality-gate work reserved for Specs
281through287.
Research & Design Outputs
research.mdrecords the surviving panel choice, workspace-only Filament tenancy, chooser-flow reuse plan, shared operations-link strategy, middleware/current-context convergence plan, global-search treatment, and proof strategy.data-model.mdcaptures the route-context and page-view-model contracts for workspace dashboard, environment chooser, managed-environment dashboard, workspace operations, and searchable destinations.quickstart.mdgives reviewers the bounded cutover flow and exact validation commands.contracts/workspace-tenancy-environment-routing.logical.openapi.yamlcaptures the conceptual GET-route and removed-route contract for the workspace-first runtime.checklists/requirements.mdrecords package readiness, boundedness, and outcome state.
Project Structure
Documentation (this feature)
specs/280-workspace-tenancy-environment-routing/
├── checklists/
│ └── requirements.md
├── contracts/
│ └── workspace-tenancy-environment-routing.logical.openapi.yaml
├── data-model.md
├── plan.md
├── quickstart.md
├── research.md
├── spec.md
└── tasks.md
Source Code (expected implementation surfaces)
apps/platform/
├── app/
│ ├── Filament/
│ │ ├── Concerns/
│ │ │ └── ResolvesPanelTenantContext.php
│ │ ├── Pages/
│ │ │ ├── ChooseTenant.php
│ │ │ ├── ChooseWorkspace.php
│ │ │ ├── TenantDashboard.php
│ │ │ ├── TenantRequiredPermissions.php
│ │ │ ├── WorkspaceOverview.php
│ │ │ ├── Monitoring/
│ │ │ │ └── Operations.php
│ │ │ └── Workspaces/
│ │ │ └── ManagedTenantsLanding.php
│ │ └── Resources/
│ │ ├── TenantResource.php
│ │ └── Workspaces/
│ │ └── WorkspaceResource.php
│ ├── Providers/Filament/
│ │ ├── AdminPanelProvider.php
│ │ └── TenantPanelProvider.php
│ ├── Http/Middleware/
│ │ └── EnsureWorkspaceSelected.php
│ └── Support/
│ ├── Middleware/
│ │ └── EnsureFilamentTenantSelected.php
│ ├── Navigation/
│ │ └── RelatedNavigationResolver.php
│ ├── Tenants/
│ │ └── TenantPageCategory.php
│ ├── Workspaces/
│ │ └── WorkspaceRedirectResolver.php
│ └── OperationRunLinks.php
├── bootstrap/
│ └── providers.php
├── routes/
│ └── web.php
└── tests/
├── Browser/
└── Feature/
Structure decision: keep the documentation package self-contained under specs/280-workspace-tenancy-environment-routing/; later implementation should modify the existing apps/platform panel, route, middleware, and navigation seams directly instead of introducing a parallel routing subsystem.
Complexity Tracking
No constitution violation or bloat exception is introduced by the plan. The slice removes a temporary panel and route family and adds no new persistence, abstraction, state family, or taxonomy.
Proportionality Review
- Current operator problem: the operator runtime still communicates two public truths by splitting workspace work under
/adminand environment work under/admin/t. - Existing structure is insufficient because: the temporary second panel is encoded in providers, chooser redirects, middleware, route categorization, breadcrumbs, and shared deep-link builders, so a local redirect fix would preserve the same structural drift.
- Narrowest correct implementation: reuse the existing
adminpanel, dashboard builders, chooser surfaces, and operations hub while replacing only the panel-tenancy and route-contract shell around them. - Ownership cost created: focused route, middleware, link-builder, and browser/feature proof work across several shared seams.
- Alternative intentionally rejected: keeping
/admin/twith redirects or dual-panel ownership, because it preserves the temporary shell and contradicts the pre-production no-legacy doctrine. - Release truth: current-release truth; this is a bounded cutover slice, not future-framework preparation.