Skip to content

Add OTP 2.x GraphQL trip-planning support#1794

Merged
bmander merged 3 commits into
mainfrom
otp2-graphql-trip-planning
Jul 11, 2026
Merged

Add OTP 2.x GraphQL trip-planning support#1794
bmander merged 3 commits into
mainfrom
otp2-graphql-trip-planning

Conversation

@bmander

@bmander bmander commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Sound Transit's OTP server has dropped the OTP1 REST /plan endpoint entirely in favor of GraphQL (planConnection). This adds an OTP 2.x GraphQL trip-planning path alongside the existing OTP1 REST stack, targeting the same app-owned TripItinerary domain model from #1782/#1787/#1790 (#1778) so the UI/ViewModels/trip monitor need zero changes.

  • Vendors OTP's GraphQL schema (pinned to opentripplanner/OpenTripPlanner tag v2.9.0 — not live-introspected, per the issue's guidance) and adds Apollo Kotlin codegen for the planConnection query, using a PlaceFields fragment so Leg.from/Leg.to share one generated type.
  • Adds an explicit Region.usesOtp2GraphQl protocol flag, threaded through RegionDto → Room (migration 5→6, tested in AppDatabaseMigrationTest) → Region, plus a manual "Use GraphQL (OTP 2.x)" toggle in Advanced Settings for the custom-OTP-URL case (there's no Region to carry the flag there). Infra only — no bundled region (including Puget Sound) is flipped to OTP2 by this PR; testing happens via the custom-URL override. Flipping a real region is a follow-up once Sound Transit's endpoint is stable.
  • Otp2PlanRequestBuilder / Otp2PlanAdapters translate to/from the GraphQL wire format (ISO-8601 offset-datetimes and durations, seconds vs. OTP1's ms, structural vertexType inference from stop/rentalVehicle/vehicleParking/vehicleRentalStation rather than OTP2's own deprecated field, extended TripMode enum for OTP2's mode superset) using the same "mint at the boundary" discipline as the OTP1 adapter — requireField/toEnum<E>() are shared between both adapters.
  • Wires OTP1's optimize=TRANSFERS preference through to OTP2's PlanPreferencesInput.transit.transfer.cost. OTP2 replaced the old binary enum with a continuous per-transfer cost (seconds); the 1800s value isn't a guess — cloned OpenTripPlanner at v1.5.0 and confirmed optimize=TRANSFERS historically did exactly request.transferPenalty += 1800 (RoutingResource.java), and that the same transferPenalty concept carries forward to OTP2's transfer.cost via the current repo's own LegacyRouteRequestMapper (callWith.argument("transferPenalty", tx::withCost)).
  • Otp2Planner executes queries via an ApolloClient cached per base URL (avoids rebuilding it on the trip monitor's 60s repeating tick) and maps routingErrors to user-facing messages, reusing OTP1's strings where the failure mode is equivalent and adding two new ones where it isn't.
  • DefaultTripPlanRepository dispatches OTP1 vs OTP2 on TripRequestBuilder.usesOtp2 — explicit, never sniffed from the URL or a failed request, per the issue's acceptance criteria.

Test plan

  • ./gradlew :onebusaway-android:compileObaGoogleDebugKotlin -PwarningsAsErrors=true (and unit-test/androidTest source sets) — clean under the strict CI gate
  • ./gradlew :onebusaway-android:testObaGoogleDebugUnitTest — 826 tests, 0 failures, including Otp2PlanDecodeTest, Otp2PlanRequestBuilderTest (incl. the transfer-cost/wheelchair preference wiring), and a RegionsDecodeTest guard that every bundled region still defaults to OTP1
  • AppDatabaseMigrationTest.migrate5To6_addsUsesOtp2GraphQlColumn_defaultingExistingRowsToFalse — Room migration verified against the exported 6.json schema
  • Full debug APK installs and launches cleanly on a physical device (validates the Hilt DI graph + Room migration on a real DB)
  • End-to-end verified against a real OTP2 GraphQL server (Sound Transit's), via a throwaway instrumented test driving DefaultTripPlanRepository directly with the custom-URL + GraphQL toggle set exactly as a user would configure them — returned a correct WALK → TRAM (2 Line) → WALK itinerary through both the plan() and planBlocking() (trip-monitor) paths; also verified the transit.transfer.cost preference is accepted by the live server via a direct curl request
  • Manual UI walkthrough of the new "Use GraphQL (OTP 2.x)" Advanced Settings toggle (not yet done via the actual UI — verified the underlying state plumbing via unit tests and the direct-repository smoke test instead)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for trip planning through OpenTripPlanner 2.x GraphQL services (including itinerary/leg mapping with real-time delay handling and geometry).
    • Regions can select the trip-planning protocol, with existing regions defaulting to the legacy service.
    • Added an Advanced Settings toggle to mark custom OTP URLs as GraphQL.
  • Bug Fixes

    • Improved OTP2 error messaging (e.g., unavailable service dates, routing errors, and “walking faster than transit” cases).
    • Added Room migration coverage to ensure the new per-region OTP selection flag defaults correctly for existing data.

Sound Transit's OTP server has dropped the OTP1 REST /plan endpoint in favor
of GraphQL, so this adds an OTP 2.x planning path alongside the existing OTP1
REST stack, targeting the same app-owned TripItinerary domain model (#1778)
so the UI/ViewModels/trip monitor need no changes.

- Vendors OTP's GraphQL schema (pinned to opentripplanner/OpenTripPlanner
  v2.9.0) and wires up Apollo Kotlin codegen for the planConnection query.
- Adds an explicit Region.usesOtp2GraphQl protocol flag (threaded through
  RegionDto/Room, migration 5->6) plus a manual "Use GraphQL (OTP 2.x)"
  toggle in Advanced Settings for the custom-OTP-URL case. Infra only: no
  bundled region is flipped on by this change.
- Otp2PlanRequestBuilder / Otp2PlanAdapters translate to/from the GraphQL
  wire format (ISO-8601 times/durations, structural vertexType inference,
  extended TripMode enum) using the same "mint at the boundary" discipline
  as the OTP1 adapter.
- Otp2Planner executes queries via a per-base-URL cached ApolloClient;
  DefaultTripPlanRepository dispatches OTP1 vs OTP2 on the resolved
  TripRequestBuilder.usesOtp2 flag.

Verified against a real OTP2 GraphQL server (Sound Transit) end-to-end via
an instrumented smoke test exercising the production repository directly;
823 unit tests pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@bmander, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d5ce6bd-e436-40fa-b7d0-bc316b37bc89

📥 Commits

Reviewing files that changed from the base of the PR and between 298c5d3 and f5062d2.

📒 Files selected for processing (2)
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/settings/AdvancedSettingsScreen.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt
📝 Walkthrough

Walkthrough

Adds OTP2 GraphQL trip planning with Apollo code generation, explicit OTP1/OTP2 selection, Room persistence, custom URL settings, request and response adapters, planner dispatch, and tests covering migration, modes, decoding, and OTP1 defaults.

Changes

OTP2 GraphQL planning

Layer / File(s) Summary
GraphQL contracts and request construction
build.gradle, onebusaway-android/build.gradle, onebusaway-android/src/main/graphql/otp2/*, onebusaway-android/src/main/java/.../Otp2PlanRequestBuilder.kt, onebusaway-android/src/test/.../Otp2PlanRequestBuilderTest.kt
Apollo 5 code generation and runtime support are configured for the OTP2 schema and planConnection; request construction maps coordinates, dates, wheelchair settings, and travel modes into generated query inputs.
Protocol selection and persistence
onebusaway-android/src/main/java/.../region/*, .../database/*, .../ui/settings/*, onebusaway-android/src/main/res/values/*, tests and fixtures
Regions, cached records, and custom URL preferences store OTP2 selection. Room version 6 adds uses_otp2_graphql, while settings expose the custom URL GraphQL override and existing defaults remain OTP1.
OTP2 response mapping and validation
onebusaway-android/src/main/java/.../api/adapters/*, onebusaway-android/src/test/java/.../Otp2PlanDecodeTest.kt
Generated OTP2 plans are converted into canonical itineraries, legs, places, steps, geometry, times, delays, and vertex types; shared adapter helpers and edge-case tests are added.
OTP2 transport and repository dispatch
onebusaway-android/src/main/java/.../app/di/*, .../ui/tripplan/*
A qualified timeout-configured client supports Apollo requests, Otp2Planner maps GraphQL errors and responses, and TripPlanRepository selects OTP2 or the existing OTP1 path from TripRequestBuilder.usesOtp2.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TripPlanRepository
  participant TripRequestBuilder
  participant Otp2Planner
  participant ApolloClient
  participant Otp2PlanAdapters
  TripPlanRepository->>TripRequestBuilder: resolve protocol and base URL
  TripPlanRepository->>Otp2Planner: plan OTP2 request
  Otp2Planner->>ApolloClient: execute planConnection
  ApolloClient-->>Otp2Planner: return GraphQL plan data
  Otp2Planner->>Otp2PlanAdapters: map response
  Otp2PlanAdapters-->>TripPlanRepository: return TripItinerary list
Loading

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding OTP 2.x GraphQL trip-planning support.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch otp2-graphql-trip-planning

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt (1)

64-68: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Old ApolloClient is not closed when the base URL changes.

ApolloClient implements Closeable (owns a coroutine scope and cached state). When a new URL replaces the cached entry, the previous client is orphaned without close(). Low impact in practice (one URL per instance per the comment), but still a leak on region switches.

♻️ Proposed fix: close the old client before replacing
     private fun apolloClientFor(baseUrl: String): ApolloClient = synchronized(this) {
         cachedClient?.takeIf { it.first == baseUrl }?.second
             ?: ApolloClient.Builder().serverUrl(baseUrl).okHttpClient(okHttpClient).build()
-                .also { cachedClient = baseUrl to it }
+                .also {
+                    cachedClient?.second?.close()
+                    cachedClient = baseUrl to it
+                }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt`
around lines 64 - 68, Update apolloClientFor so that when the requested baseUrl
differs from cachedClient, the previously cached ApolloClient is closed before
replacing cachedClient with the newly built client. Preserve reuse of the cached
client when the URLs match and keep the existing synchronized construction flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@onebusaway-android/src/main/java/org/onebusaway/android/ui/settings/AdvancedSettingsScreen.kt`:
- Around line 214-219: Update the AdvancedSettingsScreen GraphQL
SwitchPreferenceItem visibility to render only when state.customOtpApiUrl is
set, while preserving its existing title, summary, checked state, and change
handler for custom URLs.

In
`@onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt`:
- Around line 80-82: Update the ApolloException handling in the trip-planning
request flow to distinguish actual timeout failures from other ApolloException
subtypes. Keep tripplanner_error_request_timeout only for timeout exceptions,
and map non-timeout failures to the existing tripplanner_error_not_defined
fallback when no dedicated network-error string is available; preserve the
original exception as the cause.

---

Nitpick comments:
In
`@onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt`:
- Around line 64-68: Update apolloClientFor so that when the requested baseUrl
differs from cachedClient, the previously cached ApolloClient is closed before
replacing cachedClient with the newly built client. Preserve reuse of the cached
client when the URLs match and keep the existing synchronized construction flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4cd9556a-5643-4c8f-beb9-72bdd6839cc5

📥 Commits

Reviewing files that changed from the base of the PR and between 26ecf0b and d9449fb.

📒 Files selected for processing (35)
  • build.gradle
  • onebusaway-android/build.gradle
  • onebusaway-android/schemas/org.onebusaway.android.database.AppDatabase/6.json
  • onebusaway-android/src/androidTest/java/org/onebusaway/android/database/AppDatabaseMigrationTest.kt
  • onebusaway-android/src/androidTest/java/org/onebusaway/android/mock/MockRegion.java
  • onebusaway-android/src/main/graphql/otp2/Plan.graphql
  • onebusaway-android/src/main/graphql/otp2/schema.graphqls
  • onebusaway-android/src/main/java/org/onebusaway/android/api/adapters/Otp2PlanAdapters.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/api/adapters/RegionAdapters.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/api/adapters/TripPlanAdapters.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/api/contract/ObaApiModels.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/app/di/DatabaseModule.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/app/di/NetworkModule.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/app/di/Otp2HttpClient.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/database/AppDatabase.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/database/Migrations.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/database/oba/ObaEntities.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/directions/model/TripItinerary.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/directions/util/Otp2PlanRequestBuilder.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/directions/util/TripRequestBuilder.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/region/Region.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/region/RegionMapper.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/settings/AdvancedSettingsScreen.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/settings/AdvancedSettingsViewModel.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/settings/SettingsUiState.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/Otp2Planner.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/ui/tripplan/TripPlanRepository.kt
  • onebusaway-android/src/main/java/org/onebusaway/android/util/RegionUtils.java
  • onebusaway-android/src/main/res/values/donottranslate.xml
  • onebusaway-android/src/main/res/values/strings.xml
  • onebusaway-android/src/test/java/org/onebusaway/android/api/Otp2PlanDecodeTest.kt
  • onebusaway-android/src/test/java/org/onebusaway/android/api/RegionsDecodeTest.kt
  • onebusaway-android/src/test/java/org/onebusaway/android/directions/util/Otp2PlanRequestBuilderTest.kt
  • onebusaway-android/src/test/java/org/onebusaway/android/region/RegionTestFixtures.kt
  • onebusaway-android/src/test/java/org/onebusaway/android/ui/settings/SettingsUiStateTest.kt

bmander and others added 2 commits July 11, 2026 21:01
…ence

OTP2's GraphQL API replaced the old binary optimize=TRANSFERS/QUICK enum with
a continuous PlanPreferencesInput.transit.transfer.cost (seconds, added per
transfer). Converts Plan.graphql's preferences argument from a hardcoded
wheelchair-only literal to a full $preferences variable so both settings can
be built together in Otp2PlanRequestBuilder.buildPreferences().

The 1800-second value isn't a guess: cloned OpenTripPlanner at v1.5.0 and
found optimize=TRANSFERS's actual historical behavior in
RoutingResource.java (request.transferPenalty += 1800), confirmed the same
concept carries forward to OTP2's transfer.cost via
LegacyRouteRequestMapper's callWith.argument("transferPenalty", tx::withCost).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…oggle

- Otp2Planner.apolloClientFor: close the previously-cached ApolloClient
  before replacing it on a base-URL change, instead of leaking its
  coroutine scope.
- Otp2Planner.plan: only map ApolloNetworkException (actual transport
  failures/timeouts) to the "request timeout" message; other
  ApolloException subtypes (HTTP status, parse failure, GraphQL-protocol
  error) now fall back to the generic error message instead of incorrectly
  claiming a timeout.
- AdvancedSettingsScreen: hide the "Use GraphQL (OTP 2.x)" toggle unless a
  custom OTP URL is actually set, since TripRequestBuilder.usesOtp2 only
  reads it in that case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@bmander
bmander merged commit be0329b into main Jul 11, 2026
3 checks passed
@bmander
bmander deleted the otp2-graphql-trip-planning branch July 11, 2026 21:37
bmander added a commit to bmander/onebusaway-android that referenced this pull request Jul 12, 2026
…sAway#1780)

OneBusAway#1794 selected OTP2 with a `usesOtp2GraphQl` boolean layered on the single
`otpBaseUrl` — but the OBA regions directory doesn't publish that key, and a
region's GraphQL endpoint is a different host than its OTP1 REST server (Puget
Sound's REST server is otp.prod.sound.obaweb.org/otp/routers/default), so the two
URLs can't share one field. The directory carries a dedicated `otpBaseGraphqlUrl`
key instead — the mechanism for pointing a region at its OTP2 server on demand.

Replace the boolean with an `otpBaseGraphqlUrl` field end to end (RegionDto →
Room → Region): a non-blank value is both the explicit OTP2 signal and the OTP
mount base. `TripRequestBuilder.usesOtp2`/`formattedOtpBaseUrl` derive from it,
and `Otp2Planner` appends OTP2's fixed `/gtfs/v1` gtfs GraphQL mount to reach the
endpoint — mirroring the OTP1 path appending `/plan`, and matching the custom-URL
hint that already takes an `…/otp` base. Selection stays explicit, never sniffed.

Point Puget Sound at its OTP2 GraphQL server in the bundled regions seed
(otpBaseGraphqlUrl = …/prod/otp; the base serves the OTP root, base + /gtfs/v1
serves GraphQL — both verified live). Other bundled regions stay on OTP1.

Fix the OTP2 bikeshare mode encoding: `Otp2PlanRequestBuilder` sent bare
BICYCLE_RENTAL in the access/egress (Transit+Bike) and direct (Bikeshare) mode
lists, which OTP2 rejects with a BadRequestError ("BIKE_RENTAL needs to be
combined with WALK mode for the same leg"). Both lists now include WALK, verified
against the live server. Device-verified end to end (Pixel 7 Pro, Puget Sound).

Because OneBusAway#1794 is unreleased, this revises the v6 schema/migration in place
(regions.uses_otp2_graphql → regions.otp_base_graphql_url) rather than shipping a
dead column plus a churn migration; contributors on merged main clear app data.

NOTE: the live regions directory must be repointed to match before this ships —
it currently serves Puget Sound otpBaseGraphqlUrl = sound-transit-otp.ibi-
transit.com/prod/, which 404s, and would break Puget Sound trip planning as soon
as a device refreshes regions over the bundled seed.
bmander added a commit that referenced this pull request Jul 12, 2026
#1799)

#1794 selected OTP2 with a `usesOtp2GraphQl` boolean layered on the single
`otpBaseUrl` — but the OBA regions directory doesn't publish that key, and a
region's GraphQL endpoint is a different host than its OTP1 REST server (Puget
Sound's REST server is otp.prod.sound.obaweb.org/otp/routers/default), so the two
URLs can't share one field. The directory carries a dedicated `otpBaseGraphqlUrl`
key instead — the mechanism for pointing a region at its OTP2 server on demand.

Replace the boolean with an `otpBaseGraphqlUrl` field end to end (RegionDto →
Room → Region): a non-blank value is both the explicit OTP2 signal and the OTP
mount base. `TripRequestBuilder.usesOtp2`/`formattedOtpBaseUrl` derive from it,
and `Otp2Planner` appends OTP2's fixed `/gtfs/v1` gtfs GraphQL mount to reach the
endpoint — mirroring the OTP1 path appending `/plan`, and matching the custom-URL
hint that already takes an `…/otp` base. Selection stays explicit, never sniffed.

Point Puget Sound at its OTP2 GraphQL server in the bundled regions seed
(otpBaseGraphqlUrl = …/prod/otp; the base serves the OTP root, base + /gtfs/v1
serves GraphQL — both verified live). Other bundled regions stay on OTP1.

Fix the OTP2 bikeshare mode encoding: `Otp2PlanRequestBuilder` sent bare
BICYCLE_RENTAL in the access/egress (Transit+Bike) and direct (Bikeshare) mode
lists, which OTP2 rejects with a BadRequestError ("BIKE_RENTAL needs to be
combined with WALK mode for the same leg"). Both lists now include WALK, verified
against the live server. Device-verified end to end (Pixel 7 Pro, Puget Sound).

Because #1794 is unreleased, this revises the v6 schema/migration in place
(regions.uses_otp2_graphql → regions.otp_base_graphql_url) rather than shipping a
dead column plus a churn migration; contributors on merged main clear app data.

NOTE: the live regions directory must be repointed to match before this ships —
it currently serves Puget Sound otpBaseGraphqlUrl = sound-transit-otp.ibi-
transit.com/prod/, which 404s, and would break Puget Sound trip planning as soon
as a device refreshes regions over the bundled seed.
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