Commit Graph

4 Commits

Author SHA1 Message Date
Suriyakumarvijayanayagam
6e5da09329 fix: miler logs read returns newest rows, not oldest (blank early-boot ping)
GetMilerLogs fetched miler_periodic_logs with ZRangeByScore (ascending) +
Count: limit, so ?limit=1 returned the FIRST ping of the day — an early-boot
row with GPS but empty battery/connection/accuracy — instead of the latest
fix. That is exactly the blank-telemetry the rider-detail console showed,
even though the app was sending full telemetry (verified in live Redis).

Switch to ZRevRangeByScore (newest-first) so a limit-capped window keeps the
most recent rows, then flip the slice back to chronological so the trail and
distance sum still walk consecutive fixes in ride order. ?limit=1 now returns
the latest full-telemetry row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WRaFH5hMRqmUQvVPQsyjZD
2026-08-28 16:43:29 +05:30
Suriya
f44e8fa3b4 fix: access checks that returned utils.Forbidden never blocked anything
utils.Forbidden and utils.NotFound write the response and return c.JSON's
nil. Any helper that signalled refusal by returning one of them handed its
caller a nil error, so every `if err != nil { return err }` guard passed and
the handler carried straight on.

The observable result: GET /admin/milers?tenantid=14 as a DailyGrubs login
returned HTTP 403 with all 30 of the network's riders in the body. Status
line correct, payload leaked.

Three helpers were affected:
  effectiveTenantID    (yesterday, mine) — cross-tenant read returned the
                       unfiltered list under a 403
  canAccessBooking     (was assertBookingAccess, shipped in 6d9232f) — four
                       mutating booking handlers were unguarded
  findMilerForConsole  (was assertMilerAccess) — worse, callers went on to
                       dereference the nil profile

All three now return a bool and the caller writes the refusal itself, so the
control flow is visible at the call site instead of hiding in a helper.

Adds a test that pins utils.Forbidden/NotFound returning nil, so if that ever
changes the assumption breaks loudly rather than silently, plus table tests
for effectiveTenantID.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 12:32:13 +05:30
Suriya
42f2a41ff6 feat: filter console reads by tenant, for clients and for Doormile staff
Two halves of the same thing. A client login was already pinned to its own
tenant on most reads, but the roster, the B2C customer list and the dashboard
counters were not — a DailyGrubs login listed the whole network's riders.

The other half was missing entirely: Doormile's own staff had no way to look
at one client's slice. Reports accepted ?tenantid= but applied it only to the
consignment count, and bookings accepted it while milers, customers,
consignments and the dashboard ignored it.

effectiveTenantID(c) now resolves both cases in one place — the caller's own
tenant for a client login, the requested one for Doormile staff, 0 for the
whole network. A client asking for someone else's tenantid is refused rather
than silently handed their own data back under the wrong label.

Applied to: milers, customers, bookings, consignments, dashboard, reports and
the rider summary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 12:01:13 +05:30
Suriya
d85d5571b8 feat: rider visibility and tracking for the express console
A client login could list its own bookings but had no way to see what its
riders were actually doing. jupiter's console gave them getridersummary and
the rider/delivery logs; Doormile records all of it and exposed none of it.

New console endpoints, all tenant-scoped:
  GET /admin/milers/summary        roster with live state + range totals
  GET /admin/milers/:id/logs       GPS trail from the Redis telemetry index
  GET /admin/milers/:id/activity   one rider's assignments, duty and breaks
  GET /admin/consignments/:id/logs event history + telemetry + proof
  GET /admin/bookings/:id/track    booking -> assignments -> parcel -> proof

Also closes a rider IDOR: GetMilers scoped the roster to the caller's own
fleet, but reading, editing, blocking, notifying or assigning a vehicle to a
single rider by id did not, so a client login could walk the whole network's
riders by incrementing the id. All five now go through assertMilerAccess.

And the client dashboard no longer reports milers/customers/exceptions as
zero — those have no tenant column, so they are counted through appusers,
bookings and consignments respectively.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 11:41:02 +05:30