Skip to content

add Freshdesk support widget integration - #709

Open
girts512 wants to merge 2 commits into
developmentfrom
feature/freshdesk-support-tickets
Open

add Freshdesk support widget integration#709
girts512 wants to merge 2 commits into
developmentfrom
feature/freshdesk-support-tickets

Conversation

@girts512

@girts512 girts512 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Embed the official Freshdesk webchat loader as a nonce-carrying inline script (bodyClose) in nuxt.config.ts. Allow euler.freshdesk.com in the CSP (connect/style/font/frame/media-src) — the parent page loads widget.js and widget.css directly; the chat iframe is cross-origin so its internals run under Freshdesk's own CSP. object-src stays 'none'. Hide the widget (#fd_frame) on the onboarding page via a root class toggled in app.vue. Add a regression test for the connect-src entry.

Summary by CodeRabbit

  • New Features

    • Added a support chat widget that loads in the browser and appears across the app.
    • Kept the widget hidden on the onboarding screen for a cleaner first-time experience.
  • Bug Fixes

    • Improved page styling so the support widget is properly hidden when needed.
    • Updated site security settings to allow the chat widget to load reliably.

Embed the official Freshdesk webchat loader as a nonce-carrying inline
script (bodyClose) in nuxt.config.ts. Allow euler.freshdesk.com in the
CSP (connect/style/font/frame/media-src) — the parent page loads
widget.js and widget.css directly; the chat iframe is cross-origin so
its internals run under Freshdesk's own CSP. object-src stays 'none'.
Hide the widget (#fd_frame) on the onboarding page via a root class
toggled in app.vue. Add a regression test for the connect-src entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-709 July 8, 2026 13:21 Destroyed
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@girts512, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d8da12ad-a495-43bc-8c74-db568459534d

📥 Commits

Reviewing files that changed from the base of the PR and between de1d382 and 2774f6b.

📒 Files selected for processing (1)
  • assets/styles/main.scss
📝 Walkthrough

Walkthrough

This PR integrates a Freshdesk support widget: injects a widget loader script in Nuxt config, adds a route-based watcher in app.vue to hide the widget on the onboarding screen via a CSS class, adds corresponding CSS, and expands CSP directives to allow Freshdesk resources, with a test.

Changes

Freshdesk Widget

Layer / File(s) Summary
Widget loader script and injection
nuxt.config.ts
Adds freshdeskWidgetScript constant with async Freshdesk webchat loader logic and injects it into app.head.script.
Route-based visibility toggle and hiding CSS
app.vue, assets/styles/main.scss
Adds a client watcher toggling support-widget-hidden class on route.name change to hide widget on onboarding, and a CSS rule hiding #fd_frame when that class is set.
CSP allowlisting for Freshdesk resources
server/plugins/csp.ts, tests/server/security.test.ts
Expands connect-src, style-src, font-src, frame-src, and media-src directives to permit Freshdesk domains/assets, and adds a test verifying connect-src includes the Freshdesk endpoint.

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

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant AppVue as app.vue
  participant DOM as document.documentElement
  participant Freshdesk as Freshdesk widget.js

  Browser->>AppVue: route.name change
  AppVue->>DOM: toggle support-widget-hidden class
  Browser->>Browser: window load event
  Browser->>Freshdesk: insert widget.js script tag
  Freshdesk->>Freshdesk: fdWidget.init(token, host, widgetId)
  Freshdesk-->>DOM: render `#fd_frame`
  DOM-->>Browser: CSS hides `#fd_frame` if class present
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: integrating the Freshdesk support widget into the app.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/freshdesk-support-tickets

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
server/plugins/csp.ts (1)

163-167: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Redundant entry in connect-src.

https://euler.freshdesk.com is already covered by the https://*.freshdesk.com wildcard on the next line. The explicit entry can be removed for clarity, though it's harmless.

♻️ Optional cleanup
   // Freshdesk support widget (loaded from euler.freshdesk.com, see
   // freshdesk-widget script in nuxt.config.ts)
-  'https://euler.freshdesk.com',
   'https://*.freshdesk.com',
   'wss://*.freshdesk.com',
🤖 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 `@server/plugins/csp.ts` around lines 163 - 167, Remove the redundant
`https://euler.freshdesk.com` entry from the `connect-src` list in
`server/plugins/csp.ts`, since the `freshdesk` wildcard already covers it. Keep
the remaining Freshdesk sources (`https://*.freshdesk.com` and
`wss://*.freshdesk.com`) unchanged, and update the surrounding comment if needed
so the `connect-src` block in the CSP config remains clear and minimal.
🤖 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.

Nitpick comments:
In `@server/plugins/csp.ts`:
- Around line 163-167: Remove the redundant `https://euler.freshdesk.com` entry
from the `connect-src` list in `server/plugins/csp.ts`, since the `freshdesk`
wildcard already covers it. Keep the remaining Freshdesk sources
(`https://*.freshdesk.com` and `wss://*.freshdesk.com`) unchanged, and update
the surrounding comment if needed so the `connect-src` block in the CSP config
remains clear and minimal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 041a2451-5aaf-4ed8-8e09-3a753143be09

📥 Commits

Reviewing files that changed from the base of the PR and between 76b1dec and de1d382.

📒 Files selected for processing (5)
  • app.vue
  • assets/styles/main.scss
  • nuxt.config.ts
  • server/plugins/csp.ts
  • tests/server/security.test.ts

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

Leonard review — PR #709

Verdict: changes requested — one privacy/UX blocker around the onboarding page.

What changed: the PR adds a global Freshdesk loader in nuxt.config.ts, widens CSP for Freshdesk widget traffic, hides #fd_frame on onboarding via a root class, and adds a CSP regression test.

Validation performed on head de1d382632942314b506a6a5f8b33b14c096ece1:

  • npm run test:run -- tests/server/security.test.ts — passed, 21 tests
  • npm run typecheck — passed
  • npm run build — passed, with existing chunk/Rollup warnings only
  • Direct fetch of https://euler.freshdesk.com/webchat/js/widget.js — HTTP 200, text/javascript
  • Headed/Xvfb Playwright smoke on the PR preview:
    • /onboarding?network=1 desktop: onboarding rendered, support-widget-hidden was true, #fd_frame display was none
    • /lend?network=1 desktop and mobile: Lend page rendered and support widget was visible
    • wallet/signing smoke: not run; PR does not touch transaction construction

Screenshot evidence:

Scalability / maintainability hygiene pass: there is only one Freshdesk integration surface and the route visibility logic is centralized in app.vue plus one global stylesheet rule, so I did not find sibling route/component duplication. The reusable gap is test coverage breadth: the added test locks only connect-src, while this feature also depends on frame-src, style-src, font-src, media-src, nonce injection, and onboarding gating. I am not making that a separate blocker because the runtime smoke covered the current path, but those are the seams most likely to regress.

Bot feedback: CodeRabbit’s redundancy nit about https://euler.freshdesk.com being covered by https://*.freshdesk.com is directionally correct but low impact; it is not the material issue here.

See inline comment for the blocker.

Comment thread nuxt.config.ts
tagPriority: 'critical',
},
{
id: 'freshdesk-widget',

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.

This hides the Freshdesk frame on onboarding only after the global loader has already run. In the PR preview, /onboarding?network=1 had support-widget-hidden === true and #fd_frame { display: none }, but the page still loaded widget.js, created the Freshdesk iframe, and called Freshdesk visitor/ticket/token/event endpoints before the user left the connect-wallet onboarding screen.

That makes the onboarding hide visual rather than operational: a hidden third-party support widget still sends the page/referrer and creates a Freshdesk visitor session. For this surface I think we should gate initialization itself — e.g. defer injecting/loading Freshdesk until onboarding is complete or the current route is not onboarding — rather than loading globally and hiding with CSS. If the intended policy is explicitly “load Freshdesk on onboarding but hide the button,” that privacy/UX decision should be documented, but the safer invariant is no third-party widget traffic while the widget is hidden on onboarding.

@railway-app

railway-app Bot commented Jul 8, 2026

Copy link
Copy Markdown

🚅 Deployed to the euler-lite-pr-709 environment in euler-lite(dev,PR previews)

Service Status Web Updated (UTC)
dev-build ✅ Success (View Logs) Web Jul 31, 2026 at 9:57 am

Browsers paint an opaque white canvas behind a cross-origin iframe when
the embedding page's color-scheme (dark) mismatches the iframe
document's (undeclared). Declare the widget iframe light to restore
its transparency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

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

Leonard review — PR #709

Verdict: changes requested — the Freshdesk widget is still initialized on onboarding while it is visually hidden.

Reviewed head: 2774f6b2ecaca410eb01e8d4fa362a49dccac3b9

What changed:

  • Adds a global Freshdesk loader script in nuxt.config.ts.
  • Widens CSP for Freshdesk script/widget traffic in server/plugins/csp.ts.
  • Adds a route-driven support-widget-hidden root class in app.vue and CSS in assets/styles/main.scss to hide #fd_frame on onboarding and fix the dark-theme iframe canvas.
  • Adds a focused CSP regression test for Freshdesk connect-src.

Blocking finding:

  • The onboarding suppression is visual only. On the PR preview, /onboarding?network=1 sets support-widget-hidden === true and #fd_frame { display: none }, but the global loader has already fetched Freshdesk, mounted the iframe, created a visitor session, and called ticket/token/event endpoints. That means the connect-wallet onboarding page still sends Freshdesk traffic even though the widget is hidden. The safer invariant is: if the widget is hidden on onboarding, initialization should also be deferred/gated until onboarding is complete or the current route is not onboarding. If the intended product/privacy policy is explicitly “load Freshdesk on onboarding but hide the launcher,” that should be stated deliberately; I would not let the CSS hide imply operational suppression.

Evidence:

Validation performed:

  • git diff --check origin/development...HEAD
  • npm run typecheck
  • npm run test:run -- tests/server/security.test.ts — 21 tests passed
  • npm run build — passed; only existing bundle/chunk-size style warnings
  • Headed Chromium/Xvfb browser smoke against the Railway PR preview:
    • desktop /onboarding?network=1: onboarding visible, Freshdesk button hidden, but #fd_frame exists and Freshdesk network requests occur
    • mobile /onboarding?network=1: same result
    • desktop /borrow?network=1: app route visible and Freshdesk launcher visible

Scalability / maintainability hygiene:

  • The route-level class is centralized in app.vue, so there is not a sibling route with a separate copy of the same hide logic.
  • The missing reusable boundary is the loader policy itself: the global inline script in nuxt.config.ts owns initialization while app.vue owns visibility. That split is what allowed hidden UI and third-party traffic to diverge. I would prefer a small shared client-side widget controller/composable, or equivalent route-aware loader gate, with a focused regression that asserts onboarding does not create #fd_frame or call Freshdesk.
  • The current unit test only locks connect-src; it does not cover the onboarding privacy/UX invariant.

Bot/reviewer feedback checked:

  • CodeRabbit’s Freshdesk connect-src redundancy note is low-value/non-blocking. The explicit https://euler.freshdesk.com entry is harmless beside the wildcard and is not the material risk here.

Smoke coverage: browser visual smoke + mobile smoke. Wallet/signing smoke not run; this PR changes a support widget/CSP path, not transaction construction.

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