Dependency security design

Scope: npm manifests and lockfiles, with a shared record for the parallel Python dependency workstream. The source and installed-App boundaries are recorded separately.

Current implementation and verified gap

The repository uses npm workspaces for apps/web, apps/desktop, and apps/cli. The Web application is an App Router application with output: "export"; its generated files are served by the Python worker. The desktop shell uses Electron and electron-builder. The root lockfile contains runtime, build, and optional dependency graphs for all workspaces.

The canonical Dependabot inventory at /tmp/openprogram-completion-audit/dependabot-open.json records 194 open alerts at the base: 154 npm alerts across 18 package names and 40 pip alerts across uv.lock. The npm baseline has 6 critical, 54 high, 78 medium, and 16 low alerts; 55 records are direct and 99 are transitive. The ignored report reports/content-security/npm-dependency-security-baseline.md records the exact advisories, ranges, versions, and commands. Range reconciliation treats comma-separated GitHub ranges as semver conjunctions and fails on parse errors.

Reference corpus and framework comparison

Fixed versions come from the GitHub advisory records and package registries. Registry metadata is checked with npm view before changing the lockfile. The selected framework versions require Node 22.12 or newer, so the root engine contract, CI bootstrap, and developer setup must use the same minimum.

AreaExisting capabilityAbsent capability or riskDecision
Next.jsApp Router, static export, client-side runtime APIs, no Next server in the packaged path.The installed 14.2.35 matched the affected ranges for current Next advisories, and Next 16 removes next lint.Use Next 16.3.5 with eslint 9 and a direct lint script. Keep static export through dynamic = "force-static" for the manifest route and the existing webpack build.
ElectronNative shell, preload isolation, packaged runtime, worker URL on loopback.Electron 37.10.3 matched the affected lock/direct records.Use Electron 44.4.3. Its package and unpacked app declare macOS 13 as the minimum; desktop checks cover the source API surface. Packaging must replace the installed Electron bundle before local App acceptance.
Raster annotationsImage crop, rotate, draw, text, shape, save, undo, redo, and selection/drag editing.tui-image-editor carried the vulnerable Fabric 4 chain and the replacement must preserve annotation interaction.Remove tui-image-editor and use maintained Fabric 7.4.0 directly as a transparent annotation layer over the native canvas. Crop and rotate flatten annotations into the image; selection, movement, resize, and text editing remain available before export.
Transitive npm graphOne npm lockfile pins reproducible workspace dependencies.Old nested tar, form-data, postcss, extract-zip, and legacy HTTP packages remained in the graph.Refresh compatible transitive paths and remove unmaintained chains where the graph has no fixed release. The final lock is checked against every advisory range, including package-absent records.
Python graphuv.lock is independently managed by the Python dependency workstream.AnyIO, torch, setuptools, and other pip advisories must be reconciled with their exact fixed ranges.Keep the same inventory, evidence, and full-gate contract; the parallel owner supplies Python version changes and evidence before integration.

Official references: Next.js 16 upgrade guide, Next.js 16.3.5 release, Electron 44 release, Fabric advisory GHSA-hfvx-25r5-qc3w, Fabric advisory GHSA-w22m-hvvm-xmwx, and the per-advisory links recorded in the ignored baseline and reconciliation reports.

Adopted, modified, and rejected choices

Target architecture and boundaries

All package resolution goes through the root npm lockfile. Direct workspace manifests declare the supported framework and shell versions; nested package entries are accepted only when their parent package requires them. The build boundary is npm ci --ignore-scripts followed by workspace checks. The runtime boundary is the exported Web assets, Electron main/preload code, and the Python worker that serves those assets. Untrusted input must not be passed to package CLIs or archive extractors without the existing product validation.

Electron package resolution does not update an existing /Applications/OpenProgram.app by itself. The supported local path is to package the current checkout with the trusted runtime base, install the resulting app over the single default App, then run scripts/refresh-local-app.sh once. Verification must inspect the installed app's actual process.versions.electron; source-only checks do not establish the installed runtime version.

The Python dependency workstream owns uv.lock and records its host policy in the shared report: Intel macOS supports BM25, the optional embedding wheel is unavailable on Intel, and macOS arm64 embedding wheels require Python 3.14 or newer. The current verification host is macOS 15.7.3.

Security failures are handled as dependency-resolution failures: a clean install, audit, typecheck, build, or affected test failure blocks completion and is recorded with the exact command. Compatibility failures preserve the old manifest in Git until the minimum source adjustment is proven by the affected check. No remote write, release, installed-App refresh, or Python source edit is in this workstream.

Acceptance criteria

  1. At the final commit, every direct npm manifest version and every lockfile instance is outside each applicable fixed advisory range in the canonical inventory; no alert is dismissed or hidden.
  2. npm ci --ignore-scripts succeeds on the supported Node/npm engines, npm audit --json reports zero vulnerabilities, and the canonical range reconciliation reports no affected npm version. If an upstream no-patch advisory remains, the report names its parent chain, reason, and tested replacement.
  3. npm run build --workspace apps/web, npm run typecheck --workspace apps/cli, npm test --workspace apps/web, npm run check:web, npm run check:desktop, and npm run check:cli are run from a clean install. The final report distinguishes existing source failures from dependency-induced failures.
  4. The final diff contains only dependency manifests/lockfile, necessary Next/Electron compatibility source, the canonical design, and the ignored evidence rule. The worktree is clean after the scoped commit.

Full gate manifest

Implementation status

The npm candidate uses Next 16.3.5, Electron 44.4.3, Fabric 7.4.0, and the fixed transitive graph recorded in the lockfile. Source checks cover static export, direct lint invocation, the native desktop surface, and the raster editor's crop, rotate, draw, annotation, save, undo, redo, and destroy paths. The Python section remains a coordination boundary for the separate uv.lock changes. Final audit counts, reconciliation output, and residual source-test failures belong in the ignored final ledger.