# 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.
