# Architecture

This document is the current high-level map for Ped-AI. It is intentionally shorter and more operational than the older deep-dive files under `docs/logic/`.

## System Shape

Ped-AI is a self-hosted Express application with a browser frontend, PostgreSQL storage, Redis operational state, LiteLLM model routing, and optional MCP-backed clinical retrieval.

| Area | Owner | Notes |
|---|---|---|
| Web app | Ped-AI | Auth, UI, clinical workflows, admin settings, notes, Learning Hub, bedside tools |
| Database | PostgreSQL | Users, sessions, settings, saved app data, audit/API/access logs |
| Operational cache | Redis | Prompt suggestions, lightweight state, queue groundwork; not clinical answer caching |
| Model gateway | LiteLLM | Text, speech, image, embedding model discovery and routing |
| Clinical retrieval | MCP service | Nextcloud access, indexing, search, rerank, source metadata |
| Reverse proxy | Caddy or equivalent | TLS and public routing |

## Request Flow

Normal app request:

```txt
browser
  -> reverse proxy
  -> Express middleware
  -> auth/session check when protected
  -> route handler
  -> PostgreSQL/Redis/provider calls as needed
  -> JSON or HTML fragment response
```

Clinical Assistant request:

```txt
browser
  -> Ped-AI clinical assistant route
  -> MCP semantic search for indexed clinical sources
  -> Ped-AI builds grounded answer prompt
  -> LiteLLM chat model
  -> Ped-AI returns answer plus source metadata
  -> browser renders markdown, citations, and source cards
```

Ped-AI owns the user workflow and rendering. MCP owns retrieval and indexed source metadata. LiteLLM owns model routing.

## Runtime Boundaries

| Boundary | Main Risk | Current Direction |
|---|---|---|
| Browser to Ped-AI | XSS, stale shell, session handling | Sanitized rendering, httpOnly cookie for web, cache busting |
| Ped-AI to PostgreSQL | schema drift, slow queries | migrations, maintenance checks, indexes where needed |
| Ped-AI to Redis | unavailable operational state | Redis is useful but should not hold required clinical answers |
| Ped-AI to LiteLLM | provider downtime, wrong model mode | metadata-based model discovery and timeouts |
| Ped-AI to MCP | retrieval latency/failure | explicit MCP client layer and graceful fallback messages |
| MCP to Nextcloud | stale indexed metadata | scanner/indexer updates source metadata over time |

## Source Of Truth

| Data | Source Of Truth |
|---|---|
| User accounts and sessions | Ped-AI PostgreSQL |
| Admin app settings | Ped-AI PostgreSQL `app_settings` |
| Clinical source documents | Nextcloud and MCP index |
| Clinical source title/path shown to users | MCP result metadata, especially indexed `file_path` |
| Clinical answer text | Generated per request; intentionally not cached |
| Model availability | LiteLLM metadata and configured fallbacks |

## Deployment Shape

Production usually runs:

```txt
Caddy/TLS
  -> pediatric-ai-scribe container
     -> pedscribe-db container
     -> ped-ai-redis container
     -> LiteLLM endpoint
     -> MCP endpoint
```

The app should stay private behind the reverse proxy. Do not expose PostgreSQL, Redis, MCP internals, or provider keys publicly.

## Design Principles

- Keep Ped-AI stateless enough to run more than one app container.
- Keep clinical answer generation live and source-grounded; do not cache final clinical answers.
- Prefer model capability metadata over model-name regexes.
- Prefer indexed file names and paths over embedded PDF metadata for source titles.
- Keep renderer fixes narrow and tested because LLM markdown is messy.
- Keep old frontend globals working until the affected feature is intentionally converted to ESM.
