@cortexkit/anthropic-auth-core 1.22.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +2 -0
  2. package/dist/accounts.d.ts +52 -8
  3. package/dist/cachekeep.d.ts +27 -1
  4. package/dist/cch.d.ts +11 -1
  5. package/dist/claude-code.d.ts +23 -1
  6. package/dist/claustrum-enrollment.d.ts +72 -0
  7. package/dist/claustrum-scoped-roster.d.ts +27 -0
  8. package/dist/claustrum-scoped-runtime.d.ts +31 -0
  9. package/dist/claustrum-scoped.d.ts +53 -0
  10. package/dist/claustrum.d.ts +16 -82
  11. package/dist/commands/account.d.ts +38 -11
  12. package/dist/constants.d.ts +3 -2
  13. package/dist/custom-headers.d.ts +3 -0
  14. package/dist/index.d.ts +50 -0
  15. package/dist/index.js +29700 -31
  16. package/dist/internal-types/LICENSE +21 -0
  17. package/dist/internal-types/commands/builtins.d.ts +71 -0
  18. package/dist/internal-types/commands/index.d.ts +10 -0
  19. package/dist/internal-types/commands/menu.d.ts +61 -0
  20. package/dist/internal-types/commands/model.d.ts +238 -0
  21. package/dist/internal-types/commands/pi.d.ts +23 -0
  22. package/dist/internal-types/commands/seam.d.ts +72 -0
  23. package/dist/internal-types/fs/refresh-file-lock.d.ts +33 -0
  24. package/dist/internal-types/logger/capture-sink.d.ts +14 -0
  25. package/dist/internal-types/logger/engine.d.ts +100 -0
  26. package/dist/internal-types/logger/index.d.ts +6 -0
  27. package/dist/internal-types/logger/redact.d.ts +11 -0
  28. package/dist/internal-types/pi-slot/index.d.ts +3 -0
  29. package/dist/internal-types/pi-slot/slot.d.ts +49 -0
  30. package/dist/internal-types/quota/codec.d.ts +11 -0
  31. package/dist/internal-types/quota/format.d.ts +46 -0
  32. package/dist/internal-types/quota/index.d.ts +10 -0
  33. package/dist/internal-types/quota/map.d.ts +63 -0
  34. package/dist/internal-types/quota/merge.d.ts +48 -0
  35. package/dist/internal-types/quota/projection.d.ts +64 -0
  36. package/dist/internal-types/store/attribution.d.ts +28 -0
  37. package/dist/internal-types/store/errors.d.ts +55 -0
  38. package/dist/internal-types/store/hooks.d.ts +12 -0
  39. package/dist/internal-types/store/identity.d.ts +39 -0
  40. package/dist/internal-types/store/index.d.ts +21 -0
  41. package/dist/internal-types/store/mutate.d.ts +189 -0
  42. package/dist/internal-types/store/pool.d.ts +196 -0
  43. package/dist/internal-types/store/provider-state.d.ts +131 -0
  44. package/dist/internal-types/store/publication.d.ts +47 -0
  45. package/dist/internal-types/store/pull.d.ts +36 -0
  46. package/dist/internal-types/store/refresh-lock.d.ts +63 -0
  47. package/dist/internal-types/store/refresh.d.ts +72 -0
  48. package/dist/internal-types/store/rows.d.ts +313 -0
  49. package/dist/internal-types/store/runtime.d.ts +36 -0
  50. package/dist/internal-types/store/schema.d.ts +443 -0
  51. package/dist/internal-types/store/settings.d.ts +63 -0
  52. package/dist/internal-types/store/torn.d.ts +78 -0
  53. package/dist/migration-source.d.ts +33 -0
  54. package/dist/model-remap.d.ts +27 -0
  55. package/dist/models.d.ts +60 -0
  56. package/dist/native-account-runtime.d.ts +121 -0
  57. package/dist/native-account-view.d.ts +126 -0
  58. package/dist/native-command-effects.d.ts +59 -0
  59. package/dist/native-credential-validation.d.ts +42 -0
  60. package/dist/native-custody-activation.d.ts +45 -0
  61. package/dist/native-custody.d.ts +114 -0
  62. package/dist/native-enrollment-authority.d.ts +2 -0
  63. package/dist/native-host-auth-read.d.ts +3 -0
  64. package/dist/native-host-auth-write.d.ts +51 -0
  65. package/dist/native-host-auth.d.ts +12 -0
  66. package/dist/native-local-credential-service.d.ts +76 -0
  67. package/dist/native-local-runtime-readers.d.ts +22 -0
  68. package/dist/native-lock-observer.d.ts +12 -0
  69. package/dist/native-menu-executor.d.ts +243 -0
  70. package/dist/native-menu-model.d.ts +142 -0
  71. package/dist/native-migration-proof.d.ts +28 -0
  72. package/dist/native-migration-source.d.ts +47 -0
  73. package/dist/native-migration.d.ts +66 -0
  74. package/dist/native-quota-codec.d.ts +32 -0
  75. package/dist/native-refresh-coordinator.d.ts +240 -0
  76. package/dist/native-roster-seed.d.ts +115 -0
  77. package/dist/native-runtime-registry.d.ts +19 -0
  78. package/dist/native-runtime.d.ts +204 -0
  79. package/dist/native-transient-account.d.ts +38 -0
  80. package/dist/native-ui.d.ts +45 -0
  81. package/dist/native-usage-publication.d.ts +11 -0
  82. package/dist/native-vault-admission.d.ts +8 -0
  83. package/dist/native-vault-connection.d.ts +33 -0
  84. package/dist/native-vault-paths.d.ts +13 -0
  85. package/dist/native-vault-runtime.d.ts +102 -0
  86. package/dist/native-vault-seed.d.ts +16 -0
  87. package/dist/oauth-profile.d.ts +2 -1
  88. package/dist/pool-authority.d.ts +159 -0
  89. package/dist/pool-binding.d.ts +32 -0
  90. package/dist/pool-paths.d.ts +21 -0
  91. package/dist/pool-store.d.ts +32 -0
  92. package/dist/prime.d.ts +11 -3
  93. package/dist/provider-error.d.ts +139 -0
  94. package/dist/quota-header-feed.d.ts +13 -0
  95. package/dist/quota-manager.d.ts +30 -5
  96. package/dist/relay.d.ts +22 -1
  97. package/dist/request-history.d.ts +34 -0
  98. package/dist/sse.d.ts +81 -0
  99. package/dist/sticky-routing.d.ts +29 -0
  100. package/package.json +9 -3
  101. package/dist/accounts.js +0 -3330
  102. package/dist/auth.js +0 -182
  103. package/dist/cache1h.js +0 -97
  104. package/dist/cachekeep-registry.js +0 -124
  105. package/dist/cachekeep.js +0 -578
  106. package/dist/cch.js +0 -127
  107. package/dist/claude-code.js +0 -388
  108. package/dist/claustrum.js +0 -529
  109. package/dist/commands/account.js +0 -239
  110. package/dist/constants.js +0 -82
  111. package/dist/dump.js +0 -616
  112. package/dist/fast.js +0 -66
  113. package/dist/json.js +0 -10
  114. package/dist/killswitch.js +0 -132
  115. package/dist/logger.js +0 -286
  116. package/dist/logging.js +0 -59
  117. package/dist/mid-conversation-output-config.js +0 -89
  118. package/dist/models.js +0 -141
  119. package/dist/network-errors.js +0 -27
  120. package/dist/oauth-profile.js +0 -54
  121. package/dist/pkce.js +0 -17
  122. package/dist/prime.js +0 -823
  123. package/dist/provider.js +0 -0
  124. package/dist/quota-header-feed.js +0 -279
  125. package/dist/quota-headers.js +0 -121
  126. package/dist/quota-manager.js +0 -805
  127. package/dist/quotas.js +0 -141
  128. package/dist/relay.js +0 -1243
  129. package/dist/routing.js +0 -94
  130. package/dist/start.js +0 -29
  131. package/dist/sticky-routing.js +0 -523
  132. package/dist/thinking-binding.js +0 -54
  133. package/dist/token-fingerprint.js +0 -8
package/dist/claustrum.js DELETED
@@ -1,529 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { userInfo } from 'node:os';
3
- import { SubcCallError, SubcClient, } from '@cortexkit/subc-client';
4
- import { logger } from './logger';
5
- export function getDefaultClaustrumConnectionPath() {
6
- const uid = process.getuid?.() ?? userInfo().uid;
7
- return `/run/user/${uid}/subc-connection.json`;
8
- }
9
- function isRecord(value) {
10
- return typeof value === 'object' && value !== null && !Array.isArray(value);
11
- }
12
- function isEndpoint(value) {
13
- return (isRecord(value) &&
14
- typeof value.host === 'string' &&
15
- value.host.trim().length > 0 &&
16
- typeof value.port === 'number' &&
17
- Number.isInteger(value.port) &&
18
- value.port > 0 &&
19
- value.port <= 65_535);
20
- }
21
- export async function detectClaustrumConnection(path = getDefaultClaustrumConnectionPath()) {
22
- let raw;
23
- try {
24
- raw = await readFile(path, 'utf8');
25
- }
26
- catch (error) {
27
- const code = error.code;
28
- if (code === 'ENOENT')
29
- return { status: 'absent', path };
30
- return {
31
- status: 'malformed',
32
- path,
33
- reason: `unreadable (${code ?? 'unknown'})`,
34
- };
35
- }
36
- let value;
37
- try {
38
- value = JSON.parse(raw);
39
- }
40
- catch {
41
- return {
42
- status: 'malformed',
43
- path,
44
- reason: 'invalid JSON',
45
- };
46
- }
47
- if (!isRecord(value) ||
48
- typeof value.schema !== 'number' ||
49
- !Number.isFinite(value.schema) ||
50
- typeof value.wire_version !== 'number' ||
51
- !Number.isFinite(value.wire_version) ||
52
- !Array.isArray(value.endpoints) ||
53
- value.endpoints.length === 0 ||
54
- !value.endpoints.every(isEndpoint)) {
55
- return {
56
- status: 'malformed',
57
- path,
58
- reason: 'connection file has an invalid schema, wire_version, or endpoints',
59
- };
60
- }
61
- return {
62
- status: 'available',
63
- schema: value.schema,
64
- wireVersion: value.wire_version,
65
- endpoints: value.endpoints.map((endpoint) => ({
66
- host: endpoint.host,
67
- port: endpoint.port,
68
- })),
69
- };
70
- }
71
- export const CUSTODY_TOMBSTONE_PREFIX = 'claustrum-tombstone:v1:';
72
- export function custodyTombstoneKey(provider) {
73
- return `${CUSTODY_TOMBSTONE_PREFIX}${provider}`;
74
- }
75
- export function isCustodyTombstoneValue(value) {
76
- return typeof value === 'string' && value.startsWith(CUSTODY_TOMBSTONE_PREFIX);
77
- }
78
- export function isCustodyTombstoneOAuth(auth, provider) {
79
- if (!isRecord(auth) || auth.type !== 'oauth')
80
- return false;
81
- const key = custodyTombstoneKey(provider);
82
- return auth.refresh === key && auth.access === key;
83
- }
84
- export class CustodyTombstoneRefreshError extends Error {
85
- provider;
86
- code = 'custody_tombstone_refresh';
87
- constructor(provider) {
88
- super(`${provider} main slot is vault-custodied; local refresh is forbidden — the vault-served main path is not yet implemented`);
89
- this.provider = provider;
90
- this.name = 'CustodyTombstoneRefreshError';
91
- }
92
- }
93
- export function assertNotCustodyTombstone(refreshToken, provider) {
94
- if (isCustodyTombstoneValue(refreshToken)) {
95
- throw new CustodyTombstoneRefreshError(provider);
96
- }
97
- }
98
- const CUSTODY_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
99
- // The suffix is base64url for 256 CSPRNG bits; its charset is not fixture-derived.
100
- const CUSTODY_HANDLE_PATTERN = /^ckh_[A-Za-z0-9_-]{43}$/;
101
- const RESERVED_CUSTODY_IDS = new Set(['__proto__', 'constructor', 'prototype']);
102
- function isCustodyId(value) {
103
- return (typeof value === 'string' &&
104
- CUSTODY_ID_PATTERN.test(value) &&
105
- !RESERVED_CUSTODY_IDS.has(value));
106
- }
107
- export function isValidCustodyHandle(value) {
108
- return typeof value === 'string' && CUSTODY_HANDLE_PATTERN.test(value);
109
- }
110
- export function readCustodyHandles(json, provider) {
111
- if (!isCustodyId(provider)) {
112
- throw new Error(`Invalid custody provider id ${provider}`);
113
- }
114
- const providers = isRecord(json) && Array.isArray(json.providers) ? json.providers : [];
115
- const source = providers.find((entry) => isRecord(entry) &&
116
- Object.hasOwn(entry, 'provider') &&
117
- entry.provider === provider);
118
- if (!source || !Array.isArray(source.accounts)) {
119
- throw new Error(`Missing custody handles for provider ${provider}`);
120
- }
121
- return {
122
- provider: String(source.provider),
123
- serve: String(source.serve),
124
- shape: String(source.shape),
125
- accounts: source.accounts.flatMap((entry) => {
126
- if (!isRecord(entry))
127
- return [];
128
- if (!Object.hasOwn(entry, 'label') ||
129
- !Object.hasOwn(entry, 'handle') ||
130
- !Object.hasOwn(entry, 'credential_id') ||
131
- typeof entry.label !== 'string' ||
132
- typeof entry.handle !== 'string' ||
133
- !isCustodyId(entry.label) ||
134
- !isValidCustodyHandle(entry.handle) ||
135
- typeof entry.credential_id !== 'string')
136
- return [];
137
- return [
138
- {
139
- label: entry.label,
140
- handle: entry.handle,
141
- credentialId: entry.credential_id,
142
- },
143
- ];
144
- }),
145
- };
146
- }
147
- export class ClaustrumClient {
148
- #client;
149
- #connector;
150
- #connectionFile;
151
- #handshakeTimeoutMs;
152
- #reconnecting = null;
153
- #nextReconnectAt = 0;
154
- #closed = false;
155
- constructor(client, connector, connectionFile, handshakeTimeoutMs) {
156
- this.#client = client;
157
- this.#connector = connector;
158
- this.#connectionFile = connectionFile;
159
- this.#handshakeTimeoutMs = handshakeTimeoutMs;
160
- }
161
- static async connect(options = {}) {
162
- const connectionFile = options.connectionFile ?? getDefaultClaustrumConnectionPath();
163
- const connector = options.connector ??
164
- ((connectOptions) => SubcClient.connect(connectOptions));
165
- const client = await connector({
166
- connectionFile,
167
- handshakeTimeoutMs: options.handshakeTimeoutMs,
168
- });
169
- return new ClaustrumClient(client, connector, connectionFile, options.handshakeTimeoutMs);
170
- }
171
- async catalogList(moduleId) {
172
- return this.#client.catalogList(moduleId);
173
- }
174
- async routeOpen(target, identity, options = {}) {
175
- // The host process inherits aft's supervised-spawn environment; null is the
176
- // library contract that omits that identity instead of impersonating aft.
177
- return this.#client.routeOpen(target, identity, {
178
- ...options,
179
- consumerIdentity: null,
180
- });
181
- }
182
- async request(handle, body, options = {}) {
183
- return this.#client.request(handle, body, options);
184
- }
185
- async call(moduleId, method, params, options = {}) {
186
- try {
187
- return await this.#client.call(moduleId, method, params, {
188
- ...options,
189
- consumerIdentity: null,
190
- });
191
- }
192
- catch (error) {
193
- if (!this.#shouldReconnect(error))
194
- throw error;
195
- await this.#reconnect();
196
- return this.#client.call(moduleId, method, params, {
197
- ...options,
198
- consumerIdentity: null,
199
- });
200
- }
201
- }
202
- subscribe(handle, body, onEvent, options = {}) {
203
- return this.#client.subscribe(handle, body, onEvent, options);
204
- }
205
- async closeRoute(handle, options = {}) {
206
- return this.#client.closeRoute(handle, options);
207
- }
208
- async closeManagedRoute(target, identity, options = {}) {
209
- return this.#client.closeManagedRoute(target, identity, {
210
- ...options,
211
- consumerIdentity: null,
212
- });
213
- }
214
- close() {
215
- this.#closed = true;
216
- this.#client.close();
217
- }
218
- #shouldReconnect(error) {
219
- return (!this.#closed &&
220
- error instanceof SubcCallError &&
221
- error.kind === 'terminal' &&
222
- error.code !== 'missing_identity' &&
223
- error.code !== 'invalid_control_body');
224
- }
225
- async #reconnect() {
226
- if (this.#closed)
227
- throw new Error('Claustrum client is closed');
228
- if (this.#reconnecting) {
229
- await this.#reconnecting;
230
- return;
231
- }
232
- const now = Date.now();
233
- if (now < this.#nextReconnectAt) {
234
- throw new Error('Claustrum client reconnect is backed off');
235
- }
236
- this.#nextReconnectAt = now + CLAUSTRUM_CREDENTIAL_REFRESH_BACKOFF_MS;
237
- this.#reconnecting = this.#connector({
238
- connectionFile: this.#connectionFile,
239
- handshakeTimeoutMs: this.#handshakeTimeoutMs,
240
- })
241
- .then((client) => {
242
- if (this.#closed) {
243
- client.close();
244
- throw new Error('Claustrum client is closed');
245
- }
246
- const previous = this.#client;
247
- this.#client = client;
248
- previous.close();
249
- })
250
- .finally(() => {
251
- this.#reconnecting = null;
252
- });
253
- await this.#reconnecting;
254
- }
255
- }
256
- export function connectClaustrumClient(options = {}) {
257
- return ClaustrumClient.connect(options);
258
- }
259
- export const CLAUSTRUM_MODULE_ID = 'claustrum';
260
- export const DEFAULT_CLAUSTRUM_CREDENTIAL_MIN_TTL_MS = 120_000;
261
- const CLAUSTRUM_CREDENTIAL_REFRESH_BACKOFF_MS = 60_000;
262
- export const ERROR_CLASS_WIRE_SET = [
263
- 'transient',
264
- 'permanent',
265
- 'auth_required',
266
- 'context_overflow',
267
- ];
268
- export class ClaustrumCredentialError extends Error {
269
- code;
270
- action;
271
- errorClass;
272
- constructor(message, code, errorClass, action) {
273
- super(message);
274
- this.code = code;
275
- this.action = action;
276
- this.name = 'ClaustrumCredentialError';
277
- this.errorClass = errorClass;
278
- }
279
- }
280
- function credentialErrorAction(errorClass) {
281
- switch (errorClass) {
282
- case 'permanent':
283
- return 'gone';
284
- case 'auth_required':
285
- return 'reauth';
286
- case 'context_overflow':
287
- return 'reduce_and_retry';
288
- case 'transient':
289
- return 'retry';
290
- }
291
- }
292
- function asCredentialError(response, fallbackCode = 'invalid_response') {
293
- const result = isRecord(response) && isRecord(response.result)
294
- ? response.result
295
- : undefined;
296
- const error = result && isRecord(result.error) ? result.error : undefined;
297
- const rawErrorClass = error?.class;
298
- const errorClass = typeof rawErrorClass === 'string' &&
299
- ERROR_CLASS_WIRE_SET.includes(rawErrorClass)
300
- ? rawErrorClass
301
- : 'transient';
302
- if (typeof rawErrorClass !== 'string' ||
303
- !ERROR_CLASS_WIRE_SET.includes(rawErrorClass)) {
304
- logger.warn('claustrum', 'unrecognised credential error class', {
305
- errorClass: rawErrorClass ?? null,
306
- });
307
- }
308
- const code = error && typeof error.code === 'string' ? error.code : fallbackCode;
309
- return new ClaustrumCredentialError(`Claustrum credential request failed: ${code}`, code, errorClass, credentialErrorAction(errorClass));
310
- }
311
- function asCredentialCallError(error) {
312
- if (error instanceof ClaustrumCredentialError) {
313
- return error;
314
- }
315
- if (error instanceof SubcCallError && error.kind === 'terminal') {
316
- logger.warn('claustrum', 'terminal credential call failed', {
317
- code: error.code ?? null,
318
- message: error.message,
319
- });
320
- return new ClaustrumCredentialError(`Claustrum credential request failed: ${error.message}`, error.code ?? 'terminal_error', 'transient', 'retry');
321
- }
322
- const message = error instanceof Error ? error.message : String(error);
323
- const code = isRecord(error) && typeof error.code === 'string'
324
- ? error.code
325
- : 'transport_error';
326
- return new ClaustrumCredentialError(`Claustrum credential request failed: ${message}`, code, 'transient', 'retry');
327
- }
328
- function decodeCredentialGetResponse(response) {
329
- const result = isRecord(response) && isRecord(response.result)
330
- ? response.result
331
- : undefined;
332
- if (result && isRecord(result.error)) {
333
- throw asCredentialError(response);
334
- }
335
- const payload = result?.payload;
336
- if (!Array.isArray(payload) ||
337
- payload.length === 0 ||
338
- !payload.every((value) => typeof value === 'number' &&
339
- Number.isInteger(value) &&
340
- value >= 0 &&
341
- value <= 255)) {
342
- throw asCredentialError(response);
343
- }
344
- const recordVersion = result?.record_version;
345
- if (typeof recordVersion !== 'number' ||
346
- !Number.isSafeInteger(recordVersion) ||
347
- recordVersion < 0) {
348
- throw asCredentialError(response, 'invalid_record_version');
349
- }
350
- const rawExpiresAtMs = result?.expires_at_ms;
351
- const expiresAtMs = rawExpiresAtMs === null || rawExpiresAtMs === undefined
352
- ? null
353
- : typeof rawExpiresAtMs === 'number' && Number.isFinite(rawExpiresAtMs)
354
- ? rawExpiresAtMs
355
- : undefined;
356
- if (expiresAtMs === undefined) {
357
- throw asCredentialError(response, 'invalid_expiry');
358
- }
359
- const decoded = new TextDecoder().decode(Uint8Array.from(payload));
360
- return {
361
- payload: decoded,
362
- expiresAtMs,
363
- recordVersion,
364
- ...(typeof result?.project_id === 'string' && {
365
- projectId: result.project_id,
366
- }),
367
- ...(typeof result?.account_id === 'string' && {
368
- accountId: result.account_id,
369
- }),
370
- };
371
- }
372
- export class ClaustrumCredentialCache {
373
- #cache = new Map();
374
- #inFlight = new Map();
375
- #client;
376
- #identity;
377
- #now;
378
- #refreshBackoffUntil = new Map();
379
- #minTtlMs;
380
- constructor(client, options = {}) {
381
- this.#client = client;
382
- this.#identity = options.identity;
383
- this.#now = options.now ?? Date.now;
384
- this.#minTtlMs = options.minTtlMs ?? DEFAULT_CLAUSTRUM_CREDENTIAL_MIN_TTL_MS;
385
- if (!Number.isSafeInteger(this.#minTtlMs) || this.#minTtlMs < 0) {
386
- throw new RangeError('minTtlMs must be a non-negative safe integer');
387
- }
388
- }
389
- async get(handle, minTtlMs = this.#minTtlMs) {
390
- if (!Number.isSafeInteger(minTtlMs) || minTtlMs < 0) {
391
- throw new RangeError('minTtlMs must be a non-negative safe integer');
392
- }
393
- const now = this.#now();
394
- const cached = this.#cache.get(handle);
395
- if (cached && cached.expiresAtMs !== null && cached.expiresAtMs > now) {
396
- if (cached.expiresAtMs - now <= minTtlMs) {
397
- this.#refreshIfApproachingExpiry(handle, now, minTtlMs);
398
- }
399
- return cached;
400
- }
401
- if (cached) {
402
- this.#cache.delete(handle);
403
- this.#refreshBackoffUntil.delete(handle);
404
- }
405
- const pending = this.#inFlight.get(handle);
406
- if (pending)
407
- return pending;
408
- const load = this.#load(handle, minTtlMs);
409
- this.#inFlight.set(handle, load);
410
- try {
411
- return await load;
412
- }
413
- finally {
414
- if (this.#inFlight.get(handle) === load)
415
- this.#inFlight.delete(handle);
416
- }
417
- }
418
- peek(handle) {
419
- return this.#cache.get(handle);
420
- }
421
- seedForTest(handle, credential) {
422
- this.#cache.set(handle, credential);
423
- }
424
- reduceMinTtlMs() {
425
- this.#minTtlMs = Math.floor(this.#minTtlMs / 2);
426
- return this.#minTtlMs;
427
- }
428
- async reportAuthFailure(handle, providerStatusOrServedCredential, servedCredentialOrStatus, reporterSource) {
429
- const providerStatus = typeof providerStatusOrServedCredential === 'number'
430
- ? providerStatusOrServedCredential
431
- : typeof servedCredentialOrStatus === 'number'
432
- ? servedCredentialOrStatus
433
- : 401;
434
- const servedCredential = typeof providerStatusOrServedCredential === 'number'
435
- ? typeof servedCredentialOrStatus === 'object' &&
436
- servedCredentialOrStatus !== null
437
- ? servedCredentialOrStatus
438
- : undefined
439
- : providerStatusOrServedCredential;
440
- const recordVersion = servedCredential?.recordVersion;
441
- if (typeof recordVersion !== 'number' ||
442
- !Number.isSafeInteger(recordVersion) ||
443
- recordVersion < 0) {
444
- throw new TypeError('record_version is required from the credential served to the provider');
445
- }
446
- try {
447
- let response;
448
- try {
449
- response = await this.#client.call(CLAUSTRUM_MODULE_ID, 'credential.report_auth_failure', {
450
- handle,
451
- provider_status: providerStatus,
452
- record_version: recordVersion,
453
- ...(reporterSource ? { reporter_source: reporterSource } : {}),
454
- }, { identity: this.#identity });
455
- }
456
- catch (error) {
457
- throw asCredentialCallError(error);
458
- }
459
- const result = isRecord(response) && isRecord(response.result)
460
- ? response.result
461
- : undefined;
462
- if (result && isRecord(result.error)) {
463
- throw asCredentialError(response);
464
- }
465
- }
466
- finally {
467
- this.invalidate(handle, recordVersion);
468
- }
469
- }
470
- invalidate(handle, recordVersion) {
471
- const cached = this.#cache.get(handle);
472
- if (cached &&
473
- (recordVersion === undefined || cached.recordVersion === recordVersion)) {
474
- this.#cache.delete(handle);
475
- }
476
- }
477
- close() {
478
- this.#client.close();
479
- }
480
- #refreshIfApproachingExpiry(handle, now, minTtlMs) {
481
- if (this.#inFlight.has(handle))
482
- return;
483
- const retryAt = this.#refreshBackoffUntil.get(handle);
484
- if (retryAt !== undefined && retryAt > now)
485
- return;
486
- this.#refreshBackoffUntil.set(handle, now + CLAUSTRUM_CREDENTIAL_REFRESH_BACKOFF_MS);
487
- const load = this.#load(handle, minTtlMs);
488
- this.#inFlight.set(handle, load);
489
- void load
490
- .catch(() => { })
491
- .finally(() => {
492
- if (this.#inFlight.get(handle) === load)
493
- this.#inFlight.delete(handle);
494
- });
495
- }
496
- async #load(handle, minTtlMs) {
497
- let response;
498
- try {
499
- response = await this.#client.call(CLAUSTRUM_MODULE_ID, 'credential.get', {
500
- handle,
501
- force_refresh: false,
502
- min_ttl_ms: minTtlMs,
503
- }, { identity: this.#identity });
504
- }
505
- catch (error) {
506
- throw asCredentialCallError(error);
507
- }
508
- const result = decodeCredentialGetResponse(response);
509
- const credential = {
510
- payload: result.payload,
511
- expiresAtMs: result.expiresAtMs,
512
- recordVersion: result.recordVersion,
513
- ...(result.projectId !== undefined && { projectId: result.projectId }),
514
- ...(result.accountId !== undefined && { accountId: result.accountId }),
515
- };
516
- if (credential.expiresAtMs !== null &&
517
- credential.expiresAtMs > this.#now()) {
518
- this.#cache.set(handle, credential);
519
- }
520
- return credential;
521
- }
522
- }
523
- export async function connectClaustrumCredentialCache(options = {}) {
524
- if (options.enabled !== true)
525
- return null;
526
- const { enabled: _enabled, identity, now, minTtlMs, ...clientOptions } = options;
527
- const client = await connectClaustrumClient(clientOptions);
528
- return new ClaustrumCredentialCache(client, { identity, now, minTtlMs });
529
- }