## Summary - remove legacy tenant-scoped routing and middleware paths in favor of the current environment/workspace context flow - update Filament pages and resources to use the cleaned-up admin surface and environment filter context - add the related spec 317 artifacts and targeted tests for environment filter state and legacy context cleanup ## Testing - not run as part of this commit/push/PR workflow Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #372
24 KiB
Implementation Plan: Legacy Tenant / Environment Context Cleanup
Branch: 317-legacy-tenant-environment-context-cleanup | Date: 2026-05-16 | Spec: spec.md
Input: Feature specification from /specs/317-legacy-tenant-environment-context-cleanup/spec.md
Preparation status: Specification artifacts only. No runtime implementation has been performed by this preparation step.
Summary
Spec 317 performs the hard-cut cleanup that follows Specs 314-316:
314: sidebar/global entry -> clean workspace-wide hub
315: Environment CTA -> workspace hub ?environment_id=...
316: Clear filter -> clean workspace-wide hub, reload-safe
317: remove old Tenant platform-context names, aliases, fallbacks, routes, copy, and docs drift
The implementation must remove or quarantine legacy Tenant platform-context residue while preserving provider-boundary Tenant terminology for Microsoft/Entra/provider identity. Workspace remains the primary platform context, Environment remains the explicit secondary filter/context, and Provider Tenant remains external identity only.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52.0
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Laravel Sail, Laravel Socialite, Laravel MCP
Storage: PostgreSQL; default expectation is no schema changes
Testing: Pest 4.3.1 / PHPUnit 12.5.4; focused browser smoke where applicable
Validation Lanes: fast-feedback for static/feature guards, confidence for Filament/Livewire behavior, browser for active UI/link verification
Target Platform: Laravel admin application under apps/platform, local development through Sail, staging/production through Dokploy
Project Type: Web application, Laravel/Filament admin panel
Performance Goals: Static guards should scan bounded paths and avoid broad expensive runtime setup. Runtime cleanup should not add query overhead.
Constraints: Hard cutover. No compatibility aliases, legacy redirects, dual-param readers, migration shims, new packages, env vars, queues, scheduler, storage, or broad cosmetic DB renames.
Scale/Scope: Cross-cutting cleanup across admin navigation/context code, Workspace hubs, Environment pages, provider-boundary copy, tests, current docs/spec candidates, and route/helper semantics.
UI / Surface Guardrail Plan
- Guardrail scope: Existing operator-facing Workspace/Environment surfaces and visible scope terminology.
- Native vs custom classification summary: Existing Filament/Livewire/Blade surfaces only. No redesign and no new styling system.
- Shared-family relevance: Navigation, context/scope signals, filter chips, URL helpers, route helpers, provider identity labels, and test/static guard outputs.
- State layers in scope: URL query, route generation, helper names, page properties, table filter state only where it still carries legacy Tenant-as-Environment state, session/remembered context where it can affect Workspace hubs, visible copy, docs current truth.
- Audience modes in scope: Operator-MSP and support-platform. Customer-read-only applies to existing Customer Review Workspace surfaces.
- Decision/diagnostic/raw hierarchy plan: Scope truth stays default-visible; provider raw IDs remain diagnostics/detail where already designed.
- Raw/support gating plan: No new raw/support data exposure.
- One-primary-action / duplicate-truth control: Do not create additional context signals. Replace old Tenant wording with the existing Workspace/Environment signal path.
- Handling modes by drift class or surface: Hard-stop for legacy query alias support and
/admin/troutes; review-mandatory for quarantined names; report-only for historical archived specs. - Repository-signal treatment: Static guards and inventory entries are required evidence.
- Special surface test profiles: global-context-shell, standard-native-filament, provider-boundary-copy.
- Required tests or manual smoke: Static legacy guard, Workspace hub legacy query guard, no Filament tenant fallback guard, route guard, UI copy guard, helper/API rename tests, Spec 314-316 regression tests, and focused browser smoke.
- Exception path and spread control: Quarantine is allowed only with inventory reason, risk, owner, and follow-up. Deprecated aliases are not allowed.
- Active feature PR close-out entry: Guardrail and Smoke Coverage.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes.
- Systems touched:
WorkspaceHubRegistry,WorkspaceHubEnvironmentFilter,WorkspaceHubFilterStateResetter,WorkspaceSidebarNavigation,CanonicalNavigationContext,ManagedEnvironmentLinks,OperationRunLinks,WorkspaceContext,OperateHubShell,CanonicalAdminTenantFilterState,TenantPageCategory,WorkspaceScopedTenantRoutes,EnsureFilamentTenantSelected, active Filament pages/resources/views, admin routes, current docs/spec candidates, and guard/browser tests. - Shared abstractions reused: Existing Workspace hub registry/filter/reset contract from Specs 314-316 and existing Filament/Livewire test patterns.
- New abstraction introduced? why?: None planned. If renaming an existing helper/class creates a new class name, it must replace the old name and keep the same bounded responsibility rather than add a parallel abstraction.
- Why the existing abstraction was sufficient or insufficient: Runtime helpers now encode the right behavior but some names still encode the wrong legacy concept. The fix is replacement/rename/removal, not another compatibility layer.
- Bounded deviation / spread control: Provider-boundary Tenant terminology remains allowed through an explicit allowlist. Historical specs remain untouched unless they are current truth.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: no.
- Central contract reused: Existing
OperationRunLinksonly if cleanup touches old route/query helper names. - Delegated UX behaviors: Existing tenant/workspace-safe URL resolution remains.
- Surface-owned behavior kept local: Existing run start/completion/status/notification behavior remains unchanged.
- 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: Microsoft/Entra provider tenant IDs, external provider tenant IDs, OAuth tenant authority segments, Graph payload
tenantId, provider connection identity metadata, and provider-specific copy. - Platform-core seams: Workspace hub query contract, Environment filter contract, Workspace shell/context, route/helper naming, UI copy, docs current truth, test/static guards.
- Neutral platform terms / contracts preserved:
Workspace,Managed Environment,Environment,environment_id,Workspace hub,Environment filter,Provider Connection,Provider Scope. - Retained provider-specific semantics and why: Tenant terminology is retained only where it means external provider identity and is necessary for Microsoft/Entra/Graph accuracy.
- Bounded extraction or follow-up path: Spec 318 handles durable browser regression coverage. Any broad schema rename or unresolved product terminology decision becomes a follow-up instead of expanding Spec 317.
Constitution Check
GATE: Must pass before implementation. Re-check after runtime changes.
- Inventory-first: no inventory/snapshot truth semantics change.
- Read/write separation: no Graph writes or destructive operations are added.
- Graph contract path: no Graph calls are introduced.
- Deterministic capabilities: existing capability checks remain; no new capability model.
- RBAC-UX: workspace/environment authorization remains authoritative. Non-member access remains 404/safe no-access; missing capability remains existing 403 behavior.
- Workspace isolation: Workspace remains primary context; cleanup must not infer Workspace/Environment from legacy Tenant state.
- Tenant isolation: provider-boundary Tenant identity must not become platform data scope. Existing environment-scoped records remain access-checked.
- Run observability: no OperationRun lifecycle behavior changes.
- Test governance (TEST-GOV-001): lane, fixture cost, static/browserscope, and reviewer handoff are explicit in spec/plan/tasks.
- Proportionality (PROP-001): cleanup artifacts and static guards are justified by current cross-surface drift risk.
- No premature abstraction (ABSTR-001): no generic context framework; replacement over layering.
- Persisted truth (PERSIST-001): no new persisted entity/table. Spec-local inventory/allowlist are implementation evidence, not product persistence.
- Behavioral state (STATE-001): no new status/state/reason family.
- UI semantics (UI-SEM-001): direct vocabulary cleanup only; no new semantic UI framework.
- Shared pattern first (XCUT-001): extend/rename existing Workspace hub helpers; do not create parallel Tenant/Environment helpers.
- Provider boundary (PROV-001): provider-specific Tenant semantics stay provider-owned and do not leak into platform-core contracts.
- V1 explicitness / few layers: direct hard cutover and guard tests.
- Spec discipline / bloat check: 317 absorbs the cleanup work that Specs 314-316 intentionally deferred; durable browser no-drift remains Spec 318.
- Filament-native UI (UI-FIL-001): no ad-hoc styling; visible copy changes remain on existing surfaces.
- Filament v5 / Livewire v4: Livewire v4.1.4 compliance is required; no Livewire v3 references.
- Provider registration: Laravel 12 panel providers remain in
apps/platform/bootstrap/providers.php;AdminPanelProviderandSystemPanelProviderremain the active providers. - Global search: no global search behavior is intentionally changed. If any Resource is touched, verify its Edit/View page or disabled global search state still satisfies Filament v5 rules.
- Destructive actions: no destructive actions are added or changed. If a touched surface already has destructive actions, verify
->action(...),->requiresConfirmation(), authorization, and audit behavior remain intact. - Asset strategy: no new Filament assets are planned;
filament:assetsdeployment requirements do not change.
Test Governance Check
- Test purpose / classification by changed surface: Static/Unit for source guards and allowlist matching; Feature/Livewire for Workspace hub query/route/helper behavior; Browser for visible copy and generated link/query verification.
- Affected validation lanes: fast-feedback, confidence, browser.
- Why this lane mix is the narrowest sufficient proof: Structural drift is best caught statically; query/route behavior requires feature tests; visible copy/link truth requires browser or rendered-view verification.
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail artisan test --filter=LegacyTenantPlatformContextcd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubcd apps/platform && ./vendor/bin/sail artisan test --filter=TenantPanelcd apps/platform && ./vendor/bin/sail artisan test --filter=EnvironmentCopy- focused browser smoke for Spec 317 surfaces
cd apps/platform && ./vendor/bin/sail pint --testor scoped Pint check for touched PHP filesgit diff --check
- Fixture / helper / factory / seed / context cost risks: Static guards should avoid DB setup. Feature/browser tests may reuse existing Workspace, ManagedEnvironment, membership/capability, provider connection, evidence, review, finding, and operation helpers. Do not widen shared setup defaults.
- Expensive defaults or shared helper growth introduced?: no.
- Heavy-family additions, promotions, or visibility changes: Focused browser smoke only; durable browser no-drift family is Spec 318.
- Surface-class relief / special coverage rule: Existing native Filament pages/resources receive ordinary behavior tests plus focused UI copy/link smoke.
- Closing validation and reviewer handoff: Review
legacy-inventory.md,tenant-usage-allowlist.md, renamed helper/class list, removed query handlers, route output, browser evidence, and Spec 314-316 regression results. - Budget / baseline / trend follow-up: none expected if static scans stay bounded.
- Review-stop questions: Does any Workspace hub still parse
tenantas Environment? Does any helper expose Tenant-named Environment behavior? Does any active UI say Tenant for Managed Environment? Does any provider-boundary allowlist entry hide platform context? Are completed specs left intact? - Escalation path: follow-up-spec for durable browser infrastructure (318), broad schema rename, or unresolved
needs_product_decisioninventory items. - Active feature PR close-out entry: Guardrail and Smoke Coverage.
- Why no dedicated follow-up spec is needed: 317 is the dedicated cleanup spec. Only durable browser regression/no-drift automation remains separate.
Project Structure
Documentation (this feature)
specs/317-legacy-tenant-environment-context-cleanup/
|-- spec.md
|-- plan.md
|-- tasks.md
|-- legacy-inventory.md # created/populated during implementation
|-- tenant-usage-allowlist.md # created/populated during implementation
|-- checklists/
| `-- requirements.md
`-- artifacts/
`-- screenshots/ # created during implementation/browser verification if useful
No research.md, data-model.md, quickstart.md, or contracts/ artifact is required for preparation because this feature introduces no data model, external API contract, or new workflow API.
Source Code (repository root)
Likely runtime files to inspect or update during implementation:
apps/platform/app/Support/Navigation/WorkspaceHubRegistry.php
apps/platform/app/Support/Navigation/WorkspaceHubEnvironmentFilter.php
apps/platform/app/Support/Navigation/WorkspaceHubFilterStateResetter.php
apps/platform/app/Support/Navigation/WorkspaceSidebarNavigation.php
apps/platform/app/Support/Navigation/CanonicalNavigationContext.php
apps/platform/app/Support/Filament/CanonicalAdminTenantFilterState.php
apps/platform/app/Support/Middleware/EnsureFilamentTenantSelected.php
apps/platform/app/Support/Tenants/TenantPageCategory.php
apps/platform/app/Support/Workspaces/WorkspaceContext.php
apps/platform/app/Support/OperateHub/OperateHubShell.php
apps/platform/app/Support/ManagedEnvironmentLinks.php
apps/platform/app/Support/Operations/OperationRunLinks.php
apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php
apps/platform/app/Providers/Filament/AdminPanelProvider.php
apps/platform/routes/web.php
apps/platform/resources/views/
apps/platform/tests/Feature/
apps/platform/tests/Browser/
Critical Workspace/Environment surfaces:
apps/platform/app/Filament/Pages/EnvironmentDashboard.php
apps/platform/app/Filament/Pages/Monitoring/Operations.php
apps/platform/app/Filament/Pages/Governance/GovernanceInbox.php
apps/platform/app/Filament/Pages/Governance/DecisionRegister.php
apps/platform/app/Filament/Pages/Monitoring/FindingExceptionsQueue.php
apps/platform/app/Filament/Resources/ProviderConnectionResource.php
apps/platform/app/Filament/Pages/Monitoring/EvidenceOverview.php
apps/platform/app/Filament/Pages/Reviews/ReviewRegister.php
apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php
apps/platform/app/Filament/Pages/EnvironmentRequiredPermissions.php
apps/platform/app/Filament/Pages/EnvironmentDiagnostics.php
Docs/current product truth candidates:
docs/product/spec-candidates.md
docs/product/roadmap.md
docs/product/principles.md
docs/product/standards/
docs/ui/
docs/architecture-guidelines.md
docs/filament-guidelines.md
docs/testing-guidelines.md
specs/313-workspace-environment-context-browser-verification/
specs/314-workspace-hub-navigation-context-contract/
specs/315-environment-cta-explicit-filter-contract/
specs/316-workspace-hub-clear-filter-contract/
Structure Decision: Laravel/Filament platform app under apps/platform. Renames stay inside existing support/page/resource/test/doc locations. No new base application folder is planned.
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| Static guard with allowlist | Prevents legacy platform-context Tenant terminology from returning while preserving provider-boundary Tenant usage | Naive grep would block valid provider terms; no guard would let old aliases return |
| Spec-local inventory and allowlist artifacts | Cleanup spans many files and requires reviewable classification before broad edits | Direct rename without classification risks breaking provider-boundary Microsoft/Entra Tenant concepts |
| Class/helper renames | Old names encode the wrong platform concept and mislead future work | Keeping aliases would preserve the legacy mental model and violate hard cutover |
Phase 0: Discovery Completed During Preparation
Relevant repository facts discovered before authoring this plan:
- Current branch before creation was
platform-dev, clean, at9b097f97 Spec 316: implement workspace hub clear filter contract (#371). specs/317-legacy-tenant-environment-context-cleanupdid not exist before this preparation.- No local or remote branch matching
317-*was present before creation. - Specs 313-316 contain completion/checklist signals and are historical baseline context.
- Specs 314-316 explicitly identify Spec 317 as the cleanup follow-up for old Tenant aliases, stale Tenant naming, remembered context drift, and
Filament::getTenant()Workspace hub usage. docs/product/roadmap.mdhas an unrelated numbering note that recommends "Spec 317" for External Support Desk / PSA Handoff; the user-supplied Spec 317 and Specs 314-316 follow-up chain supersede that numbering note for this branch.- Initial discovery found active references to
TenantPageCategory,WorkspaceScopedTenantRoutes,CanonicalAdminTenantFilterState,tenantPrefilterUrl,lastTenantId,Filament::getTenant(),/admin/t,tenant_scope,managed_environment_id, and Tenant-named tests in the expected app/test/doc areas. - Laravel Boost application info confirms PHP 8.4.15, Laravel 12.52.0, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, and PostgreSQL.
Technical Approach
1. Build inventory and allowlist first
Create:
specs/317-legacy-tenant-environment-context-cleanup/legacy-inventory.md
specs/317-legacy-tenant-environment-context-cleanup/tenant-usage-allowlist.md
Inventory schema:
File
Symbol / method / route / label
Current meaning
Correct meaning
Classification
Action
Risk
Classification values:
remove
rename_to_environment
rename_to_provider_tenant
allowed_provider_boundary
allowed_historical_archived_doc
dead_code_candidate
needs_product_decision
out_of_scope
Initial required search:
cd apps/platform
rg "\btenant\b|\bTenant\b|\btenant_id\b|\btenant_scope\b|managed_environment_id|Filament::getTenant|getTenant\(|lastTenantId|TenantPageCategory|WorkspaceScopedTenantRoutes|CanonicalAdminTenantFilterState|tenantPrefilterUrl|TenantPanelProvider|/admin/t" app resources routes tests docs specs -n
2. Remove legacy Workspace hub query alias handling
Workspace hubs must use WorkspaceHubEnvironmentFilter and accept only:
environment_id
Invalid as Environment filter state:
tenant
tenant_id
managed_environment_id
tenant_scope
environment
tableFilters
remembered Tenant
remembered Environment
Filament::getTenant()
lastTenantId
provider external tenant id
3. Rename or remove helper/class names
Use actual responsibility, not mechanical rename. Expected candidates:
tenantPrefilterUrl() -> environmentFilterUrl()
TenantPageCategory -> EnvironmentPageCategory / AdminSurfaceScope / quarantine with reason
WorkspaceScopedTenantRoutes -> WorkspaceScopedEnvironmentRoutes / EnvironmentScopedAdminRoutes / quarantine with reason
CanonicalAdminTenantFilterState -> CanonicalAdminEnvironmentFilterState / WorkspaceHubTableFilterState / quarantine with reason
EnsureFilamentTenantSelected -> EnsureEnvironmentContextSelected / ResolveAdminContext / quarantine with reason
Rules:
- no deprecated aliases
- no wrapper methods preserving old names
- no compatibility adapters
- tests updated to new names/contracts
4. Remove Workspace hub Filament::getTenant() fallback paths
Allowed:
- truly Environment-scoped pages where Filament tenant represents the selected Managed Environment
Disallowed:
- Workspace hub data scope
- default Environment for Workspace hubs
- authorization fallback for Workspace hubs
- shell context for Workspace hubs
- URL parameter source
5. Clean active UI copy and generated links
Replace platform-context:
Tenant
Managed tenant
Current tenant
Selected tenant
Tenant context
Tenant scope
Tenant filter
with:
Environment
Managed environment
Current environment
Selected environment
Environment context
Environment scope
Environment filter
Provider-boundary copy can keep:
Microsoft tenant
Entra tenant
Provider tenant ID
6. Update current docs/spec truth only
Update current docs/spec candidates where they still describe Tenant as TenantPilot platform context. Do not rewrite completed specs as implementation history. If a historical spec creates confusion in current docs, add a current-truth note in an active doc or the Spec 317 artifacts.
Implementation Phases
- Guardrails and inventory.
- Tests first: static legacy guard, query alias guard, fallback guard, route guard, UI copy/helper guards.
- Helper/class/query cleanup.
- UI copy/current docs cleanup.
- Spec 314-316 regression verification.
- Focused browser verification.
- Final report and no-compatibility confirmation.
Rollout / Deployment
- Environment variables: none expected.
- Migrations: default none. Any discovered schema rename must be explicitly justified, tested, and documented before implementation.
- Queues / scheduler: no changes expected.
- Storage / volumes: no changes expected.
- Filament assets: no new assets expected; no new
filament:assetsdeployment requirement unless implementation unexpectedly registers assets. - Staging/Production: pre-production hard cutover. No legacy URL or data compatibility is required.
Risks and Controls
- Risk: Naive Tenant cleanup breaks provider-boundary Microsoft/Entra identity.
- Control: inventory and allowlist before broad edits.
- Risk: Renaming a helper creates a hidden deprecated alias.
- Control: static helper/API guard and no-alias review.
- Risk: Workspace hub filtering regresses from Specs 314-316.
- Control: run existing 314/315/316 regression tests after cleanup.
- Risk: Static guard becomes noisy and blocks valid historical/provider references.
- Control: explicit allowlist categories and bounded scan paths.
- Risk: Route churn exceeds this cleanup.
- Control: prefer hard rename in pre-production; quarantine only with documented reason and follow-up.
Acceptance Review Checklist
legacy-inventory.mdandtenant-usage-allowlist.mdare complete enough for review.- Workspace hubs use only
environment_idfor explicit Environment filtering. - No legacy query aliases are accepted as Environment filters.
- No Workspace hub uses Filament tenant or remembered Tenant state as scope.
- No active
/admin/troute or TenantPanelProvider registration remains. - Active UI copy uses Environment where it means Managed Environment.
- Provider-boundary Tenant usage remains valid and documented.
- Current docs/spec candidates reflect Workspace-first / Environment-second terminology.
- Static, route, helper, UI copy, and regression tests pass.
- Browser smoke passes for required surfaces.
- No backwards compatibility layer was introduced.