fast-browser-with-jev
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { chmod, lstat, mkdir, readFile, readdir, symlink } from "node:fs/promises";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { test } from "node:test";
|
||||
import { FilePrivateArtifactStore } from "./artifact-store.ts";
|
||||
|
||||
async function temporaryRoot(): Promise<string> {
|
||||
return mkdtemp(join(tmpdir(), "fast-browser-artifacts-test-"));
|
||||
}
|
||||
|
||||
const owner = {
|
||||
sessionId: "session/with-secret?no-path",
|
||||
runId: "run/../../not-a-directory",
|
||||
operationId: "operation-1",
|
||||
} as const;
|
||||
|
||||
test("commits bounded private artifacts atomically with sanitized ownership paths", async () => {
|
||||
const root = await temporaryRoot();
|
||||
const store = new FilePrivateArtifactStore({ root, maxArtifactBytes: 32 });
|
||||
try {
|
||||
const writer = await store.open(owner, "diagnostics");
|
||||
await writer.write(new TextEncoder().encode('{"level":"error"}'));
|
||||
const metadata = await writer.commit();
|
||||
assert.equal(metadata.kind, "diagnostics");
|
||||
assert.equal(metadata.contentType, "application/json");
|
||||
assert.equal(metadata.bytes, 17);
|
||||
assert.equal(metadata.permissions, "0600");
|
||||
assert.equal(metadata.localOnly, true);
|
||||
assert.equal(metadata.modelForwarded, false);
|
||||
assert.equal(metadata.owner.runId, owner.runId);
|
||||
assert.ok(!metadata.path.includes(".."));
|
||||
assert.ok(metadata.path.startsWith(root));
|
||||
const stat = await lstat(metadata.path);
|
||||
assert.equal(stat.isFile(), true);
|
||||
assert.equal(stat.mode & 0o777, 0o600);
|
||||
assert.equal(await readFile(metadata.path, "utf8"), '{"level":"error"}');
|
||||
assert.equal((await readdir(root)).length, 1);
|
||||
} finally {
|
||||
await store.close();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects oversized chunks and removes incomplete private files", async () => {
|
||||
const root = await temporaryRoot();
|
||||
const store = new FilePrivateArtifactStore({ root, maxArtifactBytes: 4 });
|
||||
try {
|
||||
const writer = await store.open({ sessionId: "s", runId: "r", operationId: "o" }, "screenshot");
|
||||
await assert.rejects(writer.write(new Uint8Array(5)), /size limit/);
|
||||
await assert.rejects(writer.commit(), /closed/);
|
||||
const sessionEntries = await readdir(root);
|
||||
assert.equal(sessionEntries.length, 1);
|
||||
const runEntries = await readdir(join(root, sessionEntries[0]!, (await readdir(join(root, sessionEntries[0]!)))[0]!));
|
||||
assert.equal(runEntries.length, 0);
|
||||
} finally {
|
||||
await store.close();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("aborts open writers on store close and does not expose foreign paths", async () => {
|
||||
const root = await temporaryRoot();
|
||||
const foreign = await temporaryRoot();
|
||||
const store = new FilePrivateArtifactStore(root);
|
||||
try {
|
||||
const writer = await store.open({ sessionId: "s", runId: "r", operationId: "o" }, "diagnostics");
|
||||
await writer.write(new TextEncoder().encode("private"));
|
||||
await store.close();
|
||||
await assert.rejects(writer.write(new Uint8Array([1])), /closed/);
|
||||
const sessionPath = join(root, (await readdir(root))[0]!);
|
||||
const runPath = join(sessionPath, (await readdir(sessionPath))[0]!);
|
||||
assert.deepEqual(await readdir(runPath), []);
|
||||
await assert.rejects(store.open({ sessionId: "foreign", runId: "r", operationId: "o" }, "diagnostics"), /closed/);
|
||||
assert.equal(await readdir(foreign).then((items) => items.length), 0);
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
await rm(foreign, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("fails closed for a symlink in the artifact root path", async () => {
|
||||
const parent = await temporaryRoot();
|
||||
const target = await temporaryRoot();
|
||||
const root = join(parent, "root-link");
|
||||
await symlink(target, root);
|
||||
const store = new FilePrivateArtifactStore(root);
|
||||
try {
|
||||
await assert.rejects(store.open({ sessionId: "s", runId: "r", operationId: "o" }, "diagnostics"), /symlink/);
|
||||
} finally {
|
||||
await store.close();
|
||||
await rm(parent, { recursive: true, force: true });
|
||||
await rm(target, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects broad permissions on an existing root without chmodding its parent", async () => {
|
||||
const root = await temporaryRoot();
|
||||
const parentMode = (await lstat(dirname(root))).mode & 0o777;
|
||||
await chmod(root, 0o755);
|
||||
const store = new FilePrivateArtifactStore(root);
|
||||
try {
|
||||
await assert.rejects(store.open({ sessionId: "s", runId: "r", operationId: "o" }, "diagnostics"), /permissions/);
|
||||
assert.equal((await lstat(dirname(root))).mode & 0o777, parentMode);
|
||||
} finally {
|
||||
await store.close();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user