From 26d4e6361afd361cc10a2d9ab3ab832581a13cea Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 15 Apr 2026 04:27:09 +0200 Subject: [PATCH 1/2] feat(nginx): emit Content-Security-Policy from origin (csp-headers.conf) Include CSP in each location that sets Cache-Control so headers apply on HTML/static responses (nginx add_header inheritance rules). Used by Dockerfile-react / ghcr.io isaac-react-app-cs image builds. Made-with: Cursor --- Dockerfile-react | 1 + csp-headers.conf | 3 +++ nginx.conf | 5 +++++ 3 files changed, 9 insertions(+) create mode 100644 csp-headers.conf diff --git a/Dockerfile-react b/Dockerfile-react index 5ab4dde604..86e7529877 100644 --- a/Dockerfile-react +++ b/Dockerfile-react @@ -18,3 +18,4 @@ ARG BUILD_TARGET COPY --from=builder /build/$BUILD_TARGET/ /usr/share/nginx/html COPY nginx.conf /etc/nginx/nginx.conf +COPY csp-headers.conf /etc/nginx/csp-headers.conf diff --git a/csp-headers.conf b/csp-headers.conf new file mode 100644 index 0000000000..ae509ce6b8 --- /dev/null +++ b/csp-headers.conf @@ -0,0 +1,3 @@ +# Included from each location block that sets Cache-Control (nginx does not inherit +# add_header from http/server when a location defines its own add_header). +add_header Content-Security-Policy "default-src 'self' https://*.isaaccomputerscience.org; object-src 'none'; frame-src 'self' https://*.isaaccomputerscience.org https://www.youtube.com https://www.youtube-nocookie.com https://www.google.com https://www.gstatic.com https://fast.wistia.net; img-src 'self' data: https://cdn-cookieyes.com https://*.isaaccomputerscience.org https://*.google-analytics.com https://*.googletagmanager.com https://*.tile.openstreetmap.org https://developers.google.com https://i.ytimg.com/; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://*.isaaccomputerscience.org https://fonts.gstatic.com; connect-src 'self' wss://*.isaaccomputerscience.org https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com https://*.cookieyes.com https://cdn-cookieyes.com; script-src 'self' https://*.isaaccomputerscience.org https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com https://www.youtube-nocookie.com https://www.youtube.com https://www.google.com https://www.gstatic.com https://cdn-cookieyes.com https://fast.wistia.net https://embedwistia-a.akamaihd.net" always; diff --git a/nginx.conf b/nginx.conf index d755977e96..922ee8a487 100644 --- a/nginx.conf +++ b/nginx.conf @@ -50,12 +50,14 @@ http { location /assets { # Strongly cache these things for at least 30 days: add_header Cache-Control "public, max-age=2592000, no-transform"; + include /etc/nginx/csp-headers.conf; try_files $uri @default; } location /static { # Maybe also strongly cache these things for at least 30 days? add_header Cache-Control "public, max-age=2592000, no-transform"; + include /etc/nginx/csp-headers.conf; try_files $uri @default; } @@ -63,11 +65,13 @@ http { # Index pages, and also serves unknown URLs too from @default. # Do not allow caching of these index pages at all: add_header Cache-Control "no-cache, no-store, must-revalidate"; + include /etc/nginx/csp-headers.conf; try_files $uri @default; } location ~ ^/unsupported_browser.(html|js)$ { add_header Cache-Control "no-cache, no-store, must-revalidate"; + include /etc/nginx/csp-headers.conf; try_files $uri @default; } @@ -78,6 +82,7 @@ http { } # Allow caching, but require revalidation every time: add_header Cache-Control "no-cache, must-revalidate"; + include /etc/nginx/csp-headers.conf; try_files $uri @default; } From b007ffd4fb5c727c3b2dbb9dd02191735dcc253d Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 15 Apr 2026 05:12:44 +0200 Subject: [PATCH 2/2] fix: use staging API + isStaging for ALB shadow hostname (isaac-fe-alb-test) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same-origin /api on the FE pod serves the SPA, not the Java API—events requests failed then recovered when something else retried. Point API at STAGING_URL and allow CORS from the ALB test origin (infra follow-up). Made-with: Cursor --- src/app/services/constants.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/services/constants.ts b/src/app/services/constants.ts index 7e7bd8d2a4..e8d0445f85 100644 --- a/src/app/services/constants.ts +++ b/src/app/services/constants.ts @@ -40,9 +40,14 @@ if (document.location.hostname === "localhost") { apiPath = `${STAGING_URL}/api/any/api`; } else if (document.location.hostname.endsWith(".eu.ngrok.io")) { apiPath = "https://isaacscience.eu.ngrok.io/isaac-api/api"; +} else if (document.location.hostname === "isaac-fe-alb-test.development.isaaccomputerscience.org") { + // ALB shadow hostname serves only the FE; API stays on the main staging hosts (ingress-nginx /api rewrite). + apiPath = `${STAGING_URL}/api/${API_VERSION}/api`; } export const isStaging = - document.location.hostname.startsWith("staging.") || document.location.hostname.startsWith("www.staging."); + document.location.hostname.startsWith("staging.") || + document.location.hostname.startsWith("www.staging.") || + document.location.hostname === "isaac-fe-alb-test.development.isaaccomputerscience.org"; export const envSpecific = (live: L, staging: S, dev: D) => isStaging ? staging : process.env.NODE_ENV === "production" ? live : dev;