Make the offline RAG chain observable without widening credential access
Some checks failed
verify / verify (push) Has been cancelled
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.
This commit is contained in:
@@ -18,6 +18,8 @@ from app.persistence.job_queue_sql import ( # noqa: E402
|
||||
|
||||
COMPOSE = (ROOT / "compose.yaml").read_text(encoding="utf-8")
|
||||
DOCKERFILE = (BACKEND / "Dockerfile").read_text(encoding="utf-8")
|
||||
FRONTEND_DOCKERFILE = (ROOT / "frontend/Dockerfile").read_text(encoding="utf-8")
|
||||
NGINX = (ROOT / "frontend/nginx.conf").read_text(encoding="utf-8")
|
||||
DEMO_API = (BACKEND / "app/api/v1/demo.py").read_text(encoding="utf-8")
|
||||
BOOTSTRAP = (ROOT / "ops/postgres/init/10-bootstrap-rag.sh").read_text(encoding="utf-8")
|
||||
MIGRATION = (BACKEND / "migrations/versions/0001_initial_schema.py").read_text(encoding="utf-8")
|
||||
@@ -35,6 +37,7 @@ def test_compose_isolates_database_credentials_and_networks() -> None:
|
||||
migrate = _service_block("migrate")
|
||||
api = _service_block("api")
|
||||
gateway = _service_block("gateway")
|
||||
web = _service_block("web")
|
||||
provider_smoke = _service_block("provider-smoke")
|
||||
seed_demo = _service_block("seed-demo")
|
||||
seed_demo_offline = _service_block("seed-demo-offline")
|
||||
@@ -59,15 +62,29 @@ def test_compose_isolates_database_credentials_and_networks() -> None:
|
||||
assert "no-new-privileges:true" in api
|
||||
assert "cap_drop:" in api and " - ALL" in api
|
||||
|
||||
assert '"127.0.0.1:8000:8000"' in gateway
|
||||
assert " - edge" in gateway
|
||||
assert '"127.0.0.1:8000:8000"' not in gateway
|
||||
assert " - ingress" in gateway
|
||||
assert " - data" in gateway
|
||||
assert " - edge" not in gateway
|
||||
assert " - egress" not in gateway
|
||||
assert "secrets:" not in gateway
|
||||
assert "POSTGRES_" not in gateway
|
||||
assert "BAILIAN_" not in gateway
|
||||
assert "read_only: true" in gateway
|
||||
assert "no-new-privileges:true" in gateway
|
||||
|
||||
assert '"127.0.0.1:8000:8080"' in web
|
||||
assert " - edge" in web
|
||||
assert " - ingress" in web
|
||||
assert " - data" not in web
|
||||
assert " - egress" not in web
|
||||
assert "secrets:" not in web
|
||||
assert "POSTGRES_" not in web
|
||||
assert "BAILIAN_" not in web
|
||||
assert "read_only: true" in web
|
||||
assert "no-new-privileges:true" in web
|
||||
assert len(re.findall(r"(?m)^ ports:$", COMPOSE)) == 1
|
||||
|
||||
assert "bailian_api_key" in provider_smoke
|
||||
assert "postgres_" not in provider_smoke
|
||||
|
||||
@@ -83,11 +100,15 @@ def test_compose_isolates_database_credentials_and_networks() -> None:
|
||||
assert "./data/samples/public:/demo:ro" in seed_demo_offline
|
||||
|
||||
assert re.search(r"(?ms)^ data:\n.*?^ internal: true$", COMPOSE)
|
||||
assert re.search(r"(?ms)^ ingress:\n.*?^ internal: true$", COMPOSE)
|
||||
assert re.search(r"(?m)^ edge:$", COMPOSE)
|
||||
assert re.search(r"(?m)^ egress:$", COMPOSE)
|
||||
|
||||
assert "USER 10001:10001" in DOCKERFILE
|
||||
assert 'CMD ["uvicorn", "app.main:app"' in DOCKERFILE
|
||||
assert "USER 101:101" in FRONTEND_DOCKERFILE
|
||||
assert "proxy_buffering off" in NGINX
|
||||
assert "server gateway:8000" in NGINX
|
||||
|
||||
|
||||
def test_demo_queries_pin_governed_offline_identity() -> None:
|
||||
|
||||
Reference in New Issue
Block a user