limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_conn_zone $binary_remote_addr zone=per_client:10m;
limit_req_status 429;
limit_conn_status 429;
server_tokens off;

map $http_sec_fetch_site $cross_site_request {
    default 0;
    cross-site 1;
}

server {
    listen 80;
    server_name _;
    return 308 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name _;
    client_max_body_size 2m;
    client_body_timeout 15s;
    client_header_timeout 15s;
    keepalive_timeout 30s;
    send_timeout 30s;
    limit_conn per_client 30;

    ssl_certificate /run/tls/fullchain.pem;
    ssl_certificate_key /run/tls/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:HayvaTLS:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
    add_header Content-Security-Policy "default-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'; object-src 'none'; img-src 'self' data: blob:; connect-src 'self'; font-src 'self'; style-src 'self'; script-src 'self'" always;
    add_header X-Content-Type-Options nosniff always;
    add_header Referrer-Policy no-referrer always;
    add_header X-Frame-Options DENY always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Resource-Policy "same-origin" always;
    add_header X-Permitted-Cross-Domain-Policies "none" always;

    if ($cross_site_request) { return 403; }
    if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) { return 405; }

    location ~ ^/health/(database|redis|ai|browser|readiness)$ { return 404; }

    location = /health {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://core-api:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Request-ID $request_id;
        proxy_connect_timeout 5s;
        proxy_read_timeout 15s;
        proxy_send_timeout 15s;
        proxy_hide_header Server;
        proxy_hide_header X-Powered-By;
    }

    location = /api/v1/auth/login {
        limit_req zone=login burst=5 nodelay;
        proxy_pass http://core-api:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Request-ID $request_id;
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
        proxy_cookie_flags ~^ secure httponly samesite=strict;
        proxy_hide_header Server;
        proxy_hide_header X-Powered-By;
    }

    location ^~ /api/ {
        limit_req zone=api burst=40 nodelay;
        proxy_pass http://core-api:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Request-ID $request_id;
        proxy_connect_timeout 5s;
        proxy_read_timeout 120s;
        proxy_send_timeout 120s;
        proxy_cookie_flags ~^ secure httponly samesite=strict;
        proxy_hide_header Server;
        proxy_hide_header X-Powered-By;
    }

    location / {
        proxy_pass http://web:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_hide_header Server;
        proxy_hide_header X-Powered-By;
    }
}
