Doc status: Latest (rolling). See Versions.
Goals
- Prevent unauthorized alerts, membership changes, and admin actions.
- Minimise stored sensitive data (no exact home addresses; avoid exact lat/lng when possible).
- Make abuse and spam harder than legitimate use.
- Keep security controls server-side and auditable.
Threat model (practical)
Primary threats
- Account takeover of a legitimate user (phishing, device compromise).
- Malicious member (or ex-member) attempting spam/harassment via alerts.
- Invite leakage leading to unauthorized joins.
- API abuse (bot traffic, token replay, endpoint discovery).
- Device-token abuse (registering many tokens, sending to wrong audience).
Non-goals
- Defending against a fully compromised manager account beyond standard controls.
- Guaranteeing critical-alert behavior on iOS without Apple entitlement approval.
Identity & authentication
- Clients authenticate with Firebase Auth.
- All API calls are authenticated with an ID token:
Authorization: Bearer <token>. - The Worker verifies the Firebase ID token server-side and derives the canonical
uid. - Never trust
uid/role claims from the client; always compute authorization server-side.
Authorization & privileges
Authorization is enforced in the Worker, using Firestore membership state:
Member actions
registerDevice: only for self (uidfrom token)joinGroupViaInvite: only for selftriggerIncident: only if the user is an active member of the group
Manager actions (group scoped)
- pause / ban member
- create/revoke invites
- broadcast
Membership status is enforced server-side:
active: may trigger incidentpaused: cannot trigger incidentbanned: cannot trigger incident or re-join (unless explicitly unbanned)
Data minimisation & PII policy
- Do not store exact home addresses.
- Avoid storing exact latitude/longitude when possible.
- Prefer coarse “zones” (e.g., suburb-level or grid cell identifiers) rather than precise locations.
- Store only what is necessary to operate:
- user identity:
uid, optionalemail/displayName - device push token + platform
- group membership + role + status
- incident metadata (time, group, type)
- user identity:
Address privacy (on-device + encrypted)
- A user’s exact home address is stored only on their phone.
- The address is transmitted only when an alert is triggered, and only as an encrypted payload.
- The backend must not log or persist plaintext addresses.
If an incident record stores the address at all, it must store only an opaque encrypted blob with a short TTL.
Cryptography (PQC-ready)
We use AES-256-GCM for payload encryption.
Important detail: FALCON and Dilithium are signature schemes (authenticity/integrity), not encryption. For key transport/encryption we use a KEM.
Recommended suites:
- Payload: AES-256-GCM
- Key transport (KEM): ML-KEM-768 (Kyber)
- Signatures: FALCON-512 (preferred if available) or ML-DSA-44 / Dilithium2
For forward compatibility, include a cryptoSuite and kid (key id) in encrypted payload metadata.
Key management & rotation
- Each device generates and stores its private keys locally.
- Only public keys are stored centrally (e.g.,
users/{uid}/crypto). - Key rotation is supported by publishing a new
kidand keeping the previous key for a short overlap window.
Recipient scoping
- The Worker computes recipients using server-side membership state (group + status).
- Only active members receive the push payload.
- Ex-members do not receive pushes; even if they retained old keys, they cannot decrypt messages they do not receive.
Push notification safety
- Push is sent via FCM HTTP v1 from the Worker.
- Fan-out targets only the devices of active members in the relevant group.
- Device tokens are treated as secrets:
- never log full tokens
- rotate/re-register on app reinstall
“Loud” alerts limitations
- Android: sound/importance depends on channel configuration and user settings.
- iOS: true “critical alerts” require Apple approval and entitlements. The system can support the payload flags, but entitlement acquisition is an external process.
Abuse controls
Minimum controls (server-side):
- Rate limiting for incident triggering and admin broadcast.
- Idempotency / dedupe to avoid accidental double sends.
- Invite controls
- expiry
- max uses
- revoke capability
Operational controls:
- Managers can pause/ban members.
- Maintain an incident review workflow (even if manual early).
Secrets & configuration
- Service account credentials and FCM credentials must be stored as Cloudflare secrets/env vars.
- Never commit secrets to git.
- Keep separate environments for dev/staging/prod where practical.
Logging & monitoring
Log security-relevant events (without sensitive payloads):
- auth failures
- authorization failures
- invite use / join
- incident triggers (metadata only)
- admin actions
Avoid logging PII and never log device tokens.
Firestore rules
Firestore rules should be treated as defense-in-depth.
- The Worker is the primary enforcement point for privileged actions.
- Client direct access should be restricted to the minimum required (ideally none for privileged writes).
Checklist
- Server-side token verification on every API request
- Group-scoped authorization on every privileged action
- No exact addresses stored
- Device tokens never logged
- Rate limit trigger/broadcast
- Invite expiry + max-uses + revocation