Skip to content

feat(venues): canonical city keys; GET /venues/facets (#667) - #675

Open
h0mele55 wants to merge 6 commits into
mainfrom
feat/667-canonical-cities
Open

h0mele55 wants to merge 6 commits into
mainfrom
feat/667-canonical-cities

Conversation

@h0mele55

Copy link
Copy Markdown
Collaborator

Part of #667. Owner decision 2026-11-12: a canonical Bulgarian city list; venues reference a city id; old rows migrated; the API returns the name in the viewer's language.

  • P86 migration (additive): venue.cityKey (nullable, indexed), filled from city by a BEFORE INSERT OR UPDATE OF city trigger through venue_city_key_for(), and backfilled as app_superuser (FORCE RLS, as in P41). A city outside the list keeps a null key and its typed text. The previous image never names the column, so a rollback keeps working and its writes are still keyed.
  • One list: the keys are CITY_SPELLINGS (src/lib/geo/cities.ts, [Core] /venues: sport and city filters, Bulgarian city names #357), whose display names already live in messages/*.json under cities.<key>. The SQL function is generated from that list; the new guardrail city-key-sql.test.ts fails if they drift (adding a city = a migration replacing the function).
  • API: every VenueSummary/VenueDetail gains cityKey and cityNames {bg, en} (the v1 API has no request language, so both go out). ?city= on /venues and /venues/near takes the key (any spelling still works). New public GET /api/v1/venues/facets: cities: [{value, key, names}] (one per key) and sports, from the same query as the web's filters; added to the BYPASSRLS allowlist with its reason.

Checked locally: tsc; eslint; guardrails + unit + rendered (9945); integration: new venue-city-key (trigger on insert and edit, card fields, ?city=sofia, facets dedupe), api-v1-public-reads, venue-filters, least-privileged-role, rls-policy-shape (43) on a private test DB.

Overlaps #673 on dto.ts and three test fixtures; whichever lands second is rebased.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DfeuWUNfBvCav72pHsXdHa

user and others added 6 commits November 12, 2026 14:41
Owner decision 2026-11-12: a canonical Bulgarian city list, venues
reference a city id. `venue.cityKey` (P86) is filled from the typed city by
a trigger on every write, backfilled, and is a key of CITY_SPELLINGS
(src/lib/geo/cities.ts), whose names already live in the catalogues. A
guardrail holds the SQL function to the TypeScript list.

Every venue card carries cityKey and cityNames {bg, en} (the v1 API has no
request language); `?city=` takes the key; GET /api/v1/venues/facets offers
one city per key and the live sports, so the phone stops showing «Sofia»
and «София» as two cities and stops missing cities past its first page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfeuWUNfBvCav72pHsXdHa
`migration_lock.toml` sits beside them, and reading it as a folder failed
the whole suite to load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfeuWUNfBvCav72pHsXdHa
`toVenueDetail` spreads `toVenueSummary`, so a venue's detail carries
currency, clubLogoUrl, cityKey and cityNames, but the flat VenueDetail
schema only named them on VenueSummary: the iOS client could not read
them on the venue screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfeuWUNfBvCav72pHsXdHa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant