App:
- When the single-estimate fallback sees MaxTime 0 (or an all-$0.00 ladder),
show "Parking is currently free" instead of a bogus $0.00 purchase ladder.
Free-detection extracted to tested client helpers (isFreeEstimate/ladderAllFree).
Client + tests (node:test, zero deps):
- src/estimates.ts: pure isFreeEstimate/ladderAllFree helpers (exported).
- test/estimates + test/http (mocked fetch): headers, query serialization,
error->ParkSmarterApiError, rolling Auth_Token refresh, 401 clears token.
- test/integration: live checks against the Sandpoint (DSB) zones; targets the
`test` instance by default and SKIPS when it's unreachable (non-prod is
IP-restricted -> 403). Verified 3/3 green against prodv2 read-only.
- CI runs `npm test` as a build gate.
Note: dev/stage/test instances return 403 "Web App - Unavailable" from the
public internet (IP-restricted). API schema is otherwise unchanged vs Jul 6.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reverse-engineered ParkSmarter API client (TypeScript, live-verified) plus a
de-Googled Expo/React Native app for GrapheneOS: MapLibre meter map with GPS,
VisionCamera QR kiosk scanning with save/share, local session-expiry reminders,
UnifiedPush wiring, and Gitea CI to publish signed APKs for Obtainium.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>