security: gate audits on jpkg advisories

Jaime Fournier <jaimef@linbsd.org>

7d22f49233357eddb63834aaa91cf378df6fd010

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 66ca438..e8d4337 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -4,6 +4,9 @@ on:
   push:
     branches: [master]
   pull_request:
+  schedule:
+    # Weekly advisory freshness check: `make audit` runs cargo-audit and jpkg audit.
+    - cron: '23 9 * * 1'
 
 env:
   IMAGE: jerboa21/jerboa
diff --git a/Makefile b/Makefile
index eca5c15..6d497d2 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@ TYPED_LLVMIR_PARITY_FN ?= sample_typed_llvmir_smoke::main
 LLVM_BIN ?= $(shell if command -v llvm-as >/dev/null 2>&1; then dirname "$$(command -v llvm-as)"; elif [ -x /opt/homebrew/opt/llvm/bin/llvm-as ]; then echo /opt/homebrew/opt/llvm/bin; elif [ -x /usr/local/opt/llvm/bin/llvm-as ]; then echo /usr/local/opt/llvm/bin; fi)
 TYPED_WRAPPER_DIR ?= build/typed/jerboa
 
-.PHONY: help chez static-supported-check chez-cross build binary binary-typed binary-typed-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-llvmir typed-llvmir-check typed-llvmir-smoke typed-llvmir-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase4f test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-uri-fuzz fuzz-format-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check docker-build docker-push lint
+.PHONY: help chez static-supported-check chez-cross build binary binary-typed binary-typed-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-llvmir typed-llvmir-check typed-llvmir-smoke typed-llvmir-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase4f test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native jpkg-audit import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-uri-fuzz fuzz-format-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check docker-build docker-push lint
 .PHONY: check-cross-tools docker fuzz-websocket-fuzz jlsp jlsp-freebsd-amd64 \
         jlsp-install jlsp-linux-amd64 jlsp-portable jmcp-freebsd-amd64 \
         jmcp-freebsd-arm64 jmcp-linux-amd64 jmcp-linux-arm64 \
@@ -1735,6 +1735,9 @@ audit-native:
 	fi; \
 	cd $(RUST_NATIVE_DIR) && "$$cargo_audit" audit -D warnings
 
+jpkg-audit: build
+	@$(SCHEME) --libdirs $(LIBDIRS) --script tools/jpkg-main.ss audit
+
 security-audit:
 	@tools/security-audit.sh
 
@@ -1755,7 +1758,7 @@ unsafe-deserialize-check:
 import-policy-check: build
 	@$(SCHEME) --libdirs $(LIBDIRS) --script tools/check-import-policy.ss examples
 
-audit: source-balance restrict-closure-check unsafe-deserialize-check import-policy-check security-audit audit-native data-check security-production unification-check
+audit: source-balance restrict-closure-check unsafe-deserialize-check import-policy-check security-audit audit-native jpkg-audit data-check security-production unification-check
 
 test-gaps:
 	$(SCHEME) --libdirs $(LIBDIRS) --script tests/test-gaps.ss
diff --git a/docs/jpkg-guide.md b/docs/jpkg-guide.md
index 8dd5617..88b5b16 100644
--- a/docs/jpkg-guide.md
+++ b/docs/jpkg-guide.md
@@ -410,6 +410,9 @@ capabilities, command, and the build-log SHA-256.
   last one you saw (equivocation / history-rewrite detection).
 
 Run it in CI: a non-zero exit on a blocking finding fails the pipeline.
+Advisory provenance is the configured jpkg registry metadata: OSV records
+live under signed TUF targets, and the snapshot/timestamp roles pin the exact
+advisory set the client accepted before applying it to `jpkg.lock`.
 
 ---
 
diff --git a/docs/kimi3-security-recommmendations.md b/docs/kimi3-security-recommmendations.md
index b35140c..c9a3243 100644
--- a/docs/kimi3-security-recommmendations.md
+++ b/docs/kimi3-security-recommmendations.md
@@ -862,6 +862,14 @@ keep `cargo audit -D warnings`; add a scheduled weekly job that fails on
 new advisories affecting locked versions; document the OSV DB snapshot
 provenance.
 
+- **Status:** complete for the repo gate. `make audit` now depends on
+  `jpkg-audit`, which runs the dev-tree jpkg CLI against this repo's
+  `jpkg.lock` and fails on blocking advisories/yanks/transparency findings,
+  while `audit-native` keeps `cargo audit -D warnings` for Rust. The GitHub CI
+  workflow has a weekly scheduled run of the same audit gate. `docs/jpkg-guide.md`
+  documents that jpkg advisory provenance is the signed TUF advisory target set
+  accepted by snapshot/timestamp metadata.
+
 ### K3-P2-03 — Automated TCB accounting
 **Serves:** G5. **Effort:** 1 week.
 
@@ -1020,7 +1028,7 @@ Track these in `docs/status.md` per release:
 | Fuzz corpora / crash regressions | 0 / 0 | per-parser corpora + every crash a test |
 | Exploit-shaped regression tests | ~0 | ≥ 1 per historical finding |
 | Sandboxed-by-default app entry | no | yes (P0-06) |
-| Supply-chain gates in `make audit` | partial | jpkg audit + cargo audit + signatures required |
+| Supply-chain gates in `make audit` | jpkg audit + cargo audit wired 2026-07-27; generated projects require signatures/provenance | signatures required for all release install checks |
 | Security-doc drift items | ≥ 5 (§4.4) | 0 |
 | Time from advisory → release evidence answering "affected?" | unmeasured | < 1 hour drill, quarterly |