[feature] Resolve valid IDFM services #3
- @github-anthodev opened this issue · Aug 29, 2026edited
🔢 Impact Version (SemVer)
MINOR
🌿 Suggested Branch
feature/resolve-idfm-services/backend/3
📝 Description
Users must create favorites from real Île-de-France Mobilités services without seeing or combining transport identifiers. Build the backend catalog/search boundary that maps a user-facing place to only its valid line/direction combinations and returns an opaque
serviceIdfor later departure requests.This ticket owns evidence-backed IDFM reference-data selection, catalog refresh lifecycle, accent-tolerant bounded search, homonym/platform/direction distinctions, preservation across revisions, and a runtime path that never spends the user's personal stop-monitoring quota.
✅ Expected Behavior
The backend searches representative Île-de-France stops/stations, lists only combinations supported by the current catalog, and resolves each selection to one backend-controlled opaque service identifier suitable for a PRIM stop-monitoring request. A failed refresh never takes the last complete catalog offline, and removed services become explicitly unresolved rather than silently pointing somewhere else.
📋 Acceptance Criteria
- Evaluate current official IDFM reference sources and record which source joins user-facing places, stop areas/quays, lines, directions, and PRIM monitoring identifiers; include sample identifier traces proving the join for bus, metro, tram, RER, and Transilien.
- Import or cache only the catalog data required by version 1 and validate it before activation.
- Select a catalog source/refresh path that does not require a production user's personal key in the browser or watch flow; any authenticated build-time import secret is operator-supplied, ephemeral, redacted, and absent from artifacts.
- Define and implement a refresh process that builds and validates a replacement separately, atomically activates it, and leaves the previous complete catalog available when replacement fails.
- Implement accent-tolerant stop/station search without collapsing distinct homonyms, stop areas, quays, or directions.
- Return only lines and directions attached to the selected place; never accept a client-constructed combination that the active catalog did not offer.
- Keep all raw IDFM/SIRI identifiers behind an opaque
serviceIdboundary. - Preserve favorites whose services remain resolvable across a catalog refresh without changing their meaning.
- Report a removed or unresolvable service explicitly; never redirect it to a similar stop, line, or direction.
- Search returns representative bus, metro, and RER or Transilien places, preserving the source Gate.
- The active catalog and deterministic integration fixtures cover valid place→service resolution for all five version-1 modes: bus, metro, tram, RER, and Transilien.
- Every offered selection resolves to a PRIM query supported by the current catalog.
- Opposite directions on the same line produce different opaque service IDs.
- Bound search to trimmed queries of 2–100 characters and at most 20 ranked results; measure a representative full-catalog workload and require cache-warm p95 backend search latency ≤200 ms without unbounded allocation.
- Record links to representative query output, identifier traces, latency/memory measurements, refresh success/failure proof, and removed-service proof in a resolution comment before closing this issue.
🔗 Affected Endpoints/Routes
- New read-only backend routes for bounded place search and valid service options; these routes use the local/reference catalog and never call PRIM stop monitoring.
- Freeze exact paths, 2–100-character queries, 20-result maximum, and response schemas in repository contract tests before the configuration-page ticket consumes them.
- No route may accept arbitrary raw stop/line/direction/PRIM identifiers or a personal PRIM key from a client.
🧪 Tests to Add
Type Coverage Unit tests Accent normalization, homonym preservation, direction distinction, opaque ID generation/resolution, unresolved-service behavior Catalog integration tests Import validation and supported place→service joins for bus, metro, tram, RER, and Transilien; atomic successful refresh; failed-refresh rollback HTTP contract tests Search/service response schemas, invalid selections, pagination/limits, absence of raw source identifiers Recorded-data smoke Representative current IDFM catalog samples resolve to supported PRIM request inputs Performance tests Full representative catalog; cache-warm p95 ≤200 ms; 20-result bound; peak-memory measurement during refresh/search
⚙️ Constraints
- Version 1 covers Île-de-France through PRIM only.
- A favorite is one backend-validated stop/line/direction service; clients never construct one from unrelated values.
serviceIdis opaque and stable outside the backend.- The backend stores no user preferences, searches, or favorites.
- Catalog refresh must keep the previous complete catalog live until a replacement is fully valid.
- Catalog search and browsing make zero PRIM stop-monitoring calls and consume zero personal-key quota.
- National SNCF integration, nearby-stop search, and journey planning remain out of scope.
🔀 Dependencies
- Blocked by
[feature] Establish the application foundation and contracts(https://github.com/Anthodev/lapin-fute/issues/2). Reuse its repository structure and frozen shared contracts; do not introduce a second service identifier or schema-version convention.
⚠️ Impact on Existing Behavior
Introduces the first backend catalog boundary. Later configuration and departure tickets must consume its opaque service options instead of reaching into IDFM data directly.
🔍 Technical Context
The selected catalog must support this flow: place search → one place → only its valid line/direction options → one opaque
serviceId→ a PRIM stop-monitoring request. The source selection is deliberately part of this ticket because the repository contains no verified IDFM catalog decision yet.Required references
Sign in to comment.