Team & RBAC
A property owner rarely runs check-ins themselves. They hire a front-desk team, a manager, possibly an accountant. ABc lets the owner add as many staff accounts as they need, each with a scoped role that limits exactly what they can see and do.
Built-in roles
Owner
Full access. Can add/remove staff, change pricing, change payout bank, delete property. Only role allowed to invite other owners.
Manager
Everything an owner can do, except: cannot delete the property, cannot change payout bank, cannot remove the owner. Default role for "second-in-command".
Front-desk
Can view bookings, create manual bookings, capture cash/UPI, check-in/check-out. Cannot edit rates, cannot view payout reports.
Finance
Read-only on bookings; full access to payments, refunds, invoices, GST reports. Cannot modify property data.
Read-only
Everything visible, nothing editable. Great for accountants, auditors, board members.
Custom
Owner mixes-and-matches individual permissions. V1.x feature; MVP ships the 5 presets above.
Permission matrix
Every action in ABc maps to one of ~30 permissions. Here is the abbreviated map across the 5 preset roles:
| Permission | Owner | Manager | Front-desk | Finance | Read-only |
|---|---|---|---|---|---|
| property.create | ✅ | — | — | — | — |
| property.edit | ✅ | ✅ | — | — | — |
| property.delete | ✅ | — | — | — | — |
| property.pause | ✅ | ✅ | — | — | — |
| room.create_edit | ✅ | ✅ | — | — | — |
| rate.edit | ✅ | ✅ | — | — | — |
| booking.view | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking.create_manual | ✅ | ✅ | ✅ | — | — |
| booking.checkin_checkout | ✅ | ✅ | ✅ | — | — |
| booking.cancel | ✅ | ✅ | — | — | — |
| booking.price_override | ✅ | ✅ | ± (≤20 %) | — | — |
| payment.capture | ✅ | ✅ | ✅ | ✅ | — |
| payment.refund | ✅ | ✅ | — | ✅ | — |
| payout_bank.edit | ✅ | — | — | — | — |
| channel.connect | ✅ | ✅ | — | — | — |
| team.invite | ✅ | ✅ | — | — | — |
| team.remove | ✅ | — | — | — | — |
| analytics.view | ✅ | ✅ | — | ✅ | ✅ |
| analytics.financials | ✅ | ✅ | — | ✅ | — |
| audit_log.view | ✅ | ✅ | — | ✅ | ✅ |
Property scope
Beyond role, every team member is scoped to one or more properties. A multi-property owner can hire one manager for "Manali" and another for "Kasol" — they will not see each other's data.
Global staff
Owner-level account, all properties owned. Default when the owner adds someone to "all properties".
Property-scoped staff
Visible only on the assigned property. UI hides everything else; API enforces scope on every read & write.
Team list UI
| Member | Role | Properties | Status | |
|---|---|---|---|---|
RM Rohan Mehta · you rohan@parkviewhotel.in |
Owner | All (3) | Active | |
SK Sneha Kapoor sneha@parkviewhotel.in |
Manager | Park View · Hillside | Active | |
AP Anjali Patel anjali@parkviewhotel.in |
Front-desk | Park View | Active | |
RK Ravi Khanna (CA) ravi.ca@example.com |
Finance | All (3) | Active | |
? arjun@example.com Invited 2 hrs ago |
Front-desk | Hillside | Pending |
Invite member · UI
Custom role · permissions editor
Property
Bookings
Payments
Team
Analytics
Activity by member
| Member | Activity (14 d) | Total | Last seen | Risky actions |
|---|---|---|---|---|
|
RM
Rohan Mehta
Owner |
142 actions | Now | — | |
|
SK
Sneha Kapoor
Manager |
89 actions | 12 m ago | 1 price override | |
|
AP
Anjali Patel
Front-desk |
56 actions | 2 h ago | — | |
|
RK
Ravi Khanna
Finance · CA |
23 actions | Yesterday | 2 refunds today |
Invite flow
Owner enters email + role + property scope
Optional: a personalised note.
System sends invite email
One-time link, valid 7 days. New users get a sign-up page; existing users get a one-click accept.
Invitee accepts
If new: completes sign-up (name, password, phone OTP). If existing: just confirms.
Membership row created
user × property × rolestored inmemberships. User now sees that property in their workspace switcher.Welcome email + notification to owner
Owner gets a heads-up that the invite was accepted.
Removing a member
- Owner clicks "Remove" → confirmation dialog → membership row deleted.
- Active sessions for that user / property revoked immediately (JWT version bumped).
- The user's bookings and audit entries stay intact (we never delete history). Their attribution is preserved.
- If the user has no other memberships, their account remains but they lose access to this workspace.
The DB model
memberships
- iduuid
- user_id→ users
- property_id→ properties · nullable
- roleenum
- scopeall | specific
- invited_byuuid
- accepted_attimestamp
invitations
- iduuid
- emailtext
- property_id→ properties
- roleenum
- token_hashtext
- expires_attimestamp
- accepted_attimestamp · nullable
Permission checks in code
// Express / NestJS-style guard @RequiresPermission("booking.cancel") @RequiresProperty() async cancelBooking(@Param("id") id: string, @User() me: CurrentUser) { // Guard already verified: // - user has booking.cancel permission // - user has access to the property the booking belongs to return bookings.cancel(id, me); }
Front-end hides buttons by role for UX, but every server endpoint re-checks the permission. A revoked agent loading a stale page should still be denied.