Some checks failed
verify / verify (push) Has been cancelled
Expose the verified synthetic retrieval path through a typed React client and a non-root Nginx edge while keeping database credentials and data-network reachability out of the browser tier. A fixed-origin gateway preserves request boundaries and now closes upstream streams even when downstream disconnects before body iteration. The deployment ADR and runbooks record the four-network topology and its accepted Web edge-egress risk. Constraint: The previously exposed Bailian key must be revoked and no live provider credential may enter Git, images, logs, or the browser. Rejected: Connect Web directly to the data network | expands lateral reach to PostgreSQL. Rejected: Publish the database-aware API on the edge network | gives a credential-bearing process a public default route. Rejected: Buffer streaming responses in either proxy | prevents incremental chat delivery in the future. Confidence: high Scope-risk: moderate Reversibility: clean Directive: Do not mark Stage 1 or Stage 2 complete until the rotated-key live smoke and remaining stage gates pass. Tested: make verify; 65 backend tests; 14 frontend tests; Docker image build; container health and isolation probes; real HTTP demo/status/search/docs/OpenAPI checks. Not-tested: Live Bailian models, real document ingestion, business chat SSE generation, and final browser screenshot automation because the browser skill runtime was unavailable.
115 lines
3.7 KiB
Nginx Configuration File
115 lines
3.7 KiB
Nginx Configuration File
pid /tmp/nginx.pid;
|
|
|
|
worker_processes auto;
|
|
|
|
error_log /dev/stderr notice;
|
|
|
|
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
include /etc/nginx/mime.types;
|
|
default_type application/octet-stream;
|
|
|
|
access_log /dev/stdout;
|
|
|
|
client_body_temp_path /tmp/client_temp;
|
|
proxy_temp_path /tmp/proxy_temp;
|
|
fastcgi_temp_path /tmp/fastcgi_temp;
|
|
uwsgi_temp_path /tmp/uwsgi_temp;
|
|
scgi_temp_path /tmp/scgi_temp;
|
|
|
|
sendfile on;
|
|
tcp_nopush on;
|
|
keepalive_timeout 65s;
|
|
server_tokens off;
|
|
|
|
gzip on;
|
|
gzip_comp_level 5;
|
|
gzip_min_length 1024;
|
|
gzip_proxied any;
|
|
gzip_types
|
|
application/javascript
|
|
application/json
|
|
application/xml
|
|
image/svg+xml
|
|
text/css
|
|
text/plain;
|
|
|
|
# FastAPI's development Swagger page currently references versioned assets
|
|
# from jsDelivr and uses an inline bootstrap script. Keep that exception
|
|
# scoped to /docs; the React application retains the strict self-only policy.
|
|
map $uri $content_security_policy {
|
|
~^/docs(?:/|$) "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https://fastapi.tiangolo.com; object-src 'none'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net";
|
|
default "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'";
|
|
}
|
|
|
|
resolver 127.0.0.11 valid=10s ipv6=off;
|
|
|
|
upstream gateway_upstream {
|
|
zone gateway_upstream 64k;
|
|
server gateway:8000 resolve;
|
|
keepalive 32;
|
|
}
|
|
|
|
server {
|
|
listen 8080;
|
|
server_name _;
|
|
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
client_max_body_size 1m;
|
|
|
|
add_header Content-Security-Policy $content_security_policy always;
|
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
|
add_header Cross-Origin-Resource-Policy "same-origin" always;
|
|
add_header Permissions-Policy "camera=(), geolocation=(), microphone=()" always;
|
|
add_header Referrer-Policy "no-referrer" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
|
|
|
location = /nginx-health {
|
|
access_log off;
|
|
default_type text/plain;
|
|
return 200 "ok\n";
|
|
}
|
|
|
|
location ~ /\.(?!well-known(?:/|$)) {
|
|
deny all;
|
|
}
|
|
|
|
# Keep all browser API traffic same-origin. Buffering is disabled so
|
|
# event-stream responses can be delivered incrementally end to end.
|
|
location ~ ^/(?:api(?:/|$)|health(?:/|$)|docs(?:/|$)|openapi\.json$) {
|
|
proxy_pass http://gateway_upstream;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Connection "";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_buffering off;
|
|
proxy_cache off;
|
|
proxy_request_buffering off;
|
|
proxy_read_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
}
|
|
|
|
location ^~ /assets/ {
|
|
expires 1y;
|
|
try_files $uri =404;
|
|
}
|
|
|
|
location = /index.html {
|
|
expires -1;
|
|
try_files /index.html =404;
|
|
}
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
}
|
|
}
|