Skip to content

fix(mobile): Pylon Connect reaches mobile builds - #37

Merged
rynfar merged 5 commits into
pylonfrom
feat/mobile-connect-config
Aug 15, 2026
Merged

rynfar merged 5 commits into
pylonfrom
feat/mobile-connect-config

Conversation

@rynfar

@rynfar rynfar commented Aug 15, 2026 •

Copy link
Copy Markdown
Collaborator

Pylon Connect is fully implemented on mobile — CloudAuthProvider, linkEnvironment, the onboarding sheet, and a "Pylon Connect" section in Connections — but no mobile build has ever received the public config it needs, so every one of those surfaces was omitted at runtime.

The problem

relay_public_config in release.yml reads the Clerk publishable key, JWT template, and relay domain from the GitHub production environment and feeds them to the desktop, CLI, and hosted-web jobs. The two mobile EAS workflows are not part of that workflow. They get their config from eas env:pull, which reads an expo.dev environment store that nothing ever populated — all three EAS environments were empty.

The failure is invisible. hasCloudPublicConfig() gates every Connect surface, and each one returns null when config is absent: SettingsRouteScreen falls back to the local settings screen, SettingsAuthRouteScreen renders nothing, CloudEnvironmentRows drops to connected-only. No error, no empty state — the app reads as though it never shipped the feature.

The fix

The GitHub production environment stays the single source of truth. mobile-eas-production.yml declares that environment and mirrors the values into the EAS production, preview, and development environments before building. The mirror is necessary rather than incidental: EAS build servers read their own store, and a repo-root .env is gitignored so it never reaches them.

Both mobile workflows then run scripts/verify-mobile-connect-config.ts, which resolves the public app manifest and fails the job when clerk.publishableKey, clerk.jwtTemplate, or relay.url is missing. Partial configuration is treated as none, matching relay_public_config.

.env.example now carries Pylon's own public identifiers. That was the recorded revisit condition for upstream E21, which was skipped because it pointed fresh clones at T3's infrastructure; Pylon owns its Clerk application and relay now.

Verification

  • vp test run scripts/lib/public-config.test.ts apps/mobile/src/features/cloud/publicConfig.test.ts — 11 passed
  • vp run -F @t3tools/scripts typecheck — clean
  • Resolved the preview manifest locally: hasCloudPublicConfig => true
  • Guard exercised both ways: exit 1 with config absent, exit 0 with it present
  • Both workflow files parse; production environment has no protection rules, so declaring it adds no approval gate

No UI changed, so there are no before/after images — the same components render, now with the config they were always waiting for.

Note: both mobile workflows still skip entirely until an EXPO_TOKEN secret exists on the repository.

Model: Claude Opus 5. Harness: Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 15, 2026
@github-actions

github-actions Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for 5f899cf.

This comment will update automatically after the next completed run.

@rynfar rynfar added 🚀 Mobile Continuous Deployment Build and publish this PR to EAS preview and removed 🚀 Mobile Continuous Deployment Build and publish this PR to EAS preview labels Aug 15, 2026
rynfar added 5 commits August 15, 2026 12:42
Mobile was the only surface whose build never received Pylon Connect's
public config. `relay_public_config` in release.yml feeds the Clerk
publishable key, JWT template, and relay URL to desktop, the CLI, and
hosted web, but the two mobile EAS workflows are not part of that
workflow and read `eas env:pull` instead — a separate expo.dev store
that nothing populated. Every Connect surface on mobile is gated on
`hasCloudPublicConfig()`, which omits the UI entirely rather than
disabling it, so the app looked like it had simply never shipped the
feature.

The GitHub `production` environment stays the source of truth.
mobile-eas-production.yml now declares that environment and mirrors the
values into the EAS production, preview, and development environments
before building, because EAS build servers read their own store and a
gitignored repo-root .env never reaches them. Both mobile workflows then
verify the resolved app manifest actually carries the config and fail
loudly if it does not, so a Connect-dark build cannot ship silently
again.

.env.example carries Pylon's own public identifiers now that Pylon owns
its Clerk application and relay, which was the recorded revisit
condition for the skipped upstream E21.
The settings account row read "T3 Account" and the Connect onboarding
sheet asked users to sign in to their "T3 account". Both surfaces only
became reachable once mobile started receiving Connect's public config,
so the stale copy had never been visible. Web already says "Pylon
Connect" throughout.

Compatibility identifiers keep their T3 names: the native module names,
T3CODE_* environment variables, and the T3Mark widget asset are contract
surfaces, not product copy.
Clerk's native AuthView derives its redirect from the iOS bundle
identifier, so every bundle variant needs its own allowlist entry. The
guidance said only that a future browser OAuth flow might need one, which
left the native view's requirement undocumented until sign-in failed.
Verified against the production instance: the native AuthView validates
against Clerk's Redirect URLs resource, while `allowed_origins` covers
Electron and browser extensions. The previous revision folded mobile into
the desktop allowlist, which would have sent a reader to patch a field
that has no effect on native sign-in.
Every eas command in CI failed with "EAS project not configured".
app.config.ts builds `extra.eas.projectId` from PYLON_EAS_PROJECT_ID,
which lives only in a gitignored .env.local, so the CI checkout resolved
it to empty and eas-cli had no project to act on.

Same shape as the Connect config bug this branch already fixes: state
that exists only on a developer's disk is invisible to CI. Both values
are public identifiers — the project ID ships in every app's update URL
— so they are repository variables rather than secrets.

Without the project ID, `updates.url` also resolved to null, which would
have disabled over-the-air updates in any CI-built app.
@rynfar
rynfar force-pushed the feat/mobile-connect-config branch from 1801116 to 5f899cf Compare August 15, 2026 18:42
@rynfar
rynfar merged commit a682347 into pylon Aug 15, 2026
11 checks passed
@rynfar
rynfar deleted the feat/mobile-connect-config branch August 15, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant