import { test } from "node:test"; import assert from "node:assert/strict"; import { mkdtempSync, readFileSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { decideApply, grantOf, holdsLogin, readCredentials, withGrant, writeCredentials, type Grant, } from "../dist/grant.js"; const NOW = 1_700_000_000_000; const HOUR = 3_600_000; const g = (over: Partial = {}): Grant => ({ accessToken: "tok-A", expiresAt: NOW + HOUR, refreshTokenExpiresAt: NOW + 30 * 24 * HOUR, ...over, }); test("a rotation applies a newer grant of the same licence", () => { assert.deepEqual(decideApply(g(), g({ accessToken: "tok-B", expiresAt: NOW + 2 * HOUR }), "rotation"), { apply: true }); }); test("a rotation refuses a grant that arrived late and is older", () => { const d = decideApply(g({ accessToken: "new", expiresAt: NOW + 2 * HOUR }), g({ accessToken: "old" }), "rotation"); assert.equal(d.apply === false && d.reason, "not-newer"); }); test("a grant re-issued by a login is adopted even though it expires sooner (2026-09-05)", () => { const local = g({ expiresAt: NOW + 8 * HOUR, refreshTokenExpiresAt: NOW + 30 * 24 * HOUR }); const offered = g({ accessToken: "reissued", expiresAt: NOW + HOUR, refreshTokenExpiresAt: NOW + 5 * 24 * HOUR }); assert.deepEqual(decideApply(local, offered, "rotation"), { apply: true, reissued: true }); }); test("a switch to another licence applies whatever the expiries say", () => { const local = g({ expiresAt: NOW + 8 * HOUR }); assert.equal(decideApply(local, g({ accessToken: "other", expiresAt: NOW + HOUR }), "switch").apply, true); }); test("the same token is not rewritten", () => { assert.deepEqual(decideApply(g(), g(), "switch"), { apply: false, reason: "already-current" }); }); test("a full grant left by a login is seen as a login, and stripped when the node's own is written", () => { const dir = mkdtempSync(join(tmpdir(), "claude-code-")); const path = join(dir, ".claude", ".credentials.json"); writeFileSync(join(dir, "x"), ""); const login = { claudeAiOauth: { accessToken: "at-login", refreshToken: "rt-login", expiresAt: NOW }, other: 1 }; assert.equal(holdsLogin(login), true); writeCredentials(path, withGrant(login, g({ accessToken: "at-mesh", scopes: ["user:inference"] }))); const back = readCredentials(path)!; assert.equal(holdsLogin(back), false); assert.equal(grantOf(back)!.accessToken, "at-mesh"); assert.deepEqual(back.claudeAiOauth!.scopes, ["user:inference"]); assert.equal(back.other, 1, "a key the module does not know was lost"); assert.ok(!readFileSync(path, "utf8").includes("rt-login")); assert.equal(statSync(path).mode & 0o777, 0o600); });