# Tasks: Environment-Owned Surface Routing & Shell Context Contract **Input**: Design documents from `/specs/319-environment-owned-surface-routing-shell-context-contract/` **Prerequisites**: `plan.md`, `spec.md` **Tests**: Required. This is a runtime route/shell/access contract change. ## Test Governance Checklist - [x] Lane assignment is named and is the narrowest sufficient proof for route, shell, copy, CTA, cross-workspace, remembered fallback, and browser behavior. - [x] New or changed tests stay in the smallest honest family; browser additions are explicit. - [x] Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default. - [x] Planned validation commands cover the change without pulling in unrelated lane cost. - [x] The declared surface test profile `global-context-shell` is explicit. - [x] Any material budget, baseline, trend, or escalation note is recorded in the implementation close-out. ## Phase 1: Guardrails and Repo Verification **Purpose**: Confirm current repo truth before runtime edits. - [x] T001 Verify the implementation starts from branch `319-environment-owned-surface-routing-shell-context-contract` and the worktree has no unrelated user changes. - [x] T002 Re-read Specs 313-318, especially `specs/318-admin-surface-scope-shell-context-audit/mismatch-findings.md`, `audit-report.md`, `recommended-fixes.md`, and `page-matrix.md`. - [x] T003 Confirm Laravel/Filament/Livewire/Pest versions through Laravel Boost `application_info`. - [x] T004 Confirm no migration, seeder, package, env var, queue, scheduler, storage, or deployment asset change is required. - [x] T005 Inventory current Baseline Compare route names, URLs, page registration, shell resolution, and old URL behavior in `apps/platform/app/Providers/Filament/AdminPanelProvider.php`, `apps/platform/routes/web.php`, and `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`. - [x] T006 Inventory all Baseline Compare link generators with `rg "BaselineCompareLanding::getUrl|baseline-compare-landing|Baseline Compare" apps/platform/app apps/platform/resources apps/platform/tests`. - [x] T007 Confirm `WorkspaceHubRegistry` does not include Baseline Compare and record it as a must-preserve fact. - [x] T008 Confirm the canonical route shape to use from existing Environment routes under `/admin/workspaces/{workspace}/environments/{environment}/...`. - [x] T009 Identify any existing test that asserts remembered Environment fallback for Baseline Compare and mark it for replacement rather than preservation. ## Phase 2: Tests First / Contract Coverage **Purpose**: Add failing or alongside tests that define the new contract. - [x] T010 Add/update a unit test in `apps/platform/tests/Unit/Tenants/AdminSurfaceScopeTest.php` proving `/admin/workspaces/{workspace}/environments/{environment}/baseline-compare` is `AdminSurfaceScope::EnvironmentBound`. - [x] T011 Add/update `apps/platform/tests/Feature/Navigation/WorkspaceHubRegistryTest.php` proving Baseline Compare is not a workspace hub and remains excluded from workspace hub handling. - [x] T012 Add a feature test proving the canonical Baseline Compare Environment route opens for an authorized user and renders the Baseline Compare page with Workspace + Environment shell context. - [x] T013 Add a feature test proving the old clean workspace-only Baseline Compare URL does not render the page after remembered Environment context is cleared. - [x] T014 Add a feature test proving the old workspace-style Baseline Compare URL with `?environment_id=...` does not render as canonical Baseline Compare. - [x] T015 Add a feature test proving remembered Environment state alone does not allow Baseline Compare to render from the old clean URL. - [x] T016 Add a feature test proving Workspace A + Environment B from Workspace B is rejected as 404/safe no-access with no workspace switch. - [x] T017 Add a Livewire or feature test proving Baseline Compare "this environment" copy only appears when active Environment shell context exists. - [x] T018 Add a feature test proving Environment Dashboard Baseline Compare CTA/action URL uses the canonical Environment route. - [x] T019 Add CTA URL assertions that no `environment_id`, `tenant`, `tenant_id`, `managed_environment_id`, `tenant_scope`, or `tableFilters` appears. - [x] T020 Replace or update `apps/platform/tests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php` so it no longer expects remembered admin tenant fallback. - [x] T021 Add/keep a test proving existing Compare Now action still uses confirmation, action execution, capability authorization, and OperationRun UX after route hardening. - [x] T022 Add/keep Decision Register regression coverage proving clean workspace URL remains workspace hub with no active Environment shell. - [x] T023 Add/keep Decision Register regression coverage proving `?environment_id=...` remains a filtered workspace hub with visible chip and no active Environment shell. - [x] T024 Add/keep Spec 314-316 regression coverage for workspace hub clean entry, Environment CTA filter, and clear filter behavior. - [x] T025 Add/keep Spec 317 regression coverage proving legacy Tenant aliases are not resurrected. ## Phase 3: Canonical Route Implementation **Purpose**: Make Baseline Compare route-owned by Workspace + Environment. - [x] T026 Implement the canonical Baseline Compare Environment route in `apps/platform/routes/web.php` or the narrowest repo-consistent Filament page route mechanism. - [x] T027 Ensure the route uses the established Workspace route binding and ManagedEnvironment route key pattern (`{environment:slug}` if consistent with existing routes). - [x] T028 Ensure route/model resolution validates `environment.workspace_id === workspace.id` before rendering. - [x] T029 Ensure invalid Workspace/Environment combinations return 404/safe no-access without revealing the foreign Environment. - [x] T030 Ensure the canonical route flows through admin panel middleware, workspace membership checks, and Environment-bound context handling. - [x] T031 Disable, remove, or invalidate the old unbound `/admin/baseline-compare-landing` render path without adding a compatibility layer. - [x] T032 Ensure old URLs with `environment_id` do not become compatibility redirects unless a documented existing convention makes redirect unavoidable. - [x] T033 If redirect is unavoidable, validate Workspace/Environment relationship, redirect only to canonical route, emit no legacy alias support, and cover with tests. - [x] T034 Ensure `AdminSurfaceScope` classification for the canonical path is Environment-bound without adding a new broad scope enum unless unavoidable. ## Phase 4: Baseline Compare Page and Shell Context **Purpose**: Remove hidden context reliance from the page. - [x] T035 Update `apps/platform/app/Filament/Pages/BaselineCompareLanding.php` so valid rendering requires route-owned Environment context. - [x] T036 Remove `UsesAdminEnvironmentFilterQueryParameter` from Baseline Compare if it remains a query-based access path. - [x] T037 Ensure `canAccess()` cannot pass from remembered Environment, last Environment, provider tenant ID, or `environment_id` query on an old URL. - [x] T038 Ensure `mount()` and `refreshStats()` only operate when canonical route Environment context is active. - [x] T039 Ensure missing Environment context returns safe no-access or never reaches render. - [x] T040 Ensure page breadcrumbs/header/title/copy align with active Environment ownership. - [x] T041 Ensure `getFindingsUrl()`, `getRunUrl()`, and `openCompareMatrixUrl()` still generate safe links from canonical Environment context. - [x] T042 Ensure Compare Now still uses existing `BaselineCompareService`, `OperationUxPresenter`, `OpsUxBrowserEvents`, and `OperationRunLinks`. ## Phase 5: Entry Points and Navigation **Purpose**: Update all in-scope links to the canonical Environment route. - [x] T043 Update `apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php` Baseline Compare action URL. - [x] T044 Update `apps/platform/app/Filament/Widgets/ManagedEnvironment/BaselineCompareCoverageBanner.php` Baseline Compare landing URL. - [x] T045 Update `apps/platform/app/Filament/Widgets/Dashboard/BaselineCompareNow.php` Baseline Compare landing URL. - [x] T046 Update `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php` Baseline Compare action URL. - [x] T047 Update `apps/platform/app/Filament/Pages/BaselineCompareMatrix.php` per-Environment Baseline Compare links if they remain in scope. - [x] T048 Add or update `apps/platform/app/Support/ManagedEnvironmentLinks.php` with a narrow Baseline Compare Environment URL helper only if this reduces repeated route generation. - [x] T049 Ensure Environment Dashboard CTA/action emits no `environment_id`, `tenant`, `tenant_id`, `managed_environment_id`, `tenant_scope`, or `tableFilters`. - [x] T050 Ensure Baseline Compare appears only as Environment-owned navigation/action when an active Environment context exists. - [x] T051 Ensure workspace sidebar remains free of Baseline Compare as a workspace-wide hub. - [x] T052 Ensure `WorkspaceSidebarNavigation` and `WorkspaceHubRegistry` do not gain Baseline Compare as a workspace hub entry. ## Phase 6: Related Environment-Owned Page Inspection **Purpose**: Fix only same-class mismatches found during implementation. - [x] T053 Inspect Required Permissions, Provider Readiness/Diagnostics, Environment Diagnostics, Inventory/Coverage, Backup/Restore Environment-owned views, Findings/Risk Exceptions, Evidence, Environment Reviews, Stored Reports, and Review Packs for route/shell/copy mismatch. - [x] T054 If a touched related page has the same mismatch, update it using the same Environment-owned route/shell rule and add focused tests. - [x] T055 If a related page is already correct or belongs to Spec 320/321, document it in the implementation close-out and do not modify it. - [x] T056 Confirm Baselines, Baseline Snapshots, Baseline Compare Matrix, Cross-environment Compare, Alerts, and Audit Log are not changed under Spec 319 unless repo analysis proves direct Baseline Compare dependency. ## Phase 7: Browser Verification **Purpose**: Prove visible route/shell/copy behavior. - [x] T057 Start local platform stack using Sail or the repo platform dev command. - [x] T058 Browser Flow A: Environment Dashboard -> Baseline Compare CTA, verify canonical Environment URL, no legacy query params, Workspace + Environment shell, aligned breadcrumb/header/copy. - [x] T059 Save Flow A screenshot to `specs/319-environment-owned-surface-routing-shell-context-contract/artifacts/screenshots/environment-cta--baseline-compare.png`. - [x] T060 Browser Flow B: open old clean workspace-only Baseline Compare URL if route exists and verify rejection/no render/no remembered fallback. - [x] T061 Save Flow B screenshot or route-absence note as `direct-clean--baseline-compare--rejected.png`. - [x] T062 Browser Flow C: open old workspace-style `?environment_id=...` Baseline Compare URL if route exists and verify rejection/non-canonical behavior. - [x] T063 Save Flow C screenshot or route-absence note as `direct-filtered--baseline-compare--rejected.png`. - [x] T064 Browser Flow D: reload canonical Baseline Compare route and verify shell/copy remains Workspace + Environment. - [x] T065 Save Flow D screenshot to `baseline-compare--after-reload.png`. - [x] T066 Browser Flow E: Environment Dashboard -> Baseline Compare -> Decision Register -> back -> forward, verify Baseline Compare Environment shell and Decision Register workspace shell. - [x] T067 Save Flow E screenshots to `baseline-compare--back-forward.png` and `decision-register--regression.png` where useful. - [x] T068 If browser setup cannot be made deterministic, document exact blocker and available alternate proof in the implementation close-out. ## Phase 8: Final Validation and Close-Out **Purpose**: Finish with tests, formatting, and implementation report. - [x] T069 Run focused Baseline Compare tests: `cd apps/platform && ./vendor/bin/sail artisan test --filter=BaselineCompare`. - [x] T070 Run classifier/registry tests: `cd apps/platform && ./vendor/bin/sail artisan test --filter=AdminSurfaceScope` and `cd apps/platform && ./vendor/bin/sail artisan test --filter=WorkspaceHubRegistry`. - [x] T071 Run Decision Register regression tests: `cd apps/platform && ./vendor/bin/sail artisan test --filter=DecisionRegister`. - [x] T072 Run relevant WorkspaceHub regression tests for Specs 314-316. - [x] T073 Run relevant LegacyTenantPlatformContextCleanup/Spec 317 regression tests. - [x] T074 Run formatting for touched PHP files, including `cd apps/platform && ./vendor/bin/sail pint --test` or a scoped Pint command. - [x] T075 Run `git diff --check`. - [x] T076 Confirm no migrations, seeders, package files, env vars, queues, scheduler, storage, or deployment asset files changed. - [x] T077 Confirm no backwards compatibility layer, old route redirect, dual route model, or legacy query alias support was introduced. - [x] T078 Prepare final implementation report with changed behavior, classification, canonical route, removed/invalidated routes, files changed, tests, browser verification, screenshots, follow-ups 320/321/322, and any unrelated residual failures. ## Non-Tasks / Scope Guards - [x] NT001 Do not implement Spec 320 workspace-owned analysis shell cutover. - [x] NT002 Do not implement Spec 321 Alerts/Audit Log filter decision. - [x] NT003 Do not implement Spec 322 durable browser no-drift infrastructure. - [x] NT004 Do not add `environment_id` filter support to Baseline Compare. - [x] NT005 Do not make Baseline Compare workspace-wide. - [x] NT006 Do not add compatibility redirects, aliases, dual-param support, or remembered fallback. - [x] NT007 Do not create migrations, seeders, packages, env vars, queues, scheduler, storage, or Filament assets. ## Dependencies ```text Phase 1 -> Phase 2 -> Phase 3 -> Phase 4 -> Phase 5 -> Phase 6 -> Phase 7 -> Phase 8 ``` Route tests (T010-T016) should be in place before route implementation. Entry point tests (T018-T019) should be in place before link updates. Browser verification runs after runtime implementation. ## Parallel Opportunities - T010-T024 can be split by test file after the canonical route shape is agreed. - T043-T047 can be updated in parallel because they touch separate entry-point files. - T069-T073 can run independently after implementation, subject to Sail/test environment availability. ## MVP Scope The MVP is Baseline Compare canonical Environment route, invalid old URL behavior, Environment Dashboard CTA update, cross-workspace rejection, no remembered fallback, and Decision Register regression. Related Environment-owned pages are inspect-only unless the same mismatch is confirmed. ## Implementation Evidence - Canonical route registered: `/admin/workspaces/{workspace}/environments/{environment}/baseline-compare`. - Old `/admin/baseline-compare-landing` and `/admin/baseline-compare-landing?environment_id=...` return Not Found; no redirect or compatibility alias was added. - Browser smoke artifacts saved under `artifacts/screenshots/`. - Focused validation passed: - `./vendor/bin/sail artisan test` on Baseline Compare route/component/navigation/authorization contract files: 112 tests, 345 assertions. - `./vendor/bin/sail artisan test tests/Feature/Governance/DecisionRegisterWorkspaceHubContractTest.php` - `./vendor/bin/sail artisan test tests/Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php tests/Feature/Navigation/WorkspaceHubClearFilterContractTest.php` - `./vendor/bin/sail artisan test tests/Feature/Guards/LegacyTenantPlatformContextCleanupTest.php` - scoped Pint on touched PHP files. - `git diff --check` - Broader `./vendor/bin/sail artisan test --filter=DecisionRegister` surfaced an existing unrelated failure in `FindingExceptionDecisionRegisterNavigationTest` where the expected back URL still includes `managed_environment_id`; no Spec 319 files or Decision Register code were changed for that. ## Reopened Validation Note Spec 322's broader no-drift regression split exposed five Baseline Compare tests that still mounted `BaselineCompareLanding` without route-owned Environment context. That direct Livewire mount contradicted the Spec 319 hard cutover even though the runtime route contract was already canonical. Fix applied on the 319 session branch: - Extended the existing `baselineCompareLandingLivewire()` test helper so tests can pass an explicit acting user while preserving the canonical Baseline Compare referer and `environment` mount parameter. - Updated Baseline Compare explanation, summary-consistency, authorization, gap-surface, and action-surface tests to mount through explicit Environment ownership instead of remembered/implicit panel tenant state. - Confirmed no direct `Livewire::test(BaselineCompareLanding::class)` Feature/Unit mount remains. Validation after reopening: - `./vendor/bin/sail artisan test tests/Feature/Baselines/BaselineCompareExplanationFallbackTest.php tests/Feature/Filament/BaselineCompareExplanationSurfaceTest.php tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php --compact` - Result: 5 passed, 42 assertions. - `./vendor/bin/sail artisan test tests/Feature/Filament/BaselineActionAuthorizationTest.php tests/Feature/Filament/BaselineGapSurfacesDbOnlyRenderTest.php tests/Feature/Guards/ActionSurfaceContractTest.php --filter='baseline|compareNow|full content' --compact` - Result: 20 passed, 199 assertions. - `./vendor/bin/sail artisan test tests/Unit tests/Feature --filter='WorkspaceHub|EnvironmentFilter|ClearFilter|LegacyTenant|BaselineCompare|WorkspaceOwnedAnalysis|AlertsAudit' --compact` - Result: 233 passed, 1826 assertions.