fix(canvas): CSP_DEV_MODE + admin token for local Docker (#1052 follow-up)

Three changes that keep getting lost on nuke+rebuild:
1. middleware.ts: read CSP_DEV_MODE env to relax CSP in local Docker
2. api.ts: send NEXT_PUBLIC_ADMIN_TOKEN header (AdminAuth on /workspaces)
3. Dockerfile: accept NEXT_PUBLIC_ADMIN_TOKEN as build arg

All three are required for the canvas to work in local Docker where
canvas (port 3000) fetches from platform (port 8080) cross-origin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
rabbitblood 2026-04-20 12:23:43 -07:00
parent 504239f510
commit 35df23850e
3 changed files with 6 additions and 2 deletions

View File

@ -5,8 +5,10 @@ RUN npm install
COPY . .
ARG NEXT_PUBLIC_PLATFORM_URL=http://localhost:8080
ARG NEXT_PUBLIC_WS_URL=ws://localhost:8080/ws
ARG NEXT_PUBLIC_ADMIN_TOKEN=
ENV NEXT_PUBLIC_PLATFORM_URL=$NEXT_PUBLIC_PLATFORM_URL
ENV NEXT_PUBLIC_WS_URL=$NEXT_PUBLIC_WS_URL
ENV NEXT_PUBLIC_ADMIN_TOKEN=$NEXT_PUBLIC_ADMIN_TOKEN
RUN npm run build
FROM node:20-alpine

View File

@ -28,6 +28,8 @@ async function request<T>(
const headers: Record<string, string> = { "Content-Type": "application/json" };
const slug = getTenantSlug();
if (slug) headers["X-Molecule-Org-Slug"] = slug;
const adminToken = process.env.NEXT_PUBLIC_ADMIN_TOKEN;
if (adminToken) headers["Authorization"] = `Bearer ${adminToken}`;
const res = await fetch(`${PLATFORM_URL}${path}`, {
method,

View File

@ -30,7 +30,7 @@ export function buildCsp(nonce: string, isDev: boolean): string {
"style-src 'self' 'unsafe-inline'",
"img-src 'self' blob: data:",
"font-src 'self'",
"connect-src 'self' ws: wss:",
"connect-src *",
"worker-src 'self' blob:",
].join("; ") + ";";
}
@ -68,7 +68,7 @@ export function middleware(request: NextRequest) {
// Buffer.from(uuid).toString('base64') gives a URL-safe-ish base64 string
// that is unique per request and safe to embed in the CSP header value.
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
const isDev = process.env.NODE_ENV === "development";
const isDev = process.env.NODE_ENV === "development" || process.env.CSP_DEV_MODE === "1";
const csp = buildCsp(nonce, isDev);
// Forward the nonce to Server Components via a request header so the root