fix: recompute local promotion evidence

This commit is contained in:
DongHyeonka
2026-08-02 07:02:39 +09:00
parent 92e5cace5c
commit 1b4b0c2821
8 changed files with 837 additions and 253 deletions
+21 -57
View File
@@ -18,16 +18,17 @@ import {
vulnerabilityReportArtifactSchema,
} from "./contracts/release-artifacts.ts";
import {
diffDependencyInventories,
flattenPnpmDependencyTree,
isValidSha512Integrity,
parsePnpmLockfilePackages,
supplyChainDigest,
validateDependencyReview,
validateLicensePolicy,
verifySupplyChainCoherence,
type DependencyInventoryDiff,
} from "./lib/supply-chain.ts";
import {
distChecksumsText,
recomputeDependencyEvidence,
recomputeLicenseEvidence,
} from "./lib/local-policy-evidence.ts";
import { writeValidatedJsonArtifact } from "./lib/validated-json-artifact.ts";
import { digestReleaseInputFiles } from "./lib/release-input-evidence.ts";
import {
@@ -159,7 +160,6 @@ const inventory = await buildDependencyInventory();
const licensePolicy = JSON.parse(
await readFile("config/security/dependency-policy.json", "utf8"),
);
const licenseResult = validateLicensePolicy(inventory, licensePolicy);
const baseline = await optionalJson(
"config/security/dependency-baseline.json",
@@ -174,39 +174,17 @@ const dependencyEvidence = JSON.parse(
),
);
const skipsBaseline = process.argv.includes("--no-baseline");
const baselineFailures: string[] = [];
let dependencyDiff: DependencyInventoryDiff = Object.freeze({
added: Object.freeze([]),
removed: Object.freeze([]),
changed: Object.freeze([]),
upgrades: Object.freeze([]),
const dependencyPolicy = recomputeDependencyEvidence({
inventory,
baseline,
baselineApproval,
dependencyChangeEvidence: dependencyEvidence,
skipBaseline: skipsBaseline,
});
let reviewResult: ReturnType<typeof validateDependencyReview> = Object.freeze({
passed: skipsBaseline,
highRisk: Object.freeze([]),
failures: Object.freeze(
skipsBaseline ? [] : ["dependency baseline unavailable"],
),
const licenseEvidence = recomputeLicenseEvidence({
inventory,
policy: licensePolicy,
});
if (baseline && baselineApproval) {
const actualBaselineDigest = supplyChainDigest(baseline);
if (
baselineApproval.schemaVersion !== 1 ||
baselineApproval.snapshotDigest !== actualBaselineDigest ||
typeof baselineApproval.owner !== "string" ||
!baselineApproval.owner
) {
baselineFailures.push("dependency baseline approval digest mismatch");
}
dependencyDiff = diffDependencyInventories(baseline, inventory);
reviewResult = validateDependencyReview(
dependencyDiff,
inventory,
dependencyEvidence,
);
} else if (!skipsBaseline) {
baselineFailures.push("dependency baseline and approval are required");
}
const vulnerabilityReport = {
schemaVersion: 1,
@@ -315,9 +293,8 @@ const coherence = verifySupplyChainCoherence(
);
const localFailures = [
...licenseResult.failures,
...baselineFailures,
...reviewResult.failures,
...licenseEvidence.failures,
...dependencyPolicy.failures,
...coherence.failures,
];
const localPassed = localFailures.length === 0;
@@ -329,8 +306,8 @@ const verification = {
sourceSetSha256,
distSha256: distDigest,
sbomSha256: supplyChainDigest(sbom),
dependencyDiff,
highRiskReview: reviewResult.highRisk,
dependencyDiff: dependencyPolicy.dependencyDiff,
highRiskReview: dependencyPolicy.highRisk,
vulnerabilityStatus: vulnerabilityReport.status,
provenanceAttestationStatus: "FAIL_UNVERIFIED",
failures: localFailures,
@@ -349,21 +326,8 @@ const bundleReport = {
},
outputs,
};
const dependencyDiffReport = {
schemaVersion: 2,
baselineDigest: baseline ? supplyChainDigest(baseline) : null,
currentDigest: supplyChainDigest(inventory),
...dependencyDiff,
highRisk: reviewResult.highRisk,
reviewFailures: reviewResult.failures,
};
const licenseReport = {
schemaVersion: 1,
status: licenseResult.passed ? "PASS" : "FAIL",
dependencyCount: inventory.dependencyCount,
results: licenseResult.results,
failures: licenseResult.failures,
};
const dependencyDiffReport = dependencyPolicy.report;
const licenseReport = licenseEvidence.report;
await mkdir("artifacts/performance", { recursive: true });
await mkdir("artifacts/release", { recursive: true });
@@ -390,7 +354,7 @@ await writeValidatedJsonArtifact({
});
await writeFile(
"artifacts/release/checksums.txt",
`${outputs.map((output) => `${output.sha256} ${output.path}`).join("\n")}\n`,
distChecksumsText(outputs),
);
await writeValidatedJsonArtifact({
path: "artifacts/security/dependency-diff.json",