# FarmaFinder Security Dependency and Release Hardening Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Remove the remaining high/critical dependency and supply-chain risks, make Python and container builds reproducible, and establish deployment-blocking security verification after the configuration and access-control hotfixes. **Architecture:** Upgrade dependencies in isolated package-family batches while preserving the existing runtime security controls. Resolve Python dependencies into a committed `uv.lock`, pin container inputs by immutable digests, and run dependency, image, and secret scans in CI. Any remaining advisory is recorded with its path, exploitability, mitigation, and owner. **Tech Stack:** npm workspaces/package-lock, Node.js 20/24, Python 3.13, uv, pip-audit, Docker Compose, Trivy, Gitleaks, Jest, Vitest, pytest. --- ## Files and responsibilities - Create `docs/security/2026-07-22-dependency-hardening.md`: audit baseline, selected versions/digests, residual-advisory decisions, and verification evidence. - Create `apps/pip-platform/uv.lock`: resolved, hash-pinned Python dependency graph. - Modify `apps/backend/package.json`, `apps/parapharmacy-api/package.json`, `apps/frontend/package.json`, `apps/scraper/package.json`, and the root `package-lock.json` for isolated dependency batches. - Modify both Node Dockerfiles, Compose files, and deployment docs for immutable images and lockfile-enforced installs. - Create `.github/workflows/security.yml`: reproducible installs, tests, audits, secret scanning, image scanning, and Compose checks. ## Baseline to preserve The preceding hotfix plan already added production secret validation, service-key middleware, protected parapharmacy mutations, internal Compose networking, production-safe Swagger behavior, and security regression tests. Do not revert those controls. The last online audit reported 56 advisories for the backend/workspace scope and 3 for the parapharmacy API; counts must be refreshed before each batch. ### Task 1: Establish an auditable dependency baseline **Files:** Create `docs/security/2026-07-22-dependency-hardening.md`. - [ ] Run `npm ci` from the repository root, then run `npm audit --json`, `npm audit --prefix apps/backend --json`, `npm audit --prefix apps/parapharmacy-api --json`, `npm audit --prefix apps/frontend --json`, and `npm audit --prefix apps/scraper --json`, saving reports only under `/tmp` and never recording secret values. - [ ] Record counts, direct versions, Node/npm/Python/uv/Docker versions, dependency paths, available fixes, and whether each finding reaches a production image. - [ ] Confirm no unrelated lockfile rewrite exists with `git diff --check` and `git status --short`. - [ ] Commit the ledger with `git add docs/security/2026-07-22-dependency-hardening.md && git commit -m "docs: record dependency hardening baseline"`. ### Task 2: Create and verify the Python lockfile **Files:** Create `apps/pip-platform/uv.lock`; update PIP deployment docs if present. - [ ] Run `cd apps/pip-platform && uv lock`; do not hand-edit generated lock content. - [ ] Recreate from the lock with `uv sync --frozen --extra dev`, then run `uv run pytest -q` and `uv run pip-audit --strict`. - [ ] If `pip-audit` is absent, add it to the development dependency group, rerun `uv lock`, and repeat the frozen sync. Record each Python advisory with package, path, reachability, and owner. - [ ] Commit with `git add apps/pip-platform/uv.lock && git commit -m "build: lock pip platform dependencies"`. ### Task 3: Pin runtime container inputs immutably **Files:** Root/PIP Compose files, both Node Dockerfiles, and the dependency-hardening ledger. - [ ] Replace every runtime `:latest` image with an approved release. Resolve digests with `docker buildx imagetools inspect redis:7-alpine`, `postgres:16-alpine`, `mongo:7`, the approved n8n release, the approved Redis exporter release, and the approved PostgreSQL exporter release. - [ ] Replace each reference with `repository:tag@sha256:` followed by the exact digest returned by `docker buildx imagetools inspect`, record the UTC update date and approver, and verify the digest is for the deployment platform. - [ ] Ensure each Node Dockerfile copies its matching `package.json` and lockfile before `npm ci --omit=dev`; build both images and run a startup/config smoke test. - [ ] Commit the image/Dockerfile batch separately so it can be reverted without undoing dependency code. ### Task 4: Upgrade backend dependency families independently **Files:** `apps/backend/package.json`, root `package-lock.json`, existing backend tests. - [ ] Run `npm ci` and `npm test --prefix apps/backend -- --runInBand` before changing versions. - [ ] Upgrade all direct OpenTelemetry packages as one compatible family: API, auto-instrumentations, exporters, instrumentation-pino, resources, SDKs, and semantic conventions. Do not upgrade only `auto-instrumentations-node`. - [ ] Regenerate only through npm, inspect the lockfile for unrelated upgrades, and rerun the backend suite. - [ ] In a separate batch, upgrade `bcrypt` and `sqlite3`; verify native installs under Node 20 and 24, session/database tests, `npm ls tar node-gyp`, and `npm audit --prefix apps/backend --audit-level=high`. - [ ] Never use `npm audit fix --force`; any major upgrade requires a compatibility note and review. Commit each family separately. ### Task 5: Upgrade parapharmacy and scraper dependency families **Files:** `apps/parapharmacy-api/package.json`, `apps/scraper/package.json`, root `package-lock.json`, security tests. - [ ] Upgrade Mongoose within its supported major, regenerate the lockfile, and confirm `npm ls fast-uri` resolves outside the audited range. - [ ] Run `npm test --prefix apps/parapharmacy-api -- --runInBand __tests__/security.test.js` and `npm audit --prefix apps/parapharmacy-api --audit-level=high`. - [ ] Upgrade scraper Puppeteer dependencies only after recording the current executable path. Preserve `PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true` and `/usr/bin/chromium`; verify with `node -e "console.log(process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/chromium')"`. - [ ] Run scraper module-load/available tests and commit Mongoose and scraper batches separately. ### Task 6: Upgrade frontend tooling without exposing Vitest UI **Files:** `apps/frontend/package.json`, root `package-lock.json`, Vite/Vitest config, CI workflow. - [ ] Confirm no production or CI command uses Vitest UI with `rg -n "vitest( --ui|.*ui)" apps/frontend package.json .github`. - [ ] Upgrade Vite, Rollup/esbuild, and Vitest as a compatible toolchain; keep React plugin, jsdom, and testing-library versions compatible with the selected Vitest major. - [ ] Regenerate the lockfile and run `npm test --prefix apps/frontend`, `npm run build --prefix apps/frontend`, and `npm audit --prefix apps/frontend --audit-level=high`. - [ ] Record any development-only residual advisory and commit this batch separately. ### Task 7: Add deployment-blocking CI gates **Files:** Create `.github/workflows/security.yml`. - [ ] Add pull-request/protected-branch jobs for `npm ci` plus all Node tests/builds; workspace/app `npm audit --audit-level=high`; `uv sync --frozen`, pytest, and `pip-audit --strict`; Gitleaks full-history scanning; Trivy high/critical image scanning; and root/PIP Compose rendering. - [ ] The Compose job must use fixture values and assert that only intended frontend/API ports are published, no internal database/exporter ports are published, and no production-secret `${...:-placeholder}` fallback remains. - [ ] Build production images with committed lockfiles, scan image digests, upload JSON reports as artifacts, and never upload `.env` files or secret values. - [ ] Pin third-party actions to reviewed immutable commit SHAs and grant read-only repository permissions. Commit with `git add .github/workflows/security.yml && git commit -m "ci: enforce dependency and image security gates"`. ### Task 8: Run final verification and residual-advisory review **Files:** Update the dependency-hardening ledger only if verification exposes a regression or documented exception. - [ ] Run `npm ci`, backend tests, parapharmacy security tests, frontend tests/build, `uv sync --frozen --extra dev`, `uv run pytest`, and `uv run pip-audit --strict`. - [ ] Render all Compose files with production-like fixture variables; inspect for placeholders, mutable tags, public database/exporter ports, and missing required secrets. - [ ] Build all production images and black-box test public GETs, 401 unauthenticated mutations, 403 invalid keys, absent production Swagger, and absent host-published internal infrastructure. - [ ] Re-run all audits. Every remaining high/critical item must list package, dependency path, production reachability, exploitability, mitigation, owner, and review/expiry date; unexplained high/critical findings block deployment. - [ ] Run `git diff --check`, confirm no real `.env` is tracked, attach command counts to the ledger, and commit the final evidence. ## Self-review This plan covers the remaining audit findings: dependency-family upgrades, Python locking/auditing, immutable images, lockfile-enforced Docker installs, secret scanning, image scanning, frontend/Vitest exposure, and residual-advisory review. It deliberately avoids forced major upgrades and keeps each risky family in a reversible batch.