Documentation

Technical documentation for the PestControlOS CRM and Android app.

Architecture, security, Firestore model, and feature details for developers and technical reviewers.

Firestore Security Rules (reference)

Technical reference for Firestore Security Rules used across PestControlOS.

Rule structure

  • Default: Deny all. Each match block explicitly allows read/write when conditions are met.
  • Authentication: request.auth != null for any user-specific data. Use request.auth.uid and 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 if request.auth != null and (optional) request.auth.uid or 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 set AssignedTechKey to 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 != null and 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 with firebase 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.