PR-3 follow-up. Live smoke surfaced that the @sentry/vue SDK was running correctly and emitting events, but Crewli's strict connect-src directive blocked every POST at the browser layer. No fallback — events evaporated silently with a CSP-violation log in DevTools console only. Updated locations (audited the CSP surface; only two locations actually need the whitelist): - apps/app/index.html — dev meta CSP, adds http://localhost:8200 to connect-src so local dev hits the docker-compose GlitchTip stack. - deploy/nginx/csp-spa.conf — prod organizer SPA CSP, adds https://monitoring.hausdesign.nl to BOTH the report-only and enforce add_header lines so a future flip between modes can't silently break observability. NOT updated (deviation from prompt): - api/config/security.php — the API CSP is `default-src 'none'; frame-ancestors 'none'` for JSON responses. Browsers don't enforce connect-src on JSON contexts (no document, no fetch origin). Adding connect-src would be semantically a no-op and confuse the deny-by- default policy. Regression guard: tests/Feature/Security/CspConnectsToObservabilityTest. Reads both the dev meta tag and the prod nginx conf directly (the SPA's CSP is not Laravel-served, so $this->get() can't reach it). Apply-with- revert verified: stashing both fixes makes both cases fail with a clear "Refused to connect because it violates the following CSP directive" hint; popping the stash restores green. SECURITY_AUDIT.md A13-9 updated with a WS-7 follow-up note documenting the GlitchTip whitelist as an explicit security control: outgoing observability traffic restricted to a single known host. Test count 1549 to 1551. Larastan + Pint clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
59 lines
2.9 KiB
HTML
59 lines
2.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<link rel="icon" href="/favicon.ico" />
|
|
<meta name="robots" content="noindex, nofollow" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Crewli — Organizer</title>
|
|
<!-- CSP for local development — mirrors production Nginx policy.
|
|
connect-src includes http://localhost:8200 so the @sentry/vue SDK
|
|
can POST events to the local GlitchTip stack (RFC-WS-7 §3.5).
|
|
Without this, the browser silently blocks every Sentry event. -->
|
|
<meta http-equiv="Content-Security-Policy"
|
|
content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' http://localhost:8000 ws://localhost:5174 http://localhost:8200; form-action 'self'; base-uri 'self'">
|
|
<link rel="stylesheet" type="text/css" href="/loader.css" />
|
|
</head>
|
|
|
|
<body>
|
|
<div id="app">
|
|
<div id="loading-bg">
|
|
<div class="loading-logo">
|
|
<!-- SVG Logo -->
|
|
<svg width="86" height="48" viewBox="0 0 34 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
d="M0.00183571 0.3125V7.59485C0.00183571 7.59485 -0.141502 9.88783 2.10473 11.8288L14.5469 23.6837L21.0172 23.6005L19.9794 10.8126L17.5261 7.93369L9.81536 0.3125H0.00183571Z"
|
|
fill="var(--initial-loader-color)" />
|
|
<path opacity="0.06" fill-rule="evenodd" clip-rule="evenodd"
|
|
d="M8.17969 17.7762L13.3027 3.75173L17.589 8.02192L8.17969 17.7762Z" fill="#161616" />
|
|
<path opacity="0.06" fill-rule="evenodd" clip-rule="evenodd"
|
|
d="M8.58203 17.2248L14.8129 5.24231L17.6211 8.05247L8.58203 17.2248Z" fill="#161616" />
|
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
d="M8.25781 17.6914L25.1339 0.3125H33.9991V7.62657C33.9991 7.62657 33.8144 10.0645 32.5743 11.3686L21.0179 23.6875H14.5487L8.25781 17.6914Z"
|
|
fill="var(--initial-loader-color)" />
|
|
</svg>
|
|
</div>
|
|
<div class=" loading">
|
|
<div class="effect-1 effects"></div>
|
|
<div class="effect-2 effects"></div>
|
|
<div class="effect-3 effects"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script type="module" src="/src/main.ts"></script>
|
|
<script>
|
|
const loaderColor = localStorage.getItem('vuexy-initial-loader-bg') || '#FFFFFF'
|
|
const primaryColor = localStorage.getItem('vuexy-initial-loader-color') || '#0D9394'
|
|
|
|
if (loaderColor)
|
|
document.documentElement.style.setProperty('--initial-loader-bg', loaderColor)
|
|
if (loaderColor)
|
|
document.documentElement.style.setProperty('--initial-loader-bg', loaderColor)
|
|
|
|
if (primaryColor)
|
|
document.documentElement.style.setProperty('--initial-loader-color', primaryColor)
|
|
</script>
|
|
</body>
|
|
|
|
</html> |