Skip to content
106 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", "bogus:read"] }),
42 );
43 assert.deepEqual(parsed, { ok: true, value: ["code:read", "issues:write", "agents:run"] });
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: "memory:read" })), { ok: true, value: { scopes: ["memory: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"));
66 assert.ok(all.includes("code:write"));
67 assert.ok(!all.includes("code:read"));
68});
69
70test("presets are recognised however their scopes are written", () => {
71 assert.equal(matchingPreset(null), "full");
72 assert.equal(matchingPreset(["repo:read", "code:write", "packages:write", "workflows:write", "checks:write", "deployments:write"]), "ci");
73 assert.equal(matchingPreset([...OAUTH_DEFAULT_SCOPES]), "agent");
74 assert.equal(matchingPreset(["issues:read"]), null);
75});
76
77test("a token's access reads plainly", () => {
78 assert.equal(accessSummary({ scopes: null, legacy: true }), "Legacy · full access");
79 assert.equal(accessSummary({ scopes: null, legacy: false }), "Full access");
80 assert.equal(accessSummary({ scopes: ["code:read", "code:write", "packages:write", "workflows:write", "checks:write", "deployments:write", "repo:read"], legacy: false }), "CI");
81 assert.equal(accessSummary({ scopes: ["issues:read", "issues:write", "memory:read"], legacy: false }), "2 scopes");
82 assert.equal(accessSummary({ scopes: [], legacy: false }), "No scopes");
83});
84
85test("an application asking for nothing usable gets the default set, never admin", () => {
86 assert.deepEqual(requestedScopes(null), OAUTH_DEFAULT_SCOPES);
87 assert.deepEqual(requestedScopes("openid profile *"), OAUTH_DEFAULT_SCOPES);
88 assert.ok(!requestedScopes("").some((scope) => scope.endsWith(":admin")));
89 assert.deepEqual(requestedScopes("issues:write nonsense repo:read"), ["repo:read", "issues:write"]);
90});
91
92test("consent keeps only what was asked for", () => {
93 const requested = requestedScopes("repo:read issues:read issues:write");
94 assert.deepEqual(consentedScopes(form({ scope: ["issues:write", "repo:admin", "secrets:admin"] }), requested), ["issues:write"]);
95 assert.deepEqual(consentedScopes(form({ scope: ["issues:read", "repo:read"] }), requested), ["repo:read", "issues:read"]);
96 assert.deepEqual(consentedScopes(form({}), requested), []);
97});
98
99test("expiry words", () => {
100 const now = Date.parse("2026-10-05T00:00:00Z");
101 assert.equal(describeExpiry(null, now), "No expiry");
102 assert.equal(describeExpiry("2026-10-04T00:00:00Z", now), "Expired");
103 assert.equal(describeExpiry("2026-10-12T00:00:00Z", now), "Expires in 7 days");
104 assert.equal(describeExpiry("2026-10-05T01:00:00Z", now), "Expires in 1 hour");
105 assert.equal(describeExpiry("2027-01-03T00:00:00Z", now), "Expires in 3 months");
106});