Skip to content

Mobile login fix: bake API URL into builds, allow Capacitor origins, …#27

Merged
HiLleywyn merged 1 commit into
mainfrom
claude/fix-ui-ux-multidevice-4GV0U
May 9, 2026
Merged

Mobile login fix: bake API URL into builds, allow Capacitor origins, …#27
HiLleywyn merged 1 commit into
mainfrom
claude/fix-ui-ux-multidevice-4GV0U

Conversation

@HiLleywyn
Copy link
Copy Markdown
Owner

…surface bad responses

The Android (and iOS) APK was crashing on Sign in with "Cannot read properties of null (reading 'challenge')" because:

  1. The web bundle inside the Capacitor shell defaulted apiFetch to /api, but Capacitor serves the bundle from https://localhost on Android (capacitor://localhost on iOS). The fetch hit the shell's own host, which returned the index.html via the SPA fallback, apiFetch silently returned null, and start.challenge blew up.
  2. Even if the right host had been reached, the API's CORS layer only trusted the configured allowed_origins, so a Capacitor origin was rejected.
  3. apiFetch swallowed the JSON parse failure (returning null on a 2xx with non-JSON body), which masked the real cause.

Fixes:

  • The mobile workflows (android.yml, ios.yml) now resolve VITE_API_BASE and VITE_GATEWAY_URL from repository variables, falling back to apps/mobile/.env.production. Both values are exported to the env of the web build step so Vite bakes them into the bundle. Without this, every mobile login attempt 404s.
  • tempest-api always trusts https://localhost, http://localhost, capacitor://localhost, ionic://localhost, and tauri://localhost in addition to the configured web origin, so the mobile shells can authenticate without per-deploy CORS surgery.
  • apiFetch now throws a bad_response TempestError with a snippet of the body when a 2xx returns non-JSON or an empty body, instead of returning null and crashing the caller five lines later.

apps/mobile/.env.production seeds the user's existing Railway URLs so fresh APK builds work out of the box; override via repo vars or by editing the file before tagging a release.

…surface bad responses

The Android (and iOS) APK was crashing on Sign in with "Cannot read
properties of null (reading 'challenge')" because:

1. The web bundle inside the Capacitor shell defaulted apiFetch to
   `/api`, but Capacitor serves the bundle from https://localhost on
   Android (capacitor://localhost on iOS). The fetch hit the shell's
   own host, which returned the index.html via the SPA fallback,
   apiFetch silently returned null, and start.challenge blew up.
2. Even if the right host had been reached, the API's CORS layer
   only trusted the configured allowed_origins, so a Capacitor
   origin was rejected.
3. apiFetch swallowed the JSON parse failure (returning null on a
   2xx with non-JSON body), which masked the real cause.

Fixes:

* The mobile workflows (android.yml, ios.yml) now resolve VITE_API_BASE
  and VITE_GATEWAY_URL from repository variables, falling back to
  apps/mobile/.env.production. Both values are exported to the env of
  the web build step so Vite bakes them into the bundle. Without
  this, every mobile login attempt 404s.
* tempest-api always trusts https://localhost, http://localhost,
  capacitor://localhost, ionic://localhost, and tauri://localhost in
  addition to the configured web origin, so the mobile shells can
  authenticate without per-deploy CORS surgery.
* apiFetch now throws a `bad_response` TempestError with a snippet of
  the body when a 2xx returns non-JSON or an empty body, instead of
  returning null and crashing the caller five lines later.

apps/mobile/.env.production seeds the user's existing Railway URLs so
fresh APK builds work out of the box; override via repo vars or by
editing the file before tagging a release.
@HiLleywyn HiLleywyn merged commit 29d4774 into main May 9, 2026
4 of 6 checks passed
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.

2 participants