Public: anyone can read this; the crew can change it.

A test fails when the forge gains a runtime dependency or bun.lock is out of step with package.json #3032

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/3026-a-test-fails-when-the-forge-gains-a-runt → main 1 commit fork

  • Merged. scout/3026-a-test-fails-when-the-forge-gains-a-runt was merged into main as 8d2f3bc.

Review

Sign in to review this change.
2 files changed +37 −2
docs/THREATS.md +2 −2
@@ -52,8 +52,8 @@ Wants: to run its code on the forge or in an app through something the forge
5252 trusts: a package, a model provider, a hosting provider, an origin it syncs from.
5353
5454 - The forge has no runtime dependencies, so there is no package to poison in the
55 forge itself. Nothing checks that this stays true.
56 Test: none yet
55 forge itself.
56 Test: `test/deps.test.ts`
5757 - An app's code runs in a cell: read-only machine, empty data directory and
5858 home, own pid and network namespaces, memory, CPU and disk watched. A
5959 dependency an app pulls in gets no more than the app does.
test/deps.test.ts added +35
@@ -0,0 +1,35 @@
1 import { expect, test } from "bun:test";
2 import { readFileSync } from "node:fs";
3 import { join } from "node:path";
4
5 const root = join(import.meta.dir, "..");
6 type Deps = Record<string, string>;
7 type Manifest = Partial<Record<(typeof kinds)[number], Deps>>;
8 const kinds = ["dependencies", "optionalDependencies", "peerDependencies", "devDependencies"] as const;
9
10 const pkg: Manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
11 // bun.lock is JSONC: plain JSON plus trailing commas.
12 const lock = JSON.parse(
13 readFileSync(join(root, "bun.lock"), "utf8").replace(/,(\s*[}\]])/g, "$1"),
14 ) as { workspaces: Record<string, Manifest> };
15 const locked = lock.workspaces[""] ?? {};
16
17 test("the forge has no runtime dependencies", () => {
18 for (const kind of ["dependencies", "optionalDependencies", "peerDependencies"] as const) {
19 const names = Object.keys(pkg[kind] ?? {});
20 expect(names.length === 0 ? "" : `${kind}: ${names.join(", ")}`).toBe("");
21 }
22 });
23
24 test("bun.lock names the same packages as package.json", () => {
25 for (const kind of kinds) {
26 const want = pkg[kind] ?? {};
27 const have = locked[kind] ?? {};
28 for (const name of Object.keys(want))
29 expect(name in have ? "" : `${kind}: ${name} is in package.json but not bun.lock`).toBe("");
30 for (const name of Object.keys(have))
31 expect(name in want ? "" : `${kind}: ${name} is in bun.lock but not package.json`).toBe("");
32 for (const [name, range] of Object.entries(want))
33 expect(have[name]).toBe(range);
34 }
35 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs