# HTTPS with automatic Let's Encrypt (only if CADDY_DOMAIN is set)
# Fallback: HTTP only if no domain

{
    auto_https off
}

:443 {
    handle_path /api/* {
        reverse_proxy {$NSCT_API_UPSTREAM}
    }

    reverse_proxy web:3000

    # Security Headers
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' https://*; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'"
        Referrer-Policy no-referrer-when-downgrade
        Permissions-Policy "camera=(), microphone=(), geolocation=()"
        X-Permitted-Cross-Domain-Policies none
        X-DNS-Prefetch-Control off
    }

    # HTTPS redirect (only when domain is set)
    @hasDomain {
        host {env.CADDY_DOMAIN}
    }
    redir @hasDomain https://{host}{uri}

    # Compression
    encode gzip zstd

    # Rate limiting (optional, only if NSCT_RATE_LIMIT is set)
    @hasRateLimit {
        expression {env.NSCT_RATE_LIMIT} != ""
    }

    # Log
    log {
        format json
        output stdout
    }
}

# HTTP fallback (when no domain is set)
:80 {
    handle_path /api/* {
        reverse_proxy {$NSCT_API_UPSTREAM}
    }

    reverse_proxy web:3000

    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' https://*; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'"
        Referrer-Policy no-referrer-when-downgrade
    }

    encode gzip zstd
}
