Add referenced last30days catalog entry

This commit is contained in:
Dotta
2026-06-04 20:01:25 +00:00
parent 1227bb8ead
commit bee2b25f5d
17 changed files with 1276 additions and 49 deletions
@@ -223,6 +223,47 @@ describeEmbeddedPostgres("companySkillService.installFromCatalog", () => {
});
});
it("installs script-bearing catalog skills when materialized bytes pass the static audit", async () => {
const script = "print('safe')\n";
const scriptFiles: CatalogSkillFile[] = [
...sampleFiles,
{ path: "scripts/run.py", kind: "script", sizeBytes: Buffer.byteLength(script), sha256: sha256(script) },
];
const scriptCatalogSkill: CatalogSkill = {
...sampleCatalogSkill,
trustLevel: "scripts_executables",
files: scriptFiles,
contentHash: contentHash(scriptFiles),
};
mockCatalogService.getCatalogSkillOrThrow.mockReturnValue(scriptCatalogSkill);
mockCatalogService.copyCatalogSkillFile.mockImplementation(async (_ref: string, filePath: string, targetPath: string) => {
if (filePath === "scripts/run.py") {
await fs.writeFile(targetPath, script, "utf8");
return;
}
const content = filePath === "SKILL.md" ? sampleSkillMarkdown : sampleReferenceMarkdown;
await fs.writeFile(targetPath, content, "utf8");
});
const companyId = await createCompany();
const result = await svc.installFromCatalog(companyId, {
catalogSkillId: scriptCatalogSkill.id,
});
expect(result.action).toBe("created");
expect(result.skill).toMatchObject({
trustLevel: "scripts_executables",
metadata: expect.objectContaining({
auditVerdict: "warning",
auditCodes: expect.arrayContaining(["script_trust"]),
}),
});
expect(result.warnings).toEqual(expect.arrayContaining([
"Skill includes a script file.",
]));
await expect(fs.readFile(path.join(result.skill.sourceLocator!, "scripts/run.py"), "utf8")).resolves.toBe(script);
});
it("restores portable catalog provenance when importing packaged skills", async () => {
const companyId = await createCompany();
const importedFiles = {
@@ -1,3 +1,4 @@
import { createHash } from "node:crypto";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { CatalogSkill } from "@paperclipai/shared";
@@ -42,6 +43,10 @@ function catalogSkill(slug: string, name = slug): CatalogSkill {
};
}
function sha256(value: string | Buffer) {
return createHash("sha256").update(value).digest("hex");
}
function manifest(skills: CatalogSkill[], packageVersion = "0.3.1") {
return JSON.stringify({
schemaVersion: 1,
@@ -59,6 +64,7 @@ describe("skills catalog service", () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
vi.unstubAllGlobals();
manifestJson = manifest([catalogSkill("old-skill", "Old Skill")]);
manifestMtimeMs = 1;
mockExistsSync.mockReturnValue(true);
@@ -110,4 +116,38 @@ describe("skills catalog service", () => {
});
expect(mockReadFile).not.toHaveBeenCalled();
});
it("reads referenced GitHub catalog files from pinned raw bytes", async () => {
const markdown = "---\nname: remote\n---\n\n# Remote\n";
const remoteSkill = catalogSkill("remote-skill", "Remote Skill");
remoteSkill.source = {
type: "github",
hostname: "github.com",
owner: "example",
repo: "remote-skill",
ref: "v1.0.0",
commit: "0123456789abcdef0123456789abcdef01234567",
path: "skills/remote",
url: "https://github.com/example/remote-skill/tree/v1.0.0/skills/remote",
};
remoteSkill.files = [
{ path: "SKILL.md", kind: "skill", sizeBytes: Buffer.byteLength(markdown), sha256: sha256(markdown) },
];
manifestJson = manifest([remoteSkill]);
const fetchMock = vi.fn(async (url: string) => {
expect(url).toBe("https://raw.githubusercontent.com/example/remote-skill/0123456789abcdef0123456789abcdef01234567/skills/remote/SKILL.md");
return new Response(markdown, { status: 200 });
});
vi.stubGlobal("fetch", fetchMock);
const service = await import("../services/skills-catalog.js");
await expect(service.readCatalogSkillFile(remoteSkill.id, "SKILL.md")).resolves.toMatchObject({
catalogSkillId: remoteSkill.id,
path: "SKILL.md",
content: markdown,
markdown: true,
});
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(mockReadFile).not.toHaveBeenCalled();
});
});