← All stories

BRANCH · ef-002-team-selection

Team Selection

EF-002Persona: Organizer adminRoots in: admin-shell-accessMatrix: Partial

Auth/session roles and tenant context middleware exist, but the admin shell still needs an EventFarm-style multi-account switcher with persisted active-team URL state and audit per switch.

Preconditions

User is authenticated and belongs to at least two teams with different tenant ids.

Happy path

  1. Open the team switcher from the admin shell header.

    An autocomplete or keyboard menu lists every team the user can access.

  2. Select a different team.

    Unsaved work prompts first; confirmation updates URL state, active tenant context, cached data scope, and visible team name.

  3. Refresh and navigate.

    The active team persists across refresh and all subsequent API requests use the selected tenant.

Failure modes

Permission denied at the right boundary

Trigger: user selects a team after membership was revoked.

Resolution: switch request returns 403 and current tenant remains unchanged.

Cross-tenant isolation

Trigger: user guesses a team id outside their memberships.

Resolution: 404 masks team existence.

Soft-delete leaves audit trail

Trigger: team membership is removed while switcher is open.

Resolution: membership is inactive with prior state in audit and cannot be selected.

Archive vs delete distinction

Trigger: a team is archived rather than deleted.

Resolution: archived team is labelled unavailable; deleted team is absent.

Edit lock during concurrent operations

Trigger: switch begins while unsaved admin form is dirty.

Resolution: modal requires discard/save before changing tenant context.

Audit log row on every state change

Trigger: user changes active team.

Resolution: team-switch audit row includes actor, from team, to team, timestamp, and session id.

Two organizers concurrent

Trigger: two sessions for the same user switch teams independently.

Resolution: per-tab URL state decides context; no tab steals another tab's active team.

Undo window for destructive actions

Trigger: switch discards dirty form state.

Resolution: 10 second undo returns to the previous team and restores preserved draft state.

Refresh loses active team

Trigger: user refreshes after switch.

Resolution: URL-state mandate restores the selected team, not the default membership.

Subsequent request uses previous tenant

Trigger: event list fetch after switch carries old tenant header.

Resolution: request is blocked or retried with new tenant context before data renders.

Accidental cross-tenant mutation after switch

Trigger: user switches teams while an old event page is open.

Resolution: stale event mutation returns 404 and UI redirects to selected team's dashboard.

Capability gap: active-team switcher missing

Trigger: matrix marks EF-002 partial.

Resolution: visible gap panel remains until switcher, URL persistence, and audit-per-switch ship.

Stable test attributes

Visibility teeth. Each attribute must be effectively visible when active.

team-selection-switcherHeaderTeam picker
team-selection-menuPopoverAvailable teams
team-selection-optionMenuTeam option
team-selection-active-labelHeaderActive team
team-selection-unsaved-modalModalDirty work confirmation
team-selection-confirm-toastToastSwitch confirmation
team-selection-gap-panelPagePartial gap
team-selection-audit-rowAudit viewSwitch audit
team-selection-undo-toastToastUndo switch discard
team-selection-errorMenuSwitch error

Agent test plan

- team-switcher-renders
- team-switch-persists-url
- team-switch-audits
- permission-denied-boundary
- cross-tenant-404
- soft-delete-audit
- archive-delete-distinction
- dirty-edit-lock
- audit-row-every-change
- per-tab-team-context
- destructive-undo-window
- refresh-keeps-active-team
- subsequent-requests-use-new-tenant
- stale-cross-tenant-mutation-blocked
- team-selection-gap-probe
- evaluate-team-selection