@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
@@ -0,0 +1,32 @@
1
+ import { type QuotaCodec, type QuotaMap } from "./internal-types/quota/index.js";
2
+ import { type OAuthQuotaSnapshot } from './accounts.ts';
3
+ type ScopedMetadata = {
4
+ id: string;
5
+ title: string;
6
+ modelId?: string;
7
+ modelName: string;
8
+ remainingPercent: number;
9
+ };
10
+ /** Snapshot checkedAt, remaining percentages, scoped labels/ownership, account/source provenance and monetary extra usage absent from QuotaMap. */
11
+ export type NativeQuotaMetadata = Omit<OAuthQuotaSnapshot, 'five_hour' | 'seven_day' | 'scoped'> & {
12
+ version: 1;
13
+ remainingPercent: {
14
+ five_hour?: number;
15
+ seven_day?: number;
16
+ };
17
+ scoped?: ScopedMetadata[];
18
+ };
19
+ export interface NativeQuotaMap extends QuotaMap {
20
+ anthropic: NativeQuotaMetadata;
21
+ }
22
+ export declare class NativeQuotaCodecError extends Error {
23
+ constructor();
24
+ }
25
+ export declare function isNativeOAuthQuotaSnapshot(value: unknown): value is OAuthQuotaSnapshot;
26
+ export declare function nativeQuotaModelScope(model: string): string;
27
+ /** Conversion is arithmetic-free: preserve independent clocks and raw percentages. */
28
+ export declare function toNativeQuotaMap(snapshot: OAuthQuotaSnapshot): NativeQuotaMap;
29
+ /** Reject missing Anthropic metadata, extra keys, duplicate/unowned limits, absent/retired entries and inconsistent budgets. */
30
+ export declare function fromNativeQuotaMap(value: unknown): OAuthQuotaSnapshot;
31
+ export declare const nativeQuotaCodec: QuotaCodec;
32
+ export {};
@@ -0,0 +1,240 @@
1
+ import { type PoolFailureKind, type PoolLockSpec } from "./internal-types/store/index.js";
2
+ import { refreshClaudeOAuthToken } from './auth.ts';
3
+ import { type resolveClaudeCodeIdentity } from './claude-code.ts';
4
+ import { type NativeLocalCredentialValidation, type NativeLocalCredentialVersion } from './native-credential-validation.ts';
5
+ import { type NativeLocalPoolBinding } from './pool-binding.ts';
6
+ import type { NativePoolPaths } from './pool-paths.ts';
7
+ import { type NativePoolStoreOptions } from './pool-store.ts';
8
+ export declare const NATIVE_REFRESH_MAX_ATTEMPTS = 3;
9
+ /**
10
+ * Jobs distinguish credential replacements. This lock must still serialize
11
+ * all refreshes for the same account.
12
+ */
13
+ export declare function nativeAccountProviderLock(paths: NativePoolPaths, identity: string): PoolLockSpec;
14
+ export type NativeRefreshRestriction = {
15
+ status: 'allowed';
16
+ } | {
17
+ status: 'blocked';
18
+ reason: 'quota-ineligible' | 'account-disabled' | 'local-mode-unavailable';
19
+ } | {
20
+ status: 'blocked';
21
+ reason: 'refresh-backoff' | 'invalid-grant';
22
+ /**
23
+ * A one-way refresh-credential fingerprint ties this backoff to the stored
24
+ * OAuth lineage. Bearer values are secret, and an access-token fingerprint
25
+ * would identify a rotating access token rather than the failed refresh credential.
26
+ */
27
+ credentialFingerprint: string;
28
+ };
29
+ /**
30
+ * Outcome of the account lookup for a credential. 'unsupported-credential'
31
+ * means the lookup refused the access value itself (it is not a Claude OAuth
32
+ * access token, or it is a vault custody marker): no lookup request was made
33
+ * and no retry can succeed until the account is signed in again.
34
+ */
35
+ export type NativeIdentityBootstrap = 'resolved' | 'unavailable' | 'failed' | 'unsupported-credential';
36
+ export type NativeRefreshHandoff = 'not-needed' | 'acquired' | 'skipped-contention' | 'skipped-loss' | 'skipped-cancelled';
37
+ export interface NativeRefreshFailure {
38
+ kind: PoolFailureKind | 'caller-hook' | 'validation';
39
+ classification: 'transient' | 'invalid-grant' | 'permanent';
40
+ status?: number;
41
+ retryAfter?: number;
42
+ }
43
+ /**
44
+ * Access can change while the refresh token and credential epoch stay the
45
+ * same. These fields identify the exact stored OAuth version observed.
46
+ */
47
+ export type NativeRefreshDispatchVersion = Partial<NativeLocalCredentialVersion>;
48
+ /**
49
+ * Identifies a captured pool row by storage, row id, credential epoch and
50
+ * recorded account UUID, together with its full refresh-token fingerprint and
51
+ * access fingerprint, expiry and optional refresh timestamp. Neither token is
52
+ * included; access fingerprint and expiry may be absent before recovery.
53
+ */
54
+ export interface NativeRefreshSubject {
55
+ readonly binding: NativeLocalPoolBinding;
56
+ readonly credentialFingerprint: string;
57
+ readonly version: NativeRefreshDispatchVersion;
58
+ }
59
+ export type NativeKnownCredentialSubject = NativeLocalCredentialValidation;
60
+ /**
61
+ * Records the runtime binding and error-reset timestamps/generation observed
62
+ * for the captured pool row. Null means no binding or no reset value was
63
+ * present; a recorded timestamp or generation of zero must remain distinct.
64
+ */
65
+ export interface NativeRefreshContext {
66
+ readonly subject: NativeRefreshSubject;
67
+ readonly runtimeBinding: NativeLocalPoolBinding | null;
68
+ readonly refreshErrorClearedAt: number | null;
69
+ readonly quotaErrorClearedAt: number | null;
70
+ readonly quotaErrorGeneration: number | null;
71
+ }
72
+ export interface NativeRefreshPolicy {
73
+ readonly restriction: NativeRefreshRestriction;
74
+ readonly context: NativeRefreshContext;
75
+ }
76
+ export type NativeServingAdmission = {
77
+ status: 'proven';
78
+ validation: NativeLocalCredentialValidation;
79
+ } | {
80
+ status: 'unproven';
81
+ } | {
82
+ status: 'blocked';
83
+ reason: 'quota-ineligible' | 'account-disabled' | 'local-mode-unavailable' | 'refresh-backoff' | 'invalid-grant' | 'validation-backoff';
84
+ };
85
+ export interface NativeCommittedMaterial {
86
+ readonly credentialFingerprint: string;
87
+ readonly version: NativeRefreshDispatchVersion;
88
+ }
89
+ interface ObservationBase {
90
+ /**
91
+ * Identifies the row, credential version and account before refresh. Compare
92
+ * this binding with current store state before writing an observation.
93
+ */
94
+ binding: NativeLocalPoolBinding;
95
+ attempt: number;
96
+ credentialFingerprint?: string;
97
+ credentialVersion?: NativeRefreshDispatchVersion;
98
+ /**
99
+ * Runtime binding and error-reset values read before the provider exchange or
100
+ * account lookup. Later serving checks must not replace these values: doing
101
+ * so could let an older network result overwrite an intervening error reset.
102
+ */
103
+ context?: NativeRefreshContext;
104
+ bootstrap: NativeIdentityBootstrap;
105
+ handoff: NativeRefreshHandoff;
106
+ }
107
+ /**
108
+ * Observations contain no tokens or exceptions from the provider account lookup.
109
+ * Only a successful account lookup reported by a persisted or
110
+ * validation-observed event can support new validation evidence. An adopted
111
+ * event merely records credentials already present on the requesting pool row;
112
+ * it performs no account lookup. Failed events cannot create validation evidence.
113
+ */
114
+ export type NativeRefreshObservation = ObservationBase & ({
115
+ status: 'persisted';
116
+ identity?: string;
117
+ successorFingerprint: string;
118
+ successorVersion: NativeRefreshDispatchVersion;
119
+ committed: NativeCommittedMaterial;
120
+ } | {
121
+ status: 'adopted';
122
+ successorFingerprint: string;
123
+ successorVersion: NativeRefreshDispatchVersion;
124
+ } | {
125
+ status: 'validation-observed';
126
+ identity: string;
127
+ context: NativeRefreshContext;
128
+ } | {
129
+ status: 'refused';
130
+ reason: string;
131
+ consumed: boolean;
132
+ } | {
133
+ status: 'identity-contradicted';
134
+ expectedIdentity: string;
135
+ returnedIdentity: string;
136
+ successorFingerprint: string;
137
+ successorVersion: NativeRefreshDispatchVersion;
138
+ committed: NativeCommittedMaterial;
139
+ } | {
140
+ status: 'failed';
141
+ failure: NativeRefreshFailure;
142
+ persisted: boolean;
143
+ committed?: NativeCommittedMaterial;
144
+ });
145
+ export interface NativeRefreshHooks {
146
+ /**
147
+ * Read native local-mode, account-disable, quota and refresh-error restrictions
148
+ * for the captured row. Credential-bound errors apply only to the matching
149
+ * full refresh-token fingerprint; absent account-validation evidence must not
150
+ * prevent a refresh exchange. Echo the supplied row binding, refresh-token
151
+ * fingerprint and access version. Include the observed runtime binding,
152
+ * refreshErrorClearedAt, quotaErrorClearedAt and quotaErrorGeneration, using
153
+ * null for absent values. Before each physical exchange the coordinator keeps
154
+ * a new frozen copy after lock waits, outside pool-config/pool-state locks.
155
+ * Do not read host credentials or mutate the store.
156
+ */
157
+ readRestrictions(subject: NativeRefreshSubject): Promise<NativeRefreshPolicy>;
158
+ /**
159
+ * Read serving restrictions and validation evidence for the supplied row
160
+ * binding, full refresh-token fingerprint and access version, without token
161
+ * input or state writes. The binding has a recorded account UUID, but that
162
+ * UUID alone does not establish that the presented credential was validated.
163
+ * Returned evidence must match the credentials on the captured requesting row.
164
+ */
165
+ readAdmission(subject: NativeKnownCredentialSubject): Promise<NativeServingAdmission>;
166
+ /**
167
+ * Acquire pool-config, pool-state, then native-runtime before saving refresh
168
+ * errors or validation evidence. Re-read the observation's pool row and check
169
+ * storage, row id, credential epoch, recorded UUID, full refresh-token
170
+ * fingerprint, access fingerprint, expiry and lastRefreshedAt presence/value.
171
+ *
172
+ * credentialVersion names the credential captured before network work;
173
+ * successorVersion names the observed replacement; committed names the
174
+ * replacement actually saved before a later failure. A failed observation
175
+ * without committed credentials must not infer a replacement from a newer row.
176
+ *
177
+ * Compare the runtime binding and error-reset timestamps/generation with
178
+ * context. Changed reset values mean the older observation cannot overwrite
179
+ * state cleared while its exchange or lookup was pending. Learned UUIDs belong
180
+ * only to the row receiving the replacement. Clear obsolete credential-bound
181
+ * errors only after confirming which replacement is stored. Failed account
182
+ * lookups leave stored replacements without new validation evidence; observing
183
+ * an already advanced row or a failed operation cannot create that evidence.
184
+ *
185
+ * Reconciliation completes before authorize returns. The shared config/state
186
+ * locks are already released. A successful token exchange still holds the
187
+ * refresh locks that prevent another exchange for this row and account.
188
+ * Failed operations and checks of existing access without an exchange do not
189
+ * guarantee those locks. Do not call store operations that acquire row locks
190
+ * or wait for another caller of the same account's refresh job; either can
191
+ * wait for the locks or reconciliation this callback must complete.
192
+ */
193
+ reconcile(observation: NativeRefreshObservation): Promise<void>;
194
+ }
195
+ export interface NativeRefreshCoordinatorOptions extends NativePoolStoreOptions, NativeRefreshHooks {
196
+ paths: NativePoolPaths;
197
+ refreshToken?: typeof refreshClaudeOAuthToken;
198
+ resolveIdentity?: typeof resolveClaudeCodeIdentity;
199
+ }
200
+ export interface NativeRefreshRequest {
201
+ intent: 'serve' | 'refresh';
202
+ mode: 'local' | 'claustrum';
203
+ binding: NativeLocalPoolBinding;
204
+ /** A 401's dispatched access token, used only for replacement adoption. */
205
+ rejectedAccessToken?: string;
206
+ signal?: AbortSignal;
207
+ }
208
+ export type NativeRefreshResult = {
209
+ status: 'usable';
210
+ source: 'current' | 'validated' | 'rotated' | 'adopted';
211
+ binding: NativeLocalPoolBinding;
212
+ /**
213
+ * Token from the row addressed by request.binding.rowId whose validation
214
+ * evidence was checked. A caller for another row with the same account UUID
215
+ * may share recovery work, but must not receive the job owner's row token.
216
+ */
217
+ access: string;
218
+ expires: number;
219
+ subject: NativeKnownCredentialSubject;
220
+ validation: NativeLocalCredentialValidation;
221
+ } | {
222
+ status: 'refused';
223
+ reason: string;
224
+ persisted: boolean;
225
+ } | {
226
+ status: 'identity-contradicted';
227
+ expectedIdentity: string;
228
+ returnedIdentity: string;
229
+ persisted: true;
230
+ } | {
231
+ status: 'failed';
232
+ failure: NativeRefreshFailure;
233
+ persisted: boolean;
234
+ reconciliationFailed: boolean;
235
+ };
236
+ /** Independent local machinery: construction performs no network or migration. */
237
+ export declare function createNativeRefreshCoordinator(options: NativeRefreshCoordinatorOptions): {
238
+ authorize: (request: NativeRefreshRequest) => Promise<NativeRefreshResult>;
239
+ };
240
+ export {};
@@ -0,0 +1,115 @@
1
+ import type { NativeCustodyInventory } from './native-custody.ts';
2
+ /**
3
+ * Builds and re-checks the vault roster seed written while a legacy custody
4
+ * install migrates to the native pool. It is pure: it never lists, reads,
5
+ * refreshes or writes anything. The caller lists the vault, reads the legacy
6
+ * config, resolves the primary route id and owns every file write.
7
+ *
8
+ * The seed keeps the route ids the legacy install already used, so later
9
+ * discovery (which only adds new routes under its own prefix) keeps them.
10
+ * It carries no token, refresh token or other credential material.
11
+ */
12
+ /** Allowed build/check failure codes. Diagnostics contain no caller data. */
13
+ export type NativeRosterSeedErrorCode = 'roster-incomplete' | 'unenrolled-local-row' | 'roster-route-conflict' | 'seed-conflict';
14
+ export declare class NativeRosterSeedError extends Error {
15
+ readonly code: NativeRosterSeedErrorCode;
16
+ constructor(code: NativeRosterSeedErrorCode);
17
+ }
18
+ /** One OAuth account row from the legacy custody config. No secrets. */
19
+ export interface NativeRosterSeedLegacyRow {
20
+ /** The legacy account id; it becomes the seeded route id unchanged. */
21
+ readonly routeId: string;
22
+ /** Vault credential ID associated with this enrolled legacy row, if present. */
23
+ readonly scopedCredentialId?: string;
24
+ readonly anthropicAccountUuid?: string;
25
+ readonly label?: string;
26
+ readonly addedAt?: number;
27
+ /** The user's enable/disable choice for this row. */
28
+ readonly enabled: boolean;
29
+ }
30
+ export interface NativeRosterSeedInput {
31
+ /** The vault list, already verified by the caller's discovery. */
32
+ readonly inventory: NativeCustodyInventory;
33
+ /** The primary credential and account captured from the legacy config. */
34
+ readonly primary: {
35
+ readonly credentialId: string;
36
+ readonly accountIdentity: string;
37
+ };
38
+ /** Route ID assigned by offline migration to the legacy primary Claude account. */
39
+ readonly primaryRouteId: string;
40
+ readonly legacyRows: readonly NativeRosterSeedLegacyRow[];
41
+ /** Accounts the user disabled, by Anthropic account UUID. */
42
+ readonly disabledAccountIdentities: readonly string[];
43
+ /** Route ids taken by imported API-key rows; a seeded route never takes one. */
44
+ readonly reservedRouteIds: readonly string[];
45
+ }
46
+ export interface NativeVaultRosterSeedRow {
47
+ routeId: string;
48
+ credentialId: string;
49
+ credentialType: 'oauth';
50
+ accountIdentity: string;
51
+ state: string;
52
+ label: string;
53
+ enabled: boolean;
54
+ addedAt: number;
55
+ }
56
+ export interface NativeVaultRosterSeedDecline {
57
+ credentialId: string;
58
+ accountIdentity: string;
59
+ }
60
+ /** Fresh secret-free roster, compatible with common-auth's readVaultRoster. */
61
+ export interface NativeVaultRosterSeed {
62
+ version: 1;
63
+ view: string;
64
+ complete: true;
65
+ rows: NativeVaultRosterSeedRow[];
66
+ declined: NativeVaultRosterSeedDecline[];
67
+ }
68
+ /**
69
+ * Stored roster returned by common-auth's readVaultRoster. Account quota,
70
+ * email and organisation metadata do not participate in seed matching.
71
+ */
72
+ export interface NativeVaultRosterDocument {
73
+ readonly version: 1;
74
+ readonly view?: string;
75
+ readonly complete: boolean;
76
+ readonly rejected?: readonly {
77
+ readonly credentialId?: string;
78
+ readonly reason: string;
79
+ }[];
80
+ readonly rows: readonly {
81
+ readonly routeId: string;
82
+ readonly credentialId: string;
83
+ readonly credentialType: 'oauth' | 'api_key';
84
+ readonly accountIdentity?: string;
85
+ readonly aliases?: readonly string[];
86
+ readonly state: string;
87
+ readonly label: string;
88
+ readonly email?: string;
89
+ readonly orgName?: string;
90
+ readonly enabled: boolean;
91
+ readonly addedAt: number;
92
+ readonly quota?: unknown;
93
+ readonly stale?: true;
94
+ readonly unclaimed?: true;
95
+ }[];
96
+ readonly declined: readonly {
97
+ readonly credentialId: string;
98
+ readonly accountIdentity?: string;
99
+ }[];
100
+ }
101
+ /**
102
+ * Build the first seed from the current verified vault list and the captured
103
+ * legacy state. The result is a complete roster the published reader accepts,
104
+ * built only from owned copies, so it shares no object with the input.
105
+ */
106
+ export declare function buildNativeVaultRosterSeed(input: NativeRosterSeedInput): NativeVaultRosterSeed;
107
+ /**
108
+ * Check a seed already on disk against the captured legacy state, so a resumed
109
+ * migration can keep it. Returns nothing: a valid seed is kept exactly as it
110
+ * is, with its original view and states. The current vault list must still
111
+ * pass every refusal, but a changed view or record state alone is not a
112
+ * conflict. Route, credential and account membership, labels, added times and
113
+ * enable/decline choices must match exactly; any difference refuses.
114
+ */
115
+ export declare function validateNativeVaultRosterSeed(existing: NativeVaultRosterDocument, input: NativeRosterSeedInput): void;
@@ -0,0 +1,19 @@
1
+ import type { NativePoolPaths } from './pool-paths.ts';
2
+ /** Compare injected transports and policy callbacks by object identity when selecting a shared runtime. */
3
+ export declare function nativeRuntimeOptionIdentity(value: object | undefined): number | undefined;
4
+ export declare function nativeRuntimeStorageKey(options: {
5
+ paths: NativePoolPaths;
6
+ host: 'opencode' | 'pi';
7
+ env?: NodeJS.ProcessEnv;
8
+ }): string;
9
+ export declare function nativeRuntimeConnectionFile(host: 'opencode' | 'pi', env: NodeJS.ProcessEnv): string;
10
+ /** A release applies to the runtime entry acquired earlier, not to a later entry created with the same key. */
11
+ export declare class NativeRuntimeRegistry<T extends {
12
+ close(): void;
13
+ }> {
14
+ private readonly entries;
15
+ acquire(key: string, create: () => T): {
16
+ use: () => T;
17
+ close: () => void;
18
+ };
19
+ }
@@ -0,0 +1,204 @@
1
+ import type { AccountOperationError, OAuthAccountProfile, PrimeUsageCounters } from './accounts.ts';
2
+ import { type NativeLocalCredentialValidation } from './native-credential-validation.ts';
3
+ import { type NativeQuotaMap } from './native-quota-codec.ts';
4
+ import type { NativeRefreshObservation, NativeRefreshSubject } from './native-refresh-coordinator.ts';
5
+ import { type NativeLocalPoolBinding } from './pool-binding.ts';
6
+ import type { NativePoolPaths } from './pool-paths.ts';
7
+ /** Identifies the vault credential and Claude account that supplied an observation. This binding contains no access token. */
8
+ export interface NativeCustodyRuntimeBinding {
9
+ kind: 'custody';
10
+ storageId: string;
11
+ routeId: string;
12
+ credentialId: string;
13
+ accountIdentity: string;
14
+ recordVersion: number;
15
+ }
16
+ export type NativeRuntimeBinding = NativeLocalPoolBinding | NativeCustodyRuntimeBinding;
17
+ /**
18
+ * A failed account check is recorded against the exact credentials it used.
19
+ * This lets a retry delay apply only to those credentials, without treating
20
+ * the failure as evidence that the account check succeeded.
21
+ */
22
+ export interface NativeLocalValidationRetry {
23
+ readonly subject: Pick<NativeLocalCredentialValidation, 'binding' | 'credentialFingerprint' | 'version'>;
24
+ readonly checkedAt: number;
25
+ readonly nextRetryAt: number;
26
+ }
27
+ /**
28
+ * Match refresh failures using fingerprintOf({ type: 'oauth', refresh }),
29
+ * the full refresh-credential fingerprint. The legacy tokenHash hashes the raw refresh token, and
30
+ * refreshTokenFingerprint is a short hash; neither is an alias for this value.
31
+ * Errors without the explicit full fingerprint preserve error-reset timestamps
32
+ * but cannot restrict a credential.
33
+ */
34
+ export interface NativeLocalRefreshError extends AccountOperationError {
35
+ credentialFingerprint?: string;
36
+ }
37
+ /**
38
+ * Per-account retry errors, profiles, quota-priming usage and observation
39
+ * identifiers stored separately from credentials. Vault quota is stored here;
40
+ * local quota stays in the pool.
41
+ */
42
+ export interface NativeRuntimeEntry {
43
+ binding: NativeRuntimeBinding;
44
+ credentialValidation?: NativeLocalCredentialValidation;
45
+ validationRetry?: NativeLocalValidationRetry;
46
+ lastUsed?: number;
47
+ lastRefreshedAt?: number;
48
+ lastRefreshError?: NativeLocalRefreshError;
49
+ refreshErrorClearedAt?: number;
50
+ refreshLeaseId?: string;
51
+ refreshLeaseUntil?: number;
52
+ refreshLeaseTokenHash?: string;
53
+ lastQuotaRefreshError?: AccountOperationError;
54
+ quotaErrorGeneration?: number;
55
+ quotaErrorClearedAt?: number;
56
+ quota?: NativeQuotaMap;
57
+ quotaCheckedAt?: number;
58
+ quotaToken?: string;
59
+ profile?: OAuthAccountProfile;
60
+ /** No supported writer supplies profileToken, so its value cannot safely be interpreted as an identifier. */
61
+ profileToken?: never;
62
+ prime?: PrimeUsageCounters;
63
+ authLineageId?: string;
64
+ primeAuthLineageRefreshTokenFingerprint?: string;
65
+ }
66
+ export interface NativeRuntimeState {
67
+ version: 1;
68
+ storageId: string;
69
+ accounts: Record<string, NativeRuntimeEntry>;
70
+ relay?: {
71
+ token: string;
72
+ };
73
+ }
74
+ export type NativeRuntimeRead = {
75
+ status: 'missing';
76
+ } | {
77
+ status: 'ready';
78
+ state: NativeRuntimeState;
79
+ };
80
+ export declare class NativeRuntimeError extends Error {
81
+ readonly code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused';
82
+ constructor(code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused');
83
+ }
84
+ /** Validate structure and internal identifier consistency. The publisher separately checks these identifiers against the current pool or vault roster. */
85
+ export declare function decodeNativeRuntime(value: unknown, storageId: string): NativeRuntimeState;
86
+ export declare function readNativeRuntime(path: string, storageId: string): Promise<NativeRuntimeRead>;
87
+ export interface NativeRuntimeWriteHooks {
88
+ /** Verify that the observed account still matches the current pool record or vault roster and that the caller still owns the locks protecting those records. */
89
+ beforeRename?: () => Promise<void>;
90
+ /** Check caller authority after every lease assertion, immediately before replacement. This hook can only refuse publication. */
91
+ beforePublish?: () => Promise<void>;
92
+ /** Runs after the new file replaces the old one. Failure does not undo that replacement. */
93
+ afterRename?: () => Promise<void>;
94
+ }
95
+ /** This writer alone uses `<leaf>.native-runtime.<UUID v4>.partial`. */
96
+ export declare function isNativeRuntimeStagingName(path: string, name: string): boolean;
97
+ /**
98
+ * This file has its own update lock. Account publishers also hold the locks
99
+ * protecting the pool and, for vault accounts, the roster. They verify those
100
+ * locks immediately before replacement. A process paused beyond a lock expiry
101
+ * can overlap a new owner even with normal renewal.
102
+ */
103
+ export declare function updateNativeRuntime(path: string, storageId: string, change: (current: NativeRuntimeState) => NativeRuntimeState | Promise<NativeRuntimeState>, hooks?: NativeRuntimeWriteHooks): Promise<NativeRuntimeState>;
104
+ /**
105
+ * Result of a write whose final check may withdraw it. `skipped` means the
106
+ * staged file was discarded and the runtime file was left as it was.
107
+ */
108
+ export type NativeRuntimeOptionalPublication = {
109
+ status: 'published';
110
+ state: NativeRuntimeState;
111
+ } | {
112
+ status: 'skipped';
113
+ };
114
+ export interface NativeRuntimeOptionalWriteHooks {
115
+ /**
116
+ * Same checks as NativeRuntimeWriteHooks.beforeRename, run at the same
117
+ * point. Resolve 'skip' to discard the staged write without an error; throw
118
+ * to refuse it exactly as a strict write would.
119
+ */
120
+ beforeRename: () => Promise<'publish' | 'skip'>;
121
+ }
122
+ /**
123
+ * For writes that only record information a newer observation makes
124
+ * redundant. The final check can withdraw such a write instead of failing it.
125
+ * The runtime lock is still asserted before a skip is reported, so a lost
126
+ * lock refuses the write either way.
127
+ */
128
+ export declare function updateNativeRuntimeOptional(path: string, storageId: string, change: (current: NativeRuntimeState) => NativeRuntimeState | Promise<NativeRuntimeState>, hooks: NativeRuntimeOptionalWriteHooks): Promise<NativeRuntimeOptionalPublication>;
129
+ /**
130
+ * Core-internal reconciliation of a successfully checked first local UUID.
131
+ * Matching a response to an account disabled after dispatch does not give that
132
+ * account permission to make another model request; admission checks still apply.
133
+ * No caller mutator or publication callback can widen this transition.
134
+ */
135
+ export declare function publishNativeLocalFirstIdentity(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeRuntimeState>;
136
+ /**
137
+ * Record successful credential validation for a local account with a known UUID.
138
+ * Bootstrap must provide the state captured before its request and the exact
139
+ * credentials it checked. An unidentified entry requires first-identity publication.
140
+ * Recording validation for a disabled entry does not enable it or permit serving.
141
+ */
142
+ export declare function publishNativeLocalCredentialValidation(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeRuntimeState>;
143
+ export interface NativeLocalFailurePolicy {
144
+ readonly checkedAt: number;
145
+ /** A nextRetryAt equal to checkedAt adds no delay beyond the recorded failure time. */
146
+ readonly nextRetryAt?: number;
147
+ readonly retryCount?: number;
148
+ }
149
+ export type NativeLocalFailureSkipReason = 'not-a-failure' | 'no-context' | 'not-attributable' | 'missing-committed';
150
+ export type NativeLocalFailureAttribution = {
151
+ readonly kind: 'none';
152
+ readonly reason: NativeLocalFailureSkipReason;
153
+ } | {
154
+ readonly kind: 'refresh-error';
155
+ readonly target: 'captured' | 'committed';
156
+ readonly subject: NativeRefreshSubject;
157
+ readonly permanent: boolean;
158
+ readonly message: 'Local refresh failed' | 'Local account-check recovery required';
159
+ readonly status?: number;
160
+ } | {
161
+ readonly kind: 'validation-retry';
162
+ readonly target: 'captured' | 'committed';
163
+ readonly subject: NativeLocalValidationRetry['subject'];
164
+ } | {
165
+ /**
166
+ * The exchange saved a successor whose access value is not a supported
167
+ * Claude OAuth credential. It is kept because the previous refresh token
168
+ * is consumed, but it is never validated or retried; only a new sign-in
169
+ * replaces it. Publishing it removes refresh-error and retry state no
170
+ * newer than its check, advancing the refresh-error clear marker to the
171
+ * check time when it removes any, and adds no error or backoff.
172
+ */
173
+ readonly kind: 'unsupported-successor';
174
+ readonly target: 'committed';
175
+ readonly subject: NativeRefreshSubject;
176
+ };
177
+ export type NativeLocalFailureSupersededReason = 'row-binding' | 'row-credential' | 'entry-binding' | 'reset-context' | 'already-proven' | 'older-than-stored';
178
+ export type NativeLocalFailurePublication = {
179
+ readonly status: 'published';
180
+ readonly attribution: Exclude<NativeLocalFailureAttribution, {
181
+ kind: 'none';
182
+ }>;
183
+ readonly state: NativeRuntimeState;
184
+ } | {
185
+ readonly status: 'skipped';
186
+ readonly reason: NativeLocalFailureSkipReason;
187
+ } | {
188
+ readonly status: 'superseded';
189
+ readonly reason: NativeLocalFailureSupersededReason;
190
+ };
191
+ /**
192
+ * Classify the captured observation only. Saved credentials identify which
193
+ * account needs recovery, but do not prove a failed refresh or a completed
194
+ * account check. Refuse malformed action inputs rather than infer them from disk.
195
+ */
196
+ export declare function classifyNativeLocalFailure(observation: NativeRefreshObservation): NativeLocalFailureAttribution;
197
+ /**
198
+ * Bind recovery metadata to the exact credential version that produced it.
199
+ * An unsupported replacement token needs sign-in, not another refresh attempt:
200
+ * remove older retry restrictions so they do not hide that account state.
201
+ * This does not validate credentials or repair their account identity. Credentials
202
+ * are saved separately; a metadata write failure cannot undo a token exchange.
203
+ */
204
+ export declare function publishNativeLocalRefreshFailure(paths: NativePoolPaths, observation: NativeRefreshObservation, policy: NativeLocalFailurePolicy, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeLocalFailurePublication>;
@@ -0,0 +1,38 @@
1
+ import { type NativePoolStorePaths } from './pool-store.ts';
2
+ /**
3
+ * A local account could not be authorized because another writer was part
4
+ * way through saving it (for example the refresh that records its first
5
+ * account UUID) and did not finish within the short wait Core allows.
6
+ *
7
+ * The request should be retried. `code: 'ECONNRESET'` is how this package
8
+ * marks an error retryable for its hosts. A host must surface it rather than
9
+ * route the request to a different account, because that account was not the
10
+ * one routing selected. The message is fixed and names no account.
11
+ */
12
+ export declare class NativeTransientAccountError extends Error {
13
+ readonly code: 'ECONNRESET';
14
+ readonly syscall: 'native-account-update';
15
+ constructor();
16
+ }
17
+ /** True only for an error Core itself constructed as NativeTransientAccountError. */
18
+ export declare function isNativeTransientAccountError(value: unknown): value is NativeTransientAccountError;
19
+ /**
20
+ * Wait until no writer holds the pool's store locks, then let them go.
21
+ *
22
+ * Takes the config lock and then the state lock, in the order every pool
23
+ * writer takes them, and releases both (state first) as soon as both are
24
+ * held, without doing anything while holding them. A writer holds both locks
25
+ * across its state-file and config-file writes, so once both have been
26
+ * acquired the earlier write has finished. A writer can start again after
27
+ * release, so the caller rereads the pool and checks for another partially
28
+ * saved row.
29
+ *
30
+ * Returns 'deadline' when the locks could not be taken within the total
31
+ * budget. Each wait between attempts ends early when any of `signals`
32
+ * aborts; `check` is then called after the leases are released and is
33
+ * expected to throw the caller's cancellation error. `check` runs before
34
+ * every attempt too, so a cancelled caller never takes a lock. `now` must be
35
+ * the clock the pool's writers stamp their lock expiry with, or a live
36
+ * writer's lock could be judged expired and taken over.
37
+ */
38
+ export declare function joinNativePoolWrite(paths: NativePoolStorePaths, signals: readonly AbortSignal[], check: () => void, now?: () => number): Promise<'joined' | 'deadline'>;