## Summary - replace the remaining workspace overview tenant-first copy with environment-first wording in the builder, Blade view, and focused feature assertions - add the Spec 299 workspace overview browser smoke and the final cutover audit documenting fixed copy, clean runtime scans, and allowed internal/provider/regression-guard `Tenant` references - add the Spec 299 spec package (`spec.md`, `plan.md`, `tasks.md`, checklist, audit) to close the managed-environment cutover with an explicit final seal decision ## Validation - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/WorkspaceOverviewContentTest.php tests/Feature/Filament/AdminHomeRedirectsToChooseTenantWhenWorkspaceSelectedTest.php tests/Feature/Filament/WorkspaceOverviewEmptyStatesTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/NoLegacyTenantPanelRuntimeTest.php tests/Feature/Guards/NoActiveTenantResourceRoutesTest.php tests/Feature/Guards/ManagedEnvironmentCanonicalRouteContractTest.php tests/Feature/Filament/PanelNavigationSegregationTest.php tests/Feature/Workspaces/WorkspaceIntendedUrlLegacyRejectionTest.php tests/Feature/ProviderConnections/LegacyRedirectTest.php tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Workspaces` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec299WorkspaceOverviewCutoverSealSmokeTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `git diff --check` ## Notes - Filament remains on Livewire v4. - Provider registration remains in `apps/platform/bootstrap/providers.php`. - No new panel provider or asset-strategy changes are included. - Remaining technical `Tenant` references are documented in `specs/299-managed-environment-cutover-final-seal/final-cutover-audit.md`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #354
22 KiB
Implementation Plan: Managed Environment Cutover Final Seal & Regression Guard Pack
Branch: 299-managed-environment-cutover-final-seal | Date: 2026-05-13 | Spec: spec.md
Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/299-managed-environment-cutover-final-seal/spec.md
Summary
Spec 299 is a final acceptance-and-regression package over the managed-environment cutover. The runtime app tree is already mostly aligned to the canonical owners introduced and hardened by Specs 297 and 298. The implementation therefore stays narrow:
- re-run and document the final cutover baseline in
final-cutover-audit.md - verify the runtime tree remains clean of retired tenant routes and helper generators
- seal any remaining workspace-vs-environment navigation or intended-URL seam
- bound the last touched product-facing tenant-first copy on active surfaces
- classify remaining technical, provider-specific, historical, and guard-only
Tenantreferences - run the final focused proof pack and stop with one explicit cutover decision
This plan is preparation only. It does not implement application code.
Technical Context
Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12.52.0, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Laravel Sail 1.52.0
Storage: PostgreSQL through Laravel/Sail for tests; no schema or persistence change planned
Testing: Pest via ./vendor/bin/sail artisan test --compact; targeted Browser smoke only for touched visible anchors
Validation Lanes: Feature/Guards, Feature/Workspaces, Feature/ProviderConnections, Feature/RequiredPermissions, Feature/Filament, selected Browser anchors
Target Platform: Laravel Sail local runtime and Gitea-compatible CI runners
Project Type: Laravel web application under apps/platform
Performance Goals: keep the final proof bounded and reproducible; no raw full suite unless explicitly requested
Constraints: no compatibility routes, no DB/model rename, no broad localization sweep, no provider/RBAC rewrite, no new panel, no new asset strategy
Scale/Scope: closure of route/link/navigation/copy/test allowlist seams only
Initial Repo Baseline
Preparation checks on 2026-05-13 found:
- Current branch before Spec Kit execution was
node-dev; Spec Kit created and checked out299-managed-environment-cutover-final-seal. - The working tree was clean before creating the package.
docs/product/spec-candidates.mdcurrently says there is no safe automatic next-best-prep target. Spec 299 is therefore an explicit manual promotion directed by the user, not an auto-selected queue item.- Related existing specs:
specs/297-managed-environment-canonical-route-cutover/is dependency context and carries completed-task signals.specs/298-managed-environment-terminology-copy-cleanup/is dependency context and carries completed-task plus checklist review signals.- Neither package may be rewritten back into preparation-only state.
- Current canonical owners are already repo-real:
apps/platform/app/Support/ManagedEnvironmentLinks.phpapps/platform/app/Support/Workspaces/WorkspaceIntendedUrl.phpapps/platform/app/Support/Workspaces/WorkspaceRedirectResolver.phpapps/platform/app/Providers/Filament/AdminPanelProvider.phpapps/platform/tests/Feature/Filament/PanelNavigationSegregationTest.phpapps/platform/tests/Pest.phpwithsetAdminEnvironmentContext()
- A focused baseline scan found no direct retired tenant route/helper hits under
apps/platform/app,apps/platform/resources, orapps/platform/routesforTenantPanelProvider,/admin/t,/admin/tenants, old runtime URL generators, orsetTenantPanelContext(). - The remaining confirmed pressure is in proof depth and residual wording:
apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.phpstill contains active workspace-overview labels such asAccessible tenantsandNo accessible tenants in this workspace.apps/platform/resources/views/filament/pages/workspace-overview.blade.phpstill rendersGovernance risk counts affected tenants.- The test tree still contains many technical
TenantResource::getUrl(...),TenantDashboard::getUrl(...), retired-path negative assertions, and explicitsetTenantPanelContextforbidden-pattern guards that now need final classification instead of broad removal.
Implementation-readiness note:
- The spec package can be prepared now.
- Runtime implementation must still honor the start condition from the spec: 298 changes must be committed/merged or intentionally isolated before 299 runtime edits begin.
UI / Surface Guardrail Plan
- Guardrail scope: changed workspace/environment navigation proof, workspace overview copy, and guardrail workflow evidence; no new product surface.
- Native vs custom classification summary: native Filament/Laravel/Blade surfaces plus shared route helpers.
- Shared-family relevance: navigation registration, context-bar/workspace summary copy, canonical links, intended URLs, and guard tests.
- State layers in scope: shell, page, detail, URL-query, test helper, and audit artifact.
- Audience modes in scope: operator-MSP and support-platform.
- Decision/diagnostic/raw hierarchy plan: keep workspace routes workspace-first and environment routes environment-first; do not surface extra raw/support detail.
- Raw/support gating plan: unchanged.
- One-primary-action / duplicate-truth control: no new actions; keep one scope truth per route and remove or document duplicate tenant-first wording.
- Handling modes by drift class or surface: active runtime seam = fix now; active product copy seam = fix now; technical/provider/historical reference = document in audit; broad rename request = out of scope.
- Repository-signal treatment: review-mandatory for final scans, navigation proof, helper retirement, browser anchor changes, and allowlist classification.
- Special surface test profiles:
standard-native-filament,global-context-shell,browser-smokewhen touched. - Required tests or manual smoke: focused guards and feature tests first, browser anchors only for touched visible flows.
- Exception path and spread control: every surviving
Tenantreference must be recorded infinal-cutover-audit.mdwith reason and guard status. - Active feature PR close-out entry: Guardrail / Final Cutover Seal / Smoke Coverage.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes.
- Systems touched:
ManagedEnvironmentLinksWorkspaceIntendedUrlWorkspaceRedirectResolverAdminPanelProvider- resource/page
shouldRegisterNavigation()owners WorkspaceOverviewBuilderworkspace-overview.blade.phpsetAdminEnvironmentContext()and focused guard/browser tests
- Shared abstractions reused: current canonical route helpers, current route-scope navigation owners, existing guard-test patterns, and the existing test helper vocabulary.
- New abstraction introduced? why?: none planned. Only extend existing route-scope or navigation owners if a concrete live seam is discovered.
- Why the existing abstraction was sufficient or insufficient: canonical ownership already exists for routes, links, and intended URLs. The remaining issue is final proof, classification, and narrow residual cleanup.
- Bounded deviation / spread control: technical
Tenantowners remain allowed only when documented as internal, provider-owned, historical, or regression-guard only.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, canonical operations link ownership and intended-URL normalization only.
- Central contract reused:
OperationRunLinksandManagedEnvironmentLinks::operationsUrl(...). - Delegated UX behaviors: no local lifecycle or notification behavior; only prove that
/admin/operationsresolves safely and retired tenant-scoped operation paths stay dead. - Surface-owned behavior kept local: workspace overview summary copy and existing navigation only.
- Queued DB-notification policy: N/A.
- Terminal notification path: unchanged.
- Exception path: none.
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: yes.
- Provider-owned seams: Microsoft tenant ID, Entra tenant ID, provider target-tenant scope wording, Graph permission wording.
- Platform-core seams: workspace/environment navigation and operator vocabulary, canonical route ownership, intended URL handling, workspace overview copy.
- Neutral platform terms / contracts preserved: workspace, environment, managed environment, provider connection, required permissions, diagnostics, operations, findings, evidence, reviews.
- Retained provider-specific semantics and why: provider-specific
tenantwording remains only when it describes external Microsoft/Entra truth. - Bounded extraction or follow-up path: no new framework. Structural rename remains a separate future topic if ever promoted.
Constitution Check
GATE: Must pass before runtime implementation and re-check before close-out.
- Inventory-first: no inventory or snapshot truth changes.
- Read/write separation: no new write workflow. Any touched destructive action labels must preserve existing confirmation, authorization, and audit behavior.
- Graph contract path: no new Graph calls.
- Deterministic capabilities: no capability-resolution change.
- Workspace isolation: workspace routes remain workspace-safe and must not be overridden by remembered environment context.
- Tenant isolation: canonical environment routes remain entitlement-checked; retired tenant routes remain unavailable.
- RBAC-UX: non-member/out-of-scope remains 404; member missing capability remains 403.
- OperationRun: no new lifecycle semantics; workspace operations links remain canonical.
- Proportionality / no premature abstraction: use the existing route and navigation owners; no new framework is justified.
- Persisted truth: no new application persistence. The only new artifact is the spec-local cutover audit.
- Provider boundary: generic operator vocabulary must stay environment-first; provider-specific tenant wording remains bounded.
- Test governance: validation remains in the narrowest honest lanes; no hidden full-suite requirement.
- Filament-native UI: Filament remains v5 on Livewire v4, no new panel, no ad hoc styling.
Filament v5 Output Contract
- Livewire compliance: Filament v5 targets Livewire v4.0+; current app has Livewire 4.1.4.
- Provider registration location: provider registration remains in
apps/platform/bootstrap/providers.php; this package must not restore any retired panel provider. - Globally searchable resources: any remaining technical
TenantResourcesurface must stay non-primary and must not leak old routes through global search. - Destructive actions: any touched restore/remove/archive action must still use
->action(...),->requiresConfirmation(), and server-side authorization. - Asset strategy: unchanged. If implementation unexpectedly registers assets, deployment must include
cd apps/platform && php artisan filament:assets. - Testing plan: touched pages/resources are covered with focused Pest/Filament tests, plus explicit route/helper/copy guards and selected browser anchors.
Test Governance Check
- Test purpose / classification by changed surface: Feature guards for route/helper/copy regression, Feature/Filament and Feature/Workspaces for navigation proof, Browser for touched visible anchors only.
- Affected validation lanes: Feature/Guards, Feature/Workspaces, Feature/ProviderConnections, Feature/RequiredPermissions, Feature/Filament, selected Browser anchors.
- Why this lane mix is the narrowest sufficient proof: the goal is final cutover sealing, not broad behavior changes. Focused lanes prove route, navigation, copy, and allowlist integrity without reopening unrelated suites.
- Narrowest proving command(s):
cd apps/platform
./vendor/bin/sail artisan test --compact \
tests/Feature/Guards/NoLegacyTenantPanelRuntimeTest.php \
tests/Feature/Guards/NoActiveTenantResourceRoutesTest.php \
tests/Feature/Guards/ManagedEnvironmentCanonicalRouteContractTest.php \
tests/Feature/Filament/PanelNavigationSegregationTest.php \
tests/Feature/Workspaces/WorkspaceIntendedUrlLegacyRejectionTest.php
- Fixture / helper / factory / seed / context cost risks: do not widen
setAdminEnvironmentContext()or add new expensive defaults to prove this package. - Expensive defaults or shared helper growth introduced?: none planned.
- Heavy-family additions, promotions, or visibility changes: none planned; browser runs stay anchor-only.
- Surface-class relief / special coverage rule:
standard-native-filamentplusglobal-context-shell; browser only when touched. - Closing validation and reviewer handoff: rerun the focused proof pack, final scans, selected lanes, browser anchors if touched, Pint, and
git diff --check. - Budget / baseline / trend follow-up: none expected beyond recording any unexpected browser or guard runtime drift.
- Review-stop questions: Did any active runtime legacy seam remain? Did workspace navigation still leak environment-owned entries? Did any active product copy remain tenant-first without classification? Did the proof pack stay focused?
- Escalation path: document-in-feature for allowed references; blocked-by-prerequisite or blocked-by-runtime-finding if 298 is not landed or a live seam remains.
- Active feature PR close-out entry: Guardrail / Final Cutover Seal / Smoke Coverage.
- Why no dedicated follow-up spec is needed: this package exists specifically to close the current cutover topic without reopening broader rename work.
Project Structure
Documentation (this feature)
specs/299-managed-environment-cutover-final-seal/
├── spec.md
├── plan.md
├── tasks.md
├── final-cutover-audit.md
└── checklists/
└── requirements.md
Source Code (repository root)
Likely touched implementation surfaces if a concrete remaining seam is found:
apps/platform/app/
├── Providers/Filament/AdminPanelProvider.php
├── Support/ManagedEnvironmentLinks.php
├── Support/Workspaces/WorkspaceIntendedUrl.php
├── Support/Workspaces/WorkspaceRedirectResolver.php
├── Support/Workspaces/WorkspaceOverviewBuilder.php
└── Filament/**
apps/platform/resources/views/
└── filament/pages/workspace-overview.blade.php
apps/platform/tests/
├── Pest.php
├── Feature/Guards/**
├── Feature/Workspaces/**
├── Feature/Filament/**
└── Browser/**
Structure Decision: stay inside the existing Laravel/Filament app and spec package shape; do not create new application folders or dependencies.
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
Spec-local final-cutover-audit.md |
The repo needs one durable final acceptance record that separates active drift from allowed references | A one-paragraph close-out would not preserve the allowlist or proof obligations |
| Cross-cutting guard pack | The remaining risk spans routes, navigation, intended URLs, copy, and tests | One local cleanup would not seal the cutover topic |
Phase 0: Start Condition And Safety Gate
- Run:
git status --short --branch
git diff --stat
git log -1 --oneline
- Confirm Spec 298 changes are committed/merged into the implementation base or intentionally isolated in a separate clean worktree/session branch.
- Stop if unrelated uncommitted changes are present.
- Read:
.specify/memory/constitution.md
specs/297-managed-environment-canonical-route-cutover/
specs/298-managed-environment-terminology-copy-cleanup/
Phase 1: Baseline Final Cutover Audit
Refresh final-cutover-audit.md before runtime edits:
git status --short --branch
git diff --stat
cd apps/platform
./vendor/bin/sail artisan route:list | rg "admin/t|admin/tenants|workspaces/.*/environments|operations|provider-connections|required-permissions"
rg "TenantPanelProvider|panel:\s*'tenant'|panel:\s*\"tenant\"|/admin/t/|/admin/tenants|filament\.admin\.resources\.tenants|TenantResource::getUrl|TenantDashboard::getUrl|TenantRequiredPermissions::getUrl|setTenantPanelContext" app resources routes --glob '!vendor' --glob '!node_modules'
rg "setTenantPanelContext|panel:\s*'tenant'|panel:\s*\"tenant\"|/admin/t/|/admin/tenants|TenantResource::getUrl|TenantDashboard::getUrl|TenantRequiredPermissions::getUrl" tests --glob '!vendor' --glob '!node_modules'
rg "Tenant dashboard|Tenant detail|Open tenant|Select tenant|Tenant scope|Tenant memberships|Remove tenant|Restore tenant|Accessible tenants|affected tenants" app resources lang tests --glob '!vendor' --glob '!node_modules'
rg "shouldRegisterNavigation|getNavigationGroup|getNavigationLabel|getNavigationSort|Filament::getTenant|TenantPageCategory|setAdminEnvironmentContext|WorkspaceContext" app tests --glob '!vendor' --glob '!node_modules'
Implementation intent:
- if the runtime app tree is still clean, keep it that way and move to proof depth
- if a live runtime seam appears, fix only that seam
- classify every remaining hit as active runtime, test-only, copy-only, provider-specific, internal, historical, or guard-only
Phase 2: Runtime Final Seal
- Inspect
ManagedEnvironmentLinks,WorkspaceIntendedUrl,WorkspaceRedirectResolver, andAdminPanelProvideras the current canonical owners. - Keep
TenantPanelProviderabsent from the runtime app tree and registration. - Verify
TenantResource,TenantDashboard, andTenantRequiredPermissionsremain technical-only or route through canonical owners without reviving retired route families. - If a direct runtime legacy hit still exists, replace it with the existing canonical helper or route owner. Do not add compatibility routes or aliases.
- Re-run the focused runtime source scan and update
final-cutover-audit.md.
Phase 3: Navigation Seal
- Re-prove workspace vs environment navigation using the current route, not stale remembered environment state.
- Keep workspace surfaces limited to workspace-owned navigation: Overview, Operations, Alerts, Audit Log, Governance inbox, Customer reviews, Manage workspaces, Integrations, Settings.
- Keep environment-owned navigation limited to canonical environment routes.
- Reuse existing
shouldRegisterNavigation()andTenantPageCategory/ route-scope owners rather than inventing a new navigation framework. - Update focused tests or resource/page navigation owners only when the final proof surfaces a live leak.
Phase 4: Intended URL And Helper Retirement Proof
- Re-prove that
WorkspaceIntendedUrlandWorkspaceRedirectResolverreject/admin/t...and/admin/tenants...paths. - Re-prove that
/admin/operationsonly normalizes to the canonical workspace operations route. - Verify
setAdminEnvironmentContext()remains the current helper. - Leave
setTenantPanelContextonly inside explicit forbidden-pattern guards, if anywhere.
Phase 5: Product Copy Boundary And Allowlist
- Start with the confirmed active workspace-overview copy seams in
WorkspaceOverviewBuilder.phpandworkspace-overview.blade.php. - Replace touched product-facing tenant-first wording with environment-first wording where the subject is a managed environment.
- Leave provider-specific Microsoft/Entra tenant terms untouched when the provider is the subject.
- Classify technical/internal/historical/guard-only
Tenantreferences infinal-cutover-audit.mdrather than trying to erase the entire repo.
Phase 6: Final Proof Pack
Run the focused proof pack:
cd apps/platform
./vendor/bin/sail artisan test --compact \
tests/Feature/Guards/NoLegacyTenantPanelRuntimeTest.php \
tests/Feature/Guards/NoActiveTenantResourceRoutesTest.php \
tests/Feature/Guards/ManagedEnvironmentCanonicalRouteContractTest.php \
tests/Feature/Guards/WorkspaceEnvironmentNavigationSegregationTest.php \
tests/Feature/Workspaces/WorkspaceIntendedUrlLegacyRejectionTest.php \
tests/Feature/ProviderConnections/LegacyRedirectTest.php \
tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php \
tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php \
tests/Feature/Filament/ManagedEnvironmentAccessScopeManagementTest.php \
tests/Feature/Rbac/ProviderConnectionWorkspaceFirstPolicyTest.php
./vendor/bin/sail artisan test --compact tests/Feature/Guards
./vendor/bin/sail artisan test --compact tests/Feature/Workspaces
./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections
./vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions
./vendor/bin/sail artisan test --compact tests/Feature/Filament
./vendor/bin/sail artisan test --compact \
tests/Browser/Spec281ProviderConnectionScopeSmokeTest.php \
tests/Browser/Spec285WorkspaceRbacEnvironmentAccessSmokeTest.php \
tests/Browser/Dashboard/TenantDashboardProductizationSmokeTest.php \
tests/Browser/Spec192RecordPageHeaderDisciplineSmokeTest.php
./vendor/bin/sail bin pint --dirty --format agent
Then from the repo root:
git diff --check
Finally rerun the route/source scans from Phase 1 and update the audit with the final clean or blocked state.
Phase 7: Close-Out
- Update
final-cutover-audit.mdwith final findings, allowlists, commands, and outcomes. - Record the Filament v5 output contract in the implementation summary.
- End with one explicit decision string:
merge-ready; managed environment cutover sealedmerge-ready with documented allowed internal Tenant referencesblocked by active legacy runtime findingblocked by navigation context leak
Explicit Follow-Ups / Out Of Scope
- DB/model/table rename from
TenanttoManagedEnvironment - broad historical or documentation copy sweep
- provider-architecture rewrite
- new RBAC model or new product navigation framework
- new feature work unrelated to cutover closure