diff --git a/specs/107-workspace-chooser/spec.md b/specs/107-workspace-chooser/spec.md index de2dbf3..518e1b0 100644 --- a/specs/107-workspace-chooser/spec.md +++ b/specs/107-workspace-chooser/spec.md @@ -141,6 +141,7 @@ ### Edge Cases - What happens when the workspace referenced by `last_workspace_id` is **archived**? → Treated as invalid, cleared, chooser shown. - What happens when `?choose=1` is used by a user with **only 1 workspace**? → Chooser is shown anyway (forced mode). - What happens when `session.current_workspace_id` is set but the workspace was **archived** between requests? → Session cleared, warning shown, chooser displayed. +- What happens when a user has **multiple browser tabs** open and switches workspace in one tab? → Session is the single source of truth. Other tabs reflect the new workspace on their next server request. No per-tab isolation in v1. --- @@ -174,7 +175,7 @@ ### Functional Requirements - **FR-006**: Chooser MUST NOT prominently display "Create workspace". A "Manage workspaces" link MAY appear, gated by `workspace.manage` capability. - **FR-007**: Route parameter `?choose=1` MUST force the chooser to display regardless of auto-resume eligibility. - **FR-008**: User menu MUST contain a "Switch workspace" entry that links to `/admin/choose-workspace?choose=1`. Entry is visible only when the user has >1 workspace membership. -- **FR-009**: After workspace selection (auto or manual), the system MUST redirect to the workspace dashboard (no smart redirect in v1). +- **FR-009**: After workspace selection (auto or manual), the system MUST apply existing tenant-count branching: 0 tenants → Managed Tenants index, 1 tenant → Tenant Dashboard directly, >1 tenants → Choose Tenant page. No "smart redirect" to the last-visited page in v1. - **FR-010**: The `EnsureActiveWorkspace` middleware MUST run on all `/admin/*` routes except the chooser page itself, login/logout routes, and OAuth callbacks. - **FR-011**: Chooser queries MUST NOT produce N+1 problems (eager load memberships + `withCount('tenants')`). @@ -233,9 +234,9 @@ ## Middleware: EnsureActiveWorkspace (v1 Algorithm) - If membership valid + workspace not archived → **allow**. - Else: clear session, set flash warning ("Your access to {name} was removed."), redirect to chooser. 4. Load user's workspace memberships (selectable only: not archived). -5. If exactly 1 → set active, emit audit (`auto_selected`, reason: `single_membership`), redirect to dashboard. +5. If exactly 1 → set active, emit audit (`auto_selected`, reason: `single_membership`), redirect via tenant-count branching (0→managed tenants, 1→tenant dashboard, >1→choose tenant). 6. If `users.last_workspace_id` set: - - If membership valid + workspace selectable → set active, emit audit (`auto_selected`, reason: `last_used`), redirect to dashboard. + - If membership valid + workspace selectable → set active, emit audit (`auto_selected`, reason: `last_used`), redirect via tenant-count branching. - Else: clear `last_workspace_id`, set flash warning, redirect to chooser. 7. Else → redirect to chooser. @@ -289,6 +290,15 @@ ## Test Plan (Feature/Integration) --- +## Clarifications + +### Session 2026-02-22 + +- Q: Should v1 redirect always to a fixed dashboard, or preserve existing tenant-count branching (0→managed tenants, 1→tenant dashboard, >1→choose tenant)? → A: Preserve existing tenant-count branching — avoids UX regression for current users. +- Q: Should the middleware treat the session as single source of truth for all tabs, or add per-tab workspace isolation? → A: Session is single source of truth — all tabs share the workspace context. Switching in one tab is reflected in all others on next request. Matches existing `WorkspaceContext` design. + +--- + ## v2 Backlog (Explicitly Deferred) - Search/Sort/Favorites/Pins in chooser