Firestore Security Rules (reference)
Technical reference for Firestore Security Rules used across PestControlOS.
Rule structure
- Default: Deny all. Each
matchblock explicitly allows read/write when conditions are met. - Authentication:
request.auth != nullfor any user-specific data. Userequest.auth.uidand optional custom claims (request.auth.token.role,request.auth.token.contractKey,request.auth.token.orgId) to scope access.
Collections (Android / shared back end)
- "[User] Contracts":
match /{user} Contracts/{doc}: allow read, write ifrequest.auth != nulland (optional)request.auth.uidor token matches user. Production: scope by authenticated user or admin role. - JobWork: allow read if admin/super_admin or
resource.data.AssignedTechKey == request.auth.token.contractKey. allow create if auth; allow update/delete if same as read or admin. Do not allow tech to setAssignedTechKeyto a different tech. - ManagmentJobs: allow read/write if admin/super_admin.
- Leads: allow read if admin or
resource.data.AssignedTechKey == request.auth.token.contractKey. allow write of invoiceStatus, materialsCost only if admin/super_admin. - notifications/{userId}/items: allow read, write if
request.auth.uid == userId(or app-specific userId in token). - *user_workview / _workview: allow read, write if token.contractKey matches collection user or role is admin/super_admin.
- AI-Chat/AI-API: allow read if auth; allow write only if admin (e.g. request.auth.token.role == 'admin' or uid == 001). Protects API keys.
- users, staff: allow read if auth; allow write only by admin or same uid for own profile.
Marketing site / CRM (per-tenant project)
- previewRequests: create-only.
allow create: if request.auth == null || true; allow read, update, delete: if false;. Schema:request.resource.data.keys().hasOnly(['email','name',...])and type checks. Prevents client read/update/delete of signups. - rateLimits/{id}: allow read, write if request.auth != null and (optional) role is server or callable sets this via Admin SDK.
- Other collections: read/write only when
request.auth != nulland token claims match resource (e.g. orgId, contractKey). No cross-tenant reads.
Patterns
- hasOnly: Restrict document shape on create/update:
request.resource.data.keys().hasOnly(['field1','field2']). - Type checks:
request.resource.data.field is string,request.resource.data.count is int. - Token protection: Shared account tokens in Firestore: allow read/write only for super_admin (request.auth.token.role == 'super_admin').
Deployment
- Rules live in
firestore.rules. Deploy withfirebase deploy --only firestore:rules. Test in Rules Playground with authenticated and unauthenticated requests; verify tech cannot read another tech’s JobWork and cannot write AssignedTechKey to different value.