Technology Stack
| Layer | Tech | Why |
|---|---|---|
| API | NestJS 10 · TypeScript 5 strict · Node 20 | First-class DI; decorator-driven auth/consent; TS strict catches shape drift at compile time |
| Frontend | Next.js 15 · React 19 · Tailwind CSS v4 · Zustand · TanStack Query 5 · Socket.IO client | App Router for CSP nonce delivery; Zustand for stable selectors (no re-render storms); TanStack for cache freshness |
| ML | FastAPI · Python 3.12 · Pydantic v2 | Pydantic for LLM prompt-response schema validation; slowapi rate limiting |
| Research services | FastAPI · motor (async MongoDB) · patientrx-contracts (Pydantic shared schemas) | Shared contracts = shared shapes across 4 services; motor = non-blocking I/O |
| DB | MongoDB Atlas (prod) · MongoDB 7 Docker (local, :6205, replica set) | Native driver; $graphLookup for entity walks; Atlas Search for BM25; change-streams for event-driven pipelines |
| Encryption | crypto.createCipheriv AES-256-GCM · Azure Key Vault KEK | FIPS-compliant; envelope per-record DEK; Managed Identity auth in prod |
| Auth | MSAL (Microsoft Entra ID) + GIS (Google Workspace) + JWKS verify per iss | Dual IdP; (idpProvider, idpSubject) natural key; per-tenant rate limit + allowlist |
| MFA | @simplewebauthn/* passkey + otpauth TOTP + bcryptjs ≥ 12 recovery codes | Passkey-first per OMB M-22-09; TOTP fallback |
| LLM | OpenAI GPT-4o + Gemini 2.0 Flash via google-genai SDK | Dual-provider with audited fallback (FR-021a) |
| Testing | Vitest (unit) · Playwright (E2E + CSP regression) · pytest (ML + research) | Vitest speed; Playwright real-browser CSP; pytest for Python services |
| CI | GitHub Actions (self-hosted Mac mini + ubuntu-latest) | Self-hosted avoids billing cap; ubuntu-latest for x86_64 deploys |
| Dashboards | Azure Monitor + KQL + Workbooks | Log-query expressive, workbook dashboards per team |
| Static hosting | Azure Static Web Apps Free SKU | Free; global CDN; auto SSL via Let's Encrypt; zero PHI |
Python deps (per service)
Canonical locations:
packages/patientrx-contracts/pyproject.toml(monorepo root package)apps/research/*/requirements.txt(service-local — install with-e ../../../packages/patientrx-contracts)research-engine/packages/patientrx-guardrails/pyproject.toml(consent + audit client)research-engine/packages/patientrx-memory-sdk/pyproject.toml(memory-store SDK)
JS/TS deps
- Root
package.json(monorepo tooling) apps/api/package.json,apps/web/package.json(per-app)- Turbo + workspace protocol for mono-install
Container images
- Dev:
docker composewith profiles (mongo,group3,dev-console) - Prod (planned): Azure Container Apps (staging), Azure App Service + AKS (prod) — deferred to production-launch milestone
Dev toolchain
- asdf (
.tool-versions) pins Node 20 + Python 3.12.10 - Turbo for parallel task execution
- Vitest, Playwright, pytest as the test runners
- Claude Code harness for skills + hooks
Supply-chain posture
- Every new dep goes through
/package-security-scanskill → decision record indocs/compliance/package-security-scans/ - Existing-dep bumps go through
/dependency-upgradeskill → changelog diff + transitive-dep audit - CI gates:
pip-audit,npm audit --production,Trivy,Semgrep,gitleaks(PR-changeset + scheduled full-history) - BAA registry (
apps/api/src/config/baa-registry.yml) — every PHI-capable vendor registered + fail-closed on unsigned in prod