Skip to content

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

TierMeaningExample failure
CriticalFailure 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.
HighFailure 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.
StandardFailure 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.

PackageVersionPurposeRiskModel providerModel versionValidation status
github.com/aws/aws-sdk-go-v2v1.41.6AWS SDK base — authentication, request signing, retry logic. Foundation for S3 + future KMS.Critical
github.com/aws/aws-sdk-go-v2/configv1.32.16AWS SDK config loading (env, profile, IMDS).Critical
github.com/aws/aws-sdk-go-v2/credentialsv1.19.15AWS SDK credentials providers (static, env, role assumption).Critical
github.com/aws/aws-sdk-go-v2/service/s3v1.100.0S3 client — patient-data file storage (signatures, documents, forms uploads). See file-storage.md.Critical
github.com/aws/aws-sdk-go-v2/service/sesv2v1.60.4SES 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/v2v2.5.1Clerk auth SDK — JWT verification on every authenticated request. See features/auth/clerk-integration.Critical
github.com/go-chi/chi/v5v5.2.5HTTP router. Every Core API request passes through chi.Critical
github.com/google/uuidv1.6.0UUIDv7 generation. Every primary key in the database.Critical
github.com/jackc/pgx/v5v5.8.0Postgres driver + connection pooling. Sole DB access path.Critical
github.com/redis/go-redis/v9v9.18.0Redis client — caching, idempotency store, slot holds, rate limiting.Critical
github.com/kelseyhightower/envconfigv1.4.0Environment-variable to config struct. Boot-time only.High
github.com/oapi-codegen/runtimev1.4.0OpenAPI runtime helpers used by generated types. Types-only generation keeps the runtime surface minimal.High
gopkg.in/yaml.v3v3.0.1YAML parser (OpenAPI spec, tooling).High
github.com/lmittmann/tintv1.1.3Colored slog handler for development logs. Production uses the stdlib JSON handler.Standard
github.com/testcontainers/testcontainers-gov0.42.0Test-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/postgresv0.42.0Test-only — spins up Postgres containers for the RLS integration test harness. Not in production binary.Standard
github.com/testcontainers/testcontainers-go/modules/localstackv0.42.0Test-only — spins up LocalStack for the S3 integration test harness. Not in production binary.Standard
github.com/testcontainers/testcontainers-go/modules/redisv0.42.0Test-only — spins up Redis containers for the rate-limit integration test harness. Not in production binary.Standard
golang.org/x/modv0.35.0go.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.

PackageVersionOwnerPurposeRiskModel providerModel versionValidation status
@clerk/nextjs^7.2.5clinic, portal, consoleClerk auth integration — sign-in / sign-up / session refresh on every page.Critical
next16.2.4clinic, portal, consoleNext.js framework — server components, routing, proxy.ts.Critical
react^19.2.5clinic, portal, console, uiUI framework.Critical
react-dom^19.2.5clinic, portal, console, uiReact DOM renderer.Critical
undici^8.2.0api-clientHTTP/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.3uiAccessibility primitives (dialogs, popovers, dropdowns, listboxes). a11y compliance for forms / clinical UI.High
zod^4.3.6uiRuntime schema validation for forms and inputs.High
next-intl^4.9.1clinic, portal, consolei18n message resolution (en, ro). See i18n.md.Standard
@tanstack/react-table^8.21.3uiHeadless table primitives — Console audit-log table and every Layer 2+ list page.Standard
react-day-picker^9.14.0uiCalendar component (date filters, future scheduling UI).Standard
lucide-react^1.11.0clinic, portal, console, uiIcon set.Standard
class-variance-authority^0.7.1uiVariant utility for component styling.Standard
clsx^2.1.1uiConditional className utility.Standard
tailwind-merge^3.5.0uiTailwind class deduplication.Standard
date-fns^4.1.0uiDate formatting and arithmetic.Standard
tw-animate-css^1.4.0uiAnimation utility classes.Standard
sonner^2.0.7uiToast / 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.0uiQR-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.

PackageVersionOwnerPurposeRisk
typescript^6.0.3all workspacesTypeScript compiler.High — silent miscompilation could produce incorrect bundles.
turbo^2.9.6rootMonorepo task orchestrator.Standard
@turbo/gen^2.9.6uiCode generators for shadcn components.Standard
tailwindcss^4.2.4uiCSS framework, build-time.Standard
@tailwindcss/postcss^4.2.4ui, all appsPostCSS plugin for Tailwind.Standard
shadcn^4.4.0uishadcn/ui CLI for adding components. Source-imported, not runtime.Standard
eslint^9.39.4all workspacesLinter.Standard
@eslint/js^9.39.4eslint-configESLint base rules.Standard
@next/eslint-plugin-next^16.2.4eslint-configNext.js linting rules.Standard
@typescript-eslint/eslint-plugin^8.59.0eslint-configTypeScript-aware lint rules.Standard
@typescript-eslint/parser^8.59.0eslint-configTypeScript parser for ESLint.Standard
typescript-eslint^8.59.0eslint-configTypeScript-ESLint umbrella.Standard
eslint-config-prettier^10.1.8eslint-configDisables ESLint rules that conflict with Prettier.Standard
eslint-plugin-only-warn^1.2.1eslint-configConvert errors to warnings (non-blocking).Standard
eslint-plugin-react^7.37.5eslint-configReact lint rules.Standard
eslint-plugin-react-hooks^7.1.1eslint-configReact hooks lint rules.Standard
eslint-plugin-turbo^2.9.6eslint-configTurborepo lint rules.Standard
globals^17.5.0eslint-configGlobal identifier definitions for ESLint.Standard
prettier^3.8.3rootFormatter.Standard
openapi-typescript^7.13.0rootOpenAPI → TypeScript codegen for @workspace/api-client.Standard
vitepress^1.6.3docsStatic-site generator for apps/docs/. Not part of any product app.Standard
@types/node^25.6.0all apps, uiNode types.Standard
@types/react^19.2.14all apps, uiReact types.Standard
@types/react-dom^19.2.3all apps, uiReact 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:

ModelVersionProviderPurposeRiskValidation status
examplegpt-5OpenAIexercise prescription draftingCriticalValidated 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.sum and pnpm-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:

  1. Add the dep (go get, pnpm add, etc.).
  2. Open this file and add a row to the matching table.
  3. 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.
  4. If the dep is an AI/ML model: also add a row to AI/ML Models with Model provider, Model version, and Validation status. Validation status cannot 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.