Rules live in firestore.rules. They enforce role-based access for the synthetic transport domain.
All rules assume Firebase Auth. User role is stored on users/{uid}.role and loaded via:
get(/databases/$(database)/documents/users/$(request.auth.uid)).data
Helper functions: isAdmin(), isDispatcher(), isDriver(), isStaff() (admin or dispatcher).
| Action | Who |
|---|---|
| Read own profile | Self |
| Read any profile | Staff |
| Create | Admin only |
| Update own profile | Self (cannot change role) |
| Update any profile | Admin |
| Delete | Admin |
| Action | Who | Constraints |
|---|---|---|
| Read | Staff | All trips |
| Read | Driver | Own assigned trips only (driverId == uid) |
| Create | Staff | Must set status: requested, createdBy == uid |
| Update | Staff | Full update |
| Update | Driver | Own trip only; may change status + updatedAt; new status ∈ {en_route, completed} |
| Delete | Admin | — |
| Action | Who | Constraints |
|---|---|---|
| Read | Staff | All tickets |
| Read | Creator | Own tickets |
| Create | Any signed-in user | status: open, createdBy == uid |
| Update | Staff | Full update |
| Update | Creator | body + updatedAt only, while status == open |
| Delete | Admin | — |
| Action | Who |
|---|---|
| Read | Recipient (recipientId == uid) |
| Write | Denied — server-only via Cloud Functions Admin SDK |
Notifications are immutable from the client. The Admin SDK bypasses security rules when the onTripStatusChange function writes notification documents.
- Start emulators:
firebase emulators:start --only firestore,auth - Use the Auth emulator to sign in test users with known UIDs.
- Seed
users/{uid}documents with appropriaterolevalues. - Attempt reads/writes from a client SDK or the Emulator UI Rules playground.
- Fail closed: unauthenticated requests are denied except where explicitly allowed.
- Role elevation blocked: users updating their own profile cannot change
role. - Driver least privilege: drivers see and mutate only their assigned trips, with limited status transitions.
- Notification integrity: client writes to
notificationsare fully blocked to prevent spoofing.