Web-Anwendung: Design-Tokens, Texte, Gesundheitsendpunkt
Design-Tokens aus docs/10-design-system.md als CSS-Variablen: Grundpalette, die sechs Klassifizierungsfarben, Eckenradius durchgehend 2 px, keine Schatten ausser dem Fokusring. Der Schwärzungsbalken mit dem einmaligen Durchwischen respektiert prefers-reduced-motion. Vier Tests halten die Tokens gegen das Dokument. IBM Plex selbst gehostet als woff2, latin und latin-ext getrennt über unicode-range, font-display: swap, immutable-Cache. Alle Oberflächentexte in lib/i18n/de.ts. Ein Test durchsucht app/ und components/ nach Umlauten im JSX und schlägt fehl, wenn dort deutscher Text steht. Er hat beim ersten Lauf gleich einen Verstoss gefunden. /api/health prüft Datenbank, Discord-Gateway und ClamAV. Die Gesamtbewertung fällt nur auf "down", wenn die Datenbank weg ist: die anderen Dienste haben eigene Healthchecks im Stack, und ein ausgefallener Virenscanner soll nicht den Web-Container als tot markieren. Strikte CSP mit Nonce, kein unsafe-inline für Skripte. Die erste Route liegt bei 100 kB JavaScript nach Kompression, Budget sind 120 kB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
51984f17d4
commit
6b0cd331bb
@@ -0,0 +1,51 @@
|
||||
import { NextResponse, type NextRequest } from 'next/server'
|
||||
|
||||
/**
|
||||
* Strikte CSP mit Nonce. Kein 'unsafe-inline' fuer Skripte, siehe
|
||||
* docs/07-dateien-und-sicherheit.md. Next.js liest die CSP aus dem Request und
|
||||
* haengt den Nonce an seine eigenen Skript-Tags.
|
||||
*
|
||||
* Im Dev-Server braucht der React Refresh Runtime 'unsafe-eval'.
|
||||
*/
|
||||
export function middleware(request: NextRequest): NextResponse {
|
||||
const nonce = btoa(crypto.randomUUID())
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
const csp = [
|
||||
`default-src 'self'`,
|
||||
`script-src 'self' 'nonce-${nonce}' 'strict-dynamic'${isDev ? " 'unsafe-eval'" : ''}`,
|
||||
// Tailwind erzeugt zur Laufzeit keine Styles, aber Next setzt inline-Styles
|
||||
// fuer den Bildplatzhalter. Style-Nonces unterstuetzt Next nicht.
|
||||
`style-src 'self' 'unsafe-inline'`,
|
||||
`img-src 'self' blob: data:`,
|
||||
`font-src 'self'`,
|
||||
// Der SSE-Endpunkt laeuft ueber dieselbe Herkunft.
|
||||
`connect-src 'self'`,
|
||||
`object-src 'none'`,
|
||||
`base-uri 'none'`,
|
||||
`form-action 'self'`,
|
||||
`frame-ancestors 'none'`,
|
||||
`upgrade-insecure-requests`,
|
||||
].join('; ')
|
||||
|
||||
const headers = new Headers(request.headers)
|
||||
headers.set('x-nonce', nonce)
|
||||
headers.set('content-security-policy', csp)
|
||||
|
||||
const response = NextResponse.next({ request: { headers } })
|
||||
response.headers.set('content-security-policy', csp)
|
||||
return response
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
// Statische Assets und Bild-Optimierung brauchen keine CSP-Berechnung.
|
||||
{
|
||||
source: '/((?!_next/static|_next/image|fonts|favicon.ico).*)',
|
||||
missing: [
|
||||
{ type: 'header', key: 'next-router-prefetch' },
|
||||
{ type: 'header', key: 'purpose', value: 'prefetch' },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user