# Implementation Plan: Legacy Tenant / Environment Context Cleanup **Branch**: `317-legacy-tenant-environment-context-cleanup` | **Date**: 2026-05-16 | **Spec**: [spec.md](/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/317-legacy-tenant-environment-context-cleanup/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: ```text 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/t` routes; 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 `OperationRunLinks` only 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`; `AdminPanelProvider` and `SystemPanelProvider` remain 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:assets` deployment 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=LegacyTenantPlatformContext` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHub` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=TenantPanel` - `cd apps/platform && ./vendor/bin/sail artisan test --filter=EnvironmentCopy` - focused browser smoke for Spec 317 surfaces - `cd apps/platform && ./vendor/bin/sail pint --test` or scoped Pint check for touched PHP files - `git 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 `tenant` as 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_decision` inventory 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) ```text 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: ```text 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: ```text 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: ```text 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, at `9b097f97 Spec 316: implement workspace hub clear filter contract (#371)`. - `specs/317-legacy-tenant-environment-context-cleanup` did 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.md` has 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: ```text specs/317-legacy-tenant-environment-context-cleanup/legacy-inventory.md specs/317-legacy-tenant-environment-context-cleanup/tenant-usage-allowlist.md ``` Inventory schema: ```text File Symbol / method / route / label Current meaning Correct meaning Classification Action Risk ``` Classification values: ```text 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: ```bash 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: ```text environment_id ``` Invalid as Environment filter state: ```text 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: ```text 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: ```text Tenant Managed tenant Current tenant Selected tenant Tenant context Tenant scope Tenant filter ``` with: ```text Environment Managed environment Current environment Selected environment Environment context Environment scope Environment filter ``` Provider-boundary copy can keep: ```text 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 1. Guardrails and inventory. 2. Tests first: static legacy guard, query alias guard, fallback guard, route guard, UI copy/helper guards. 3. Helper/class/query cleanup. 4. UI copy/current docs cleanup. 5. Spec 314-316 regression verification. 6. Focused browser verification. 7. 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:assets` deployment 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.md` and `tenant-usage-allowlist.md` are complete enough for review. - Workspace hubs use only `environment_id` for 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/t` route 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.