Narong's "Random Bugs" #1, filed 2026-07-22. nix-cafe only. No migration, no backend change.
His report:
"Team > Members: Remove a user removes all the roles > when set from Active to Inactive or vice versa > Escalates the User to Owner Privileges."
Not the Active/Inactive toggle — that branch only writes is_active. The escalation rode along on the
same Save:
nix_user_product_roles row → roleId is now null.listTeamMembers left-joins the role, so the member stays in the list with an Edit button.useState(member.roleId || roles[0]?.id || "") — so it
silently pre-selected an arbitrary role.handleSave always sent roleId, so a save intended only to flip the status
wrote that role.listCafeRoles had no ORDER BY → roles[0] was raw Postgres
heap order: unstable, and on lumiere-coffee it was literally Owner.The server-side guards were never at fault — they held throughout. A Manager attempting this still gets a 403. What this actually was: an Owner silently granting a role nobody chose, with no confirmation, and wrong in both directions (on get-coffee the same flow silently assigned POS User instead).
| Change | Why |
|---|---|
useState(member.roleId || "") | no silent fallback — the dangerous line |
| Disabled "Select a role…" placeholder + hint | the operator is told the member has no role |
handleSave omits roleId when empty | a status-only save can't write a role |
listCafeRoles ORDER BY privilege ascending | deterministic; any roles[0] fallback now fails safe |
role="switch" + aria-checked + testid on the Active toggle | it was an unlabelled div — untestable and inaccessible |

get-coffee.staging — the role field is empty with the placeholder, and the hint explains why. Previously this silently showed a real role.
The local suite was re-run with the old default temporarily restored. It failed exactly where it should — so the test genuinely reproduces the reported bug before asserting the fix:
✗ opening Edit does NOT silently pre-select a role: pre-filled with "9e600b16-…" ✗ toggling Active + Save does NOT assign any role: status-only save assigned role "pos_user"
It wrote pos_user rather than Owner only because the ORDER BY fix was already in
place — which shows the two changes are complementary: the ordering caps the blast radius, the dialog fix stops the
silent write.
| Suite | Result |
|---|---|
| Local — remove role → Edit → toggle Active → Save, asserted against the DB (+ negative control) | 8/8 |
Staging — same flow over real SSO on get-coffee.staging, asserted against Neon | 6/6 |
| Staging smoke (SSO, cross-tenant guard, Starter login, no-session redirect) | 5/5 |
tsc --noEmit | clean |
Both suites assert on database state, not screenshots — the property that matters is "no role row was written". Each restores its subject exactly on the way out.
Deleted app/(authed)/orders/management/order-management-client.tsx — orphaned dead code (392 lines). Its
route is now a redirect to /orders, so nothing rendered it. It was a stale duplicate of the live Order
Management view and had already caused one bug to need fixing in two places.
nix-cafe staging 9b32ca1 (Worker e97448a8). No migration. Parked for the
scheduled prod promote. Note: on staging the account Narong had escalated has since been reset to cashier and
deactivated — no lingering Owner privilege.