## Summary - enforce the canonical workspace/environment scope contract for workspace hubs and environment-owned surfaces - replace first-party Operations deep links that leaked Filament `tableFilters[...]` internals with stable product-level query behavior - add the sidebar scope indicator and split environment-page navigation into explicit `Workspace-wide` and `Workspace admin` groups - remove redundant tenantless `All environments` scope badges from workspace-wide pages while preserving explicit environment filter affordances - include the Spec 338 artifacts, guard tests, and browser smoke coverage for the new contract ## Validation - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation/Spec338EnvironmentSidebarSeparationTest.php tests/Feature/Navigation/Spec338OperationRunLinksQueryContractTest.php tests/Feature/Navigation/Spec338SidebarScopeIndicatorTest.php tests/Feature/Filament/PanelNavigationSegregationTest.php` - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec338ScopeContractSmokeTest.php --compact` ## Notes - Livewire v4 compliance unchanged - Filament provider registration remains in `bootstrap/providers.php` - no destructive action behavior changed - no migrations, env var changes, or new Filament asset registration Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #409
7.2 KiB
7.2 KiB
Implementation Plan: Spec 338 - Workspace / Environment Resource Scope Contract
- Branch:
338-workspace-environment-resource-scope-contract - Date: 2026-05-30
- Spec:
specs/338-workspace-environment-resource-scope-contract/spec.md - Input: User-provided Spec 338 draft + repo inspection for link/query seams.
Summary
Harden TenantPilot’s resource scope contract by tightening the canonical deep-link and query contract for workspace hubs and by eliminating first-party helper outputs that encode Filament internals (tableFilters[...]) as a product-level URL contract.
This is contract-first and targeted:
OperationRunLinks::index(..., operationType: ...)must stop emittingtableFilters[type][value].- Evidence scope special casing under
/admin/evidence/*must be either proven real and contractual, or removed as stale ambiguity. - Environment-owned sidebar navigation must keep environment-owned entries primary and move workspace-wide/admin links into explicitly labeled cross-scope groups.
- Baseline ownership/navigation is regression-only (Spec 320 already completed; do not reopen).
Technical Context
- Language/Version: PHP 8.4.15, Laravel 12.52.x.
- Primary Dependencies: Filament 5.2.x, Livewire 4.1.x, Pest 4.x, Tailwind CSS 4.x.
- Storage: PostgreSQL; no schema change expected.
- Testing: Pest Feature tests + minimal browser smoke only if navigation presentation is materially affected.
- Validation Lanes: fast-feedback (Feature) + browser (smoke, scoped).
- Target Platform: Sail locally; Dokploy/container deployment posture unchanged.
- Project Type: Laravel monolith under
apps/platform. - Constraints: No new persisted truth, migrations, packages, env vars, queue/scheduler changes, or route architecture rewrite.
UI / Surface Guardrail Plan
- Guardrail scope: changed existing operator-facing scope/link behavior (navigation + deep links).
- Affected surfaces:
- Workspace hub links to Operations (
OperationRunLinksand anyCanonicalNavigationContextfilter payload usage). - Evidence Overview hub + “clear environment context” redirect behavior.
- Environment → workspace hub “filtered” links (
environment_idmust remain canonical). - Environment sidebar grouping for workspace-wide/admin links.
- Workspace hub links to Operations (
- Native vs custom: native Filament + existing project navigation helpers; no custom UI framework.
- Shared-family relevance: navigation entry points, scope presentation, deep links, hub filtering, OperationRun “view in collection” links.
- State layers in scope: shell scope (route-owned), URL query contract, local table filter state (internal translation only).
- Handling modes: review-mandatory.
- Required tests / smoke:
- Feature tests for URL contract + helper output.
- Optional minimal browser smoke when sidebar/scope presentation changes are user-visible.
- UI/Productization coverage: no new routes/pages expected; capture screenshots only when needed to prove a scope regression fix.
Shared Pattern & System Fit
- Cross-cutting feature marker: yes.
- Systems touched (expected):
apps/platform/app/Support/OperationRunLinks.phpapps/platform/app/Support/Navigation/CanonicalNavigationContext.phpapps/platform/app/Support/Navigation/AdminSurfaceScope.phpapps/platform/app/Support/Navigation/WorkspaceHubNavigation.phpapps/platform/app/Http/Controllers/ClearEnvironmentContextController.phpapps/platform/app/Support/Navigation/WorkspaceHubRegistry.phpapps/platform/app/Support/Navigation/WorkspaceSidebarNavigation.php
- New abstraction introduced?:
WorkspaceHubNavigation, a narrow helper for environment-surface hub grouping and explicitenvironment_idURL carry. - Shared abstractions reused: existing
AdminSurfaceScope+ hub registry + navigation context; do not create a second taxonomy framework. - Bounded deviation: if Filament requires
tableFiltersinternally, keep it internal (page-level translation) and keep first-party helper output contract stable.
OperationRun UX Impact
Link semantics only (no new OperationRun types, no lifecycle changes):
- Stop emitting Filament internals as deep-link contract for operation type filtering.
- Decide between:
operation_type=<canonical-code>accepted by Operations page and mapped to internal table state, or- removing operation-type deep-linking entirely if safe mapping is not feasible without bloat.
Implementation Approach
Phase 1 — Repo truth + failing tests first
- Inventory current first-party helper outputs and navigation contexts that emit:
tableFilters[...](confirmed inOperationRunLinks; re-checkCanonicalNavigationContextusage and call sites)- legacy
/admin/evidence/*special casing branches (AdminSurfaceScope,ClearEnvironmentContextController)
- Add failing tests that lock the desired contract:
OperationRunLinks::index(..., operationType: ...)must not containtableFilters.- Evidence Overview is workspace hub; any
/admin/evidence/*environment-scope handling is either intentional + tested or removed.
Phase 2 — OperationRunLinks query contract
- Change
OperationRunLinks::index:- replace
tableFilters[type][value]emission with a stable query key (operation_type) or remove operation-type deep linking.
- replace
- Update the Operations page boundary to translate
operation_typeinto internal table state where needed (keepenvironment_idcanonical).
Phase 3 — Navigation context payload hygiene
- Re-check
CanonicalNavigationContext::toQuery()usage:- prefer keeping navigation metadata under
nav[...]only, - avoid emitting additional top-level filter payload that encodes
tableFiltersfor hub filtering whenenvironment_idis sufficient.
- prefer keeping navigation metadata under
- Adjust the specific call sites (e.g. RelatedNavigationResolver contexts) that currently inject
tableFilters[managed_environment_id]into query strings when linking to Operations.
Phase 4 — Evidence scope special casing
- Verify actual route inventory for
/admin/evidence/*beyond overview. - Remove stale classification or redirect rules only when route inventory proves they are not real, or explicitly document + test the remaining route family if it is still reachable.
Phase 5 — Validation and regression posture
- Split Environment sidebar IA:
- keep environment-owned resources in their domain groups,
- move workspace hub entries into “Workspace-wide” on environment pages,
- move workspace configuration/admin entries into “Workspace admin” on environment pages,
- preserve explicit
environment_idonly for workspace hubs that already accept that filter.
Run narrow tests first:
cd apps/platform && ./vendor/bin/sail artisan test --compact <new/updated Spec 338 tests>cd apps/platform && ./vendor/bin/sail pint --dirty --format agentgit diff --check
Run minimal browser smoke only if link/scope changes are user-visible in navigation:
cd apps/platform && php vendor/bin/pest tests/Browser --filter=Spec338 --compact
Deployment / Ops Impact
- Migrations: none expected.
- Env vars: none expected.
- Queues/scheduler: none expected.
- Filament assets: no new registered assets expected;
filament:assetsposture unchanged.