@cortexkit/anthropic-auth-core 2.2.5 → 2.2.7

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.
package/dist/index.js CHANGED
@@ -21380,6 +21380,77 @@ function createNativeLocalCredentialService(options) {
21380
21380
  return Object.freeze({ authorize: authorize2 });
21381
21381
  }
21382
21382
 
21383
+ // src/native-local-publication.ts
21384
+ var publishers = new Map;
21385
+ function acquireNativeLocalPublisher(key) {
21386
+ let owned = publishers.get(key);
21387
+ if (!owned) {
21388
+ owned = { writer: createPublisher(), leases: 0 };
21389
+ publishers.set(key, owned);
21390
+ }
21391
+ owned.leases++;
21392
+ let released = false;
21393
+ return {
21394
+ ...owned.writer,
21395
+ release() {
21396
+ if (released)
21397
+ return;
21398
+ released = true;
21399
+ if (--owned.leases === 0)
21400
+ publishers.delete(key);
21401
+ }
21402
+ };
21403
+ }
21404
+ function createPublisher() {
21405
+ let tail = Promise.resolve();
21406
+ const pending = new Map;
21407
+ const run = (write) => {
21408
+ const result = tail.then(write);
21409
+ tail = result.catch(() => {});
21410
+ return result;
21411
+ };
21412
+ return {
21413
+ run,
21414
+ enqueue(key, patch, write) {
21415
+ const queued = pending.get(key);
21416
+ if (queued) {
21417
+ const previous = queued.patch;
21418
+ if (previous.quota && patch.quota && patch.quota.source !== "headers" && quotaSnapshotCheckedAt(previous.quota) > quotaSnapshotCheckedAt(patch.quota))
21419
+ return Promise.resolve(false);
21420
+ queued.patch = { ...previous, ...patch };
21421
+ if (previous.quota && patch.quota)
21422
+ queued.patch.quota = fromNativeQuotaMap(nativeQuotaCodec.merge(toNativeQuotaMap(previous.quota), toNativeQuotaMap(patch.quota)));
21423
+ if (previous.lastUsed !== undefined || patch.lastUsed !== undefined)
21424
+ queued.patch.lastUsed = Math.max(previous.lastUsed ?? 0, patch.lastUsed ?? 0);
21425
+ for (const field of [
21426
+ "quotaErrorClearedAt",
21427
+ "quotaErrorGeneration"
21428
+ ])
21429
+ if (previous[field] !== undefined || patch[field] !== undefined)
21430
+ queued.patch[field] = Math.max(previous[field] ?? 0, patch[field] ?? 0);
21431
+ if (previous.lastQuotaRefreshError && patch.lastQuotaRefreshError && previous.lastQuotaRefreshError.checkedAt > patch.lastQuotaRefreshError.checkedAt)
21432
+ queued.patch.lastQuotaRefreshError = previous.lastQuotaRefreshError;
21433
+ return queued.result;
21434
+ }
21435
+ const batch = { patch, result: Promise.resolve(false) };
21436
+ pending.set(key, batch);
21437
+ batch.result = run(async () => {
21438
+ await new Promise((resolve10) => setTimeout(resolve10, 0));
21439
+ pending.delete(key);
21440
+ return write(batch.patch);
21441
+ });
21442
+ return batch.result;
21443
+ },
21444
+ async drain() {
21445
+ let observed;
21446
+ do {
21447
+ observed = tail;
21448
+ await observed;
21449
+ } while (observed !== tail);
21450
+ }
21451
+ };
21452
+ }
21453
+
21383
21454
  // src/native-usage-publication.ts
21384
21455
  import { types as types3 } from "node:util";
21385
21456
  function usagePublicationRefusalIsFatal(error) {
@@ -21526,7 +21597,7 @@ class NativeQuotaObservations extends Map {
21526
21597
  let clearAt;
21527
21598
  let matched = false;
21528
21599
  for (const observation of this.values()) {
21529
- if (observation.entry.quota.source === "headers")
21600
+ if (observation.entry.quota.source === "headers" && observation.routeBeforeSave !== true)
21530
21601
  continue;
21531
21602
  if (observation.lineage !== lineage || observation.accountUuid !== accountUuid2 || getQuotaNextRefreshAt(observation.entry.quota, storage, observation.entry.checkedAt) <= now)
21532
21603
  continue;
@@ -21556,6 +21627,17 @@ class NativeQuotaObservations extends Map {
21556
21627
  }
21557
21628
  }));
21558
21629
  }
21630
+ hold(accountId, observation) {
21631
+ const current = this.get(accountId);
21632
+ if (current && current.lineage === observation.lineage && quotaSnapshotCheckedAt(current.entry.quota) > quotaSnapshotCheckedAt(observation.entry.quota))
21633
+ return false;
21634
+ this.set(accountId, observation);
21635
+ return true;
21636
+ }
21637
+ forget(accountId, observation) {
21638
+ if (this.get(accountId) === observation)
21639
+ this.delete(accountId);
21640
+ }
21559
21641
  drain() {
21560
21642
  return this.publications.drain();
21561
21643
  }
@@ -24111,27 +24193,30 @@ function decideStickyQuotaFailure(input) {
24111
24193
  const quota2 = knownQuota(input.quota);
24112
24194
  if (!quota2)
24113
24195
  return { action: "retain", reason: "unknown" };
24114
- const scoped = getScopedQuotaWindowForModel(quota2, input.modelId);
24115
- if (scoped && Number.isFinite(scoped.remainingPercent) && scoped.remainingPercent <= 0) {
24116
- return { action: "migrate", reason: "model-scoped" };
24117
- }
24118
- const sevenDay = quota2.seven_day;
24119
- if (sevenDay && Number.isFinite(sevenDay.remainingPercent) && sevenDay.remainingPercent <= 0) {
24120
- return { action: "migrate", reason: "seven-day" };
24121
- }
24122
- const fiveHour = quota2.five_hour;
24123
- if (fiveHour && Number.isFinite(fiveHour.remainingPercent) && fiveHour.remainingPercent <= 0) {
24124
- const resetAt = fiveHour.resetsAt ? Date.parse(fiveHour.resetsAt) : NaN;
24125
- if (Number.isFinite(resetAt) && resetAt > now && resetAt - now <= STICKY_ROUTING_SHORT_RESET_GRACE_MS) {
24126
- return {
24127
- action: "hold",
24128
- reason: "five-hour-short-reset",
24129
- retryAfterSeconds: Math.max(1, Math.ceil((resetAt - now) / 1000))
24130
- };
24131
- }
24132
- return { action: "migrate", reason: "five-hour" };
24196
+ let blocking;
24197
+ for (const [reason, window2] of [
24198
+ ["model-scoped", getScopedQuotaWindowForModel(quota2, input.modelId)],
24199
+ ["seven-day", quota2.seven_day],
24200
+ ["five-hour", quota2.five_hour]
24201
+ ]) {
24202
+ if (!window2 || !Number.isFinite(window2.remainingPercent) || window2.remainingPercent > 0)
24203
+ continue;
24204
+ const resetAt = window2.resetsAt ? Date.parse(window2.resetsAt) : NaN;
24205
+ if (!Number.isFinite(resetAt) || resetAt <= now)
24206
+ return { action: "migrate", reason };
24207
+ if (!blocking || resetAt > blocking.resetAt)
24208
+ blocking = { resetAt, reason };
24209
+ }
24210
+ if (!blocking)
24211
+ return { action: "retain", reason: "not-exhausted" };
24212
+ if (blocking.resetAt - now <= STICKY_ROUTING_SHORT_RESET_GRACE_MS) {
24213
+ return {
24214
+ action: "hold",
24215
+ reason: `${blocking.reason}-short-reset`,
24216
+ retryAfterSeconds: Math.max(1, Math.ceil((blocking.resetAt - now) / 1000))
24217
+ };
24133
24218
  }
24134
- return { action: "retain", reason: "not-exhausted" };
24219
+ return { action: "migrate", reason: blocking.reason };
24135
24220
  }
24136
24221
  function getStickyRoutingStatePath(accountStoragePath) {
24137
24222
  const name = basename6(accountStoragePath);
@@ -25782,6 +25867,11 @@ async function sendViaRelay(options) {
25782
25867
  responseMode ??= requestResponseMode(bodyText);
25783
25868
  return responseMode;
25784
25869
  };
25870
+ let directFallbackStarted = false;
25871
+ const directFallback = () => {
25872
+ directFallbackStarted = true;
25873
+ return fallback();
25874
+ };
25785
25875
  try {
25786
25876
  let result;
25787
25877
  const sendStart = perfNowMs();
@@ -25802,7 +25892,7 @@ async function sendViaRelay(options) {
25802
25892
  payload,
25803
25893
  bodyText,
25804
25894
  requestMode,
25805
- fallback,
25895
+ fallback: directFallback,
25806
25896
  signal: init?.signal,
25807
25897
  authorizeAttempt
25808
25898
  });
@@ -25813,7 +25903,7 @@ async function sendViaRelay(options) {
25813
25903
  payload,
25814
25904
  bodyText,
25815
25905
  requestMode,
25816
- fallback,
25906
+ fallback: directFallback,
25817
25907
  signal: init?.signal,
25818
25908
  authorizeAttempt
25819
25909
  });
@@ -25873,6 +25963,10 @@ async function sendViaRelay(options) {
25873
25963
  throw error.failure;
25874
25964
  if (error instanceof RelayResponseMetadataError)
25875
25965
  throw error;
25966
+ if (directFallbackStarted) {
25967
+ relayLog(`direct fallback failed session=${shortAffinity2(affinity)}; not sending it again code=relay_transport_error`);
25968
+ throw error;
25969
+ }
25876
25970
  if (!config.fallbackToDirect) {
25877
25971
  relayLog(`relay failed session=${shortAffinity2(affinity)} and fallbackToDirect=false code=relay_transport_error`);
25878
25972
  throw error;
@@ -26265,11 +26359,12 @@ function acquireNativeAccountRuntime(options) {
26265
26359
  const quotaObservations = use().quotaObservations;
26266
26360
  const onLockEvent = use().onLockEvent;
26267
26361
  const drainRoutingPublications = use().drainRoutingPublications;
26362
+ const drainQuotaPublications = use().drainQuotaPublications;
26268
26363
  return {
26269
26364
  onLockEvent,
26270
26365
  vault,
26271
26366
  quotaObservations,
26272
- drainQuotaPublications: () => quotaObservations.drain(),
26367
+ drainQuotaPublications,
26273
26368
  drainRoutingPublications,
26274
26369
  getRelayConfig: () => use().getRelayConfig(),
26275
26370
  getSettingsPath: () => use().getSettingsPath(),
@@ -26297,7 +26392,10 @@ function acquireNativeAccountRuntime(options) {
26297
26392
  fetchProfileForDisplay: (id2, transport, signal) => use().fetchProfileForDisplay(id2, transport, signal),
26298
26393
  close: () => {
26299
26394
  vault.close();
26300
- return drainRoutingPublications();
26395
+ return Promise.all([
26396
+ drainQuotaPublications(),
26397
+ drainRoutingPublications()
26398
+ ]).then(() => {});
26301
26399
  }
26302
26400
  };
26303
26401
  }
@@ -26337,6 +26435,9 @@ function createNativeAccountRuntime(options) {
26337
26435
  }
26338
26436
  });
26339
26437
  const shutdown = new AbortController;
26438
+ let closing;
26439
+ const quotaPublications = acquireNativeLocalPublisher(paths.config);
26440
+ const metadataPublications = acquireNativeLocalPublisher(paths.runtime);
26340
26441
  const store = createNativePoolStore({
26341
26442
  paths,
26342
26443
  quota: nativeQuotaCodec,
@@ -26459,6 +26560,51 @@ function createNativeAccountRuntime(options) {
26459
26560
  throw error;
26460
26561
  }
26461
26562
  }
26563
+ async function localMetadataMatches(subject) {
26564
+ const binding2 = subject.binding;
26565
+ const row = await poolRow(binding2.rowId);
26566
+ if (row?.stamp !== "bound" || !row.credential || !nativeLocalPoolBindingMatches(binding2, paths, row))
26567
+ return false;
26568
+ if ("kind" in subject)
26569
+ return row.credential.type === "api" && fingerprintOf(row.credential) === subject.credentialFingerprint && row.credential.baseURL === subject.baseURL && row.credential.authHeader === subject.authHeader;
26570
+ return row.credential.type === "oauth" && fingerprintOf(row.credential) === subject.credentialFingerprint && nativeLocalCredentialValidationMatches(subject, binding2, row.credential);
26571
+ }
26572
+ async function localMetadataWrite(subject, change) {
26573
+ const binding2 = subject.binding;
26574
+ if (await authority() !== "local")
26575
+ return false;
26576
+ const matches2 = await localMetadataMatches(subject);
26577
+ await localAuthority();
26578
+ if (!matches2)
26579
+ return false;
26580
+ try {
26581
+ await updateNativeRuntime(paths.runtime, paths.storageId, (current) => {
26582
+ const old = current.accounts[binding2.rowId];
26583
+ const previous = old?.binding;
26584
+ const same = previous?.kind === "local" && previous.rowId === binding2.rowId && previous.identity === binding2.identity && previous.credentialEpoch === binding2.credentialEpoch;
26585
+ current.accounts[binding2.rowId] = change(same && old ? old : { binding: binding2 });
26586
+ return current;
26587
+ }, {
26588
+ onLockEvent: options.local?.onLockEvent,
26589
+ beforeRename: async () => {
26590
+ if (!await localMetadataMatches(subject))
26591
+ throw new NativeRuntimeError("publication-refused");
26592
+ await localAuthority();
26593
+ },
26594
+ beforePublish: () => localAuthority()
26595
+ });
26596
+ if (await authority() !== "local")
26597
+ throw new NativeRuntimeError("publication-refused");
26598
+ return true;
26599
+ } catch (error) {
26600
+ if (error instanceof NativeRuntimeError && (error.code === "runtime-conflict" || error.code === "publication-refused")) {
26601
+ if (await authority() !== "local")
26602
+ throw error;
26603
+ return false;
26604
+ }
26605
+ throw error;
26606
+ }
26607
+ }
26462
26608
  async function initializeCredentialEpoch(id2) {
26463
26609
  const row = await poolRow(id2);
26464
26610
  if (!row?.credential || row.credentialEpoch === undefined)
@@ -26594,7 +26740,13 @@ function createNativeAccountRuntime(options) {
26594
26740
  onLockEvent,
26595
26741
  vault,
26596
26742
  quotaObservations: vault.quotaObservations,
26597
- drainQuotaPublications: () => vault.quotaObservations.drain(),
26743
+ drainQuotaPublications: async () => {
26744
+ await vault.quotaObservations.drain();
26745
+ await Promise.all([
26746
+ quotaPublications.drain(),
26747
+ metadataPublications.drain()
26748
+ ]);
26749
+ },
26598
26750
  drainRoutingPublications: () => vaultRouter.drain(),
26599
26751
  async getRelayConfig() {
26600
26752
  const { mode, paths: paths2, store: store2 } = await selectedStorage();
@@ -26857,11 +27009,12 @@ function createNativeAccountRuntime(options) {
26857
27009
  } catch {
26858
27010
  throw new Error("Claude account identity could not be verified; retry sign-in. No account changes were saved.");
26859
27011
  }
27012
+ const { access, refresh, expires } = input.credential;
26860
27013
  return runtime2.putAccount({
26861
27014
  ...input,
26862
27015
  accountIdentity,
26863
27016
  replace: input.replace ?? true,
26864
- credential: { type: "oauth", ...input.credential }
27017
+ credential: { type: "oauth", access, refresh, expires }
26865
27018
  });
26866
27019
  },
26867
27020
  async putAccount(input) {
@@ -27052,30 +27205,45 @@ function createNativeAccountRuntime(options) {
27052
27205
  };
27053
27206
  },
27054
27207
  async publishLocal(subject, rawPatch) {
27055
- const patch = captureNativeMetadataPatch(rawPatch);
27056
- if (await authority() !== "local")
27057
- return false;
27058
- const { quota: quota2, ...metadata2 } = patch;
27059
- const quotaOnly = quota2 !== undefined && Object.keys(metadata2).length === 0;
27060
- const row = await poolRow(subject.binding.rowId);
27061
- if (row?.stamp !== "bound" || row.credential?.type !== "oauth" || !nativeLocalPoolBindingMatches(subject.binding, paths, row) || !quotaOnly && !nativeLocalCredentialValidationMatches(subject, subject.binding, row.credential))
27062
- return false;
27063
- if (quota2) {
27064
- if (quota2.source !== "headers" && row.quota && quotaSnapshotCheckedAt(fromNativeQuotaMap(row.quota)) > quotaSnapshotCheckedAt(quota2))
27208
+ const captured = captureNativeMetadataPatch(rawPatch);
27209
+ const { quota: _quota, ...metadata2 } = captured;
27210
+ const mixed = captured.quota !== undefined && Object.keys(metadata2).length > 0;
27211
+ let admission;
27212
+ const admitted = () => admission ??= (async () => {
27213
+ if (await authority() !== "local")
27065
27214
  return false;
27066
- if (quota2.accountIdentity !== subject.binding.identity)
27067
- throw new NativeRuntimeError("publication-refused");
27068
- await store.recordQuota(subject.binding.rowId, {
27069
- credentialEpoch: subject.binding.credentialEpoch,
27070
- identity: subject.binding.identity
27071
- }, toNativeQuotaMap(quota2));
27072
- }
27073
- return localWrite(subject, (old) => applyNativeMetadataPatch(old, metadata2), quotaOnly ? "binding" : true);
27215
+ const matches2 = await localMetadataMatches(subject);
27216
+ await localAuthority();
27217
+ return matches2;
27218
+ })();
27219
+ const key = JSON.stringify(subject);
27220
+ const writes = [];
27221
+ if (captured.quota)
27222
+ writes.push(quotaPublications.enqueue(mixed ? `${key}:mixed` : key, { quota: captured.quota }, async ({ quota: quota2 }) => {
27223
+ if (mixed && !await admitted())
27224
+ return false;
27225
+ if (!quota2 || await authority() !== "local")
27226
+ return false;
27227
+ const row = await poolRow(subject.binding.rowId);
27228
+ if (row?.stamp !== "bound" || row.credential?.type !== "oauth" || !nativeLocalPoolBindingMatches(subject.binding, paths, row) || quota2.accountIdentity !== subject.binding.identity)
27229
+ return false;
27230
+ if (quota2.source !== "headers" && row.quota && quotaSnapshotCheckedAt(fromNativeQuotaMap(row.quota)) > quotaSnapshotCheckedAt(quota2))
27231
+ return false;
27232
+ await store.recordQuota(subject.binding.rowId, {
27233
+ credentialEpoch: subject.binding.credentialEpoch,
27234
+ identity: subject.binding.identity
27235
+ }, toNativeQuotaMap(quota2));
27236
+ return true;
27237
+ }));
27238
+ if (Object.keys(metadata2).length)
27239
+ writes.push(metadataPublications.enqueue(mixed ? `${key}:mixed` : key, metadata2, async (patch) => {
27240
+ if (mixed && !await admitted())
27241
+ return false;
27242
+ return localMetadataWrite(subject, (old) => applyNativeMetadataPatch(old, patch));
27243
+ }));
27244
+ return (await Promise.all(writes)).every(Boolean);
27074
27245
  },
27075
- publishApi: (subject, patch) => localWrite(subject, (old) => ({
27076
- ...old,
27077
- lastUsed: Math.max(old.lastUsed ?? 0, patch.lastUsed)
27078
- })),
27246
+ publishApi: (subject, patch) => metadataPublications.enqueue(JSON.stringify(subject), patch, (merged) => localMetadataWrite(subject, (old) => applyNativeMetadataPatch(old, merged))),
27079
27247
  async resetBackoff(routeId, fence, kind = "all") {
27080
27248
  if ("accessToken" in fence)
27081
27249
  return vault.resetBackoff(fence, kind);
@@ -27107,13 +27275,13 @@ function createNativeAccountRuntime(options) {
27107
27275
  if (await physicalId(routeId) !== fence.binding.rowId)
27108
27276
  return;
27109
27277
  let lineage;
27110
- const kept = await localWrite(fence, (old) => {
27278
+ const kept = await metadataPublications.run(() => localMetadataWrite(fence, (old) => {
27111
27279
  lineage = old.authLineageId ?? randomUUID15();
27112
27280
  return {
27113
27281
  ...old,
27114
27282
  authLineageId: lineage
27115
27283
  };
27116
- });
27284
+ }));
27117
27285
  return kept ? lineage : undefined;
27118
27286
  },
27119
27287
  async incrementPrimeUsage(routeId, fence, delta = {}) {
@@ -27124,7 +27292,7 @@ function createNativeAccountRuntime(options) {
27124
27292
  if (await physicalId(routeId) !== fence.binding.rowId)
27125
27293
  return false;
27126
27294
  const captured = primeDelta(delta);
27127
- return localWrite(fence, (old) => ({
27295
+ return metadataPublications.run(() => localMetadataWrite(fence, (old) => ({
27128
27296
  ...old,
27129
27297
  prime: {
27130
27298
  count: (old.prime?.count ?? 0) + 1,
@@ -27132,7 +27300,7 @@ function createNativeAccountRuntime(options) {
27132
27300
  outputTokens: (old.prime?.outputTokens ?? 0) + captured.outputTokens,
27133
27301
  since: old.prime?.since ?? now()
27134
27302
  }
27135
- }));
27303
+ })));
27136
27304
  },
27137
27305
  async fetchQuota(routeId, fetchImpl = fetch, signal, dispatch, purpose) {
27138
27306
  const snapshot = await runtime2.read();
@@ -27196,11 +27364,16 @@ function createNativeAccountRuntime(options) {
27196
27364
  });
27197
27365
  },
27198
27366
  close() {
27199
- if (!shutdown.signal.aborted) {
27367
+ if (closing)
27368
+ return closing;
27369
+ const draining = runtime2.drainQuotaPublications();
27370
+ vault.close();
27371
+ closing = Promise.all([draining, vaultRouter.drain()]).then(() => {}).finally(() => {
27200
27372
  shutdown.abort(new NativeCustodyError("closed"));
27201
- vault.close();
27202
- }
27203
- return vaultRouter.drain();
27373
+ quotaPublications.release();
27374
+ metadataPublications.release();
27375
+ });
27376
+ return closing;
27204
27377
  }
27205
27378
  };
27206
27379
  function readLocalProfile(id2, fetchImpl, signal) {
@@ -0,0 +1,8 @@
1
+ import type { NativeAccountMetadataPatch } from './native-account-view.ts';
2
+ /** Share one replaceable bookkeeping mailbox per destination in this process, never for credential writes. */
3
+ export declare function acquireNativeLocalPublisher(key: string): {
4
+ release(): void;
5
+ run: <T>(write: () => Promise<T>) => Promise<T>;
6
+ enqueue(key: string, patch: NativeAccountMetadataPatch, write: (patch: NativeAccountMetadataPatch) => Promise<boolean>): Promise<boolean>;
7
+ drain(): Promise<void>;
8
+ };
@@ -7,6 +7,14 @@ export type NativeQuotaObservation = {
7
7
  entry: QuotaEntry;
8
8
  generalExhausted: boolean;
9
9
  quotaErrorClearedAt?: number;
10
+ /**
11
+ * Set on a response-header reading from a host that routes on native
12
+ * snapshots (OpenCode 2). The snapshot overlay then applies it while its
13
+ * detached save is still pending, as it does for poll readings. Header
14
+ * readings without it stay host-owned: OpenCode 1 applies its own routing
15
+ * and display rules to them.
16
+ */
17
+ routeBeforeSave?: boolean;
10
18
  };
11
19
  export declare function nativePollQuotaGenerallyExhausted(quota: OAuthQuotaSnapshot): boolean;
12
20
  export declare function nativeLocalQuotaLineage(binding: NativeLocalPoolBinding & {
@@ -22,5 +30,14 @@ export declare class NativeQuotaObservations extends Map<string, NativeQuotaObse
22
30
  clearAt?: number;
23
31
  } | undefined;
24
32
  publish(accountId: string, observation: NativeQuotaObservation, write: () => Promise<boolean>): Promise<void>;
33
+ /**
34
+ * Registers a response-header reading before its detached save starts, so
35
+ * routing in this process sees it while the save waits on file locks. A
36
+ * reading older than the one already held for the same credential lineage
37
+ * is not registered, so an older reading never replaces a newer one.
38
+ */
39
+ hold(accountId: string, observation: NativeQuotaObservation): boolean;
40
+ /** Forgets a held reading whose save was refused, unless a later reading already replaced it. */
41
+ forget(accountId: string, observation: NativeQuotaObservation): void;
25
42
  drain(): Promise<void>;
26
43
  }
@@ -104,10 +104,10 @@ export interface NativeRuntimeWriteHooks {
104
104
  /** This writer alone uses `<leaf>.native-runtime.<UUID v4>.partial`. */
105
105
  export declare function isNativeRuntimeStagingName(path: string, name: string): boolean;
106
106
  /**
107
- * This file has its own update lock. Account publishers also hold the locks
108
- * protecting the pool and, for vault accounts, the roster. They verify those
109
- * locks immediately before replacement. A process paused beyond a lock expiry
110
- * can overlap a new owner even with normal renewal.
107
+ * This file has its own update lock. Advisory account publishers recheck the
108
+ * pool or roster binding without taking its lock immediately before replacement;
109
+ * readers reject metadata whose binding no longer matches. Credential writers
110
+ * retain their separate ownership and custody checks.
111
111
  */
112
112
  export declare function updateNativeRuntime(path: string, storageId: string, change: (current: NativeRuntimeState) => NativeRuntimeState | Promise<NativeRuntimeState>, hooks?: NativeRuntimeWriteHooks): Promise<NativeRuntimeState>;
113
113
  /**
@@ -15,8 +15,9 @@ export interface NativePoolStoreOptions extends Pick<OpenPoolStoreOptions, 'now'
15
15
  onLockEvent?: (event: NativeLockEvent) => void;
16
16
  }
17
17
  /**
18
- * These config/state locks also fence local account metadata against concurrent
19
- * credential changes. Legacy sidecar writers use different files and locks.
18
+ * These locks serialize pool transactions, including credential changes and
19
+ * quota publication. Runtime bookkeeping has its own lock and binding checks.
20
+ * Legacy sidecar writers use different files and locks.
20
21
  */
21
22
  export declare function nativePoolStoreLocks(paths: NativePoolStorePaths): readonly [{
22
23
  readonly path: string;
@@ -45,7 +45,7 @@ export type StickyQuotaFailureDecision = {
45
45
  reason: 'not-exhausted' | 'unknown';
46
46
  } | {
47
47
  action: 'hold';
48
- reason: 'five-hour-short-reset';
48
+ reason: 'five-hour-short-reset' | 'seven-day-short-reset' | 'model-scoped-short-reset';
49
49
  retryAfterSeconds: number;
50
50
  } | {
51
51
  action: 'migrate';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/anthropic-auth-core",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",