feat(security): MYCELIUM_LLAMA_REQUIRE_CHECKSUM=1 fail-closed — Pillar 6 follow-up to #188#189
Conversation
…Pillar 6 PR #188 added SHA-256 verification but warns-and-skips when no manifest entry / override is found. Security-conscious deployments now opt into strict mode: an unknown URI is refused outright instead of letting an unverified GGUF load. Resolution moves to BEFORE resolveModelFile() so strict mode never even pulls a 100 MB GGUF that it would then reject. Default behaviour unchanged (custom-GGUF power users keep the warn-and-proceed path). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Retargeted base from
|
…n W4.1
W4.1 of docs/wave-4-anti-echo.md says "the first PR of this wave creates
the directory" — this is that scaffold. Lands two files only:
- mcp-server/src/__tests__/fixtures/anti-echo/README.md
Developer-facing spec for the corpus shape, mirrors the governance
rules from the anchor doc but written for the file-format reader.
- mcp-server/src/__tests__/fixtures/anti-echo/corpus-types.ts
`AntiEchoCorpusFixture` + `AntiEchoCohortFixture` discriminated union
over the v1.1 Lesson envelope (services/wire-types.ts). Types only,
no loader, no harness — those land alongside the first concrete
fixture per category in subsequent PRs.
Why scaffold-first instead of one big "land all 8 fixtures" PR: the eight
attack categories from wave-4-anti-echo.md §"Corpus categories" each have
their own subtleties (cohort vs single-envelope, signing-key handling,
which §10 mechanism asserts). Decomposing into one fixture per follow-up
PR keeps each diff reviewable and lets the harness shape evolve from the
first concrete fixture rather than from speculation.
Why this can land while the 9-PR native-app queue is open: the new
directory lives entirely under `__tests__/fixtures/`, so it has zero file
overlap with the native-app stack (#185 / #187 / #188 / #189 / #190 /
#191 / #192 / #193 / #194). 939/939 node --test tests still green;
`tsc --noEmit` clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rain) Reed merged 10 PRs today: all 3 W4.1 anti-echo (#197/#198/#201), both W2 federation (#199/#200), 5 native-app (#190/#191/#192/#193/#194). Only the linear 4-PR #178-stack remains open (#185 independent + #187 → #188 → #189 strictly stacked). Three-cohort split collapsed to one cohort — old order- independence proofs (143rd/148th tick) now obsolete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…open While the previous commit was being prepared, Reed merged the remaining 4-PR native-app stack (#185, #187, #188, #189). All 14 PRs from yesterday's queue are now on main: 9 Native-App + 3 W4.1 + 2 W2. Key shift: the "wait for queue drain" block on Native-App Sub-Tasks 3, 6, 7, 8, 9, 10 is gone. Implementation can resume directly from the spikes in docs/native-*-spike.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
MYCELIUM_LLAMA_REQUIRE_CHECKSUM=1env /requireChecksumoption toLlamaCppEmbeddingProvider. When set and the GGUF URI has neither a manifest entry nor an override hash, init throws instead of warn-and-proceed. Default behaviour unchanged.resolveModelFile()so strict mode does not pull a ~100 MB GGUF only to reject it.parseBoolEnvhelper and unit tests for both the parser and the fail-closed code-path.Why
PR #188 shipped soft Pillar 6: known URIs are verified, unknown URIs warn-and-skip so power users running custom GGUFs aren't locked out. Security-conscious deployments need the opposite default — refuse anything we can't verify. This adds the opt-in switch without changing the default surface.
Test plan
npm test— 959 pass / 1 skip (full suite)MYCELIUM_LLAMA_REQUIRE_CHECKSUMso operators can correlate.parseBoolEnvcovers canonical truthy spellings + obvious falsy.Stack
Branched off
agent/llama-gguf-sha256(PR #188). Will rebase to main once #188 lands; the diff against main becomes the same patch (no PR #188 changes are touched).🤖 Generated with Claude Code