# Pediatric AI Scribe v6 AI-powered clinical documentation platform for pediatric medicine. Generates HPIs, hospital courses, chart reviews, SOAP notes, well/sick visit notes, and developmental milestone assessments from voice recordings or dictation. ## Features ### Clinical Documentation - **Live Encounter** — record doctor-patient conversations, AI generates structured OLDCARTS HPI - **Voice Dictation** — dictate narrative, AI cleans and restructures - **Hospital Course** — paste progress notes, generates prose, day-by-day, organ-system (ICU), or psych format - **Chart Review / Precharting** — summarize outpatient, subspecialty, and ED notes - **SOAP Notes** — full SOAP or subjective-only from dictation - **Well Visit** — AAP 2025 Bright Futures periodicity with vaccines, screenings, billing codes, SSHADESS (12+), milestones - **Sick Visit** — quick documentation with auto-suggested ROS and PE from chief complaint - **Developmental Milestones** — AAP/Nelson tracker (birth-11y) with narrative/structured/summary output ### AI & Speech - **5 AI Providers** — OpenRouter, AWS Bedrock, Azure OpenAI, Google Vertex AI, LiteLLM - **5 STT Providers** — Google Gemini, Amazon Transcribe (Medical), OpenAI Whisper, Local Whisper, LiteLLM - **3 TTS Providers** — Google Cloud TTS, LiteLLM (OpenAI), ElevenLabs - **Browser Whisper** — fully offline in-browser transcription via WebAssembly (HIPAA-safe) - **Per-tab model selector** — choose fast vs. smart vs. premium models per task - **Physician memory system** — Dragon-like learning from your corrections ### Learning Hub - **Content Management** — articles, clinical pearls, quizzes, presentations - **AI Content Generation** — generate from topics, uploaded PDFs, or Nextcloud files - **Marp Presentations** — slide editor with preview and PPTX export - **Semantic Search** — vector-based search via pgvector embeddings - **Quiz System** — MCQ, multi-select, true/false with scoring and progress tracking ### Platform - **Multi-user with roles** — admin, moderator, user - **OIDC/SSO** — Azure AD, Okta, Keycloak, PocketID, Google - **2FA** — TOTP-based two-factor authentication - **Cloudflare Turnstile** — bot protection on login, register, password reset - **Email verification** — with customizable templates - **Nextcloud integration** — WebDAV export - **S3 Document Storage** — AWS S3, Backblaze B2, MinIO - **PWA** — installable, works on mobile - **Admin Panel** — user management, settings, prompt editor, model configuration, logs --- ## Quick Start ### 1. Configure ```bash cp .env.example .env ``` Edit `.env` — at minimum set: ```env AI_PROVIDER=litellm # or openrouter, bedrock, azure, vertex LITELLM_API_BASE=https://your-litellm.example.com LITELLM_API_KEY=sk-... OPENAI_API_KEY=sk-... # for Whisper transcription (if not using LiteLLM STT) JWT_SECRET=<64-char random> # openssl rand -hex 32 DB_PASSWORD= APP_URL=https://your-domain.com ``` ### 2. Start ```bash docker compose up -d ``` App runs on **port 3552**. First user to register becomes admin. ### 3. Admin CLI ```bash docker exec pediatric-ai-scribe node admin-cli.js list-users docker exec pediatric-ai-scribe node admin-cli.js create-admin admin@example.com password123 "Dr. Admin" docker exec pediatric-ai-scribe node admin-cli.js make-admin user@example.com docker exec pediatric-ai-scribe node admin-cli.js reset-password user@example.com newpassword docker exec pediatric-ai-scribe node admin-cli.js toggle-registration docker exec pediatric-ai-scribe node admin-cli.js stats ``` --- ## AI Provider Configuration Switch providers by setting `AI_PROVIDER` in `.env`. No code changes needed. | Provider | HIPAA | Config | |----------|-------|--------| | **LiteLLM** | Depends on backend | `LITELLM_API_BASE`, `LITELLM_API_KEY` | | **AWS Bedrock** | Yes (with BAA) | `AWS_BEDROCK_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` | | **Azure OpenAI** | Yes (with BAA) | `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, `AZURE_DEPLOYMENT_NAME` | | **Google Vertex AI** | Yes (with BAA) | `GOOGLE_VERTEX_PROJECT`, `GOOGLE_VERTEX_LOCATION` | | **OpenRouter** | No | `OPENROUTER_API_KEY` | --- ## Transcription (Speech-to-Text) Set `TRANSCRIBE_PROVIDER` or let the app auto-detect. | Provider | HIPAA | Config | |----------|-------|--------| | **Google Gemini** | Yes | `GOOGLE_VERTEX_PROJECT`, `GOOGLE_STT_MODEL` | | **Amazon Transcribe** | Yes | AWS creds + `TRANSCRIBE_PROVIDER=aws` | | **Amazon Transcribe Medical** | Yes | `AWS_TRANSCRIBE_MEDICAL=true`, `AWS_TRANSCRIBE_SPECIALTY=PRIMARYCARE` | | **Local Whisper** | Yes (offline) | `TRANSCRIBE_PROVIDER=local`, `WHISPER_BINARY`, `WHISPER_MODEL_SIZE` | | **OpenAI Whisper** | No | `OPENAI_API_KEY` | | **LiteLLM** | Depends | `TRANSCRIBE_PROVIDER=litellm`, `LITELLM_STT_MODEL` | | **Browser Whisper** | Yes (client-side) | No config needed — toggle in user settings | --- ## Text-to-Speech | Provider | HIPAA | Config | |----------|-------|--------| | **Google Cloud TTS** | Yes | `GOOGLE_VERTEX_PROJECT`, `GOOGLE_TTS_VOICE` | | **LiteLLM** | Depends | `LITELLM_TTS_MODEL`, `LITELLM_TTS_VOICE` | | **ElevenLabs** | No | `ELEVENLABS_API_KEY` | --- ## OpenID Connect / SSO Supports Azure AD, Okta, Keycloak, PocketID, Google, and any OIDC-compliant provider. 1. Register callback URL: `https://your-domain.com/api/auth/oidc/callback` 2. Admin Panel > Settings > Configure OIDC (Issuer URL, Client ID, Client Secret) 3. Users are auto-created and linked by email on first SSO login See [OPENID_SETUP.md](OPENID_SETUP.md) for provider-specific guides. --- ## Cloudflare Turnstile (Bot Protection) Optional CAPTCHA on login, registration, and password reset forms. ```env TURNSTILE_SITE_KEY=0x4AAA... TURNSTILE_SECRET_KEY=0x4AAA... ``` --- ## Email Without SMTP, email verification is skipped and users are auto-verified. ```env SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your-email@gmail.com SMTP_PASS=your-app-password SMTP_FROM=noreply@yourdomain.com ``` --- ## Maintenance CLI After a Postgres image upgrade (major version bump or silent base-layer change), btree indexes on text columns can become inconsistent with the new ICU/glibc library. The app auto-detects this at startup and reindexes on drift, but you can also trigger it manually: ```bash # Health check — no writes docker exec pediatric-ai-scribe npm run maint:check # Rebuild all indexes + refresh collation + ANALYZE docker exec pediatric-ai-scribe npm run maint:reindex ``` Run `maint:reindex` any time after: - Upgrading the Postgres image (major or minor) - Restoring from a dump created on a different Linux distro - Seeing "invalid credentials" on credentials you know are correct - Seeing `0 rows` returned from a lookup that should match The reindex takes seconds on a small DB and a minute or two on larger ones. Safe to run while the app is serving traffic, though queries may slow briefly. --- ## Docker Hub ```bash docker pull danielonyejesi/pediatric-ai-scribe-v3:latest ``` Minimal compose without building: ```yaml services: app: image: danielonyejesi/pediatric-ai-scribe-v3:latest ports: - "3552:3000" env_file: .env depends_on: postgres: condition: service_healthy restart: unless-stopped postgres: image: pgvector/pgvector:pg16 environment: POSTGRES_DB: pedscribe POSTGRES_USER: pedscribe POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U pedscribe"] interval: 10s retries: 5 volumes: pgdata: ``` --- ## HIPAA Notice This application processes data through third-party AI APIs. - All connections use HTTPS/TLS - Authentication required for all AI endpoints - 2FA and SSO available - Cloudflare Turnstile bot protection - **AWS Bedrock**, **Azure OpenAI**, and **Google Vertex AI** offer BAAs - **OpenRouter** and **ElevenLabs** do NOT offer BAAs - **Browser Whisper** and **Local Whisper** keep audio fully private **Do not use real PHI without executed BAAs with all providers in your deployment.** --- ## Documentation See the [docs/](docs/) directory for detailed documentation: - [Architecture Overview](docs/architecture.md) - [API Reference](docs/api-reference.md) - [Database Schema](docs/database.md) - [Authentication & Security](docs/authentication.md) - [AI Providers & Models](docs/ai-providers.md) - [Speech (STT/TTS)](docs/speech.md) - [Learning Hub & CMS](docs/learning-hub.md) - [Configuration Reference](docs/configuration.md) - [Deployment Guide](docs/deployment.md) - [Developer Guide](docs/developer-guide.md) --- ## Development ```bash npm install cp .env.example .env # edit with your keys # Requires PostgreSQL with pgvector node server.js ``` --- ## Testing Two layers, both zero-config after the initial setup. ### Unit tests — pure dose math (Node built-in) ```bash npm test ``` Runs `node --test test/` against `public/js/calc-math.js` — pure functions for APLS / Best Guess weight, Parkland, Holliday-Segar 4-2-1, PRAM, Westley, epi (anaphylaxis vs arrest vs NRP, different concentrations), RSI drugs, min SBP, ETT sizing, Lund-Browder TBSA. **36 assertions, no dependencies.** ### End-to-end tests — Playwright smoke suite Runs a headless Chromium against the live app. **128 tests** covering every calculator tab, every Bedside sub-pill + widget, auth-gated pages (encounter, well visit, charts, vaccines, catch-up, learning hub, dictation, settings, FAQ), at **both desktop and mobile (Pixel 5) viewports**. ```bash # First-time setup: spin up the auth-less test container (port 3553) docker compose -f docker-compose.yml -f docker-compose.e2e.yml up -d pediatric-scribe-e2e # Then run the full suite (runs inside an official Playwright container) npm run e2e ``` The runner script (`scripts/e2e.sh`) uses `mcr.microsoft.com/playwright` so you don't need Node or browsers on the host. **Test environment:** - `pediatric-ai-scribe` (port 3552) — your normal app - `pediatric-ai-scribe-e2e` (port 3553) — identical image, but with `TURNSTILE_SECRET_KEY=""` and `SMTP_HOST=""` so Playwright can log in without a bot challenge. Shares the same Postgres + pgdata volume. - Test user: `e2e-user@ped-ai.test` (auto-verified on first register) - Harness page: `public/e2e-harness.html` loads the calculators component without the auth wall for smoke tests that don't need a logged-in session. **Viewing failures** — Playwright writes `e2e/test-results//` with: - `test-failed-1.png` — screenshot at the point of failure - `trace.zip` — full action trace (replay with `npx playwright show-trace`) - `error-context.md` — DOM snapshot and console logs Everything but the specs and config is gitignored under `e2e/`. **Files:** - `e2e/tests/bedside-smoke.spec.js` — 26 tests for the Bedside module - `e2e/tests/top-calculators.spec.js` — 27 tests for BP / BMI / Growth / Bili / Vitals / BSA / Dose / Resus / GCS / Equipment - `e2e/tests/auth-gated-smoke.spec.js` — 11 tests for the auth-gated tabs - `e2e/playwright.config.js` — runs all the above under both `chromium` (Desktop Chrome) and `mobile-chrome` (Pixel 5) projects **Writing a new test:** ```js const { test, expect } = require('@playwright/test'); test('my new smoke test', async ({ page }) => { await page.goto('/e2e-harness.html'); // bypasses auth for calculators await page.waitForFunction(() => window.__harnessReady === true); await page.click('button.calc-nav-pill[data-calc="bedside"]'); await expect(page.locator('#calc-bedside')).toBeVisible(); }); ``` For auth-gated routes, use the login fixture in `auth-gated-smoke.spec.js` as a template — it caches the token at module scope so you don't hit the login rate-limit.