// Task 1670 — resolveHouseScopedToken shells cf-token.sh against the house env // file and reads back the persisted key value. The cf-token.sh invocation is // mocked via the injected RunFn (it appends the key and echoes the key name). import test from "node:test"; import assert from "node:assert/strict"; import { mkdtempSync, writeFileSync, appendFileSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { resolveHouseScopedToken } from "../house-scoped-token.js"; import type { RunFn } from "../cf-exec.js"; function houseFile(contents: string): string { const dir = mkdtempSync(join(tmpdir(), "hst-")); const p = join(dir, "cloudflare-house.env"); writeFileSync(p, contents); return p; } test("mints and reads back the scoped token value", async () => { const p = houseFile("CLOUDFLARE_API_TOKEN=cfat_minter\nCLOUDFLARE_ACCOUNT_ID=acc\n"); const run: RunFn = async (_cmd, args) => { assert.equal(args[1], "storage", "scope passed to cf-token.sh"); appendFileSync(p, "CF_STORAGE_TOKEN=minted_value\n"); return { stdout: "CF_STORAGE_TOKEN\n" }; }; const tok = await resolveHouseScopedToken("storage", p, "/x/cf-token.sh", run); assert.equal(tok, "minted_value"); }); test("reuse: a pre-existing key resolves to its value", async () => { const p = houseFile("CLOUDFLARE_API_TOKEN=cfat_minter\nCLOUDFLARE_ACCOUNT_ID=acc\nCF_STORAGE_TOKEN=already_here\n"); // cf-token.sh reuse path writes nothing new, still echoes the key. const run: RunFn = async () => ({ stdout: "CF_STORAGE_TOKEN\n" }); const tok = await resolveHouseScopedToken("storage", p, "/x/cf-token.sh", run); assert.equal(tok, "already_here"); }); test("throws when the persisted key is absent after the run", async () => { const p = houseFile("CLOUDFLARE_API_TOKEN=cfat_minter\nCLOUDFLARE_ACCOUNT_ID=acc\n"); const run: RunFn = async () => ({ stdout: "CF_STORAGE_TOKEN\n" }); // writes nothing await assert.rejects(() => resolveHouseScopedToken("storage", p, "/x/cf-token.sh", run)); }); test("throws when cf-token.sh returns no key name", async () => { const p = houseFile("CLOUDFLARE_API_TOKEN=cfat_minter\nCLOUDFLARE_ACCOUNT_ID=acc\n"); const run: RunFn = async () => ({ stdout: "\n" }); await assert.rejects(() => resolveHouseScopedToken("storage", p, "/x/cf-token.sh", run)); });