feat(gateway): address geocoding (Nominatim) for kernels + orders - #174
Open
LamaSu wants to merge 4 commits into
Open
feat(gateway): address geocoding (Nominatim) for kernels + orders#174LamaSu wants to merge 4 commits into
LamaSu wants to merge 4 commits into
Conversation
Address -> {lat,lng} via the open OpenStreetMap Nominatim search endpoint.
No third-party SDK and no API key: a small client with a descriptive
User-Agent, a per-request timeout (AbortController), and an in-memory cache.
Fails soft (null on any error/timeout/empty) so callers keep their fallback.
Injectable fetch seam (setGeocodeFetch) + an IS_TEST guard so tests never
make live Nominatim calls. 12 unit tests cover happy path, caching, and every
soft-failure mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KernelFacade.register() now resolves a postal address to coordinates when an
operator supplies physicalAddress (or the legacy string-form location) but no
explicit { lat, lng }. Previously every such kernel persisted location {0,0},
which silently broke delivery-distance and location-aware matching.
Soft-fail: on a geocode miss the {0,0} sentinel is kept (prior behaviour). When
explicit coords are sent the geocoder is never consulted. 4 wiring tests cover
address->coords, legacy string form, explicit-coords short-circuit, and miss.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
POST /api/demo/pizza-order now resolves the buyer's deliveryAddress to coordinates when no deliveryLocation is supplied, instead of always falling back to the hardcoded SF drop point. The resolved point feeds the compose location filter, so shop/driver matching is anchored to the real delivery address. Order of precedence: explicit deliveryLocation > geocoded address > SF default. 2 wiring tests cover address->coords (order planned at the geocoded point) and the explicit-coords short-circuit (geocoder never called). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up build lane from the pizza-order roleplay (Spark, build-only). CI verifies build+tests. Self-flagged gaps below:
Address geocoding — implementation + verification notes
Branch:
fix/lane-geocode. Scope: gateway address→{lat,lng} geocoding.Build + test only — no deploy, no push to prod, no GHCR/Railway/:prod changes.
Status: done, verified by scoped tests (mocked geocoder, no live Nominatim)
A user can now enter a street address and have it resolved to
{lat,lng}atthe two seams that need real coordinates. Previously kernels/orders carried
{lat:0,lng:0}(or a hardcoded SF default), so delivery-distance andlocation-aware matching couldn't work.
What was built
Clean-room geocode client —
packages/gateway/src/services/geocode.ts.geocode(address) -> {lat,lng} | nullover the open OpenStreetMapNominatim search endpoint (
/search?format=json&q=...). No third-party SDK,no API key.
User-Agent(Nominatim policy requires one), per-requesttimeout via
AbortController, in-memory success cache (negative results arenot cached, so a transient outage can't poison an address).
body returns
null. Every caller keeps its existing fallback.setGeocodeFetch()injects a fake fetch;IS_TESTguardmeans tests never make a live call unless a fetch is injected.
PCC_GEOCODE_URL,PCC_GEOCODE_USER_AGENT,PCC_GEOCODE_TIMEOUT_MS.Seam 1 — kernel registration (
facades/kernel.facade.ts,register()):when an operator supplies
physicalAddress(or the legacy string-form