Skip to content

fix: review follow-ups — ds-lint font-(--x) weight, SupportDrawer hardware back, landing Log in link, claim receipt cancelledAt - #2990

Merged
innolope-dev merged 5 commits into
devfrom
sweep/small-followups
Sep 5, 2026
Merged

fix: review follow-ups — ds-lint font-(--x) weight, SupportDrawer hardware back, landing Log in link, claim receipt cancelledAt#2990
innolope-dev merged 5 commits into
devfrom
sweep/small-followups

Conversation

@innolope-dev

Copy link
Copy Markdown
Collaborator

Sweep of the small follow-ups filed off #2905 / #2920 / the sendlink-crash investigation. One commit per task.

What

  • TASK-22101 — untyped font-(--x) bypassed the typography ratchet. Tailwind 4 compiles a bare font-(--value) as font-weight; a family needs the family-name: hint. WEIGHT_STACK_RE excluded the untyped form as a family, so text-body-s font-(--my-weight) stacked an off-ramp weight while countWeightStacks returned 0. It now counts the untyped form and excludes only font-(family-name:…); regression cases updated. No font-(-- in src/, so the baseline is unchanged (ds-lint --check ok).
  • TASK-22118 — SupportDrawer off the hardware-back stack. fix(native): regression-review fixes — Sentry, OTA, Android back, setup sign-in #2920 put the DS Drawer/Modal on the LIFO back stack; the hand-rolled support sheet was left out, so Android back with it open navigated the page underneath. It registers useBackHandler while open and consumes the press. Tests dispatch dispatchBackPress() open (closes, consumed) and closed (falls through).
  • TASK-22117 — no Log in on the marketing landing. A returning user with an expired session had no visible way back in; every CTA pointed at signup. fix(native): regression-review fixes — Sentry, OTA, Android back, setup sign-in #2920 made /setup?step=login land on the passkey Log In step — this links to it from the hero (under the primary CTA) and from the sticky mobile CTA, with a landingLogIn string in en / es-419 / es-ar / pt-br (messages.test key-parity green). DS text-body-s token, no new ratchet debt.
  • TASK-22068 (FE half) — claim receipt never showed a cancellation date. Claim.tsx derived cancelledDate from events[0], which only holds a date when a claim attempt was recorded; a sender's cancel/reclaim leaves none. peanut-api-ts#1525 puts the row's own cancelledAt on GET /send-links/:pubKey; the receipt now prefers it and keeps the events fallback. Test asserts the receipt receives cancelledDate from cancelledAt on the cache-hit shape.

Verification

  • tsc --noEmit clean; ds-lint-rules, SupportDrawer, i18n/messages, Claim/claim-states suites green; node scripts/ds-lint-counts.mjs --check ok; prettier clean.
  • Not verified in a browser: the hero/sticky link placement. Both use existing landing spacing; screenshots welcome if design wants to move it.

Tailwind 4 compiles a bare font-(--value) as font-weight; a family needs
the family-name: type hint. The matcher excluded the untyped form as a
family, so text-body-s font-(--my-weight) stacked an off-ramp weight while
countWeightStacks returned 0 and --check stayed green (TASK-22101)
#2920 put DS drawers and modals on the LIFO back stack; SupportDrawer is a
hand-rolled overlay and was left out, so back with the sheet open navigated
the page underneath. It now registers while open and consumes the press
(TASK-22118)
peanut.me only offered SIGN UP: a user with an account and an expired
session had no visible way back in from the marketing site. #2920 made
/setup?step=login land on the passkey Log In step; this links to it from
the hero and the sticky mobile CTA, in all four landing locales (TASK-22117)
The receipt derived cancelledDate from events[0], which only holds a date
when a claim attempt was recorded — a sender's cancel/reclaim leaves none,
so the receipt showed no cancellation date. GET /send-links now carries
cancelledAt (peanut-api-ts fix/kyc-qr-sendlink-followups); prefer it, keep
the events fallback (TASK-22068)
@vercel

vercel Bot commented Sep 4, 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 4, 2026 11:56pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 4, 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: Team

Run ID: 09c846cf-839b-4acb-bf80-e465623d465f

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

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

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7167.05 → 7167.8 (+0.75)
Findings: 0 net (+25 new, -25 resolved)

🆕 New findings (25)

  • critical complexity — src/utils/native-routes.ts — CC 109, MI 54.93, SLOC 293
  • critical complexity — src/components/Claim/Claim.tsx — CC 100, MI 53.63, SLOC 400
  • critical complexity — src/components/Global/SupportDrawer/index.tsx — CC 74, MI 61.63, SLOC 223
  • high hotspot — src/components/LandingPage/hero.tsx — 46 commits, +401/-282 lines since 6 months ago
  • high hotspot — src/components/Global/SupportDrawer/index.tsx — 40 commits, +759/-301 lines since 6 months ago
  • high complexity — src/components/LandingPage/hero.tsx — CC 31, MI 61.88, SLOC 88
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:30 — SupportDrawer: MDD 123.5 (uses across many lines from declarations)
  • medium high-mdd — src/components/Claim/Claim.tsx:50 — Claim: MDD 101.5 (uses across many lines from declarations)
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:209 — : MDD 54.5 (uses across many lines from declarations)
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:348 — : MDD 40.5 (uses across many lines from declarations)
  • medium high-dlt — src/components/Global/SupportDrawer/index.tsx:30 — SupportDrawer: DLT 38 (calls 38 distinct functions — high context load)
  • medium high-mdd — src/components/Claim/Claim.tsx:122 — : MDD 26.7 (uses across many lines from declarations)
  • medium high-mdd — src/components/LandingPage/landingStrings.ts:49 — landingStrings: MDD 26.0 (uses across many lines from declarations)
  • medium complexity — src/components/LandingPage/StickyMobileCTA.tsx — CC 20, MI 65.67, SLOC 73
  • medium method-complexity — src/utils/native-routes.ts:401 — rewriteMethodPath CC 20 SLOC 34
  • medium method-complexity — src/components/Claim/Claim.tsx:122 — CC 16 SLOC 80
  • medium method-complexity — src/components/Global/SupportDrawer/index.tsx:30 — CC 16 SLOC 100
  • medium complexity — src/components/LandingPage/landingStrings.ts — CC 2, MI 52.52, SLOC 51
  • medium react-effect-derives-state — src/components/Global/SupportDrawer/index.tsx:180 — small useEffect that only sets state from deps
  • medium react-effect-derives-state — src/components/Global/SupportDrawer/index.tsx:348 — useEffect with empty deps + setState — derived state anti-pattern

…and 5 more.

✅ Resolved (25)

  • src/utils/native-routes.ts — CC 109, MI 54.99, SLOC 291
  • src/components/Claim/Claim.tsx — CC 100, MI 53.65, SLOC 399
  • src/components/Global/SupportDrawer/index.tsx — CC 73, MI 61.41, SLOC 219
  • src/components/LandingPage/hero.tsx — 45 commits, +391/-282 lines since 6 months ago
  • src/components/Global/SupportDrawer/index.tsx — 39 commits, +750/-301 lines since 6 months ago
  • src/components/LandingPage/hero.tsx — CC 31, MI 61.9, SLOC 88
  • src/components/Global/SupportDrawer/index.tsx:29 — SupportDrawer: MDD 121.6 (uses across many lines from declarations)
  • src/components/Claim/Claim.tsx:50 — Claim: MDD 103.1 (uses across many lines from declarations)
  • src/components/Global/SupportDrawer/index.tsx:208 — : MDD 54.5 (uses across many lines from declarations)
  • src/components/Global/SupportDrawer/index.tsx:347 — : MDD 40.5 (uses across many lines from declarations)
  • src/components/Global/SupportDrawer/index.tsx:29 — SupportDrawer: DLT 37 (calls 37 distinct functions — high context load)
  • src/components/Claim/Claim.tsx:122 — : MDD 26.8 (uses across many lines from declarations)
  • src/components/LandingPage/landingStrings.ts:48 — landingStrings: MDD 25.6 (uses across many lines from declarations)
  • src/components/LandingPage/StickyMobileCTA.tsx — CC 20, MI 65.7, SLOC 73
  • src/utils/native-routes.ts:398 — rewriteMethodPath CC 20 SLOC 34
  • src/components/Claim/Claim.tsx:122 — CC 16 SLOC 79
  • src/components/Global/SupportDrawer/index.tsx:29 — CC 16 SLOC 98
  • src/components/LandingPage/landingStrings.ts — CC 2, MI 52.77, SLOC 50
  • src/components/Global/SupportDrawer/index.tsx:179 — small useEffect that only sets state from deps
  • src/components/Global/SupportDrawer/index.tsx:347 — useEffect with empty deps + setState — derived state anti-pattern

…and 5 more.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 5897 ran, 0 failed, 0 skipped, 2.0m

📊 Coverage (unit)

metric %
statements 74.7%
branches 60.1%
functions 68.5%
lines 75.6%
⏱ 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_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 › MANTECA_MERCHANT_VOLUME_NEAR_CAP 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_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 › 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_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 › 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 › routes the KYC rejection on its wire code, and does not retry it
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`.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🖼 Visual diff — ⚠️ no result for the latest push

The newest Tests run produced no diff report in any attempt: ds-shots was skipped, failed before the diff, or had no cached baseline.
The previous result on this comment no longer reflects the latest run, so it was cleared.

Fixture screenshots, no backend. Advisory — this check never blocks a merge.

@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

Clean review: the four follow-ups correctly tighten the typography ratchet, add SupportDrawer hardware-back handling, expose the returning-user login route, and prefer the send link's cancellation timestamp. No actionable defect remains, and all exact-head CI checks completed green.

Findings

  • MAJOR · src/components/Claim/Claim.tsx:170 · [claude-opus] GET /send-links does not return cancelledAt on the pinned API branch, so the receipt fix stays inert
    Claim.tsx now reads claimLinkData.cancelledAt from the GET /send-links/:pubKey payload, and services.types.ts adds it to the SendLink type. On the peanut-api-ts policy checkout, that route's projection does not select it: SEND_LINK_SELECT in src/routes/send-links/index.ts:40-104 lists pubKey…claimFailureCode, sender and intents but no cancelledAt, and sanitizeSendLink (index.ts:153,178) returns {...rest} from exactly that select, so the field never reaches the wire. The column exists (prisma/schema.prisma:240) and is stamped on cancel (src/routes/claim.ts:330), and /users/history does surface it (src/transaction-intent/history.ts:781), but the claim page does not use that endpoint.

Nothing breaks at runtime — the ?? claimLinkData.events?.[0]?.timestamp fallback preserves today's behaviour — but the bug this PR fixes (cancelled receipt with no date, because a sender cancel leaves no SEND_LINK_CLAIM intent) is not actually fixed until the API side ships. The test comment at src/components/Claim/tests/claim-states.test.tsx:422 asserts the opposite ("GET /send-links now carries the row's own cancelledAt"), which is what makes this worth flagging rather than assuming.

This normally ships as a pair and the peanut-api-ts half is likely an open PR not present in the pinned policy branch, so this is major rather than blocking. Fix: confirm the companion PR adds cancelledAt: true to SEND_LINK_SELECT (and to the cached row shape covered by src/routes/send-links/cache-response-shape.test.ts, which is derived from the same select), and link it here; otherwise soften the test comment to say the field is expected but not yet served.

Checked clean

  • Confirmed the detached HEAD, trusted author, dev base ref/SHA, exact PR head, and merge base match the supplied review target.
  • Verified the font-weight matcher counts Tailwind's untyped font-(--x) weight shorthand while excluding the typed family-name form; targeted matcher cases and git diff --check passed.
  • Traced SupportDrawer registration through the shared LIFO hardware-back stack: it registers only while open, closes through the modal context, consumes the press, and unregisters when closed.
  • Traced both landing-page login links through /setup?step=login and resolveSetupEntryStep, and checked the new string is present in every supported locale and the narrowed LandingStrings contract.
  • Traced cancelledAt from the send-link wire type into the cancelled receipt, including the legacy events fallback and the current API projection boundary; the new field is optional and does not regress older responses.
  • Correctness, security, adversarial, and slop passes found no actionable authorization, data-exposure, failure-path, regression, dead-code, duplication, or architecture-drift issue in the changed behavior.
  • All exact-head GitHub checks completed successfully, including unit, typecheck, eslint, format, ds-lint, native export, analysis, screenshots, preview deployment, provenance, report, and ci-success.
  • Local Jest was not repeated because the detached worktree has no node_modules; exact-head CI supplied the test evidence instead.

Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.

Third opinion by claude-opus: 1 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: 5f0fdcd73b4a · Context: repo, sibling-api · Took 10m

Mirror of the main-targeted fix (#2991): the scheme://host prefix kept
`user:pass@` intact, so a crafted https://SECRET@peanut.me/qr/… link
would carry that userinfo into telemetry next to the redacted path. Only
the host survives now. Also names peanut-api-ts#1525 as the API half of
the cancelledAt receipt fix in the claim-states test.
@innolope-dev

Copy link
Copy Markdown
Collaborator Author

Re the claude-opus finding on Claim.tsx:170 — the API half is peanut-api-ts#1525 (adds cancelledAt: true to both SEND_LINK_SELECTs; cache-response-shape.test.ts asserts it reaches the wire on the cached shape too). The review's pinned api checkout was dev, which doesn't have it yet. Merge order: #1525 first. Softened the test comment in f4d2b02 to say the field is served as of #1525; until then the events[0] fallback keeps today's behaviour, as noted.

Also in f4d2b02: mirrored the userinfo redaction fix from #2991 (CodeRabbit finding there) so dev and main carry identical redactNativePath code.

@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

The support-back, login-link, typography-ratchet, and telemetry-redaction changes hold, but the cancellation-date fix remains inert against the pinned API response contract.

Findings

  • MAJOR · src/components/Claim/Claim.tsx:170 · Return cancelledAt from the send-link API
    This value still cannot arrive at runtime: the pinned API's SEND_LINK_SELECT does not select cancelledAt, so sanitizeSendLink cannot include it in either the DB or cache response. For a sender cancellation with no claim intent, events is empty as well, leaving cancelledDate undefined; the new component test passes only because it injects a response shape the route cannot emit. Add cancelledAt to the API projection/response and cover both GET paths, or land that API half before treating this receipt fix as complete.

Checked clean

  • Exact head and dev base matched the supplied SHAs; the detached worktree was clean.
  • SupportDrawer registers only while open and correctly consumes the LIFO hardware-back press.
  • The landing Log in links route to the existing passkey-capable auth landing, with locale key parity covered.
  • The Tailwind weight matcher now counts untyped font custom properties while preserving the typed family-name escape.
  • Deep-link telemetry removes authority userinfo while preserving the scheme and host; focused tests cover credential and bearer-secret shapes.
  • Exact-head aggregate CI, unit, typecheck, lint, format, native export, analysis, and provenance checks passed. The non-gating ds-shots job exited during its Next build without a changed-code diagnostic; preview deployment was still in progress.

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: f4d2b02e6c3f · Context: repo, api · Took 9m

Comment thread src/components/Claim/Claim.tsx
@innolope-dev
innolope-dev merged commit f613add into dev Sep 5, 2026
23 of 24 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.

1 participant