Skip to content

Commit 68c8478

Browse files
voidstackloopclaude
andcommitted
release: v1.3.0 — ModelForge Medical, a clinical decision-support workspace
This release moves the project from a general-purpose local AI chat/agent client to a medical-focused clinical workspace. See the notice at the top of README.md and its Product boundary section for what that does and doesn't mean (never an autonomous diagnostician or prescriber, no regulatory certification claimed). Highlights: - Clinical layer: Patient Cases, Evidence Library, per-case Knowledge Graph, and an Audit & Privacy log, plus a structured 8-section response contract and deterministic safety checks (emergency red-flag detection, allergy/medication conflict warnings, transmission preview, redaction) that run independently of the model. - MCP client rework on the official SDK: protocol version negotiation, AJV schema validation, resources/prompts, OAuth 2.1+PKCE, per-tool trust profiles, and a DICOM MCP integration with an enforced tool denylist. - Privacy/security: passphrase-based encryption at rest for patient cases and chat sessions, automatic session locking, configurable audit retention, and a SHA-256 hash-chained tamper-evident audit log. - Approved model registry, clinical-note review sign-off, structured consent records, and a swappable MedicationSafetyProvider. - Rust-backed data store I/O (lib/, napi-rs): atomic JSON read/write and audit-log hashing/appends moved off the O(n) Node path, fixing an O(n^2) audit-log growth pattern (~20s -> ~0.3s at 5,000 events) — every native call has a verified pure-TypeScript fallback. See docs/RUST_DATASTORE_TEST_REPORT.md and docs/RUST_MIGRATION_ASSESSMENT.md. - SBOM generation and Dependabot coverage across every workspace; CI's Rust job now also builds and load-verifies the native addon on Windows and macOS, not just Linux. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent d39eb04 commit 68c8478

77 files changed

Lines changed: 9484 additions & 353 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
version: 2
2+
updates:
3+
# Each of these is an independent package.json/package-lock.json — kept as
4+
# separate entries (rather than one root entry) so an update PR for, say,
5+
# frontend never bundles unrelated app or e2e dependency bumps.
6+
- package-ecosystem: npm
7+
directory: /frontend
8+
schedule:
9+
interval: weekly
10+
open-pull-requests-limit: 10
11+
groups:
12+
# Security patches land immediately rather than waiting in a batched
13+
# group PR that might sit unreviewed.
14+
production-dependencies:
15+
applies-to: version-updates
16+
dependency-type: production
17+
development-dependencies:
18+
applies-to: version-updates
19+
dependency-type: development
20+
21+
- package-ecosystem: npm
22+
directory: /app
23+
schedule:
24+
interval: weekly
25+
open-pull-requests-limit: 10
26+
groups:
27+
production-dependencies:
28+
applies-to: version-updates
29+
dependency-type: production
30+
development-dependencies:
31+
applies-to: version-updates
32+
dependency-type: development
33+
34+
- package-ecosystem: npm
35+
directory: /e2e
36+
schedule:
37+
interval: weekly
38+
open-pull-requests-limit: 5
39+
40+
- package-ecosystem: npm
41+
directory: /mastervault-mcp-server
42+
schedule:
43+
interval: weekly
44+
open-pull-requests-limit: 5
45+
46+
# lib/ is the napi-rs (Rust) download engine bound into the Electron app.
47+
- package-ecosystem: cargo
48+
directory: /lib
49+
schedule:
50+
interval: weekly
51+
open-pull-requests-limit: 5
52+
53+
# ml/hardware-recommender is a standalone Python project (see ci.yml's
54+
# python-recommender job) — its own dependency surface, tracked separately
55+
# from the shipped app since only its exported ONNX artifact ships.
56+
- package-ecosystem: pip
57+
directory: /ml/hardware-recommender
58+
schedule:
59+
interval: weekly
60+
open-pull-requests-limit: 5
61+
62+
# The CI/release workflows' own actions (actions/checkout, setup-node, …)
63+
# — easy to forget since they're not in any package.json.
64+
- package-ecosystem: github-actions
65+
directory: /
66+
schedule:
67+
interval: weekly
68+
open-pull-requests-limit: 5

.github/workflows/ci.yml

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,23 @@ jobs:
136136
retention-days: 7
137137

138138
rust:
139-
# lib/ (modelforge-native) is the napi-rs download engine used by
140-
# download-queue.ts. GitHub's ubuntu-latest runners ship rustup with a
141-
# default stable toolchain already installed, so this only needs to add
142-
# the two components fmt/clippy actually use.
143-
runs-on: ubuntu-latest
139+
# lib/ (modelforge-native) is the napi-rs addon backing GGUF downloads
140+
# and, more recently, the JSON datastore/audit-hashing primitives (see
141+
# docs/ARCHITECTURE.md). fmt/clippy/cargo test only prove the Rust side
142+
# is correct on whichever OS runs them — they say nothing about whether
143+
# the resulting `.node` binary actually loads under Node on that OS,
144+
# which is a materially different failure mode (wrong ABI, missing
145+
# platform target, packaging mismatch). Previously this job only ran on
146+
# ubuntu-latest, so nothing in CI ever built or loaded the addon on
147+
# Windows or macOS despite installers shipping for both — see
148+
# docs/RUST_MIGRATION_ASSESSMENT.md's platform-matrix section. The
149+
# matrix below and the "napi build + require() smoke test" step close
150+
# that gap.
151+
strategy:
152+
fail-fast: false
153+
matrix:
154+
os: [ubuntu-latest, windows-latest, macos-latest]
155+
runs-on: ${{ matrix.os }}
144156
defaults:
145157
run:
146158
working-directory: lib
@@ -161,10 +173,15 @@ jobs:
161173
restore-keys: |
162174
${{ runner.os }}-cargo-
163175
176+
# fmt/clippy only need to run once — Rust source and formatting are
177+
# identical across OSes, so repeating this on all three runners would
178+
# just burn CI minutes for the same answer three times.
164179
- name: Format check
180+
if: matrix.os == 'ubuntu-latest'
165181
run: cargo fmt --check
166182

167183
- name: Clippy
184+
if: matrix.os == 'ubuntu-latest'
168185
run: cargo clippy --all-targets -- -D warnings
169186

170187
- name: Build
@@ -173,6 +190,89 @@ jobs:
173190
- name: Test
174191
run: cargo test
175192

193+
- uses: actions/setup-node@v4
194+
with:
195+
node-version: 22
196+
cache: npm
197+
cache-dependency-path: lib/package-lock.json
198+
199+
- name: Install napi CLI
200+
run: npm ci
201+
202+
- name: napi build (produces the real platform-specific .node binary)
203+
run: npm run build:debug
204+
205+
# The actual gap this job exists to close: proves Node on *this* OS
206+
# can load the binary napi build just produced, not just that Cargo
207+
# compiled it. A wrong target triple, an ABI mismatch, or a packaging
208+
# error would fail cargo build's cross-compile silently-succeed case
209+
# but fail right here.
210+
- name: Load the built addon under Node and verify its exports
211+
shell: bash
212+
run: |
213+
node -e "
214+
const addon = require('../app/native');
215+
const expected = ['downloadGgufFile', 'DownloadManager', 'readJsonFileNative', 'writeJsonFileAtomicNative', 'sha256HexNative', 'appendJsonArrayElementNative'];
216+
const missing = expected.filter((name) => !(name in addon));
217+
if (missing.length > 0) {
218+
console.error('Native addon loaded but is missing expected exports:', missing);
219+
process.exit(1);
220+
}
221+
console.log('Native addon loaded successfully on ${{ matrix.os }} with all expected exports.');
222+
"
223+
224+
sbom:
225+
# Generates a CycloneDX SBOM per npm workspace so every release has an
226+
# auditable, machine-readable dependency manifest — required groundwork
227+
# for the supply-chain/provenance controls flagged in
228+
# docs/ENTERPRISE_READINESS_ASSESSMENT.md, and useful on its own for
229+
# answering "are we affected by CVE-X" without re-deriving the dependency
230+
# tree by hand. Runs independently of the test job so a flaky SBOM
231+
# generation never blocks the build/test signal.
232+
runs-on: ubuntu-latest
233+
234+
steps:
235+
- uses: actions/checkout@v4
236+
237+
- uses: actions/setup-node@v4
238+
with:
239+
node-version: 22
240+
cache: npm
241+
cache-dependency-path: |
242+
frontend/package-lock.json
243+
app/package-lock.json
244+
mastervault-mcp-server/package-lock.json
245+
246+
- name: Install frontend dependencies
247+
working-directory: frontend
248+
run: npm ci
249+
250+
- name: Install app dependencies
251+
working-directory: app
252+
run: npm ci
253+
254+
- name: Install mastervault-mcp-server dependencies
255+
working-directory: mastervault-mcp-server
256+
run: npm ci
257+
258+
- name: Generate SBOM (frontend)
259+
working-directory: frontend
260+
run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-frontend.cdx.json
261+
262+
- name: Generate SBOM (app)
263+
working-directory: app
264+
run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-app.cdx.json
265+
266+
- name: Generate SBOM (mastervault-mcp-server)
267+
working-directory: mastervault-mcp-server
268+
run: npx --yes @cyclonedx/cyclonedx-npm --output-file ../sbom-mastervault-mcp-server.cdx.json
269+
270+
- uses: actions/upload-artifact@v4
271+
with:
272+
name: sbom
273+
path: sbom-*.cdx.json
274+
retention-days: 90
275+
176276
python-recommender:
177277
# ml/hardware-recommender/ is a standalone project (its own venv, own
178278
# train/download-dataset scripts) that isn't part of the app's build —

0 commit comments

Comments
 (0)