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 path from "node:path";
|
||||
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", () => {
|
||||
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");
|
||||
});
|
||||
|
||||
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", () => {
|
||||
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 {
|
||||
const rows: Record<PermissionMode, Omit<PermissionPostureReceipt, "schema" | "createdAt" | "mode" | "deployAttempted">> = {
|
||||
"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 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 { createFactoryMemoryQuarantineReceipt, createStaleMemoryQuarantineReceipt, writeStaleMemoryQuarantineReceipt } from "./stale-memory-quarantine.js";
|
||||
|
|
|
|||
Loading…
Reference in New Issue