@modelprofile.com/authswitch 6.2.0 → 6.4.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 (50) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/authority-contract.d.ts +142 -0
  3. package/dist_ts/authority-contract.js +3 -0
  4. package/dist_ts/authority-runtime-contract.d.ts +32 -0
  5. package/dist_ts/authority-runtime-contract.js +2 -0
  6. package/dist_ts/classes.authoritybroker.d.ts +73 -0
  7. package/dist_ts/classes.authoritybroker.js +548 -0
  8. package/dist_ts/classes.authorityclient.d.ts +34 -0
  9. package/dist_ts/classes.authorityclient.js +200 -0
  10. package/dist_ts/classes.authoritydaemon.d.ts +26 -0
  11. package/dist_ts/classes.authoritydaemon.js +249 -0
  12. package/dist_ts/classes.authoritydatabase.d.ts +94 -0
  13. package/dist_ts/classes.authoritydatabase.js +736 -0
  14. package/dist_ts/classes.authorityframing.d.ts +8 -0
  15. package/dist_ts/classes.authorityframing.js +22 -0
  16. package/dist_ts/classes.authoritymodels.d.ts +215 -0
  17. package/dist_ts/classes.authoritymodels.js +818 -0
  18. package/dist_ts/classes.authoritysecrets.d.ts +9 -0
  19. package/dist_ts/classes.authoritysecrets.js +30 -0
  20. package/dist_ts/classes.authorityservice.d.ts +28 -0
  21. package/dist_ts/classes.authorityservice.js +71 -0
  22. package/dist_ts/classes.cli.d.ts +56 -0
  23. package/dist_ts/classes.cli.js +238 -63
  24. package/dist_ts/classes.codexpreuse.js +2 -2
  25. package/dist_ts/classes.tui.js +51 -2
  26. package/dist_ts/index.d.ts +2 -0
  27. package/dist_ts/index.js +26 -1
  28. package/dist_ts/plugins.d.ts +9 -2
  29. package/dist_ts/plugins.js +10 -3
  30. package/dist_ts/preuse.d.ts +89 -2
  31. package/dist_ts/preuse.js +107 -2
  32. package/package.json +17 -3
  33. package/readme.md +118 -16
  34. package/ts/00_commitinfo_data.ts +1 -1
  35. package/ts/authority-contract.ts +109 -0
  36. package/ts/authority-runtime-contract.ts +27 -0
  37. package/ts/classes.authoritybroker.ts +530 -0
  38. package/ts/classes.authorityclient.ts +183 -0
  39. package/ts/classes.authoritydaemon.ts +219 -0
  40. package/ts/classes.authoritydatabase.ts +725 -0
  41. package/ts/classes.authorityframing.ts +21 -0
  42. package/ts/classes.authoritymodels.ts +367 -0
  43. package/ts/classes.authoritysecrets.ts +27 -0
  44. package/ts/classes.authorityservice.ts +83 -0
  45. package/ts/classes.cli.ts +236 -54
  46. package/ts/classes.codexpreuse.ts +1 -1
  47. package/ts/classes.tui.ts +39 -2
  48. package/ts/index.ts +25 -0
  49. package/ts/plugins.ts +9 -2
  50. package/ts/preuse.ts +141 -3
@@ -0,0 +1,548 @@
1
+ import * as plugins from './plugins.js';
2
+ import { AuthSwitchAuthorityDatabase } from './classes.authoritydatabase.js';
3
+ import { AuthSwitchTpmSecretCodec } from './classes.authoritysecrets.js';
4
+ const idHash = (...values) => plugins.crypto.createHash('sha256').update(JSON.stringify(values)).digest('hex');
5
+ const isId = (value) => typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
6
+ const isUuid = (value) => typeof value === 'string' && /^[a-f0-9-]{36}$/.test(value);
7
+ const safeLabel = (value) => typeof value === 'string' && value.trim() === value
8
+ && value.length > 0 && value.length <= 128 && !/[\u0000-\u001f\u007f]/.test(value);
9
+ const safeScope = (value, maximum) => typeof value === 'string'
10
+ && value.length > 0 && value.length <= maximum && !/[\u0000-\u001f\u007f]/.test(value);
11
+ const validRevision = (value) => Number.isSafeInteger(value) && Number(value) >= 0;
12
+ const tokenExpiry = (credential) => {
13
+ try {
14
+ return plugins.flexAuth.parseOpenAiChatGptTokenInfo(credential.accessToken).expiresAt ?? null;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ };
20
+ const openAiGrantId = (accountId) => idHash('authswitch-grant-v1', accountId, 'openai_managed', 'chatgpt');
21
+ const publicAccount = (account, grant) => ({
22
+ id: account.id, providerId: account.providerId, label: account.label, email: account.email,
23
+ plan: account.plan, health: account.removed ? 'removed'
24
+ : grant?.state === 'exchange_may_have_been_sent' ? 'refreshing' : grant?.state ?? 'needs_reauth',
25
+ owner: grant?.owner ?? 'none', grantGeneration: grant?.grantGeneration ?? 0, revision: account.revision,
26
+ accessExpiresAt: grant?.accessExpiresAt ?? null, retryAt: grant?.retryAt ?? null, problem: grant?.problem ?? 'none',
27
+ statusObservedAt: account.statusObservedAt,
28
+ });
29
+ const publicBinding = (binding) => ({
30
+ id: binding.id, accountId: binding.accountId, runtime: binding.runtime,
31
+ scopeId: binding.scopeId, incarnationId: binding.incarnationId, revision: binding.revision,
32
+ });
33
+ /** One daemon-owned authority. No management DTO contains a refresh grant. */
34
+ export class AuthSwitchAuthorityBroker {
35
+ database;
36
+ provider;
37
+ secrets;
38
+ now;
39
+ proactive;
40
+ operations = new Map();
41
+ refreshes = new Map();
42
+ listeners = new Set();
43
+ timer;
44
+ closed = false;
45
+ constructor(database, options = {}) {
46
+ this.database = database;
47
+ this.provider = options.provider ?? new plugins.flexAccounts.OpenAiProviderAdapter();
48
+ this.secrets = options.secrets ?? new AuthSwitchTpmSecretCodec();
49
+ this.now = options.now ?? Date.now;
50
+ this.proactive = options.proactive ?? true;
51
+ }
52
+ async start() {
53
+ const probe = plugins.crypto.randomBytes(32);
54
+ const probeId = idHash('authswitch-custody-probe-v1');
55
+ try {
56
+ const sealed = await this.secrets.seal(probeId, probe);
57
+ const opened = await this.secrets.unseal(probeId, sealed);
58
+ try {
59
+ if (opened.length !== probe.length || !plugins.crypto.timingSafeEqual(opened, probe)) {
60
+ throw new Error('Authswitch secret custody self-check failed.');
61
+ }
62
+ }
63
+ finally {
64
+ opened.fill(0);
65
+ }
66
+ }
67
+ finally {
68
+ probe.fill(0);
69
+ }
70
+ let after = null;
71
+ while (true) {
72
+ const page = await this.database.grantsByState('exchange_may_have_been_sent', after);
73
+ if (!page.length)
74
+ break;
75
+ for (const grant of page) {
76
+ const updateId = plugins.crypto.randomUUID();
77
+ await this.database.changeGrant(updateId, grant.id, current => {
78
+ if (!current || current.state !== 'exchange_may_have_been_sent')
79
+ throw new Error('Refresh recovery changed concurrently.');
80
+ return { ...current, state: 'needs_reauth', attemptId: null, problem: 'exchange_uncertain',
81
+ revision: current.revision + 1, statusObservedAt: new Date(this.now()).toISOString(), updateId };
82
+ });
83
+ this.publish();
84
+ }
85
+ after = page.at(-1).id;
86
+ }
87
+ if (this.proactive)
88
+ this.schedule();
89
+ }
90
+ schedule() {
91
+ if (this.closed)
92
+ return;
93
+ this.timer = setTimeout(() => {
94
+ void this.refreshDueAccounts().catch(() => {
95
+ process.stderr.write('Authswitch proactive refresh scan failed; account status may be stale.\n');
96
+ }).finally(() => this.schedule());
97
+ }, 30_000);
98
+ this.timer.unref();
99
+ }
100
+ async refreshDueAccounts() {
101
+ if (this.closed)
102
+ return;
103
+ for (const state of ['ready', 'retry_wait']) {
104
+ let after = null;
105
+ while (true) {
106
+ const page = await this.database.grantsByState(state, after);
107
+ if (!page.length)
108
+ break;
109
+ await Promise.allSettled(page.filter(grant => grant.purpose === 'openai_managed'
110
+ && grant.owner === 'daemon' && this.isDue(grant, 0)
111
+ && (grant.state !== 'retry_wait' || (grant.retryAt !== null && Date.parse(grant.retryAt) <= this.now())))
112
+ .map(grant => this.refreshAccount(grant.accountId)));
113
+ after = page.at(-1).id;
114
+ }
115
+ }
116
+ }
117
+ isDue(grant, minValidityMs) {
118
+ const expires = grant.accessExpiresAt === null ? NaN : Date.parse(grant.accessExpiresAt);
119
+ return !Number.isFinite(expires) || expires <= this.now() + Math.max(minValidityMs, 0) + 300_000;
120
+ }
121
+ publish() {
122
+ for (const listener of this.listeners)
123
+ listener();
124
+ }
125
+ async snapshot(options = {}) {
126
+ if ((options.accountAfter !== undefined && !isId(options.accountAfter))
127
+ || (options.bindingAfter !== undefined && !isId(options.bindingAfter)))
128
+ throw new Error('Invalid account snapshot cursor.');
129
+ const page = await this.database.page(options.accountAfter ?? null, options.bindingAfter ?? null, options.limit ?? 128);
130
+ return { schemaVersion: 1, epoch: page.meta.epoch, revision: page.meta.revision,
131
+ generatedAt: new Date(this.now()).toISOString(),
132
+ accounts: page.accounts.filter(item => !item.account.removed)
133
+ .map(item => publicAccount(item.account, item.grant)),
134
+ bindings: page.bindings.map(publicBinding),
135
+ nextAccountCursor: page.nextAccountCursor, nextBindingCursor: page.nextBindingCursor };
136
+ }
137
+ async events(epoch, afterRevision, waitMs, signal) {
138
+ if (!isUuid(epoch) || !validRevision(afterRevision) || !Number.isSafeInteger(waitMs) || waitMs < 0 || waitMs > 30_000) {
139
+ throw new Error('Invalid account event cursor.');
140
+ }
141
+ const inspect = async () => {
142
+ const meta = await this.database.readMeta();
143
+ const resyncRequired = epoch !== meta.epoch || afterRevision > meta.revision;
144
+ const persisted = resyncRequired ? [] : await this.database.eventsAfter(afterRevision);
145
+ if (!resyncRequired && afterRevision < meta.revision
146
+ && (persisted.length === 0 || persisted.some((item, index) => item.revision !== afterRevision + index + 1))) {
147
+ return { epoch: meta.epoch, revision: meta.revision, resyncRequired: true, events: [] };
148
+ }
149
+ const events = persisted.map(item => ({ epoch: item.epoch, revision: item.revision, kind: item.kind, accountId: item.accountId }));
150
+ const revision = events.at(-1)?.revision ?? meta.revision;
151
+ return { epoch: meta.epoch, revision, resyncRequired, events };
152
+ };
153
+ const immediate = await inspect();
154
+ if (immediate.resyncRequired || immediate.events.length || waitMs === 0 || this.closed || signal?.aborted)
155
+ return immediate;
156
+ return new Promise((resolve, reject) => {
157
+ let finished = false;
158
+ const fail = (error) => {
159
+ if (finished)
160
+ return;
161
+ finished = true;
162
+ clearTimeout(timer);
163
+ this.listeners.delete(wake);
164
+ signal?.removeEventListener('abort', wake);
165
+ reject(error);
166
+ };
167
+ const wake = () => {
168
+ if (finished)
169
+ return;
170
+ finished = true;
171
+ clearTimeout(timer);
172
+ this.listeners.delete(wake);
173
+ signal?.removeEventListener('abort', wake);
174
+ void inspect().then(resolve, reject);
175
+ };
176
+ const timer = setTimeout(wake, waitMs);
177
+ this.listeners.add(wake);
178
+ signal?.addEventListener('abort', wake, { once: true });
179
+ // Close the read/register race without holding a database session for the wait.
180
+ void inspect().then(result => { if (result.resyncRequired || result.events.length)
181
+ wake(); }, fail);
182
+ });
183
+ }
184
+ identity(credential) {
185
+ const token = plugins.flexAuth.parseOpenAiChatGptTokenInfo(credential.idToken);
186
+ const subject = token.chatgptUserId;
187
+ const workspaceId = token.chatgptAccountId;
188
+ if (!subject || !workspaceId)
189
+ throw new Error('OpenAI login omitted a stable user or account identity.');
190
+ return { id: idHash('authswitch-account-v1', 'openai', subject, workspaceId), subject, workspaceId,
191
+ email: token.email?.toLowerCase() ?? null, plan: token.chatgptPlanType ?? null };
192
+ }
193
+ async sealCredential(grantId, credential) {
194
+ const bytes = Buffer.from(JSON.stringify(credential), 'utf8');
195
+ try {
196
+ return await this.secrets.seal(grantId, bytes);
197
+ }
198
+ finally {
199
+ bytes.fill(0);
200
+ }
201
+ }
202
+ async unsealCredential(account, grant) {
203
+ if (!grant.ciphertext || grant.owner !== 'daemon' || grant.purpose !== 'openai_managed'
204
+ || grant.accountId !== account.id)
205
+ throw new Error('Account has no daemon-owned credential.');
206
+ const bytes = await this.secrets.unseal(grant.id, grant.ciphertext);
207
+ try {
208
+ const value = JSON.parse(Buffer.from(bytes).toString('utf8'));
209
+ if (!value || typeof value !== 'object')
210
+ throw new Error();
211
+ const record = value;
212
+ if (record.kind !== 'chatgptOAuth' || record.providerId !== 'openai'
213
+ || typeof record.accessToken !== 'string' || typeof record.refreshToken !== 'string'
214
+ || typeof record.idToken !== 'string')
215
+ throw new Error();
216
+ const credential = value;
217
+ if (this.identity(credential).id !== account.id)
218
+ throw new Error();
219
+ this.provider.inspectCredential(credential);
220
+ return credential;
221
+ }
222
+ catch {
223
+ throw new Error('Stored account credential is invalid or belongs to another account.');
224
+ }
225
+ finally {
226
+ bytes.fill(0);
227
+ }
228
+ }
229
+ async beginAddOpenAi() { return this.beginLogin(null); }
230
+ async beginReauthOpenAi(accountId) {
231
+ if (!isId(accountId))
232
+ throw new Error('Invalid account ID.');
233
+ const { account, grant } = await this.database.readAccountAndPrimaryGrant(accountId);
234
+ if (!account || account.removed || account.providerId !== 'openai')
235
+ throw new Error('OpenAI account was not found.');
236
+ if (grant?.owner === 'legacy_native')
237
+ throw new Error('Stop the legacy native owner before reauthenticating this account.');
238
+ return this.beginLogin(accountId);
239
+ }
240
+ async beginLogin(targetId) {
241
+ if (this.closed)
242
+ throw new Error('Authswitch authority is closing.');
243
+ this.pruneOperations();
244
+ if ([...this.operations.values()].filter(item => item.public.state === 'pending').length >= 32) {
245
+ throw new Error('Too many pending device logins.');
246
+ }
247
+ const handle = await this.provider.beginLogin({ flow: 'device' });
248
+ if (handle.prompt.flow !== 'device') {
249
+ await handle.close();
250
+ throw new Error('Provider did not start a device login.');
251
+ }
252
+ const publicOperation = { id: plugins.crypto.randomUUID(), state: 'pending',
253
+ prompt: { flow: 'device', verificationUrl: handle.prompt.verificationUrl, userCode: handle.prompt.userCode },
254
+ account: null, error: null };
255
+ const operation = { public: publicOperation, handle, task: Promise.resolve(),
256
+ cancelled: false, committing: false, finishedAt: null };
257
+ this.operations.set(publicOperation.id, operation);
258
+ operation.task = handle.completion.then(async (result) => {
259
+ if (operation.cancelled || this.closed)
260
+ return;
261
+ operation.committing = true;
262
+ const identity = this.identity(result.credential);
263
+ if (targetId !== null && identity.id !== targetId)
264
+ throw new Error('The device login selected a different OpenAI account.');
265
+ const grantId = openAiGrantId(identity.id);
266
+ const ciphertext = await this.sealCredential(grantId, result.credential);
267
+ if (operation.cancelled || this.closed)
268
+ return;
269
+ const updateId = plugins.crypto.randomUUID();
270
+ const updated = await this.database.changeAccountAndGrant(updateId, identity.id, grantId, (existing, oldGrant) => {
271
+ if (targetId === null && existing && !existing.removed)
272
+ throw new Error('Account already exists; reauthenticate that account instead.');
273
+ if (targetId !== null && (!existing || existing.removed))
274
+ throw new Error('Target account was removed during login.');
275
+ if (oldGrant?.owner === 'legacy_native')
276
+ throw new Error('The legacy native owner still holds this grant.');
277
+ const now = new Date(this.now()).toISOString();
278
+ const account = existing
279
+ ? { ...existing, label: existing.label || identity.email || `OpenAI ${identity.workspaceId}`,
280
+ email: identity.email, plan: identity.plan, primaryGrantId: grantId, removed: false,
281
+ revision: existing.revision + 1, statusObservedAt: now, updateId }
282
+ : { id: identity.id, providerId: 'openai', issuer: 'openai', subject: identity.subject,
283
+ workspaceId: identity.workspaceId, label: identity.email ?? `OpenAI ${identity.workspaceId}`,
284
+ email: identity.email, plan: identity.plan, primaryGrantId: grantId, removed: false,
285
+ revision: 1, statusObservedAt: now, updateId };
286
+ const grant = oldGrant
287
+ ? { ...oldGrant, state: 'ready', owner: 'daemon', ciphertext,
288
+ grantGeneration: oldGrant.grantGeneration + 1,
289
+ authorizationGeneration: oldGrant.authorizationGeneration + 1,
290
+ revision: oldGrant.revision + 1, accessExpiresAt: tokenExpiry(result.credential),
291
+ attemptId: null, retryAt: null, retryCount: 0, problem: 'none', statusObservedAt: now, updateId }
292
+ : { id: grantId, accountId: identity.id, providerId: 'openai', purpose: 'openai_managed',
293
+ audience: 'chatgpt', state: 'ready', owner: 'daemon', grantGeneration: 1,
294
+ authorizationGeneration: 1, revision: 1, ciphertext,
295
+ accessExpiresAt: tokenExpiry(result.credential), attemptId: null,
296
+ retryAt: null, retryCount: 0, problem: 'none', statusObservedAt: now, updateId };
297
+ return { account, grant };
298
+ });
299
+ this.publish();
300
+ operation.public.account = publicAccount(updated.account, updated.grant);
301
+ operation.public.state = 'complete';
302
+ }).catch(() => {
303
+ operation.public.state = operation.cancelled ? 'cancelled' : 'failed';
304
+ operation.public.error = operation.cancelled ? null : targetId === null
305
+ ? 'OpenAI login failed or the account could not be saved. No active account was changed.'
306
+ : 'OpenAI reauthentication failed or selected a different account. The existing account was preserved.';
307
+ }).finally(async () => {
308
+ operation.finishedAt = this.now();
309
+ try {
310
+ await handle.close();
311
+ }
312
+ catch { /* A completed operation remains inspectable. */ }
313
+ });
314
+ return structuredClone(publicOperation);
315
+ }
316
+ getOperation(operationId) {
317
+ if (!isUuid(operationId))
318
+ throw new Error('Invalid operation ID.');
319
+ this.pruneOperations();
320
+ const operation = this.operations.get(operationId);
321
+ if (!operation)
322
+ throw new Error('Account operation expired or was not found.');
323
+ return structuredClone(operation.public);
324
+ }
325
+ pruneOperations() {
326
+ for (const [id, operation] of this.operations) {
327
+ if (operation.finishedAt !== null && this.now() - operation.finishedAt > 600_000)
328
+ this.operations.delete(id);
329
+ }
330
+ }
331
+ async cancelOperation(operationId) {
332
+ const operation = this.operations.get(operationId);
333
+ if (!isUuid(operationId) || !operation)
334
+ throw new Error('Account operation expired or was not found.');
335
+ if (operation.public.state !== 'pending')
336
+ return structuredClone(operation.public);
337
+ if (operation.committing)
338
+ throw new Error('Login is completing; check its operation status.');
339
+ operation.cancelled = true;
340
+ await operation.handle.cancel();
341
+ operation.public.state = 'cancelled';
342
+ operation.public.error = null;
343
+ return structuredClone(operation.public);
344
+ }
345
+ async renameAccount(accountId, expectedRevision, label) {
346
+ if (!isId(accountId) || !validRevision(expectedRevision) || !safeLabel(label))
347
+ throw new Error('Invalid account change.');
348
+ const updateId = plugins.crypto.randomUUID();
349
+ const updated = await this.database.changeAccount(updateId, accountId, account => {
350
+ if (!account || account.removed || account.revision !== expectedRevision)
351
+ throw new Error('Account changed; refresh before editing.');
352
+ return { ...account, label, revision: account.revision + 1, updateId,
353
+ statusObservedAt: new Date(this.now()).toISOString() };
354
+ });
355
+ this.publish();
356
+ const grant = updated.account.primaryGrantId ? await this.database.readGrant(updated.account.primaryGrantId) : null;
357
+ return publicAccount(updated.account, grant);
358
+ }
359
+ async removeAccount(accountId, expectedRevision) {
360
+ if (!isId(accountId) || !validRevision(expectedRevision))
361
+ throw new Error('Invalid account change.');
362
+ const updateId = plugins.crypto.randomUUID();
363
+ const account = await this.database.removeAccountAndGrants(updateId, accountId, expectedRevision, new Date(this.now()).toISOString());
364
+ this.publish();
365
+ const grant = account.primaryGrantId ? await this.database.readGrant(account.primaryGrantId) : null;
366
+ return publicAccount(account, grant);
367
+ }
368
+ async bindAccount(input) {
369
+ if (!isId(input.accountId) || !['flex', 'codex', 'opencode', 'claude'].includes(input.runtime)
370
+ || !safeScope(input.scopeId, 512) || !safeScope(input.incarnationId, 256))
371
+ throw new Error('Invalid account binding.');
372
+ const id = idHash('authswitch-binding-v1', input.runtime, input.scopeId);
373
+ const capability = plugins.crypto.randomBytes(32).toString('base64url');
374
+ const capabilityHash = idHash(capability);
375
+ const updateId = plugins.crypto.randomUUID();
376
+ const updated = await this.database.changeBinding(updateId, id, input.accountId, (existing, account, grant) => {
377
+ if (account.removed || grant?.state !== 'ready' || grant.owner !== 'daemon'
378
+ || grant.purpose !== 'openai_managed' || account.providerId !== 'openai'
379
+ || input.runtime === 'claude') {
380
+ throw new Error('Account is not available for this runtime.');
381
+ }
382
+ return { id, accountId: input.accountId, grantId: grant.id, runtime: input.runtime, scopeId: input.scopeId,
383
+ incarnationId: input.incarnationId, revision: (existing?.revision ?? 0) + 1,
384
+ grantAuthorizationGeneration: grant.authorizationGeneration, capabilityHash, updateId };
385
+ });
386
+ this.publish();
387
+ return { binding: publicBinding(updated.binding), capability };
388
+ }
389
+ async resolveAccess(bindingId, capability, minValidityMs) {
390
+ if (!isId(bindingId) || !/^[A-Za-z0-9_-]{43}$/.test(capability)
391
+ || !Number.isSafeInteger(minValidityMs) || minValidityMs < 0 || minValidityMs > 3_600_000)
392
+ throw new Error('Invalid runtime credential request.');
393
+ const supplied = Buffer.from(idHash(capability), 'hex');
394
+ for (let attempt = 0; attempt < 4; attempt++) {
395
+ const initial = await this.database.readBindingContext(bindingId);
396
+ const binding = initial.binding;
397
+ const expected = Buffer.from(binding?.capabilityHash ?? '0'.repeat(64), 'hex');
398
+ if (!binding || !plugins.crypto.timingSafeEqual(supplied, expected)) {
399
+ throw new Error('Runtime binding is not authorized.');
400
+ }
401
+ const { account, grant } = initial;
402
+ if (!account || account.removed || !grant || grant.id !== binding.grantId
403
+ || binding.grantAuthorizationGeneration !== grant.authorizationGeneration) {
404
+ throw new Error('Account needs reauthentication.');
405
+ }
406
+ if (grant.state === 'exchange_may_have_been_sent') {
407
+ const inFlight = this.refreshes.get(account.id);
408
+ if (!inFlight)
409
+ throw new Error('Account refresh is unresolved; reauthentication is required.');
410
+ await inFlight;
411
+ continue;
412
+ }
413
+ if (grant.owner !== 'daemon' || grant.purpose !== 'openai_managed'
414
+ || !['ready', 'retry_wait'].includes(grant.state)) {
415
+ throw new Error('Account needs reauthentication.');
416
+ }
417
+ if (this.isDue(grant, minValidityMs)) {
418
+ if (grant.state === 'ready' || (grant.retryAt !== null && Date.parse(grant.retryAt) <= this.now())) {
419
+ await this.refreshAccount(account.id);
420
+ continue;
421
+ }
422
+ throw new Error('Account access credential is not fresh enough.');
423
+ }
424
+ if (!grant.accessExpiresAt)
425
+ throw new Error('Account access credential is not fresh enough.');
426
+ const credential = await this.unsealCredential(account, grant);
427
+ const info = plugins.flexAuth.parseOpenAiChatGptTokenInfo(credential.accessToken);
428
+ if (info.chatgptAccountId !== account.workspaceId || info.chatgptUserId !== account.subject) {
429
+ throw new Error('Account access identity changed.');
430
+ }
431
+ const latest = await this.database.readBindingContext(bindingId);
432
+ if (!latest.binding || latest.binding.capabilityHash !== binding.capabilityHash
433
+ || latest.binding.accountId !== binding.accountId
434
+ || latest.binding.grantId !== binding.grantId
435
+ || latest.binding.incarnationId !== binding.incarnationId
436
+ || latest.binding.grantAuthorizationGeneration !== binding.grantAuthorizationGeneration
437
+ || latest.account?.removed || !latest.grant
438
+ || latest.grant.authorizationGeneration !== grant.authorizationGeneration
439
+ || latest.grant.owner !== 'daemon') {
440
+ throw new Error('Account binding changed during credential resolution.');
441
+ }
442
+ if (latest.grant.grantGeneration !== grant.grantGeneration
443
+ || latest.grant.state === 'exchange_may_have_been_sent')
444
+ continue;
445
+ if (!['ready', 'retry_wait'].includes(latest.grant.state) || this.isDue(latest.grant, minValidityMs)) {
446
+ throw new Error('Account access credential is not fresh enough.');
447
+ }
448
+ return { accessToken: credential.accessToken, accountId: account.workspaceId,
449
+ isFedrampAccount: info.chatgptAccountIsFedramp, expiresAt: grant.accessExpiresAt,
450
+ grantGeneration: grant.grantGeneration };
451
+ }
452
+ throw new Error('Account credential rotated repeatedly during resolution; retry the request.');
453
+ }
454
+ async refreshAccount(accountId) {
455
+ const prior = this.refreshes.get(accountId);
456
+ if (prior)
457
+ return prior;
458
+ const task = this.performRefresh(accountId).finally(() => { if (this.refreshes.get(accountId) === task)
459
+ this.refreshes.delete(accountId); });
460
+ this.refreshes.set(accountId, task);
461
+ return task;
462
+ }
463
+ async performRefresh(accountId) {
464
+ const initial = await this.database.readAccountAndPrimaryGrant(accountId);
465
+ const initialGrant = initial.grant;
466
+ if (!initial.account || initial.account.removed || !initialGrant || initialGrant.purpose !== 'openai_managed'
467
+ || !['ready', 'retry_wait'].includes(initialGrant.state) || initialGrant.owner !== 'daemon'
468
+ || !this.isDue(initialGrant, 0)
469
+ || (initialGrant.state === 'retry_wait'
470
+ && (initialGrant.retryAt === null || Date.parse(initialGrant.retryAt) > this.now())))
471
+ return;
472
+ const credential = await this.unsealCredential(initial.account, initialGrant);
473
+ const attemptId = plugins.crypto.randomUUID();
474
+ await this.database.changeGrant(attemptId, initialGrant.id, (grant, account) => {
475
+ if (account.removed || grant.state !== initialGrant.state || grant.revision !== initialGrant.revision
476
+ || grant.grantGeneration !== initialGrant.grantGeneration)
477
+ throw new Error('Account changed before refresh began.');
478
+ return { ...grant, state: 'exchange_may_have_been_sent', attemptId, retryAt: null,
479
+ revision: grant.revision + 1, statusObservedAt: new Date(this.now()).toISOString(), updateId: attemptId };
480
+ });
481
+ this.publish();
482
+ try {
483
+ const refreshed = await this.provider.refreshCredential(credential);
484
+ if (!refreshed.success) {
485
+ if (refreshed.requestOutcome === 'notSent') {
486
+ const retryId = plugins.crypto.randomUUID();
487
+ await this.database.changeGrant(retryId, initialGrant.id, grant => {
488
+ if (grant.state !== 'exchange_may_have_been_sent' || grant.attemptId !== attemptId) {
489
+ throw new Error('Account ownership changed during refresh.');
490
+ }
491
+ const backoffMs = Math.min(30_000 * 2 ** Math.min(grant.retryCount, 10), 1_800_000);
492
+ const retryMs = Math.max(backoffMs, Math.min(refreshed.retryAfterMs ?? 0, 3_600_000));
493
+ return { ...grant, state: 'retry_wait', attemptId: null,
494
+ retryAt: new Date(this.now() + retryMs).toISOString(), retryCount: grant.retryCount + 1,
495
+ problem: 'provider_unavailable',
496
+ revision: grant.revision + 1, statusObservedAt: new Date(this.now()).toISOString(), updateId: retryId };
497
+ });
498
+ this.publish();
499
+ return;
500
+ }
501
+ throw new Error('Provider refresh outcome is unknown.');
502
+ }
503
+ const identity = this.identity(refreshed.credential);
504
+ if (identity.id !== accountId)
505
+ throw new Error('Provider returned a different account.');
506
+ const ciphertext = await this.sealCredential(initialGrant.id, refreshed.credential);
507
+ const commitId = plugins.crypto.randomUUID();
508
+ await this.database.changeGrant(commitId, initialGrant.id, grant => {
509
+ if (grant.state !== 'exchange_may_have_been_sent' || grant.attemptId !== attemptId) {
510
+ throw new Error('Account ownership changed during refresh.');
511
+ }
512
+ return { ...grant, state: 'ready', attemptId: null, retryAt: null, retryCount: 0, problem: 'none',
513
+ ciphertext, accessExpiresAt: tokenExpiry(refreshed.credential),
514
+ grantGeneration: grant.grantGeneration + 1, revision: grant.revision + 1,
515
+ statusObservedAt: new Date(this.now()).toISOString(), updateId: commitId };
516
+ });
517
+ this.publish();
518
+ }
519
+ catch {
520
+ const uncertainId = plugins.crypto.randomUUID();
521
+ try {
522
+ await this.database.changeGrant(uncertainId, initialGrant.id, grant => {
523
+ if (grant.state !== 'exchange_may_have_been_sent' || grant.attemptId !== attemptId) {
524
+ throw new Error('Account was changed after its refresh attempt.');
525
+ }
526
+ return { ...grant, state: 'needs_reauth', attemptId: null, retryAt: null,
527
+ problem: 'exchange_uncertain', revision: grant.revision + 1,
528
+ statusObservedAt: new Date(this.now()).toISOString(), updateId: uncertainId };
529
+ });
530
+ this.publish();
531
+ }
532
+ catch { /* A persisted attempt marker forces needs_reauth on daemon restart. */ }
533
+ throw new Error('Refresh result is uncertain. Reauthenticate this account; its old grant will not be replayed.');
534
+ }
535
+ }
536
+ async close() {
537
+ this.closed = true;
538
+ if (this.timer)
539
+ clearTimeout(this.timer);
540
+ for (const wake of this.listeners)
541
+ wake();
542
+ await Promise.allSettled([...this.operations.values()].map(item => item.handle.cancel()));
543
+ await Promise.allSettled([...this.operations.values()].map(item => item.task));
544
+ await Promise.allSettled([...this.refreshes.values()]);
545
+ await this.provider.dispose();
546
+ }
547
+ }
548
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRob3JpdHlicm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmF1dGhvcml0eWJyb2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUU3RSxPQUFPLEVBQUUsd0JBQXdCLEVBQStCLE1BQU0sK0JBQStCLENBQUM7QUFvQnRHLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxNQUFnQixFQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNqSSxNQUFNLElBQUksR0FBRyxDQUFDLEtBQWMsRUFBbUIsRUFBRSxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDNUcsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFjLEVBQW1CLEVBQUUsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQy9HLE1BQU0sU0FBUyxHQUFHLENBQUMsS0FBYyxFQUFtQixFQUFFLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxLQUFLO09BQ3JHLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3JGLE1BQU0sU0FBUyxHQUFHLENBQUMsS0FBYyxFQUFFLE9B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