sdk

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

commit fe61cbdbcc10001bada09e796e583b8c86e70525
parent f5daaf2be9febea5963169b54d1739e28e24bfff
Author: triesap <tyson@radroots.org>
Date:   Tue, 25 Aug 2026 07:17:38 +0000

security: align package supply-chain evidence

Diffstat:
MAGENTS.md | 3+++
MREADME | 3++-
Mpackage.json | 3++-
Mpackages/core-bindings/LICENSE-APACHE | 2+-
Mpackages/core-bindings/LICENSE-MIT | 2+-
Mpackages/event-bindings/LICENSE-APACHE | 2+-
Mpackages/event-bindings/LICENSE-MIT | 2+-
Mpackages/event-codec-wasm/LICENSE-APACHE | 2+-
Mpackages/event-codec-wasm/LICENSE-MIT | 2+-
Mpackages/identity-bindings/LICENSE-APACHE | 2+-
Mpackages/identity-bindings/LICENSE-MIT | 2+-
Mpackages/replica-schema-bindings/LICENSE-APACHE | 2+-
Mpackages/replica-schema-bindings/LICENSE-MIT | 2+-
Mpackages/replica-store-wasm/LICENSE-APACHE | 2+-
Mpackages/replica-store-wasm/LICENSE-MIT | 2+-
Mpackages/replica-sync-wasm/LICENSE-APACHE | 2+-
Mpackages/replica-sync-wasm/LICENSE-MIT | 2+-
Mpackages/trade-bindings/LICENSE-APACHE | 2+-
Mpackages/trade-bindings/LICENSE-MIT | 2+-
Atools/radroots_sdk_supply_chain.mjs | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 files changed, 130 insertions(+), 18 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -72,6 +72,9 @@ its subtree. `cargo extbuild run -- ...`. - `pnpm run contracts:check` validates the exact historical inventory and the absence of forbidden public roots without requiring a lib checkout. +- `pnpm run supply-chain:check` validates the exact pnpm toolchain and lock, + immutable public Lib source lock, package repository identities, workspace- + only internal edges, and byte-identical package license artifacts. - `pnpm run test:tools` runs standalone tool and boundary tests. - `pnpm run source:check` and generation/freshness commands require an exact `RADROOTS_LIB_SOURCE_ROOT` matching the checked-in lock. `pnpm run check` is diff --git a/README b/README @@ -9,7 +9,8 @@ capsule. Generated TypeScript, Wasm, Swift, and Kotlin surfaces are produced through `tools/radroots_sdk_artifact.mjs` from the exact `radrootslabs/lib` revision recorded in `radroots.lib.source-lock.v1.toml`. -Use `pnpm run contracts:check` for standalone contract validation and +Use `pnpm run supply-chain:check` for locked dependency, source, and license +validation, `pnpm run contracts:check` for standalone contract validation, and `pnpm run check` with an exact `RADROOTS_LIB_SOURCE_ROOT` for the complete generated-package lane. See `AGENTS.md` and `CONTRIBUTING.md` for repository rules and command requirements. diff --git a/package.json b/package.json @@ -3,6 +3,7 @@ "private": true, "packageManager": "pnpm@10.25.0", "scripts": { + "supply-chain:check": "node tools/radroots_sdk_supply_chain.mjs", "contracts:check": "node tools/radroots_sdk_contract.mjs", "source:check": "node tools/radroots_sdk_artifact.mjs source-check", "generate:ts": "node tools/radroots_sdk_artifact.mjs write typescript", @@ -12,7 +13,7 @@ "generate": "pnpm run generate:ts && pnpm run generate:wasm && pnpm run generate:swift && pnpm run generate:kotlin", "check:generated": "node tools/radroots_sdk_artifact.mjs check typescript && node tools/radroots_sdk_artifact.mjs check wasm && node tools/radroots_sdk_artifact.mjs check swift && node tools/radroots_sdk_artifact.mjs check kotlin", "test:tools": "node --test tools/*.test.mjs", - "check": "pnpm run contracts:check && pnpm run generate && pnpm -r build && pnpm -r typecheck && pnpm run test:tools && pnpm run check:generated", + "check": "pnpm run supply-chain:check && pnpm run contracts:check && pnpm run generate && pnpm -r build && pnpm -r typecheck && pnpm run test:tools && pnpm run check:generated", "build": "pnpm run generate:ts && pnpm run generate:wasm && pnpm -r build", "typecheck": "pnpm -r typecheck" }, diff --git a/packages/core-bindings/LICENSE-APACHE b/packages/core-bindings/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/core-bindings/LICENSE-MIT b/packages/core-bindings/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/event-bindings/LICENSE-APACHE b/packages/event-bindings/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/event-bindings/LICENSE-MIT b/packages/event-bindings/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/event-codec-wasm/LICENSE-APACHE b/packages/event-codec-wasm/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/event-codec-wasm/LICENSE-MIT b/packages/event-codec-wasm/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/identity-bindings/LICENSE-APACHE b/packages/identity-bindings/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/identity-bindings/LICENSE-MIT b/packages/identity-bindings/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/replica-schema-bindings/LICENSE-APACHE b/packages/replica-schema-bindings/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/replica-schema-bindings/LICENSE-MIT b/packages/replica-schema-bindings/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/replica-store-wasm/LICENSE-APACHE b/packages/replica-store-wasm/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/replica-store-wasm/LICENSE-MIT b/packages/replica-store-wasm/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/replica-sync-wasm/LICENSE-APACHE b/packages/replica-sync-wasm/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/replica-sync-wasm/LICENSE-MIT b/packages/replica-sync-wasm/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/trade-bindings/LICENSE-APACHE b/packages/trade-bindings/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2025 Tyson Lupul +Copyright 2026 Tyson Lupul Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/trade-bindings/LICENSE-MIT b/packages/trade-bindings/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Tyson Lupul +Copyright (c) 2026 Tyson Lupul Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/tools/radroots_sdk_supply_chain.mjs b/tools/radroots_sdk_supply_chain.mjs @@ -0,0 +1,107 @@ +import { readFileSync, readdirSync } from "node:fs"; +import { basename, dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = dirname(dirname(fileURLToPath(import.meta.url))); +const expectedLicense = "MIT OR Apache-2.0"; +const expectedRepository = "git+https://github.com/radrootslabs/sdk.git"; +const expectedPackages = [ + "core-bindings", + "event-bindings", + "event-codec-wasm", + "identity-bindings", + "replica-schema-bindings", + "replica-store-wasm", + "replica-sync-wasm", + "trade-bindings", +]; + +function fail(message) { + throw new Error(`supply_chain_invalid: ${message}`); +} + +function readJson(path) { + return JSON.parse(readFileSync(path, "utf8")); +} + +function packageDirectories() { + return readdirSync(join(root, "packages"), { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => join(root, "packages", entry.name)) + .filter((path) => { + try { + readFileSync(join(path, "package.json")); + return true; + } catch { + return false; + } + }) + .sort(); +} + +function verifyManifest(path) { + const manifest = readJson(join(path, "package.json")); + if (manifest.license !== expectedLicense) fail("package license drifted"); + if ( + manifest.repository?.type !== "git" || + manifest.repository?.url !== expectedRepository || + manifest.repository?.directory !== `packages/${basename(path)}` + ) { + fail("package repository identity drifted"); + } + if ( + !Array.isArray(manifest.files) || + !manifest.files.includes("LICENSE-MIT") || + !manifest.files.includes("LICENSE-APACHE") + ) { + fail("package artifact omits governed license files"); + } + for (const section of ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"]) { + for (const value of Object.values(manifest[section] ?? {})) { + if (!String(value).startsWith("workspace:")) { + fail("package dependency is not workspace-locked"); + } + } + } + for (const license of ["LICENSE-MIT", "LICENSE-APACHE"]) { + if (readFileSync(join(path, license)).compare(readFileSync(join(root, license))) !== 0) { + fail("package license bytes differ from the repository authority"); + } + } +} + +const manifest = readJson(join(root, "package.json")); +if (manifest.packageManager !== "pnpm@10.25.0") fail("package manager drifted"); +if (manifest.devDependencies?.typescript !== "^5.9.0") fail("TypeScript input drifted"); +if (Object.keys(manifest.devDependencies ?? {}).length !== 1) fail("root dependency inventory drifted"); + +const lock = readFileSync(join(root, "pnpm-lock.yaml"), "utf8"); +for (const required of [ + "lockfileVersion: '9.0'", + "typescript@5.9.3:", + "specifier: ^5.9.0", + "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", +]) { + if (!lock.includes(required)) fail("pnpm lock authority drifted"); +} +for (const forbidden of ["git+", "github:", "http://"]) { + if (lock.includes(forbidden)) fail("pnpm lock contains an unapproved source"); +} + +const sourceLock = readFileSync(join(root, "radroots.lib.source-lock.v1.toml"), "utf8"); +if (!/^repository = "https:\/\/github\.com\/radrootslabs\/lib"$/m.test(sourceLock)) { + fail("Lib repository identity drifted"); +} +if (!/^revision = "[0-9a-f]{40}"$/m.test(sourceLock)) fail("Lib revision is not immutable"); +if (!/^lockfile_sha256 = "[0-9a-f]{64}"$/m.test(sourceLock)) fail("Cargo lock digest is absent"); + +const packages = packageDirectories(); +if ( + packages.length !== expectedPackages.length || + packages.some((path, index) => basename(path) !== expectedPackages[index]) +) { + fail("package inventory drifted"); +} +for (const path of packages) verifyManifest(path); + +console.log(`supply-chain ok: ${packages.length} packages`);