#2156 wired an "Open in Lime" chip that today never opens Lime.
rentalUris is null on all 13,396 rental vehicles the Puget Sound OTP2 deployment serves (checked against the live server, 2026-08-03, across both its networks). The sibling iOS app establishes that this is not a local quirk: OBAKit/Mapping/Layers/RentalDeepLink.swift records a survey of all 48 Lime systems in MobilityData's catalog (~87,000 vehicles) finding zero published rental_uris. Deep links are a Lime Transit Partnership feature; the public feed omits them worldwide.
So the deep-link path is dead by construction, not pending a feed fix. The chip falls through to opening the operator's app at its home screen, which drops the rider on a map they must re-find their own bike on.
What iOS does
RentalDeepLink.target(for:) synthesizes the link from the operator's URL scheme and the vehicle's own id when the feed publishes none, ranked below a feed-published URI and above the operator's home page:
- Lime:
limebike://map?selected_vehicle_id=<id>&generated_at=<epoch>
- Bird:
bird:// — Bird cannot target an individual vehicle, so it only ever gets the app-launch form
Android has what it needs. TripVehicleRental.id carries the network:id the raw GBFS bike_id is recoverable from (strip through the first colon), and #2156's fallback chain already degrades gracefully when nothing on the device claims a scheme.
🚩 This is a human sign-off gate
Twice over, under CLAUDE.md's "No unsanctioned heuristics":
- The URL schemes are reverse-engineered and undocumented by the operators — iOS cites ubahnverleih/WoBike.
- iOS's
generated_at is an inferred format (epoch seconds against an untyped <timestamp> in the documented shape).
Tolerable there only because failure is graceful: UIApplication reports success == false when no app claims the scheme, and the caller opens the store fallback. Android's ExternalIntents.openFeedUri already reports the same thing. But this needs a human to accept the guesswork before merge — it is not a call an agent makes alone.
Tasks
Related: #2150, #2138 (the reservation-handoff milestone this deliberately stops short of).
#2156 wired an "Open in Lime" chip that today never opens Lime.
rentalUrisis null on all 13,396 rental vehicles the Puget Sound OTP2 deployment serves (checked against the live server, 2026-08-03, across both its networks). The sibling iOS app establishes that this is not a local quirk:OBAKit/Mapping/Layers/RentalDeepLink.swiftrecords a survey of all 48 Lime systems in MobilityData's catalog (~87,000 vehicles) finding zero publishedrental_uris. Deep links are a Lime Transit Partnership feature; the public feed omits them worldwide.So the deep-link path is dead by construction, not pending a feed fix. The chip falls through to opening the operator's app at its home screen, which drops the rider on a map they must re-find their own bike on.
What iOS does
RentalDeepLink.target(for:)synthesizes the link from the operator's URL scheme and the vehicle's own id when the feed publishes none, ranked below a feed-published URI and above the operator's home page:limebike://map?selected_vehicle_id=<id>&generated_at=<epoch>bird://— Bird cannot target an individual vehicle, so it only ever gets the app-launch formAndroid has what it needs.
TripVehicleRental.idcarries thenetwork:idthe raw GBFSbike_idis recoverable from (strip through the first colon), and #2156's fallback chain already degrades gracefully when nothing on the device claims a scheme.🚩 This is a human sign-off gate
Twice over, under CLAUDE.md's "No unsanctioned heuristics":
generated_atis an inferred format (epoch seconds against an untyped<timestamp>in the documented shape).Tolerable there only because failure is graceful:
UIApplicationreportssuccess == falsewhen no app claims the scheme, and the caller opens the store fallback. Android'sExternalIntents.openFeedUrialready reports the same thing. But this needs a human to accept the guesswork before merge — it is not a call an agent makes alone.Tasks
limebike://is its iOS scheme and does not transfer; Bird's own GBFSrental_apps.android.store_uri/discovery_uriis the authority for Bird. If a scheme can't be sourced, that operator gets no synthesis rather than a guess.Uri.Builder, never string interpolation — iOS documents why it holds URL components: escaping a query value does not escape&or=inside it.RentalPickups.links(), whose ordering doc already explains each step.Related: #2150, #2138 (the reservation-handoff milestone this deliberately stops short of).