Files
petfeed/next.config.ts
T
admin b4a49f8ed3 fix: address findings from full security/functionality audit (Gitea #17)
Rate-limiting on messages.send, reports.create, reactions.toggle,
follows.create, reposts.create. Unique constraints on Report to stop
report-flooding. Mux webhook now fails hard in production without a
signing secret instead of skipping verification. Admin-panel outline
buttons fixed on 4 more pages (same white-on-dark bug as the Users page).
Timing-safe comparison for ADMIN_SECRET/CRON_SECRET. Fixed duplicate HSTS
header (Cloudflare's stronger one was being shadowed by the app's own).
tRPC now returns clean JSON 401s instead of HTML redirects when
unauthenticated, and no longer blocks public procedures for logged-out
visitors. 14 previously-silent catch blocks now log to GlitchTip.
invite/page.tsx and EmergencyVetSection.tsx fully localized (were 100%
hardcoded German). Stale TODO comments removed, auth.test.ts scaffold
rewritten to match the actual lazy-upsert pattern instead of a Clerk
webhook flow that was never built.
2026-08-13 12:42:49 +02:00

53 lines
1.8 KiB
TypeScript

import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
import { withSentryConfig } from "@sentry/nextjs";
const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts");
function getSupabaseHostname(): string {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
if (url) {
try { return new URL(url).hostname; } catch { /* fall through */ }
}
return "*.supabase.co";
}
const nextConfig: NextConfig = {
output: "standalone",
allowedDevOrigins: ["192.168.1.92"],
images: {
remotePatterns: [
{ protocol: "https", hostname: getSupabaseHostname() },
],
},
async headers() {
return [
{
source: "/(.*)",
headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
// HSTS intentionally NOT set here — Cloudflare (in front of the origin) already
// sends a stronger one (max-age=63072000; preload). Setting both resulted in two
// Strict-Transport-Security headers on every response; browsers only honor the
// first, so the app's weaker one was pure noise. If Cloudflare is ever removed
// from the path, re-add this header at the edge/proxy layer, not here.
],
},
];
},
};
export default withSentryConfig(withNextIntl(nextConfig), {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
silent: true,
// No auth token configured on this self-hosted deploy yet — skip
// source-map upload rather than failing the Docker build.
sourcemaps: { disable: !process.env.SENTRY_AUTH_TOKEN },
disableLogger: true,
});