v0.5.0 — Tracking, Real-Time Push, and Alerts Foundation
Pre-releasev0.5.0 — Tracking, Real-Time Push, and Alerts Foundation
This release covers everything since v0.4.0, including an unplanned but
critical security hardening pass — see below.
⚠️ Security Hardening (previously unreleased)
The API had no authentication at all until this point. Every endpoint
was publicly readable and writable, and customer-scoped routes had no
ownership check — any authenticated (or entirely unauthenticated) caller
could read or modify any customer's data, including live vehicle location.
Fixed:
- Firebase JWT bearer authentication, validated against Google's own
signing keys — no custom login/token-issuing endpoint - Deny-by-default authorization policy: every endpoint now requires a
valid token unless explicitly marked[AllowAnonymous] Customer.FirebaseUidlinks Firebase accounts to customer records[OwnsCustomer]filter for{customerId}routes; service-layer
ownership checks for vehicle/telemetry routes keyed by a resource ID
rather than a customer ID- Staff-only role restriction on list ("get all") endpoints
- Non-owned resources return
404, not403— avoids confirming a
resource's existence to a caller who doesn't own it - Production exception handler no longer leaks raw database error
details in its response
If you're consuming this API from any client, every request now
requires a valid Firebase Bearer token — this is a breaking change from
prior versions.
GPS Tracking History
GET /api/gpstracking/trips— computes trip and stop reports for a
vehicle over a date range- Each trip includes start/end point and time, duration, real route
distance (sum of point-to-point movement, not straight-line
displacement), and max/avg speed - Each stop includes location and full duration (5+ continuous
minutes stationary) - GPS-jitter filtering: a "trip" additionally requires 100m+ of genuine
displacement, so drift while parked isn't misread as a trip
Real-Time Location Push
Replaces fixed-interval polling with live push, typically under 2
seconds from database write to client receipt:
- A Postgres trigger fires
pg_notifyon everyCurrentLocationswrite - A background listener service holds a persistent, session-pooled
connection and relays notifications to a SignalR hub - Clients join a per-vehicle SignalR group; joining enforces the same
ownership rule as REST endpoints
Infrastructure note: the listener requires Supabase's session
pooler (port 5432), not the transaction pooler (port 6543) used
elsewhere — LISTEN/NOTIFY needs a stable, persistent connection that
transaction-mode pooling can't provide.
Alerts & Notifications (Foundation)
GET /api/alerts— caller's own alert history, ownership-scopedPATCH /api/alerts/{alertId}/read— mark as readPOST /api/alerts/register-token— register/refresh an FCM device token- Not yet included: push delivery and the trigger logic that detects
alert-worthy conditions (ignition change, overspeed, power-cut, low
battery, device offline, geofence). The data model supports these alert
types; nothing yet creates anAlertrow automatically.
Upgrade notes
- No manual data migration needed for existing records — all new tables
(Alerts,CustomerFcmTokens) are additive. - Any client integration must be updated to send a Firebase Bearer token
on every request, per the security hardening above.
What's next (v0.6.0)
- Alerts push delivery (FCM) + trigger detection for state-change alerts
- Device offline detection (periodic check)
- Geofencing (new schema, fence management, boundary-crossing detection)
Full changelog: see [README.md](./README.md#release-history)