Skip to content

chore: backmerge main into dev (2026-08-26) - #2830

Closed
innolope-dev wants to merge 48 commits into
devfrom
chore/backmerge-main-into-dev-20260826
Closed

innolope-dev wants to merge 48 commits into
devfrom
chore/backmerge-main-into-dev-20260826

Conversation

@innolope-dev

Copy link
Copy Markdown
Collaborator

Backmerge of main into dev.

One conflict, in src/config/peanut.config.tsx — both sides rewrote the same provider useEffect. Resolved as the semantic union:

  • kept dev's structure: the dynamic AppStateProviders import, the marketing-route split, and the lazy country-locale load
  • grafted in main's passkey-shim install path from fix(login): unwedge a never-settling native passkey ceremony #2801 wholesale: async installPasskeyShim with the patched-flag verification throw, the bounded 1.5s retry, and markPasskeyShimFailed() on double failure
  • the scheduleDirectFetchCanary() call and import from main's side were not carried over: dev retired the native transport-migration canary in chore(native): retire the transport-migration probes #2737 and the native-canary.ts module no longer exists on this branch — this merge is where main's last reference to it dies

Typecheck clean; passkeyCeremony.utils, ClientProviders, user-query and usePWAStatus test suites all green (35 tests).

Brings in:

abalinda and others added 30 commits August 20, 2026 14:13
Sumsub's `bridge-requirements` workflow now branches every EEA applicant to the
`bridge-eea-uplift` questionnaire as soon as the documents go GREEN. The
frontend closed the SDK on the first submit for every non-LATAM flow, so the
questionnaire never showed. About 3 minutes later the backend poller read the
follow-up level's `init` state, and the KYC drawer fell back to "Start
verification". The user could not reach the questionnaire at all.

`isMultiLevel` is the flag that holds the SDK open past the first submit. It
was derived from the `regionIntent` hook prop. Almost every entry point
withholds that prop on purpose: the bank, claim and add-money flows pass the
intent to handleInitiateKyc at call time, so that mounting a page does not
create a backend record. The flag was false for all of them. It now comes from
the intent the SDK was actually opened with, and it covers the Bridge intents
(EU, NA) as well as LATAM.

TASK-21510
CodeRabbit flagged the render-time write to isMultiLevelRef: React can discard
an interrupted render, but a ref write survives it, so the guard could act on a
value that never committed. Drop the ref and read showWrapper / isMultiLevel as
state, with both in the effect's dependency array. A re-run with an unchanged
status is a no-op, because prevStatusRef already holds that status.
…tion

Review follow-ups on the EEA uplift fix.

NA shares the `bridge-requirements` workflow with EU, but only EEA applicants
branch to the uplift questionnaire. Holding the SDK open for NA would park
every US applicant on Sumsub's "documents submitted" screen until approval, and
suppress the submit handler that fires KYC_SUBMITTED. NA is now single-level.

The held ACTION_REQUIRED transition was consumed, not deferred: prevStatusRef
advanced before the guard returned, so the transition could never fire again. A
user who abandoned mid-questionnaire was left on a stale "verifying" modal with
nothing to close it. The guard now returns before the ref advances, so closing
the SDK re-runs the effect and evaluates the same transition for real.

isMultiLevel is now cleared in the two close handlers instead of being reset at
each single-level open, so a closed SDK reads false by construction.

The drawer CTA said "Re-submit verification" under copy that asks the user to
continue. The generic branch now says "Continue", matching the sibling modal.
The reject-labels branch keeps the re-submit label.
CodeRabbit (Major): the APPROVED branch hides the SDK without clearing the
flag, so a later self-heal, restart-identity or start-action open inherited a
stale true. SumsubKycWrapper then suppressed that session's completion close and
stranded the user in the SDK.

Approval is the third and last path that closes the SDK. Clearing here is what
makes "closed implies single-level" hold everywhere, so the per-open resets stay
deleted rather than being reinstated as belt and braces.

Also drops the stale NA references from two comments: NA shares the
bridge-requirements workflow but never branches to the EEA uplift.
…restart flag

Review round (jjramirezn):

- The store-refresh effect in useMultiPhaseKycFlow fired KYC_REJECTED and
  fetchUser on every happy-path ACTION_REQUIRED once api#1370 makes it a
  routine mid-questionnaire status. Same defer guard as the transition
  effect: hold while a multi-level SDK session is open, act on close.
- A deferred ACTION_REQUIRED replayed on EVERY close, so an in-session
  resubmit (handleSdkComplete) closed the progress modal it had just
  opened. A submission close now consumes the held transition; the manual
  close keeps the replay — abandoning really does leave the action
  required, and the SDK can sit on top of an open progress modal.
- Multi-level sessions emitted no KYC_SUBMITTED at all (submit handlers
  early-return, the APPROVED close skips onComplete). New optional
  onSubmitted prop reports the Level-1 submit; useMultiPhaseKycFlow
  captures the event with the same region_intent resolution.
- handleRestartIdentity reopened the same workflow with isMultiLevel
  false, closing a restarted LATAM session before the questionnaire. It
  now re-derives the flag from regionIntentRef.
- The NA exclusion comments claimed NA has no second level; the backend
  registry documents organic source-of-funds / proof-of-address branches.
  Comments corrected — NA stays excluded because the branches are rare
  and the hold would apply to every US applicant.
The deposit screen told every user a ~0.1% bridging fee applies. No such
fee exists: deposits ledger 1:1 and the Rhino fee is booked on withdraw
only. The copy drifted in during the i18n string extraction (0cffa3e)
and contradicted both the same screen's tooltips (variance, not fee) and
the fees help page (deposits free). Reworded as bridging variance and
made the EVM variant say USDC on Arbitrum arrives exactly, since no
bridging happens there at all. Reported by a user via support.
zerodev's toWebAuthnKey has no timeout; on native Android a tap that races
the async autoShimWebAuthn install (or a Credential Manager callback that
never fires) pends forever — isLoggingIn stays true and the Log In button
is dead until the app is killed (TASK-21782, Konrad's 2026-08-24 recording).

- race the ceremony against a 60s timeout; late results are discarded
- gate native ceremonies on the capgo shim actually being installed
- Sentry tags login_ceremony_timeout / login_shim_not_ready (+shimInstalled,
  elapsedMs) — the discriminating telemetry the RCA lacked
- disable Sign Up while a login ceremony is pending (waitlist-step flash)
- stop labeling the native app isPwa:true in the login capture
…honest failure copy

/code-review high findings applied:
- guardPasskeyCeremony() is now the one wrapper both login and register route
  through (register had the identical hang with zero telemetry — the tightest
  shim race is a fresh install's first Sign Up tap)
- timeout race is native-only: web hybrid/QR and security-key ceremonies
  legitimately run minutes; the silent hang is a Capacitor defect
- verify-token capture now requires an active ceremony window, so a verify
  response landing after the timeout cannot leave a half-authenticated session
- shim install failures (incl. the previously-uncaught dynamic import) mark a
  known-dead flag: login fails immediately with restart copy instead of
  polling 3s toward advice that can never come true
- PasskeyErrorCode is a closed union of the copy map keys — a future code
  can't silently fall into the clearAuthState branch
- isPwa telemetry uses isNativeBridge() (capacitor-flavored web builds keep
  real PWA semantics); comment now states usePWAStatus's deliberate behavior
- shim-flag reads unified on isPasskeyShimInstalled(); waitForPasskeyShim
  tests moved to fake timers
A bare any-ceremony-active check re-opened the capture window: ceremony A
times out, the user retries (B), and A's late verify token would be stored
while B runs. Each verify request now records the ceremony id it was issued
under, and its token persists only if that SAME ceremony is still active at
response time. Test covers exactly the A-times-out/B-active/A-lands-late path.
fix(i18n): deposit note claimed a 0.1% bridging fee that does not exist
…open

fix(kyc): keep the Sumsub SDK open through the EEA uplift questionnaire
…ces-v2

fix(seo): noindex app surfaces at response layer
Manteca outage 2026-08-24. disabledPaymentProviders: ['MANTECA'] blocks
QR payments (MP AR + PIX BR); disabledMantecaCurrencies: ['ARS','BRL']
blocks add-money and withdraw for both geos. Revert by emptying both
arrays.
hotfix: disable all Manteca surfaces (maintenance kill-switch)
Reverts the kill-switch flip from #2807: QR payments (MP AR + PIX BR)
and ARS/BRL add-money + withdraw are live again.
…remaining WebAuthn paths

- guardPasskeyCeremony now rejects a second concurrent ceremony
  (CeremonyConflictError -> PASSKEY_INTERRUPTED) instead of evicting the
  first window, and the fetch wrapper only STASHES a verify token: it is
  persisted when the owning ceremony resolves and discarded on failure.
  Token persisted <=> a ceremony the user saw succeed - closes both the
  stale-token-under-retry and evicted-window half-auth holes.
- native sign callback and app-lock presence check get the same shim
  gate + ceremony timeout (same silent-hang class as login); app-lock
  maps PasskeyShimFailedError to 'unsupported' so a lock that can never
  be lifted does not engage.
- SetupPasskey surfaces guard errors with curated copy (no generic
  UnknownError modal, no double Sentry capture); a timed-out register
  re-checks the username and routes to login instead of re-registering.
- the 'pending' bail in the register catch releases isRegistering.
- web ceremonies get a generous 5-min bound so an abandoned hybrid/QR
  login cannot dead-end the landing page now that Sign Up is disabled
  while isLoggingIn.
- shim install retries once before markPasskeyShimFailed; guard-error
  captures unified in captureCeremonyGuardError with per-class tags
  (shim_failed no longer reported as shim_not_ready).
- login analytics use real display-mode detection instead of
  usePWAStatus's Capacitor short-circuit.
…l resolved-but-unpatched shim install

- stashCeremonyVerifyToken takes the issue-time ceremony id and accepts
  only while that ceremony is still active: a request issued outside the
  current window (a timed-out ceremony's late verify) cannot enter the
  retry's stash. A late request issued DURING the retry's window remains
  unattributable at the fetch layer; commit-on-resolve still bounds it
  to ceremonies the user saw succeed.
- installPasskeyShim throws when autoShimWebAuthn resolves without
  patching navigator.credentials, routing the resolved-but-unpatched
  state through the retry/markPasskeyShimFailed path.
- isStandaloneDisplayMode reads mode=pwa via URLSearchParams so the
  parameter is detected regardless of query order; regression test.
… hatch

- SetupPasskey guard-error branches use setup.passkey.* i18n keys
  (tookTooLong / notReady / deviceState / interrupted) added to en,
  es-419 and pt-BR (es-AR inherits via the delta overlay) instead of
  the hardcoded-English classifyPasskeyError map.
- Landing disables Sign Up during a pending login on native only: the
  waitlist-step flash was native, while on web an abandoned hybrid/QR
  ceremony can pend minutes and Sign Up must stay the way out; a
  mid-ceremony register now fails cleanly as CeremonyConflictError.
…emony-hang

fix(login): unwedge a never-settling native passkey ceremony
hotfix: re-enable Manteca (revert 2026-08-24 kill-switch)
… OTA shipped env-less

The OTA lane ran native-build.js without writing .env.production.local, so
every NEXT_PUBLIC_* was inlined as undefined: recognizeQr threw on BASE_URL for
every scan, and Sentry/PostHog never initialised, which is why nothing reported
it. The store lanes wrote the file all along. Four months, two applied bundles.

native-build.js now fails the build in CI when the file is missing or a required
key has no value, so a lane that forgets it cannot ship a dark bundle again.

Ref: mono ops/native-ota-envless-bundle-rca.md
…n env-less bundle

DirectSendQR/utils re-declared BASE_URL from process.env with a non-null
assertion, and read it on the first line of recognizeQr. @/constants/general.consts
already exports the same value with a peanut.me fallback; nothing imported the
local copy. The test reproduces the production TypeError against the old code.
…log lines; require NEXT_PUBLIC_ONESIGNAL_APP_ID

The hand-rolled RP_ID / OneSignal regexes were unanchored (a commented-out key
read as set) and duplicated missingNativeEnv(); OneSignal was only a warning
although the native adapter throws at init without it.
…into-dev-20260826

# Conflicts:
#	src/config/peanut.config.tsx
@innolope-dev innolope-dev self-assigned this Aug 26, 2026
@vercel

vercel Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview Aug 26, 2026 6:20pm

Request Review

Co-authored-by: Aleks Balinda <aleks@peanut.me>
Co-authored-by: chip-bot[bot] <2915219+chip-bot[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7451.59 → 7495.57 (+43.98)
Findings: +17 net (+183 new, -166 resolved)

🆕 New findings (183)

  • critical complexity — src/lib/content.ts — CC 103, MI 58.31, SLOC 387
  • critical complexity — src/context/kernelClient.context.tsx — CC 101, MI 57.03, SLOC 479
  • critical complexity — src/hooks/useSumsubKycFlow.ts — CC 91, MI 52.29, SLOC 394
  • critical complexity — src/components/Invites/InvitesPage.tsx — CC 88, MI 54.93, SLOC 217
  • critical complexity — src/hooks/useMultiPhaseKycFlow.ts — CC 82, MI 56.54, SLOC 380
  • critical complexity — src/components/Kyc/SumsubKycWrapper.tsx — CC 63, MI 60.22, SLOC 320
  • critical complexity — src/components/LandingPage/LandingPageClient.tsx — CC 51, MI 56.24, SLOC 205
  • high complexity — src/components/AddMoney/views/CryptoDeposit.view.tsx — CC 49, MI 58.12, SLOC 108
  • high hotspot — src/hooks/useZeroDev.ts — 47 commits, +559/-337 lines since 6 months ago
  • high hotspot — src/hooks/useSumsubKycFlow.ts — 46 commits, +661/-280 lines since 6 months ago
  • high complexity — src/utils/webauthn.utils.ts — CC 40, MI 54.03, SLOC 146
  • high method-complexity — src/components/AddMoney/views/CryptoDeposit.view.tsx:52 — CC 38 SLOC 90
  • high complexity — src/components/Setup/Views/SetupPasskey.tsx — CC 36, MI 55.45, SLOC 177
  • high complexity — src/utils/passkeyCeremony.utils.ts — CC 35, MI 65.45, SLOC 117
  • high hotspot — src/components/Invites/InvitesPage.tsx — 31 commits, +562/-351 lines since 6 months ago
  • high hotspot — src/context/kernelClient.context.tsx — 31 commits, +639/-203 lines since 6 months ago
  • high complexity — src/components/Global/DirectSendQR/utils.ts — CC 25, MI 47.05, SLOC 113
  • high complexity — src/utils/ephemeralSpendKey.ts — CC 18, MI 44.79, SLOC 230
  • high complexity — src/app/layout.tsx — CC 11, MI 40.89, SLOC 104
  • medium high-mdd — src/hooks/useSumsubKycFlow.ts:89 — useSumsubKycFlow: MDD 216.4 (uses across many lines from declarations)

…and 163 more.

✅ Resolved (166)

  • src/context/kernelClient.context.tsx — CC 101, MI 57.09, SLOC 477
  • src/components/Invites/InvitesPage.tsx — CC 87, MI 55.1, SLOC 214
  • src/hooks/useSumsubKycFlow.ts — CC 80, MI 52.52, SLOC 374
  • src/hooks/useMultiPhaseKycFlow.ts — CC 74, MI 56.63, SLOC 358
  • src/lib/content.ts — CC 64, MI 61.45, SLOC 252
  • src/components/Kyc/SumsubKycWrapper.tsx — CC 60, MI 60.45, SLOC 306
  • src/components/LandingPage/LandingPageClient.tsx — CC 51, MI 56.04, SLOC 205
  • src/components/AddMoney/views/CryptoDeposit.view.tsx — CC 48, MI 58.25, SLOC 107
  • src/hooks/useZeroDev.ts — 44 commits, +474/-279 lines since 6 months ago
  • src/hooks/useSumsubKycFlow.ts — 39 commits, +524/-237 lines since 6 months ago
  • src/components/AddMoney/views/CryptoDeposit.view.tsx:52 — CC 37 SLOC 89
  • src/app/(mobile-ui)/withdraw/page.tsx — 30 commits, +309/-205 lines since 6 months ago
  • src/components/Invites/JoinWaitlistPage.tsx — 30 commits, +463/-204 lines since 6 months ago
  • src/components/Global/DirectSendQR/utils.ts — CC 25, MI 46.95, SLOC 114
  • src/utils/ephemeralSpendKey.ts — CC 18, MI 44.85, SLOC 229
  • src/app/layout.tsx — CC 11, MI 40.69, SLOC 107
  • src/hooks/useSumsubKycFlow.ts:64 — useSumsubKycFlow: MDD 192.4 (uses across many lines from declarations)
  • src/components/AddMoney/views/CryptoDeposit.view.tsx:52 — CryptoDepositView: MDD 135.6 (uses across many lines from declarations)
  • src/hooks/useMultiPhaseKycFlow.ts:120 — useMultiPhaseKycFlow: MDD 125.6 (uses across many lines from declarations)
  • src/components/Invites/InvitesPage.tsx:39 — InvitePageContent: MDD 109.8 (uses across many lines from declarations)

…and 146 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/utils/passkeyCeremony.utils.ts 0.0 6.5 +6.5
src/components/LandingPage/landingContentHrefs.server.ts 0.0 5.4 +5.4
src/components/LandingPage/landingContentHrefs.ts 0.0 5.3 +5.3
src/components/LandingPage/FooterChrome.tsx 0.0 5.2 +5.2
src/app/robots.ts 5.3 8.2 +2.9
src/lib/content.ts 8.8 11.1 +2.3
src/utils/app-lock.ts 6.8 8.5 +1.7
src/config/peanut.config.tsx 7.4 9.0 +1.6
src/hooks/useSumsubKycFlow.ts 16.4 17.7 +1.3
src/utils/native-auth-capture.ts 8.4 9.7 +1.3
src/components/Setup/Views/SetupPasskey.tsx 11.9 13.0 +1.0
src/hooks/query/user.ts 12.3 13.3 +1.0
src/constants/zerodev.consts.ts 7.0 7.9 +0.9
src/utils/webauthn.utils.ts 8.3 9.1 +0.8
src/hooks/useMultiPhaseKycFlow.ts 12.9 13.6 +0.6
src/components/Kyc/states/KycActionRequired.tsx 5.5 6.0 +0.6
src/components/LandingPage/RegulatedRails.tsx 8.7 9.3 +0.6
src/components/Kyc/sumsubStatusEvent.utils.ts 4.8 5.3 +0.5
src/app/quests/page.tsx 9.7 9.0 -0.7
src/components/LandingPage/Footer.tsx 8.3 5.8 -2.4

@github-actions

github-actions Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • ✅ unit: 3744 ran, 0 failed, 0 skipped, 49.5s

📊 Coverage (unit)

metric %
statements 69.7%
branches 53.8%
functions 60.1%
lines 70.6%
⏱ 10 slowest test cases
time test
3.1s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.0s src/hooks/query/__tests__/user.test.tsx › does NOT clear a token that rotated mid-request (stale 401 racing a fresh login)
0.5s src/utils/__tests__/crisp.test.ts › resets the native session on logout once support has been opened
0.4s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/utils/__tests__/crisp.test.ts › settles, and hands back a usable plugin, against a real-shaped plugin proxy
0.3s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/utils/__tests__/crisp.test.ts › configures once across repeated support opens
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › the lazy bank view survives a re-render without blanking
0.3s src/hooks/__tests__/useCrispTokenId.test.ts › retries then stays undefined when the endpoint keeps failing (no fallback token)
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

abalinda and others added 2 commits August 26, 2026 18:07
fix(ci): bake NEXT_PUBLIC_* into Capgo OTA bundles (native QR scan/paste dead on ota-1.0.54/1.0.55)
@coderabbitai

coderabbitai Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c0b70b29-1ee7-4a97-bae4-c1e2bd2c591a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

- require published prose for ownership so resolved links never target
  routes that notFound() on published: false
- decode percent-encoded path segments before content lookups
- localize en-authored absolute peanut.me URLs with no content owner,
  matching the relative-href behavior; non-en absolute URLs stay pinned
- derive legal slugs from the content mirror instead of a hand-kept set
- resolve landing content hrefs inside the server components via a shared
  memoized contentHrefsFor, and require the href props where they remain
  so a missing map can no longer silently ship /en/ links
- build help/stories hub links from the locale that served the prose,
  removing the second fallback walk per slug
- drop the now-unused localizeContentHref and derive LandingContentHrefs
  from the href map
@abalinda

Copy link
Copy Markdown
Contributor

Hey @innolope-dev — one more main merge before this lands, please: #2823 (hotfix/ota-env-bake, the Capgo OTA env fix) hit main at 17:07Z as d4bd3abae, 26 min after this PR was opened, so it's not in here yet.

Its delta doesn't touch src/config/peanut.config.tsx, so your resolution stands as-is — git merge origin/main on this branch should be conflict-free (verified with a dry run). Files it brings: .github/workflows/capgo-deploy.yml (env step), scripts/native-build.js (+ test), src/components/Global/DirectSendQR/utils.ts (+ test), plus the small comment tweaks in ios-release.yml / android-release.yml.

Why it matters for dev: an ota-* tag pushed on a dev commit runs dev's capgo-deploy.yml, which still builds without .env.production.local — same broken bundle as ota-1.0.54 / 1.0.55. Context: mono ops/native-ota-envless-bundle-rca.md, TASK-21900.

@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: Changes requested

Request changes: cross-region EU uplift is treated as single-level, so the web SDK closes before the required EEA follow-up questionnaire.

Findings

  • MAJOR · src/hooks/useSumsubKycFlow.ts:391 · Keep cross-region EU uplift multi-level
    An already-approved EEA user choosing a locked EU region calls handleInitiateKyc with crossRegion=true. The backend moves them to bridge-requirements and returns a token with actionType "bridge-uplift"; that workflow then branches to bridge-eea-uplift. This truthiness check sets isMultiLevel=false, so the web SDK closes on the first submission before showing the required follow-up questionnaire. Treat bridge-uplift as multi-level (and add it to KycActionType), or return the effective level/isMultiLevel from the API, with a cross-region EU regression test.

Checked clean

  • Validated the exact head/base pair and the PeanutProvider merge-conflict semantic union.
  • Reviewed passkey shim gating, ceremony serialization and timeouts, late-token attribution, native signing guards, and error handling.
  • Reviewed Sumsub multi-level transitions, deferred ACTION_REQUIRED handling, web/native SDK close paths, and the backend actionType contract.
  • Reviewed response-level noindex headers, route metadata and canonical ownership, robots crawl exceptions, and preview fail-closed behavior.
  • Reviewed Manteca kill-switch restoration and crypto-deposit bridging copy.
  • Exact-head CI passed typecheck, unit, eslint, e2e, format, analyze, and deployment checks; local focused tests could not start because the detached worktree has no node_modules.

Exact head: 5b20452d088d · Context: repo, peanut-api-ts

Comment thread src/hooks/useSumsubKycFlow.ts Outdated
innolope-dev and others added 8 commits August 26, 2026 18:49
RegulatedRails, SecurityBuiltIn and YourMoney now resolve content hrefs
from the filesystem, and the barrel is imported by client components
(LandingPageClient, ShhhhhLandingPage, MerchantLandingPage), which pulled
fs into the client bundle and broke the production build. Drop the three
server sections from the barrel and import them directly in /quests.
…l on submitted closes

The capture+fetchUser effect in useMultiPhaseKycFlow re-fired on every dep
change while the status sat on a stale REJECTED/ACTION_REQUIRED, duplicating
the posthog event and the user refetch on resubmit rounds. It now tracks the
previous status like the sibling transition effect in useSumsubKycFlow.

The multi-level ACTION_REQUIRED deferral also replayed on ANY close. A close
after the user submitted (level-2 done, SDK on "documents submitted") now
carries submitted: true from the wrapper and consumes the deferred transition
in both hooks, while an abandoned close still replays it once.
startAuthentication ran bare, so a step-up racing the native passkey shim
install could silently never settle (same class as login, TASK-21782). Route
it through guardPasskeyCeremony and map guard failures to StepUpError with
the curated classifyPasskeyError copy so callers render sane text.
robots.ts derived IS_PRODUCTION_DOMAIN from BASE_URL, whose production
fallback opened indexing on any environment with the env unset. Extract the
raw-env fail-closed derivation layout.tsx already used into
seo-route-policy.js (isProductionDomain) and use it in both.
tookTooLong, notReady, deviceState and interrupted landed in es-419 without
es-AR counterparts, so Argentine users got tuteo forms for these errors.
Login failures surfaced the hardcoded English PASSKEY_LOGIN_MESSAGES copy at
SetupPasskey and InvitesPage even though the same strings exist translated in
the setup.* catalog. The thrown PasskeyError already carries its code, so map
known codes to their catalog keys at the render sites and keep the English
message as the fallback for codes without a translated equivalent.
getUnderlyingFetch (and its canary-era doc comment) has zero importers; the
metadata-policy font mock still stubbed Londrina_Solid, which layout no
longer imports.
…ale-links-v2

fix(seo): link localized pages to content owners
…into-dev-20260826

# Conflicts:
#	src/components/LandingPage/Footer.tsx
#	src/components/LandingPage/LandingPageClient.tsx
#	src/components/LandingPage/LandingPageContent.tsx
#	src/components/LandingPage/RegulatedRails.tsx

This branch was successfully deployed

1 active deployment
Preview — b3ed020f Deployed Aug 26, 2026 by vercel[bot]
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.

6 participants