Geofence module

Tenant definitions (circles & polygons), trip assignments, motion-engine ingest with journey memory, immutable event log, and signed outbound webhooks. Uses Postgres when POSTGRES_URL is set; otherwise a server-local JSON file (GEOFENCE_MODULE_STORE_PATH). Telematics uses POST /api/geofence-ingest with X-Geofence-Ingest-Key.

Motion hub Dispatch

Geofencing — how it actually works

A plain-English walkthrough of the BlueDXP geofencing pipeline: the inputs it listens to, the math it runs on every GPS ping, the events it produces, and the actions it takes without anyone pressing a button.

220
Pre-mapped anchors (ports, borders, hubs)
5
Corridor families auto-recognised
4
Event types emitted
< 100ms
Per-ping evaluation budget

The 30-second picture

Every GPS ping flows through the same four stages, in the same order, every time.

1Receive
A GPS ping arrives — driver app, telematics box, or the demo replayer.
2Evaluate
Engine checks the corridor, 220 anchors, and any custom zones.
3Decide
Inside? Outside? Entered a port? Crossed a border?
4Act
Log event, fire webhook, ask driver via WhatsApp.

Step-by-step: what happens to a single GPS ping

Same six stages, broken open. Each card shows who is involved, what runs, and what comes out the other side.

1
Stage 1 of 6
A position arrives
WHO RUNS IT
Driver app, telematics provider, or the demo replayer.
WHAT HAPPENS
POST /api/geofence-ingest with trip_id, latitude, longitude. The system already knows which corridor and cargo type belong to this trip from the auto-attach step that ran when the lane was created.
WHAT COMES OUT
A validated position bound to a trip and an organisation.
2
Stage 2 of 6
The motion engine evaluates the geometry
WHO RUNS IT
motion-corridor-engine.js — pure math, no external calls.
WHAT HAPPENS
Computes distance to the corridor polyline, checks 220 port/border/hub anchors, checks any custom polygons the operator drew, and applies the deviation threshold tightened for the cargo type (DG, temperature, high-value).
WHAT COMES OUT
A snapshot: corridorState (inside/outside), adherence percentage, list of anchors the truck is currently inside, nearest anchors.
3
Stage 3 of 6
The engine compares against memory
WHO RUNS IT
Trip state stored in Postgres (or JSON fallback).
WHAT HAPPENS
Looks at the previous snapshot for this trip. Did we just enter an anchor we were not in before? Did the corridor state flip from inside to outside? Did the journey phase change (loading → mainline → dest border)?
WHAT COMES OUT
Zero or more journey transitions: anchor_entered, anchor_exited, corridor_state_changed, inferred_role_changed.
4
Stage 4 of 6
Events are written to the log
WHO RUNS IT
geofence-module-store.js — single source of truth.
WHAT HAPPENS
Every transition becomes an immutable row in geofence_events with the lat/lon, severity, and a full motion snapshot for audit. The trip state is updated atomically in the same write.
WHAT COMES OUT
Permanent, queryable event history per trip and per organisation.
5
Stage 5 of 6
Webhooks fire to partners
WHO RUNS IT
Outbound HTTP with HMAC-SHA256 signature.
WHAT HAPPENS
For each event, every active webhook for that organisation is filtered by event_type and posted with a signed header so the receiver can verify it really came from BlueDXP.
WHAT COMES OUT
Real-time notifications to ERPs, customer portals, partner systems.
6
Stage 6 of 6
WhatsApp asks the driver to confirm
WHO RUNS IT
Hazalyze gateway, only on touchpoint entries.
WHAT HAPPENS
When the truck enters a meaningful anchor (port, border, consignee) the system sends a WhatsApp location request to the bound driver phone. A per-trip per-touchpoint cooldown (15 min default) prevents GPS jitter from spamming.
WHAT COMES OUT
A short message to the driver, an audit event in the log, and a pending location binding so the inbound share is auto-correlated to the trip.

What is automated vs what a human does

CapabilityHow it worksMode
Corridor inference from origin/destination textKeyword matcher recognises 5 corridor families (KSA→KW, KSA→JO, KSA→EG land, KSA→EG sea, KSA landbridge).Automated
Cargo-type threshold tighteningDG cuts deviation tolerance to 55%, temperature to 82%, high-value to 75% of the default band.Automated
Geofence assignment when a lane is createdautoAttachLane() arms monitoring before the first GPS ping, idempotent on retries.Automated
Journey phase detectionDerived from which anchors the truck currently sits inside, weighted by journeyPhaseOrder.Automated
WhatsApp location request on anchor entryAutomated when GEOFENCE_WA_AUTO_REQUEST=1, with per-touchpoint cooldown to prevent jitter spam.Automated
Webhook signing and fan-outEvery event is signed and pushed to all matching active webhooks.Automated
Drawing custom zones (yard A, restricted area, etc.)Operator creates a circle (lat/lon/radius) or polygon ring in the Definitions tab.Manual
Registering a partner webhook URLOperator pastes the HTTPS URL once; the signing secret is shown one time.Manual
Adding new corridors to the inference tableEngineering edits CORRIDOR_HINTS in geofence-auto-attach.js.Manual
Rotating the telematics ingest secretEnvironment variable change today; will become per-tenant later.Manual

Live demo replay — Dammam to Kuwait City

The seeded scenario sends 8 GPS pings through the real ingest pipeline. This is what the system sees and emits at each step — the same code path a production lane will hit. Run it from the Demo tab.

PingLocationCorridor stateWhat fires
1Loading at Dammam port yardinsideanchor_entered: tp-dammam-port-corridor
2Departing Dammam — heading westinsideanchor_exited: tp-dammam-port-corridor
3Mid-corridor — Saudi–Kuwait spineinside(no transitions, adherence high)
4Approaching Khafji border zoneinside(no transitions, adherence high)
5Driver detours to fuel station off-corridoroutsidecorridor_deviation (severity: high)
6Back on the spine after refuelinsidecorridor_state_changed: outside → inside
7Crossing into Kuwait City metroinside(adherence rises again)
8Arrived Kuwait City consigneeinsideanchor_entered → triggers WhatsApp confirm

Capabilities at a glance

Inputs the system listens to

1Operator UI — draw zones, assign trips, view events, register webhooks.
2Lane creation hook — every new freight listing or dispatch trip auto-arms monitoring.
3Telematics POST — GPS providers push positions with a shared-secret header, no user login needed.
4Driver WhatsApp share — inbound location is auto-correlated to the trip via a pending binding.

Outputs the system produces

1corridor_deviation — truck strayed beyond the cargo-adjusted band.
2journey_transition — entered or exited a port, border, or hub anchor.
3custom_zone_enter / exit — operator-drawn circle or polygon crossed.
4whatsapp_location_request_sent / skipped / failed — full audit of every outbound prompt.

Smart logic baked in

·Cargo-aware deviation thresholds — DG, temperature, and high-value loads get tighter bands automatically.
·Journey memory with versioning — the engine remembers which anchors a trip was inside last ping, so transitions are real, not phantom.
·Per-trip + per-touchpoint cooldown — GPS jitter at a border cannot spam the driver with WhatsApp prompts every 30 seconds.
·Idempotent auto-attach — the same lane created twice will not produce two monitoring rows.

Safety nets and audit

·Multi-tenant isolation on every read and every write, enforced by organization_id.
·Dual storage — Postgres in production, JSON file fallback so a laptop demo runs the same code path.
·Signed outbound webhooks (HMAC-SHA256) so partners can verify the payload truly came from BlueDXP.
·Reproducible end-to-end demo — replay 8 pings any time and prove what monitoring would have done.

The five things that happen with no human in the loop

From the moment a freight lane is created until the driver pulls up at the consignee, this is what runs on its own.

1Lane is created → corridor + route + cargo type are inferred and monitoring is armed.
2GPS ping arrives → engine evaluates 220 anchors, polyline distance, custom zones, and intel polygons in one pass.
3Trip state is compared against last ping → entry, exit, deviation, and phase change events are produced.
4Events are persisted (Postgres or JSON), then signed and pushed to every matching partner webhook.
5On meaningful entries (port, border, consignee) the driver receives a WhatsApp location request, with cooldown protection.
Try it yourself. Click the Demo tab above and press Run demo. You will see all 8 pings replayed and the resulting event log appear in real time — the same tables a real shipment writes to.

Definitions

NameKindId

Assignments

TripDefinitionCorridor

Event log

TimeTripTypeSeverityDetail

Outbound webhooks

Signing secret is returned once; we send X-BlueDXP-Geofence-Signature: sha256=<hmac> on POST.

IdURL

End-to-end demo (lane → touchpoints → WhatsApp)

Replays a synthetic Saudi → Kuwait drive (8 GPS pings) through the same code path a real lane uses. Auto-attaches a demo trip, fires /api/geofence-module?action=ingest for each ping, and shows the journey transitions + any WhatsApp location-request attempts that fired. Set GEOFENCE_WA_AUTO_REQUEST=1 + Hazalyze gateway env to receive a real WA prompt on the demo phone.

Raw response


    

Authenticated ingest (JWT)


      

Telematics (shared secret)