diff --git a/docs/native-publisher.md b/docs/native-publisher.md index b7c2c52c..174b9a88 100644 --- a/docs/native-publisher.md +++ b/docs/native-publisher.md @@ -71,18 +71,18 @@ and UI peers. No unknown executable or symlink is ignored. The unchanged legacy7 alias has its own frozen original SHA/SRI and ALL-member gate; it is NOT authenticated staging trust. Its package/file/pin remain unchanged. -**Co064253 installer policy:** the initial genuine RED refused the SDK's generated -`node_modules/.bin/yaml`. Reader now independently verifies its OWN pinned AND -actual PNPM10.7.0 POSIX templates, not Writer's different tool version. Original -SDK896/UI81/protocol67 files still ALL match. The SDK and direct protocol each -have one separately counted, regular executable YAML shim; BOTH exact program, -NODE_PATH branches and targets must match. All 233 original bundled YAML files -match; the direct protocol's external YAML copy additionally matches EVERY one of -those original files, with exact version/location/target resolution. Any changed -original, unknown extra, changed shim, symlink or other manager/template refuses. -No blanket `.bin` ignore, deletion or shim execution occurs. Installer evidence -records original counts and total installed counts separately, is immutable- -artifact digest-bound, and is NOT SDK authentication or product qualification. +**Co100025 supersedes the exact generated-program classifier:** pnpm generates +`node_modules/.bin/yaml`; its wrapper bytes are not SDK authority and are no +longer compared to a shell template. Frozen-lockfile installation, pinned/actual +PNPM10.7.0 and ALL original SDK896/UI81/protocol67 bytes remain checked. Only the +sole known regular executable wrapper at that location is counted separately in +SDK/direct-protocol installations; no arbitrary extra member or symlink is ignored. +All233 original bundled YAML files and EVERY external protocol YAML file still +match, with original version/location/bin binding. No wrapper is executed or +removed. Existing installer evidence remains artifact-bound, not authentication. +Run39398579665/a1 at879 failed on the obsolete protocol-wrapper template check; +that genuine RED is preserved, not relabeled as success. No diagnostic capture +or alternate template is needed for this explicit tooling-policy remedy. Production has no accepted target archive/packet. It refuses; staging is never retargeted to production or LAB. Old vendor archives/dead legacy files remain. @@ -200,7 +200,7 @@ records transport-file SHA, SPKI SHA and public ID separately from Git source. Local plans explicitly carry `qualificationOnly: true`, null Git SHA/tree and no publication authority; CI plans come only from the exact-clean-source guard. The compiled target/native/SQLite/origin checks run only AFTER ALL original and -separate exact installer-output gates. +separate known-wrapper/original-YAML checks. The unchanged UI companion still says `label: "dev intake, not release-qualified"` and `releaseQualified: false`; those historical fields are not a live refusal condition. The current authorized Reader UIb2 source-lock component and protected diff --git a/scripts/lib/native-originals.mjs b/scripts/lib/native-originals.mjs index 0f9884e6..daad7c20 100644 --- a/scripts/lib/native-originals.mjs +++ b/scripts/lib/native-originals.mjs @@ -140,8 +140,8 @@ export async function assertInstalledOriginals( return; } // ALL original SDK files (including every YAML file) still have to match. - // This is the separate, independently verified installer-output class that - // Co064253 permits, NOT ignoring any extra executable/member. + // Co100025: the sole known pnpm-generated wrapper is not an SDK original; + // its program bytes are not classified. Other extra members still refuse. equal( actual.filter((m) => paths.has(m.path)), members, @@ -664,7 +664,7 @@ export async function loadOriginals({ manager: "pnpm@10.7.0", file: pnpmYamlShim, template: - "Reader exact pinned POSIX YAML shim; separate from SDK originals; all original YAML files still required", + "pnpm-generated wrapper bytes are not SDK authority; all original YAML files still required", originalYamlMembers: members.filter((m) => m.path.startsWith("node_modules/yaml/")).length, }, release, diff --git a/scripts/lib/reader-pnpm-installer.mjs b/scripts/lib/reader-pnpm-installer.mjs index e39139f2..c01681e4 100644 --- a/scripts/lib/reader-pnpm-installer.mjs +++ b/scripts/lib/reader-pnpm-installer.mjs @@ -1,6 +1,6 @@ -// Reader-owned PNPM10.7.0 installer-output policy, NOT an SDK-original exception. -// ALL original package/YAML files are compared independently BEFORE qualifying -// these exact generated files. No blanket .bin ignore, deletion or execution. +// Co100025: pnpm-generated wrappers are tooling, NOT SDK-original authority. +// ALL original package/YAML files still match independently. Only the known +// wrapper location is separate; no blanket .bin ignore, deletion or execution. import { execFileSync } from "node:child_process"; import { createHash } from "node:crypto"; import { join, relative, resolve } from "node:path"; @@ -47,55 +47,6 @@ function canonicalRoot(repoRoot, packageRoot, name) { "unexpected PNPM installed package root", ); } -function render(paths, target) { - return Buffer.from( - [ - "#!/bin/sh", - String.raw`basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")`, - "", - "case `uname` in", - ' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;', - "esac", - "", - 'if [ -z "$NODE_PATH" ]; then', - ` export NODE_PATH="${paths.join(":")}"`, - "else", - ` export NODE_PATH="${paths.join(":")}:$NODE_PATH"`, - "fi", - 'if [ -x "$basedir/node" ]; then', - ` exec "$basedir/node" "$basedir/${target}" "$@"`, - "else", - ` exec node "$basedir/${target}" "$@"`, - "fi", - "", - ].join("\n"), - ); -} -export function pnpm107YamlTemplate(repoRoot, sdkRoot) { - canonicalRoot(repoRoot, sdkRoot, "@mdbase-dev/sdk"); - return render( - [ - join(sdkRoot, "node_modules/yaml/node_modules"), - join(sdkRoot, "node_modules"), - join(sdkRoot, "../node_modules"), - resolve(sdkRoot, "../.."), - join(repoRoot, "node_modules/.pnpm/node_modules"), - ], - "../yaml/bin.mjs", - ); -} -export function pnpm107ProtocolYamlTemplate(repoRoot, protocolRoot, yamlRoot) { - canonicalRoot(repoRoot, protocolRoot, "@mdbase-dev/connect-protocol"); - canonicalRoot(repoRoot, yamlRoot, "yaml"); - return render( - [ - join(yamlRoot, "node_modules"), - resolve(yamlRoot, ".."), - join(repoRoot, "node_modules/.pnpm/node_modules"), - ], - "../../../../yaml/bin.mjs", - ); -} function originalYaml(yamlPackageBytes, originalMembers) { const yaml = originalMembers.filter((m) => m.path.startsWith("node_modules/yaml/")); const pkg = yaml.find((m) => m.path === "node_modules/yaml/package.json"); @@ -121,11 +72,11 @@ function evidence(bytes, count) { bytes: bytes.length, sha256: hash(bytes), manager: "pnpm@10.7.0", - policy: "exact POSIX template + separately verified ALL original package/YAML members", + policy: "pnpm-generated wrapper; separately verified ALL original package/YAML members", originalYamlMembers: count, targetOriginal: "node_modules/yaml/bin.mjs", disposition: - "retained as independently verified installer output; never counted as package original or executed", + "retained as pnpm-generated tooling; never counted as package original, SDK authority or executed", }; } export function verifyReaderYamlShim({ @@ -138,11 +89,7 @@ export function verifyReaderYamlShim({ }) { check(managerVersion === "10.7.0", "unqualified installer version"); const { yaml } = originalYaml(yamlPackageBytes, originalMembers); - const expected = pnpm107YamlTemplate(repoRoot, sdkRoot); - check( - bytes.length === expected.length && bytes.equals(expected), - "generated SDK YAML shim differs from exact pinned PNPM template", - ); + canonicalRoot(repoRoot, sdkRoot, "@mdbase-dev/sdk"); return evidence(bytes, yaml.length); } export function verifyReaderProtocolYamlShim({ @@ -160,10 +107,7 @@ export function verifyReaderProtocolYamlShim({ yamlRoot === join(repoRoot, `node_modules/.pnpm/yaml@${manifest.version}/node_modules/yaml`), "direct protocol YAML location/version differs from original SDK YAML", ); - const expected = pnpm107ProtocolYamlTemplate(repoRoot, protocolRoot, yamlRoot); - check( - bytes.length === expected.length && bytes.equals(expected), - "generated protocol YAML shim differs from exact pinned PNPM template", - ); + canonicalRoot(repoRoot, protocolRoot, "@mdbase-dev/connect-protocol"); + canonicalRoot(repoRoot, yamlRoot, "yaml"); return evidence(bytes, yaml.length); } diff --git a/scripts/tests/reader-installer.test.mjs b/scripts/tests/reader-installer.test.mjs index 2642d912..186e01b3 100644 --- a/scripts/tests/reader-installer.test.mjs +++ b/scripts/tests/reader-installer.test.mjs @@ -5,12 +5,7 @@ import { mkdtemp, mkdir, writeFile, readFile, chmod, rm, symlink, lstat } from " import { join } from "node:path"; import { tmpdir } from "node:os"; import { assertInstalledOriginals } from "../lib/native-originals.mjs"; -import { - pnpm107YamlTemplate, - verifyReaderYamlShim, - pnpmYamlShim, - pnpm107ProtocolYamlTemplate, -} from "../lib/reader-pnpm-installer.mjs"; +import { verifyReaderYamlShim, pnpmYamlShim } from "../lib/reader-pnpm-installer.mjs"; const hash = (b) => createHash("sha256").update(b).digest("hex"); async function fixture() { const repo = await mkdtemp(join(tmpdir(), "reader-pnpm-policy-")); @@ -33,7 +28,9 @@ async function fixture() { } members.sort((a, b) => (a.path < b.path ? -1 : 1)); await mkdir(join(sdk, "node_modules/.bin")); - const bytes = pnpm107YamlTemplate(repo, sdk); + const bytes = Buffer.from( + "#!/bin/sh\n# pnpm-generated SDK wrapper fixture DATA, never executed\n", + ); await writeFile(join(sdk, pnpmYamlShim), bytes); await chmod(join(sdk, pnpmYamlShim), 0o755); const options = { @@ -63,7 +60,9 @@ async function protocolFixture(f) { }); await writeFile(join(protocol, "package.json"), pkg); const members = [{ path: "package.json", bytes: Buffer.byteLength(pkg), sha256: hash(pkg) }]; - const bytes = pnpm107ProtocolYamlTemplate(f.repo, protocol, yaml); + const bytes = Buffer.from( + "#!/bin/sh\n# pnpm-generated protocol wrapper fixture DATA, never executed\n", + ); await writeFile(join(protocol, pnpmYamlShim), bytes); await chmod(join(protocol, pnpmYamlShim), 0o755); return { @@ -80,7 +79,28 @@ async function protocolFixture(f) { }, }; } -test("direct protocol exact PNPM shim additionally binds EVERY external YAML file to original SDK YAML", async () => { +for (const kind of ["sdk", "protocol"]) + test(`Co100025: differing pnpm-generated ${kind} wrapper bytes do not reject unchanged originals`, async () => { + const f = await fixture(); + try { + const p = + kind === "protocol" + ? await protocolFixture(f) + : { protocol: f.sdk, members: f.members, options: f.options }; + const bytes = Buffer.from("#!/bin/sh\n# different pnpm wrapper DATA; never executed\n"); + await writeFile(join(p.protocol, pnpmYamlShim), bytes); + await assertInstalledOriginals( + p.protocol, + p.members, + "originals must still match", + p.options, + ); + assert.deepEqual(await readFile(join(p.protocol, pnpmYamlShim)), bytes); + } finally { + await rm(f.repo, { recursive: true, force: true }); + } + }); +test("direct protocol installation binds EVERY external YAML file to original SDK YAML", async () => { const f = await fixture(); try { const p = await protocolFixture(f); @@ -101,7 +121,6 @@ for (const mutation of [ "external-YAML-extra", "external-YAML-link", "protocol-byte", - "protocol-shim-target", "protocol-extra-bin", ]) test("protocol installer policy refuses " + mutation, async () => { @@ -117,11 +136,6 @@ for (const mutation of [ await symlink("dist/index.js", join(p.yaml, "bin.mjs")); } if (mutation === "protocol-byte") await writeFile(join(p.protocol, "package.json"), "{}"); - if (mutation === "protocol-shim-target") - await writeFile( - join(p.protocol, pnpmYamlShim), - p.bytes.toString().replace("../../../../yaml/bin.mjs", "../evil.js"), - ); if (mutation === "protocol-extra-bin") await writeFile(join(p.protocol, "node_modules/.bin/other"), "extra"); await assert.rejects( @@ -133,7 +147,7 @@ for (const mutation of [ await rm(f.repo, { recursive: true, force: true }); } }); -test("ALL original SDK/YAML members + sole exact PNPM10.7 shim verified separately, no deletion", async () => { +test("ALL original SDK/YAML members + sole known pnpm wrapper retained separately, no deletion", async () => { const f = await fixture(); try { await assertInstalledOriginals(f.sdk, f.members, "fixture originals", f.options); @@ -152,8 +166,6 @@ test("ALL original SDK/YAML members + sole exact PNPM10.7 shim verified separate for (const mutation of [ "SDK-byte", "YAML-byte", - "shim-extra-command", - "shim-target", "unknown-bin", "unknown-hidden", "symlink", @@ -169,16 +181,6 @@ for (const mutation of [ await writeFile(join(f.sdk, "dist/index.js"), "altered SDK DATA"); if (mutation === "YAML-byte") await writeFile(join(f.sdk, "node_modules/yaml/dist/index.js"), "altered YAML DATA"); - if (mutation === "shim-extra-command") - await writeFile( - join(f.sdk, pnpmYamlShim), - Buffer.concat([f.bytes, Buffer.from("echo extra\n")]), - ); - if (mutation === "shim-target") - await writeFile( - join(f.sdk, pnpmYamlShim), - f.bytes.toString().replace("../yaml/bin.mjs", "../evil.js"), - ); if (mutation === "unknown-bin") await writeFile(join(f.sdk, "node_modules/.bin/other"), "unknown"); if (mutation === "unknown-hidden") await writeFile(join(f.sdk, ".hidden-extra"), "unknown"); @@ -198,7 +200,7 @@ for (const mutation of [ } }, ); -test("known template is NOT granted to another PNPM version or another root/target", async () => { +test("original YAML binding, installed roots and pinned manager checks remain", async () => { const f = await fixture(); try { const args = { @@ -217,14 +219,10 @@ test("known template is NOT granted to another PNPM version or another root/targ originalMembers: f.members.filter((m) => m.path !== "node_modules/yaml/bin.mjs"), }), ); + assert.throws(() => verifyReaderYamlShim({ ...args, repoRoot: "/tmp/unsafe;root" })); assert.throws(() => - verifyReaderYamlShim({ - ...args, - bytes: Buffer.from(f.bytes.toString().replace("$NODE_PATH", "OTHER")), - }), + verifyReaderYamlShim({ ...args, sdkRoot: "/elsewhere/node_modules/@mdbase-dev/sdk" }), ); - assert.throws(() => pnpm107YamlTemplate("/tmp/unsafe;root", f.sdk)); - assert.throws(() => pnpm107YamlTemplate(f.repo, "/elsewhere/node_modules/@mdbase-dev/sdk")); } finally { await rm(f.repo, { recursive: true, force: true }); } diff --git a/scripts/tests/reader-publisher.test.mjs b/scripts/tests/reader-publisher.test.mjs index 68a565e7..32ba00bc 100644 --- a/scripts/tests/reader-publisher.test.mjs +++ b/scripts/tests/reader-publisher.test.mjs @@ -70,7 +70,7 @@ test("last current HEAD rejects moved branch even if source remains ancestor", a ]) await assert.rejects(assertCurrentHead(env, async () => Response.json(value))); }); -test("ALL current eaa4 installed SDK/UI/protocol/peers: originals plus separately exact installer output", async () => { +test("ALL current eaa4 installed SDK/UI/protocol/peers: originals plus separately counted pnpm wrapper", async () => { const installerEvidence = []; const trust = await loadOriginals({ target: "staging",