@cortexkit/anthropic-auth-core 2.0.3 → 2.1.1

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 (40) hide show
  1. package/dist/cachekeep.d.ts +2 -0
  2. package/dist/cch.d.ts +19 -0
  3. package/dist/claude-code.d.ts +8 -2
  4. package/dist/claustrum-enrollment.d.ts +5 -1
  5. package/dist/constants.d.ts +15 -3
  6. package/dist/dump.d.ts +2 -0
  7. package/dist/index.d.ts +7 -5
  8. package/dist/index.js +2698 -478
  9. package/dist/insula-quota.d.ts +25 -0
  10. package/dist/internal-types/claustrum/availability.d.ts +89 -0
  11. package/dist/internal-types/claustrum/consumer.d.ts +41 -1
  12. package/dist/internal-types/claustrum/custody.d.ts +135 -14
  13. package/dist/internal-types/claustrum/errors.d.ts +1 -0
  14. package/dist/internal-types/claustrum/index.d.ts +5 -3
  15. package/dist/internal-types/claustrum/insula.d.ts +48 -0
  16. package/dist/internal-types/claustrum/watch.d.ts +141 -0
  17. package/dist/internal-types/quota/format.d.ts +17 -3
  18. package/dist/internal-types/quota/index.d.ts +2 -2
  19. package/dist/internal-types/quota/projection.d.ts +16 -0
  20. package/dist/internal-types/setup/command-error.d.ts +15 -0
  21. package/dist/internal-types/setup/index.d.ts +2 -2
  22. package/dist/internal-types/setup/types.d.ts +12 -0
  23. package/dist/mid-conversation-output-config.d.ts +12 -15
  24. package/dist/migration-source.d.ts +2 -0
  25. package/dist/native-account-runtime.d.ts +3 -2
  26. package/dist/native-custody.d.ts +130 -0
  27. package/dist/native-enrollment-authority.d.ts +5 -1
  28. package/dist/native-host-auth-read.d.ts +2 -1
  29. package/dist/native-host-auth-write.d.ts +2 -0
  30. package/dist/native-runtime.d.ts +5 -1
  31. package/dist/native-vault-invalidation.d.ts +9 -0
  32. package/dist/native-vault-runtime.d.ts +32 -3
  33. package/dist/owner-only.d.ts +19 -0
  34. package/dist/pool-authority.d.ts +2 -1
  35. package/dist/provider-error.d.ts +34 -0
  36. package/dist/publication-rename.d.ts +11 -0
  37. package/dist/quota-manager.d.ts +21 -4
  38. package/dist/quotas.d.ts +19 -3
  39. package/dist/request-gzip.d.ts +99 -0
  40. package/package.json +4 -4
@@ -11,8 +11,14 @@ export declare const NO_LIMITS_REPORTED = "no limits reported";
11
11
  /**
12
12
  * `compact` fits a footer or a sidebar row: each window's figure, the credit
13
13
  * budget and the stale marker, without reset times. `full` adds each reset.
14
+ * `narrow` fits one line per account in a narrow sidebar: `5h 92% · 7d 66%
15
+ * · Fa 98% left`, the account-wide windows plus at most one model-scoped
16
+ * window or the budget (as `cr`), and no stale marker (see `isQuotaStale`).
17
+ * A reading whose windows belong to named groups and that has no
18
+ * account-wide window reads up to two groups instead:
19
+ * `Ge 7d 62% · Ot 7d 48% left`.
14
20
  */
15
- export type QuotaTextForm = 'compact' | 'full';
21
+ export type QuotaTextForm = 'compact' | 'full' | 'narrow';
16
22
  export interface QuotaTextOptions {
17
23
  /** The current time in ms, for reset countdowns and the stale marker. */
18
24
  now: number;
@@ -55,17 +61,25 @@ export declare function quotaWindowName(limit: Pick<ProjectedLimit, 'scope' | 'l
55
61
  * and the optional age keep the shared formatter's wording.
56
62
  */
57
63
  export declare function quotaWindowParts(quota: ProjectedQuota | undefined, options: QuotaTextOptions): QuotaParts;
64
+ /**
65
+ * Whether the reading is stale: true exactly when the compact and full forms
66
+ * would end with `checked … ago`. The narrow form leaves that age out to stay
67
+ * short, so a caller drawing a narrow line uses this to dim it instead.
68
+ */
69
+ export declare function isQuotaStale(quota: ProjectedQuota | undefined, options: QuotaTextOptions): boolean;
58
70
  /**
59
71
  * The pieces of a quota text, in order: one per reported window
60
72
  * (`5h 58% left, resets 2h`), then the credit budget when there is one, then
61
73
  * `checked 3h ago` when the oldest piece shown is stale. Empty when nothing
62
74
  * was reported; `formatQuota` turns that into a sentence. A caller printing
63
- * one line per window (the terminal auth menu) uses these directly.
75
+ * one line per window (the terminal auth menu) uses these directly. In the
76
+ * narrow form the pieces are the narrow line's (`5h 92%`, `7d 66% left`).
64
77
  */
65
78
  export declare function quotaTextParts(quota: ProjectedQuota | undefined, options: QuotaTextOptions): string[];
66
79
  /**
67
80
  * A row's quota as one line: `5h 58% left · 7d 90% left` in the compact
68
- * form, with `, resets 2h` after each window in the full form. With nothing
81
+ * form, with `, resets 2h` after each window in the full form, and
82
+ * `5h 58% · 7d 90% left` in the narrow form. With nothing
69
83
  * reported it is `NO_QUOTA_READING`, or `NO_LIMITS_REPORTED` when the
70
84
  * provider answered without a limit for any window.
71
85
  */
@@ -1,10 +1,10 @@
1
1
  export type { QuotaCodec } from './codec.js';
2
2
  export { quotaCodec } from './codec.js';
3
3
  export type { QuotaParts, QuotaTextForm, QuotaTextOptions, QuotaWindowPart, } from './format.js';
4
- export { formatQuota, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
4
+ export { formatQuota, isQuotaStale, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
5
5
  export type { CreditBudgetCleared, CreditBudgetEntry, CreditBudgetReading, QuotaAbsentEntry, QuotaCounter, QuotaEntry, QuotaMap, QuotaReadingEntry, QuotaRetiredEntry, } from './map.js';
6
6
  export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, decodeQuotaMap, emptyQuotaMap, isQuotaMap, } from './map.js';
7
7
  export type { ObservedBudget, ObservedPair, ObservedReading, QuotaObservation, } from './merge.js';
8
8
  export { isQuotaObservation, mergeQuotaObservation, QuotaCodecError, } from './merge.js';
9
- export type { ExhaustionReset, ProjectedBudget, ProjectedLimit, ProjectedQuota, } from './projection.js';
9
+ export type { ExhaustionReset, ProjectedBudget, ProjectedLimit, ProjectedQuota, QuotaGroup, } from './projection.js';
10
10
  export { budgetExhaustedResetAt, futureResetAt, projectQuota, readsExhausted, } from './projection.js';
@@ -19,6 +19,15 @@ export interface ProjectedBudget {
19
19
  remainingPercent?: number;
20
20
  resetsAt?: string;
21
21
  }
22
+ /**
23
+ * A named group of windows, such as antigravity-auth's `Gemini` and
24
+ * `Other models`: every window stored under `scope` belongs to it, and
25
+ * `label` is the group's display name.
26
+ */
27
+ export interface QuotaGroup {
28
+ scope: string;
29
+ label: string;
30
+ }
22
31
  export interface ProjectedQuota {
23
32
  scope: string;
24
33
  /** One entry per label: longest known window first, unknown lengths last. */
@@ -31,6 +40,13 @@ export interface ProjectedQuota {
31
40
  /** Present only when the stored budget is a reading, not cleared. */
32
41
  budget?: ProjectedBudget;
33
42
  counters?: Record<string, QuotaCounter>;
43
+ /**
44
+ * The named groups the windows belong to, in the order the plugin lists
45
+ * them. Set only by a plugin whose windows all belong to such groups; the
46
+ * narrow form then shows one item per group (see `formatQuota`).
47
+ * `projectQuota` never sets it.
48
+ */
49
+ groups?: readonly QuotaGroup[];
34
50
  }
35
51
  /**
36
52
  * Resolves `map` for a request in `scope` (`all` or a model family). A family
@@ -1,3 +1,4 @@
1
+ import type { SetupHostEnrollment } from './types.js';
1
2
  /**
2
3
  * Keeps the Pi install refusal message stable while exposing safe process details.
3
4
  * A clipped tail can start inside a credential, so discard its first line—or
@@ -15,3 +16,17 @@ export declare class SetupCommandError extends Error {
15
16
  stderrTruncated?: boolean;
16
17
  });
17
18
  }
19
+ /** The line setup prints for one host's outcome, e.g. `Pi: not connected`. */
20
+ export declare function setupEnrollmentLine({ host, outcome, }: SetupHostEnrollment): string;
21
+ /**
22
+ * Remember which hosts a failed setup left connected to the vault, against the
23
+ * thrown value. Only objects can carry a record; a thrown primitive is left as
24
+ * it is, and the printed lines are then the only report.
25
+ */
26
+ export declare function recordSetupEnrollment(failure: unknown, enrollment: readonly SetupHostEnrollment[]): void;
27
+ /**
28
+ * The per-host vault enrollment outcomes a failed `runSetup` recorded for the
29
+ * value it threw, or `undefined` when setup failed before any host's enrollment
30
+ * began, or the value is not one setup threw (or is not an object).
31
+ */
32
+ export declare function setupEnrollment(error: unknown): readonly SetupHostEnrollment[] | undefined;
@@ -1,6 +1,6 @@
1
1
  export { AMBIGUOUS_OPENCODE_MESSAGE, runSetup } from './command.js';
2
- export { SetupCommandError } from './command-error.js';
2
+ export { SetupCommandError, setupEnrollment } from './command-error.js';
3
3
  export { detectHosts, detectOpenCodeGeneration, findExecutableOnPath, openCodeDesktopMarkers, } from './detect.js';
4
4
  export { assertHostsStopped, createProcessFence, listSetupProcesses, ProcessFenceViolationError, ProcessInspectionError, type ProcessInspectionStep, } from './process-fence.js';
5
5
  export { type PlannedWrite, planOpenCodeRegistration, registerOpenCode, registerPi, updatePluginConfig, } from './register.js';
6
- export type { CommandResult, CommandRunner, HostDetection, OpenCodeGeneration, ProcessFence, SetupCallbackContext, SetupDetection, SetupEnvironment, SetupFileSystem, SetupHost, SetupIO, SetupPlugin, SetupResult, } from './types.js';
6
+ export type { CommandResult, CommandRunner, HostDetection, OpenCodeGeneration, ProcessFence, SetupCallbackContext, SetupDetection, SetupEnrollmentOutcome, SetupEnvironment, SetupFileSystem, SetupHost, SetupHostEnrollment, SetupIO, SetupPlugin, SetupResult, } from './types.js';
@@ -3,6 +3,18 @@ import type { ClaustrumEnrollmentConnection, hostEnrollmentPaths } from '../clau
3
3
  export type SetupHost = 'opencode' | 'pi';
4
4
  export type OpenCodeGeneration = '1' | '2' | 'both';
5
5
  export type SetupEnvironment = Record<string, string | undefined>;
6
+ /**
7
+ * What a setup run recorded about one host's vault enrollment when it failed:
8
+ * `enrolled` once approval landed and the token was written, `not-enrolled`
9
+ * when the host was never asked or its enrollment was refused or gave up
10
+ * waiting, and `unknown` when setup failed while the enrollment was still in
11
+ * flight and the host's token file could not settle it.
12
+ */
13
+ export type SetupEnrollmentOutcome = 'enrolled' | 'not-enrolled' | 'unknown';
14
+ export interface SetupHostEnrollment {
15
+ host: SetupHost;
16
+ outcome: SetupEnrollmentOutcome;
17
+ }
6
18
  /**
7
19
  * What setup decided before calling a plugin callback. The OpenCode generation
8
20
  * is the one being registered, after `--opencode` or the interactive choice, so
@@ -1,9 +1,7 @@
1
- /** Per-message effort beta sent with every OAuth Fable 5.1 request. */
2
- export declare const MID_CONVERSATION_OUTPUT_CONFIG_BETA = "mid-conversation-output-config-2026-07-01";
3
1
  /**
4
- * Per-turn control beta that Claude Code sends on every Opus 5.5 and Sonnet
5
- * 5.5 request. It enables effort changes carried by an empty `role: "system"`
6
- * message on those two models.
2
+ * Per-turn control beta that Claude Code sends on Opus 5.5, Sonnet 5.5,
3
+ * Fable 5.1 and Haiku 5.5. It enables effort changes carried by empty
4
+ * `role: "system"` messages on the eligible models below.
7
5
  */
8
6
  export declare const PER_TURN_CONTROL_BETA = "per-turn-control-2026-07-01";
9
7
  export type AdaptiveEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
@@ -14,19 +12,18 @@ export type MidConversationEffortTransition = {
14
12
  };
15
13
  export declare function normalizeAdaptiveEffort(value: unknown): AdaptiveEffort | undefined;
16
14
  /**
17
- * Whether an OAuth request for this model carries the Fable 5.1 per-message
18
- * effort beta (`MID_CONVERSATION_OUTPUT_CONFIG_BETA`). Opus 5.5 and Sonnet
19
- * 5.5 use `PER_TURN_CONTROL_BETA` instead.
15
+ * Models that require adaptive thinking for per-message effort: Opus 5.5
16
+ * and Sonnet 5.5, including dated and `[1m]` context-window ids. Header
17
+ * eligibility is separate; `sendsPerTurnControlBeta` follows Claude Code.
20
18
  */
21
- export declare function usesMidConversationOutputConfig(body: Record<string, unknown>): boolean;
19
+ export declare function usesPerTurnControl(model: unknown): boolean;
22
20
  /**
23
- * Opus 5.5 and Sonnet 5.5, including dated and `[1m]` context-window ids.
24
- * Their OAuth requests always carry `PER_TURN_CONTROL_BETA`, as Claude Code's
25
- * do. Anthropic also documents per-message effort for Mythos 5.1, Opus 5 and
26
- * Haiku 5.5, but without a Claude Code capture to match, those models keep
27
- * sending requests without the beta or effort markers.
21
+ * Models whose OAuth requests carry `PER_TURN_CONTROL_BETA`: Opus 5.5 and
22
+ * Sonnet 5.5, plus Fable 5.1 and Haiku 5.5, which Claude Code 2.1.302 also
23
+ * sends it on. Sending the beta does not by itself make a model eligible for
24
+ * effort markers; `supportsPerMessageEffort` decides that.
28
25
  */
29
- export declare function usesPerTurnControl(model: unknown): boolean;
26
+ export declare function sendsPerTurnControlBeta(model: unknown): boolean;
30
27
  /**
31
28
  * Whether a request may move effort changes into empty system messages.
32
29
  *
@@ -1,3 +1,4 @@
1
+ import { type OwnerOnlyOptions } from './owner-only.ts';
1
2
  export type NativeMigrationSourceRole = 'config' | 'state' | 'hostAuth' | 'routing' | 'journal';
2
3
  export interface NativeMigrationSourceSnapshot {
3
4
  readonly role: NativeMigrationSourceRole;
@@ -20,6 +21,7 @@ export declare class NativeMigrationSourceError extends Error {
20
21
  }
21
22
  interface SourceReadHooks {
22
23
  onOpened?: () => Promise<void>;
24
+ ownership?: OwnerOnlyOptions;
23
25
  }
24
26
  /**
25
27
  * Capture exact import bytes without the legacy loader's missing-entry recovery.
@@ -7,7 +7,7 @@ import { type NativeLocalCredentialServiceOptions } from './native-local-credent
7
7
  import type { NativeLocalExternalPolicy } from './native-local-runtime-readers.ts';
8
8
  import { type NativeQuotaObservations } from './native-quota-observations.ts';
9
9
  import type { NativeKnownCredentialSubject, NativeRefreshResult, NativeRefreshSubject } from './native-refresh-coordinator.ts';
10
- import { type NativeDisplayProfile, type NativeVaultRuntime, type NativeVaultRuntimeOptions } from './native-vault-runtime.ts';
10
+ import { type NativeDisplayProfile, type NativeVaultQuotaPurpose, type NativeVaultRuntime, type NativeVaultRuntimeOptions } from './native-vault-runtime.ts';
11
11
  import { type NativeLocalPoolBinding } from './pool-binding.ts';
12
12
  import { type NativePoolPaths } from './pool-paths.ts';
13
13
  import type { QuotaRequestDispatch } from './quota-manager.ts';
@@ -106,7 +106,8 @@ export interface NativeAccountRuntime {
106
106
  resetBackoff(routeId: string, fence: NativeRefreshSubject | NativeCustodyReceipt, kind?: 'refresh' | 'quota' | 'all'): Promise<boolean>;
107
107
  getOrCreateAuthLineage(routeId: string, fence: NativeKnownCredentialSubject | NativeCustodyReceipt): Promise<string | undefined>;
108
108
  incrementPrimeUsage(routeId: string, fence: NativeKnownCredentialSubject | NativeCustodyReceipt, delta?: PrimeUsageDelta): Promise<boolean>;
109
- fetchQuota(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal, dispatch?: QuotaRequestDispatch): Promise<OAuthQuotaSnapshot>;
109
+ /** `purpose` applies to vault accounts only; local accounts always poll. */
110
+ fetchQuota(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal, dispatch?: QuotaRequestDispatch, purpose?: NativeVaultQuotaPurpose): Promise<OAuthQuotaSnapshot>;
110
111
  fetchProfile(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<OAuthAccountProfile>;
111
112
  /** Like fetchProfile, but returns before the profile is saved; see NativeDisplayProfile. */
112
113
  fetchProfileForDisplay(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<NativeDisplayProfile>;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Reads insula's quota cache from the vault daemon. Declared here with the
3
+ * same shape as common-auth's InsulaUsageTransport so this module's published
4
+ * declarations do not depend on common-auth.
5
+ */
6
+ export interface NativeInsulaUsageTransport {
7
+ connectionFile: string;
8
+ getUsage(): Promise<unknown>;
9
+ }
1
10
  /** Claustrum IPC operations for listing accounts, reading tokens, reporting rejection, and closing the connection. */
2
11
  export interface NativeCustodyClient {
3
12
  listScoped: (enrollmentToken?: string) => Promise<{
@@ -18,6 +27,16 @@ export interface NativeCustodyClient {
18
27
  readonly email?: string;
19
28
  readonly orgName?: string;
20
29
  }[];
30
+ /**
31
+ * How many grants this enrollment holds, and which. Undefined when the
32
+ * vault is too old to send them: unknown, never zero.
33
+ */
34
+ readonly grants: number | undefined;
35
+ readonly grantTuples: readonly {
36
+ readonly selectorKind: string;
37
+ readonly selector: string;
38
+ readonly operation: string;
39
+ }[] | undefined;
21
40
  }>;
22
41
  getScoped: (input: {
23
42
  credentialId: string;
@@ -41,6 +60,79 @@ export interface NativeCustodyClient {
41
60
  reporterSource: NativeCustodyReporterSource;
42
61
  }) => Promise<void>;
43
62
  close: () => void;
63
+ /**
64
+ * Open one vault watch that announces changes to the accounts this
65
+ * enrollment can see. Present from claustrum-client 0.12.0; without it the
66
+ * host keeps listing on its own timer.
67
+ */
68
+ watchScoped?(onNotice: (notice: NativeScopedWatchNotice) => void, options?: {
69
+ enrollmentToken?: string;
70
+ }): NativeScopedWatchHandle;
71
+ /**
72
+ * How to read insula's background quota cache on the same daemon. Present
73
+ * when the connection was made with connectClaustrumScopedClient; reading
74
+ * it opens a separate short-lived socket and never uses this connection.
75
+ */
76
+ insula?: NativeInsulaUsageTransport;
77
+ }
78
+ /**
79
+ * A vault watch notice. `view` is the same digest `listScoped` returns, so
80
+ * only a different view means the visible accounts changed. Declared here,
81
+ * like the rest of this client shape, so published declarations do not
82
+ * depend on claustrum-client or common-auth.
83
+ */
84
+ export interface NativeScopedWatchNotice {
85
+ readonly kind: string;
86
+ readonly epoch: string;
87
+ readonly seq: number;
88
+ readonly view: string;
89
+ }
90
+ /**
91
+ * How a vault watch ended. `refused` carries the vault's refusal of the
92
+ * confirming account listing (a revoked enrollment answers `not_found`);
93
+ * `unsupported` means the vault does not know the watch method.
94
+ */
95
+ export type NativeScopedWatchEnd = {
96
+ readonly kind: 'refused';
97
+ readonly error: unknown;
98
+ } | {
99
+ readonly kind: 'transport_lost';
100
+ readonly error: unknown;
101
+ } | {
102
+ readonly kind: 'ended' | 'not_accepting' | 'unsupported' | 'stopped';
103
+ };
104
+ export interface NativeScopedWatchHandle {
105
+ stop(): void;
106
+ readonly closed: Promise<NativeScopedWatchEnd>;
107
+ }
108
+ /**
109
+ * How the host currently learns about account changes. `watching`: a vault
110
+ * watch is open, so the host's list timer only needs to run as a slow safety
111
+ * net. `polling` and `fallback`: no watch is open, so the host lists at its
112
+ * usual pace.
113
+ */
114
+ export type NativeRosterWatchMode = 'watching' | 'polling' | 'fallback';
115
+ export interface NativeRosterWatchOptions {
116
+ /**
117
+ * Run the host's discovery and roster publication. Called when a notice
118
+ * shows the visible accounts changed since the roster the host holds; one
119
+ * call at a time, and notices that arrive meanwhile earn at most one more.
120
+ */
121
+ onView: (view: string) => unknown;
122
+ /** The view of the roster the host currently holds, if any. */
123
+ view?: () => string | undefined;
124
+ onMode?: (mode: NativeRosterWatchMode) => void;
125
+ /**
126
+ * The vault refused the watch and its confirming listing. Kept receipts are
127
+ * already dropped, as a refused listing drops them.
128
+ */
129
+ onRefused?: (error: unknown) => void;
130
+ onError?: (error: unknown) => void;
131
+ }
132
+ export interface NativeRosterWatch {
133
+ readonly mode: NativeRosterWatchMode;
134
+ /** Stop the watch and its timers. Safe to call more than once. */
135
+ close(): void;
44
136
  }
45
137
  export type NativeCustodyReporterSource = 'direct' | 'relay_status_field' | 'relay_message_parse';
46
138
  export interface NativeCustodyLogger {
@@ -57,6 +149,12 @@ export interface NativeCustodyOptions {
57
149
  env?: NodeJS.ProcessEnv;
58
150
  now?: () => number;
59
151
  logger?: NativeCustodyLogger;
152
+ /**
153
+ * Timer functions for the custody's outage probe and roster watch retries.
154
+ * Defaults to the global ones; tests pass their own.
155
+ */
156
+ setTimeout?: typeof globalThis.setTimeout;
157
+ clearTimeout?: typeof globalThis.clearTimeout;
60
158
  }
61
159
  export interface NativeCustodyIdentity {
62
160
  readonly credentialId: string;
@@ -74,6 +172,7 @@ export interface NativeCustodyReceipt {
74
172
  readonly recordVersion: number;
75
173
  readonly expiresAtMs: number | null;
76
174
  readonly accessToken: string;
175
+ readonly fromKeptReceipt?: true;
77
176
  }
78
177
  export interface NativeCustodyInventory {
79
178
  readonly view: string;
@@ -89,6 +188,20 @@ export interface NativeCustodyInventory {
89
188
  readonly credentialId?: string;
90
189
  readonly reason: 'empty credential id' | 'duplicate credential id' | 'blank account identity' | 'empty state';
91
190
  }[];
191
+ /**
192
+ * What this host's enrollment is granted, as the vault's list reply named
193
+ * it. It explains an empty listing: `grants === 0` means no grant at all,
194
+ * while `grants > 0` means a grant that reaches no credential. Undefined
195
+ * means unknown (the vault predates these fields), never zero grants.
196
+ */
197
+ readonly grantReach?: {
198
+ readonly grants: number;
199
+ readonly tuples: readonly {
200
+ readonly selectorKind: string;
201
+ readonly selector: string;
202
+ readonly operation: string;
203
+ }[];
204
+ };
92
205
  }
93
206
  export type NativeCustodyErrorCode = 'closed' | 'not-enrolled' | 'invalid-token' | 'unavailable' | 'identity-changed' | 'identity-unasserted' | 'insufficient-validity' | 'invalid-material' | 'not-active' | 'route-unavailable' | 'route-declined' | 'no-receipt' | 'unsafe-file' | 'invalid-state' | 'wrong-consumer' | 'roster-busy' | 'host-slot-login' | 'host-slot-placeholder' | 'placeholder-refresh';
94
207
  export declare class NativeCustodyError extends Error {
@@ -108,6 +221,23 @@ export interface NativeCustody {
108
221
  authorize: (identity: NativeCustodyIdentity, signal?: AbortSignal) => Promise<NativeCustodyReceipt>;
109
222
  reportFailure: (receipt: NativeCustodyReceipt, status: number, reporterSource: NativeCustodyReporterSource) => Promise<void>;
110
223
  prepareRetry: (served: NativeCustodyReceipt, signal?: AbortSignal) => Promise<NativeCustodyRetry>;
224
+ /** The shared connection's insula transport, connecting first if needed; undefined when the client has none. */
225
+ insulaTransport: () => Promise<NativeInsulaUsageTransport | undefined>;
226
+ retain: (rows: readonly (NativeCustodyIdentity & {
227
+ enabled: boolean;
228
+ state: string;
229
+ })[]) => void;
230
+ forget: (credentialId: string) => void;
231
+ keptReceiptState: () => Readonly<{
232
+ active: boolean;
233
+ since: number | null;
234
+ }>;
235
+ /**
236
+ * Watch the vault for account changes over the shared connection instead
237
+ * of relying on the host's list timer alone. A client or vault without the
238
+ * watch reports `fallback`. Closing the custody closes every watch.
239
+ */
240
+ watchRoster: (options: NativeRosterWatchOptions) => NativeRosterWatch;
111
241
  close: () => void;
112
242
  }
113
243
  /** Share a lazy Claustrum connection; each authorize call reads a fresh enrollment token and OAuth receipt. */
@@ -1,2 +1,6 @@
1
+ import { enrollmentAuthority, readClaustrumEnrollmentStatus } from "./internal-types/claustrum/index.js";
1
2
  /** Enrollment files, not account settings, choose the host's credential source. */
2
- export declare function readNativeEnrollmentMode(host: 'opencode' | 'pi', env?: NodeJS.ProcessEnv): Promise<'local' | 'claustrum'>;
3
+ export declare function readNativeEnrollmentMode(host: 'opencode' | 'pi', env?: NodeJS.ProcessEnv, dependencies?: {
4
+ enrollmentAuthority: typeof enrollmentAuthority;
5
+ readClaustrumEnrollmentStatus: typeof readClaustrumEnrollmentStatus;
6
+ }): Promise<'local' | 'claustrum'>;
@@ -1,3 +1,4 @@
1
1
  import { type NativeHostAuthEntryInspection } from './native-host-auth.ts';
2
+ import { type OwnerOnlyOptions } from './owner-only.ts';
2
3
  /** Read only the host's login classification; credentials and source fingerprints never leave this boundary. */
3
- export declare function readNativeHostAuthKind(host: 'opencode' | 'pi', path: string): Promise<NativeHostAuthEntryInspection['kind']>;
4
+ export declare function readNativeHostAuthKind(host: 'opencode' | 'pi', path: string, ownership?: OwnerOnlyOptions): Promise<NativeHostAuthEntryInspection['kind']>;
@@ -1,3 +1,4 @@
1
+ import { type PublicationOptions } from './publication-rename.ts';
1
2
  export interface NativeHostAuthWriteInput {
2
3
  readonly host: 'opencode' | 'pi';
3
4
  /**
@@ -16,6 +17,7 @@ export interface NativeHostAuthWriteInput {
16
17
  readonly processFence: () => Promise<void>;
17
18
  }
18
19
  export interface NativeHostAuthWriteHooks {
20
+ readonly publication?: PublicationOptions;
19
21
  readonly beforeRecheck?: () => Promise<void>;
20
22
  readonly beforeRename?: () => Promise<void>;
21
23
  readonly afterRename?: () => Promise<void>;
@@ -2,8 +2,10 @@ import type { AccountOperationError, OAuthAccountProfile, PrimeUsageCounters } f
2
2
  import { type NativeLocalCredentialValidation } from './native-credential-validation.ts';
3
3
  import { type NativeQuotaMap } from './native-quota-codec.ts';
4
4
  import type { NativeRefreshObservation, NativeRefreshSubject } from './native-refresh-coordinator.ts';
5
+ import { type OwnerOnlyOptions } from './owner-only.ts';
5
6
  import { type NativeLocalPoolBinding } from './pool-binding.ts';
6
7
  import type { NativePoolPaths } from './pool-paths.ts';
8
+ import { type PublicationOptions } from './publication-rename.ts';
7
9
  /** Identifies the vault credential and Claude account that supplied an observation. This binding contains no access token. */
8
10
  export interface NativeCustodyRuntimeBinding {
9
11
  kind: 'custody';
@@ -83,8 +85,9 @@ export declare class NativeRuntimeError extends Error {
83
85
  }
84
86
  /** Validate structure and internal identifier consistency. The publisher separately checks these identifiers against the current pool or vault roster. */
85
87
  export declare function decodeNativeRuntime(value: unknown, storageId: string): NativeRuntimeState;
86
- export declare function readNativeRuntime(path: string, storageId: string): Promise<NativeRuntimeRead>;
88
+ export declare function readNativeRuntime(path: string, storageId: string, ownership?: OwnerOnlyOptions): Promise<NativeRuntimeRead>;
87
89
  export interface NativeRuntimeWriteHooks {
90
+ publication?: PublicationOptions;
88
91
  /** 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
92
  beforeRename?: () => Promise<void>;
90
93
  /** Check caller authority after every lease assertion, immediately before replacement. This hook can only refuse publication. */
@@ -112,6 +115,7 @@ export type NativeRuntimeOptionalPublication = {
112
115
  status: 'skipped';
113
116
  };
114
117
  export interface NativeRuntimeOptionalWriteHooks {
118
+ publication?: PublicationOptions;
115
119
  /**
116
120
  * Same checks as NativeRuntimeWriteHooks.beforeRename, run at the same
117
121
  * point. Resolve 'skip' to discard the staged write without an error; throw
@@ -0,0 +1,9 @@
1
+ import type { NativeVaultRosterDocument } from './native-roster-seed.ts';
2
+ export declare function watchNativeVaultAuthority(holder: {
3
+ roster: string;
4
+ tokenPath: string;
5
+ retain: (roster: NativeVaultRosterDocument | undefined) => void;
6
+ close: () => void;
7
+ }): () => void;
8
+ export declare function retainNativeVaultRoster(path: string, roster: NativeVaultRosterDocument | undefined): void;
9
+ export declare function closeNativeVaultAuthority(tokenPath: string): void;
@@ -1,4 +1,4 @@
1
- import { type ClaustrumClientOptions } from '@cortexkit/claustrum-client';
1
+ import type { ClaustrumClientOptions } from '@cortexkit/claustrum-client';
2
2
  import { type OAuthAccountProfile, type OAuthQuotaSnapshot, type PrimeUsageDelta } from './accounts.ts';
3
3
  import { type NativeAccountMetadataPatch } from './native-account-view.ts';
4
4
  import { type NativeCustodyClient, type NativeCustodyInventory, type NativeCustodyReceipt, type NativeCustodyReporterSource, type NativeCustodyRetry } from './native-custody.ts';
@@ -7,7 +7,7 @@ import { type NativeRosterSeedInput, type NativeVaultRosterDocument, type Native
7
7
  import { type NativeRuntimeState } from './native-runtime.ts';
8
8
  import type { NativeVaultPaths } from './native-vault-paths.ts';
9
9
  import type { NativePoolPaths } from './pool-paths.ts';
10
- import type { QuotaRequestDispatch } from './quota-manager.ts';
10
+ import type { QuotaReadingPurpose, QuotaRequestDispatch } from './quota-manager.ts';
11
11
  export interface NativeVaultRuntimeOptions {
12
12
  paths: NativePoolPaths;
13
13
  host: 'opencode' | 'pi';
@@ -21,7 +21,34 @@ export interface NativeVaultRuntimeOptions {
21
21
  }>;
22
22
  env?: NodeJS.ProcessEnv;
23
23
  now?: () => number;
24
+ /**
25
+ * Timer functions for the vault custody's outage probe and roster watch
26
+ * retries. Defaults to the global ones; tests pass their own.
27
+ */
28
+ setTimeout?: typeof globalThis.setTimeout;
29
+ clearTimeout?: typeof globalThis.clearTimeout;
30
+ /**
31
+ * Called each time the runtime has finished handling a vault notice that
32
+ * asked it to rediscover the roster, after the discovery that notice ran.
33
+ * Common-auth asks when the notice's view differs from the roster held,
34
+ * after a gap in the notices, and on a re-subscribed watch's first notice.
35
+ * Tests use it to wait for that handling instead of for the clock.
36
+ */
37
+ onRosterNoticeHandled?: () => void;
24
38
  }
39
+ /**
40
+ * Why a vault quota reading is wanted, which decides whether insula's
41
+ * background quota cache may answer instead of Anthropic's usage endpoint.
42
+ * - 'background': a periodic sweep. Refresh insula's cache (at most once a
43
+ * minute per daemon and enrollment), look the route's account up in it,
44
+ * and skip the usage GET when it holds a current reading.
45
+ * - 'admission': a request needs a reading. Look the served credential's
46
+ * account up in insula's cache only, never refreshing it, then poll on a
47
+ * miss.
48
+ * Omitted: poll Anthropic directly (explicit user refreshes and other
49
+ * callers that must see the provider's own reading).
50
+ */
51
+ export type NativeVaultQuotaPurpose = QuotaReadingPurpose;
25
52
  export interface NativeVaultWatchOptions {
26
53
  intervalMs: number;
27
54
  onRefresh?: () => void | Promise<void>;
@@ -73,7 +100,7 @@ export interface NativeVaultRuntime {
73
100
  */
74
101
  prepareRetry(receipt: NativeCustodyReceipt, signal?: AbortSignal, site?: NativeScoped401Site): Promise<NativeCustodyRetry>;
75
102
  publish(receipt: NativeCustodyReceipt, patch: NativeAccountMetadataPatch): Promise<boolean>;
76
- fetchQuota(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal, dispatch?: QuotaRequestDispatch): Promise<OAuthQuotaSnapshot>;
103
+ fetchQuota(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal, dispatch?: QuotaRequestDispatch, purpose?: NativeVaultQuotaPurpose): Promise<OAuthQuotaSnapshot>;
77
104
  fetchProfile(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<OAuthAccountProfile>;
78
105
  /** Return the fetched account profile without waiting for its metadata write. NativeDisplayProfile.persisted reports whether that asynchronous write succeeded, failed or was refused. */
79
106
  fetchProfileForDisplay(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<NativeDisplayProfile>;
@@ -95,6 +122,8 @@ export declare function publishNativeVaultRosterSeed(paths: Pick<NativeVaultPath
95
122
  export declare function publishNativeVaultRuntimeSeed(paths: Pick<NativeVaultPaths, 'roster' | 'runtime' | 'storageId'>, state: NativeRuntimeState, options?: {
96
123
  assertOwned?: () => Promise<void>;
97
124
  }): Promise<void>;
125
+ /** Connect through the same short deadline used when requests wait for a vault roster. */
126
+ export declare function connectNativeVaultScopedClient(connectionFile: string, identity?: ClaustrumClientOptions['identity']): Promise<import("./internal-types/claustrum/index.js").ClaustrumScopedClient>;
98
127
  /** List accounts readable by this host's enrollment for offline setup. An inventory grants no bearer authority; every outbound request still needs a fresh scoped receipt. */
99
128
  export declare function discoverNativeVaultInventory(options: NativeVaultRuntimeOptions, signal?: AbortSignal): Promise<NativeCustodyInventory>;
100
129
  /** Retain the vault client's original per-attempt receipts and version provenance; access tokens never persist in roster or runtime metadata. */
@@ -0,0 +1,19 @@
1
+ import type * as PrivateFiles from '@cortexkit/private-files';
2
+ /** Per-operation injection keeps simulated Windows policy out of process globals. */
3
+ export interface OwnerOnlyOptions {
4
+ platform?: NodeJS.Platform;
5
+ privateFiles?: Pick<typeof PrivateFiles, 'verifyOwnerOnly' | 'readPrivateFile'> & Partial<Pick<typeof PrivateFiles, 'verifySafeParent' | 'createPrivateFile' | 'createPrivateDirectory'>>;
6
+ }
7
+ /** POSIX callers retain their exact mode/uid policy; Windows must prove its DACL. */
8
+ export declare function isOwnerOnly(path: string, posix: () => boolean, options?: OwnerOnlyOptions): Promise<boolean>;
9
+ /** Windows reads through the ACL-verified native handle, not a pathname reopen. */
10
+ export declare function readWindowsOwnerOnly(path: string, options?: OwnerOnlyOptions): Promise<Buffer | undefined>;
11
+ /** Ancestors protect directory entries; they need not themselves be private. */
12
+ export declare function isSafeWindowsParent(path: string, options?: OwnerOnlyOptions): Promise<boolean | undefined>;
13
+ /** Native creation establishes a protected DACL before any bytes are written. */
14
+ export declare function createWindowsOwnerOnly(path: string, bytes: string, options?: OwnerOnlyOptions): Promise<boolean>;
15
+ /**
16
+ * Create only missing Windows directories; never tighten an existing shared directory.
17
+ * Returns false off Windows so callers retain their POSIX directory policy.
18
+ */
19
+ export declare function ensureWindowsOwnerOnlyDirectory(path: string, options?: OwnerOnlyOptions): Promise<boolean>;
@@ -1,4 +1,5 @@
1
1
  import { type NativeMigrationPreparedProof } from './native-migration-proof.ts';
2
+ import { type OwnerOnlyOptions } from './owner-only.ts';
2
3
  import type { NativePoolPaths } from './pool-paths.ts';
3
4
  declare const PHASES: readonly ['building', 'verified', 'activation-installed', 'committed', 'retired'];
4
5
  export type NativeMigrationPhase = (typeof PHASES)[number];
@@ -134,7 +135,7 @@ export declare class NativeAuthorityError extends Error {
134
135
  readonly code: 'migration-required' | 'migration-incomplete' | 'invalid-journal' | 'journal-conflict';
135
136
  constructor(code: 'migration-required' | 'migration-incomplete' | 'invalid-journal' | 'journal-conflict');
136
137
  }
137
- export declare function readNativeMigrationJournal(paths: NativePoolPaths): Promise<NativeMigrationJournal | undefined>;
138
+ export declare function readNativeMigrationJournal(paths: NativePoolPaths, ownership?: OwnerOnlyOptions): Promise<NativeMigrationJournal | undefined>;
138
139
  /**
139
140
  * The migration phase that authorizes serving, or undefined while the
140
141
  * migration or a requested switch to vault custody is unfinished. Every reader
@@ -33,6 +33,39 @@ export declare const PROVIDER_ERROR_OVERSIZED_MESSAGE = "Provider error body exc
33
33
  export declare const PROVIDER_ERROR_MAX_BODY_BYTES: number;
34
34
  /** Largest SSE frame carried while looking for its end. */
35
35
  export declare const PROVIDER_ERROR_MAX_FRAME_BYTES: number;
36
+ /**
37
+ * Error types kept in a generic replacement body. A closed list rather than
38
+ * a syntax check: an opaque credential can look like any identifier.
39
+ */
40
+ declare const PROVIDER_ERROR_TYPES: readonly ['api_error', 'authentication_error', 'billing_error', 'invalid_request_error', 'not_found_error', 'overloaded_error', 'permission_error', 'rate_limit_error', 'relay_upstream_error', 'request_too_large', 'timeout_error'];
41
+ type ProviderErrorType = (typeof PROVIDER_ERROR_TYPES)[number];
42
+ declare const PREWARM_ERROR_MESSAGES: {
43
+ readonly http_validation: 'Provider rejected the prewarm request';
44
+ readonly http_error: 'Provider prewarm request failed';
45
+ readonly credential_unavailable: 'OAuth cache prewarm credential is unavailable';
46
+ readonly transport: 'Provider prewarm transport failed';
47
+ readonly withheld: 'Provider prewarm error details were withheld';
48
+ readonly parse_failure: 'Provider prewarm error response could not be parsed';
49
+ };
50
+ export type ProviderErrorSummary = {
51
+ status?: number;
52
+ provider_error: {
53
+ type: ProviderErrorType | 'unknown';
54
+ reason: keyof typeof PREWARM_ERROR_MESSAGES;
55
+ message: (typeof PREWARM_ERROR_MESSAGES)[keyof typeof PREWARM_ERROR_MESSAGES];
56
+ };
57
+ };
58
+ /**
59
+ * Prompt-safe prewarm metadata, not a replacement for per-send redaction.
60
+ * Read input.body from the response returned by ProviderErrorResponseScope's
61
+ * redactResponse, using a scope created for the physical request's credentials.
62
+ * Parsing is bounded independently; no provider text is copied to the result.
63
+ */
64
+ export declare function summarizePrewarmProviderError(input: {
65
+ status?: number;
66
+ body?: string;
67
+ failure?: 'credential_unavailable' | 'transport';
68
+ }): ProviderErrorSummary;
36
69
  /**
37
70
  * For producers of a non-2xx body, such as the relay, that stop buffering it
38
71
  * at PROVIDER_ERROR_MAX_BODY_BYTES: error the raw body stream with a new
@@ -137,3 +170,4 @@ export declare const PROVIDER_ERROR_RESPONSE_SCOPE_USED_MESSAGE = "Provider erro
137
170
  * once settled, `redactError` only returns a generic error.
138
171
  */
139
172
  export declare function createProviderErrorResponseScope(secrets: readonly string[], mode: ProviderResponseMode): ProviderErrorResponseScope;
173
+ export {};
@@ -0,0 +1,11 @@
1
+ /** Per-publication seams keep platform and sharing-failure tests out of process globals. */
2
+ export interface PublicationOptions {
3
+ readonly platform?: NodeJS.Platform;
4
+ readonly rename?: (from: string, to: string) => Promise<void>;
5
+ readonly now?: () => number;
6
+ readonly sleep?: (ms: number) => Promise<void>;
7
+ }
8
+ /** Capture optional callbacks before staging I/O, just like the writer's other hooks. */
9
+ export declare function capturePublicationOptions(options?: PublicationOptions): PublicationOptions;
10
+ /** First publication is unconditional; only subsequent Windows sharing failures are retried. */
11
+ export declare function renameWithWindowsSharingRetry(from: string, to: string, options?: PublicationOptions, beforeRetry?: () => Promise<'publish' | 'skip'>): Promise<'published' | 'skipped'>;