server {
    listen 8080;
    server_name _;
    root /usr/share/nginx/html;
    index index.html;

    absolute_redirect off;
    port_in_redirect off;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Gzip
    gzip on;
    gzip_vary on;
    gzip_min_length 256;
    gzip_types text/html text/css text/javascript application/javascript application/json image/svg+xml;

    # Proxy API calls to catalyst-api service (K8s internal)
    # SSE support: disable buffering on log stream endpoint
    resolver 10.43.0.10 valid=30s;
    set $api_upstream http://catalyst-api.catalyst.svc.cluster.local:8080;

    location /api/ {
        proxy_pass $api_upstream;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection '';

        # SSE streaming
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
        chunked_transfer_encoding on;
        add_header X-Accel-Buffering no;
    }

    # Cache static assets
    location ~* \.(js|css|png|jpg|svg|woff2|ico)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # SPA fallback — all routes serve index.html.
    # Vite is built with base: '/' so assets live at /assets/*.
    # On contabo (console.openova.io/sovereign/*), Traefik's strip-sovereign
    # Middleware rewrites /sovereign/assets/foo → /assets/foo before the
    # request reaches nginx. On Sovereigns (console.<sov>/), the HTTPRoute
    # passes through to / directly. Both paths resolve to /assets/* here.
    # React routes (/dashboard, /wizard, etc.) fall through to /index.html
    # and are handled client-side (issue #596).
    location / {
        try_files $uri /index.html;
    }

    # Health check (used by K8s probes)
    location = /healthz {
        access_log off;
        return 200 'ok';
        add_header Content-Type text/plain;
    }
}
