# Implementation Plan: Workspace Switch Semantic Fix **Branch**: `121-workspace-switch-fix` | **Date**: 2026-03-07 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/121-workspace-switch-fix/spec.md` ## Summary Correct the context-bar `Switch workspace` affordance so it uses the canonical chooser flow and remains the only workspace-switching affordance. The implementation will keep the topbar partial targeting `ChooseWorkspace::getUrl(panel: 'admin').'?choose=1'`, remove the duplicate admin user-menu shortcut, preserve the current chooser redirect behavior (`WorkspaceIntendedUrl` / `WorkspaceRedirectResolver`), and leave workspace management reachable only through its separate administrative navigation path. Validation stays focused on response-level topbar rendering plus regression coverage that management navigation and chooser semantics remain distinct. ## Technical Context **Language/Version**: PHP 8.4.15 / Laravel 12 **Primary Dependencies**: Filament v5 + Livewire v4.0+ + Tailwind CSS v4 **Storage**: PostgreSQL + session-backed workspace context; no schema changes **Testing**: Pest v4 feature tests (HTTP response assertions and existing workspace flow regression tests) **Target Platform**: Web admin and tenant panels (`/admin`, `/admin/t/...`) running in Laravel Sail / container deployment **Project Type**: Laravel monolith / Filament web application **Performance Goals**: No additional remote calls or new query paths; topbar render remains effectively unchanged except for link destination **Constraints**: Preserve existing RBAC and workspace isolation rules; preserve chooser post-selection behavior; avoid hardcoded management URLs for switch intent; keep workspace switching in context surfaces rather than account surfaces; no CRUD behavior changes **Scale/Scope**: One context-bar Blade partial, one admin panel provider cleanup, plus targeted workspace/navigation tests; no data migration, no new services, no new routes ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: PASS (feature only changes navigation semantics; no inventory or backup semantics affected). - Read/write separation: PASS (no new writes or mutations introduced; chooser selection behavior remains existing behavior). - Graph contract path: PASS (no Microsoft Graph calls; all affected surfaces are DB/session-only). - Deterministic capabilities: PASS (no new capabilities; existing workspace membership and management capability rules remain canonical). - RBAC-UX: PASS (feature stays in `/admin`; non-member and capability behavior are unchanged because only the destination link changes). - Workspace isolation: PASS (`?choose=1` intentionally forces the chooser while preserving existing workspace membership enforcement and post-selection resolution). - Destructive confirmation: PASS / N/A (no destructive actions are added or changed). - Global search: PASS / N/A (no global search behavior changes). - Tenant isolation: PASS (chooser and management separation remains explicit; no tenant data exposure changes). - Run observability: PASS / N/A (no long-running or operational work; no `OperationRun` usage). - Ops-UX 3-surface feedback: PASS / N/A (no operation lifecycle involved). - Automation: PASS / N/A (no scheduled or queued work). - Data minimization: PASS (no new persisted data or logging payloads). - Badge semantics (BADGE-001): PASS / N/A (no new status-like badges). - Filament UI Action Surface Contract: PASS with exemption note. The affected surface is a topbar/context-bar navigation link, not a CRUD Resource/RelationManager/Page action surface. - Filament UI UX-001: PASS with exemption note. The feature preserves the existing chooser page and does not alter Create/Edit/View layouts. ## Project Structure ### Documentation (this feature) ```text specs/121-workspace-switch-fix/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── routes.md └── tasks.md ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ └── Pages/ │ └── ChooseWorkspace.php # reference-only canonical chooser ├── Http/ │ └── Middleware/ │ └── EnsureWorkspaceSelected.php # reference-only forced chooser semantics ├── Providers/ │ └── Filament/ │ └── AdminPanelProvider.php # MODIFY — remove duplicate user-menu switch shortcut └── Support/ └── Workspaces/ ├── WorkspaceIntendedUrl.php # reference-only existing post-selection flow └── WorkspaceRedirectResolver.php # reference-only existing post-selection flow resources/ └── views/ └── filament/ └── partials/ └── context-bar.blade.php # MODIFY — switch link target tests/ └── Feature/ ├── Monitoring/ │ └── HeaderContextBarTest.php # MODIFY — assert chooser target from context bar └── Workspaces/ ├── WorkspaceSwitchUserMenuTest.php # MODIFY — assert user menu no longer exposes workspace switching ├── ChooseWorkspacePageTest.php # reference or extend — management remains reachable └── WorkspaceNavigationHubTest.php # reference-only IA separation guard ``` **Structure Decision**: Keep the change inside the existing Laravel/Filament monolith. Implementation is a narrowly scoped view-level routing correction backed by targeted Pest feature tests and existing workspace chooser/navigation helpers. ## Complexity Tracking > No Constitution Check violations. No justifications needed. | Violation | Why Needed | Simpler Alternative Rejected Because | |-----------|------------|-------------------------------------| | — | — | — | ## Phase 0 — Research (output: `research.md`) See: [research.md](./research.md) Research goals: - Confirm the canonical workspace-switch destination and whether forced chooser semantics require `?choose=1`. - Confirm whether chooser post-selection redirect behavior should remain unchanged. - Confirm the smallest reliable test surface for a context-bar-only switch rule plus management-navigation regression coverage. ## Phase 1 — Design & Contracts (outputs: `data-model.md`, `contracts/`, `quickstart.md`) See: - [data-model.md](./data-model.md) - [contracts/routes.md](./contracts/routes.md) - [quickstart.md](./quickstart.md) Design focus: - Treat the context-bar link as a pure navigation contract update, not a behavior rewrite. - Reuse the existing chooser page and `?choose=1` forced-chooser convention to preserve manual switching semantics. - Remove the duplicate user-menu shortcut so workspace switching stays anchored to the context bar. - Preserve existing management navigation, chooser redirect resolution, and capability boundaries unchanged. - Validate the semantic split with response-level topbar assertions plus regression checks around management reachability. ## Phase 2 — Implementation Outline (tasks created in `/speckit.tasks`) ### UI routing correction - Replace the context-bar `Switch workspace` link target in `context-bar.blade.php`. - Use the canonical chooser helper (`ChooseWorkspace::getUrl(panel: 'admin')`) with the forced chooser query parameter. - Keep the link as navigation-only; no action/mutation flow is added. - Remove the duplicate Filament user-menu switch action from the admin panel provider. ### Regression protection - Extend the real rendered topbar test to assert the context-bar switch link points at the chooser URL rather than workspace CRUD. - Update user-menu coverage to assert no workspace-switch shortcut is registered there. - Reuse or mirror existing workspace chooser tests to prove management navigation remains separate and accessible through its dedicated path. - Keep existing middleware/chooser tests as the source of truth for post-selection branching. ### Verification - Run focused Pest coverage for context bar + workspace navigation semantics. - Run Pint on dirty files through Sail. ## Constitution Check (Post-Design) Re-check result: PASS. The design keeps workspace switching and workspace management semantically separate, reuses the existing chooser and middleware contract, introduces no new authorization rules or operational flows, and limits the implementation to a navigation target correction plus regression tests.