← All tests

#30 — Assign members & cashiers to shops (prod)

SHIPPED 2026-06-07 · nix-cafe dc5d3e5 · Gate 2 7/7 · regression 51/51 · no migration

Notion test-run #30 “Edit Member > Register Access not saving.” The old “Register access” picker was a ghost field — access is per-shop in the multi-register-shop model, and both /api/team routes silently discarded the register list. Replaced it with real shop assignment. Verified on lumiere-coffee (owner SSO).

Members — Shop access picker (writes commerce.user_shop_access)

Invite + Edit Member now show a multi-select Shop access picker (members can cover several shops — a Branch Manager over 2 branches). Saving writes real grants that the existing POS gates already read (listAccessibleShops ∩ shop registers), so assigning a shop actually grants POS access — no enforcement change needed. is_manager mirrors the role (Manager → Store Manager). The Team table’s old “Registers” column is now Shops (“All shops” for owner/admin). Gate 2 proved the grant lands in the DB and the access derivation follows it; clearing shops removes the grant.

Invite member with the multi-select Shop access picker
Invite member → Shop access multi-select
Edit cashier shop reassignment dropdown
Edit cashier → reassign shop (was create-only)

Cashiers — reassign shop after creation

Non-user cashiers (PIN identities) could be given a shop only at creation. Added an Edit cashier flow (name + shop) so a cashier can be moved between shops without delete + recreate (which would lose the PIN). Cashiers stay single-shop or “Any shop” (tenant-wide). New updatePinIdentity DAO + updateCashierAction.

Also fixed

listTeamMembers is now db.transaction-wrapped (like listPinIdentities) so a just-invited member / just-changed shop grant shows immediately instead of being hidden by Hyperdrive’s ~60s SELECT cache.