sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

radroots_sdk_package_license_lib.mjs (2050B)


      1 import { createHash } from "node:crypto";
      2 import { readFileSync } from "node:fs";
      3 import { join } from "node:path";
      4 
      5 const CONTRACT_PATH = "contracts/generated_package_licenses.v1.json";
      6 const EXPECTED_FILES = Object.freeze(["LICENSE-APACHE", "LICENSE-MIT"]);
      7 
      8 function fail(message) {
      9   throw new Error(`supply_chain_invalid: ${message}`);
     10 }
     11 
     12 function exactKeys(value, expected, context) {
     13   if (!value || typeof value !== "object" || Array.isArray(value)) {
     14     fail(`${context} must be an object`);
     15   }
     16   const actual = Object.keys(value).sort();
     17   if (JSON.stringify(actual) !== JSON.stringify([...expected].sort())) {
     18     fail(`${context} has invalid keys`);
     19   }
     20 }
     21 
     22 function sha256(path) {
     23   return createHash("sha256").update(readFileSync(path)).digest("hex");
     24 }
     25 
     26 export function validateGeneratedPackageLicenses(root, packageDirectories, expectedRevision) {
     27   const contract = JSON.parse(readFileSync(join(root, CONTRACT_PATH), "utf8"));
     28   exactKeys(
     29     contract,
     30     ["schema", "source_repository", "source_revision", "files"],
     31     "generated package license contract",
     32   );
     33   if (
     34     contract.schema !== "radroots.sdk.generated-package-licenses.v1" ||
     35     contract.source_repository !== "https://github.com/radrootslabs/lib" ||
     36     contract.source_revision !== expectedRevision
     37   ) {
     38     fail("generated package license authority drifted");
     39   }
     40   if (!Array.isArray(contract.files) || contract.files.length !== EXPECTED_FILES.length) {
     41     fail("generated package license inventory drifted");
     42   }
     43 
     44   for (let index = 0; index < EXPECTED_FILES.length; index += 1) {
     45     const file = contract.files[index];
     46     exactKeys(file, ["name", "sha256"], `generated package license ${index}`);
     47     if (file.name !== EXPECTED_FILES[index] || !/^[0-9a-f]{64}$/.test(file.sha256)) {
     48       fail("generated package license identity drifted");
     49     }
     50     for (const packageDirectory of packageDirectories) {
     51       if (sha256(join(packageDirectory, file.name)) !== file.sha256) {
     52         fail("generated package license bytes drifted");
     53       }
     54     }
     55   }
     56 }