---
title: "Application architecture — N1 IT Landscape"
---

N1 IT Landscape — The Blueprint · CF-Access internal

# Application architecture

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

# N1 IT Landscape — Application architecture

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

_What N1 actually does, end to end: the request path, the medical-record ingestion pipeline, and Comprehensive Health Report generation._

* * *

## 10\. APPLICATION ARCHITECTURE (the platform data flow)

This is what the company actually does, end to end. Repo → service mapping and develop SHAs are in [§18](/landscape/dependencies/00-bom/).

### 10.1 The request path (web app → backend)
    
    
    React app (app.n1.care, Cloudflare Worker)
          │   (Cloudflare Tunnel, prod)
          ▼
    api.n1.care ── WebSocket path ──▶ api-websocket-proxy  (Go, :9999)  ──▶ api-backend
                ── HTTP path     ──▶ oathkeeper-proxy (:4455) ──▶ api-backend
    File uploads ───────────────────────────────────────────▶ api-backend  (direct)
    

  * **react-frontend** (the web app) talks to **api-websocket-proxy** (a tiny Go service) which fronts **api-backend** (Python). **Only file uploads go directly to api-backend.**
  * 🔒 **Ory Oathkeeper** sits in front of api-backend (`:4455`) and injects identity/authorization headers so api-backend doesn't re-check auth on every call.

### 10.2 The ingestion pipeline (medical record → structured clinical data)

A doctor creates a patient and uploads medical records. Then:
    
    
    api-backend  ─ saves file → S3 (n1-{env}-user-data)
                 └ appends → Redis(Valkey) stream
                                │
            phoenix-router (parser-router) ─ classifies each PAGE via mineru (mineru-2.5, ai-inference)
                                │  → Redis stream
            phoenix-parser (parser-sequential) ─ extracts clinical data:
                                │     biomarkers · genetics · diagnoses · procedures · medications
                                │  → Redis stream
            rosetta-grouper ─ uses the ROSETTA BiomarkerDefinition library (Arun's invention):
                                │     resolves WHAT a biomarker is against a global definition,
                                │     and groups all identical biomarkers under it
                                ▼
                          api-backend (via the n1 api client) → Aurora (n1-{env}-app DB)
    

  * BiomarkerDefinition resolution is N1's core IP (the **Rosetta** library, [§16](/landscape/dependencies/00-bom/)). A genetics variant (`rosetta-genetics-grouper`) runs alongside in staging.
  * Workers are **stateless Redis-stream consumers** , scaled by **KEDA** on queue depth (2→50).

### 10.3 Report generation (CHR — Comprehensive Health Report)

Once biomarkers are extracted, a doctor can generate a CHR. **3 CHR types are in production; many more are in development.**
    
    
    api-backend ─ enqueue → Redis stream (subscribed by forge-sentinel)
    forge-sentinel ─ loads the config for that CHR type
                   └ launches forge-runner as a Kubernetes JOB with the right variables
    forge-runner (built on the AGNO framework) ─ runs the CHR workflow
                   │   workflow tools are MCPs powered by the n1 api client → api-backend → patient data
                   └ on completion → saves the report to S3 via the document-manager library
    

  * **forge-sentinel** is the queue supervisor; **forge-runner** is the per-report worker (a k8s Job), built on the **agno** agent framework (local docs in `~/agno` \+ `~/agno-docs`). forge-runner persists agno session/memory and LangGraph checkpoints to the `forge-runner-{env}` Aurora database ([§8.5](/landscape/aws/)).
  * CHR workflows fetch patient data through **MCP servers backed by the n1 api client** , which read from the database via api-backend.
  * **forge-agents-api** is a separate, long-running read-only HTTP service (the `forge-runner` image started as `uvicorn forge_runner.agents_server:app`). At startup it parses the agent/skill/workflow catalog files baked into the image (`workflows/<name>/AGENTS.md`, `agents/*.md`, `skills/*.md`, `skills/<name>/SKILL.md`) into memory and serves them to **api-backend** over GET endpoints under `/agents/skills/` and `/agents/workflows/` (each requiring an `N1-Api-Key`). It runs no workflows and has no database.

### 10.4 Auth, billing, validation (the supporting services)

  * **Auth (Ory stack):** OAuth 2.0 via **Hydra** (OAuth server), **Kratos** (identities/login, `oauth.n1.care` / `auth.n1.care`), **Oathkeeper** (the header-injecting gateway), glued together by the **authentication-service**. Backed by the `auth-{env}` Aurora cluster (separate `hydra` DB).
  * **Billing:** **billing-service** handles all Stripe billing (subscriptions, metered usage). CronJobs emit meter events every minute and reconcile nightly. Backed by `billing-{env}` (prod Multi-AZ).
  * **Validation:** **data-validation-service** evaluates the parsers' and CHRs' output. It runs in staging and, on an older build, in prod.

* * *
