TenantAtlas/specs/341-canonical-link-query-cleanup/plan.md
ahmido e324bd7bd6 feat: canonicalize admin scope links and queries (341) (#413)
## Summary
- remove remaining legacy scope query hint parsing from shared workspace and environment scoping seams so hubs only narrow via explicit `environment_id`
- align canonical link generation across workspace hubs, provider connections, audit log, alerts, and decision register flows
- add focused Spec 341 regression coverage for canonical link/query behavior and legacy alias rejection
- include the Spec 341 artifacts and move the review screenshots into `specs/341-canonical-link-query-cleanup/artifacts/screenshots/`
- ignore local `.playwright-mcp` browser tool output so it does not pollute future commits or pull requests

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation --filter=Spec341`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation/Spec341CanonicalLinkQueryCleanupTest.php tests/Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php tests/Feature/ProviderConnections/ProviderConnectionsWorkspaceHubContractTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `git diff --check`

## Notes
- Livewire v4 compliance unchanged
- Filament provider registration remains in `apps/platform/bootstrap/providers.php`
- no globally searchable resource behavior was changed in this slice
- no destructive action behavior was changed
- no new Filament assets; deploy `filament:assets` posture is unchanged

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #413
2026-05-31 22:46:39 +00:00

112 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Spec 341 - Canonical Link / Query Cleanup
**Branch**: `341-canonical-link-query-cleanup` | **Date**: 2026-05-31 | **Spec**: `specs/341-canonical-link-query-cleanup/spec.md`
**Input**: Candidate `canonical-link-query-cleanup` from `docs/product/spec-candidates.md` + repo inspection of legacy scope query parsing seams.
## Summary
Inventory and remove remaining legacy “scope hint” query parsing (`tenant`, `managed_environment_id`, etc.) in shared request-scoping seams and align canonical link generation so that:
- workspace hubs are workspace-wide unless explicitly filtered via `environment_id`;
- environment-bound pages are route-owned and do not accept legacy query aliases as authority; and
- “clear filter” behavior returns to clean canonical URLs.
This is contract hardening; it must not introduce new abstractions, persistence, or UI frameworks.
## Technical Context
- **Language/Version**: PHP 8.4.15, Laravel 12.52.x
- **Primary Dependencies**: Filament v5, Livewire v4, Pest v4
- **Storage**: PostgreSQL (no schema changes planned)
- **Testing**: Pest Feature tests (navigation + scope contracts)
- **Validation Lanes**: fast-feedback (Feature); browser only if later proven necessary for visible UX behaviors that cannot be asserted reliably in Feature tests
- **Target Platform**: `apps/platform` (Sail locally; Dokploy/container posture unchanged)
- **Constraints**:
- no compatibility redirects or “legacy alias preservation”
- no new packages, migrations, queues, scheduler, storage changes
- deny-as-not-found semantics remain authoritative
## UI / Surface Guardrail Plan
- **Guardrail scope**: existing reachable surfaces; navigation + scope contract hardening
- **Affected routes/pages/actions/states** (inventory-driven):
- workspace hubs that accept environment narrowing via `environment_id` and expose “clear filter” behavior
- environment-bound pages under `/admin/workspaces/{workspace}/environments/{environment}/...` that must remain route-owned
- shared request-scoping seams that must not treat legacy query keys as authority
- **State layers in scope**: URL/query + route parameters + session workspace context
- **Handling mode**: review-mandatory (scope/authority semantics)
- **Required tests or manual smoke**: Feature contract tests for clean vs filtered hub URLs and legacy alias rejection/ignore behavior; browser smoke only if required later
- **UI/Productization coverage decision**: existing pages changed / navigation semantics changed; no new reachable surface added; do not update `docs/ui-ux-enterprise-audit/*` unless implementation materially changes navigation entries or routes (not expected)
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes
- **Systems touched** (expected):
- `apps/platform/app/Support/Navigation/WorkspaceHubNavigation.php`
- `apps/platform/app/Support/Navigation/WorkspaceHubEnvironmentFilter.php`
- `apps/platform/app/Filament/Concerns/UsesAdminEnvironmentFilterQueryParameter.php`
- `apps/platform/app/Http/Middleware/EnsureWorkspaceSelected.php`
- `apps/platform/app/Support/Middleware/EnsureEnvironmentContextSelected.php`
- `apps/platform/app/Support/OperateHub/OperateHubShell.php`
- `apps/platform/tests/Feature/Navigation/*`
- **Shared abstractions reused**: existing hub filter contract helpers, `WorkspaceContext`, deny-as-not-found semantics, existing guard-test patterns
- **New abstraction introduced?**: none
- **Spread control**: inventory-driven; limit changes to URL/query scope semantics and canonical link generation only
## OperationRun UX Impact
N/A — no `OperationRun` start/completion/link UX changes.
## Implementation Approach
### Phase 1 — Repo truth inventory + failing tests first
- inventory every remaining legacy scope query parsing seam (query keys only, not DB naming)
- add/adjust Feature tests that fail on todays behavior and encode the intended contract
### Phase 2 — Remove legacy query scope hint parsing in shared seams
- remove or strictly ignore legacy scope hints in:
- `EnsureWorkspaceSelected`
- `EnsureEnvironmentContextSelected`
- `OperateHubShell`
- `EnvironmentRequiredPermissions` (query-hint handling only)
- ensure out-of-scope requests preserve deny-as-not-found semantics
### Phase 3 — Align canonical link generation
- ensure link generation:
- never emits legacy scope query keys
- uses `environment_id` only for workspace hub narrowing
- does not treat `environment_id` as a replacement for route-owned environment pages
### Phase 4 — Regression guards
- add/extend guard tests that block:
- parsing legacy scope keys as authority
- generating navigation URLs containing forbidden scope query keys
### Phase 5 — Validation + close-out
- run the narrowest Feature tests
- run `pint` on dirty files and `git diff --check`
## Test Governance Check
- **Test purpose / classification**: Feature
- **Affected validation lanes**: fast-feedback (Feature)
- **Narrowest proving command(s)**:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation --filter=Spec341`
- **Fixture / helper cost risks**: none expected; reuse existing workspace/environment factories + navigation harness helpers
- **Escalation path**: `document-in-feature` if a bounded exception is proven necessary; otherwise treat legacy alias preservation as a blocker
## Deployment / Ops Impact
No migrations, env vars, queues, scheduler, storage, or asset pipeline changes are planned.
## Constitution Check (subset)
- Proportionality: no new persistence/abstractions/taxonomy introduced
- Compatibility posture: legacy alias preservation is out of scope
- Scope & isolation: route-owned environment remains authoritative; hub narrowing is `environment_id` only; deny-as-not-found semantics preserved