00ab790a7f56

prove koh offer --builds --json names saves that came in flagged during a stolen repo's upgrade, sharing the test platform helper (v3.0.88)

time
2026-09-28 15:36 UTC · 2 weeks ago
machine
Junes-MacBook-Pro.local
agent
claude-opus-5-5
session
quarantine unsafe paths
parent
0336dc246093
4 files package.json+1 −1tests/fixture.ts+7 −0tests/kohrelease.test.ts+1 −8tests/kohsteal.test.ts+23 −1
package.json+1 −1
@@ -1,6 +1,6 @@11 {22 	"name": "kepr",3-	"version": "3.0.87",3+	"version": "3.0.88",44 	"private": true,55 	"type": "module",66 	"scripts": {

view file

tests/fixture.ts+7 −0
@@ -236,3 +236,10 @@236236 	await writeFile(join(dir, "release.json"), JSON.stringify(record, null, 2));237237 	if (latest) await writeFile(join(bucketDir, repo, "releases", "latest"), release.version);238238 }239+240+/** This machine's platform, which is what `koh build` builds for with no flags. */241+export function platform(): string {242+	const os = process.platform === "darwin" ? "macos" : "linux";243+	const arch = process.arch === "arm64" ? "aarch64" : "x86_64";244+	return `${os}-${arch}`;245+}

view file

tests/kohrelease.test.ts+1 −8
@@ -9,7 +9,7 @@99 import { syncAll } from "../src/bucket/sync.ts";1010 import { createApp } from "../src/server/app.ts";1111 import { openKeprDb } from "../src/server/db.ts";12-import { kohWorkspace } from "./fixture.ts";12+import { kohWorkspace, platform } from "./fixture.ts";1313 1414 /**1515  * The joint contract (§3 item 4): `koh3 offer --builds` publishes a release into a folder remote@@ -23,13 +23,6 @@2323 	"a release note long enough to clear forty characters and the twelve word rule easily";2424 // No newline: a real newline inside koh.build's command would end the line there.2525 const ARTIFACT = "the artifact";26-27-/** This machine's platform, which is what `koh build` builds for with no flags. */28-function platform(): string {29-	const os = process.platform === "darwin" ? "macos" : "linux";30-	const arch = process.arch === "arm64" ? "aarch64" : "x86_64";31-	return `${os}-${arch}`;32-}3326 3427 type Latest = {3528 	version: string;

view file

tests/kohsteal.test.ts+23 −1
@@ -18,7 +18,7 @@1818 import { createApp } from "../src/server/app.ts";1919 import { openKeprDb } from "../src/server/db.ts";2020 import { Browser, PASSWORD } from "./browser.ts";21-import { stripPath } from "./fixture.ts";21+import { platform, stripPath } from "./fixture.ts";2222 2323 const REPO = "shipped";2424 const PRIVATE_REPO = "kept";@@ -198,6 +198,10 @@198198 				const third = join(root, "thief-three");199199 				await mkdir(third, { recursive: true });200200 				expect((await koh3(third, thiefHome, ["steal", `${host}/${REPO}`])).code).toBe(0);201+				// And a fourth, for `offer --builds --json` to upgrade.202+				const fourth = join(root, "thief-four");203+				await mkdir(fourth, { recursive: true });204+				expect((await koh3(fourth, thiefHome, ["steal", `${host}/${REPO}`])).code).toBe(0);201205 202206 				// Signing in: a code from the connect page, read the way `koh` reads it.203207 				// This Kepr's domain is the loopback address it is served on, so the same-origin@@ -280,6 +284,17 @@280284 				// Saves that come in flagged during offer's upgrade are named in its JSON, as steal's are.281285 				expect((await koh3(repoDir, ownerHome, ["steal"])).code).toBe(0);282286 				await writeFile(join(repoDir, "risky.txt"), "risky\n");287+				// The same save brings a build file, so the fourth copy can publish a release.288+				await writeFile(join(repoDir, "VERSION"), "1.0.0\n");289+				await writeFile(290+					join(repoDir, "koh.build"),291+					[292+						`command = mkdir -p out && printf built > out/app-1.0.0-${platform()}`,293+						"output = out/app-{version}-{platform}",294+						`platforms = ${platform()}`,295+						"",296+					].join("\n"),297+				);283298 				const risky = JSON.parse(284299 					(await koh3(repoDir, ownerHome, ["save", "risky", "--json"])).out,285300 				).id;@@ -289,6 +304,13 @@289304 				const flaggedOffer = await koh3(join(third, REPO), thiefHome, ["offer", "--json"]);290305 				expect(flaggedOffer.code, flaggedOffer.err + flaggedOffer.out).toBe(0);291306 				expect(JSON.parse(flaggedOffer.out).flagged).toEqual([risky]);307+				const flaggedBuilds = await koh3(join(fourth, REPO), thiefHome, [308+					"offer",309+					"--builds",310+					"--json",311+				]);312+				expect(flaggedBuilds.code, flaggedBuilds.err + flaggedBuilds.out).toBe(0);313+				expect(JSON.parse(flaggedBuilds.out).flagged).toEqual([risky]);292314 			} finally {293315 				bucketServer.stop();294316 			}

view file