Skip to content

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.sh
107 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { DANGEROUS_SCOPES, OAUTH_DEFAULT_SCOPES, SCOPES, SCOPE_GROUPS } from "@g1t/contracts/scopes";
5
6import {
7 accessSummary,
8 consentedScopes,
9 describeExpiry,
10 everyScope,
11 grantFromForm,
12 impliedBy,
13 matchingPreset,
14 normalizeScopes,
15 requestedScopes,
16 scopesFromForm,
17} from "./token-scopes.ts";
18
19function form(fields: Record<string, string | string[]>) {
20 return {
21 get: (name: string) => {
22 const value = fields[name];
23 return Array.isArray(value) ? (value[0] ?? null) : (value ?? null);
24 },
25 getAll: (name: string) => {
26 const value = fields[name];
27 return value === undefined ? [] : Array.isArray(value) ? value : [value];
28 },
29 };
30}
31
32test("every scope is on the checklist exactly once, admin ones under Dangerous", () => {
33 const listed = [...SCOPE_GROUPS.flatMap((group) => group.scopes), ...DANGEROUS_SCOPES];
34 assert.deepEqual([...listed].sort(), SCOPES.map((row) => row.scope).sort());
35 assert.equal(new Set(listed).size, listed.length);
36 assert.ok(DANGEROUS_SCOPES.every((scope) => scope.endsWith(":admin") || scope.endsWith(":delete")));
37});
38
39test("ticked boxes store the highest level of each resource", () => {
40 const parsed = scopesFromForm(
41 form({ scope: ["issues:read", "issues:write", "code:read", "agents:run", "memory:write", "bogus:read"] }),
42 );
43 assert.deepEqual(parsed, { ok: true, value: ["code:read", "issues:write"] });
44 assert.deepEqual(normalizeScopes(["repo:read", "repo:admin", "repo:write"]), ["repo:admin"]);
45});
46
47test("full access is null, and nothing ticked is refused", () => {
48 assert.deepEqual(scopesFromForm(form({ preset: "full", scope: "issues:read" })), { ok: true, value: null });
49 assert.equal(scopesFromForm(form({ preset: "full" }), { allowFull: false }).ok, false);
50 assert.equal(scopesFromForm(form({ preset: "custom" })).ok, false);
51 assert.deepEqual(grantFromForm(form({ scope: "observability:read" })), { ok: true, value: { scopes: ["observability:read"] } });
52});
53
54test("a higher level ticks the lower ones of its resource only", () => {
55 assert.equal(impliedBy(["issues:write"], "issues:read"), "issues:write");
56 assert.equal(impliedBy(["repo:admin"], "repo:write"), "repo:admin");
57 assert.equal(impliedBy(["issues:write"], "issues:write"), null);
58 assert.equal(impliedBy(["issues:write"], "pull_requests:read"), null);
59 assert.equal(impliedBy(["code:read"], "code:write"), null);
60});
61
62test("full access ticks the top level of everything", () => {
63 const all = everyScope();
64 assert.ok(all.includes("repo:admin"));
65 assert.ok(!all.includes("agents:run"), "retired");
66 assert.ok(!all.some((scope) => scope.startsWith("memory:")), "retired");
67 assert.ok(all.includes("code:write"));
68 assert.ok(!all.includes("code:read"));
69});
70
71test("presets are recognised however their scopes are written", () => {
72 assert.equal(matchingPreset(null), "full");
73 assert.equal(matchingPreset(["repo:read", "code:write", "packages:write", "workflows:write", "checks:write", "deployments:write"]), "ci");
74 assert.equal(matchingPreset([...OAUTH_DEFAULT_SCOPES]), "agent");
75 assert.equal(matchingPreset(["issues:read"]), null);
76});
77
78test("a token's access reads plainly", () => {
79 assert.equal(accessSummary({ scopes: null, legacy: true }), "Legacy · full access");
80 assert.equal(accessSummary({ scopes: null, legacy: false }), "Full access");
81 assert.equal(accessSummary({ scopes: ["code:read", "code:write", "packages:write", "workflows:write", "checks:write", "deployments:write", "repo:read"], legacy: false }), "CI");
82 assert.equal(accessSummary({ scopes: ["issues:read", "issues:write", "pull_requests:read"], legacy: false }), "2 scopes");
83 assert.equal(accessSummary({ scopes: [], legacy: false }), "No scopes");
84});
85
86test("an application asking for nothing usable gets the default set, never admin", () => {
87 assert.deepEqual(requestedScopes(null), OAUTH_DEFAULT_SCOPES);
88 assert.deepEqual(requestedScopes("openid profile *"), OAUTH_DEFAULT_SCOPES);
89 assert.ok(!requestedScopes("").some((scope) => scope.endsWith(":admin")));
90 assert.deepEqual(requestedScopes("issues:write nonsense repo:read"), ["repo:read", "issues:write"]);
91});
92
93test("consent keeps only what was asked for", () => {
94 const requested = requestedScopes("repo:read issues:read issues:write");
95 assert.deepEqual(consentedScopes(form({ scope: ["issues:write", "repo:admin", "secrets:admin"] }), requested), ["issues:write"]);
96 assert.deepEqual(consentedScopes(form({ scope: ["issues:read", "repo:read"] }), requested), ["repo:read", "issues:read"]);
97 assert.deepEqual(consentedScopes(form({}), requested), []);
98});
99
100test("expiry words", () => {
101 const now = Date.parse("2026-10-05T00:00:00Z");
102 assert.equal(describeExpiry(null, now), "No expiry");
103 assert.equal(describeExpiry("2026-10-04T00:00:00Z", now), "Expired");
104 assert.equal(describeExpiry("2026-10-12T00:00:00Z", now), "Expires in 7 days");
105 assert.equal(describeExpiry("2026-10-05T01:00:00Z", now), "Expires in 1 hour");
106 assert.equal(describeExpiry("2027-01-03T00:00:00Z", now), "Expires in 3 months");
107});