Skip to content

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 (uid from token)
    • joinGroupViaInvite: only for self
    • triggerIncident: 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 incident
  • paused: cannot trigger incident
  • banned: 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, optional email/displayName
    • device push token + platform
    • group membership + role + status
    • incident metadata (time, group, type)

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 kid and 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