TenantAtlas/specs/121-workspace-switch-fix/plan.md
ahmido 891f177311 fix: route workspace switch to chooser (#147)
## Summary
- route the context-bar `Switch workspace` link to the canonical chooser flow instead of workspace management
- add focused regression coverage for topbar switching, management separation, and chooser redirect semantics
- add Spec 121 artifacts (`spec`, `plan`, `research`, `data-model`, `contracts`, `quickstart`, `tasks`, checklist)

## Validation
- `vendor/bin/sail artisan test --compact tests/Feature/Monitoring/HeaderContextBarTest.php tests/Feature/Workspaces/WorkspaceSwitchUserMenuTest.php tests/Feature/Workspaces/ChooseWorkspacePageTest.php tests/Feature/Workspaces/WorkspaceNavigationHubTest.php tests/Feature/Workspaces/EnsureWorkspaceSelectedMiddlewareTest.php tests/Feature/Workspaces/ChooseWorkspaceRedirectsToChooseTenantTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Notes
- base branch: `dev`
- branch: `121-workspace-switch-fix`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #147
2026-03-08 00:58:51 +00:00

146 lines
8.4 KiB
Markdown

# 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.