Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
661 changes: 661 additions & 0 deletions packages/loopover-miner/LICENSE

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion scripts/check-engine-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { FORBIDDEN_CONTENT } from "./forbidden-content";
// editing on every such PR and would silently rot. Pattern-match the dist/ shape itself instead; the
// forbidden-path/forbidden-content/stale-text checks below still catch anything that doesn't belong.
const ALLOWED = [/^dist\/.*\.(js|d\.ts)$/, /^package\.json$/, /^README\.md$/, /^CHANGELOG\.md$/, /^LICENSE$/];
const REQUIRED = ["package.json", "README.md", "CHANGELOG.md", "dist/index.js", "dist/index.d.ts"];
const REQUIRED = ["package.json", "README.md", "CHANGELOG.md", "dist/index.js", "dist/index.d.ts", "LICENSE"];
// #9786: LICENSE was allowed but never required here, which is how @loopover/miner shipped AGPL with no
// license text and nothing caught it. Asserted so the same omission cannot recur in this package.
const FORBIDDEN_PATH = /(^|\/)(\.dev\.vars|\.env|\.npmrc|.*\.pem|.*private.*key.*|.*secret.*)$/i;
const STALE_PACKAGE_TEXT = /(private beta|zeronode\.workers\.dev|preview URL)/i;

Expand Down
10 changes: 10 additions & 0 deletions scripts/check-mcp-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import { FORBIDDEN_CONTENT } from "./forbidden-content";
import { MCP_PACKAGE_ALLOWED_FILE_PATTERNS } from "./mcp-package-allowlist";

const FORBIDDEN_PATH = /(^|\/)(\.dev\.vars|\.env|\.npmrc|.*\.pem|.*private.*key.*|.*secret.*)$/i;
// #9786: this checker validated only that nothing UNEXPECTED ships -- it had no notion of a file that MUST.
// @loopover/miner shipped AGPL-3.0-only with no LICENSE and nothing caught it, because every published
// package's checker allowed the file without ever asserting it. LICENSE is the entry that matters: its
// absence from a copyleft package is a licensing defect, not a packaging one. package.json is asserted
// alongside it because a pack result missing it is not a package at all, and would otherwise let a
// pathologically empty file list pass every check above by vacuous truth.
const REQUIRED = ["package.json", "LICENSE"];
const STALE_PACKAGE_TEXT = /(private beta|zeronode\.workers\.dev|preview URL)/i;

type PackedFile = string | { path: string };
Expand All @@ -21,6 +28,9 @@ export function validateMcpPackFileList(files: readonly PackedFile[], readConten
if (FORBIDDEN_CONTENT.test(content)) throw new Error(`Secret-like content found in MCP package file: ${file}`);
if (file === "README.md" && STALE_PACKAGE_TEXT.test(content)) throw new Error(`Stale public-package wording found in MCP package file: ${file}`);
}
for (const required of REQUIRED) {
if (!paths.includes(required)) throw new Error(`Missing required file in MCP package: ${required}`);
}
return paths;
}

Expand Down
6 changes: 6 additions & 0 deletions scripts/check-miner-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ALLOWED = [
/^dist\/package\.json$/,
/^package\.json$/,
/^README\.md$/,
/^LICENSE$/,
/^expected-engine\.version$/,
// Operational material shipped for `npm install -g` users so the quickstart doesn't require a repo visit (#4874):
/^DEPLOYMENT\.md$/,
Expand All @@ -35,6 +36,11 @@ const REQUIRED = [
"DEPLOYMENT.md",
"Dockerfile",
"schema/miner-goal-spec.schema.json",
// #9786: this package declares AGPL-3.0-only and shipped no LICENSE at all. It could not have: LICENSE was
// absent from ALLOWED above, so adding the file would have failed this very check. Required, not merely
// allowed, for the same reason DEPLOYMENT.md and Dockerfile are -- a license that can silently drop out of
// a copyleft package is the one file whose absence is a licensing problem, not a packaging one.
"LICENSE",
];
// Exact-name dotfiles that are inherently credential-shaped regardless of extension.
const FORBIDDEN_DOTFILE = /(^|\/)(\.dev\.vars|\.env|\.npmrc)$/i;
Expand Down
4 changes: 3 additions & 1 deletion scripts/check-ui-kit-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { FORBIDDEN_CONTENT } from "./forbidden-content";
// output shape, plus .d.ts.map declaration sourcemaps), and grows with every new component -- pattern-match
// the shape instead of enumerating each component file.
const ALLOWED = [/^dist\/.*\.(js|d\.ts|d\.ts\.map)$/, /^src\/theme\.css$/, /^package\.json$/, /^README\.md$/, /^CHANGELOG\.md$/, /^LICENSE$/];
const REQUIRED = ["package.json", "README.md", "CHANGELOG.md", "src/theme.css", "dist/utils.js", "dist/utils.d.ts"];
const REQUIRED = ["package.json", "README.md", "CHANGELOG.md", "src/theme.css", "dist/utils.js", "dist/utils.d.ts", "LICENSE"];
// #9786: LICENSE was allowed but never required here, which is how @loopover/miner shipped AGPL with no
// license text and nothing caught it. Asserted so the same omission cannot recur in this package.
const FORBIDDEN_PATH = /(^|\/)(\.dev\.vars|\.env|\.npmrc|.*\.pem|.*private.*key.*|.*secret.*)$/i;
const STALE_PACKAGE_TEXT = /(private beta|zeronode\.workers\.dev|preview URL)/i;

Expand Down
9 changes: 9 additions & 0 deletions test/unit/check-engine-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ describe("check-engine-package script", () => {
expect(result.out).toMatch(/^Engine package dry-run ok: 8 files\.\n$/);
});

it("REGRESSION (#9786): rejects a package shipping no LICENSE", () => {
// Every checker ALLOWED this file and none asserted it, which is how @loopover/miner shipped
// AGPL-3.0-only with no license text at all. The absence of a license from a copyleft package is a
// licensing defect, not a packaging one, so it fails the pack check like any other missing artifact.
const result = runChecker({ CHECK_ENGINE_PACK_TEST_FILES: JSON.stringify(["package.json", "README.md", "CHANGELOG.md", "dist/index.js", "dist/index.d.ts"]) });
expect(result.status).toBe(1);
expect(result.out).toContain("Engine package is missing required file: LICENSE");
});

it("rejects a forbidden path", () => {
const result = runChecker({ CHECK_ENGINE_PACK_TEST_FILES: JSON.stringify([".env"]) });
expect(result.status).toBe(1);
Expand Down
18 changes: 14 additions & 4 deletions test/unit/check-mcp-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function runChecker(env: Record<string, string | undefined> = {}): { status: num
// A complete, valid MCP tarball: a bin, shipped lib modules, the preview scripts, and the package metadata files.
const FULL_PACKAGE = [
"package.json",
"LICENSE",
"README.md",
"CHANGELOG.md",
"LICENSE",
Expand Down Expand Up @@ -52,6 +53,15 @@ describe("check-mcp-package script", () => {
expect(result.out).toContain("scripts/gittensor-score-preview.mjs");
});

it("REGRESSION (#9786): rejects a package shipping no LICENSE", () => {
// Every checker ALLOWED this file and none asserted it, which is how @loopover/miner shipped
// AGPL-3.0-only with no license text at all. The absence of a license from a copyleft package is a
// licensing defect, not a packaging one, so it fails the pack check like any other missing artifact.
const result = runChecker({ CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "dist/bin/loopover-mcp.js"]) });
expect(result.status).toBe(1);
expect(result.out).toContain("Missing required file in MCP package: LICENSE");
});

it("rejects a forbidden path", () => {
const result = runChecker({ CHECK_MCP_PACK_TEST_FILES: JSON.stringify([".env"]) });
expect(result.status).toBe(1);
Expand All @@ -66,7 +76,7 @@ describe("check-mcp-package script", () => {

it("rejects an unexpected bin that matches the package name prefix", () => {
const result = runChecker({
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "dist/bin/loopover-mcp-backdoor.js"]),
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "LICENSE", "dist/bin/loopover-mcp-backdoor.js"]),
CHECK_MCP_PACK_TEST_CONTENT: "console.log('not secret');",
});
expect(result.status).toBe(1);
Expand All @@ -76,7 +86,7 @@ describe("check-mcp-package script", () => {
it("rejects secret-like content", () => {
const probe = ["PROBE", "_", "SECRET", "=", "value"].join("");
const result = runChecker({
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "dist/bin/loopover-mcp.js"]),
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "LICENSE", "dist/bin/loopover-mcp.js"]),
CHECK_MCP_PACK_TEST_CONTENT: probe,
});
expect(result.status).toBe(1);
Expand All @@ -85,7 +95,7 @@ describe("check-mcp-package script", () => {

it("rejects stale public-package wording in README.md", () => {
const result = runChecker({
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "README.md"]),
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "LICENSE", "README.md"]),
CHECK_MCP_PACK_TEST_CONTENT: "Join the private beta today!",
});
expect(result.status).toBe(1);
Expand All @@ -95,7 +105,7 @@ describe("check-mcp-package script", () => {
it("only scopes the stale-wording check to README.md, not other allowlisted files", () => {
// The same stale phrase in a non-README file (here CHANGELOG.md) is accepted — the guard is README-only.
const result = runChecker({
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "CHANGELOG.md"]),
CHECK_MCP_PACK_TEST_FILES: JSON.stringify(["package.json", "LICENSE", "CHANGELOG.md"]),
CHECK_MCP_PACK_TEST_CONTENT: "Historic note: was once a private beta.",
});
expect(result.status).toBe(0);
Expand Down
19 changes: 19 additions & 0 deletions test/unit/check-miner-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ describe("check-miner-package script", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"LICENSE",
"dist/bin/loopover-miner.js",
"dist/lib/secret-helper.js",
"dist/lib/secret-helper.d.ts",
Expand Down Expand Up @@ -79,6 +81,7 @@ describe("check-miner-package script", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"README.md",
"DEPLOYMENT.md",
Expand All @@ -103,6 +106,7 @@ describe("check-miner-package script", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"dist/bin/loopover-miner-backdoor.js",
"dist/lib/cli.js",
Expand All @@ -117,6 +121,7 @@ describe("check-miner-package script", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"dist/lib/cli.js",
"dist/lib/calibration/index.js",
Expand All @@ -130,6 +135,7 @@ describe("check-miner-package script", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"dist/lib/cli.js",
"dist/lib/calibration/nested/index.js",
Expand All @@ -152,6 +158,7 @@ describe("check-miner-package script", () => {
// Every REQUIRED file present so the check reaches (and fails on) the lib-artifacts guard specifically.
CHECK_MINER_PACK_TEST_FILES: JSON.stringify([
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"DEPLOYMENT.md",
"Dockerfile",
Expand All @@ -178,6 +185,7 @@ describe("check-miner-package script", () => {
// and the schema — is accepted.
const FULL_PACKAGE = [
"package.json",
"LICENSE",
"dist/bin/loopover-miner.js",
"dist/lib/cli.js",
"DEPLOYMENT.md",
Expand Down Expand Up @@ -207,6 +215,17 @@ describe("check-miner-package script", () => {
expect(result.out).toContain("Miner package is missing required file: DEPLOYMENT.md");
});

it("REGRESSION (#9786): requires LICENSE — this package shipped AGPL-3.0-only without one", () => {
// It could not have been added before: LICENSE was absent from the ALLOWED list too, so the file
// would have failed this very check as an unexpected artifact.
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify(FULL_PACKAGE.filter((f) => f !== "LICENSE")),
CHECK_MINER_PACK_TEST_CONTENT: "ok",
});
expect(result.status).toBe(1);
expect(result.out).toContain("Miner package is missing required file: LICENSE");
});

it("requires at least one docs/*.md file to be published", () => {
const result = runChecker({
CHECK_MINER_PACK_TEST_FILES: JSON.stringify(FULL_PACKAGE.filter((f) => !f.startsWith("docs/"))),
Expand Down
11 changes: 10 additions & 1 deletion test/unit/check-ui-kit-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ describe("check-ui-kit-package script", () => {
expect(result.out).toMatch(/^ui-kit package dry-run ok: 12 files\.\n$/);
});

it("REGRESSION (#9786): rejects a package shipping no LICENSE", () => {
// Every checker ALLOWED this file and none asserted it, which is how @loopover/miner shipped
// AGPL-3.0-only with no license text at all. The absence of a license from a copyleft package is a
// licensing defect, not a packaging one, so it fails the pack check like any other missing artifact.
const result = runChecker({ CHECK_UI_KIT_PACK_TEST_FILES: JSON.stringify(["package.json", "README.md", "CHANGELOG.md", "src/theme.css", "dist/utils.js", "dist/utils.d.ts", "dist/components/button.js", "dist/components/button.d.ts"]) });
expect(result.status).toBe(1);
expect(result.out).toContain("ui-kit package is missing required file: LICENSE");
});

it("rejects a forbidden path", () => {
const result = runChecker({ CHECK_UI_KIT_PACK_TEST_FILES: JSON.stringify([".env"]) });
expect(result.status).toBe(1);
Expand Down Expand Up @@ -67,7 +76,7 @@ describe("check-ui-kit-package script", () => {

it("rejects a package with no dist/components/*.js artifacts at all", () => {
const result = runChecker({
CHECK_UI_KIT_PACK_TEST_FILES: JSON.stringify(["package.json", "README.md", "CHANGELOG.md", "src/theme.css", "dist/utils.js", "dist/utils.d.ts"]),
CHECK_UI_KIT_PACK_TEST_FILES: JSON.stringify(["package.json", "README.md", "CHANGELOG.md", "LICENSE", "src/theme.css", "dist/utils.js", "dist/utils.d.ts"]),
CHECK_UI_KIT_PACK_TEST_CONTENT: "public docs, nothing secret",
});
expect(result.status).toBe(1);
Expand Down
8 changes: 6 additions & 2 deletions test/unit/forbidden-content.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ const PACKAGE_CHECKERS = ["scripts/check-miner-package.ts", "scripts/check-mcp-p

// A minimal file list that passes each checker's path/allowlist/required-file guards, so the run reaches the
// shared secret-content read. Mirrors the file lists each checker's own "rejects secret-like content" test uses.
// LICENSE is in both lists because both checkers now REQUIRE it (#9787): a published package that declares
// a license in package.json but ships no LICENSE file is the drift that change exists to catch. Without it
// the MCP checker exits on "Missing required file" before it ever reads content, and this file's clean-content
// case would be asserting the required-file guard rather than the shared detector.
const REACHABLE_FILES: Record<string, string[]> = {
"scripts/check-miner-package.ts": ["package.json", "dist/bin/loopover-miner.js", "dist/lib/cli.js"],
"scripts/check-mcp-package.ts": ["package.json", "dist/bin/loopover-mcp.js"],
"scripts/check-miner-package.ts": ["package.json", "LICENSE", "dist/bin/loopover-miner.js", "dist/lib/cli.js"],
"scripts/check-mcp-package.ts": ["package.json", "LICENSE", "dist/bin/loopover-mcp.js"],
};

// Assembled from fragments so this file never itself contains a credential-shaped literal -- the same
Expand Down