Something went wrong. Try again.
A local-first event pipeline for independent agents, built on Jazz.
Something went wrong. Try again.
15 kB · 43 lines
TypeScript
1234567891011121314151617181920212223242526272829303132333435363738394041424344import fs from "node:fs/promises";import path from "node:path";import { afterEach, describe, expect, test } from "vitest";import { appendArtifactRequest, materializeArtifactRequest, requestArtifactStorage } from "../src/artifacts/append.js";import { buildArtifactCatalog, getArtifactBody, getArtifactCatalog } from "../src/artifacts/catalog.js";import { ARTIFACT_EVENT_TYPE, ARTIFACT_MAX_IMAGE_BYTES, ARTIFACT_MAX_TEXT_BYTES, ARTIFACT_REQUEST_EVENT_TYPE } from "../src/artifacts/types.js";import { createDefaultRegistry } from "../src/events/registry.js";import { JazzThoughtStore } from "../src/jazz/store.js";import { renderArtifactMarkdown, startInspectorServer } from "../src/web/inspector.js";import { temporaryProject, testStore } from "./helpers.js";
const stores: JazzThoughtStore[] = []; const roots: string[] = []; const servers: import("node:http").Server[] = [];afterEach(async () => { await Promise.all(servers.splice(0).map((server) => new Promise<void>((resolve) => { server.closeAllConnections(); server.close(() => resolve()); }))); await Promise.all(stores.splice(0).map((store) => store.close())); await Promise.all(roots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true }))); });async function fixture(name = "artifact.md", bytes: string | Buffer = "# Artifact\n") { const project = await temporaryProject("artifact-store-"); const workspace = await temporaryProject("artifact-workspace-"); roots.push(project, workspace); const store = await testStore(project); stores.push(store); await fs.writeFile(path.join(workspace, name), bytes); return { project, workspace, store }; }const input = { requestId: "req-1", workspaceLeaseId: "lease-1", workspaceRootLabel: "exe workspace lease", relativeFilePath: "artifact.md", artifactId: "skill:test", artifactVersion: 1, kind: "skill" as const, title: "Test", summary: "Private test artifact", mediaType: "text/markdown" as const, provenance: { source: "agent-workspace", label: "selected skill file" }, visibility: "private" as const, requestingAgentId: "agent-test", requestingRunId: "run-test", sourceEventId: "evt-source" };const png = Buffer.from([137,80,78,71,13,10,26,10,0,0,0,0]);
describe("durable private artifact storage", () => { test("request evidence is private, bounded, path-dark, and has no authority", async () => { const { workspace, store } = await fixture(); const request = await appendArtifactRequest({ store, ...input }); expect(request.event.type).toBe(ARTIFACT_REQUEST_EVENT_TYPE); expect(request.event.privacy).toBe("private"); expect(request.event.payload.publicationEligible).toBe(false); expect(request.event.payload.publicationAuthority).toBe(false); expect(JSON.stringify(request.event)).not.toContain(workspace); }); test("schema rejects absolute request paths and provenance labels", () => { const registry = createDefaultRegistry(); const payload = { ...input, publicationEligible: false, publicationAuthority: false, status: "pending" }; expect(() => registry.validateEvent(ARTIFACT_REQUEST_EVENT_TYPE, 1, "private", { ...payload, relativeFilePath: "/etc/passwd" } as never)).toThrow(); expect(() => registry.validateEvent(ARTIFACT_REQUEST_EVENT_TYPE, 1, "private", { ...payload, provenance: { source: "x", label: "/secret" } } as never)).toThrow(); }); test("materializes exact bytes once with strong request lineage and no inline bytes", async () => { const { workspace, store } = await fixture(); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); expect(result.event.type).toBe(ARTIFACT_EVENT_TYPE); expect(result.event.payload.publicationEligible).toBe(false); expect(result.event.payload.relations).toContainEqual({ type: "materialized-from-request", eventId: result.requestEvent!.id }); expect(result.event.payload.blob).toMatchObject({ algorithm: "sha256", byteCount: 11 }); expect(result.event.payload.body).toBeUndefined(); expect(result.event.payload.bodySha256).toBeUndefined(); const detail = await getArtifactBody(store, result.event.id); expect(detail?.text).toBe("# Artifact\n"); }); test("same identity and bytes is idempotent; changed bytes conflict", async () => { const { workspace, store } = await fixture(); const first = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); const replay = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); expect(first.inserted).toBe(true); expect(replay.inserted).toBe(false); await fs.writeFile(path.join(workspace, "artifact.md"), "changed"); await expect(requestArtifactStorage({ store, workspaceRoot: workspace, ...input })).rejects.toThrow("Idempotency key reused with different payload"); }); test("request lease identity must match materializer authority", async () => { const { workspace, store } = await fixture(); const request = await appendArtifactRequest({ store, ...input }); await expect(materializeArtifactRequest({ store, requestEventId: request.event.id, workspaceRoot: workspace, workspaceLeaseId: "other" })).rejects.toThrow("lease identity"); }); test("rejects workspace escape", async () => { const { workspace, store } = await fixture(); await expect(requestArtifactStorage({ store, workspaceRoot: workspace, ...input, relativeFilePath: "../outside.md" })).rejects.toThrow("normalized relative path"); }); test("rejects file symlink", async () => { const { workspace, store } = await fixture(); await fs.symlink("artifact.md", path.join(workspace, "alias.md")); await expect(requestArtifactStorage({ store, workspaceRoot: workspace, ...input, relativeFilePath: "alias.md" })).rejects.toThrow("symbolic links"); }); test("rejects parent symlink", async () => { const { workspace, store } = await fixture(); await fs.mkdir(path.join(workspace, "real")); await fs.writeFile(path.join(workspace, "real", "x.md"), "x"); await fs.symlink("real", path.join(workspace, "alias")); await expect(requestArtifactStorage({ store, workspaceRoot: workspace, ...input, relativeFilePath: "alias/x.md" })).rejects.toThrow("symbolic links"); }); test("rejects extension and MIME mismatch", async () => { const { workspace, store } = await fixture("artifact.txt", "x"); await expect(requestArtifactStorage({ store, workspaceRoot: workspace, ...input, relativeFilePath: "artifact.txt" })).rejects.toThrow("extension and media type"); }); test("rejects PNG and JPEG magic mismatch", async () => { const a = await fixture("artifact.png", "not png"); await expect(requestArtifactStorage({ store: a.store, workspaceRoot: a.workspace, ...input, relativeFilePath: "artifact.png", mediaType: "image/png", kind: "image" })).rejects.toThrow("PNG magic"); const b = await fixture("artifact.jpg", "not jpeg"); await expect(requestArtifactStorage({ store: b.store, workspaceRoot: b.workspace, ...input, relativeFilePath: "artifact.jpg", mediaType: "image/jpeg", kind: "image" })).rejects.toThrow("JPEG magic"); }); test("validates JSON and YAML structure", async () => { const a = await fixture("artifact.json", "{"); await expect(requestArtifactStorage({ store: a.store, workspaceRoot: a.workspace, ...input, relativeFilePath: "artifact.json", mediaType: "application/json" })).rejects.toThrow(); const b = await fixture("artifact.yaml", "a: ["); await expect(requestArtifactStorage({ store: b.store, workspaceRoot: b.workspace, ...input, relativeFilePath: "artifact.yaml", mediaType: "application/yaml" })).rejects.toThrow(); }); test("enforces exact text and image caps", async () => { const a = await fixture("artifact.txt", Buffer.alloc(ARTIFACT_MAX_TEXT_BYTES + 1, 1)); await expect(requestArtifactStorage({ store: a.store, workspaceRoot: a.workspace, ...input, relativeFilePath: "artifact.txt", mediaType: "text/plain" })).rejects.toThrow("exceeds"); const b = await fixture("artifact.png", Buffer.alloc(ARTIFACT_MAX_IMAGE_BYTES + 1, 1)); await expect(requestArtifactStorage({ store: b.store, workspaceRoot: b.workspace, ...input, relativeFilePath: "artifact.png", mediaType: "image/png", kind: "image" })).rejects.toThrow("exceeds"); }); test("stores blobs with canonical path and private modes", async () => { const { workspace, store } = await fixture(); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); const blob = result.event.payload.blob as { relativePath: string }; const rootStat = await fs.stat(store.getArtifactRoot()); const fileStat = await fs.stat(path.join(store.getArtifactRoot(), ...blob.relativePath.split("/"))); expect(rootStat.mode & 0o777).toBe(0o700); expect(fileStat.mode & 0o777).toBe(0o600); expect(blob.relativePath).toMatch(/^sha256\/[a-f0-9]{2}\/[a-f0-9]{64}$/); }); test("blob tamper fails on read", async () => { const { workspace, store } = await fixture(); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); const blob = result.event.payload.blob as { relativePath: string }; await fs.writeFile(path.join(store.getArtifactRoot(), ...blob.relativePath.split("/")), "tamper"); await expect(getArtifactBody(store, result.event.id)).rejects.toThrow("integrity check failed"); }); test("catalog is projected, metadata-only, and path/credential/body dark", async () => { const { workspace, store } = await fixture("artifact.md", "PRIVATE-BODY credential=secret-token"); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); const catalog = await getArtifactCatalog(store); const projection = await store.getProjection("artifact-catalog"); const serialized = JSON.stringify(catalog); expect(catalog.entries[0]?.eventId).toBe(result.event.id); expect(projection?.projectionVersion).toBe(1); expect(projection?.payload).toEqual(JSON.parse(serialized)); expect(serialized).not.toContain("PRIVATE-BODY"); expect(serialized).not.toContain("secret-token"); expect(serialized).not.toContain(workspace); }); test("private inspector returns safe text detail and rejects mutations", async () => { const { workspace, store } = await fixture(); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); const { base } = await inspector(store); const catalog = await (await fetch(`${base}/api/artifacts`)).text(); expect(catalog).not.toContain("# Artifact"); const detail = await (await fetch(`${base}/api/artifacts/${result.event.id}`)).json() as { text: string; body?: string }; expect(detail.text).toBe("# Artifact\n"); expect(detail.body).toBeUndefined(); expect((await fetch(`${base}/api/artifacts`, { method: "POST" })).status).toBe(405); }); test("artifact UI renders content first, collapses metadata, and opens one focused detail view", async () => { const { store } = await fixture(); const { base } = await inspector(store); const page = await (await fetch(base)).text(); const renderer = page.slice(page.indexOf("function renderArtifact"), page.indexOf("function bindArtifactBack")); expect(page).toMatch(/main\.detail-selected #list-pane\s*\{\s*display:none\s*\}/); expect(page).toContain("data.renderedHtml"); expect(page).toContain("<summary>Artifact details</summary>"); expect(renderer).not.toContain("JSON.stringify(item"); expect(renderer).not.toContain("canonical envelope"); expect(renderer.indexOf("+content+metadata")).toBeGreaterThan(-1); }); test("Markdown rendering strips frontmatter, preserves document structure, and escapes active content", () => { const rendered = renderArtifactMarkdown("---\nid: secret\n---\n# Heading\n\n- one\n- **two**\n\n***both*** `code` [site](https://example.com) <script>alert(1)</script> [bad](javascript:alert(2))\n"); expect(rendered).toContain("<h1>Heading</h1>"); expect(rendered).toContain("<ul><li>one</li><li><strong>two</strong></li></ul>"); expect(rendered).toContain("<strong><em>both</em></strong>"); expect(rendered).toContain("<code>code</code>"); expect(rendered).toContain('<a href="https://example.com" rel="noreferrer">site</a>'); expect(rendered).toContain("<script>alert(1)</script>"); expect(rendered).toContain("[bad](javascript:alert(2))"); expect(rendered).not.toContain("id: secret"); }); test("suggestions UI is human-first, precedes review, and never renders proposal JSON", async () => { const { store } = await fixture(); const { base } = await inspector(store); const queue = await (await fetch(`${base}/api/proposals`)).json() as { count: number; items: unknown[] }; expect(queue).toEqual({ count: 0, items: [] }); const page = await (await fetch(base)).text(); expect(page.indexOf('id="suggestions-tab"')).toBeLessThan(page.indexOf('id="reviews-tab"')); const renderer = page.slice(page.indexOf("function renderSuggestion"), page.indexOf("function renderReview")); expect(renderer).toContain("Memory suggestion"); expect(renderer).toContain("Original delivered reply"); expect(renderer).toContain("Technical details"); expect(renderer).not.toContain("JSON.stringify(item"); expect(renderer).not.toContain("raw payload"); }); test("generated inspector client JavaScript parses", async () => { const { store } = await fixture(); const { base } = await inspector(store); const page = await (await fetch(base)).text(); const script = page.match(/<script>([\s\S]*?)<\/script>/)?.[1]; expect(script).toBeDefined(); expect(() => new Function(script!)).not.toThrow(); }); test("private inspector image detail is metadata-only and content is on-demand", async () => { const { workspace, store } = await fixture("artifact.png", png); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input, relativeFilePath: "artifact.png", mediaType: "image/png", kind: "image" }); const { base } = await inspector(store); const detail = await (await fetch(`${base}/api/artifacts/${result.event.id}`)).json() as { contentPath: string; text?: string }; expect(detail.text).toBeUndefined(); expect(JSON.stringify(detail)).not.toContain(png.toString("base64")); const content = await fetch(`${base}${detail.contentPath}`); expect(content.headers.get("content-type")).toBe("image/png"); expect(Buffer.from(await content.arrayBuffer())).toEqual(png); }); test("sensitive request and artifact remain sensitive and non-publishable", async () => { const { workspace, store } = await fixture(); const result = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input, visibility: "sensitive" }); expect(result.requestEvent?.privacy).toBe("sensitive"); expect(result.event.privacy).toBe("sensitive"); expect(result.event.payload.publicationEligible).toBe(false); }); test("supersession remains append-only", async () => { const { workspace, store } = await fixture(); const v1 = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input }); await fs.writeFile(path.join(workspace, "artifact.md"), "v2"); const v2 = await requestArtifactStorage({ store, workspaceRoot: workspace, ...input, requestId: "req-2", artifactVersion: 2, supersedesArtifactEventId: v1.event.id }); const catalog = await buildArtifactCatalog(store); expect(catalog.entries.find((e) => e.eventId === v1.event.id)?.superseded).toBe(true); expect(v2.event.payload.supersedesArtifactEventId).toBe(v1.event.id); });});async function inspector(store: JazzThoughtStore) { const server = await startInspectorServer(store, { port: 0 }); servers.push(server); const address = server.address(); if (!address || typeof address === "string") throw new Error("missing address"); return { base: `http://127.0.0.1:${address.port}` }; }