Files
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

49 lines
1.8 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { foldTranscript } from "../transcript.ts";
// A captured-shape transcript: two assistant turns and a user line, exactly the fields the port map
// names. Not imagined — the field names match the mature implementation's parse.
const TRANSCRIPT = [
JSON.stringify({ type: "user", timestamp: "2026-01-01T00:00:00Z", cwd: "/work/app", gitBranch: "main" }),
JSON.stringify({
type: "assistant",
timestamp: "2026-01-01T00:00:01Z",
costUSD: 0.01,
message: {
model: "claude-opus-4-8",
usage: { input_tokens: 100, cache_creation_input_tokens: 20, cache_read_input_tokens: 5, output_tokens: 40 },
},
}),
JSON.stringify({
type: "assistant",
timestamp: "2026-01-01T00:00:02Z",
costUSD: 0.02,
message: { model: "claude-opus-4-8", usage: { input_tokens: 200, output_tokens: 60 } },
}),
"", // a half-written trailing line is ordinary and must not be fatal.
].join("\n");
test("a transcript sums per-session token counts, cost, and metadata", () => {
const s = foldTranscript("session-abc", TRANSCRIPT);
assert.equal(s.sessionId, "session-abc");
assert.equal(s.turns, 2);
assert.equal(s.inputTokens, 300);
assert.equal(s.cacheCreationTokens, 20);
assert.equal(s.cacheReadTokens, 5);
assert.equal(s.outputTokens, 100);
assert.equal(Math.round(s.costUSD * 100) / 100, 0.03);
assert.equal(s.model, "claude-opus-4-8");
assert.equal(s.gitBranch, "main");
assert.equal(s.cwd, "/work/app");
assert.equal(s.startedAt, "2026-01-01T00:00:00Z");
assert.equal(s.lastActive, "2026-01-01T00:00:02Z");
});
test("a malformed line is skipped, not fatal", () => {
const s = foldTranscript("s", 'not json\n{"type":"assistant","message":{"usage":{"output_tokens":7}}}');
assert.equal(s.outputTokens, 7);
assert.equal(s.turns, 1);
});