Files

72 lines
2.6 KiB
Markdown

# FuelBoard Relay
Keyless proxy for the **UK Fuel Finder API**. Holds the GOV.UK OAuth 2.0
client credentials server-side so the FuelBoard iOS app and widget never embed
a secret (secrets inside an IPA are extractable by anyone).
## Architecture
```
FuelBoard app / widget
│ GET http://192.168.1.131:8788/api/v1/stations?fuel=e10&lat=..&lng=..
FuelBoard Relay (this repo, runs on the Mac Mini)
│ OAuth 2.0 client_credentials grant (token cached ~1h)
│ GET https://api.fuelfinder.service.gov.uk/v1/prices (snapshot, cached 5 min)
UK Fuel Finder API (official gov.uk open data)
```
- Token refreshed automatically before expiry (60s buffer).
- Station snapshot cached `FUEL_CACHE_TTL` (default 300s); stale cache is
served on upstream failure so the app never sees a hard outage.
- No credentials are exposed to clients — the app calls the relay keyless.
## Setup
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then fill in FUEL_API_CLIENT_ID / FUEL_API_CLIENT_SECRET
./scripts/run.sh
```
Without credentials the relay runs in **demo mode**: `/health` reports
`demo_mode: true` and `/api/v1/stations` returns a clean 503 with a hint —
useful for testing the app→relay path before credentials exist.
## Endpoints
| Endpoint | Description |
|---|---|
| `GET /health` | Cache status, last sync, failure counters |
| `GET /api/v1/stations` | All stations with prices (keyless) |
| `GET /api/v1/stations?fuel=e10&lat=53.72&lng=-1.85&radius=10&limit=10` | Filter by fuel, radius around a point, sorted nearest-first |
| `GET /api/v1/stations?fuel=diesel` (no lat/lng) | Sorted cheapest-first |
Fuel grades: `e10`, `e5`, `diesel`.
## Getting credentials
1. Sign in at <https://developer.fuel-finder.service.gov.uk/get-started-ifr/onelogin> with GOV.UK One Login.
2. Register an application → get `client_id` + `client_secret`.
3. Put them in `.env` (never in git, never in the app).
## Fair use notes (from the Fuel Finder developer guideline)
- Refresh at least every 5 minutes — we do (cron-style refresh on request + TTL cache).
- Serve data unmodified — this relay only filters/sorts, never alters prices.
- Keep timestamps — `price_updated` is passed through untouched.
## Integration point (FuelBoard app)
`Shared/FuelPriceProvider.swift` has `FuelFinderProvider` stubbed with a
`TODO`. When the relay is live, point it at:
```
http://192.168.1.131:8788/api/v1/stations?fuel=<e10|e5|diesel>&lat=..&lng=..
```
and map `stations[].price` / `stations[].distance_km` into `FuelStation`.