import { afterEach, describe, expect, spyOn, test } from "bun:test"; import { rm } from "node:fs/promises"; import { KuberApiError, type ApiRequestInit } from "../../lib/api"; import { getTrustPath, readTrust, updateTrust } from "../../lib/trust"; import { grantTrust, revokeTrust, statusTrust } from "../../command/trust"; const originalConfig = process.env.XDG_CONFIG_HOME; const identity = { project: "demo", fingerprint: "a".repeat(64) }; afterEach(async () => { const path = getTrustPath(); if (originalConfig === undefined) delete process.env.XDG_CONFIG_HOME; else process.env.XDG_CONFIG_HOME = originalConfig; await rm(path.slice(0, path.lastIndexOf("/")), { recursive: true, force: true, }); }); function requester( calls: Array<{ path: string; init?: ApiRequestInit }>, response: unknown = undefined, ) { return async (path: string, init?: ApiRequestInit): Promise => { calls.push({ path, init }); return response as T; }; } describe("trust command", () => { test("grants, reports, and revokes the current namespace fingerprint", async () => { process.env.XDG_CONFIG_HOME = `/tmp/kuber-trust-command-${crypto.randomUUID()}`; const calls: Array<{ path: string; init?: ApiRequestInit }> = []; const output = spyOn(console, "log").mockImplementation(() => {}); await grantTrust(identity, requester(calls)); expect(calls).toEqual([ { path: "/workspaces/demo/trust", init: { method: "POST", json: { fingerprint: identity.fingerprint } }, }, ]); expect(await readTrust()).toEqual([identity]); calls.length = 0; await statusTrust( identity, requester(calls, { fingerprints: [identity.fingerprint] }), ); expect(calls).toEqual([ { path: "/workspaces/demo/trust", init: undefined }, ]); expect(output.mock.calls.map(([line]) => line)).toEqual([ "Trusted this directory for namespace demo", "Namespace: demo", "Local: trusted", "Server: registered", ]); calls.length = 0; await revokeTrust(identity, requester(calls)); expect(calls).toEqual([ { path: `/workspaces/demo/trust?fingerprint=${identity.fingerprint}`, init: { method: "DELETE" }, }, ]); expect(await readTrust()).toEqual([]); output.mockRestore(); }); test("removes local trust when the server registration is already absent", async () => { process.env.XDG_CONFIG_HOME = `/tmp/kuber-trust-command-${crypto.randomUUID()}`; await updateTrust(() => [identity]); const output = spyOn(console, "log").mockImplementation(() => {}); await revokeTrust(identity, async () => { throw new KuberApiError("not found", 404); }); expect(await readTrust()).toEqual([]); expect(output).toHaveBeenCalledWith("Revoked trust for namespace demo"); output.mockRestore(); }); test("removes local trust before reporting a remote revoke failure", async () => { process.env.XDG_CONFIG_HOME = `/tmp/kuber-trust-command-${crypto.randomUUID()}`; await updateTrust(() => [identity]); await expect( revokeTrust(identity, async () => { throw new KuberApiError("unavailable", 503); }), ).rejects.toThrow("Removed local trust for namespace demo"); expect(await readTrust()).toEqual([]); }); });