Skip to content

fix(app): avoid native rebuild for app-entry QR links - #3237

Merged
innolope-dev merged 1 commit into
mainfrom
innolope/app-link-gateway-no-native
Sep 17, 2026
Merged

innolope-dev merged 1 commit into
mainfrom
innolope/app-link-gateway-no-native

Conversation

@innolope-dev

@innolope-dev innolope-dev commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • keep /app as the web smart-store route, but remove its Android and iOS native claims introduced in feat(landing): one download action across app entry points (TASK-21788) #3027
  • generate download QRs through https://peanut.me/home?app_entry=1, using the /home association already shipped in v1.6
  • redirect browser scans to /app while preserving deferred-link payloads
  • consume installed-app scans directly, apply the payload, and navigate to its sanitized destination or /home
  • pin /app exclusion and both gateway branches in tests and document the release boundary

Why this avoids a native rebuild

/home already belongs to the released Android intent filter and every iOS AASA appID. The browser and installed-app behavior now split in JavaScript, so /app no longer needs to expand the binary native surface.

Both repository OTA checks match the original v1.6.0 fingerprint (48586271a56340ed):

  • Android: native surface matches original v1.6.0
  • iOS: native surface matches original v1.6.0

Follow-up to #3027.

Validation

  • pnpm exec jest --runInBand src/components/Migration/__tests__/DownloadQR.test.tsx src/__tests__/proxy.test.ts src/hooks/__tests__/useNativeAppLinks.test.tsx src/utils/__tests__/app-links.test.ts src/utils/__tests__/native-routes.test.ts (240 passed)
  • pnpm typecheck
  • focused ESLint and Prettier checks
  • pnpm build
  • node scripts/check-native-ota-surface.mjs v1.6.0 --platform android --ref HEAD
  • node scripts/check-native-ota-surface.mjs v1.6.0 --platform ios --ref HEAD

Scope

This PR does not merge, deploy, or publish an OTA. Existing /app links remain valid smart-store links; newly generated QR links use the native-compatible gateway.

Summary by CodeRabbit

  • New Features

    • QR download links now open through /home and route web visitors to the app download page.
    • Installed-app launches can apply deferred QR handoff details and navigate directly to the intended destination.
    • Existing direct and legacy app links remain supported.
  • Bug Fixes

    • Prevented app-download pages from being treated as native deep-link destinations, avoiding incorrect app launches.

@vercel

vercel Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
peanut-wallet Ready Ready Preview Sep 17, 2026 1:48pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: f5dc3c81-cab0-45bf-b8d8-47eb252dd91a

📥 Commits

Reviewing files that changed from the base of the PR and between b1884bc and f03799e.

⛔ Files ignored due to path filters (1)
  • android/app/src/main/AndroidManifest.xml is excluded by !android/**
📒 Files selected for processing (12)
  • docs/NATIVE-RELEASE.md
  • public/.well-known/apple-app-site-association
  • src/__tests__/proxy.test.ts
  • src/components/Migration/DownloadQR.tsx
  • src/components/Migration/__tests__/DownloadQR.test.tsx
  • src/constants/migration.consts.ts
  • src/hooks/__tests__/useNativeAppLinks.test.tsx
  • src/hooks/useNativeAppLinks.ts
  • src/proxy.ts
  • src/utils/__tests__/app-links.test.ts
  • src/utils/__tests__/native-routes.test.ts
  • src/utils/native-routes.ts
💤 Files with no reviewable changes (1)
  • public/.well-known/apple-app-site-association

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

QR codes now target /home?app_entry=1. The web proxy redirects browser scans to /app. Installed apps process deferred payloads through useNativeAppLinks. Native declarations exclude /app.

Changes

QR app-entry routing

Layer / File(s) Summary
QR URL contract
src/constants/migration.consts.ts, src/components/Migration/DownloadQR.tsx, src/components/Migration/__tests__/DownloadQR.test.tsx
The QR URL uses the app_entry marker on /home and preserves optional handoff parameters.
Web and native routing
src/proxy.ts, src/hooks/useNativeAppLinks.ts, src/__tests__/proxy.test.ts, src/hooks/__tests__/useNativeAppLinks.test.tsx
The proxy redirects marked browser requests to /app. Native handling applies deferred destinations or navigates to /home. Tests cover both paths.
Native association and compatibility
public/.well-known/apple-app-site-association, src/utils/__tests__/app-links.test.ts, src/utils/native-routes.ts, src/utils/__tests__/native-routes.test.ts, docs/NATIVE-RELEASE.md
iOS and Android declarations exclude /app. Existing direct and legacy /app mappings remain documented and unchanged.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant QRCodeWrapper
  participant Browser
  participant WebProxy
  participant InstalledApp
  participant useNativeAppLinks
  participant deferred-link
  QRCodeWrapper->>Browser: Open /home?app_entry=1
  alt Browser scan
    Browser->>WebProxy: Request app-entry URL
    WebProxy-->>Browser: 307 redirect to /app
  else Installed app scan
    InstalledApp->>useNativeAppLinks: Handle app-entry URL
    useNativeAppLinks->>deferred-link: Parse and apply deferred payload
    deferred-link-->>useNativeAppLinks: Destination or no destination
    useNativeAppLinks-->>InstalledApp: Navigate to destination or /home
  end
Loading

Merge Risk: ⚪ Minimal · up to f0379

The QR routing change preserves browser and installed-app flows without an identified merge-blocking issue.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 10 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: routing app-entry QR links to avoid a native rebuild.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 10 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@github-actions

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 9003.57 → 9004.69 (+1.12)
Findings: 0 net (+24 new, -24 resolved)

🆕 New findings (24)

  • critical complexity — src/hooks/useNativeAppLinks.ts — CC 75, MI 60.74, SLOC 297
  • high complexity — src/proxy.ts — CC 39, MI 55.66, SLOC 131
  • medium high-mdd — src/hooks/useNativeAppLinks.ts:50 — useNativeAppLinks: MDD 68.8 (uses across many lines from declarations)
  • medium high-mdd — src/hooks/useNativeAppLinks.ts:53 — : MDD 63.6 (uses across many lines from declarations)
  • medium high-dlt — src/hooks/useNativeAppLinks.ts:50 — useNativeAppLinks: DLT 61 (calls 61 distinct functions — high context load)
  • medium high-dlt — src/hooks/useNativeAppLinks.ts:53 — : DLT 59 (calls 59 distinct functions — high context load)
  • medium high-mdd — src/utils/native-routes.ts:113 — mapDeepLinkPath: MDD 54.5 (uses across many lines from declarations)
  • medium high-dlt — src/hooks/useNativeAppLinks.ts:176 — init: DLT 31 (calls 31 distinct functions — high context load)
  • medium high-mdd — src/proxy.ts:12 — proxy: MDD 30.4 (uses across many lines from declarations)
  • medium high-mdd — src/hooks/useNativeAppLinks.ts:96 — openDeepLink: MDD 23.2 (uses across many lines from declarations)
  • medium high-mdd — src/hooks/useNativeAppLinks.ts:176 — init: MDD 20.6 (uses across many lines from declarations)
  • medium method-complexity — src/proxy.ts:12 — proxy CC 20 SLOC 72
  • medium method-complexity — src/utils/native-routes.ts:431 — rewriteMethodPath CC 20 SLOC 34
  • medium react-effect-derives-state — src/components/Migration/DownloadQR.tsx:21 — small useEffect that only sets state from deps
  • medium complexity — src/constants/migration.consts.ts — CC 1, MI 51.45, SLOC 33
  • low high-dlt — src/hooks/useNativeAppLinks.ts:96 — openDeepLink: DLT 21 (calls 21 distinct functions — high context load)
  • low high-dlt — src/proxy.ts:12 — proxy: DLT 18 (calls 18 distinct functions — high context load)
  • low high-mdd — src/utils/native-routes.ts:431 — rewriteMethodPath: MDD 13.2 (uses across many lines from declarations)
  • low high-mdd — src/hooks/useNativeAppLinks.ts:250 — : MDD 11.0 (uses across many lines from declarations)
  • low high-mdd — src/components/Migration/DownloadQR.tsx:18 — DownloadQR: MDD 10.0 (uses across many lines from declarations)

…and 4 more.

✅ Resolved (24)

  • src/hooks/useNativeAppLinks.ts — CC 72, MI 61.19, SLOC 288
  • src/proxy.ts — CC 37, MI 56.53, SLOC 123
  • src/hooks/useNativeAppLinks.ts:48 — useNativeAppLinks: MDD 68.9 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:51 — : MDD 63.8 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:48 — useNativeAppLinks: DLT 59 (calls 59 distinct functions — high context load)
  • src/hooks/useNativeAppLinks.ts:51 — : DLT 57 (calls 57 distinct functions — high context load)
  • src/utils/native-routes.ts:113 — mapDeepLinkPath: MDD 53.7 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:163 — init: DLT 31 (calls 31 distinct functions — high context load)
  • src/proxy.ts:11 — proxy: MDD 26.2 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:94 — openDeepLink: MDD 20.6 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:163 — init: MDD 20.6 (uses across many lines from declarations)
  • src/utils/native-routes.ts:430 — rewriteMethodPath CC 20 SLOC 34
  • src/proxy.ts:11 — proxy CC 18 SLOC 64
  • src/components/Migration/DownloadQR.tsx:17 — small useEffect that only sets state from deps
  • src/constants/migration.consts.ts — CC 1, MI 51.81, SLOC 32
  • src/hooks/useNativeAppLinks.ts:94 — openDeepLink: DLT 19 (calls 19 distinct functions — high context load)
  • src/proxy.ts:11 — proxy: DLT 17 (calls 17 distinct functions — high context load)
  • src/utils/native-routes.ts:430 — rewriteMethodPath: MDD 13.2 (uses across many lines from declarations)
  • src/hooks/useNativeAppLinks.ts:237 — : MDD 11.0 (uses across many lines from declarations)
  • src/components/Migration/DownloadQR.tsx:14 — DownloadQR: MDD 10.0 (uses across many lines from declarations)

…and 4 more.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • ✅ unit: 7088 ran, 0 failed, 0 skipped, 1.9m

📊 Coverage (unit)

metric %
statements 77.1%
branches 63.6%
functions 71.1%
lines 78.1%
⏱ 10 slowest test cases
time test
🐢 9.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Network failure keeps loading while retries remain, then shows the generic error
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_USER_NOT_PROVISIONED fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › User KYC not approved fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_SOURCE_OVER_MONTHLY_CAP fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › routes the KYC rejection on its wire code, and does not retry it
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › a refused idempotency key tells the user to scan again, not to contact support
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_RECENT_REFUND fails fast with copy that names the real cause
4.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › MANTECA_MERCHANT_VOLUME_NEAR_CAP fails fast with copy that names the real cause
3.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Going offline blames the connection, and reconnecting clears it for the recovered scan
3.0s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Scan that recovers on the retry lands on the payment screen, not an error
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@chip-peanut-bot chip-peanut-bot 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.

Chip review — no blocking findings — this is not an approval

No actionable defects found in the exact-head diff.

Checked clean

  • Verified the detached worktree HEAD, trusted author, main base ref, and exact base/head SHAs against the supplied inputs.
  • Reviewed the browser /home app-entry redirect, marker removal, native deferred-payload application, destination sanitization, and cold/warm App Link routing.
  • Verified Android manifest and all iOS AASA entries keep /home claimed and /app excluded with cross-platform parity tests in the diff.
  • Ran both dependency-free native OTA surface checks against v1.6.0; Android and iOS match fingerprint 48586271a56340ed.
  • Checked exact-head CI: unit, native-export, typecheck, ESLint, formatting, preview deployment, and JavaScript/TypeScript analysis passed; ds-shots was still in progress.
  • The focused Jest command could not run locally because this detached worktree has no installed Jest dependency; exact-head CI's unit job subsequently passed.
  • Ran git diff --check with no whitespace errors and inspected relevant history, existing deferred-link behavior, and route/export drift guards.

Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.

Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.

Exact head: f03799e96fd0 · Context: repo · Took 9m

@github-actions

Copy link
Copy Markdown
Contributor

🖼 Visual diff — 13 screens moved

18 of 74 shots changed · 56 identical · baseline b1884bc → head f03799e

worst % screen widths
13.70% avatar-picker 320, 430
0.07% send 320, 430
0.07% add-money 320
0.07% badges 320
0.07% empty-home 320, 430
0.07% home-avatar 320, 430
0.07% limits 320
0.07% request 320
0.03% add-money-crypto 430
0.03% empty-accounts 320, 430
0.03% identity-verification 430
0.03% profile-edit 430
0.01% kyc-action-required 320

job summary · before/after/diff images — artifact

Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data.

@innolope-dev
innolope-dev merged commit 57859ba into main Sep 17, 2026
34 of 36 checks passed

This branch was successfully deployed

2 active deployments
Preview — f03799e9 Deployed Sep 17, 2026 by vercel[bot]
content-publish — f03799e9 Deployed Sep 17, 2026 by innolope-dev via approve-and-merge #4223
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