Reports: the LLM reliably used company_enrichment for prose fields but inconsistently populated the parallel Finding-list/string-list fields from the same evidence, even with progressively more explicit prompting. Add a code-level backfill (products, recent developments, financial signals, strategic initiatives, regulatory signals, risks/opportunities mirrored from SWOT, unknowns, monitoring recommendations) that only ever fills in what the model left empty, never overwrites what it produced. Enrichment tab: reorder sections (Products/Recent updates before Customers/Competitors) and add a per-section "Refresh" button that re-fetches just one of NinjaPear's six independent per-company endpoints when it came back empty - confirmed live that a data-coverage gap (e.g. Amazon returning no products) is real provider behavior, not a bug. Auth: the first account registered on a deployment with zero existing admins is now auto-promoted to admin, closing the chicken-and-egg gap where the only path to admin access was direct DB access. Self-heals if the last admin ever deletes their account. Also bumps nginx's proxy_read_timeout for api.ciagent.org to cover the enrichment refresh's synchronous funding-endpoint call (up to 5 minutes per NinjaPear's docs). Co-Authored-By: Claude Sonnet 5 <[email protected]>
134 lines
4.8 KiB
Nginx Configuration File
134 lines
4.8 KiB
Nginx Configuration File
# Reverse proxy for the three ciagent.org subdomains, sitting between
|
|
# Cloudflare (which terminates public-facing TLS and hides this origin's
|
|
# real IP) and the app's own containers. TLS here is a Cloudflare Origin CA
|
|
# certificate (Cloudflare dashboard -> SSL/TLS -> Origin Server -> Create
|
|
# Certificate; covers ciagent.org + *.ciagent.org, up to 15yr validity, only
|
|
# trusted by Cloudflare - no ACME/renewal machinery needed). Cloudflare SSL
|
|
# mode must be "Full (strict)" for this to be meaningful. See DEPLOYMENT.md.
|
|
#
|
|
# CF-Connecting-IP (the header app.core.security.get_client_ip reads once
|
|
# TRUSTED_PROXY_IP_HEADER=CF-Connecting-IP is set) needs no special handling
|
|
# here - Nginx forwards any header it doesn't explicitly touch straight
|
|
# through to the upstream unmodified.
|
|
|
|
user nginx;
|
|
worker_processes auto;
|
|
|
|
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
include mime.types;
|
|
default_type application/octet-stream;
|
|
sendfile on;
|
|
server_tokens off;
|
|
|
|
# Bare :80 hits get redirected to :443 - Cloudflare already enforces
|
|
# HTTPS at the edge, but the origin shouldn't 400 a direct :80 probe.
|
|
server {
|
|
listen 80;
|
|
server_name ciagent.org api.ciagent.org git.ciagent.org db.ciagent.org;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
server_name ciagent.org;
|
|
|
|
ssl_certificate /etc/nginx/certs/cloudflare-origin.pem;
|
|
ssl_certificate_key /etc/nginx/certs/cloudflare-origin.key;
|
|
|
|
location / {
|
|
proxy_pass http://web:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
server_name api.ciagent.org;
|
|
|
|
ssl_certificate /etc/nginx/certs/cloudflare-origin.pem;
|
|
ssl_certificate_key /etc/nginx/certs/cloudflare-origin.key;
|
|
|
|
location / {
|
|
proxy_pass http://api:8000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
# NinjaPear's funding endpoint is documented as taking up to 5
|
|
# minutes (see app/enrichment/ninjapear.py's _FUNDING_TIMEOUT) -
|
|
# the enrichment-section-refresh endpoint calls it synchronously,
|
|
# so nginx's 60s default would otherwise 504 before it finishes.
|
|
proxy_read_timeout 320s;
|
|
proxy_send_timeout 320s;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
server_name git.ciagent.org;
|
|
|
|
ssl_certificate /etc/nginx/certs/cloudflare-origin.pem;
|
|
ssl_certificate_key /etc/nginx/certs/cloudflare-origin.key;
|
|
|
|
# Large git pushes (Gitea's HTTPS push path).
|
|
client_max_body_size 512m;
|
|
|
|
location / {
|
|
proxy_pass http://gitea:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
}
|
|
}
|
|
|
|
# Settings -> Database viewer (Adminer). Access isn't gated by a shared
|
|
# password - the app itself (app/api/v1/db_viewer.py) mints a short-lived
|
|
# token from a live admin session, which /_auth here exchanges for a
|
|
# session cookie that /_verify re-checks (including a fresh `is_admin`
|
|
# lookup) on every request via auth_request. See DEPLOYMENT.md.
|
|
server {
|
|
listen 443 ssl;
|
|
server_name db.ciagent.org;
|
|
|
|
ssl_certificate /etc/nginx/certs/cloudflare-origin.pem;
|
|
ssl_certificate_key /etc/nginx/certs/cloudflare-origin.key;
|
|
|
|
# Adminer renders a raw SQL/data editor - not meant to be framed or
|
|
# MIME-sniffed as another content type.
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
|
|
# Optional extra hardening for admins with a static IP: uncomment
|
|
# and set your own address to additionally require it alongside a
|
|
# valid session (default `satisfy all` - both must pass, not either).
|
|
# allow 203.0.113.9;
|
|
# deny all;
|
|
|
|
location = /_verify {
|
|
internal;
|
|
proxy_pass http://api:8000/api/v1/db-viewer/verify;
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
proxy_set_header Cookie $http_cookie;
|
|
}
|
|
|
|
location = /_auth {
|
|
proxy_pass http://api:8000/api/v1/db-viewer/bootstrap;
|
|
proxy_set_header Host $host;
|
|
}
|
|
|
|
location / {
|
|
auth_request /_verify;
|
|
proxy_pass http://adminer:8080;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
}
|
|
}
|
|
}
|