Extend login flow with party selection
Table of Contents
This page is a capture in the next bucket of the product backlog — a pre-sprint idea, not yet pulled into a sprint as a story.
After authentication, look up the user's associated parties from
account_parties. If one party, auto-select. If multiple, return the party list
to the client for selection. The client displays a party picker widget. After
selection, compute the visible party set and bind to the session.
Acceptance Criteria
- Login response includes available parties.
- Party picker displayed when user has multiple parties.
- Selected party stored in session and displayed in application window (title
bar shows
username @ party_name). - Party context immutable for session lifetime.
Design Notes
Protocol changes
Extend login_response (0x2006) with two fields appended to the wire format:
available_parties:vector<{uuid id, string name}>— empty when 0 or 1 party (auto-selected); populated when ≥2 parties.selected_party_id:uuid— non-nil only when the server auto-selected exactly one party; nil when the client must choose.
Add two new messages:
select_party_request(0x2015):{uuid party_id}select_party_response(0x2016):{bool success, string error_message}
Server changes (handle_login_request)
The party resolution block (lines 488-520 of
accounts_message_handler.cpp) currently always auto-selects
parties.front(). Change to:
- 0 parties → leave session unbound; no change.
- 1 party → auto-select as now; set
selected_party_idin response. - ≥2 parties → do NOT bind
party_idyet; returnavailable_partieslist; leave session unbound untilselect_party_requestarrives.
Add handle_select_party_request: validate chosen party_id is in
account's account_parties, bind session->party_id, recompute
visible_party_ids, update both in-memory session and DB record.
Client changes
LoginResultgainsavailable_partiesandselected_party_id.ClientManagergainscurrent_party_id_,current_party_name_, and aselectParty(uuid)method.LoginDialog::onLoginResultgains a new branch after the password-reset check: ifavailable_parties.size() > 1, showPartyPickerDialog(modal, same pattern asChangePasswordDialog). On reject → disconnect, re-enable form. On accept → callclientManager_->selectParty(id).- Main window title set to
username @ party_nameafter login completes.
Session state machine
Not connected → Connected → Authenticated (party-unbound, only when ≥2 parties) → Party selected (fully operational) 0 or 1 party: Authenticated → Party selected in one step (no picker shown).