Skip to content

fix(mobile): parse pasted pairing links - #5596

Open
DominicVonk wants to merge 7 commits into
pingdotgg:mainfrom
DominicVonk:codex/mobile-pairing-link-paste
Open

DominicVonk wants to merge 7 commits into
pingdotgg:mainfrom
DominicVonk:codex/mobile-pairing-link-paste

Conversation

@DominicVonk

@DominicVonk DominicVonk commented Aug 7, 2026 •

Copy link
Copy Markdown

Mobile treated the Host and Pairing Code fields independently, so pasting a complete pairing URL could leave the token embedded in the host field. Schemeless local URLs also behaved differently from desktop.

This change gives mobile the same paste behavior as desktop:

  • parses full pairing URLs from the Host field;
  • extracts tokens from URL fragments and query strings;
  • supports hosted pairing links;
  • accepts schemeless hostnames and local IPv4 addresses;
  • defaults schemeless IP literals to HTTP and hostnames to HTTPS;
  • preserves separately entered host/code values;
  • keeps QR and deep-link payload handling on the same parser path.

Related independent PRs

These PRs all target main and can be merged in any order:

Verification

  • vp test run apps/mobile/src/features/connection/pairing.test.ts
    • 1 file passed
    • 14 tests passed
  • vp run --filter @t3tools/mobile typecheck
    • passed
  • targeted vp lint for the three changed files
    • passed
  • fallow audit --base upstream/main
    • passed the new-change gate; inherited repository findings were excluded

UI verification after merging main (2026-10-01)

Verified merge commit f92dc1762496a852aec21dcee03098a1b9263d04 against main at 5cc99e1c23980d7995a13c47f969b47cb68ed1be. The conflicts were resolved by keeping main’s current form components, connection cleanup/development automation, and Effect error API, then applying this PR’s parsing on blur and submit. The diff against main still contains only the original three files.

Captured in T3 Code Dev on an iOS 27 simulator with a matching rebuilt native client and a disposable local backend. Before uses main’s three affected files; after and recording use the pushed merge commit’s files.

  1. Paste http://127.0.0.1:15596/#token=DUMMYTOKEN01 into Host using the native Paste menu.
  2. Tap Pairing Code to leave Host. Before: the full URL remains in Host and Pairing Code stays empty. After: Host becomes http://127.0.0.1:15596 and Pairing Code becomes DUMMYTOKEN01.
  3. Dismiss the keyboard and press Add Environment. The local server rejects the dummy credential with “The environment credential is invalid.” The fields retain the extracted values and the form remains usable.
Before: main After: merged PR
Before After

36-second recording: paste → leave Host → Add Environment → dummy-token rejection.

paste-blur-connect.mp4

Result screenshot · GitHub-hosted evidence

Re-ran the focused pairing tests (14 passed), mobile typecheck (passed), and targeted lint (zero errors; the same four existing warnings also reproduced on main). The native-client ensure/build passed. No evidence files were committed. Android and successful authentication were not exercised; the requested connection attempt deliberately uses an invalid dummy token.

Merge resolution, UI verification, and evidence update: GPT-6.1-Sol via the Codex harness in T3 Code.

Built and reviewed with GPT-5 Codex via Codex CLI.

Fork validation PR


Note

Low Risk
Connection-form parsing and URL normalization only; behavior is covered by unit tests with no auth or data-model changes.

Overview
Aligns mobile Add Environment pairing input with desktop by parsing full pairing URLs pasted into the Host field instead of treating host and code independently.

pairing.ts adds normalizePairingUrlInput (schemeless IPs → HTTP, hostnames → HTTPS, // → HTTPS) and parsePairingFields, which splits a pasted URL’s token from the host when present. buildPairingUrl and parsePairingUrl use that normalization for direct, schemeless, protocol-relative, and hosted pairing links.

ConnectionsNewRouteScreen runs field normalization on host blur and before connect so submit builds the URL from cleaned host/code values.

Tests in pairing.test.ts cover the new parsing and URL-building cases.

Reviewed by Cursor Bugbot for commit 9bdff53. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix pairing link parsing to extract embedded tokens from the host field on mobile

  • Adds parsePairingFields in pairing.ts to detect when a full pairing URL is pasted into the host field and extract the token into the code field.
  • Adds normalizePairingUrlInput to infer schemes for schemeless and protocol-relative inputs (HTTPS for hostnames, HTTP for IPs).
  • Updates parsePairingUrl and buildPairingUrl to use the new normalization, so protocol-relative and schemeless hosts are handled correctly.
  • In ConnectionsNewRouteScreen, calls parsePairingFields on blur and at submit so the host and code fields are normalized before the pairing URL is built.

Macroscope summarized 9bdff53.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 9396770e-648f-4573-9d06-6e1dabb89b59

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc99e1 and f92dc17.

📒 Files selected for processing (3)
  • apps/mobile/src/features/connection/ConnectionsNewRouteScreen.tsx
  • apps/mobile/src/features/connection/pairing.test.ts
  • apps/mobile/src/features/connection/pairing.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Pairing URL construction and parsing now normalize inputs that lack a scheme. The connection form parses host and pairing-code fields on blur and before submission, then builds the pairing URL from the parsed values.

Changes

Pairing input handling

Layer / File(s) Summary
Normalize and parse pairing URLs
apps/mobile/src/features/connection/pairing.ts, apps/mobile/src/features/connection/pairing.test.ts
Pairing URL construction and parsing normalize protocol-relative inputs to HTTPS, preserve inputs with a scheme, and add HTTP for IP-literal hosts or HTTPS otherwise. parsePairingFields returns parsed fields when parsing finds a code, and otherwise preserves the supplied fields. Tests cover these cases.
Normalize connection form fields
apps/mobile/src/features/connection/ConnectionsNewRouteScreen.tsx
The form parses its host and code fields on blur and before submission. Submission builds the pairing URL from the parsed values.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to f92dc

The pairing input normalization is mergeable after normal checks. Supported tokens are preserved, and blur and submission consistently use parsed fields.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to f92dc

A pasted hosted pairing link containing a schemeless IP backend can now select unencrypted HTTP where the previous submission path selected HTTPS. This can expose pairing and session credentials on untrusted networks. Explicitly specified schemes and the existing pairing checks remain intact.

Retained concerns

  • Medium · security · inferred: Normalizing a pasted hosted link with a schemeless IP backend changes a previously HTTPS-resolved target into HTTP. The bootstrap credential and returned bearer session then use that unencrypted target, and registration carries forward HTTP/WS endpoints. This newly affects manual pasted-link submission; the corresponding QR behavior and direct manual IP default predate this PR.
Security review details

Security Blast Radius

  • inferred — The identified exposure concerns one submitted backend registration: its bootstrap credential, returned bearer session, and resulting connection endpoints. Exploitation requires network observation or interference where HTTP is permitted; no additional backend privilege is needed to observe plaintext traffic. Broader tenant or infrastructure authority expansion was not established.

Security Findings and Attack Paths

  • inferred — For example, a pasted hosted URL whose host parameter is 192.0.2.10:3773 and whose fragment carries a valid token previously reached shared resolution unchanged and selected HTTPS. Head extraction and rebuilding select HTTP instead. After descriptor compatibility succeeds, the token exchange sends the credential as subject_token to /oauth/token. Where that HTTP request succeeds, an on-path observer can capture credentials; placing the original token in a URL fragment does not protect this subsequent exchange.

Trust Boundaries and Controls

  • observed — Shared resolution still requires a token and limits backend protocols to HTTP, HTTPS, WS, and WSS; it does not require encrypted transport. Explicit HTTPS links retain their scheme. Base manual IP building and QR hosted-link extraction already supported HTTP, limiting the introduced concern to the newly normalized pasted-hosted-link path rather than all pairing traffic.

Resilience and Maintainability Implications

  • observed — Registry registration delegates durable writes to ConnectionRegistrationStore before updating its in-memory target map and installing the entry. The inspected interface does not establish transactional crash recovery or cleanup of a bearer session issued before a persistence failure; these guarantees remain unresolved, not introduced findings.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description thoroughly explains the problem, implementation, verification steps, test results, and UI evidence. It does not provide the required scope-and-approval information or explain why this … Add a Scope and approval section with a triaged issue or maintainer approval comment. If no prior issue or discussion exists, explain why this focused, obvious bug fix qualifies for the exemption. Organize the existing problem and change de…
✅ Passed checks (3 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.
Title check ✅ Passed The title clearly and concisely describes the main change: parsing pasted pairing links on mobile.
Full details: Description check

Explanation

The description thoroughly explains the problem, implementation, verification steps, test results, and UI evidence. It does not provide the required scope-and-approval information or explain why this focused fix qualifies for an exemption.

Resolution

Add a Scope and approval section with a triaged issue or maintainer approval comment. If no prior issue or discussion exists, explain why this focused, obvious bug fix qualifies for the exemption. Organize the existing problem and change details under the template headings if needed.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 7, 2026
@DominicVonk DominicVonk changed the title fix(mobile): parse pasted pairing links [4/5] fix(mobile): parse pasted pairing links Aug 7, 2026
Comment thread packages/client-runtime/src/connection/registry.ts Outdated
Comment thread packages/client-runtime/src/connection/registry.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Effect service conventions review: one finding. The new ConnectionActivationStore implementations map their failures onto unrelated ConnectionPersistenceError operation labels (register-connection for activation writes, list-targets for listDisabled), so the structured operation context no longer identifies the failing operation. Everything else in the diff (namespace imports, Context.Service tag placement in platform/persistence.ts, the new setEnabled registry operation and atom command, and the test-only service instances in the harnesses) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/client-runtime/src/platform/persistence.ts Outdated
Comment thread apps/mobile/src/connection/storage.ts Outdated
Comment thread apps/web/src/connection/storage.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One convention issue found: in apps/mobile/src/connection/storage.ts the new activation-specific ConnectionPersistenceError operation literals are swapped with the existing target/registration ones, so the structured operation attribute no longer identifies the operation that actually failed. The web store (apps/web/src/connection/storage.ts) maps these correctly and can be used as the reference.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/mobile/src/connection/storage.ts Outdated
Comment thread apps/mobile/src/connection/storage.ts Outdated
Comment thread packages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch from f7d7de8 to efe9f1a Compare August 7, 2026 10:33
Comment thread apps/mobile/src/features/connection/ConnectionsNewRouteScreen.tsx
Comment thread packages/client-runtime/src/connection/registry.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One convention finding on the new shared connectivity helper. Everything else (activation store definition, platform implementations, error operation literals, new registry command) follows the service conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/client-runtime/src/connection/connectivity.ts Outdated
@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch from efe9f1a to c0ef226 Compare August 7, 2026 10:43
Comment thread packages/client-runtime/src/connection/connectivity.ts Outdated
@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch 3 times, most recently from 3d5c7e5 to a7c44d9 Compare August 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment thread apps/mobile/src/state/use-remote-environment-registry.ts Outdated
Comment thread packages/client-runtime/src/relay/discovery.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 055f151

Small, self-contained bug fix adding URL parsing for pasted pairing links on mobile. Changes include helper functions and comprehensive unit tests. The open review comments reference either unrelated files or scenarios covered by tests.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch from a7c44d9 to 397415a Compare August 7, 2026 11:27
@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch 3 times, most recently from ae9a81e to 8cf47b4 Compare August 7, 2026 16:17
Comment thread packages/client-runtime/src/connection/registry.ts Outdated
Comment thread packages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonk force-pushed the codex/mobile-pairing-link-paste branch from 8cf47b4 to d96ef7a Compare August 7, 2026 17:19
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Aug 7, 2026
@DominicVonk DominicVonk changed the title [4/5] fix(mobile): parse pasted pairing links [3/3] fix(mobile): parse pasted pairing links Aug 7, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 7, 2026
@DominicVonk DominicVonk changed the title [3/3] fix(mobile): parse pasted pairing links fix(mobile): parse pasted pairing links Aug 7, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 4 total unresolved issues (including 3 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 59e70a4. Configure here.

Comment thread apps/mobile/src/features/connection/pairing.ts Outdated
@macroscopeapp
macroscopeapp Bot dismissed their stale review August 10, 2026 15:59

Dismissing prior approval to re-evaluate 055f151

Copy link
Copy Markdown
Member

Note

This comment is posted by Julius' dot

Closing for missing UI verification. The parser tests are useful, but this also rewrites the visible Host and Pairing Code fields on blur and submit. Please add before/after screenshots and a short recording of pasting a complete link, leaving Host, and connecting with a dummy token, then request reconsideration.

@DominicVonk

Copy link
Copy Markdown
Author

@juliusmarminge Added the requested UI verification to the PR description for the unchanged head commit 9bdff53.

  • Before / after: with the same complete dummy-token link pasted into Host, leaving Host now extracts the token into Pairing Code. The before capture has this PR's patch reversed.
  • 37-second recording: native Paste menu → leave Host → extracted fields → Add Environment → expected “The environment credential is invalid.” response from a disposable local backend.

Verified in T3 Code Dev on an iOS 27 simulator. Pairing tests (14), mobile typecheck, and targeted lint pass. Only a dummy token appears in the evidence; no successful authentication is claimed. Android was not exercised.

Could you reconsider reopening this PR now that the missing evidence is supplied?

@juliusmarminge juliusmarminge reopened this Oct 1, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Reopened. Please resolve conflcits

@DominicVonk

Copy link
Copy Markdown
Author

@juliusmarminge Merged current main and resolved the two conflicts in f92dc17624. GitHub now reports the PR as mergeable. The resolution preserves main’s refactored form, connection cleanup/development automation, and updated Effect API; the PR remains a three-file pairing fix.

Rebuilt the matching iOS native client and replaced the PR’s UI evidence with fresh before/after screenshots and a 36-second recording for this merge commit. The recording shows native paste → leave Host → extracted token → Add Environment → expected invalid-dummy-credential error.

All 14 pairing tests and mobile typecheck pass. Targeted lint has zero errors and the same four warnings as main. Android was not exercised.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants