flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/runner/src/credentials.test.ts

100 lines4,634 bytesCodeBlame
1import assert from "node:assert/strict";
2import { createHash } from "node:crypto";
3import { test } from "node:test";
4
5import { credentialHashes, holdCredentials, modelTokenHashes, pushGrant, remotePath, revokeCredentials, sha256Hex } from "./credentials.ts";
6
7test("a remote names its repository", () => {
8 assert.deepEqual(remotePath("https://g1t.sh/acme/rocket.git"), { namespace: "acme", name: "rocket" });
9 assert.deepEqual(remotePath("https://g1t.sh/pulls/pul_01abc.git"), { namespace: "pulls", name: "pul_01abc" });
10 assert.equal(remotePath("https://g1t.sh/acme"), null);
11});
12
13test("a fork is the pull request's own; a branch of the repository is not", () => {
14 const repo = { namespace: "acme", name: "rocket" };
15 assert.deepEqual(pushGrant(repo, { namespace: "pulls", name: "pul_1" }, "main"), {
16 repo: { namespace: "pulls", name: "pul_1" },
17 branch: null,
18 });
19 assert.deepEqual(pushGrant(repo, { namespace: "Acme", name: "Rocket" }, "fix-login"), {
20 repo: { namespace: "Acme", name: "Rocket" },
21 branch: "fix-login",
22 });
23});
24
25test("tokens are hashed the way identity stores them", async () => {
26 const token = "g1t_0123456789abcdef";
27 assert.equal(await sha256Hex(token), createHash("sha256").update(token).digest("hex"));
28 const hashes = await credentialHashes({ G1T_TOKEN: token, G1T_AGENT_TOKEN: "g1t_x", OTHER: "g1t_y", CHECK_TOKEN: "c" });
29 assert.equal(hashes.length, 2);
30 assert.ok(hashes.every((hash) => /^[0-9a-f]{64}$/.test(hash)));
31});
32
33/** Identity, as far as the credentials' lifecycle uses it. */
34function fakeIdentity() {
35 const calls: { method: string; body: unknown }[] = [];
36 return {
37 calls,
38 fetch: async (url: string, init?: RequestInit) => {
39 calls.push({ method: url.split("/rpc/")[1], body: JSON.parse(String(init?.body)) });
40 return new Response("true");
41 },
42 };
43}
44
45function memoryStorage() {
46 const map = new Map<string, unknown>();
47 return {
48 map,
49 put: async (key: string, value: unknown) => void map.set(key, value),
50 get: async <T>(key: string) => map.get(key) as T | undefined,
51 delete: async (key: string) => map.delete(key),
52 };
53}
54
55test("a sandbox's credentials are bound to its run and revoked once when it stops", async () => {
56 const identity = fakeIdentity();
57 const storage = memoryStorage();
58 await holdCredentials(identity, storage, { G1T_TOKEN: "g1t_a", G1T_AGENT_TOKEN: "g1t_b" }, "run_1");
59 assert.equal(identity.calls[0].method, "bind_run_credentials");
60 assert.deepEqual((identity.calls[0].body as { runId: string }).runId, "run_1");
61 await revokeCredentials(identity, storage);
62 await revokeCredentials(identity, storage);
63 const revokes = identity.calls.filter((call) => call.method === "revoke_run_credentials");
64 assert.equal(revokes.length, 1);
65 assert.equal((revokes[0].body as { tokenHashes: string[] }).tokenHashes.length, 2);
66});
67
68test("a sandbox with no run record still has its credentials revoked", async () => {
69 const identity = fakeIdentity();
70 const storage = memoryStorage();
71 await holdCredentials(identity, storage, { G1T_TOKEN: "g1t_a" }, null);
72 assert.equal(identity.calls.length, 0);
73 await revokeCredentials(identity, storage);
74 assert.equal(identity.calls[0].method, "revoke_run_credentials");
75});
76
77test("a run's model token is closed when the run stops, once", async () => {
78 const identity = fakeIdentity();
79 const integrations = fakeIdentity();
80 const storage = memoryStorage();
81 const token = "g1tm_0123456789abcdef";
82 await holdCredentials(identity, storage, { G1T_TOKEN: "g1t_a", ANTHROPIC_API_KEY: token, AI_GATEWAY_TOKEN: token }, "run_1");
83 assert.deepEqual(await modelTokenHashes({ ANTHROPIC_API_KEY: token, OTHER: "sk-x" }), [await sha256Hex(token)]);
84 await revokeCredentials(identity, storage, integrations);
85 await revokeCredentials(identity, storage, integrations);
86 assert.equal(integrations.calls.length, 1);
87 assert.equal(integrations.calls[0].method, "close_model_sessions");
88 assert.deepEqual((integrations.calls[0].body as { token_hashes: string[] }).token_hashes, [await sha256Hex(token)]);
89 assert.equal(identity.calls.filter((call) => call.method === "revoke_run_credentials").length, 1);
90});
91
92test("a sandbox with only a model token still has it closed", async () => {
93 const identity = fakeIdentity();
94 const integrations = fakeIdentity();
95 const storage = memoryStorage();
96 await holdCredentials(identity, storage, { ANTHROPIC_API_KEY: "g1tm_x" }, null);
97 await revokeCredentials(identity, storage, integrations);
98 assert.equal(integrations.calls[0]?.method, "close_model_sessions");
99 assert.equal(identity.calls.length, 0);
100});