From ab7cb8cbab738be2485ef7f41959672c979e01fa Mon Sep 17 00:00:00 2001 From: Constantin <74049135+constantin-jais@users.noreply.github.com> Date: Fri, 9 Oct 2026 14:23:10 +0200 Subject: [PATCH] fix(supply-chain): keep advisories out of the required check (Y44-Y46) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Y44 / I-26: the required check runs `bans licenses sources` only, still with --locked. An advisory verdict depends on the RustSec database of the day; a fleet advisory control notifies on it without blocking. - Y45: the base allowlist admits `Apache-2.0 WITH LLVM-exception` (ADR-0042 §11). - Y46: `confidence-threshold` is 0.9; `multiple-versions` stays "warn". deny.toml stays byte-identical across the Rust repositories. Owner-arbitration: 2026-10-09 Claude-Session: https://claude.ai/code/session_01Qw4AExV42cXJ67Sj9dqLVf Signed-off-by: Constantin <74049135+constantin-jais@users.noreply.github.com> --- deny.toml | 21 +++++++++++----- tools/quality/check-dependency-policy.test.ts | 7 ++++++ tools/quality/check-dependency-policy.ts | 25 +++++++++---------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/deny.toml b/deny.toml index 4945131..be079b8 100644 --- a/deny.toml +++ b/deny.toml @@ -1,8 +1,14 @@ -# Base dependency policy of the constellation (decision Y43, 2026-10-09). -# Every Rust repository of libre-ai carries this file unchanged and executes it -# with cargo-deny from its required check. The licence allowlist is the inbound -# policy of ADR-0042 §4 and §11; GPL (linked), AGPL and SSPL are refused by -# omission. +# Base dependency policy of the constellation (decisions Y43-Y46, 2026-10-09). +# Every Rust repository of libre-ai carries this file unchanged and executes +# `bans`, `licenses` and `sources` with cargo-deny from its required check. +# The licence allowlist is the inbound policy of ADR-0042 §4 and §11; GPL +# (linked), AGPL and SSPL are refused by omission. +# +# `[advisories]` is NOT part of the required verdict (I-26, Y44): an advisory +# verdict depends on the RustSec database of the day, so a fleet advisory +# control notifies without blocking. The section is kept for that control and +# for manual runs (`cargo deny check advisories`), which also apply +# `yanked = "deny"`. # # `[sources.allow-org] github = ["libre-ai"]` bounds git-dep trust to the # organisation (ADR-0020 §2.5). `allow-wildcard-paths` admits the version-less @@ -17,7 +23,7 @@ all-features = true yanked = "deny" [licenses] -confidence-threshold = 0.8 +confidence-threshold = 0.9 unused-allowed-license = "allow" # The allowlist governs inbound dependencies only: the workspace's own private # crates carry the outbound licences of the repository (REUSE.toml), which @@ -28,6 +34,9 @@ allow = [ "MIT", "MIT-0", "Apache-2.0", + # Apache-2.0 plus an additional permission (ADR-0042 §11, Y45); carried by + # `ar_archive_writer`, a build dependency of `psm` through `sqlparser`. + "Apache-2.0 WITH LLVM-exception", "BSD-2-Clause", "BSD-3-Clause", "ISC", diff --git a/tools/quality/check-dependency-policy.test.ts b/tools/quality/check-dependency-policy.test.ts index 2bd40e2..7b1a1f9 100644 --- a/tools/quality/check-dependency-policy.test.ts +++ b/tools/quality/check-dependency-policy.test.ts @@ -12,10 +12,17 @@ import { countLockedPackages, main, parseArguments, + REQUIRED_CHECKS, sha256Of, verifyDigest, } from "./check-dependency-policy"; +describe("REQUIRED_CHECKS", () => { + test("keeps the calendar-dependent advisory verdict out of the required check (I-26)", () => { + expect([...REQUIRED_CHECKS]).toEqual(["bans", "licenses", "sources"]); + }); +}); + describe("archiveFor", () => { test("pins the CI runner archive to the fleet template digest", () => { const archive = archiveFor("linux", "x64"); diff --git a/tools/quality/check-dependency-policy.ts b/tools/quality/check-dependency-policy.ts index 9deaf60..2263ef2 100644 --- a/tools/quality/check-dependency-policy.ts +++ b/tools/quality/check-dependency-policy.ts @@ -1,10 +1,9 @@ // SPDX-FileCopyrightText: 2026 Libre AI contributors // SPDX-License-Identifier: EUPL-1.2 // -// Dependency policy gate (decision Y43, 2026-10-09): executes this +// Dependency policy gate (decisions Y43 and Y44, 2026-10-09): executes this // repository's own `deny.toml` against its committed Cargo graph(s) with -// cargo-deny — advisories, bans, licenses and sources — from the required -// check. +// cargo-deny — bans, licenses and sources — from the required check. // // Why the binary is fetched here rather than taken from PATH: the required // check runs inside the source composition, whose runner installs Bun, Node @@ -16,11 +15,11 @@ // `reusable-dependency-policy.yml`). The cached archive is re-hashed on every // run, so the cache is never trusted beyond its digest. // -// Why advisories block here although the fleet template only reports them: -// Y43 makes advisories part of the required verdict. The verdict therefore -// depends on the RustSec database of the day; an accepted risk is recorded as -// a dated waiver in `deny.toml` under docs/security/ADVISORY-WAIVER-POLICY.md -// (project-governance), never as a silent exception. +// Why advisories are not checked here (I-26, Y44): bans, licenses and sources +// are a pure function of the committed Cargo.lock and deny.toml, so their +// verdict is reproducible at constant commit, which is what a required check +// may assert. An advisory verdict depends on the RustSec database fetched at +// run time; a fleet advisory control notifies on it without blocking. import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; @@ -38,6 +37,9 @@ import { dirname, isAbsolute, join, resolve } from "node:path"; export const CARGO_DENY_VERSION = "0.19.5"; +/** The checks whose verdict is a function of the tree alone (I-26): no `advisories`. */ +export const REQUIRED_CHECKS = ["bans", "licenses", "sources"] as const; + export interface CargoDenyArchive { readonly triple: string; readonly url: string; @@ -213,10 +215,7 @@ export async function main(argv: readonly string[]): Promise { "--config", config, "--show-stats", - "advisories", - "bans", - "licenses", - "sources", + ...REQUIRED_CHECKS, ], root, ); @@ -229,7 +228,7 @@ export async function main(argv: readonly string[]): Promise { rmSync(scratch, { recursive: true, force: true }); } console.log( - `Dependency policy verified: advisories, bans, licenses and sources hold for ` + + `Dependency policy verified: ${REQUIRED_CHECKS.join(", ")} hold for ` + `${manifests.length} manifest(s), ${lockedPackages} locked package(s) inspected ` + `(cargo-deny ${CARGO_DENY_VERSION}, archive sha256 ${archive.sha256}).`, );