Skip to content

fix: pass Crisp proxy user data via postMessage handshake instead of URL query string - #2669

Merged
jjramirezn merged 5 commits into
mainfrom
fix/crisp-proxy-pii-in-url
Aug 12, 2026
Merged

fix: pass Crisp proxy user data via postMessage handshake instead of URL query string#2669
jjramirezn merged 5 commits into
mainfrom
fix/crisp-proxy-pii-in-url

Conversation

@kushagrasarathe

@kushagrasarathe kushagrasarathe commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

The crisp-proxy iframe URL carried the user's email, legal name, userId, username, wallet/Arbiscan link, Bridge dashboard link, PostHog person link — and the Crisp session token, which after #2666/api#1325 is a per-user bearer credential. A query string is not a private channel: it rides into Vercel runtime logs, browser history, Referer headers, and the $current_url of every analytics event fired from the iframe document. Verified in PostHog: ~10k events in the last 7 days store the full PII query string in $current_url.

This PR replaces the URL transport with a postMessage channel:

  • Pull at boot: the proxy asks its parent for data (CRISP_PROXY_REQUEST_INIT, re-asked every 250ms until answered) and boots Crisp only when the reply (CRISP_PROXY_INIT) lands. The iframe initiates, so the parent can never post before the page listens — the timing problem the URL approach was built to avoid is solved structurally.
  • Push on change: the parent re-sends the payload when it changes (email/name resolving mid-session, a new prefill) and the proxy applies it live via setCrispUserData — the old transport handled this by remounting the whole embedded app on every URL change. Token/locale changes still remount via the iframe key (they need a session re-bind).
  • The iframe src is a constant /crisp-proxy. useCrispProxyUrl is deleted. Direct visits (no parent) boot an anonymous session, as before.
  • The payload carries CrispUserData whole; the proxy reuses setCrispUserData from utils/crisp.ts (the canonical setter) instead of a third hand-rolled field mapping. Handshake message types are shared constants in constants/crisp.ts.
  • Session-reset semantics (crisp_needs_reset, crisp_last_token_id, CRISP_RESET_SESSION), the 8s readiness watchdog, and the CRISP_READY/CRISP_FAILED contract are unchanged. A never-answered handshake ends in CRISP_FAILED → existing retry UI, and the watchdog stops the request loop it declared dead.

Task

TASK-21353 — https://app.notion.com/p/peanutprotocol/F5-Remove-user-PII-from-Crisp-proxy-URLs-3b983811757981ce8f88e5accd6e094a (postmortem F5, probing-campaign-2026-08-10).

Risks / breaking changes

  • Was stacked on fix: fetch Crisp support token from the API instead of deriving it client-side #2666; that and api#1325 are now merged to main, so this PR targets main directly. It only changes how the already-fetched token and user data reach the iframe.
  • The exposure window is live: since api#1325 deployed, the new per-user bearer tokens are being minted and still ride the proxy URL into Vercel logs / PostHog $current_url until this PR deploys — which makes the token-rotation follow-up below load-bearing, not optional.
  • Same drawer, same states, no visible UI change.

Design notes / accepted trade-offs

  • Pull-then-push over a one-shot handshake: a one-shot pull would freeze whatever identity existed at first open; the old URL transport implicitly refreshed by remounting. Live pushes keep Crisp current without rebooting the embedded app per change (the WKWebView memory-crash class documented in SupportDrawer).
  • React strict-mode double-effect is handled by a per-window boot guard (__crispProxyBooted); a retry remounts the iframe and gets a fresh window.
  • The Capacitor path keeps its own native-plugin data mapping (pre-existing, unchanged).

Follow-ups (not in this PR)

  • Rotate users.crisp_token (null the column) for users who loaded the proxy between api#1325's deploy and this fix — those bearer tokens are in Vercel logs/PostHog $current_url. Cheap to do wholesale: Jota's legacy-session purge already resets in-widget history at rollout, so a full-column rotation adds no extra user-visible cost if done in the same window.
  • Purge/redact historical PostHog events carrying the PII URLs.
  • Consider not initializing posthog-js on /crisp-proxy at all (duplicate pageviews, no analytics value — and it was the egress amplifier here).

QA

  • Unit: SupportDrawer suite extended — handshake reply carries token + CrispUserData to the asking window only; foreign-origin requests ignored; iframe src asserted PII-free. Full suite green (2916 passed), typecheck + build green, 0 new eslint warnings.
  • Manual: open support drawer → chat loads with identity bound (agent sidebar shows session data); iframe src is bare /crisp-proxy.

Screenshots

N/A (no visible change) — the drawer renders identically; only the data transport changed.

Summary by CodeRabbit

  • Improvements
    • Improved support chat initialization for greater reliability and security.
    • Support chat now loads through a clean proxy URL and securely exchanges session details.
    • Added locale support, including Spanish variants and Portuguese.
    • User information and prefilled messages update without exposing details in the URL.
    • Improved handling of session resets, loading failures, retries, and duplicate initialization.

…essage handshake

The crisp-proxy iframe URL carried email, legal name, userId, wallet and
provider links, plus the Crisp session token (a bearer credential after the
server-side token change). A query string leaks into Vercel logs, browser
history, Referer headers, and the $current_url of every analytics event
fired from the iframe — confirmed stored in PostHog. Postmortem F5,
TASK-21353.

The proxy now asks its parent for the init payload (CRISP_PROXY_REQUEST_INIT)
and boots Crisp only when the reply lands, so the parent can never post
before the iframe listens — same reliability the URL transport was built
for, with nothing identifying in the URL.
@vercel

vercel Bot commented Aug 11, 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 12, 2026 6:08am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review 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: Pro

Run ID: 42344591-7a4d-4d55-b036-bade27f53f4b

📥 Commits

Reviewing files that changed from the base of the PR and between 6d1f53e and 7816e11.

📒 Files selected for processing (1)
  • src/app/crisp-proxy/page.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/crisp-proxy/page.tsx

📝 Walkthrough

Walkthrough

Crisp initialization now uses a same-origin postMessage handshake. SupportDrawer sends typed locale, identity, session, and prefilled-message data to /crisp-proxy. The proxy validates messages, injects Crisp, handles session resets, and reports readiness or failure.

Changes

Crisp initialization flow

Layer / File(s) Summary
Typed payload and iframe handshake
src/constants/crisp.ts, src/components/Global/SupportDrawer/index.tsx, src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx
The drawer builds a locale-aware CrispInitPayload, responds to same-origin initialization requests, and uses /crisp-proxy without query parameters. Tests cover payload delivery and rejected requests.
Guarded Crisp proxy boot
src/app/crisp-proxy/page.tsx, src/types/global.d.ts
The proxy requests initialization, configures and injects Crisp, resets sessions on logout or token changes, prevents duplicate boots, and tracks readiness and load failures with runtime flags.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SupportDrawer
  participant CrispProxyPage
  participant CrispRuntime
  SupportDrawer->>CrispProxyPage: Send CRISP_PROXY_INIT payload
  CrispProxyPage->>CrispRuntime: Configure session and inject script
  CrispRuntime-->>CrispProxyPage: Report load and readiness status
  CrispProxyPage-->>SupportDrawer: Report ready or failed state
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. 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: moving Crisp proxy user data from URL query parameters to a postMessage handshake.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/crisp-proxy-pii-in-url

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

@kushagrasarathe

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/components/Global/SupportDrawer/index.tsx (1)

47-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move the ref write out of the render body.

Line 48 assigns initPayloadRef.current during render. React 19 can discard or replay a render, so a payload built from state that never commits can leak into the reply. Compute the payload with useMemo and sync the ref in an effect. The proxy re-requests init every 250 ms, so a one-tick delay in the ref update does not break the handshake.

♻️ Proposed refactor
-    const initPayloadRef = useRef<CrispInitPayload>({ locale: 'en' })
-    initPayloadRef.current = {
-        locale: CRISP_LOCALE_BY_APP_LOCALE[locale] ?? 'en',
-        tokenId: crispTokenId,
-        email: userData.email,
-        nickname: userData.fullName || userData.username,
-        avatar: userData.avatar,
-        sessionData: hasSessionData
-            ? {
-                  username: userData.username || '',
-                  user_id: userData.userId || '',
-                  full_name: userData.fullName || '',
-                  wallet_address: userData.walletAddressLink || '',
-                  bridge_user_id: userData.bridgeCustomerLink || '',
-                  manteca_user_id: userData.mantecaUserId || '',
-                  posthog_person: userData.posthogPersonLink || '',
-              }
-            : undefined,
-        prefilledMessage,
-    }
+    const initPayload = useMemo<CrispInitPayload>(
+        () => ({
+            locale: CRISP_LOCALE_BY_APP_LOCALE[locale] ?? 'en',
+            tokenId: crispTokenId,
+            email: userData.email,
+            nickname: userData.fullName || userData.username,
+            avatar: userData.avatar,
+            sessionData: hasSessionData
+                ? {
+                      username: userData.username || '',
+                      user_id: userData.userId || '',
+                      full_name: userData.fullName || '',
+                      wallet_address: userData.walletAddressLink || '',
+                      bridge_user_id: userData.bridgeCustomerLink || '',
+                      manteca_user_id: userData.mantecaUserId || '',
+                      posthog_person: userData.posthogPersonLink || '',
+                  }
+                : undefined,
+            prefilledMessage,
+        }),
+        [locale, crispTokenId, userData, hasSessionData, prefilledMessage]
+    )
+    const initPayloadRef = useRef<CrispInitPayload>(initPayload)
+    useEffect(() => {
+        initPayloadRef.current = initPayload
+    }, [initPayload])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Global/SupportDrawer/index.tsx` around lines 47 - 66, Move the
`initPayloadRef.current` assignment out of the render body in `SupportDrawer`
and compute the payload with `useMemo` from its existing locale, user, session,
token, and message dependencies. Synchronize the ref to the memoized payload in
a `useEffect`, preserving the current payload fields and allowing the existing
proxy handshake to read the committed value.

Source: Linters/SAST tools

src/app/crisp-proxy/page.tsx (1)

122-126: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Consider storing a digest instead of the raw token id.

crisp_last_token_id holds the Crisp session-continuity token, which CrispInitPayload documents as a bearer credential. The code needs equality comparison only, not the value itself. Storing a digest would remove the credential from localStorage while keeping the identity-change detection at line 56.

Note that the static analysis advice to use an HttpOnly cookie does not apply here. The comparison runs entirely in the iframe with no server involved, and the parent already derives the token client-side. The residual risk is therefore low, so treat this as a hardening step rather than a blocker.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/crisp-proxy/page.tsx` around lines 122 - 126, Update the localStorage
persistence and corresponding comparison for crisp_last_token_id to use a
one-way digest of the Crisp token rather than the raw token value, while
preserving identity-change detection. Reuse the same deterministic digest
operation when reading and writing so existing-token comparisons remain
consistent, and keep the existing storage error handling unchanged.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/crisp-proxy/page.tsx`:
- Around line 154-157: Update the watchdog failure branch near the CRISP_FAILED
notification to call clearInterval(requestTimer) before reporting failure,
ensuring the init-request loop stops when the parent does not respond. Keep the
existing successful-init and direct-visit interval behavior unchanged.

In `@src/components/Global/SupportDrawer/index.tsx`:
- Around line 279-283: Update the iframe key in the SupportDrawer render path to
include the current locale alongside iframeKey, crispTokenId, and
prefilledMessage, ensuring locale changes remount the proxy iframe and refresh
its Crisp payload.

---

Nitpick comments:
In `@src/app/crisp-proxy/page.tsx`:
- Around line 122-126: Update the localStorage persistence and corresponding
comparison for crisp_last_token_id to use a one-way digest of the Crisp token
rather than the raw token value, while preserving identity-change detection.
Reuse the same deterministic digest operation when reading and writing so
existing-token comparisons remain consistent, and keep the existing storage
error handling unchanged.

In `@src/components/Global/SupportDrawer/index.tsx`:
- Around line 47-66: Move the `initPayloadRef.current` assignment out of the
render body in `SupportDrawer` and compute the payload with `useMemo` from its
existing locale, user, session, token, and message dependencies. Synchronize the
ref to the memoized payload in a `useEffect`, preserving the current payload
fields and allowing the existing proxy handshake to read the committed value.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e7c6dce6-be0f-49c0-bf9b-db83848df5f7

📥 Commits

Reviewing files that changed from the base of the PR and between bfdb460 and 4e6237c.

📒 Files selected for processing (6)
  • src/app/crisp-proxy/page.tsx
  • src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx
  • src/components/Global/SupportDrawer/index.tsx
  • src/constants/crisp.ts
  • src/hooks/useCrispProxyUrl.ts
  • src/types/global.d.ts
💤 Files with no reviewable changes (1)
  • src/hooks/useCrispProxyUrl.ts

Comment thread src/app/crisp-proxy/page.tsx
Comment thread src/components/Global/SupportDrawer/index.tsx Outdated
…, harden handshake

/code-review findings: the handshake was one-shot, so identity fields
resolving after boot (email/name during onboarding) or a new prefill never
reached Crisp — the old URL transport remounted on any change. The parent
now re-sends the payload when it changes and the proxy applies it live;
token/locale changes still remount via the iframe key.

Also: reuse setCrispUserData (util was the canonical setter; the payload
now carries CrispUserData whole), shared handshake message constants,
watchdog clears the 250ms request loop on failure, payload ref written in
an effect instead of during render.
@kushagrasarathe

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/Global/SupportDrawer/index.tsx`:
- Around line 174-180: Restrict the CRISP_PROXY_REQUEST_INIT_MSG handling in the
SupportDrawer message listener to requests whose event.source exactly matches
iframeRef.current?.contentWindow. Only post CRISP_PROXY_INIT_MSG with
initPayloadRef.current after this source check, while preserving the existing
origin and message-type validation.
- Around line 281-286: Update the iframe remount flow around the key using
crispTokenId and crispLocale so token or locale changes reset both isCrispReady
and isCrispFailed before the new proxy loads. Preserve the existing status
handling for non-remount updates, ensuring the loader remains visible until the
replacement iframe reports its status.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 430d45a9-1547-4a6f-a2ff-d70d257bdea8

📥 Commits

Reviewing files that changed from the base of the PR and between 4e6237c and 1a29be3.

📒 Files selected for processing (4)
  • src/app/crisp-proxy/page.tsx
  • src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx
  • src/components/Global/SupportDrawer/index.tsx
  • src/constants/crisp.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/Global/SupportDrawer/tests/SupportDrawer.test.tsx
  • src/app/crisp-proxy/page.tsx

Comment thread src/components/Global/SupportDrawer/index.tsx Outdated
Comment thread src/components/Global/SupportDrawer/index.tsx
…/locale remount

CodeRabbit round 2: gate CRISP_PROXY_INIT replies on event.source matching
our iframe's contentWindow so no other same-origin frame can pull the token
and user data; clear isCrispReady/isCrispFailed when a token or locale
change swaps the iframe, so the loader shows until the new proxy reports.
@kushagrasarathe

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kushagrasarathe
kushagrasarathe changed the base branch from hotfix/crisp-token-server-side to main August 11, 2026 16:17
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7125 → 7119.83 (-5.17)
Findings: -2 net (+17 new, -19 resolved)

🆕 New findings (17)

  • critical complexity — src/components/Global/SupportDrawer/index.tsx — CC 58, MI 60.86, SLOC 173
  • high complexity — src/app/crisp-proxy/page.tsx — CC 41, MI 60.18, SLOC 140
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:26 — SupportDrawer: MDD 89.4 (uses across many lines from declarations)
  • medium high-mdd — src/app/crisp-proxy/page.tsx:104 — CrispProxyPage: MDD 35.8 (uses across many lines from declarations)
  • medium high-mdd — src/app/crisp-proxy/page.tsx:105 — : MDD 35.8 (uses across many lines from declarations)
  • medium high-dlt — src/components/Global/SupportDrawer/index.tsx:26 — SupportDrawer: DLT 30 (calls 30 distinct functions — high context load)
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:177 — : MDD 22.5 (uses across many lines from declarations)
  • medium method-complexity — src/components/Global/SupportDrawer/index.tsx:26 — CC 16 SLOC 85
  • medium react-effect-derives-state — src/app/crisp-proxy/page.tsx:105 — useEffect with empty deps + setState — derived state anti-pattern
  • medium react-direct-dom — src/app/crisp-proxy/page.tsx:95 — direct DOM: document.createElement
  • medium react-effect-derives-state — src/components/Global/SupportDrawer/index.tsx:86 — small useEffect that only sets state from deps
  • medium react-effect-derives-state — src/components/Global/SupportDrawer/index.tsx:98 — small useEffect that only sets state from deps
  • medium react-effect-derives-state — src/components/Global/SupportDrawer/index.tsx:177 — useEffect with empty deps + setState — derived state anti-pattern
  • low high-dlt — src/app/crisp-proxy/page.tsx:104 — CrispProxyPage: DLT 17 (calls 17 distinct functions — high context load)
  • low high-dlt — src/app/crisp-proxy/page.tsx:105 — : DLT 16 (calls 16 distinct functions — high context load)
  • low high-mdd — src/app/crisp-proxy/page.tsx:44 — bootCrisp: MDD 13.9 (uses across many lines from declarations)
  • low missing-return-type — src/app/crisp-proxy/page.tsx:104 — CrispProxyPage: exported fn missing return type annotation

✅ Resolved (19)

  • src/components/Global/SupportDrawer/index.tsx — CC 53, MI 61.22, SLOC 146
  • src/app/crisp-proxy/page.tsx — CC 41, MI 61.23, SLOC 120
  • src/components/Global/SupportDrawer/index.tsx:20 — SupportDrawer: MDD 73.8 (uses across many lines from declarations)
  • src/app/crisp-proxy/page.tsx:21 — : MDD 40.1 (uses across many lines from declarations)
  • src/app/crisp-proxy/page.tsx:18 — CrispProxyContent: MDD 38.7 (uses across many lines from declarations)
  • src/hooks/useCrispProxyUrl.ts:27 — useCrispProxyUrl: MDD 29.8 (uses across many lines from declarations)
  • src/hooks/useCrispProxyUrl.ts — CC 26, MI 55.96, SLOC 37
  • src/hooks/useCrispProxyUrl.ts:29 — CC 24 SLOC 26
  • src/app/crisp-proxy/page.tsx:64 — CC 16 SLOC 34
  • src/components/Global/SupportDrawer/index.tsx:20 — CC 16 SLOC 69
  • src/components/Global/SupportDrawer/index.tsx:50 — small useEffect that only sets state from deps
  • src/components/Global/SupportDrawer/index.tsx:132 — useEffect with empty deps + setState — derived state anti-pattern
  • src/hooks/useCrispProxyUrl.ts:1 — Hooks used without use client directive
  • src/components/Global/SupportDrawer/index.tsx:20 — SupportDrawer: DLT 29 (calls 29 distinct functions — high context load)
  • src/app/crisp-proxy/page.tsx:18 — CrispProxyContent: DLT 21 (calls 21 distinct functions — high context load)
  • src/app/crisp-proxy/page.tsx:21 — : DLT 19 (calls 19 distinct functions — high context load)
  • src/hooks/useCrispProxyUrl.ts:29 — : MDD 16.0 (uses across many lines from declarations)
  • src/components/Global/SupportDrawer/index.tsx:132 — : MDD 11.5 (uses across many lines from declarations)
  • src/app/crisp-proxy/page.tsx:214 — CrispProxyPage: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/constants/crisp.ts 1.5 3.8 +2.4
src/app/crisp-proxy/page.tsx 9.1 10.9 +1.8
src/components/Global/SupportDrawer/index.tsx 11.1 12.3 +1.2
src/hooks/useCrispProxyUrl.ts 10.6 0.0 -10.6

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2920 ran, 0 failed, 0 skipped, 51.8s

📊 Coverage (unit)

metric %
statements 66.2%
branches 51.2%
functions 56.3%
lines 67.0%
⏱ 10 slowest test cases
time test
3.9s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.1s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.5s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.4s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.3s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
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/hooks/__tests__/useCrispTokenId.test.ts › retries then stays undefined when the endpoint keeps failing (no fallback token)
0.3s src/utils/__tests__/auth-token.test.ts › returns the token hydrated from Preferences after authReady
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@kushagrasarathe
kushagrasarathe marked this pull request as ready for review August 11, 2026 16:39
@kushagrasarathe
kushagrasarathe requested review from Hugo0 and jjramirezn and removed request for Hugo0 August 11, 2026 16:39
Comment thread src/components/Global/SupportDrawer/index.tsx
Jota's review: a background user refresh re-fired the update effect and
setCrispUserData unconditionally re-pushed message:text, overwriting
whatever the user was typing in the composer. Prefill now applies at boot
and, on updates, only when its value actually changed (a new support entry
point) — metadata refreshes never touch the composer.
@kushagrasarathe

Copy link
Copy Markdown
Contributor Author

@jjramirezn addressed your review in 7816e11 — prefill is now applied at boot only; live updates re-push message:text only when the prefill value actually changed (new support entry point), so a background user refresh can no longer overwrite in-progress typing. Thread replied + resolved, CI green. Re-requested your review.

@jjramirezn
jjramirezn merged commit f29b325 into main Aug 12, 2026
26 checks passed
innolope-dev added a commit that referenced this pull request Aug 17, 2026
main moved the Crisp proxy off the URL transport onto a postMessage
handshake (PR #2669, useCrispProxyUrl deleted) and routes the iframe
through setCrispUserData, so the verification fields this branch added
to crisp-proxy/page.tsx and useCrispProxyUrl are now duplicated by the
utils/crisp.ts mapping, which survives the merge unchanged.
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