Fundament: atomare Mandanten-Transaktionen, iframe-Vorschau, Uploads bis 25 MB, DSGVO-Felder
- db.ts: tenantTransaction() – atomar auch bei RLS_ENFORCED=true (AsyncLocalStorage bindet Operationen an eine craftvia_app-Transaktion, Kontext einmal gesetzt, verschachtelte Aufrufe treten bei, fremder Mandant wird abgewiesen) - services/context.ts: inTransaction(ctx, fn); imports/confirm.ts umgestellt - next.config.ts: EMBEDDABLE_FILE_ROUTES mit frame-ancestors 'self'/SAMEORIGIN (PDF-Vorschau Prüfmaske), proxyClientMaxBodySize 26mb (Import bis 25 MB) - test-rls-enforcement: RLS-URL-Default aus DATABASE_URL (Lane-DBs) - dsgvo/pii-fields: 26 Personenreferenzen des Craftvia-Domänenmodells - ARCHITEKTUR §4.8: Transaktions-, Header-, Upload-, Versions- und PII-Regeln - Test test-tenant-transaction (Commit/Rollback/Fremdmandant/Verschachtelung), grün im Owner- und im RLS-Modus Gate: tsc, lint, build, 31/31 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+21
-4
@@ -31,6 +31,13 @@ const csp = [
|
||||
"object-src 'none'",
|
||||
].join("; ");
|
||||
|
||||
// Same-origin embedding for inline document previews (PDF viewer in the import review
|
||||
// mask, document previews). Everything else stays frame-ancestors 'none' / DENY.
|
||||
const cspEmbeddable = csp.replace("frame-ancestors 'none'", "frame-ancestors 'self'");
|
||||
|
||||
// Routes that stream stored files and may be shown in a same-origin <iframe>.
|
||||
const EMBEDDABLE_FILE_ROUTES = ["/files/:path*", "/imports/:id/file"];
|
||||
|
||||
const securityHeaders = [
|
||||
{ key: "Content-Security-Policy", value: csp },
|
||||
// HSTS bewusst zusätzlich in der App (neben dem Coolify-/Traefik-Proxy).
|
||||
@@ -46,17 +53,27 @@ const securityHeaders = [
|
||||
const nextConfig: NextConfig = {
|
||||
// Standalone-Output für den Docker-Multi-Stage-Build (siehe Dockerfile)
|
||||
output: "standalone",
|
||||
experimental: {
|
||||
// Proxy (src/proxy.ts) buffers request bodies; the 10 MB default truncates uploads silently.
|
||||
// Largest allowed upload is 25 MB (PDF import) plus multipart overhead.
|
||||
proxyClientMaxBodySize: "26mb",
|
||||
},
|
||||
// i18n-Kataloge werden zur Laufzeit per fs geladen (src/i18n/request.ts) — für den
|
||||
// standalone-Output explizit mitkopieren.
|
||||
outputFileTracingIncludes: {
|
||||
"/*": ["./messages/**/*.json"],
|
||||
},
|
||||
async headers() {
|
||||
// Later entries override same-named headers of earlier matches (Next.js header semantics).
|
||||
return [
|
||||
{
|
||||
source: "/:path*",
|
||||
headers: securityHeaders,
|
||||
},
|
||||
{ source: "/:path*", headers: securityHeaders },
|
||||
...EMBEDDABLE_FILE_ROUTES.map((source) => ({
|
||||
source,
|
||||
headers: [
|
||||
{ key: "Content-Security-Policy", value: cspEmbeddable },
|
||||
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
|
||||
],
|
||||
})),
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user