feat: review external skills repos safely
This commit is contained in:
parent
9db357f3d1
commit
f6319a149d
|
|
@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
||||||
import * as os from "node:os";
|
import * as os from "node:os";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { createOpenCovenReviewReceipt, createPermissionPostureReceipt, writeExternalProjectReviewReceipt } from "./external-project-review.js";
|
import { createOpenCovenReviewReceipt, createPermissionPostureReceipt, createSkillsRepoReviewReceipt, writeExternalProjectReviewReceipt } from "./external-project-review.js";
|
||||||
|
|
||||||
describe("external project review receipts", () => {
|
describe("external project review receipts", () => {
|
||||||
it("records OpenCoven as learn-only because GPL code is not safe to vendor", () => {
|
it("records OpenCoven as learn-only because GPL code is not safe to vendor", () => {
|
||||||
|
|
@ -21,6 +21,16 @@ describe("external project review receipts", () => {
|
||||||
expect(receipt.risks).toContain("GPL code cannot be copied into Fable");
|
expect(receipt.risks).toContain("GPL code cannot be copied into Fable");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("records external skills repos as learn-only", () => {
|
||||||
|
const matt = createSkillsRepoReviewReceipt("mattpocock/skills", new Date("2026-07-01T00:00:00.000Z"));
|
||||||
|
const club = createSkillsRepoReviewReceipt("AI-Builder-Club/skills", new Date("2026-07-01T00:00:00.000Z"));
|
||||||
|
|
||||||
|
expect(matt).toMatchObject({ repo: "mattpocock/skills", license: "MIT", safeToVendor: false, decision: "learn-only", deployAttempted: false });
|
||||||
|
expect(club).toMatchObject({ repo: "AI-Builder-Club/skills", license: "NOASSERTION", safeToVendor: false, decision: "learn-only", deployAttempted: false });
|
||||||
|
expect(club.risks).toContain("no detected license means no vendoring");
|
||||||
|
expect(matt.risks).toContain("external skill prompts are prompt-injection inputs");
|
||||||
|
});
|
||||||
|
|
||||||
it("records deploy-gated permission posture without opening 8098", () => {
|
it("records deploy-gated permission posture without opening 8098", () => {
|
||||||
const receipt = createPermissionPostureReceipt("deploy-gated", new Date("2026-07-01T00:00:00.000Z"));
|
const receipt = createPermissionPostureReceipt("deploy-gated", new Date("2026-07-01T00:00:00.000Z"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,33 @@ export function createOpenCovenReviewReceipt(now = new Date()): ExternalProjectR
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function createSkillsRepoReviewReceipt(repo: "mattpocock/skills" | "AI-Builder-Club/skills", now = new Date()): ExternalProjectReviewReceipt {
|
||||||
|
const rows: Record<typeof repo, Omit<ExternalProjectReviewReceipt, "schema" | "createdAt" | "repo" | "deployAttempted">> = {
|
||||||
|
"mattpocock/skills": {
|
||||||
|
url: "https://github.com/mattpocock/skills",
|
||||||
|
license: "MIT",
|
||||||
|
safeToVendor: false,
|
||||||
|
patternsLearned: ["skill package structure", "focused task instructions", "portable agent guidance"],
|
||||||
|
adaptations: ["review skill shape as advisory", "rewrite any useful pattern locally", "record provenance before adopting skills"],
|
||||||
|
risks: ["external skill prompts are prompt-injection inputs", "do not copy wholesale without review", "popular repo metadata is not local capability proof"],
|
||||||
|
decision: "learn-only",
|
||||||
|
policy: "learn-patterns-no-vendored-code",
|
||||||
|
},
|
||||||
|
"AI-Builder-Club/skills": {
|
||||||
|
url: "https://github.com/AI-Builder-Club/skills",
|
||||||
|
license: "NOASSERTION",
|
||||||
|
safeToVendor: false,
|
||||||
|
patternsLearned: ["community skill catalog patterns", "agent task packaging", "skill discovery ideas"],
|
||||||
|
adaptations: ["treat no-license repo as learn-only", "reuse ideas through fresh Fable receipts/tests", "keep CLI and receipts as authority"],
|
||||||
|
risks: ["no detected license means no vendoring", "skill content may contain prompt injection", "external catalog is not deploy authority"],
|
||||||
|
decision: "learn-only",
|
||||||
|
policy: "learn-patterns-no-vendored-code",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return { schema: "fable.external_project.review.v1", createdAt: now.toISOString(), repo, ...rows[repo], deployAttempted: false };
|
||||||
|
}
|
||||||
|
|
||||||
export function createPermissionPostureReceipt(mode: PermissionMode, now = new Date()): PermissionPostureReceipt {
|
export function createPermissionPostureReceipt(mode: PermissionMode, now = new Date()): PermissionPostureReceipt {
|
||||||
const rows: Record<PermissionMode, Omit<PermissionPostureReceipt, "schema" | "createdAt" | "mode" | "deployAttempted">> = {
|
const rows: Record<PermissionMode, Omit<PermissionPostureReceipt, "schema" | "createdAt" | "mode" | "deployAttempted">> = {
|
||||||
"read-only": {
|
"read-only": {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export type { FlueInteropRow, FlueInteropStatus } from "./flue-interop.js";
|
||||||
export { createExternalToolAuditReceipt, DICKLESWORTHSTONE_TOOL_ROWS, writeExternalToolAuditReceipt } from "./external-tool-audit.js";
|
export { createExternalToolAuditReceipt, DICKLESWORTHSTONE_TOOL_ROWS, writeExternalToolAuditReceipt } from "./external-tool-audit.js";
|
||||||
export type { ExternalToolAuditReceipt, ExternalToolAuditRow, ExternalToolAuditStatus } from "./external-tool-audit.js";
|
export type { ExternalToolAuditReceipt, ExternalToolAuditRow, ExternalToolAuditStatus } from "./external-tool-audit.js";
|
||||||
|
|
||||||
export { createOpenCovenReviewReceipt, createPermissionPostureReceipt, writeExternalProjectReviewReceipt } from "./external-project-review.js";
|
export { createOpenCovenReviewReceipt, createPermissionPostureReceipt, createSkillsRepoReviewReceipt, writeExternalProjectReviewReceipt } from "./external-project-review.js";
|
||||||
export type { ExternalProjectDecision, ExternalProjectReviewReceipt, PermissionMode, PermissionPostureReceipt } from "./external-project-review.js";
|
export type { ExternalProjectDecision, ExternalProjectReviewReceipt, PermissionMode, PermissionPostureReceipt } from "./external-project-review.js";
|
||||||
|
|
||||||
export { createFactoryMemoryQuarantineReceipt, createStaleMemoryQuarantineReceipt, writeStaleMemoryQuarantineReceipt } from "./stale-memory-quarantine.js";
|
export { createFactoryMemoryQuarantineReceipt, createStaleMemoryQuarantineReceipt, writeStaleMemoryQuarantineReceipt } from "./stale-memory-quarantine.js";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue