DEV Community

Dogukan Kardas
Dogukan Kardas

Posted on Originally published at dogukankardas.com

Location-verified task flows with Firebase

EV SLA manages field technician tasks where "I started the job" must mean "I am physically at the site". This post covers the geofence check, the realtime state machine, and what happens when connectivity drops mid-shift.

The geofence check

Each task carries the site coordinates and an allowed radius. On "start job", the client captures a GPS fix and the check runs with the haversine distance. The radius adapts to reported GPS accuracy so technicians in dense urban areas are not falsely rejected.

Haversine distance with accuracy-aware radius

function canStartJob(task: Task, fix: GeoFix): boolean {
  const distanceM = haversine(task.site, fix.coords);
  // Widen the fence by the GPS accuracy, capped to avoid abuse
  const tolerance = Math.min(fix.accuracyM, MAX_ACCURACY_BONUS_M);
  return distanceM <= task.radiusM + tolerance;
}
Enter fullscreen mode Exit fullscreen mode

Task state as a realtime document

Task state lives in Firestore and every transition is validated by security rules — the client cannot jump from assigned to completed without passing through a verified started state that includes the location proof.

Firestore rule enforcing the transition

match /tasks/{taskId} {
  allow update: if
    request.auth.uid == resource.data.assigneeId &&
    (
      // assigned -> started requires a location proof
      (resource.data.status == 'assigned' &&
       request.resource.data.status == 'started' &&
       request.resource.data.startProof.keys().hasAll(['lat','lng','accuracy','at']))
      ||
      // started -> completed
      (resource.data.status == 'started' &&
       request.resource.data.status == 'completed')
    );
}
Enter fullscreen mode Exit fullscreen mode

Offline tolerance without breaking trust

  • The GPS fix is captured and signed with a timestamp at the moment of the action, not at sync time.
  • Firestore’s offline persistence queues the transition; rules validate it on replay.
  • Supervisors see a pending-sync badge instead of stale state, which killed most "the app is wrong" support calls.

The result: dispatchers trust the board, technicians are not blocked by dead zones, and disputed job-start times dropped to effectively zero after rollout.


Originally published on dogukankardas.com. The full case study is here: EV SLA. I build software for small businesses and SaaS teams — see more at dogukankardas.com.

Top comments (0)