---
title: "Network — service-to-service — N1 IT Landscape"
---

N1 IT Landscape — The Blueprint · CF-Access internal

# Network — service-to-service

N1 IT Landscape · Owner: Arun Venkataraman · source of truth: markdown SSOT

# N1 IT Landscape — Network — service-to-service map

> **CURRENT-STATE** as of **2026-06-09** · part of the **N1 IT Landscape** (start at **[Overview](/landscape/overview/)**). Owner: **Arun Venkataraman** (Principal Engineer).

* * *

_The who-calls-whom layer: every in-cluster service and port, the Valkey stream topology, ingress and egress edges, DB/cache allow-lists. The companion VPC/subnet/route-table map lives in [NETWORK.md](/landscape/network/)._

<figure class="visual-frame">
  <img src="/visuals/landscape/network-services.svg" alt="N1 service topology overview: Cloudflare ingress reaches identity and application services; applications use Valkey stream workers and PgBouncer-managed Aurora data stores.">
  <figcaption>Topology overview only; use the <a href="/visuals/network-services/">interactive topology explorer</a> or the service, port, node, and edge lists below for complete operational detail. <a href="/visuals/landscape/network-services.svg" download>Download SVG source</a></figcaption>
</figure>

* * *

## NS-1. Scope and the one big idea

This document is the **service-level wire map** for the N1 EKS clusters. [NETWORK.md](/landscape/network/) covers the VPC/subnet/peering/NAT/IGW layer; cross-reference it for CIDR blocks, route tables, and peering IDs.

**Security model — flat pod network behind the edge.** Both clusters (staging and production) have exactly **2 NetworkPolicies each** — one permits Prometheus scraping of the ArgoCD image-updater metrics pod, and one permits Prometheus scraping of the KEDA event-notifier pod. Neither is an application-traffic restriction. There are **no NetworkPolicies in the`staging`, `prod`, `llmproxy`, `ai-inference`, `monitoring`, `external-secrets`, or `kube-system` namespaces.** Pod-to-pod traffic within each cluster is completely unrestricted by NetworkPolicy. Isolation is enforced at three other layers: the Cloudflare edge (no inbound ports on AWS; all external entry via Cloudflare Tunnel), Cloudflare Access (Google IdP authentication on every `n1-research.com` hostname), and the namespace boundary (each environment's app services share a namespace; cross-environment communication is physically impossible because staging and production are separate clusters in separate VPCs that have no peering or routing link between them).

* * *

## NS-2. Service and port catalogue

All service types are `ClusterIP` unless noted. Ports are listed as `name:clusterPort→targetPort/proto`.

### NS-2.1 Staging cluster — namespace: staging (21 services)

Service | ClusterIP | Port(s) | What it is  
---|---|---|---  
admin-dashboard | 172.20.31.110 | http:3000→3000/TCP | Internal admin UI  
api-backend | 172.20.152.201 | http:8080→8080/TCP | Core Python API server  
api-websocket-proxy | 172.20.4.120 | http:9999→http/TCP | Go WebSocket proxy fronting api-backend  
authentication-service | 172.20.103.252 | http:9000→9000/TCP | Ory glue — auth, sessions, OAuth clients  
automated-testing | 172.20.58.109 | http:8787→http/TCP | Automated test runner (staging only)  
billing-service | 172.20.138.176 | http:4444→http/TCP | Stripe billing service  
forge-agents-api | 172.20.125.178 | http:8080→8080/TCP | Read-only agent/workflow catalog HTTP server  
helix-parser | 172.20.240.190 | http:8080→8080/TCP | Helix parser (staging only)  
hydra-admin | 172.20.253.6 | http:4445→http-admin/TCP | Ory Hydra admin API  
hydra-public | 172.20.201.101 | http:4444→http-public/TCP | Ory Hydra OAuth2 public endpoint  
kratos-admin | 172.20.232.148 | http:4434→admin/TCP | Ory Kratos admin API  
kratos-public | 172.20.31.183 | http:4433→public/TCP | Ory Kratos public (identity/login)  
memgraph | 172.20.149.41 | bolt:7687→7687/TCP | Memgraph graph database (staging only)  
oathkeeper-api | 172.20.248.102 | http:4456→http-api/TCP | Ory Oathkeeper management API  
oathkeeper-metrics | 172.20.187.60 | http:80→http-metrics/TCP | Oathkeeper Prometheus metrics  
oathkeeper-proxy | 172.20.205.38 | http:4455→http-proxy/TCP | Ory Oathkeeper decision/proxy gateway  
pgbouncer | 172.20.90.111 | pgbouncer:6432→6432/TCP, metrics:9127→9127/TCP | PgBouncer connection pool (Aurora front-end)  
phoenix-parser | 172.20.188.71 | http:8080→8080/TCP | Phoenix clinical data extractor (stream consumer)  
phoenix-router | 172.20.149.242 | http:8080→8080/TCP | Phoenix page classifier (stream consumer)  
qdrant | 172.20.235.42 | http:6333→6333/TCP, grpc:6334→6334/TCP | Qdrant vector database (staging only)  
rosetta-grouper | 172.20.241.57 | http:8080→8080/TCP | Rosetta BiomarkerDefinition grouper (stream consumer)  
  
### NS-2.2 Production cluster — namespace: prod (22 services)

Service | ClusterIP | Port(s) | What it is  
---|---|---|---  
admin-dashboard | 172.20.23.227 | http:3000→3000/TCP | Internal admin UI  
api-backend | 172.20.81.96 | http:8080→8080/TCP | Core Python API server  
api-proxy | 172.20.8.86 | http:8888→8888/TCP | Cloudflare-side API traffic proxy (prod only)  
api-websocket-proxy | 172.20.226.240 | http:9999→http/TCP | Go WebSocket proxy fronting api-backend  
auth-proxy | 172.20.127.127 | http:8888→8888/TCP | Cloudflare-side auth traffic proxy (prod only)  
authentication-service | 172.20.227.179 | http:9000→9000/TCP | Ory glue — auth, sessions, OAuth clients  
billing-proxy | 172.20.209.58 | http:8888→8888/TCP | Cloudflare-side billing traffic proxy (prod only)  
billing-service | 172.20.173.213 | http:4444→http/TCP | Stripe billing service  
celery-flower | 172.20.242.67 | http:5555→5555/TCP | Celery task monitor (prod only)  
forge-agents-api | 172.20.4.36 | http:8080→8080/TCP | Read-only agent/workflow catalog HTTP server  
hydra-admin | 172.20.72.27 | http:4445→http-admin/TCP | Ory Hydra admin API  
hydra-public | 172.20.241.37 | http:4444→http-public/TCP | Ory Hydra OAuth2 public endpoint  
kratos-admin | 172.20.246.65 | http:4434→admin/TCP | Ory Kratos admin API  
kratos-public | 172.20.189.83 | http:4433→public/TCP | Ory Kratos public (identity/login)  
oathkeeper-api | 172.20.212.20 | http:4456→http-api/TCP | Ory Oathkeeper management API  
oathkeeper-metrics | 172.20.150.210 | http:80→http-metrics/TCP | Oathkeeper Prometheus metrics  
oathkeeper-proxy | 172.20.171.10 | http:4455→http-proxy/TCP | Ory Oathkeeper decision/proxy gateway  
pdf-converter | 172.20.204.203 | http:9000→http/TCP | PDF-to-image converter (prod only)  
pgbouncer | 172.20.22.246 | pgbouncer:6432→6432/TCP, metrics:9127→9127/TCP | PgBouncer connection pool (Aurora front-end)  
phoenix-parser | 172.20.32.221 | http:8080→8080/TCP | Phoenix clinical data extractor (stream consumer)  
phoenix-router | 172.20.194.182 | http:8080→8080/TCP | Phoenix page classifier (stream consumer)  
rosetta-grouper | 172.20.122.135 | http:8080→8080/TCP | Rosetta BiomarkerDefinition grouper (stream consumer)  
  
### NS-2.3 Both clusters — shared namespaces

#### Namespace: ai-inference

Service | Staging ClusterIP | Prod ClusterIP | Port(s) | What it is  
---|---|---|---|---  
mineru | 172.20.5.43 | 172.20.68.27 | http:8000→http/TCP | MinerU-2.5 PDF/page classifier  
embeddinggemma | 172.20.77.41 | — (staging only) | http:8000→http/TCP, metrics:9000→metrics/TCP | Gemma embedding model  
  
#### Namespace: llmproxy

Service | Staging ClusterIP | Prod ClusterIP | Port(s) | What it is  
---|---|---|---|---  
litellm | 172.20.208.172 | 172.20.199.239 | http:4000→4000/TCP | LiteLLM proxy (all LLM calls from all services)  
  
#### Namespace: monitoring

Service | Staging ClusterIP | Prod ClusterIP | Port(s) | What it is  
---|---|---|---|---  
otel-collector | 172.20.229.229 | 172.20.70.144 | otlp-grpc:4317/TCP, otlp-http:4318/TCP, metrics:8888/TCP, statsd:8125/UDP | OpenTelemetry collector  
  
#### Namespace: argocd (both clusters identical shape)

Service | Staging ClusterIP | Prod ClusterIP | Port(s)  
---|---|---|---  
argocd-application-controller-metrics | 172.20.155.45 | 172.20.66.54 | http-metrics:8082→metrics/TCP  
argocd-applicationset-controller | 172.20.13.226 | 172.20.3.206 | http-webhook:7000→webhook/TCP  
argocd-dex-server | 172.20.125.80 | 172.20.147.157 | http:5556/TCP, grpc:5557/TCP  
argocd-image-updater-metrics | 172.20.155.121 | 172.20.24.31 | metrics:8443→metrics/TCP  
argocd-redis | 172.20.238.53 | 172.20.180.76 | redis:6379→redis/TCP  
argocd-repo-server | 172.20.50.176 | 172.20.91.51 | tcp-repo-server:8081→repo-server/TCP  
argocd-server | 172.20.209.235 | 172.20.141.99 | http:80→8080/TCP, https:443→8080/TCP  
argocd-server-proxy | 172.20.120.32 | 172.20.145.162 | http:80→8888/TCP, https:443→8888/TCP  
  
#### Namespace: keda (both clusters identical shape)

Service | Staging ClusterIP | Prod ClusterIP | Port(s)  
---|---|---|---  
keda-admission-webhooks | 172.20.64.9 | 172.20.15.103 | https:443→9443/TCP  
keda-event-notifier-kubernetes-event-exporter-metrics | 172.20.99.248 | 172.20.247.163 | http:2112→http/TCP  
keda-operator | 172.20.94.135 | 172.20.114.73 | metricsservice:9666/TCP, metrics:8080/TCP  
keda-operator-metrics-apiserver | 172.20.59.28 | 172.20.227.38 | https:443→6443/TCP, metrics:9022/TCP  
  
#### Namespace: kube-system (both clusters identical shape)

Service | Staging ClusterIP | Prod ClusterIP | Port(s)  
---|---|---|---  
eks-extension-metrics-api | 172.20.86.209 | 172.20.54.88 | metrics-api:443→10443/TCP  
karpenter | 172.20.17.91 | 172.20.138.139 | http-metrics:8080→http-metrics/TCP  
kube-dns | 172.20.0.10 | 172.20.0.10 | dns:53/UDP, dns-tcp:53/TCP, metrics:9153/TCP  
metrics-server | 172.20.103.130 | 172.20.112.139 | https:443→https/TCP  
  
#### Namespace: external-secrets (both clusters)

Service | Staging ClusterIP | Prod ClusterIP | Port(s)  
---|---|---|---  
external-secrets-webhook | 172.20.119.9 | 172.20.24.179 | webhook:443→webhook/TCP  
  
#### Namespace: default — staging only (KEDA + Kubernetes in default ns)

Service | ClusterIP | Port(s)  
---|---|---  
keda-admission-webhooks | 172.20.139.98 | https:443→9443/TCP  
keda-operator | 172.20.55.228 | metricsservice:9666/TCP, metrics:8080/TCP  
keda-operator-metrics-apiserver | 172.20.227.110 | https:443→6443/TCP, metrics:9022/TCP  
kubernetes | 172.20.0.1 | https:443→443/TCP  
  
* * *

## NS-3. Synchronous call graph (HTTP / gRPC / WebSocket)

Each edge is `caller ──proto:port──▶ callee`. Ports are from the live service catalogue (§NS-2) except where marked **(inferred)**.

### NS-3.1 External-to-cluster entry (via Cloudflare Tunnel)
    
    
    [internet browser / React app @ app.n1.care (Cloudflare Worker)]
        │
        ├─ WebSocket path ──WS:9999──▶ api-websocket-proxy.{staging|prod}
        │                                        └──HTTP:8080──▶ api-backend
        │
        └─ HTTP path ─────HTTP:4455──▶ oathkeeper-proxy.{staging|prod}
                                            └──HTTP:8080──▶ api-backend
    
    [internet → auth hostnames]
        └─ HTTP:4455──▶ oathkeeper-proxy → HTTP:4433──▶ kratos-public
                                         → HTTP:9000──▶ authentication-service
    
    [internet → oauth hostname (direct to Hydra, NOT through Oathkeeper)]
        └─ HTTP:4444──▶ hydra-public
    
    [internet → billing hostname]
        └─ HTTP:4455──▶ oathkeeper-proxy → HTTP:4444──▶ billing-service
    
    [admin dashboard hostname → Access gated]
        └─ HTTP:3000──▶ admin-dashboard
    

### NS-3.2 Internal synchronous calls
    
    
    api-backend ──HTTP:8080──▶ forge-agents-api          (catalog reads: /agents/skills/, /agents/workflows/ + N1-Api-Key header)
    api-backend ──HTTP:4000──▶ litellm                   (all LLM calls from api-backend)
    api-backend ──HTTP:6432──▶ pgbouncer                 (PgBouncer → Aurora n1-{env}-app :5432)
    
    authentication-service ──HTTP:4433──▶ kratos-public  (session/identity lookups) (inferred)
    authentication-service ──HTTP:4434──▶ kratos-admin   (admin ops) (inferred)
    authentication-service ──HTTP:4445──▶ hydra-admin    (OAuth client management) (inferred)
    authentication-service ──HTTP:6432──▶ pgbouncer      (auth DB ops — auth-{env} Aurora :5432) (inferred)
    
    oathkeeper-proxy ──HTTP:4433──▶ kratos-public        (session check for decision endpoint)
    oathkeeper-proxy ──HTTP:9000──▶ authentication-service (custom authenticator)
    
    billing-service ──HTTP:6432──▶ pgbouncer             (billing-{env} Aurora :5432) (inferred)
    billing-service ──HTTPS──▶ Stripe API                (over NAT egress) (inferred)
    
    admin-dashboard ──HTTP:8080──▶ api-backend           (inferred)
    admin-dashboard ──HTTP:4444──▶ billing-service       (inferred)
    
    phoenix-router ──HTTP:8000──▶ mineru.ai-inference    (page classification during document routing)
    phoenix-parser ──HTTP:8000──▶ mineru.ai-inference    (content extraction) (inferred)
    
    litellm ──HTTP:4000──▶ [Vertex AI | Bedrock | other LLM providers via NAT]
    litellm ──HTTP:6432──▶ pgbouncer                     (litellm-{env} Aurora :5432) (inferred)
    
    forge-runner (k8s Job) ──HTTP:8080──▶ api-backend    (MCP tools call n1 api client → api-backend for patient data) (inferred)
    forge-runner ──HTTP:4000──▶ litellm                  (LLM calls from CHR workflows) (inferred)
    forge-runner ──HTTP:6432──▶ pgbouncer                (forge-runner-{env} Aurora :5432 — agno session/memory/LangGraph checkpoints) (inferred)
    
    [all services] ──otlp-grpc:4317 | otlp-http:4318──▶ otel-collector.monitoring  (telemetry) (inferred)
    

### NS-3.3 Production-only proxy layer

In production, three additional proxy services sit between the Cloudflare Tunnel and the app namespace services. These are not present in staging.
    
    
    [Cloudflare Tunnel → api-proxy.prod:8888]     → api-backend.prod:8080  (inferred)
    [Cloudflare Tunnel → auth-proxy.prod:8888]    → authentication-service or kratos (inferred)
    [Cloudflare Tunnel → billing-proxy.prod:8888] → billing-service.prod:4444 (inferred)
    

* * *

## NS-4. Asynchronous stream topology (Valkey/Redis Streams)

Workers are stateless stream consumers scaled by KEDA on queue depth. Stream names are taken directly from KEDA ScaledObject definitions; scale ranges are from the live pull.

### NS-4.1 Active Phoenix pipeline (both clusters)
    
    
    api-backend
        └─ PRODUCE ──▶ stream: phoenix:router:input
                                │
    phoenix-router (KEDA: min=2, max=50, lag≥2)
        ├─ CONSUME phoenix:router:input  (consumerGroup: router-group)
        ├─ calls mineru:8000 per page for classification
        └─ PRODUCE ──▶ stream: phoenix:parser:input
                                │
    phoenix-parser (KEDA: min=2, max=50, lag≥2)
        ├─ CONSUME phoenix:parser:input  (consumerGroup: parser-group)
        └─ PRODUCE ──▶ stream: phoenix:grouper:input
                                │
    rosetta-grouper (KEDA: min=2, max=50, lag≥2)
        ├─ CONSUME phoenix:grouper:input  (consumerGroup: rosetta-grouper)
        └─ PRODUCE result → api-backend  (via n1 api client HTTP:8080)
    

### NS-4.2 CHR / Forge pipeline (both clusters)
    
    
    api-backend
        └─ PRODUCE ──▶ stream: (forge-sentinel subscription stream) (inferred — stream name not in ScaledObjects)
                                │
    forge-sentinel
        ├─ CONSUME stream
        └─ LAUNCH ──▶ forge-runner k8s Job
                        ├─ runs CHR workflow (agno framework)
                        ├─ calls api-backend:8080 via MCP tools
                        ├─ calls litellm:4000 for LLM steps
                        └─ saves report → S3 (n1-{env}-user-data) (inferred)
    

### NS-4.3 Data validation stream (both clusters)
    
    
    (upstream producer — not a separate K8s service, produced by api-backend or pipeline workers) (inferred)
        └─ PRODUCE ──▶ stream: data-validation-input-queue
                                │
    data-validation-service (KEDA: min=2, max=10, lag≥5)
        └─ CONSUME data-validation-input-queue  (consumerGroup: data-validation-consumer-group)
    

### NS-4.4 Evaluation streams (staging only)

Three evaluation streams exist in staging only, driven by an evals framework:

Stream | Consumer | Scale  
---|---|---  
`phoenix:router-evals:input` | router-evals-service (min=1, max=5) | lagCount=5  
`phoenix:parser-evals:input` | parser-evals-service (min=1, max=5) | lagCount=5  
`phoenix:grouper-evals:input` | grouper-evals-service (min=1, max=5) | lagCount=5  
  
### NS-4.5 Orphaned ScaledObjects in production (4)

Production contains 4 ScaledObjects whose target Deployments no longer exist. These are leftover from the Rosetta 1.0 / pre-Phoenix pipeline migration and use the legacy `redis list` trigger (not `redis-streams`).

ScaledObject name | Target Deployment | Legacy list name | Trigger type  
---|---|---|---  
`grouping-poller-service` | (gone) | `grouping_poller_queue` | redis list  
`grouping-service` | (gone) | `group_medical_records` | redis list  
`parser-service` | (gone) | `parse_medical_records` | redis list  
`router-service` | (gone) | `route_medical_records` | redis list  
  
These ScaledObjects watch real Valkey lists on `production-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com:6379` but scale nothing — the lists are empty and the Deployments do not exist.

### NS-4.6 KEDA ScaledObject summary

ScaledObject | Cluster | Trigger | Target | min | max | Threshold  
---|---|---|---|---|---|---  
staging/phoenix-router | staging | redis-streams | Deployment/phoenix-router | 2 | 50 | lagCount=2  
staging/phoenix-parser | staging | redis-streams | Deployment/phoenix-parser | 2 | 50 | lagCount=2  
staging/rosetta-grouper | staging | redis-streams | Deployment/rosetta-grouper | 2 | 50 | lagCount=2  
staging/data-validation-service | staging | redis-streams | Deployment/data-validation-service | 2 | 10 | lagCount=5  
staging/router-evals-service | staging | redis-streams | Deployment/router-evals-service | 1 | 5 | lagCount=5  
staging/parser-evals-service | staging | redis-streams | Deployment/parser-evals-service | 1 | 5 | lagCount=5  
staging/grouper-evals-service | staging | redis-streams | Deployment/grouper-evals-service | 1 | 5 | lagCount=5  
staging/api-websocket-proxy | staging | metrics-api | Deployment/api-websocket-proxy | 2 | 5 | targetValue=1000  
staging/pgbouncer | staging | metrics-api | Deployment/pgbouncer | 2 | 3 | targetValue=300  
ai-inference/mineru (staging) | staging | metrics-api | Deployment/mineru | 1 | 5 | targetValue=20  
prod/phoenix-router | prod | redis-streams | Deployment/phoenix-router | 2 | 50 | lagCount=2  
prod/phoenix-parser | prod | redis-streams | Deployment/phoenix-parser | 2 | 50 | lagCount=2  
prod/rosetta-grouper | prod | redis-streams | Deployment/rosetta-grouper | 2 | 50 | lagCount=2  
prod/data-validation-service | prod | redis-streams | Deployment/data-validation-service | 2 | 10 | lagCount=5  
prod/api-websocket-proxy | prod | metrics-api | Deployment/api-websocket-proxy | 2 | 10 | targetValue=2000  
prod/pgbouncer | prod | metrics-api | Deployment/pgbouncer | 2 | 4 | targetValue=500  
ai-inference/mineru (prod) | prod | metrics-api | Deployment/mineru | 1 | 10 | targetValue=20  
prod/grouping-poller-service | prod | redis list | Deployment/grouping-poller-service | 2 | 3 | **ORPHANED — Deployment gone**  
prod/grouping-service | prod | redis list | Deployment/grouping-service | 2 | 10 | **ORPHANED — Deployment gone**  
prod/parser-service | prod | redis list | Deployment/parser-service | 3 | 10 | **ORPHANED — Deployment gone**  
prod/router-service | prod | redis list | Deployment/router-service | 2 | 8 | **ORPHANED — Deployment gone**  
  
* * *

## NS-5. Ingress edges (Cloudflare Tunnel)

Both clusters use the `cloudflare-tunnel` Deployment (2 replicas, `kube-system`). The tunnel token is fetched from AWS Secrets Manager via ExternalSecrets. **Routing rules are stored in the Cloudflare dashboard** (`config_src=cloudflare`, `remote_config=True`), not in any in-cluster ConfigMap. The tables below are derived from `n1-helm-charts` environment configs and `PROD_CF_CUTOVER.md`.

### NS-5.1 Cloudflare tunnel inventory

The full tunnel IDs are below for the network record; the **canonical tunnel health/purpose list is in[§6.7](/landscape/cloudflare/)** (taken from the live Cloudflare API).

Tunnel name | ID | Status | Purpose  
---|---|---|---  
EKS Staging | 03dae21f-eb8d-4e44-ab5f-08a5969baa0b | healthy | Staging cluster  
EKS Production | 5a3b0a66-8ba9-4789-af12-f7433ca980b5 | healthy | Production cluster  
EKS AI Cluster | d7bf4a5c-e142-42ff-b6c8-0dae34220f29 | healthy | AI/LiteLLM cluster  
N1 NexAI | 2f9140fe-5321-4e31-8b3e-d24339346b4e | healthy | Internal chat (chat.n1-research.com)  
signoz | 4ad64177-3d69-47a4-92cc-d38fbdc5baa9 | healthy | SigNoz observability host  
N1 Langfuse | b4d155e5-2270-4f83-993c-297c490a81d5 | **down** | Langfuse (langfuse.n1-research.com)  
N1 Local Dev | e2fbdd23-150f-4126-9f05-acac2dfc4997 | **down** | cortex-demo (local dev)  
  
### NS-5.2 Staging — tunnel EKS Staging (03dae21f) — hostname → service:port

Public hostname | Path | In-cluster service:port | Notes  
---|---|---|---  
api-staging.n1.care | /ws/* | api-websocket-proxy.staging:9999 | WebSocket; token via ?token= query param  
api-staging.n1.care | /* | oathkeeper-proxy.staging:4455 | All other paths; httpHostHeader=""  
auth-staging.n1.care | /* | oathkeeper-proxy.staging:4455 |   
billing-staging.n1.care | /* | oathkeeper-proxy.staging:4455 |   
oauth-staging.n1.care | /oauth2/_, /.well-known/_ , /userinfo | hydra-public.staging:4444 | Direct to Hydra; NOT through Oathkeeper  
oauth-staging.n1.care | /login, /consent, /logout | authentication-service.staging:9000 |   
argocd-staging.n1-research.com | /* | argocd-server-proxy.argocd:443 | Cloudflare Access gated  
litellm-staging.n1-research.com | /* | litellm.llmproxy:4000 |   
staging-admin.n1-research.com | /* | admin-dashboard.staging:3000 | Cloudflare Access gated  
automated-testing.n1-research.com | /* | automated-testing.staging:8787 |   
ws-api.n1-research.com | /* | api-websocket-proxy.staging:9999 | Staging WS endpoint  
  
**Oathkeeper dispatch (staging)** — what `oathkeeper-proxy.staging:4455` routes to:

Match URL pattern | Upstream  
---|---  
api-staging.n1.care/ws/* | api-websocket-proxy.staging:9999  
api-staging.n1.care/* | api-backend.staging:8080  
auth-staging.n1.care/self-service/_, /sessions/whoami, /.well-known/_ | kratos-public.staging:4433  
auth-staging.n1.care/keys/_, /oauth/clients/_ , /sessions/_, /(auth|recovery|invite|health|kyc|patients|oauth/_) | authentication-service.staging:9000  
billing-staging.n1.care/* | billing-service.staging:4444  
  
### NS-5.3 Production — tunnel EKS Production (5a3b0a66) — hostname → service:port

Public hostname | Path | In-cluster service:port | Notes  
---|---|---|---  
api.n1.care | /ws | api-websocket-proxy.prod:9999 | WebSocket; token via ?token=  
api.n1.care | /* | oathkeeper-proxy.prod:4455 |   
billing.n1.care | /* | oathkeeper-proxy.prod:4455 |   
oauth.n1.care | /oauth2/_, /.well-known/_ , /userinfo | hydra-public.prod:4444 | Direct to Hydra  
oauth.n1.care | /login, /consent, /logout | authentication-service.prod:9000 |   
auth.n1.care | /.well-known/jwks.json | authentication-service.prod:9000 | Before Kratos .well-known  
auth.n1.care | /self-service/methods/oidc/callback/* | kratos-public.prod:4433 |   
auth.n1.care | /self-service/*, /sessions/whoami, /.well-known/ | kratos-public.prod:4433 |   
auth.n1.care | /* | authentication-service.prod:9000 | Catch-all  
api-production.n1.care | /* | api-backend.prod:8080 | Legacy hostname (rollback only)  
billing-production.n1.care | /* | billing-service.prod:4444 | Legacy hostname  
auth-production.n1.care | /self-service/*, /sessions/whoami, /.well-known/ | kratos-public.prod:4433 | Legacy  
auth-production.n1.care | /* | authentication-service.prod:9000 | Legacy catch-all  
litellm-prod.n1-research.com | /* | litellm.llmproxy:4000 |   
argocd.n1-research.com | /* | argocd-server-proxy.argocd:443 | ArgoCD auth (no dedicated CF Access app)  
admin.n1-research.com | /* | admin-dashboard.prod:3000 | CF Access — named allowlist of 7 emails  
(default/catchall) |  | http_status:404 |   
  
**Oathkeeper dispatch (production)** — what `oathkeeper-proxy.prod:4455` routes to:

Match URL pattern | Upstream  
---|---  
api.n1.care/ws/* | api-websocket-proxy.prod:9999  
api.n1.care/* | api-backend.prod:8080  
auth.n1.care/self-service/_, /sessions/whoami, /.well-known/_ | kratos-public.prod:4433  
auth.n1.care/keys/_, /oauth/clients/_ , /sessions/_, /(auth|recovery|invite|health|kyc|patients|oauth/_) | authentication-service.prod:9000  
billing.n1.care/* | billing-service.prod:4444  
  
### NS-5.4 Other tunnels (not staging/prod EKS)

Tunnel | Hostname | Backend  
---|---|---  
EKS AI Cluster (d7bf4a5c) | litellm.n1-research.com | litellm.llmproxy:4000 (AI cluster)  
signoz (4ad64177) | signoz.n1-research.com | localhost:8080 on SigNoz VM  
signoz (4ad64177) | ingest-signoz.n1-research.com | localhost:4318 on SigNoz VM (OTLP HTTP)  
N1 NexAI (2f9140fe) | chat.n1-research.com | localhost:3080 on NexAI host  
N1 Langfuse (b4d155e5) | langfuse.n1-research.com | DOWN  
  
* * *

## NS-6. Egress edges

All pod egress exits via the **single NAT gateway per cluster VPC** (in `us-east-2a`) → internet gateway. There are no VPC endpoints, so AWS API traffic (S3, ECR, Secrets Manager, STS) also egresses via NAT. See [NETWORK.md §1](/landscape/network/) for the route table detail.

External target | Protocol / port | Consumers  
---|---|---  
Vertex AI (GCP) | HTTPS:443 | litellm (inferred)  
Amazon Bedrock (AWS) | HTTPS:443 | litellm (inferred)  
Stripe API | HTTPS:443 | billing-service (inferred)  
Postmark (email) | HTTPS:443 | authentication-service, api-backend (inferred)  
GitHub | HTTPS:443 | argocd-image-updater, CI (inferred)  
Amazon ECR | HTTPS:443 | Karpenter node pulls (inferred)  
Cloudflare R2 | HTTPS:443 | artifact storage (inferred)  
dhi.io | HTTPS:443 | api-backend / pipeline workers (inferred)  
Slack | HTTPS:443 | alerting/webhook consumers (inferred)  
ClickUp | HTTPS:443 | internal tooling (inferred)  
AWS S3 (n1-{env}-user-data) | HTTPS:443 | api-backend (file storage), forge-runner (report write) (inferred)  
AWS Secrets Manager / STS | HTTPS:443 | external-secrets-operator (inferred)  
  
* * *

## NS-7. Database and cache access — routes and allow-lists

### NS-7.1 Route

All database and cache connections from cluster pods follow the same path:
    
    
    pod (cluster VPC CIDR)
        └─ pgbouncer.{staging|prod}:6432 ──▶ (TCP → VPC peering link pcx-…) ──▶ Aurora :5432 (database VPC)
    pod
        └─ Valkey endpoint :6379 ──▶ (TCP → VPC peering link) ──▶ Valkey (database VPC)
    

The peering links are:

  * Staging: `pcx-0b0be34847a25cce8` — cluster VPC `10.10.0.0/16` ↔ database VPC `10.80.0.0/16`
  * Production: `pcx-043ae3b00da8e9703` — cluster VPC `10.30.0.0/16` ↔ database VPC `10.70.0.0/16`

### NS-7.2 Security group allow-lists (the authoritative source)

Both environments use a single "database" security group that covers Aurora AND Valkey. The allowed source is the **entire cluster VPC CIDR** — not a specific per-service or per-security-group source restriction.

Env | SG ID | SG name | Port | Protocol | Allowed from | Covers  
---|---|---|---|---|---|---  
Staging | sg-0ec302e948493a190 | n1-staging-database-rds-sg | **5432** | TCP | **10.10.0.0/16** (staging cluster VPC CIDR) | Aurora PostgreSQL  
Staging | sg-0ec302e948493a190 | n1-staging-database-rds-sg | **6379** | TCP | **10.10.0.0/16** (staging cluster VPC CIDR) | Valkey  
Production | sg-09a9f6eba199245f6 | n1-production-database-rds-sg | **5432** | TCP | **10.30.0.0/16** (production cluster VPC CIDR) | Aurora PostgreSQL  
Production | sg-09a9f6eba199245f6 | n1-production-database-rds-sg | **6379** | TCP | **10.30.0.0/16** (production cluster VPC CIDR) | Valkey  
  
There is no tighter per-service or per-security-group source restriction. Any pod in the cluster VPC with a route to the peering link can reach both Aurora and Valkey. The cluster's flat pod network (§NS-1) means any pod in the cluster can in principle open a connection; the namespace boundary and application-level authentication are the actual enforcement layer.

### NS-7.3 Aurora clusters — endpoints and consumers

All clusters run **Aurora PostgreSQL 17.7 Serverless v2** on port **5432** , SG `sg-0ec302e948493a190` (staging) / `sg-09a9f6eba199245f6` (production). App services connect via `pgbouncer.{ns}:6432`.

Cluster ID | Database name | Env | Writer endpoint | Reader endpoint | Primary consumer(s)  
---|---|---|---|---|---  
n1-staging-app | app | staging | n1-staging-app.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | n1-staging-app.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | api-backend, phoenix workers, rosetta-grouper  
auth-staging | n1_auth | staging | auth-staging.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | auth-staging.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | authentication-service, kratos, hydra  
billing-staging | n1_billing | staging | billing-staging.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | billing-staging.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | billing-service  
litellm-staging | litellm | staging | litellm-staging.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | litellm-staging.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | litellm  
forge-runner-staging | forge_runner | staging | forge-runner-staging.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | forge-runner-staging.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | forge-runner (agno session/memory/LangGraph)  
n1-production-app | app | prod | n1-production-app.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | n1-production-app.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | api-backend, phoenix workers, rosetta-grouper  
auth-production | n1_auth | prod | auth-production.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | auth-production.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | authentication-service, kratos, hydra  
billing-production | n1_billing | prod | billing-production.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | billing-production.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | billing-service  
litellm-production | litellm | prod | litellm-production.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | litellm-production.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | litellm  
forge-runner-production | forge_runner | prod | forge-runner-production.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | forge-runner-production.cluster-ro-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | forge-runner (agno session/memory/LangGraph)  
  
### NS-7.4 Valkey (ElastiCache) — endpoints and consumers

Both clusters use **Valkey 8.x** (AWS open-source Redis fork). No transit encryption (`transitEncryptionEnabled: false`); at-rest encryption enabled.

Property | Staging | Production  
---|---|---  
Replication group | staging-valkey | production-valkey  
Node type | cache.r7g.xlarge ×2 | cache.m7g.large ×2  
Primary endpoint | staging-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com:6379 | production-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com:6379  
Reader endpoint | staging-valkey-ro.zc3ep9.ng.0001.use2.cache.amazonaws.com:6379 | production-valkey-ro.zc3ep9.ng.0001.use2.cache.amazonaws.com:6379  
Node 1 | staging-valkey-001.zc3ep9.0001.use2.cache.amazonaws.com:6379 | production-valkey-001.zc3ep9.0001.use2.cache.amazonaws.com:6379  
Node 2 | staging-valkey-002.zc3ep9.0001.use2.cache.amazonaws.com:6379 | production-valkey-002.zc3ep9.0001.use2.cache.amazonaws.com:6379  
Security group | sg-0ec302e948493a190 | sg-09a9f6eba199245f6  
Transit encryption | false | false  
At-rest encryption | true | true  
  
Consumers that connect to the primary Valkey endpoint:

  * `api-backend` — stream producer for `phoenix:router:input` and CHR trigger stream
  * `phoenix-router` — stream consumer (`phoenix:router:input`), producer (`phoenix:parser:input`)
  * `phoenix-parser` — stream consumer (`phoenix:parser:input`), producer (`phoenix:grouper:input`)
  * `rosetta-grouper` — stream consumer (`phoenix:grouper:input`)
  * `data-validation-service` — stream consumer (`data-validation-input-queue`)
  * `forge-sentinel` — CHR job queue consumer (inferred)
  * `router-evals-service`, `parser-evals-service`, `grouper-evals-service` — eval stream consumers (staging only)
  * `argocd-redis` (separate — argocd namespace uses its own in-cluster Redis ClusterIP service `argocd-redis:6379`, not the Valkey cluster)

### NS-7.5 Developer read-only access (staging only)

WARP-enrolled devices (`@n1.healthcare` domain) can reach staging databases via Cloudflare Gateway DNS overrides:

DNS alias | Resolves to | Reaches  
---|---|---  
`db.staging.n1` | n1-staging-app.cluster-c3gc6ccoiwig.us-east-2.rds.amazonaws.com | Aurora staging app DB :5432  
`redis.staging.n1` | staging-valkey.zc3ep9.ng.0001.use2.cache.amazonaws.com | Valkey staging :6379  
  
The DNS override returns the private endpoint; the device reaches it over the WARP tunnel's private-network route into `10.80.0.0/16` **(inferred)**. Production databases have no equivalent WARP DNS override.

* * *

## NS-8. Per-environment differences

### Production only

Feature | Service(s) | Notes  
---|---|---  
Ingress proxy layer | api-proxy, auth-proxy, billing-proxy (:8888 each) | Sit between Cloudflare Tunnel and app services; not in staging  
PDF converter | pdf-converter (:9000) | PDF-to-image conversion for document pipeline  
Celery task monitor | celery-flower (:5555) | Celery task visibility  
Higher KEDA maxima | api-websocket-proxy (max=10 vs 5), pgbouncer (max=4 vs 3) | Prod handles more traffic  
  
### Staging only

Feature | Service(s) | Notes  
---|---|---  
Eval harness | router-evals-service, parser-evals-service, grouper-evals-service | 3 streams, KEDA min=1 max=5  
Automated testing | automated-testing (:8787) | Exposes `automated-testing.n1-research.com`  
Helix parser | helix-parser (:8080) | Staging-only experimental parser  
Gemma embeddings | embeddinggemma (:8000, metrics:9000) | Staging ai-inference only  
Graph database | memgraph (:7687 Bolt) | Graph DB, staging only  
Vector database | qdrant (:6333 HTTP, :6334 gRPC) | Vector DB, staging only  
Lighter KEDA | See §NS-4.6 | Lower maxima throughout  
WARP DB access | db.staging.n1 / redis.staging.n1 | Developer read-only; no production equivalent  
  
* * *

## NS-9. Diagram generation

### NS-9.1 Node list

Every node with its namespace/port/type, grouped by environment and trust boundary.

**External / internet**

  * `internet_users` — clinicians, developers
  * `react_frontend` — Cloudflare Worker @ app.n1.care
  * `warp_devices` — @n1.healthcare developer devices

**Cloudflare edge**

  * `cf_access` — Cloudflare Access (Google IdP)
  * `cf_waf` — Cloudflare WAF (production/n1.care only)
  * `tunnel_staging` — EKS Staging tunnel 03dae21f
  * `tunnel_prod` — EKS Production tunnel 5a3b0a66

**Staging cluster — namespace: staging**

  * `s_api_ws_proxy` — api-websocket-proxy :9999
  * `s_oathkeeper` — oathkeeper-proxy :4455
  * `s_api_backend` — api-backend :8080
  * `s_auth_svc` — authentication-service :9000
  * `s_kratos` — kratos-public :4433 / kratos-admin :4434
  * `s_hydra_pub` — hydra-public :4444
  * `s_hydra_adm` — hydra-admin :4445
  * `s_billing` — billing-service :4444
  * `s_admin_dash` — admin-dashboard :3000
  * `s_forge_agents` — forge-agents-api :8080
  * `s_phoenix_router` — phoenix-router :8080
  * `s_phoenix_parser` — phoenix-parser :8080
  * `s_rosetta_grouper` — rosetta-grouper :8080
  * `s_data_val` — data-validation-service (KEDA only, no ClusterIP listed)
  * `s_pgbouncer` — pgbouncer :6432 / metrics :9127
  * `s_automated_test` — automated-testing :8787 (staging only)
  * `s_helix` — helix-parser :8080 (staging only)
  * `s_memgraph` — memgraph :7687 (staging only)
  * `s_qdrant` — qdrant :6333/:6334 (staging only)
  * `s_oathkeeper_api` — oathkeeper-api :4456
  * `s_router_evals` — router-evals-service (staging only)
  * `s_parser_evals` — parser-evals-service (staging only)
  * `s_grouper_evals` — grouper-evals-service (staging only)

**Staging cluster — namespace: ai-inference**

  * `s_mineru` — mineru :8000
  * `s_embeddinggemma` — embeddinggemma :8000 / metrics :9000 (staging only)

**Staging cluster — namespace: llmproxy**

  * `s_litellm` — litellm :4000

**Staging cluster — namespace: monitoring**

  * `s_otel` — otel-collector otlp-grpc:4317 / otlp-http:4318

**Staging database VPC**

  * `s_aurora_app` — n1-staging-app Aurora :5432
  * `s_aurora_auth` — auth-staging Aurora :5432
  * `s_aurora_billing` — billing-staging Aurora :5432
  * `s_aurora_litellm` — litellm-staging Aurora :5432
  * `s_aurora_forge` — forge-runner-staging Aurora :5432
  * `s_valkey` — staging-valkey :6379

**Staging Valkey streams (logical nodes)**

  * `stream_router_input` — `phoenix:router:input`
  * `stream_parser_input` — `phoenix:parser:input`
  * `stream_grouper_input` — `phoenix:grouper:input`
  * `stream_data_val` — `data-validation-input-queue`
  * `stream_router_evals` — `phoenix:router-evals:input` (staging only)
  * `stream_parser_evals` — `phoenix:parser-evals:input` (staging only)
  * `stream_grouper_evals` — `phoenix:grouper-evals:input` (staging only)

**Production cluster — namespace: prod** (same shape as staging plus prod-only)

  * `p_api_proxy` — api-proxy :8888 (prod only)
  * `p_auth_proxy` — auth-proxy :8888 (prod only)
  * `p_billing_proxy` — billing-proxy :8888 (prod only)
  * `p_pdf_converter` — pdf-converter :9000 (prod only)
  * `p_celery_flower` — celery-flower :5555 (prod only)
  * `p_api_ws_proxy`, `p_oathkeeper`, `p_api_backend`, `p_auth_svc`, `p_kratos`, `p_hydra_pub`, `p_hydra_adm`, `p_billing`, `p_admin_dash`, `p_forge_agents`, `p_phoenix_router`, `p_phoenix_parser`, `p_rosetta_grouper`, `p_data_val`, `p_pgbouncer` — same ports as staging counterparts

**Production cluster — shared namespaces** (same ports as staging)

  * `p_mineru`, `p_litellm`, `p_otel`

**Production database VPC**

  * `p_aurora_app`, `p_aurora_auth`, `p_aurora_billing`, `p_aurora_litellm`, `p_aurora_forge`
  * `p_valkey` — production-valkey :6379

**External egress targets (both clusters)**

  * `ext_vertex_ai`, `ext_bedrock`, `ext_stripe`, `ext_postmark`, `ext_github`, `ext_ecr`, `ext_r2`, `ext_dhi`, `ext_slack`, `ext_clickup`, `ext_s3`, `ext_secrets_mgr`

### NS-9.2 Edge list

Format: `from → to : proto/port : type`

**Ingress edges (staging)**

  1. `internet_users → cf_access : HTTPS : ingress`
  2. `cf_access → tunnel_staging : route : ingress`
  3. `tunnel_staging → s_api_ws_proxy : WS:9999 : ingress` (path /ws/*)
  4. `tunnel_staging → s_oathkeeper : HTTP:4455 : ingress` (path /* excl /ws)
  5. `tunnel_staging → s_hydra_pub : HTTP:4444 : ingress` (oauth-staging.n1.care /oauth2/* etc.)
  6. `tunnel_staging → s_auth_svc : HTTP:9000 : ingress` (oauth-staging.n1.care /login,/consent,/logout)
  7. `tunnel_staging → s_admin_dash : HTTP:3000 : ingress` (staging-admin.n1-research.com, CF Access)
  8. `tunnel_staging → s_litellm : HTTP:4000 : ingress` (litellm-staging.n1-research.com)
  9. `tunnel_staging → s_automated_test : HTTP:8787 : ingress` (automated-testing.n1-research.com)
  10. `warp_devices → s_aurora_app : TCP:5432 : ingress` (db.staging.n1, WARP, read-only, inferred)
  11. `warp_devices → s_valkey : TCP:6379 : ingress` (redis.staging.n1, WARP, read-only, inferred)

**Ingress edges (production)** 12\. `internet_users → cf_access : HTTPS : ingress` 13\. `cf_access → tunnel_prod : route : ingress` 14\. `tunnel_prod → p_api_ws_proxy : WS:9999 : ingress` (api.n1.care /ws) 15\. `tunnel_prod → p_oathkeeper : HTTP:4455 : ingress` (api.n1.care /_) 16.`tunnel_prod → p_hydra_pub : HTTP:4444 : ingress` (oauth.n1.care /oauth2/_ etc.) 17\. `tunnel_prod → p_auth_svc : HTTP:9000 : ingress` (oauth.n1.care /login,/consent,/logout) 18\. `tunnel_prod → p_admin_dash : HTTP:3000 : ingress` (admin.n1-research.com, CF Access) 19\. `tunnel_prod → p_litellm : HTTP:4000 : ingress` (litellm-prod.n1-research.com)

**Synchronous call edges (staging)** 20\. `s_api_ws_proxy → s_api_backend : HTTP:8080 : sync` (WebSocket path forwarded) 21\. `s_oathkeeper → s_api_backend : HTTP:8080 : sync` (all API calls after auth decision) 22\. `s_oathkeeper → s_kratos : HTTP:4433 : sync` (session validation) 23\. `s_oathkeeper → s_auth_svc : HTTP:9000 : sync` (custom authenticator) 24\. `s_api_backend → s_forge_agents : HTTP:8080 : sync` (catalog reads) 25\. `s_api_backend → s_litellm : HTTP:4000 : sync` (LLM calls) 26\. `s_api_backend → s_pgbouncer : TCP:6432 : sync` (DB writes/reads) 27\. `s_auth_svc → s_kratos : HTTP:4433 : sync` (inferred) 28\. `s_auth_svc → s_hydra_adm : HTTP:4445 : sync` (inferred) 29\. `s_auth_svc → s_pgbouncer : TCP:6432 : sync` (inferred) 30\. `s_billing → s_pgbouncer : TCP:6432 : sync` (inferred) 31\. `s_litellm → s_pgbouncer : TCP:6432 : sync` (inferred) 32\. `s_phoenix_router → s_mineru : HTTP:8000 : sync` (page classification) 33\. `s_phoenix_parser → s_mineru : HTTP:8000 : sync` (inferred) 34\. `s_admin_dash → s_api_backend : HTTP:8080 : sync` (inferred)

**Stream edges (staging)** 35\. `s_api_backend → stream_router_input : write : stream` (`phoenix:router:input`) 36\. `stream_router_input → s_phoenix_router : read/KEDA : stream` 37\. `s_phoenix_router → stream_parser_input : write : stream` (`phoenix:parser:input`) 38\. `stream_parser_input → s_phoenix_parser : read/KEDA : stream` 39\. `s_phoenix_parser → stream_grouper_input : write : stream` (`phoenix:grouper:input`) 40\. `stream_grouper_input → s_rosetta_grouper : read/KEDA : stream` 41\. `s_rosetta_grouper → s_api_backend : HTTP:8080 : sync` (result write-back) 42\. `s_api_backend → stream_data_val : write : stream` (inferred) 43\. `stream_data_val → s_data_val : read/KEDA : stream` 44\. `stream_router_evals → s_router_evals : read/KEDA : stream` 45\. `stream_parser_evals → s_parser_evals : read/KEDA : stream` 46\. `stream_grouper_evals → s_grouper_evals : read/KEDA : stream`

**DB/cache edges (staging)** 47\. `s_pgbouncer → s_aurora_app : TCP:5432 : sync` (via peering, app DB) 48\. `s_auth_svc → s_aurora_auth : TCP:5432 : sync` (inferred, via peering, auth DB) 49\. `s_billing → s_aurora_billing : TCP:5432 : sync` (inferred, via peering, billing DB) 50\. `s_litellm → s_aurora_litellm : TCP:5432 : sync` (inferred, via peering) 51\. `forge_runner → s_aurora_forge : TCP:5432 : sync` (inferred, via peering, agno state) 52\. `s_api_backend → s_valkey : TCP:6379 : stream` (stream producer) 53\. `s_phoenix_router → s_valkey : TCP:6379 : stream` 54\. `s_phoenix_parser → s_valkey : TCP:6379 : stream` 55\. `s_rosetta_grouper → s_valkey : TCP:6379 : stream` 56\. `s_data_val → s_valkey : TCP:6379 : stream`

**Egress edges (both clusters — shown once)** 57\. `s_litellm → ext_vertex_ai : HTTPS:443 : egress` (inferred, via NAT) 58\. `s_litellm → ext_bedrock : HTTPS:443 : egress` (inferred, via NAT) 59\. `s_billing → ext_stripe : HTTPS:443 : egress` (inferred, via NAT) 60\. `s_auth_svc → ext_postmark : HTTPS:443 : egress` (inferred, via NAT) 61\. `[all pods] → ext_ecr : HTTPS:443 : egress` (inferred, image pulls via NAT) 62\. `[all pods] → ext_secrets_mgr : HTTPS:443 : egress` (inferred, ExternalSecrets via NAT) 63\. `s_api_backend → ext_s3 : HTTPS:443 : egress` (inferred, file storage via NAT)

**Production has the same sync/stream/DB/egress edge shape** — substitute `p_*` node IDs and add edges for the prod-only proxy layer (api-proxy, auth-proxy, billing-proxy at :8888).

### NS-9.3 Published visual source

The versioned SVG overview above is the published diagram. The node and edge lists in §§NS-9.1–NS-9.2 remain the complete implementation record.

* * *

## NS-10. Boundaries — what this document does not cover

Edges in §NS-3 are derived from Kubernetes Service definitions, KEDA ScaledObject stream trigger definitions, and the verified call/stream narrative in [09-APP-ARCHITECTURE.md](/landscape/app-architecture/). Any edge not directly observable from those sources is marked **(inferred)**. The node and edge lists are the retained historical source input for the versioned visual, not browser-rendered diagram code.

This document does not include: live packet captures or flow logs; exact per-pod ephemeral-port assignments; internal Ory mesh calls beyond the primary paths documented above; the AI/development cluster (`n1-ai-cluster`, account `083636777616`), which is out of scope; or intra-ArgoCD, intra-KEDA, or intra-kube-system call graphs. For VPC/subnet/route-table/peering detail, see [NETWORK.md](/landscape/network/). For the service repo/image mapping and dependency versions, see [DEPENDENCIES/00-BOM.md](/landscape/dependencies/00-bom/).
