--- convoy: pricing-online-local brief_number: 10 depends_on: [1] recommended_model: composer-2.5 model_tier: standard files: - lib/pricing/nominatim.js - lib/pricing/overpass.js - lib/pricing/geo-cache.js - test/lib/pricing/nominatim.test.js - test/lib/pricing/overpass.test.js - test/lib/pricing/geo-cache.test.js --- # Brief 10: Geo clients + DB cache ## Goal (1 sentence) Implement Nominatim geocoding, Overpass store queries, and DB-backed caches per convoy gentleness rules. ## Files in scope (do not edit anything else) - `lib/pricing/nominatim.js` - `lib/pricing/overpass.js` - `lib/pricing/geo-cache.js` - `test/lib/pricing/nominatim.test.js` - `test/lib/pricing/overpass.test.js` - `test/lib/pricing/geo-cache.test.js` ## Conventions to follow - **Security:** Overpass QL uses fixed template only; inject parsed floats for lat/lng/radiusMeters — never user strings. - `nominatim.js`: User-Agent from `NOMINATIM_USER_AGENT`; min 1s between requests. - `overpass.js`: query `shop=games` and `shop=hobby`; radius capped 1–50 miles server-side. - `geo-cache.js`: zip coords cached forever; stores cache 7-day TTL. - Allowlist outbound hosts at module init. ## Acceptance criteria - [ ] Zip cache hit skips Nominatim - [ ] Stores cache respects 7-day TTL - [ ] Overpass parser returns distance-ready lat/lng per store - [ ] Unit tests cover parser + TTL logic - [ ] Tests pass - [ ] No scope expansion ## Rationale (≤3 sentences) Isolates external geo APIs from the route handler for testability. DB cache avoids Redis dependency for long-lived zip coords. Satisfies convoy rate-limit requirements before Brief 11 wires the API.