SOUP — Software of Unknown Provenance
Inventory of third-party code shipped with the RestartiX Platform, classified by risk and purpose. Required for IEC 62304 (medical device software) compliance and good practice for any GDPR-regulated platform.
What "SOUP" means. Any software not authored by the project team is "of unknown provenance" — even if the source is public, we did not write or fully audit it. Medical device certification requires a documented, risk-classified inventory. Plain dependency lists (
go.mod,package.json) are not sufficient because they don't carry purpose or risk classification.
The authoritative inventory of every byte we ship lives in services/api/go.sum and pnpm-lock.yaml — both checked in. This document is the risk-classified subset focused on direct dependencies (the libraries we deliberately chose to depend on). Indirect / transitive dependencies inherit their risk classification from the parent that pulled them in.
Risk Classification
| Tier | Meaning | Example failure |
|---|---|---|
| Critical | Failure compromises patient safety, data integrity, authentication, or audit. Bug class includes silent data loss, privilege escalation, or memory-safety issues with user-controlled input. | Postgres driver corrupts a write; auth library accepts forged JWT. |
| High | Failure causes feature outage, data leak, or accessibility breach. No direct safety impact, but production SLO and compliance affected. | Redis client misbehaves and rate-limit bypass succeeds; a11y primitive regresses keyboard nav. |
| Standard | Failure causes UI inconvenience or developer-experience regression. No safety, security, or compliance impact. | Icon library renders blank; date formatter localizes wrong month name. |
The AI/ML model columns (Model provider, Model version, Validation status) are populated only for AI/ML model dependencies. They are NULL for libraries — see AI/ML Models below.
Backend Runtime Dependencies
Direct dependencies in services/api/go.mod. Indirect dependencies are inherited and tracked in services/api/go.sum.
| Package | Version | Purpose | Risk | Model provider | Model version | Validation status |
|---|---|---|---|---|---|---|
github.com/aws/aws-sdk-go-v2 | v1.41.6 | AWS SDK base — authentication, request signing, retry logic. Foundation for S3 + future KMS. | Critical | — | — | — |
github.com/aws/aws-sdk-go-v2/config | v1.32.16 | AWS SDK config loading (env, profile, IMDS). | Critical | — | — | — |
github.com/aws/aws-sdk-go-v2/credentials | v1.19.15 | AWS SDK credentials providers (static, env, role assumption). | Critical | — | — | — |
github.com/aws/aws-sdk-go-v2/service/s3 | v1.100.0 | S3 client — patient-data file storage (signatures, documents, forms uploads). See file-storage.md. | Critical | — | — | — |
github.com/aws/aws-sdk-go-v2/service/sesv2 | v1.60.4 | SES v2 client — transactional email transport for the platform notification primitive (1A.18 EmailChannel). Member invites, break-glass alerts, and every future first-party email to a human flows through this. | Critical | — | — | — |
github.com/clerk/clerk-sdk-go/v2 | v2.5.1 | Clerk auth SDK — JWT verification on every authenticated request. See features/auth/clerk-integration. | Critical | — | — | — |
github.com/go-chi/chi/v5 | v5.2.5 | HTTP router. Every Core API request passes through chi. | Critical | — | — | — |
github.com/google/uuid | v1.6.0 | UUIDv7 generation. Every primary key in the database. | Critical | — | — | — |
github.com/jackc/pgx/v5 | v5.8.0 | Postgres driver + connection pooling. Sole DB access path. | Critical | — | — | — |
github.com/redis/go-redis/v9 | v9.18.0 | Redis client — caching, idempotency store, slot holds, rate limiting. | Critical | — | — | — |
github.com/kelseyhightower/envconfig | v1.4.0 | Environment-variable to config struct. Boot-time only. | High | — | — | — |
github.com/oapi-codegen/runtime | v1.4.0 | OpenAPI runtime helpers used by generated types. Types-only generation keeps the runtime surface minimal. | High | — | — | — |
gopkg.in/yaml.v3 | v3.0.1 | YAML parser (OpenAPI spec, tooling). | High | — | — | — |
github.com/lmittmann/tint | v1.1.3 | Colored slog handler for development logs. Production uses the stdlib JSON handler. | Standard | — | — | — |
github.com/testcontainers/testcontainers-go | v0.42.0 | Test-only — base testcontainers API. Used directly to customise the Postgres container with shared_preload_libraries=pg_stat_statements (1A.16). Not in production binary. | Standard | — | — | — |
github.com/testcontainers/testcontainers-go/modules/postgres | v0.42.0 | Test-only — spins up Postgres containers for the RLS integration test harness. Not in production binary. | Standard | — | — | — |
github.com/testcontainers/testcontainers-go/modules/localstack | v0.42.0 | Test-only — spins up LocalStack for the S3 integration test harness. Not in production binary. | Standard | — | — | — |
github.com/testcontainers/testcontainers-go/modules/redis | v0.42.0 | Test-only — spins up Redis containers for the rate-limit integration test harness. Not in production binary. | Standard | — | — | — |
golang.org/x/mod | v0.35.0 | go.mod parser used by cmd/check-soup to enumerate direct Go deps for the SOUP gate. Build-tooling only. | Standard | — | — | — |
Frontend Runtime Dependencies
Direct dependencies in apps/clinic, apps/portal, apps/console, and packages/ui. Shipped to the browser at runtime. Indirect dependencies tracked in pnpm-lock.yaml.
| Package | Version | Owner | Purpose | Risk | Model provider | Model version | Validation status |
|---|---|---|---|---|---|---|---|
@clerk/nextjs | ^7.2.5 | clinic, portal, console | Clerk auth integration — sign-in / sign-up / session refresh on every page. | Critical | — | — | — |
next | 16.2.4 | clinic, portal, console | Next.js framework — server components, routing, proxy.ts. | Critical | — | — | — |
react | ^19.2.5 | clinic, portal, console, ui | UI framework. | Critical | — | — | — |
react-dom | ^19.2.5 | clinic, portal, console, ui | React DOM renderer. | Critical | — | — | — |
undici | ^8.2.0 | api-client | HTTP/1.1 client backing Node's fetch() — every server-component / server-action call to the Core API flows through it. We install a tuned global Agent in each app's instrumentation.ts (keep-alive 30s, 64 connections per origin) to avoid TCP churn at fleet scale. Server-only; not shipped to the browser. | Critical | — | — | — |
radix-ui | ^1.4.3 | ui | Accessibility primitives (dialogs, popovers, dropdowns, listboxes). a11y compliance for forms / clinical UI. | High | — | — | — |
zod | ^4.3.6 | ui | Runtime schema validation for forms and inputs. | High | — | — | — |
next-intl | ^4.9.1 | clinic, portal, console | i18n message resolution (en, ro). See i18n.md. | Standard | — | — | — |
@tanstack/react-table | ^8.21.3 | ui | Headless table primitives — Console audit-log table and every Layer 2+ list page. | Standard | — | — | — |
react-day-picker | ^9.14.0 | ui | Calendar component (date filters, future scheduling UI). | Standard | — | — | — |
lucide-react | ^1.11.0 | clinic, portal, console, ui | Icon set. | Standard | — | — | — |
class-variance-authority | ^0.7.1 | ui | Variant utility for component styling. | Standard | — | — | — |
clsx | ^2.1.1 | ui | Conditional className utility. | Standard | — | — | — |
tailwind-merge | ^3.5.0 | ui | Tailwind class deduplication. | Standard | — | — | — |
date-fns | ^4.1.0 | ui | Date formatting and arithmetic. | Standard | — | — | — |
tw-animate-css | ^1.4.0 | ui | Animation utility classes. | Standard | — | — | — |
sonner | ^2.0.7 | ui | Toast / notification primitive — surfaces action results (saved, deleted, error) across all three apps. Composes with React 19 useActionState server-action flow used everywhere. shadcn's canonical toast since 2024. | Standard | — | — | — |
qrcode.react | ^4.2.0 | ui | QR-code rendering — consumed by the share-link mint UI (L10) so clinic staff can hand a phone-scannable QR to a patient at the desk. SVG-based; no canvas dependency. | Standard | — | — | — |
Build & Tooling
Dependencies used at build, lint, format, typecheck, or doc-generation time. Not shipped to production — failures here cause CI failures, never patient-visible behavior.
This section is included for completeness but classified at a lower bar than runtime deps. Risk is uniformly Standard unless flagged.
| Package | Version | Owner | Purpose | Risk |
|---|---|---|---|---|
typescript | ^6.0.3 | all workspaces | TypeScript compiler. | High — silent miscompilation could produce incorrect bundles. |
turbo | ^2.9.6 | root | Monorepo task orchestrator. | Standard |
@turbo/gen | ^2.9.6 | ui | Code generators for shadcn components. | Standard |
tailwindcss | ^4.2.4 | ui | CSS framework, build-time. | Standard |
@tailwindcss/postcss | ^4.2.4 | ui, all apps | PostCSS plugin for Tailwind. | Standard |
shadcn | ^4.4.0 | ui | shadcn/ui CLI for adding components. Source-imported, not runtime. | Standard |
eslint | ^9.39.4 | all workspaces | Linter. | Standard |
@eslint/js | ^9.39.4 | eslint-config | ESLint base rules. | Standard |
@next/eslint-plugin-next | ^16.2.4 | eslint-config | Next.js linting rules. | Standard |
@typescript-eslint/eslint-plugin | ^8.59.0 | eslint-config | TypeScript-aware lint rules. | Standard |
@typescript-eslint/parser | ^8.59.0 | eslint-config | TypeScript parser for ESLint. | Standard |
typescript-eslint | ^8.59.0 | eslint-config | TypeScript-ESLint umbrella. | Standard |
eslint-config-prettier | ^10.1.8 | eslint-config | Disables ESLint rules that conflict with Prettier. | Standard |
eslint-plugin-only-warn | ^1.2.1 | eslint-config | Convert errors to warnings (non-blocking). | Standard |
eslint-plugin-react | ^7.37.5 | eslint-config | React lint rules. | Standard |
eslint-plugin-react-hooks | ^7.1.1 | eslint-config | React hooks lint rules. | Standard |
eslint-plugin-turbo | ^2.9.6 | eslint-config | Turborepo lint rules. | Standard |
globals | ^17.5.0 | eslint-config | Global identifier definitions for ESLint. | Standard |
prettier | ^3.8.3 | root | Formatter. | Standard |
openapi-typescript | ^7.13.0 | root | OpenAPI → TypeScript codegen for @workspace/api-client. | Standard |
vitepress | ^1.6.3 | docs | Static-site generator for apps/docs/. Not part of any product app. | Standard |
@types/node | ^25.6.0 | all apps, ui | Node types. | Standard |
@types/react | ^19.2.14 | all apps, ui | React types. | Standard |
@types/react-dom | ^19.2.3 | all apps, ui | React DOM types. | Standard |
AI/ML Models
No AI/ML models shipped today. This section is reserved for the first AI feature — see Hook 5 of the AI-first ADR.
When the first AI/ML model is integrated, add a row with:
| Model | Version | Provider | Purpose | Risk | Validation status |
|---|---|---|---|---|---|
| example | gpt-5 | OpenAI | exercise prescription drafting | Critical | Validated against N=200 manually-reviewed cases — see model-validation/... |
Validation status is the regulatory anchor: every clinical model needs an evidence trail (test set, baseline, error analysis) before it ships. Non-clinical models (e.g. a model that summarizes admin emails for staff inboxes) carry a lighter validation bar but still appear here.
Indirect Dependencies
The full transitive dependency graph is in:
- Backend:
services/api/go.sum— every Go module pulled in, with cryptographic hashes - Frontend:
pnpm-lock.yaml(repo root) — every npm package, with integrity hashes
Indirect deps inherit the risk classification of the direct dep that pulled them in. We do not maintain a row for every transitive package because:
- Risk is determined by the call site, not the package. A logger pulled in by an HTTP middleware operates at the same risk tier as the middleware itself.
- The set churns on every
go mod tidy/pnpm install. Maintaining 250+ rows that update arbitrarily is paperwork without signal. - An auditor asking "what code is in this binary?" gets
go.sumandpnpm-lock.yaml. An auditor asking "what risks have you considered?" gets this document.
If a transitive dep ever becomes load-bearing in a way that's surprising — e.g. a CVE that affects us only via an indirect path, or a transitive dep that ends up doing crypto where the parent disclaims it — promote it to a direct dep and add a row here.
Adding a New Dependency
Every new dependency added in any PR must include a SOUP entry in the same PR. The reviewer's job is to confirm the row exists; the contributor's job is to write it.
Procedure:
- Add the dep (
go get,pnpm add, etc.). - Open this file and add a row to the matching table.
- Fill in the columns:
- Version: pin the exact version in your PR (
go.mod/package.json). - Purpose: one sentence — what does it do for us. "It's a Postgres driver" is wrong; "Postgres driver + connection pooling" is right.
- Risk: pick a tier from the classification rubric. When in doubt, pick the higher tier — easier to defend than the lower.
- Model columns: leave em-dashed unless this is an AI/ML model.
- Version: pin the exact version in your PR (
- If the dep is an AI/ML model: also add a row to AI/ML Models with
Model provider,Model version, andValidation status.Validation statuscannot be left blank for a clinical model — the PR is incomplete without it.
Removing a dependency: delete the row. Do not leave deprecated entries — go mod tidy and pnpm install already keep the lock files honest, and stale SOUP rows confuse audits.
Bumping a version: update the version cell in the row. No new row needed unless the upgrade introduces a new risk class (e.g. a logging library adding a network-egress feature would jump from Standard to High).
Maintenance
This document is updated with every dependency change. The make check target runs services/api/cmd/check-soup, which parses every direct dependency in services/api/go.mod and every workspace package.json (dependencies + devDependencies, excluding @workspace/* internals) and asserts each one has a SOUP row, and that no SOUP row points at a removed dep. CI fails when either invariant breaks.
A periodic full audit (every release branch cut, or quarterly minimum) should:
- Confirm every direct dep has a row.
- Spot-check that risk classifications still match how the dep is used.
- Verify versions match what's in lock files.
- Re-run dependency vulnerability scanners (
govulncheck,pnpm audit) and document any waivers here.