---
title: N1 System Architecture
---

# N1 System Architecture

**Description:** Master architecture diagram spec for the N1 Healthcare platform. Render with a bespoke HTML diagram tool — not Mermaid.

**Generated:** 2026-06-10

<figure class="visual-frame">
  <img src="/visuals/architecture/system-architecture.svg" alt="N1 architecture overview: Cloudflare routes through identity and application services to Phoenix and Forge workloads, which use shared data stores and external providers.">
  <figcaption>Overview only; the service inventory and 52 verified connections below remain the authoritative detail. <a href="/visuals/architecture/system-architecture.svg" download>Download SVG source</a></figcaption>
</figure>

## Zones and Boundaries

Total zones: 6

### Edge (Cloudflare)

**ID:** `edge`

**Services:**

- `internet`

- `cloudflare-access`

- `cloudflare-tunnel`

- `react-frontend-worker`

### Identity & Auth

**ID:** `identity`

**Services:**

- `oathkeeper-proxy`

- `kratos-public`

- `kratos-admin`

- `hydra-public`

- `hydra-admin`

- `authentication-service`

### Application Layer

**ID:** `app`

**Services:**

- `api-websocket-proxy`

- `api-backend`

- `billing-service`

- `admin-dashboard`

- `litellm`

- `api-proxy`

- `auth-proxy`

- `billing-proxy`

- `forge-agents-api`

### Medical Record Pipeline (Phoenix)

**ID:** `pipeline`

**Services:**

- `phoenix-router`

- `phoenix-parser`

- `rosetta-grouper`

- `data-validation-service`

- `helix-parser`

- `mineru`

### CHR Generation (Forge)

**ID:** `forge`

**Services:**

- `forge-sentinel`

- `forge-runner`

### Data Stores

**ID:** `data`

**Services:**

- `valkey`

- `pgbouncer`

- `aurora-app`

- `aurora-auth`

- `aurora-billing`

- `aurora-litellm`

- `aurora-forge-runner`

- `s3-n1-user-data`

- `stripe-api`

- `vertex-ai-bedrock`

- `postmark`

## Service Details

## Data Flows

Total connections: 52

| From | To | Type | Description |
|------|-----|------|-------------|
| `internet` | `cloudflare-access` | `external` | HTTPS |
| `cloudflare-access` | `cloudflare-tunnel` | `external` | verified, forwarded |
| `cloudflare-tunnel` | `api-websocket-proxy` | `http` | WS:9999 /ws |
| `cloudflare-tunnel` | `oathkeeper-proxy` | `http` | HTTP:4455 /* (api/auth/billing hostnames) |
| `cloudflare-tunnel` | `hydra-public` | `http` | HTTP:4444 (oauth hostname /oauth2/*) |
| `cloudflare-tunnel` | `authentication-service` | `http` | HTTP:9000 (oauth hostname /login,/consent,/logout) |
| `cloudflare-tunnel` | `admin-dashboard` | `http` | HTTP:3000 (admin hostname, CF Access gated) |
| `cloudflare-tunnel` | `litellm` | `http` | HTTP:4000 (litellm hostname) |
| `api-websocket-proxy` | `api-backend` | `http` | HTTP:8080 |
| `oathkeeper-proxy` | `api-backend` | `http` | HTTP:8080 (api.n1.care/*) |
| `oathkeeper-proxy` | `kratos-public` | `http` | HTTP:4433 (session check) |
| `oathkeeper-proxy` | `authentication-service` | `http` | HTTP:9000 (custom authenticator) |
| `oathkeeper-proxy` | `billing-service` | `http` | HTTP:4444 (billing.n1.care/*) |
| `authentication-service` | `kratos-public` | `http` | HTTP:4433 (session/identity lookups) |
| `authentication-service` | `kratos-admin` | `http` | HTTP:4434 (admin ops) |
| `authentication-service` | `hydra-admin` | `http` | HTTP:4445 (OAuth client management) |
| `authentication-service` | `pgbouncer` | `db` | TCP:6432 → aurora-auth |
| `admin-dashboard` | `api-backend` | `http` | HTTP:8080 |
| `admin-dashboard` | `billing-service` | `http` | HTTP:4444 |
| `api-backend` | `forge-agents-api` | `http` | HTTP:8080 (skill/workflow catalogue) |
| `api-backend` | `litellm` | `http` | HTTP:4000 (all LLM calls) |
| `api-backend` | `pgbouncer` | `db` | TCP:6432 → aurora-app |
| `api-backend` | `s3-n1-user-data` | `external` | HTTPS:443 (file storage via NAT) |
| `api-backend` | `postmark` | `external` | HTTPS:443 (email via NAT) |
| `api-backend` | `valkey` | `db` | TCP:6379 (stream producer) |
| `api-backend` | `valkey` | `valkey-stream` | PRODUCE phoenix:router:input |
| `valkey` | `phoenix-router` | `valkey-stream` | CONSUME phoenix:router:input (KEDA, lag≥2, max=50) |
| `phoenix-router` | `mineru` | `http` | HTTP:8000 (page classification) |
| `phoenix-router` | `valkey` | `valkey-stream` | PRODUCE phoenix:parser:input |
| `valkey` | `phoenix-parser` | `valkey-stream` | CONSUME phoenix:parser:input (KEDA, lag≥2, max=50) |
| `phoenix-parser` | `mineru` | `http` | HTTP:8000 (content extraction) |
| `phoenix-parser` | `valkey` | `valkey-stream` | PRODUCE phoenix:grouper:input |
| `valkey` | `rosetta-grouper` | `valkey-stream` | CONSUME phoenix:grouper:input (KEDA, lag≥2, max=50) |
| `rosetta-grouper` | `api-backend` | `http` | HTTP:8080 (result write-back) |
| `api-backend` | `valkey` | `valkey-stream` | PRODUCE data-validation-input-queue |
| `valkey` | `data-validation-service` | `valkey-stream` | CONSUME data-validation-input-queue (KEDA, lag≥5, max=10) |
| `api-backend` | `valkey` | `valkey-stream` | PRODUCE forge-sentinel-stream (name inferred) |
| `valkey` | `forge-sentinel` | `valkey-stream` | CONSUME forge-sentinel-stream (inferred) |
| `forge-sentinel` | `forge-runner` | `other` | LAUNCH K8s Job |
| `forge-runner` | `api-backend` | `http` | HTTP:8080 (MCP tools — patient data reads) |
| `forge-runner` | `litellm` | `http` | HTTP:4000 (LLM calls for CHR steps) |
| `forge-runner` | `pgbouncer` | `db` | TCP:6432 → aurora-forge-runner (agno state) |
| `forge-runner` | `s3-n1-user-data` | `external` | HTTPS:443 (CHR report write via NAT) |
| `billing-service` | `pgbouncer` | `db` | TCP:6432 → aurora-billing (DRIFT: direct Aurora also in use) |
| `billing-service` | `stripe-api` | `external` | HTTPS:443 (via NAT) |
| `litellm` | `pgbouncer` | `db` | TCP:6432 → aurora-litellm |
| `litellm` | `vertex-ai-bedrock` | `external` | HTTPS:443 (Vertex AI + Bedrock via NAT) |
| `pgbouncer` | `aurora-app` | `db` | TCP:5432 (VPC peering) |
| `pgbouncer` | `aurora-auth` | `db` | TCP:5432 (VPC peering) |
| `pgbouncer` | `aurora-billing` | `db` | TCP:5432 (VPC peering) |
| `pgbouncer` | `aurora-litellm` | `db` | TCP:5432 (VPC peering) |
| `pgbouncer` | `aurora-forge-runner` | `db` | TCP:5432 (VPC peering) |
## Critical User Flows

## Service Inventory & Maturity

## System Spine / Core Routing

### _meta

- **generated:** 2026-06-10

- **trust_sources:** ['NETWORK-SERVICES.md (cluster-verified 2026-06-09)', 'NETWORK.md (cluster-verified 2026-06-09)', 'n1-helm-charts Argo CD app yamls + chart values + env overlays', 'signoz-live-services.txt (7-day window)', 'targets.jsonl (48 repos)', 'gh repo list n1healthcare --archived (live)']

- **notes:** ['forge-runner is a Kubernetes Job launched by forge-sentinel at runtime — not a persistent Deployment. It is not listed as a ClusterIP service in NS-2.', 'data-validation-service has a KEDA ScaledObject and Argo app in both clusters but is NOT listed in the NS-2 ClusterIP service catalogue — it appears to be a worker-only Deployment with no ClusterIP service.', 'react-frontend has a K8s Argo app (Caddy:8010) but NETWORK-SERVICES.md lists it as a Cloudflare Worker at app.n1.care. Both are true: the K8s pod is an origin; the Worker is the edge.', 'celery-flower exists as a prod ClusterIP service but has no Argo app or chart in n1-helm-charts. Origin of this deployment is UNKNOWN.', 'release-notes-publisher is deployed to both clusters via Argo but has no ClusterIP service entry in NS-2. It is a periodic automation job, not a request-serving service.', 'mineru uses an upstream vllm/vllm-openai image (not an n1-built ECR image). The inference-servers repo contains the Dockerfile/config used to build an n1-customised variant.']

### Microservices Catalog

| Service | Namespace | Ports | Source Repo | Prod | Staging | Instrumented | Notes |
|---------|-----------|-------|-------------|------|---------|---------------|-------|
| `api-backend` | `staging,prod` | `http:8080` | `api-backend` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `api-websocket-proxy` | `staging,prod` | `http:9999` | `api-websocket-proxy` | ✅ Yes | ✅ Yes | ✅ Yes |  |
| `authentication-service` | `staging,prod` | `http:9000` | `authentication-service` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `billing-service` | `staging,prod` | `http:4444` | `billing-service` | ✅ Yes | ✅ Yes | ✅ Yes |  |
| `admin-dashboard` | `staging,prod` | `http:3000` | `admin-dashboard` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `forge-agents-api` | `staging,prod` | `http:8080` | `forge-runner` | ✅ Yes | ✅ Yes | ⚠️ No | Serves agent/workflow catalog via uvicorn. ECR image: n1-{env}/forge-runner. Command overridden to run forge_runner.agents_server:app. |
| `phoenix-router` | `staging,prod` | `http:8080` | `parser-router` | ✅ Yes | ✅ Yes | ⚠️ No | ECR repo n1-{env}/phoenix-router. SERVICE_NAME=phoenix-router in Dockerfile. |
| `phoenix-parser` | `staging,prod` | `http:8080` | `parser-sequential` | ✅ Yes | ✅ Yes | ⚠️ No | ECR repo n1-{env}/phoenix-parser. deploy_aws.yaml service_name=phoenix-parser. |
| `rosetta-grouper` | `staging,prod` | `http:8080` | `rosetta-grouper` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `data-validation-service` | `staging,prod` | `` | `data-validation-service` | ✅ Yes | ✅ Yes | ⚠️ No | Deployment/KEDA consumer only — no ClusterIP service in NS-2 catalogue. |
| `forge-sentinel` | `staging,prod` | `` | `forge-sentinel` | ✅ Yes | ✅ Yes | ⚠️ No | Stream consumer + job launcher. ECR repo n1-{env}/forge-sentinel. Not in NS-2 ClusterIP table. |
| `oathkeeper-proxy` | `staging,prod` | `http:4455` | `UPSTREAM:oryd/oathkeeper` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `oathkeeper-api` | `staging,prod` | `http:4456` | `UPSTREAM:oryd/oathkeeper` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `kratos-public` | `staging,prod` | `http:4433` | `UPSTREAM:oryd/kratos` | ✅ Yes | ✅ Yes | ✅ Yes | SigNoz shows 'kratos' instrumented. |
| `kratos-admin` | `staging,prod` | `http:4434` | `UPSTREAM:oryd/kratos` | ✅ Yes | ✅ Yes | ✅ Yes |  |
| `hydra-public` | `staging,prod` | `http:4444` | `UPSTREAM:oryd/hydra` | ✅ Yes | ✅ Yes | ✅ Yes | SigNoz shows 'hydra' instrumented. |
| `hydra-admin` | `staging,prod` | `http:4445` | `UPSTREAM:oryd/hydra` | ✅ Yes | ✅ Yes | ✅ Yes |  |
| `pgbouncer` | `staging,prod` | `pgbouncer:6432, metrics:9127` | `UPSTREAM:pgbouncer` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `litellm` | `llmproxy (staging+prod)` | `http:4000` | `n1-litellm` | ✅ Yes | ✅ Yes | ⚠️ No | ECR repo n1-prod/litellm. n1-litellm repo is the N1 customisation/config wrapper around upstream LiteLLM. |
| `mineru` | `ai-inference (staging+prod)` | `http:8000` | `inference-servers` | ✅ Yes | ✅ Yes | ⚠️ No | Uses upstream vllm/vllm-openai:v0.10.2 image (ECR mirror). inference-servers/mineru-vllm contains the customised Dockerfile. |
| `otel-collector` | `monitoring (staging+prod)` | `otlp-grpc:4317, otlp-http:4318, metrics:8888` | `UPSTREAM:otel/opentelemetry-collector` | ✅ Yes | ✅ Yes | ⚠️ No |  |
| `api-proxy` | `prod` | `http:8888` | `api-proxy` | ✅ Yes | ❌ No | ⚠️ No |  |
| `auth-proxy` | `prod` | `http:8888` | `api-proxy` | ✅ Yes | ❌ No | ⚠️ No | auth-proxy and billing-proxy both use the api-proxy ECR image. Same source repo, different service config. |
| `billing-proxy` | `prod` | `http:8888` | `api-proxy` | ✅ Yes | ❌ No | ⚠️ No |  |
| `pdf-converter` | `prod` | `http:9000` | `ARCHIVED:pdf-converter` | ✅ Yes | ❌ No | ⚠️ No | DRIFT FINDING: pdf-converter GitHub repo is ARCHIVED but the service is still deployed in prod. ECR image n1-prod/pdf-converter still in use. |
| `celery-flower` | `prod` | `http:5555` | `UNKNOWN` | ✅ Yes | ❌ No | ⚠️ No | Prod ClusterIP service exists per NETWORK-SERVICES.md but NO Argo app or Helm chart found in n1-helm-charts. Deployment origin unknown — likely manually applied. |
| `helix-parser` | `staging` | `http:8080` | `helix-parser` | ❌ No | ✅ Yes | ⚠️ No | Staging-only experimental parser. Has a prod Argo app yaml but NETWORK-SERVICES.md lists it as staging-only. Prod Argo app may be a misconfiguration or inactive. |
| `automated-testing` | `staging` | `http:8787` | `automated-testing` | ❌ No | ✅ Yes | ⚠️ No |  |
| `embeddinggemma` | `ai-inference (staging)` | `http:8000, metrics:9000` | `inference-servers` | ❌ No | ✅ Yes | ⚠️ No |  |
| `memgraph` | `staging` | `bolt:7687` | `UPSTREAM:memgraph` | ❌ No | ✅ Yes | ⚠️ No |  |
| `qdrant` | `staging` | `http:6333, grpc:6334` | `UPSTREAM:qdrant/qdrant` | ❌ No | ✅ Yes | ⚠️ No |  |
| `react-frontend` | `staging,prod` | `http:8010` | `react-frontend` | ✅ Yes | ✅ Yes | ✅ Yes | SigNoz shows 'react-frontend' (RUM). Deployed as K8s ClusterIP (Caddy:8010) AND exposed as Cloudflare Worker at app.n1.care. Both are active. |
| `n1-api-slack-bot` | `staging` | `` | `n1-api-slack-bot` | ❌ No | ✅ Yes | ⚠️ No |  |
| `router-evals-service` | `staging` | `` | `UNKNOWN` | ❌ No | ✅ Yes | ⚠️ No | KEDA-only worker. No source repo identified in 48 targets. |
| `parser-evals-service` | `staging` | `` | `UNKNOWN` | ❌ No | ✅ Yes | ⚠️ No | KEDA-only worker. No source repo identified in 48 targets. |
| `grouper-evals-service` | `staging` | `` | `UNKNOWN` | ❌ No | ✅ Yes | ⚠️ No | KEDA-only worker. No source repo identified in 48 targets. |
| `release-notes-publisher` | `staging,prod (argocd)` | `` | `release-scribe` | ✅ Yes | ✅ Yes | ⚠️ No | Automation job — no ClusterIP, not request-serving. |
### Service to Repository Mapping

| Service Name | Repository |
|--------------|------------|
| `api-backend` | `api-backend` |
| `api-websocket-proxy` | `api-websocket-proxy` |
| `authentication-service` | `authentication-service` |
| `billing-service` | `billing-service` |
| `admin-dashboard` | `admin-dashboard` |
| `react-frontend` | `react-frontend` |
| `forge-agents-api` | `forge-runner` |
| `forge-sentinel` | `forge-sentinel` |
| `forge-runner` | `forge-runner` |
| `phoenix-router` | `parser-router` |
| `phoenix-parser` | `parser-sequential` |
| `rosetta-grouper` | `rosetta-grouper` |
| `data-validation-service` | `data-validation-service` |
| `helix-parser` | `helix-parser` |
| `automated-testing` | `automated-testing` |
| `litellm` | `n1-litellm` |
| `mineru` | `inference-servers` |
| `embeddinggemma` | `inference-servers` |
| `api-proxy` | `api-proxy` |
| `auth-proxy` | `api-proxy` |
| `billing-proxy` | `api-proxy` |
| `pdf-converter` | `ARCHIVED:pdf-converter` |
| `celery-flower` | `UNKNOWN` |
| `n1-api-slack-bot` | `n1-api-slack-bot` |
| `oathkeeper-proxy` | `UPSTREAM:oryd/oathkeeper` |
| `kratos-public` | `UPSTREAM:oryd/kratos` |
| `kratos-admin` | `UPSTREAM:oryd/kratos` |
| `hydra-public` | `UPSTREAM:oryd/hydra` |
| `hydra-admin` | `UPSTREAM:oryd/hydra` |
| `pgbouncer` | `UPSTREAM:pgbouncer` |
| `otel-collector` | `UPSTREAM:opentelemetry-collector` |
| `memgraph` | `UPSTREAM:memgraph` |
| `qdrant` | `UPSTREAM:qdrant/qdrant` |
| `release-notes-publisher` | `release-scribe` |
### Service Dependency & Ingress Edges

| From | To | Kind | Protocol & Port | Category |
|------|----|------|-----------------|----------|
| `internet` | `cloudflare-access` | `external` | HTTPS | `other` |
| `cloudflare-tunnel` | `api-websocket-proxy` | `http` | WS:9999 /ws | `other` |
| `cloudflare-tunnel` | `oathkeeper-proxy` | `http` | HTTP:4455 /* (api, auth, billing hostnames) | `other` |
| `cloudflare-tunnel` | `hydra-public` | `http` | HTTP:4444 (oauth hostname /oauth2/*) | `token` |
| `cloudflare-tunnel` | `authentication-service` | `http` | HTTP:9000 (oauth hostname /login,/consent,/logout) | `identity` |
| `cloudflare-tunnel` | `admin-dashboard` | `http` | HTTP:3000 (admin hostname, CF Access gated) | `other` |
| `cloudflare-tunnel` | `litellm` | `http` | HTTP:4000 (litellm hostname) | `other` |
| `api-websocket-proxy` | `api-backend` | `http` | HTTP:8080 | `other` |
| `oathkeeper-proxy` | `api-backend` | `http` | HTTP:8080 (api.n1.care/*) | `other` |
| `oathkeeper-proxy` | `kratos-public` | `http` | HTTP:4433 (session check) | `identity` |
| `oathkeeper-proxy` | `authentication-service` | `http` | HTTP:9000 (custom authenticator) | `identity` |
| `oathkeeper-proxy` | `billing-service` | `http` | HTTP:4444 (billing.n1.care/*) | `payment` |
| `api-backend` | `forge-agents-api` | `http` | HTTP:8080 (N1-Api-Key header; /agents/skills/, /agents/workflows/) | `clinical-output` |
| `api-backend` | `litellm` | `http` | HTTP:4000 (all LLM calls) | `clinical-output` |
| `api-backend` | `pgbouncer` | `db` | TCP:6432 (app Aurora n1-{env}-app :5432) | `record` |
| `authentication-service` | `kratos-public` | `http` | HTTP:4433 (session/identity lookups) | `identity` |
| `authentication-service` | `kratos-admin` | `http` | HTTP:4434 (admin ops) | `identity` |
| `authentication-service` | `hydra-admin` | `http` | HTTP:4445 (OAuth client management) | `token` |
| `authentication-service` | `pgbouncer` | `db` | TCP:6432 (auth Aurora auth-{env} :5432) | `identity` |
| `billing-service` | `pgbouncer` | `db` | TCP:6432 (billing Aurora billing-{env} :5432) | `payment` |
| `billing-service` | `stripe-api` | `external` | HTTPS:443 (via NAT) | `payment` |
| `litellm` | `pgbouncer` | `db` | TCP:6432 (litellm Aurora litellm-{env} :5432) | `other` |
| `litellm` | `vertex-ai-bedrock` | `external` | HTTPS:443 (via NAT; Vertex AI + Bedrock) | `clinical-output` |
| `admin-dashboard` | `api-backend` | `http` | HTTP:8080 | `other` |
| `admin-dashboard` | `billing-service` | `http` | HTTP:4444 | `payment` |
| `api-backend` | `phoenix:router:input` | `valkey-stream` | PRODUCE stream:phoenix:router:input | `record` |
| `phoenix:router:input` | `phoenix-router` | `valkey-stream` | CONSUME (KEDA consumerGroup:router-group, lag≥2, max=50) | `record` |
| `phoenix-router` | `mineru` | `http` | HTTP:8000 (page classification) | `record` |
| `phoenix-router` | `phoenix:parser:input` | `valkey-stream` | PRODUCE stream:phoenix:parser:input | `record` |
| `phoenix:parser:input` | `phoenix-parser` | `valkey-stream` | CONSUME (KEDA consumerGroup:parser-group, lag≥2, max=50) | `record` |
| `phoenix-parser` | `mineru` | `http` | HTTP:8000 (content extraction) | `record` |
| `phoenix-parser` | `phoenix:grouper:input` | `valkey-stream` | PRODUCE stream:phoenix:grouper:input | `record` |
| `phoenix:grouper:input` | `rosetta-grouper` | `valkey-stream` | CONSUME (KEDA consumerGroup:rosetta-grouper, lag≥2, max=50) | `record` |
| `rosetta-grouper` | `api-backend` | `http` | HTTP:8080 (result write-back via n1 api client) | `record` |
| `rosetta-grouper` | `valkey` | `db` | TCP:6379 (stream consumer) | `record` |
| `api-backend` | `data-validation-input-queue` | `valkey-stream` | PRODUCE stream:data-validation-input-queue | `record` |
| `data-validation-input-queue` | `data-validation-service` | `valkey-stream` | CONSUME (KEDA consumerGroup:data-validation-consumer-group, lag≥5, max=10) | `record` |
| `api-backend` | `forge-sentinel-stream` | `valkey-stream` | PRODUCE (inferred — CHR trigger stream, name not in ScaledObjects) | `clinical-output` |
| `forge-sentinel-stream` | `forge-sentinel` | `valkey-stream` | CONSUME (inferred) | `clinical-output` |
| `forge-sentinel` | `forge-runner` | `other` | LAUNCH k8s Job (forge-runner + workflow images) | `clinical-output` |
| `forge-runner` | `api-backend` | `http` | HTTP:8080 (MCP tools — patient data reads) | `clinical-output` |
| `forge-runner` | `litellm` | `http` | HTTP:4000 (LLM calls for CHR workflow steps) | `clinical-output` |
| `forge-runner` | `pgbouncer` | `db` | TCP:6432 (forge-runner Aurora forge-runner-{env} :5432 — agno state/LangGraph checkpoints) | `clinical-output` |
| `forge-runner` | `s3-n1-user-data` | `external` | HTTPS:443 (CHR report write to S3 n1-{env}-user-data via NAT) | `clinical-output` |
| `pgbouncer` | `aurora-app` | `db` | TCP:5432 (via VPC peering pcx-…; app DB) | `record` |
| `api-backend` | `valkey` | `db` | TCP:6379 (stream producer) | `record` |
| `phoenix-router` | `valkey` | `db` | TCP:6379 | `record` |
| `phoenix-parser` | `valkey` | `db` | TCP:6379 | `record` |
| `api-backend` | `s3-n1-user-data` | `external` | HTTPS:443 (file storage via NAT) | `record` |
| `api-backend` | `postmark` | `external` | HTTPS:443 (email via NAT) | `identity` |
### Repository Classification & Tiering

| Repository | Tier | Role | Deployed As | Architecture Description |
|------------|------|------|-------------|--------------------------|
| `api-backend` | **Tier 1** | `prod-service` | `api-backend` | Core Python API — central hub of the prod network graph; every request path touches it. |
| `authentication-service` | **Tier 1** | `prod-service` | `authentication-service` | Ory glue layer for auth; in every user request path. |
| `billing-service` | **Tier 1** | `prod-service` | `billing-service` | Stripe billing; prod + staging, in network graph. |
| `parser-router` | **Tier 1** | `prod-service` | `phoenix-router` | First stage of medical-record pipeline; prod + staging KEDA worker, in network graph. |
| `parser-sequential` | **Tier 1** | `prod-service` | `phoenix-parser` | Clinical data extractor; second pipeline stage, prod + staging KEDA worker. |
| `rosetta-grouper` | **Tier 1** | `prod-service` | `rosetta-grouper` | BiomarkerDefinition grouper; final pipeline stage writing back to api-backend. |
| `forge-sentinel` | **Tier 1** | `prod-service` | `forge-sentinel` | CHR pipeline orchestrator; consumes stream, launches forge-runner Jobs. PHI flows through it. |
| `forge-runner` | **Tier 1** | `prod-service` | `forge-runner (k8s Job) + forge-agents-api (Deployment)` | CHR workflow execution engine (agno/LangGraph). PHI + clinical-output; forge-agents-api also uses this image. |
| `api-websocket-proxy` | **Tier 1** | `prod-service` | `api-websocket-proxy` | Go WebSocket proxy; in prod ingress critical path. |
| `react-frontend` | **Tier 1** | `frontend` | `react-frontend` | Clinician-facing SPA. K8s + Cloudflare Worker; SigNoz RUM instrumented. |
| `n1-litellm` | **Tier 1** | `prod-service` | `litellm` | All LLM calls from api-backend and forge-runner route through this proxy; critical for CHR pipeline. |
| `api-proxy` | **Tier 1** | `prod-service` | `api-proxy + auth-proxy + billing-proxy` | Prod-only ingress proxy layer for all three public-facing services. |
| `data-validation-service` | **Tier 1** | `prod-service` | `data-validation-service` | Validates record data in prod+staging; KEDA-scaled stream consumer on the medical-record path. |
| `admin-dashboard` | **Tier 2** | `frontend` | `admin-dashboard` | Internal admin UI; prod+staging but not in public critical path; CF Access gated. |
| `phoenix-platform` | **Tier 2** | `library` | `N/A` | Python library n1r-phoenix (v5.0.0); imported by parser-router and parser-sequential. Not a deployed service. |
| `n1r-rosetta` | **Tier 2** | `library` | `N/A` | Python library n1r-rosetta (v1.0.0); imported by rosetta-grouper. |
| `n1r-cortex` | **Tier 2** | `library` | `N/A` | Python library n1r-cortex (v0.9.1); used by forge-runner/forge-sentinel for orchestration primitives. |
| `n1r-telemetry` | **Tier 2** | `library` | `N/A` | Shared OTel setup library. Used org-wide to pin OTel version. |
| `n1-document-manager` | **Tier 2** | `library` | `N/A` | Python library n1r-document-manager; MCP document-manager tool (SigNoz confirms forge runs it). |
| `medical-unit-conversion` | **Tier 2** | `library` | `N/A` | Python library for medical unit conversion with AI fallback; likely imported by pipeline/forge-runner. |
| `api-N1-clients` | **Tier 2** | `library` | `N/A` | N1 API client library; used by forge-runner (MCP tools call api-backend) and other services. |
| `n1-ai-toolkit` | **Tier 2** | `library` | `N/A` | AI/LLM utilities used by pipeline services. Not a deployed service. |
| `inference-servers` | **Tier 2** | `infra` | `mineru (ai-inference ns) + embeddinggemma (staging)` | Dockerfiles and configs for inference servers. mineru and embeddinggemma images built from subdirectories. |
| `n1-helm-charts` | **Tier 2** | `infra` | `N/A` | All Helm charts + Argo CD app definitions for every deployed service. Foundational infra dependency. |
| `n1-infrastructure` | **Tier 2** | `infra` | `N/A` | AWS, GCP, GitHub policies and infra scripts. Not a deployed service but underpins all prod infra. |
| `helix-parser` | **Tier 2** | `prod-service` | `helix-parser` | Experimental parser deployed to staging (and has a prod Argo app yaml). Active development; T2 pending prod promotion. |
| `automated-testing` | **Tier 2** | `tooling` | `automated-testing` | Staging-only automated test runner service. Not in prod critical path. |
| `parser-gate` | **Tier 2** | `tooling` | `N/A` | Parser validation gate tool (parsergate Python package + test runner). Used in CI/testing pipeline. |
| `parser-test-suite` | **Tier 2** | `tooling` | `N/A` | E2E Playwright + Python test suite for the parser pipeline. Backs automated-testing service. |
| `n1-signoz` | **Tier 2** | `infra` | `N/A` | SigNoz dashboards, alerts, and configuration. Observability infra for the prod platform. |
| `bastion` | **Tier 3** | `infra` | `N/A` | Security rules/standards for Claude Code and agent tooling. Not a deployed service. |
| `n1-security` | **Tier 3** | `tooling` | `N/A` | Security tooling: Cloudflare Zero Trust config, detection/response scripts, YARA rules, repo recreation. Ops tooling only. |
| `github-action-deployment-approval` | **Tier 3** | `tooling` | `N/A` | Custom GitHub Action for deployment approval gates in CI. Tooling only. |
| `release-scribe` | **Tier 3** | `tooling` | `release-notes-publisher` | Automated release notes publisher. Deployed as a periodic job but not request-serving. |
| `litellm-slack-bot` | **Tier 3** | `tooling` | `N/A` | Slack bot for LiteLLM usage monitoring. Internal tooling; no Argo app found in targets. |
| `n1-api-slack-bot` | **Tier 3** | `tooling` | `n1-api-slack-bot` | Staging-only Slack bot. Not prod-critical. |
| `gitpulse` | **Tier 3** | `tooling` | `N/A` | Developer activity/commit reporting tool. Internal tooling. |
| `code-intelligence` | **Tier 3** | `tooling` | `N/A` | Code analysis tooling. Internal dev tooling. |
| `git-supply-chain-forensics` | **Tier 3** | `tooling` | `N/A` | Supply chain security forensics scripts. Security tooling. |
| `misc-scripts` | **Tier 3** | `tooling` | `N/A` | Miscellaneous ops/data scripts. Not deployed. |
| `n1-qa` | **Tier 3** | `tooling` | `N/A` | QA harness (Playwright). Test tooling only. |
| `n1-standards` | **Tier 3** | `tooling` | `N/A` | Engineering standards and Claude Code plugin/bastion rules. Documentation/tooling. |
| `skills-marketplace` | **Tier 3** | `tooling` | `N/A` | Feature management/plans JSON. Internal product tooling. |
| `developer-portal` | **Tier 3** | `tooling` | `N/A` | Developer portal (React app). Internal tooling/docs. |
| `n1care-website` | **Tier 3** | `tooling` | `N/A` | Marketing/product website (Eleventy SSG). Not a K8s service. |
| `internal-docs-confidential` | **Tier 3** | `tooling` | `N/A` | HTML-rendered internal docs (internal.n1-research.com). Not a K8s service. |
| `organisation` | **Tier 3** | `tooling` | `N/A` | Organisational context/CLAUDE.md docs repo. Not deployed. |
| `archive-chr` | **Tier 3** | `dead-candidate` | `N/A` | Name suggests archived CHR-related code. No Argo app, no imports from other active services found. |
### Critical Execution Paths

| Path Name | Ingress Point | Service Hops | Assets Touched | Criticality Rationale |
|-----------|---------------|--------------|----------------|-----------------------|
| **medical-record-upload-to-parsed-grouped** | api.n1.care → oathkeeper-proxy (HTTP:4455) → api-backend | `cloudflare-tunnel` → `oathkeeper-proxy` → `api-backend` → `phoenix:router:input (valkey stream)` → `phoenix-router` → `mineru` → `phoenix:parser:input (valkey stream)` → `phoenix-parser` → `mineru` → `phoenix:grouper:input (valkey stream)` → `rosetta-grouper` → `api-backend (write-back)` | `PHI, clinical-output` | End-to-end medical record ingestion and structuring pipeline. All PHI transit. Failure stops all CHR generation. KEDA auto-scale at each stage (max 50 replicas). |
| **chr-generation** | api-backend (triggered by user action or pipeline completion) → forge-sentinel stream | `api-backend` → `forge-sentinel-stream (valkey stream — inferred)` → `forge-sentinel` → `forge-runner (k8s Job)` → `api-backend (MCP data reads)` → `litellm (LLM steps)` → `pgbouncer (agno state → forge-runner Aurora)` → `s3-n1-user-data (report write)` | `PHI, clinical-output` | Generates the primary clinical deliverable (Comprehensive Health Report). Multi-LLM, multi-step agentic workflow. PHI read from api-backend, clinical output written to S3. forge-sentinel stream name is INFERRED — not confirmed in ScaledObjects. |
| **user-auth-and-session** | auth.n1.care → oathkeeper-proxy → authentication-service / kratos-public | `cloudflare-tunnel` → `oathkeeper-proxy` → `kratos-public` → `authentication-service` → `hydra-admin (OAuth client mgmt)` → `pgbouncer (auth Aurora)` | `identity` | Every authenticated API request gate. Ory Kratos + Hydra + custom auth layer. Kratos and Hydra are the only two Ory services with SigNoz telemetry. |
| **oauth2-token-issuance** | oauth.n1.care → hydra-public (direct, NOT through Oathkeeper) | `cloudflare-tunnel` → `hydra-public` → `authentication-service (consent/login callbacks)` → `pgbouncer (auth Aurora)` | `identity, token` | OAuth2 token issuance for API clients. hydra-public is the only path that bypasses Oathkeeper — any vulnerability here skips the auth decision layer. |
| **billing-subscription** | billing.n1.care → oathkeeper-proxy → billing-service | `cloudflare-tunnel` → `oathkeeper-proxy` → `billing-service` → `pgbouncer (billing Aurora)` → `stripe-api (external)` | `money, identity` | All subscription and payment operations. Stripe integration. Billing data in dedicated Aurora cluster. |
| **data-validation** | api-backend PRODUCE → data-validation-input-queue (valkey stream) | `api-backend` → `data-validation-input-queue (valkey stream)` → `data-validation-service` | `PHI, record` | Validates medical record data quality before downstream processing. If this fails silently, bad data propagates to CHR generation. |
| **llm-proxy-all-inference** | api-backend or forge-runner → litellm:4000 | `api-backend / forge-runner` → `litellm` → `vertex-ai / bedrock (external via NAT)` | `PHI, clinical-output` | All LLM inference for both direct API features and CHR generation routes through a single litellm instance. Single point of failure for all AI features. PHI may appear in prompts. |
### Infrastructure & Deployment Drift Findings

| ID | Severity | Finding Title | Source | Impact & Detail |
|----|----------|---------------|--------|-----------------|
| `DRIFT-001` | 🔴 High | **pdf-converter GitHub repo is ARCHIVED but still deployed to prod** | archived repo list vs prod Argo app | The pdf-converter repo appears in `gh repo list n1healthcare --archived`. However it has an active Argo CD application in /argocd/applications/prod/pdf-converter.yaml and is listed as a live prod service in NETWORK-SERVICES.md (NS-2.2). The ECR image n1-prod/pdf-converter is still being pulled. No active source repo to receive security patches or dependency updates. |
| `DRIFT-002` | 🟡 Medium | **celery-flower in prod namespace has no Argo app or Helm chart** | NS-2.2 vs argocd/applications/prod | NETWORK-SERVICES.md lists celery-flower as a prod-only ClusterIP service on :5555. No matching Argo CD application or Helm chart was found in n1-helm-charts. This service appears to have been manually applied to the cluster — it is outside GitOps control. |
| `DRIFT-003` | 🟡 Medium | **4 orphaned KEDA ScaledObjects in production referencing non-existent Deployments** | NETWORK-SERVICES.md NS-4.5 | grouping-poller-service, grouping-service, parser-service, router-service ScaledObjects remain in production from the pre-Phoenix pipeline migration. Target Deployments do not exist; they watch legacy redis LIST queues (not Valkey streams). Cluster-noise and potential confusion during incident response. |
| `DRIFT-004` | 🔵 Low | **forge-sentinel stream name not confirmed in ScaledObjects** | NETWORK-SERVICES.md NS-4.2 annotation | NETWORK-SERVICES.md marks the CHR trigger stream consumed by forge-sentinel as '(inferred — stream name not in ScaledObjects)'. The stream exists functionally (forge-runner Jobs are launched) but the stream key is undocumented. forge-sentinel may use a polling/subscription model rather than KEDA. |
| `DRIFT-005` | 🔵 Low | **data-validation-service not in NS-2 ClusterIP catalogue** | NS-2 table vs KEDA ScaledObject list vs Argo apps | data-validation-service has KEDA ScaledObjects in both clusters and Argo apps, but it is NOT listed in the NS-2 service catalogue tables. It is a worker-only Deployment with no ClusterIP service, but the omission from the catalogue creates an incomplete picture of deployed services. |
| `DRIFT-006` | 🔵 Low | **helix-parser has a prod Argo app yaml but NETWORK-SERVICES.md lists it as staging-only** | argocd/applications/prod vs NETWORK-SERVICES.md NS-8 | /argocd/applications/prod/helix-parser.yaml exists. NETWORK-SERVICES.md NS-8 states helix-parser is staging-only. Either the prod Argo app is inactive/unused or the network doc is stale. |
| `DRIFT-007` | ⚪ Info | **Known archived repos still referenced in docs** | gh repo list n1healthcare --archived + NETWORK-SERVICES.md cross-reference | The following repos are confirmed archived and excluded from live-service analysis: direct-parser, OcrRouter, parser-agentic, parser-v3-poc, chart-service, easy-chr, report-evaluation-service, n1.careV2, queue-dashboard, phoenix-view, twin-react-frontend, marketing-studio, e2e-tests. Additionally: pdf-converter (DRIFT-001 above), and the following workflow-specific repos now folded into forge-runner: workflow-functional, workflow-generative-sequential, workflow-generative-langroid, workflow-data-analysis, workflow-claude-code, workflow-claude-sdk, workflow-abc. |
| `DRIFT-008` | 🔵 Low | **Valkey transit encryption disabled on both clusters** | NETWORK-SERVICES.md NS-7.4 | NETWORK-SERVICES.md NS-7.4 explicitly states transitEncryptionEnabled: false for both staging and production Valkey clusters. All Valkey stream traffic (including PHI in the medical-record pipeline) is unencrypted in transit within the database VPC. At-rest encryption is enabled. |
| `DRIFT-009` | ⚪ Info | **EKS API-server public endpoint open to 0.0.0.0/0** | NETWORK.md §2.3, §3.3 | Both staging and production EKS clusters have endpointPublicAccess=true with publicAccessCidrs=0.0.0.0/0. Authentication is IAM/OIDC. Not a misconfiguration per se, but broadens the attack surface for the control plane. |
| `DRIFT-010` | ⚪ Info | **No VPC endpoints — all AWS API traffic egresses via NAT** | NETWORK.md §1, §5 | S3, ECR, Secrets Manager, and STS traffic all routes through the single NAT gateway (us-east-2a) rather than private VPC endpoints. Single-AZ egress dependency for all image pulls, secret fetches, and S3 operations. Cost and blast-radius concern. |
### Observability & Telemetry Gaps

| Service | Prod Deployed | Telemetry Gap Analysis |
|---------|---------------|------------------------|
| `api-backend` | ✅ Yes | No SigNoz telemetry. Central API hub handling all PHI access — highest priority instrumentation gap. |
| `oathkeeper-proxy` | ✅ Yes | No SigNoz telemetry. Every authenticated request passes through it. |
| `authentication-service` | ✅ Yes | No SigNoz telemetry. Custom Ory glue layer. |
| `phoenix-router` | ✅ Yes | No SigNoz telemetry. First stage of PHI medical-record pipeline. |
| `phoenix-parser` | ✅ Yes | No SigNoz telemetry. Clinical data extractor — PHI-heavy. |
| `rosetta-grouper` | ✅ Yes | No SigNoz telemetry. Final pipeline stage writing structured records back to api-backend. |
| `data-validation-service` | ✅ Yes | No SigNoz telemetry. Silent failures here propagate bad data to CHR. |
| `forge-sentinel` | ✅ Yes | No SigNoz telemetry for the sentinel itself. Forge runner workflows (health-summary, longitudinal-report) ARE instrumented — but the orchestrator/launcher is dark. |
| `litellm` | ✅ Yes | No SigNoz telemetry. All LLM inference (PHI in prompts) routes through a single un-traced proxy. |
| `pgbouncer` | ✅ Yes | No SigNoz telemetry. All DB connections pool through this. Prometheus metrics port exists (:9127) but no SigNoz trace correlation. |
| `admin-dashboard` | ✅ Yes | No SigNoz telemetry. |
| `pdf-converter` | ✅ Yes | No SigNoz telemetry. Also DRIFT-001: archived source repo. |
| `celery-flower` | ✅ Yes | No SigNoz telemetry. Also DRIFT-002: outside GitOps control. |
| `api-proxy` | ✅ Yes | No SigNoz telemetry. Prod-only ingress proxy for all API traffic. |
| `auth-proxy` | ✅ Yes | No SigNoz telemetry. |
| `billing-proxy` | ✅ Yes | No SigNoz telemetry. |
| `mineru` | ✅ Yes | No SigNoz telemetry. Called by phoenix-router and phoenix-parser on every page of every medical record. |
