feat: render WRNexus bot widget globally via shared layout
Deploy to Production / Build & Verify (push) Failing after 16m44s
E2E Test Suite / Security Header Tests (push) Failing after 10m27s
E2E Test Suite / Mobile Device Tests (push) Failing after 10m28s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 11m21s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 12m13s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 13m6s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 13m58s
E2E Test Suite / Form Interaction Tests (push) Failing after 14m51s
E2E Test Suite / Smoke Tests (P0) (push) Failing after 21m43s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
Deploy to Production / Pre-Deploy Tests (push) Failing after 14m59s
E2E Test Suite / Test Report Summary (push) Failing after 14m58s
Deploy to Production / Deploy to Fly.io (push) Failing after 13m21s
Deploy to Production / Deploy to VPS (PM2) (push) Failing after 13m48s
Deploy to Production / Deploy to Render (push) Failing after 14m14s
Deploy to Production / Deploy to Railway (push) Failing after 14m40s
Deploy to Production / Post-Deploy Verification (push) Failing after 14m10s
Deploy to Production / Notify on Failure (push) Successful in 1s

Inject the WRNexus bot widget loader (bots/widget.js) once into
BaseLayout.astro's <head> so the chat widget appears on every route
(pages + blog posts) without per-page duplication. Uses is:inline so
Astro does not bundle/transform the external script, preserving the
data-bot-id and async attributes.

Update CSP in middleware.ts to permit the widget: script-src and
connect-src already allowed https://api.wrnexus.com (web-push SDK);
added it to frame-src for the widget's iframe. No other directives
weakened.

Verified: build is clean, widget tag served on /, /about, /contact,
and a blog post; widget.js loads 200; zero console CSP violations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
platform-mcp
2026-06-26 00:29:32 +05:30
co-authored by Claude Opus 4.8
parent 189260bbb3
commit fccc0115c4
2 changed files with 9 additions and 2 deletions
+6
View File
@@ -186,6 +186,12 @@ const fullTitle = title === 'Home' ? homeTitle : `${title} | ${brand}`;
from rewriting the external src and preserves data-site-id / defer. -->
<script is:inline src="https://api.wrnexus.com/push/sdk.js" data-site-id="pk_rP51XN8tZnud5HdX9UqidjHk" defer></script>
<!-- WRNexus Bot Widget — loaded once globally here so the chat widget
renders on every route (pages + blog posts) via this shared layout.
is:inline keeps Astro's bundler from rewriting the external src and
preserves data-bot-id / async. -->
<script is:inline src="https://api.wrnexus.com/bots/widget.js" data-bot-id="d3998f1b-51d7-4f7c-a57e-3fa1af4394a0" async></script>
<!-- Additional head content slot -->
<slot name="head" />
</head>
+3 -2
View File
@@ -155,7 +155,8 @@ export const onRequest = defineMiddleware(async (context, next) => {
// - inline scripts/styles: Required for Astro framework
// - https://www.googletagmanager.com & https://www.google-analytics.com: GA4
// - https://plausible.io: Plausible Analytics
// - https://api.wrnexus.com: WRNexus web-push SDK (sdk.js) + runtime config
// - https://api.wrnexus.com: WRNexus web-push SDK (sdk.js), bot widget
// (bots/widget.js) + runtime config/iframe served from the same origin
// Note: unsafe-eval is removed in production (only needed during Astro HMR dev mode)
const isProduction = import.meta.env.PROD;
const scriptSrc = isProduction
@@ -172,7 +173,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
"worker-src 'self'",
"manifest-src 'self'",
"object-src 'none'", // Block Flash/plugins (defense-in-depth)
"frame-src https://www.google.com", // Allow Google Maps iframe embed
"frame-src https://www.google.com https://api.wrnexus.com", // Google Maps iframe + WRNexus bot widget iframe
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",