88 lines
3.4 KiB
Markdown
88 lines
3.4 KiB
Markdown
# Quickstart: Workspace Chooser v1
|
|
|
|
**Feature**: 107-workspace-chooser | **Date**: 2026-02-22
|
|
|
|
## Prerequisites
|
|
|
|
- Branch: `107-workspace-chooser` checked out
|
|
- Sail running: `vendor/bin/sail up -d`
|
|
- Existing workspace + user fixtures (factory-based)
|
|
|
|
## Implementation Order
|
|
|
|
### Phase A: Foundation (no visible changes)
|
|
|
|
1. **Add `AuditActionId` enum cases** — `WorkspaceAutoSelected`, `WorkspaceSelected`
|
|
2. **Extract `WorkspaceRedirectResolver`** — shared tenant-count branching helper (DRY the 4 current copies)
|
|
3. **Tests for redirect resolver** — verify 0/1/>1 tenant branching
|
|
|
|
### Phase B: Middleware Refactor (core behavior change)
|
|
|
|
4. **Refactor `EnsureWorkspaceSelected`** — implement 7-step algorithm from spec
|
|
- Step 1: workspace-optional path bypass (keep existing `isWorkspaceOptionalPath()`)
|
|
- Step 2: `?choose=1` handling (new)
|
|
- Step 3: stale session detection + flash warning (enhanced)
|
|
- Step 4-5: single membership auto-resume + audit (new)
|
|
- Step 6: `last_workspace_id` auto-resume + audit (new)
|
|
- Step 7: fallback to chooser (existing)
|
|
5. **Middleware tests** — all 7 steps covered
|
|
|
|
### Phase C: Chooser Page Upgrade (UI changes)
|
|
|
|
6. **Refactor `ChooseWorkspace` page**:
|
|
- Remove "Create workspace" header action
|
|
- Add `withCount('tenants')` to query
|
|
- Load membership roles keyed by workspace_id
|
|
- Expose `getWorkspaceRole()` and `getWorkspaceMemberships()` for Blade
|
|
7. **Update `choose-workspace.blade.php`**:
|
|
- Add role badge per card
|
|
- Add tenant count per card
|
|
- Add "Manage workspaces" link (capability-gated)
|
|
- Update empty state (spec copy)
|
|
- Replace form POST with `wire:click="selectWorkspace({{ $workspace->id }})"`
|
|
8. **Add audit logging in `selectWorkspace()`** — emit `workspace.selected` with metadata
|
|
9. **Chooser page tests** — metadata display, empty state, manage link visibility, audit events
|
|
|
|
### Phase D: User Menu Integration
|
|
|
|
10. **Register "Switch workspace" in `AdminPanelProvider`** — `userMenuItems()` with visibility condition
|
|
11. **User menu tests** — visible when >1 workspace, hidden when 1
|
|
|
|
### Phase E: Cleanup & Verification
|
|
|
|
12. **Replace inline tenant-branching** in `SwitchWorkspaceController` and `routes/web.php` with `WorkspaceRedirectResolver`
|
|
13. **Run full test suite** — verify no regressions
|
|
14. **Pint formatting** — `vendor/bin/sail bin pint --dirty`
|
|
15. **Commit + push**
|
|
|
|
## Key Files to Understand First
|
|
|
|
| File | Why |
|
|
|------|-----|
|
|
| `app/Http/Middleware/EnsureWorkspaceSelected.php` | The middleware being refactored |
|
|
| `app/Filament/Pages/ChooseWorkspace.php` | The page being upgraded |
|
|
| `app/Support/Workspaces/WorkspaceContext.php` | The workspace session manager |
|
|
| `app/Services/Audit/WorkspaceAuditLogger.php` | Where audit events are emitted |
|
|
| `app/Support/Audit/AuditActionId.php` | Where enum cases are added |
|
|
| `app/Http/Controllers/SwitchWorkspaceController.php` | POST switch (redirect resolver integration) |
|
|
| `routes/web.php` (lines 36-82) | `/admin` route with duplicated branching |
|
|
|
|
## Verification Commands
|
|
|
|
```bash
|
|
# Run workspace-related tests
|
|
vendor/bin/sail artisan test --compact tests/Feature/Workspaces/
|
|
|
|
# Run specific middleware test
|
|
vendor/bin/sail artisan test --compact --filter=EnsureWorkspaceSelected
|
|
|
|
# Run chooser page test
|
|
vendor/bin/sail artisan test --compact --filter=ChooseWorkspacePage
|
|
|
|
# Format
|
|
vendor/bin/sail bin pint --dirty
|
|
|
|
# Full suite
|
|
vendor/bin/sail artisan test --compact
|
|
```
|