Files
mesh-catalog/modules/anthropic-consumer/test/credentials.test.ts
jschoubben c206e2e11e anthropic model-access modules: manager (refreshable-grant) and consumer
Phase C of vendor-agnostic model-access (ADR 0050/0054). Two TypeScript
runtime modules:

- anthropic-manager: the refresh token is sealed at rest to the manager
  node's own key (atrest.ts, envelope encryption over X25519) and opened
  ONLY on the manager node. adopt seals the first envelope; refresh opens
  it, calls the Anthropic OAuth token endpoint, re-seals a rotated refresh
  token, and hands the control plane only the access token plus the opaque
  envelope. Also polls licence-grain usage (ADR 0054).
- anthropic-consumer: writes the delivered access token to
  ~/.claude/.credentials.json, access-token-only, atomically (the refresh
  token is never delivered); reports session-grain usage from the CLI
  transcripts; a fail-closed identity guard (expected-uuid plumbing is a
  flagged TODO).

Both run as scheduled containers (ADR 0053). Pure logic covered by
node --test fixtures (at-rest round-trip, credential strip, transcript
sum, refresh merge).

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
2026-09-07 01:00:12 +02:00

33 lines
1.6 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { applyGrant, deliver } from "../credentials.ts";
test("applyGrant strips the refresh token a full grant on disk left behind", () => {
const local = { claudeAiOauth: { accessToken: "at-old", refreshToken: "rt-must-not-survive" } };
const next = applyGrant(local, { accessToken: "at-new", expiresAt: 123 });
assert.equal(next.claudeAiOauth!.accessToken, "at-new");
assert.equal(next.claudeAiOauth!.expiresAt, 123);
assert.ok(!("refreshToken" in next.claudeAiOauth!), "a node held onto a refresh token");
});
test("deliver writes the port-map shape, access-token-only, and never a refresh token", () => {
const dir = mkdtempSync(join(tmpdir(), "anthropic-consumer-"));
const path = join(dir, ".credentials.json");
// A prior interactive login left a full grant on disk.
writeFileSync(path, JSON.stringify({ claudeAiOauth: { accessToken: "at-old", refreshToken: "rt-login" } }));
deliver(path, { accessToken: "at-delivered", expiresAt: 999, subscriptionType: "max" });
const raw = readFileSync(path, "utf8");
const creds = JSON.parse(raw);
assert.equal(creds.claudeAiOauth.accessToken, "at-delivered");
assert.equal(creds.claudeAiOauth.expiresAt, 999);
assert.equal(creds.claudeAiOauth.subscriptionType, "max");
assert.doesNotMatch(raw, /rt-login/, "the refresh token is still on disk");
assert.ok(!("refreshToken" in creds.claudeAiOauth));
});