Staff — Auth & roles

How login, sessions, roles, permissions, and route gates work.

Entry flows

Path UI Outcome
/ Role cards (StaffIndexPage) Navigate to /garson, /barkasa, or /patron
/:role PinGate PIN/password → POST /api/auth/login/ → must match selected role → /masalar
/login LoginPage Same auth API; used as admin-style password entry → /masalar

Logged-in users hitting /, /:role, or /login are redirected to /masalar.

Legacy paths still redirect:

  • /staff/
  • /staff/:role/:role
  • /app, /admin (+ optional page slug) → flat POS URLs

Session storage

Item Storage Notes
Token localStorage.auth_token Sent as Authorization: Bearer …
Current user React Query authMe (+ auth helpers) Restored via GET /api/auth/me/
Legacy staff session key Cleared on read Old biurla.staff.session.v1 removed

AuthProvider waits for /auth/me/ (or clear failure) before rendering the app shell. Failed restore clears local auth.

Logout

Confirm dialog → unsubscribe Web Push (best effort) → POST /api/auth/logout/ → clear token → navigate to /.

Roles and profile mapping

Staff roles in the API: patron | garson | barkasa.

In the UI, patron is treated as profile admin (full nav). Mapping: src/lib/staff/roles.ts (ROLE_TO_PROFILE).

PinGate rejects login when session.user.role does not match the selected role card.

Tab access (navigation)

Built by posNavItemsFor(profile, canReservation) in AdminPage.constants.ts. Reservation tab requires reservation.manage.

Tab (URL) Garson Barkasa Patron
Masalar /masalar
Ürünler /urunler
Adisyonlar /checks
Raporlar /reports
İşlem geçmişi /islem-gecmisi
Rezervasyon /rezervasyon ✓* ✓*
Müdavim /mudavim
Ayarlar /ayarlar

*Only if hasPermission(..., "reservation.manage") — true for barkasa and patron; false for garson.

AppAuthGate enforces this: unknown or disallowed slug → redirect to /masalar.

Fine-grained permissions

hasPermission(session, perm) in src/lib/staff-session.ts gates actions inside dialogs (approve, payments, merge, stock, staff manage, etc.).

Important rules:

Rule Behavior
session === null Treated as full allow (patron/admin owner path when profile is admin)
role === "patron" All permissions
Garson Add items, payments set, table close/merge, print, ikram/iptal/zayi — no order.approve, no reservation.manage, no product/staff/stock manage
Barkasa Garson set plus order.approve and reservation.manage

Permission strings include: order.add, order.approve, product.add, print.receipt, item.ikram / iptal / zayi, payment variants, table.close / merge / unmerge, stock.manage, staff.manage, reservation.manage.

STAFF_VIEWS is separate capability metadata (includes mutfak / bar labels for patron/barkasa). It does not create kitchen routes.

Implementation map

Concern Files
Provider src/providers/AuthProvider.tsx
Login UI src/features/auth/LoginPage.tsx, src/components/staff/PinGate.tsx
Gates src/features/auth/AppAuthGate.tsx
Auth API src/lib/api/auth.ts
Paths src/lib/auth/paths.ts
Permissions src/lib/staff-session.ts
Role labels src/lib/staff/roles.ts