@cortexkit/opencode-openai-auth 0.11.1 → 1.0.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.
- package/README.md +15 -26
- package/dist/index-766sfrh5.js +1 -0
- package/dist/index-8kj7sa1p.js +12 -0
- package/dist/index-b3q3j39x.js +2 -0
- package/dist/index-bmd7x5aq.js +2 -0
- package/dist/index-eqh53k8v.js +2 -0
- package/dist/{index-sdt2d2ra.js → index-hy9030jh.js} +1 -1
- package/dist/index-jyr8y8k4.js +7 -0
- package/dist/index-rv08jmd4.js +2 -0
- package/dist/index-ww91hyzr.js +221 -0
- package/dist/index.d.ts +578 -145
- package/dist/index.js +1 -110
- package/dist/pool-lifecycle-DbDmgabd.d.ts +2430 -0
- package/dist/port-file-Do3lQIEk.d.ts +29 -0
- package/dist/protocol-BOBdkqqm.d.ts +198 -0
- package/dist/rpc/port-file.d.ts +4 -17
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +2 -2
- package/dist/rpc/protocol.js +1 -0
- package/dist/rpc/rpc-client.d.ts +5 -4
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.d.ts +2 -0
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state-D6cUKgkm.d.ts +385 -0
- package/dist/sidebar-state.d.ts +2 -2
- package/dist/sidebar-state.js +1 -1
- package/dist/token-util-wdza526f.js +1 -0
- package/dist/{token-9823y0pc.js → token-ypk61xj0.js} +1 -1
- package/dist/tui-preferences.js +5 -2
- package/dist/tui.d.ts +9 -4
- package/dist/v2/server.d.ts +54 -0
- package/dist/v2/server.js +4 -0
- package/package.json +21 -9
- package/src/tui/entry.mjs +26 -25
- package/src/tui-compiled/raw/logger.js +24 -0
- package/src/tui-compiled/raw/rpc/protocol.js +3 -0
- package/src/tui-compiled/raw/rpc/rpc-client.js +7 -0
- package/src/tui-compiled/raw/rpc/rpc-dir.js +27 -0
- package/src/tui-compiled/raw/selector.js +21 -0
- package/src/tui-compiled/raw/shared/0332701351b3eeec-format.js +138 -0
- package/src/tui-compiled/raw/shared/04a6357627de5ed0-errors.js +38 -0
- package/src/tui-compiled/raw/shared/053cc17b5419261e-codec.js +12 -0
- package/src/tui-compiled/raw/shared/0766d78c6f481f18-watcher.js +157 -0
- package/src/tui-compiled/raw/shared/08eef45626a94992-reserved.js +13 -0
- package/src/tui-compiled/raw/shared/39c3cb05738fcf6d-projection.js +134 -0
- package/src/tui-compiled/raw/shared/3c2d4169d00f907e-tui-support.js +5 -0
- package/src/tui-compiled/raw/shared/3e7d45a77c6ad4d5-index.js +4 -0
- package/src/tui-compiled/raw/shared/415792e85d80819e-capture-sink.js +13 -0
- package/src/tui-compiled/raw/shared/42ae93ab554fcec2-open-url.js +28 -0
- package/src/tui-compiled/raw/shared/43fc9e6b994519c7-refresh-lock.js +136 -0
- package/src/tui-compiled/raw/shared/458b934e92490331-mutate.js +500 -0
- package/src/tui-compiled/raw/shared/45bf5343bbbf9add-admission.js +142 -0
- package/src/tui-compiled/raw/shared/46f3dff1266160e8-client.js +2 -0
- package/src/tui-compiled/raw/shared/4825e03209d6ae3e-with-lock.js +48 -0
- package/src/tui-compiled/raw/shared/4f36d333d081d040-merge.js +162 -0
- package/src/tui-compiled/raw/shared/54eba94fd64c8c3c-index.js +7 -0
- package/src/tui-compiled/raw/shared/7211cfec06a298bc-atomic-write.js +80 -0
- package/src/tui-compiled/raw/shared/754d6017f8e419cf-builtins.js +534 -0
- package/src/tui-compiled/raw/shared/75bd8c3bd63b315f-identity.js +79 -0
- package/src/tui-compiled/raw/shared/7a91bb630e6f4804-index.js +1 -0
- package/src/tui-compiled/raw/shared/826342a4b6a8b89b-model.js +16 -0
- package/src/tui-compiled/raw/shared/83068c0dbe8a6f13-publication.js +304 -0
- package/src/tui-compiled/raw/shared/836fc615de6afbd9-settings.js +120 -0
- package/src/tui-compiled/raw/shared/83bc3ba9d0fe2761-runtime.js +68 -0
- package/src/tui-compiled/raw/shared/8a18abe4fa2977c8-menu.js +300 -0
- package/src/tui-compiled/raw/shared/901e149c5a0dbbff-sticky.js +339 -0
- package/src/tui-compiled/raw/shared/9020c407ce64f672-ordered.js +58 -0
- package/src/tui-compiled/raw/shared/905bffc0220f43d0-map.js +105 -0
- package/src/tui-compiled/raw/shared/94820e324f2b4c09-seam.js +301 -0
- package/src/tui-compiled/raw/shared/97484d9bb98c705b-provider-state.js +226 -0
- package/src/tui-compiled/raw/shared/9968e3cade6969a1-index.js +2 -0
- package/src/tui-compiled/raw/shared/9b4da614c45f9cd0-lock-constants.js +14 -0
- package/src/tui-compiled/raw/shared/9d3fc9e37456504e-refresh.js +225 -0
- package/src/tui-compiled/raw/shared/9deae3c4da4fd63b-hooks.js +34 -0
- package/src/tui-compiled/raw/shared/a09b6a533c11858f-tui-preferences.js +77 -0
- package/src/tui-compiled/raw/shared/a62a27a204266acd-attribution.js +60 -0
- package/src/tui-compiled/raw/shared/a910277ac43a8626-pull.js +143 -0
- package/src/tui-compiled/raw/shared/b85c5301fddcb98a-paths.js +5 -0
- package/src/tui-compiled/raw/shared/c14988621dc60a75-port-file.js +217 -0
- package/src/tui-compiled/raw/shared/c64d7afbc14ca125-sidebar-file.js +157 -0
- package/src/tui-compiled/raw/shared/c6b176708c446d6d-pins.js +34 -0
- package/src/tui-compiled/raw/shared/c7d252bedee01600-pi.js +206 -0
- package/src/tui-compiled/raw/shared/c852a15cfe489d12-pool.js +120 -0
- package/src/tui-compiled/raw/shared/cc9e0702a752cea7-index.js +3 -0
- package/src/tui-compiled/raw/shared/cd94316a888b0a8e-schema.js +754 -0
- package/src/tui-compiled/raw/shared/d319517e3ea6ad70-redact.js +83 -0
- package/src/tui-compiled/raw/shared/d5a8f1061ee2f114-index.js +5 -0
- package/src/tui-compiled/raw/shared/d669d72c40e9e116-logger.js +19 -0
- package/src/tui-compiled/raw/shared/d7dcba96fea1685c-engine.js +246 -0
- package/src/tui-compiled/raw/shared/dbef697d1df1cd84-index.js +5 -0
- package/src/tui-compiled/raw/shared/e4acc4cb713f300c-protocol.js +3 -0
- package/src/tui-compiled/raw/shared/e8cd4929507508d8-refresh-file-lock.js +501 -0
- package/src/tui-compiled/raw/shared/ec971142548df90e-index.js +6 -0
- package/src/tui-compiled/raw/shared/f37fcefc7aedbf25-error.js +11 -0
- package/src/tui-compiled/raw/shared/fbcdcd0f925e74c0-rpc-client.js +253 -0
- package/src/tui-compiled/raw/shared/fd45e82f2f9c0a0d-torn.js +294 -0
- package/src/tui-compiled/raw/shared/fe02abeadc535f77-rows.js +1258 -0
- package/src/tui-compiled/raw/sidebar-state.js +960 -0
- package/src/tui-compiled/raw/tui/command-dialogs.tsx +424 -0
- package/src/tui-compiled/raw/tui-preferences.js +135 -0
- package/src/tui-compiled/raw/tui.tsx +135 -143
- package/src/tui-compiled/runtime/logger.js +24 -0
- package/src/tui-compiled/runtime/rpc/protocol.js +3 -0
- package/src/tui-compiled/runtime/rpc/rpc-client.js +7 -0
- package/src/tui-compiled/runtime/rpc/rpc-dir.js +27 -0
- package/src/tui-compiled/runtime/selector.js +21 -0
- package/src/tui-compiled/runtime/shared/0332701351b3eeec-format.js +138 -0
- package/src/tui-compiled/runtime/shared/04a6357627de5ed0-errors.js +38 -0
- package/src/tui-compiled/runtime/shared/053cc17b5419261e-codec.js +12 -0
- package/src/tui-compiled/runtime/shared/0766d78c6f481f18-watcher.js +157 -0
- package/src/tui-compiled/runtime/shared/08eef45626a94992-reserved.js +13 -0
- package/src/tui-compiled/runtime/shared/39c3cb05738fcf6d-projection.js +134 -0
- package/src/tui-compiled/runtime/shared/3c2d4169d00f907e-tui-support.js +5 -0
- package/src/tui-compiled/runtime/shared/3e7d45a77c6ad4d5-index.js +4 -0
- package/src/tui-compiled/runtime/shared/415792e85d80819e-capture-sink.js +13 -0
- package/src/tui-compiled/runtime/shared/42ae93ab554fcec2-open-url.js +28 -0
- package/src/tui-compiled/runtime/shared/43fc9e6b994519c7-refresh-lock.js +136 -0
- package/src/tui-compiled/runtime/shared/458b934e92490331-mutate.js +500 -0
- package/src/tui-compiled/runtime/shared/45bf5343bbbf9add-admission.js +142 -0
- package/src/tui-compiled/runtime/shared/46f3dff1266160e8-client.js +2 -0
- package/src/tui-compiled/runtime/shared/4825e03209d6ae3e-with-lock.js +48 -0
- package/src/tui-compiled/runtime/shared/4f36d333d081d040-merge.js +162 -0
- package/src/tui-compiled/runtime/shared/54eba94fd64c8c3c-index.js +7 -0
- package/src/tui-compiled/runtime/shared/7211cfec06a298bc-atomic-write.js +80 -0
- package/src/tui-compiled/runtime/shared/754d6017f8e419cf-builtins.js +534 -0
- package/src/tui-compiled/runtime/shared/75bd8c3bd63b315f-identity.js +79 -0
- package/src/tui-compiled/runtime/shared/7a91bb630e6f4804-index.js +1 -0
- package/src/tui-compiled/runtime/shared/826342a4b6a8b89b-model.js +16 -0
- package/src/tui-compiled/runtime/shared/83068c0dbe8a6f13-publication.js +304 -0
- package/src/tui-compiled/runtime/shared/836fc615de6afbd9-settings.js +120 -0
- package/src/tui-compiled/runtime/shared/83bc3ba9d0fe2761-runtime.js +68 -0
- package/src/tui-compiled/runtime/shared/8a18abe4fa2977c8-menu.js +300 -0
- package/src/tui-compiled/runtime/shared/901e149c5a0dbbff-sticky.js +339 -0
- package/src/tui-compiled/runtime/shared/9020c407ce64f672-ordered.js +58 -0
- package/src/tui-compiled/runtime/shared/905bffc0220f43d0-map.js +105 -0
- package/src/tui-compiled/runtime/shared/94820e324f2b4c09-seam.js +301 -0
- package/src/tui-compiled/runtime/shared/97484d9bb98c705b-provider-state.js +226 -0
- package/src/tui-compiled/runtime/shared/9968e3cade6969a1-index.js +2 -0
- package/src/tui-compiled/runtime/shared/9b4da614c45f9cd0-lock-constants.js +14 -0
- package/src/tui-compiled/runtime/shared/9d3fc9e37456504e-refresh.js +225 -0
- package/src/tui-compiled/runtime/shared/9deae3c4da4fd63b-hooks.js +34 -0
- package/src/tui-compiled/runtime/shared/a09b6a533c11858f-tui-preferences.js +77 -0
- package/src/tui-compiled/runtime/shared/a62a27a204266acd-attribution.js +60 -0
- package/src/tui-compiled/runtime/shared/a910277ac43a8626-pull.js +143 -0
- package/src/tui-compiled/runtime/shared/b85c5301fddcb98a-paths.js +5 -0
- package/src/tui-compiled/runtime/shared/c14988621dc60a75-port-file.js +217 -0
- package/src/tui-compiled/runtime/shared/c64d7afbc14ca125-sidebar-file.js +157 -0
- package/src/tui-compiled/runtime/shared/c6b176708c446d6d-pins.js +34 -0
- package/src/tui-compiled/runtime/shared/c7d252bedee01600-pi.js +206 -0
- package/src/tui-compiled/runtime/shared/c852a15cfe489d12-pool.js +120 -0
- package/src/tui-compiled/runtime/shared/cc9e0702a752cea7-index.js +3 -0
- package/src/tui-compiled/runtime/shared/cd94316a888b0a8e-schema.js +754 -0
- package/src/tui-compiled/runtime/shared/d319517e3ea6ad70-redact.js +83 -0
- package/src/tui-compiled/runtime/shared/d5a8f1061ee2f114-index.js +5 -0
- package/src/tui-compiled/runtime/shared/d669d72c40e9e116-logger.js +19 -0
- package/src/tui-compiled/runtime/shared/d7dcba96fea1685c-engine.js +246 -0
- package/src/tui-compiled/runtime/shared/dbef697d1df1cd84-index.js +5 -0
- package/src/tui-compiled/runtime/shared/e4acc4cb713f300c-protocol.js +3 -0
- package/src/tui-compiled/runtime/shared/e8cd4929507508d8-refresh-file-lock.js +501 -0
- package/src/tui-compiled/runtime/shared/ec971142548df90e-index.js +6 -0
- package/src/tui-compiled/runtime/shared/f37fcefc7aedbf25-error.js +11 -0
- package/src/tui-compiled/runtime/shared/fbcdcd0f925e74c0-rpc-client.js +253 -0
- package/src/tui-compiled/runtime/shared/fd45e82f2f9c0a0d-torn.js +294 -0
- package/src/tui-compiled/runtime/shared/fe02abeadc535f77-rows.js +1258 -0
- package/src/tui-compiled/runtime/sidebar-state.js +960 -0
- package/src/tui-compiled/runtime/tui/command-dialogs.js +378 -0
- package/src/tui-compiled/runtime/tui-preferences.js +135 -0
- package/src/tui-compiled/runtime/{tui.tsx → tui.js} +288 -316
- package/dist/index-4effjmr6.js +0 -2
- package/dist/index-9ehhb051.js +0 -2
- package/dist/index-g3hsdjh4.js +0 -2
- package/dist/index-hh52v8sb.js +0 -2
- package/dist/index-jwn4r3sw.js +0 -1
- package/dist/index-sq36b120.js +0 -211
- package/dist/internal-BTndPmW2.d.ts +0 -914
- package/dist/quota-normalize-08hpp51v.js +0 -1
- package/dist/sidebar-state-CoKYKcLn.d.ts +0 -220
- package/dist/token-util-ypgz7rge.js +0 -1
- package/src/tui-compiled/raw/core-account-paths.ts +0 -114
- package/src/tui-compiled/raw/core-custody-state.ts +0 -243
- package/src/tui-compiled/raw/logger.ts +0 -53
- package/src/tui-compiled/raw/rpc-port-file.ts +0 -177
- package/src/tui-compiled/raw/rpc-protocol.ts +0 -12
- package/src/tui-compiled/raw/rpc-rpc-client.ts +0 -82
- package/src/tui-compiled/raw/rpc-rpc-dir.ts +0 -46
- package/src/tui-compiled/raw/sidebar-state.ts +0 -1659
- package/src/tui-compiled/raw/tui-command-dialogs.tsx +0 -1096
- package/src/tui-compiled/raw/tui-preferences.ts +0 -328
- package/src/tui-compiled/runtime/core-account-paths.ts +0 -114
- package/src/tui-compiled/runtime/core-custody-state.ts +0 -243
- package/src/tui-compiled/runtime/logger.ts +0 -53
- package/src/tui-compiled/runtime/rpc-port-file.ts +0 -177
- package/src/tui-compiled/runtime/rpc-protocol.ts +0 -12
- package/src/tui-compiled/runtime/rpc-rpc-client.ts +0 -82
- package/src/tui-compiled/runtime/rpc-rpc-dir.ts +0 -46
- package/src/tui-compiled/runtime/sidebar-state.ts +0 -1659
- package/src/tui-compiled/runtime/tui-command-dialogs.tsx +0 -855
- package/src/tui-compiled/runtime/tui-preferences.ts +0 -328
- package/src/tui-compiled/shared/internal.ts +0 -6
- package/src/tui-compiled/shared/logger.ts +0 -264
- package/src/tui-compiled/shared/paths.ts +0 -33
- package/src/tui-compiled/shared/refresh-file-lock.ts +0 -384
- package/src/tui-compiled/shared/util/error.ts +0 -9
- package/src/tui-compiled/shared/util/open-url.ts +0 -30
|
@@ -0,0 +1,2430 @@
|
|
|
1
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/schema.d.ts
|
|
2
|
+
type OAuthCredential = {
|
|
3
|
+
type: 'oauth';
|
|
4
|
+
access?: string;
|
|
5
|
+
refresh: string;
|
|
6
|
+
expires?: number;
|
|
7
|
+
};
|
|
8
|
+
type ApiKeyCredential = {
|
|
9
|
+
type: 'api';
|
|
10
|
+
apiKey: string;
|
|
11
|
+
baseURL: string;
|
|
12
|
+
authHeader?: 'authorization-bearer' | 'x-api-key';
|
|
13
|
+
};
|
|
14
|
+
type PoolCredential = OAuthCredential | ApiKeyCredential;
|
|
15
|
+
/**
|
|
16
|
+
* What `rotate` takes. Rotation refreshes the secret of the endpoint a row
|
|
17
|
+
* already has, so an API key may leave out `baseURL` (and `authHeader`) to
|
|
18
|
+
* keep the row's; one it gives must equal the row's.
|
|
19
|
+
*/
|
|
20
|
+
type RotateCredential = OAuthCredential | (Omit<ApiKeyCredential, 'baseURL'> & {
|
|
21
|
+
baseURL?: string;
|
|
22
|
+
});
|
|
23
|
+
/** A credential as stored: an OAuth credential also carries its refresh stamp. */
|
|
24
|
+
type StoredCredential = (OAuthCredential & {
|
|
25
|
+
lastRefreshedAt?: number;
|
|
26
|
+
}) | ApiKeyCredential;
|
|
27
|
+
/** Quota codec supplied by `/quota`: the store never interprets the map itself. */
|
|
28
|
+
interface QuotaCodec {
|
|
29
|
+
validate(value: unknown): boolean;
|
|
30
|
+
merge(stored: unknown | undefined, observation: unknown): unknown;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What `ProviderStateCodec.onReplace` is told about a replacement: the row id,
|
|
34
|
+
* the credential epoch the new credential starts, `previousIdentity` (the
|
|
35
|
+
* identity the locked row recorded before the replace), `identity` (the
|
|
36
|
+
* identity the replace records), and the provider state the caller handed to
|
|
37
|
+
* `replace`, if any. Each identity is absent when none was recorded.
|
|
38
|
+
*/
|
|
39
|
+
interface ProviderStateReplacement {
|
|
40
|
+
id: string;
|
|
41
|
+
credentialEpoch: number;
|
|
42
|
+
previousIdentity?: string;
|
|
43
|
+
identity?: string;
|
|
44
|
+
incoming?: unknown;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Codec for the provider state a plugin keeps beside each row's credential
|
|
48
|
+
* (a project id, a device fingerprint, eligibility times: whatever belongs to
|
|
49
|
+
* that credential). The store never interprets the value: it stores it as
|
|
50
|
+
* JSON, asks `validate` before every write and on every load, and calls the
|
|
51
|
+
* hooks below where two values meet. Every hook is synchronous and runs
|
|
52
|
+
* under the store locks.
|
|
53
|
+
*/
|
|
54
|
+
interface ProviderStateCodec {
|
|
55
|
+
validate(value: unknown): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The part of a (valid) value that belongs to the credential: what is true
|
|
58
|
+
* of the account the credential signs in to, such as a project id or a
|
|
59
|
+
* device fingerprint, as opposed to what the plugin merely tracks about
|
|
60
|
+
* its use, such as a cooldown or a cursor. The credential stamp covers the
|
|
61
|
+
* digest of exactly this projection, so a foreign edit of it hides the
|
|
62
|
+
* value, while the rest may change through `updateProviderState` without
|
|
63
|
+
* the stamp being rewritten. It must be a pure function of the value that
|
|
64
|
+
* returns JSON with a deterministic key order. Without it the whole value
|
|
65
|
+
* is credential-bound.
|
|
66
|
+
*/
|
|
67
|
+
credentialBound?(value: unknown): unknown;
|
|
68
|
+
/**
|
|
69
|
+
* Combines the value on disk with one a write brings (`add` of a secret the
|
|
70
|
+
* pool already holds, `rotate`, or a refresh whose provider returned a
|
|
71
|
+
* state). Called only when the row has a value on disk; without it the
|
|
72
|
+
* incoming value replaces the stored one. Its result is validated.
|
|
73
|
+
*/
|
|
74
|
+
merge?(onDisk: unknown, incoming: unknown): unknown;
|
|
75
|
+
/**
|
|
76
|
+
* The provider state of a row once `replace` gives it a new credential
|
|
77
|
+
* epoch. `previous` is the old credential's value (undefined when the row
|
|
78
|
+
* shows none). Returning undefined clears it. Without this hook a replace
|
|
79
|
+
* keeps the value handed to `replace` and otherwise clears the state.
|
|
80
|
+
*/
|
|
81
|
+
onReplace?(previous: unknown | undefined, replacement: ProviderStateReplacement): unknown | undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Why a row shows no provider state although the state file holds one for it.
|
|
85
|
+
*
|
|
86
|
+
* `uncovered`: the value's credential-bound part (see
|
|
87
|
+
* `ProviderStateCodec.credentialBound`) is not the one this store last
|
|
88
|
+
* wrote beside the row's credential at its credential epoch and recorded
|
|
89
|
+
* identity. Another writer edited it, or
|
|
90
|
+
* wrote the credential beside it without knowing about it (an older version
|
|
91
|
+
* of this library, which drops the coverage, or a writer that does not know
|
|
92
|
+
* the pool at all), or it belongs to an earlier credential of the row.
|
|
93
|
+
* `invalid`: the value is covered but the codec rejects it, or the store was
|
|
94
|
+
* opened without a provider-state codec.
|
|
95
|
+
*/
|
|
96
|
+
type ProviderStateDrop = 'uncovered' | 'invalid';
|
|
97
|
+
/**
|
|
98
|
+
* What the stamp beside a row's credential proves (see `CredentialStamp`).
|
|
99
|
+
*
|
|
100
|
+
* `none`: the row holds no credential, so there is nothing to stamp.
|
|
101
|
+
* `bound`: the stamp was written with this credential (its digest matches),
|
|
102
|
+
* names the row's credential epoch (1 for a row without a per-row entry),
|
|
103
|
+
* the identity it records (or its recording none) and any endpoint it
|
|
104
|
+
* records are the row's, and its dispatch digest matches everything a
|
|
105
|
+
* request would send (the OAuth access and refresh tokens and expiry; the API
|
|
106
|
+
* key with its `baseURL` and `authHeader`).
|
|
107
|
+
* `missing`: the credential carries no stamp (written by a writer that does
|
|
108
|
+
* not know about stamps, or one that dropped it).
|
|
109
|
+
* `malformed`: the stamp is not one this store writes (wrong shape, or an
|
|
110
|
+
* epoch outside the positive safe integers).
|
|
111
|
+
* `mismatched`: the stamp was written for another credential, epoch,
|
|
112
|
+
* identity, endpoint, or token to send than the row now holds.
|
|
113
|
+
* `legacy`: a well-formed stamp written with this credential's secret but
|
|
114
|
+
* with no dispatch digest (written by 0.4.3 or earlier), so it proves
|
|
115
|
+
* neither the token sent nor the account or endpoint it goes to.
|
|
116
|
+
*/
|
|
117
|
+
type CredentialStampStatus = 'none' | 'bound' | 'missing' | 'malformed' | 'mismatched' | 'legacy';
|
|
118
|
+
/** One row of the pool as loaded. */
|
|
119
|
+
interface PoolRow {
|
|
120
|
+
id: string;
|
|
121
|
+
type: 'oauth' | 'api';
|
|
122
|
+
label?: string;
|
|
123
|
+
enabled: boolean;
|
|
124
|
+
addedAt?: number;
|
|
125
|
+
/** Recorded wire identity (the roster row's `accountId`), when known. */
|
|
126
|
+
identity?: string;
|
|
127
|
+
/** Undefined when the state file holds no usable credential for the row. */
|
|
128
|
+
credential?: StoredCredential;
|
|
129
|
+
/** Stable hash of the credential's secret material; never persisted. */
|
|
130
|
+
fingerprint?: string;
|
|
131
|
+
/** Undefined when the row has no per-row entry yet. */
|
|
132
|
+
credentialEpoch?: number;
|
|
133
|
+
needsFirstReading: boolean;
|
|
134
|
+
disabledReason?: string;
|
|
135
|
+
/** Store-owned reservation; only `publishRoster` releases it for ordinary use. */
|
|
136
|
+
staged?: {
|
|
137
|
+
reservation: string;
|
|
138
|
+
};
|
|
139
|
+
/** The opaque quota map, as validated by the codec. */
|
|
140
|
+
quota?: unknown;
|
|
141
|
+
/**
|
|
142
|
+
* The opaque provider state kept beside the credential, as validated by
|
|
143
|
+
* the provider-state codec. Absent when the row has none, or when the one
|
|
144
|
+
* on disk is not shown (see `providerStateDropped`).
|
|
145
|
+
*/
|
|
146
|
+
providerState?: unknown;
|
|
147
|
+
/**
|
|
148
|
+
* Set when the state file holds a provider state for the row that is not
|
|
149
|
+
* shown, and why. The value stays on disk untouched until a write on the
|
|
150
|
+
* row sets or clears it; the row itself stays usable.
|
|
151
|
+
*/
|
|
152
|
+
providerStateDropped?: ProviderStateDrop;
|
|
153
|
+
hasEntry: boolean;
|
|
154
|
+
/** A row that may be refreshed, pulled for, or admitted. */
|
|
155
|
+
candidate: boolean;
|
|
156
|
+
/** Set when the roster row or the per-row entry failed validation. */
|
|
157
|
+
invalid?: 'roster' | 'entry';
|
|
158
|
+
/**
|
|
159
|
+
* Set when a replace stopped between its two writes: the state file holds
|
|
160
|
+
* the new credential, stamped with the epoch and the identity or endpoint
|
|
161
|
+
* it belongs to, and the config still holds the replaced row. Also set when
|
|
162
|
+
* a write that gives a row its first identity (`recordIdentity`, or a
|
|
163
|
+
* `rotate` or refresh that learns one) stopped after stamping the identity
|
|
164
|
+
* and before recording it in the config, and when an attributed `disable`
|
|
165
|
+
* or `enable` that changed the provider state stopped after its state
|
|
166
|
+
* write and before flipping the row in the config. The row is shown as the
|
|
167
|
+
* write leaves it once completed, is never a candidate, and the next store
|
|
168
|
+
* write on it writes the config to match.
|
|
169
|
+
*/
|
|
170
|
+
torn?: true;
|
|
171
|
+
/**
|
|
172
|
+
* Whether the credential is the one the store last stamped for this row
|
|
173
|
+
* (see `CredentialStampStatus`). Every row the store loads carries it; a
|
|
174
|
+
* torn row reports the stamp of the row as it is shown completed. It is
|
|
175
|
+
* optional only so that rows built by hand (test fixtures) still type.
|
|
176
|
+
*/
|
|
177
|
+
stamp?: CredentialStampStatus;
|
|
178
|
+
/**
|
|
179
|
+
* Set only when the store was opened with `requireCredentialStamps` and
|
|
180
|
+
* the row's `stamp` is not `bound`: the row is never a candidate, and
|
|
181
|
+
* `refresh`, quota pulls, `recordQuota`, `recordIdentity`, `rotate` and a
|
|
182
|
+
* re-`add` onto it refuse with `unbound-credential`. Only `replace` (or a
|
|
183
|
+
* new row) makes it usable again.
|
|
184
|
+
*/
|
|
185
|
+
unbound?: true;
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/errors.d.ts
|
|
189
|
+
/** Every library operation that can fail, as named in the failure value. */
|
|
190
|
+
type PoolOperation = 'initialize' | 'add' | 'replace' | 'rotate' | 'disable' | 'enable' | 'remove' | 'reorder' | 'updateSettings' | 'recordIdentity' | 'updateProviderState' | 'refresh' | 'pull' | 'publishRoster';
|
|
191
|
+
/**
|
|
192
|
+
* How far an operation got before it failed.
|
|
193
|
+
*
|
|
194
|
+
* `before-first-write`: nothing was written; both files are as they were.
|
|
195
|
+
* `after-first-write`: the operation's first file write landed and a later one
|
|
196
|
+
* did not; what that first write left is on disk and is never rolled back
|
|
197
|
+
* (add: a state entry no roster row names, which no reader loads; replace:
|
|
198
|
+
* the new credential stamped ahead of the config, which readers show as a
|
|
199
|
+
* torn row and the next store write on it completes; rotate: the rotated
|
|
200
|
+
* credential beside the old per-row entry). `pull`: a quota pull, or the
|
|
201
|
+
* recording of its result, failed.
|
|
202
|
+
*/
|
|
203
|
+
type PoolFailurePhase = 'before-first-write' | 'after-first-write' | 'pull';
|
|
204
|
+
/**
|
|
205
|
+
* Why an operation failed. `lock-contention` and `lock-ownership` are the two
|
|
206
|
+
* lock outcomes (a wait that ran out, and a lease found lost); the rest are
|
|
207
|
+
* refusals and failures of the operation itself.
|
|
208
|
+
*/
|
|
209
|
+
type PoolFailureKind = 'lock-contention' | 'lock-ownership' | 'pending-migration' | 'load-error' | 'snapshot-contended' | 'publication-sync' | 'publication-incomplete' | 'unknown-row' | 'invalid-row' | 'invalid-input' | 'id-exists' | 'id-removed' | 'type-mismatch' | 'no-credential' | 'row-disabled' | 'row-protected' | 'row-staged' | 'credential-exists' | 'publication-mismatch' | 'duplicate-identity' | 'identity-mismatch' | 'identity-contradicted' | 'endpoint-mismatch' | 'row-key-changed' | 'invalid-order' | 'refresh-stamp-ahead' | 'unbound-credential' | 'attribution' | 'provider' | 'pull' | 'invalid-quota' | 'invalid-provider-state' | 'after-persist-hook' | 'unexpected';
|
|
210
|
+
/**
|
|
211
|
+
* The single failure value of every store operation. `committed` is present
|
|
212
|
+
* only when the operation had already written a credential to the state file
|
|
213
|
+
* before it failed (a partial rotation or refresh): it is the credential now
|
|
214
|
+
* on disk, so a caller never has to re-read the files to learn it.
|
|
215
|
+
*/
|
|
216
|
+
declare class PoolOperationError extends Error {
|
|
217
|
+
readonly operation: PoolOperation;
|
|
218
|
+
readonly rowId: string | undefined;
|
|
219
|
+
readonly phase: PoolFailurePhase;
|
|
220
|
+
readonly retryable: boolean;
|
|
221
|
+
readonly kind: PoolFailureKind;
|
|
222
|
+
readonly committed: StoredCredential | undefined;
|
|
223
|
+
constructor(details: {
|
|
224
|
+
operation: PoolOperation;
|
|
225
|
+
rowId?: string;
|
|
226
|
+
phase: PoolFailurePhase;
|
|
227
|
+
retryable: boolean;
|
|
228
|
+
kind: PoolFailureKind;
|
|
229
|
+
committed?: StoredCredential;
|
|
230
|
+
message?: string;
|
|
231
|
+
cause?: unknown;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/hooks.d.ts
|
|
236
|
+
interface PoolLogger {
|
|
237
|
+
warn(message: string, data?: unknown): void;
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.d.ts
|
|
241
|
+
interface LockLoss {
|
|
242
|
+
readonly reason: 'taken-over' | 'expired' | 'unreadable' | 'renewal-failed' | 'marker-lost';
|
|
243
|
+
readonly expectedOwnerId: string;
|
|
244
|
+
readonly observedOwnerId?: string;
|
|
245
|
+
readonly observedExpiresAt?: number;
|
|
246
|
+
}
|
|
247
|
+
interface RefreshFileLock {
|
|
248
|
+
readonly ownerId: string;
|
|
249
|
+
assertOwned(): Promise<void>;
|
|
250
|
+
release(): Promise<void>;
|
|
251
|
+
/** Resolves once on detected loss; remains pending after an owner's release. */
|
|
252
|
+
whenLost(): Promise<LockLoss>;
|
|
253
|
+
hasLost(): boolean;
|
|
254
|
+
}
|
|
255
|
+
declare function acquireRefreshFileLock(options: {
|
|
256
|
+
name: string;
|
|
257
|
+
ttlMs: number;
|
|
258
|
+
/**
|
|
259
|
+
* File the lock is named after. Required: the lock and the write it guards
|
|
260
|
+
* must target the same file, and a default resolved in here could only ever
|
|
261
|
+
* be one host's path.
|
|
262
|
+
*/
|
|
263
|
+
path: string;
|
|
264
|
+
now?: () => number;
|
|
265
|
+
renew?: boolean;
|
|
266
|
+
renewIntervalMs?: number;
|
|
267
|
+
/** Notifies a live-owner refusal without awaiting; observer failures are ignored. */
|
|
268
|
+
onContended?: () => void;
|
|
269
|
+
/** Synchronous, never awaited; throws and returned promise/thenable rejections are isolated. */
|
|
270
|
+
onRenewalTimer?: (event: 'scheduled' | 'cancelled') => void;
|
|
271
|
+
onStep?: (step: 'stale-marker-stat' | 'stale-marker-claimed' | 'stale-lock-observed' | 'stale-lock-confirmed' | 'stale-lock-removed' | 'stale-lock-recreated' | 'eviction-marker-acquired' | 'renewal-owner-confirmed' | 'renewal-marker-unavailable' | 'renewal-write-fenced' | 'renewal-write-ready' | 'relinquish-read' | 'renewal-finished' | 'release-owner-confirmed') => void | Promise<void>;
|
|
272
|
+
}): Promise<RefreshFileLock | null>;
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/refresh-lock.d.ts
|
|
275
|
+
type LockStep = NonNullable<Parameters<typeof acquireRefreshFileLock>[0]['onStep']> extends ((step: infer S) => unknown) ? S : never;
|
|
276
|
+
/** Tuning shared by every lock the store takes; each field is overridable. */
|
|
277
|
+
interface PoolLockOptions {
|
|
278
|
+
ttlMs: number;
|
|
279
|
+
timeoutMs: number;
|
|
280
|
+
retryMs: number;
|
|
281
|
+
renew: boolean;
|
|
282
|
+
renewIntervalMs?: number;
|
|
283
|
+
}
|
|
284
|
+
/** A lock: the (name, path) pair naming its file plus optional tuning. */
|
|
285
|
+
interface PoolLockSpec extends Partial<PoolLockOptions> {
|
|
286
|
+
name: string;
|
|
287
|
+
path: string;
|
|
288
|
+
}
|
|
289
|
+
type LockEvent = {
|
|
290
|
+
type: 'acquired' | 'released' | 'contended';
|
|
291
|
+
name: string;
|
|
292
|
+
path: string;
|
|
293
|
+
};
|
|
294
|
+
interface LockEnvironment {
|
|
295
|
+
now: () => number;
|
|
296
|
+
onLockEvent?: (event: LockEvent) => void;
|
|
297
|
+
onLockStep?: (lock: {
|
|
298
|
+
name: string;
|
|
299
|
+
path: string;
|
|
300
|
+
}, step: LockStep) => void | Promise<void>;
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/mutate.d.ts
|
|
304
|
+
/** Named points on the write path, for crash and ownership injection. */
|
|
305
|
+
type WriteStep = 'before-config-write' | 'after-config-write' | 'before-state-write' | 'after-state-write';
|
|
306
|
+
/** Awaitable pause points on the pull and refresh paths. */
|
|
307
|
+
type HoldPoint = 'refresh-before-provider' | 'pull-before-request';
|
|
308
|
+
interface StoreContext {
|
|
309
|
+
provider: string;
|
|
310
|
+
configPath: string;
|
|
311
|
+
statePath: string;
|
|
312
|
+
codec: QuotaCodec;
|
|
313
|
+
/** The provider-state codec; without one no row shows a provider state. */
|
|
314
|
+
providerState?: ProviderStateCodec;
|
|
315
|
+
now: () => number;
|
|
316
|
+
storeLocks: readonly PoolLockSpec[];
|
|
317
|
+
lockDefaults: PoolLockOptions;
|
|
318
|
+
lockEnv: LockEnvironment;
|
|
319
|
+
logger?: PoolLogger;
|
|
320
|
+
onStep?: (step: WriteStep, info: {
|
|
321
|
+
operation: PoolOperation;
|
|
322
|
+
rowId: string | undefined;
|
|
323
|
+
}) => void | Promise<void>;
|
|
324
|
+
hold?: (point: HoldPoint, rowId: string) => void | Promise<void>;
|
|
325
|
+
/** Ids whose per-row entry a library write dropped in this process. */
|
|
326
|
+
removedIds: Set<string>;
|
|
327
|
+
/**
|
|
328
|
+
* When true, rows whose credential stamp is not bound load `unbound` and
|
|
329
|
+
* the operations that use a credential refuse them (see
|
|
330
|
+
* `OpenPoolStoreOptions.requireCredentialStamps`).
|
|
331
|
+
*/
|
|
332
|
+
requireCredentialStamps?: boolean;
|
|
333
|
+
requireRemovedFingerprint?: boolean;
|
|
334
|
+
}
|
|
335
|
+
/** What `initializePool` did. */
|
|
336
|
+
type InitializeOutcome = 'initialized' | 'already-ready';
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/runtime.d.ts
|
|
339
|
+
/** Where a pull was fired from; `load` fires at most once per process per row. */
|
|
340
|
+
type PullReason = 'load' | 'add' | 'replace' | 'admission';
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/attribution.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* What a pull or refresh captured about its row (named by id alongside) when
|
|
345
|
+
* it was issued. A result applies only while the row with that id still has
|
|
346
|
+
* this credential epoch and this recorded identity; a replaced credential
|
|
347
|
+
* bumps the epoch, so work issued for the old one is discarded.
|
|
348
|
+
*
|
|
349
|
+
* The epoch names one credential lineage of the row: a credential given by
|
|
350
|
+
* `add` or `replace`, through every refresh and `rotate` of it, which keep
|
|
351
|
+
* the epoch. Since 0.8.0 that holds across removal too: a row added under an
|
|
352
|
+
* id the pool held before starts past every epoch that id held (the store
|
|
353
|
+
* records them when it drops a row, in the config file, so every process
|
|
354
|
+
* sees it), so an attribution taken for a removed row is refused once the id
|
|
355
|
+
* is added again, even with the same identity. Writers older than 0.8.0
|
|
356
|
+
* start a re-added id at epoch 1 again, and a writer that does not know the
|
|
357
|
+
* pool can remove and re-add a row without the store seeing it; work
|
|
358
|
+
* attributed across either may still apply to the new credential.
|
|
359
|
+
*/
|
|
360
|
+
interface Attribution {
|
|
361
|
+
credentialEpoch: number;
|
|
362
|
+
identity?: string;
|
|
363
|
+
}
|
|
364
|
+
//#endregion
|
|
365
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/rows.d.ts
|
|
366
|
+
type FailureHook = (rowId: string, error: PoolOperationError) => void | Promise<void>;
|
|
367
|
+
interface RowOperationOptions {
|
|
368
|
+
/** Called once, awaited, on every non-success path, before locks release. */
|
|
369
|
+
onFailure?: FailureHook;
|
|
370
|
+
/** The provider-wide lock, when an operation may change identity keying. */
|
|
371
|
+
providerLock?: PoolLockSpec;
|
|
372
|
+
/**
|
|
373
|
+
* Further locks taken after the row lock and the provider-wide lock, in
|
|
374
|
+
* this order, before the store locks: the same place `refresh` takes its
|
|
375
|
+
* extra locks, so a caller holding legacy locks around a row write and a
|
|
376
|
+
* refresh of that row acquire them in one order and cannot deadlock.
|
|
377
|
+
*/
|
|
378
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
379
|
+
}
|
|
380
|
+
interface RowProjection {
|
|
381
|
+
id: string;
|
|
382
|
+
type: 'oauth' | 'api';
|
|
383
|
+
label?: string;
|
|
384
|
+
enabled: boolean;
|
|
385
|
+
disabledReason?: string;
|
|
386
|
+
identity?: string;
|
|
387
|
+
credentialEpoch?: number;
|
|
388
|
+
stamp?: PoolRow['stamp'];
|
|
389
|
+
staged?: {
|
|
390
|
+
reservation: string;
|
|
391
|
+
};
|
|
392
|
+
torn?: true;
|
|
393
|
+
invalid?: 'roster' | 'entry';
|
|
394
|
+
}
|
|
395
|
+
interface ProtectView {
|
|
396
|
+
id: string;
|
|
397
|
+
row?: RowProjection;
|
|
398
|
+
rows: RowProjection[];
|
|
399
|
+
config: Readonly<Record<string, unknown>>;
|
|
400
|
+
}
|
|
401
|
+
type ProtectFn = (view: ProtectView) => string | undefined | Promise<string | undefined>;
|
|
402
|
+
interface AddOptions extends RowOperationOptions {
|
|
403
|
+
onExisting?: 'rotate' | 'refuse' | 'stage-duplicate';
|
|
404
|
+
protect?: ProtectFn;
|
|
405
|
+
}
|
|
406
|
+
/** Options of `replace` and `rotate`. Without `attribution` a call behaves as before. */
|
|
407
|
+
interface RowWriteOptions extends RowOperationOptions {
|
|
408
|
+
/**
|
|
409
|
+
* The credential epoch and recorded identity the caller read the row at
|
|
410
|
+
* when it decided on this write; an identity left out means the row had
|
|
411
|
+
* none. Compared exactly, under the row and store locks, before any write
|
|
412
|
+
* or replacement hook, including the completion of an interrupted replace.
|
|
413
|
+
* The call is refused (`attribution`, retryable, nothing written) once the
|
|
414
|
+
* row holds another epoch or identity, so a write decided on an older
|
|
415
|
+
* credential never overwrites the one that replaced it. `disable`, `enable`,
|
|
416
|
+
* `recordQuota` and `updateProviderState` take the same fence.
|
|
417
|
+
*/
|
|
418
|
+
attribution?: Attribution;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Options of `disable`, `enable` and `remove`. The provider-wide lock guards
|
|
422
|
+
* changes to the recorded identity a row lock is named by; none of these
|
|
423
|
+
* three records an identity, so none takes it. The extra locks are taken
|
|
424
|
+
* where every other row write takes them, after the row lock and before the
|
|
425
|
+
* store locks.
|
|
426
|
+
*/
|
|
427
|
+
type RowToggleOptions = Pick<RowOperationOptions, 'onFailure' | 'extraLocks'>;
|
|
428
|
+
/** What a `remove` protect predicate is shown, read under every lock. */
|
|
429
|
+
interface RemoveView {
|
|
430
|
+
/**
|
|
431
|
+
* The row as loaded; undefined when the roster no longer holds the id and
|
|
432
|
+
* only its state-file entry is left (an add or removal interrupted between writes).
|
|
433
|
+
*/
|
|
434
|
+
row: PoolRow | undefined;
|
|
435
|
+
/** The config file as read under the store locks. */
|
|
436
|
+
config: Readonly<Record<string, unknown>>;
|
|
437
|
+
/** The state file as read under the store locks. */
|
|
438
|
+
state: Readonly<Record<string, unknown>>;
|
|
439
|
+
}
|
|
440
|
+
interface RemoveOptions extends RowToggleOptions {
|
|
441
|
+
/** Exact reservation required to remove a row that is still staged. */
|
|
442
|
+
staged?: {
|
|
443
|
+
reservation: string;
|
|
444
|
+
};
|
|
445
|
+
/**
|
|
446
|
+
* The credential the removal was decided for (since 0.11.7). Checked under
|
|
447
|
+
* every lock, before `protect` and before anything is written or repaired:
|
|
448
|
+
* - a roster row must be bound to its credential stamp, not torn, and hold
|
|
449
|
+
* exactly this epoch and recorded identity (absence included);
|
|
450
|
+
* - an orphan (only a state-file entry left, by a removal or add
|
|
451
|
+
* interrupted between its writes) must carry a stamp this store can bind
|
|
452
|
+
* to the credential beside it, and that stamp must name exactly this
|
|
453
|
+
* epoch and identity.
|
|
454
|
+
* Epochs only grow per id (a removal records the dropped epoch, and a later
|
|
455
|
+
* add of the id starts past it), so an orphan an interrupted later add
|
|
456
|
+
* left under the same id never matches the epoch of the row the caller
|
|
457
|
+
* meant to remove. A mismatch refuses with kind `attribution`, an orphan
|
|
458
|
+
* or row with no bindable stamp with kind `unbound-credential`; both leave
|
|
459
|
+
* the files byte for byte unchanged. Without it, `remove` drops whatever
|
|
460
|
+
* the id holds, as before.
|
|
461
|
+
*
|
|
462
|
+
* The epoch survives a refresh or `rotate`, so it names a credential
|
|
463
|
+
* lineage, not one token: a caller that must remove only an exact token
|
|
464
|
+
* still checks the loaded credential in `protect`.
|
|
465
|
+
*/
|
|
466
|
+
attribution?: Attribution;
|
|
467
|
+
/**
|
|
468
|
+
* Awaited under every lock before anything is written; a reason refuses
|
|
469
|
+
* the removal (kind `row-protected`) with both files unchanged. The store
|
|
470
|
+
* keeps no record of a plugin's in-flight work, so this is where a plugin
|
|
471
|
+
* refuses an id it reserves or one its own pending-operation record (kept
|
|
472
|
+
* in the config or state file) still names: reading that record from the
|
|
473
|
+
* locked files here cannot race a writer that holds the store locks.
|
|
474
|
+
*/
|
|
475
|
+
protect?: (id: string, view: RemoveView) => string | undefined | Promise<string | undefined>;
|
|
476
|
+
}
|
|
477
|
+
type RemoveResult = {
|
|
478
|
+
id: string;
|
|
479
|
+
/**
|
|
480
|
+
* `removed`: the roster row was dropped (and its state entry, if any).
|
|
481
|
+
* `completed`: only a state-file entry was left, by a removal interrupted
|
|
482
|
+
* between its config and state writes or an add interrupted before its
|
|
483
|
+
* config write, and it is now dropped.
|
|
484
|
+
*/
|
|
485
|
+
outcome: 'removed' | 'completed';
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* Options of `reorder`. It names no row, so its failure hook is handed only
|
|
489
|
+
* the failure; it takes no row lock and no provider-wide lock, so the extra
|
|
490
|
+
* locks are taken first, then the store locks.
|
|
491
|
+
*/
|
|
492
|
+
interface ReorderOptions {
|
|
493
|
+
/** Called once, awaited, on every non-success path, before the extra locks release. */
|
|
494
|
+
onFailure?: (error: PoolOperationError) => void | Promise<void>;
|
|
495
|
+
/** Locks taken, in this order, before the store locks. */
|
|
496
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
497
|
+
}
|
|
498
|
+
type ReorderResult = {
|
|
499
|
+
/** The roster order now on disk. */
|
|
500
|
+
ids: string[];
|
|
501
|
+
/** `unchanged` when the roster was already in this order; nothing was written. */
|
|
502
|
+
outcome: 'reordered' | 'unchanged';
|
|
503
|
+
};
|
|
504
|
+
interface AddInput {
|
|
505
|
+
id: string;
|
|
506
|
+
credential: PoolCredential;
|
|
507
|
+
identity?: string;
|
|
508
|
+
label?: string;
|
|
509
|
+
disabled?: {
|
|
510
|
+
reason: string;
|
|
511
|
+
};
|
|
512
|
+
stage?: {
|
|
513
|
+
reservation: string;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* Provider state for the credential, written in the same state write as
|
|
517
|
+
* the credential (needs the store's provider-state codec). On an `add`
|
|
518
|
+
* that rotates a row already holding this secret it is merged with the
|
|
519
|
+
* row's value (`ProviderStateCodec.merge`); left out, that row keeps its
|
|
520
|
+
* value.
|
|
521
|
+
*/
|
|
522
|
+
providerState?: unknown;
|
|
523
|
+
}
|
|
524
|
+
/** What `replace` and `rotate` take beside the credential. */
|
|
525
|
+
interface CredentialWriteInput {
|
|
526
|
+
identity?: string;
|
|
527
|
+
/**
|
|
528
|
+
* Provider state written in the same state write as the credential. For
|
|
529
|
+
* `rotate` it is merged with the row's value; left out, the row keeps its
|
|
530
|
+
* value. For `replace` see `ProviderStateCodec.onReplace`.
|
|
531
|
+
*/
|
|
532
|
+
providerState?: unknown;
|
|
533
|
+
}
|
|
534
|
+
type AddResult = {
|
|
535
|
+
/** The row holding the credential; an existing row's id on a re-add. */
|
|
536
|
+
id: string;
|
|
537
|
+
outcome: 'added' | 'added-disabled' | 'completed' | 'rotated' | 'exists';
|
|
538
|
+
credential: StoredCredential;
|
|
539
|
+
credentialEpoch: number;
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Options of `disable` and `enable`. A call that passes neither
|
|
543
|
+
* `attribution` nor `providerState` behaves exactly as it did before 0.7.0.
|
|
544
|
+
*/
|
|
545
|
+
interface RowTransitionOptions extends RowToggleOptions {
|
|
546
|
+
protect?: ProtectFn;
|
|
547
|
+
/**
|
|
548
|
+
* The credential epoch and recorded identity the caller's evidence for the
|
|
549
|
+
* transition was obtained under (as `recordQuota`'s attribution: an
|
|
550
|
+
* identity left out means the row had none). The call is refused
|
|
551
|
+
* (`attribution`, retryable, nothing written) once the row holds another
|
|
552
|
+
* epoch or identity, so a provider's late answer about a replaced
|
|
553
|
+
* credential never disables, or switches back on, the row now holding its
|
|
554
|
+
* successor.
|
|
555
|
+
*/
|
|
556
|
+
attribution?: Attribution;
|
|
557
|
+
/**
|
|
558
|
+
* A provider-state change made in the same transaction as the transition,
|
|
559
|
+
* under the rules of `updateProviderState` (codec validation, the stamp
|
|
560
|
+
* rebound to the value, `unbound-credential` for a row no stamp of this
|
|
561
|
+
* store can bind it to); it requires `attribution`. The value and the
|
|
562
|
+
* enabled flag land together: no reader, and no crash at any write point,
|
|
563
|
+
* shows one without the other. Returning `DECLINE_TRANSITION` declines the
|
|
564
|
+
* whole call and writes nothing.
|
|
565
|
+
*/
|
|
566
|
+
providerState?: RowTransitionMutator;
|
|
567
|
+
}
|
|
568
|
+
interface RowTransitionResult {
|
|
569
|
+
id: string;
|
|
570
|
+
/** The provider-state mutator declined: nothing was written. */
|
|
571
|
+
declined?: true;
|
|
572
|
+
/**
|
|
573
|
+
* Set when a provider-state mutator ran and did not decline: what it did
|
|
574
|
+
* to the value, as `updateProviderState` reports it.
|
|
575
|
+
*/
|
|
576
|
+
providerStateOutcome?: UpdateProviderStateResult['outcome'];
|
|
577
|
+
/** The provider state the row now holds, when a mutator ran and left one. */
|
|
578
|
+
providerState?: unknown;
|
|
579
|
+
}
|
|
580
|
+
//#endregion
|
|
581
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/provider-state.d.ts
|
|
582
|
+
/**
|
|
583
|
+
* Receives a private copy of the row's provider state (undefined when the row
|
|
584
|
+
* shows none) and the row as loaded under the locks, and returns the next
|
|
585
|
+
* provider state; returning undefined clears it, so a mutator that means to
|
|
586
|
+
* keep the value returns it. It runs under the row lock and the store locks,
|
|
587
|
+
* so it must not call back into the store (`PoolReentryError`).
|
|
588
|
+
*/
|
|
589
|
+
type ProviderStateMutator = (current: unknown | undefined, row: PoolRow) => unknown | Promise<unknown>;
|
|
590
|
+
type UpdateProviderStateResult = {
|
|
591
|
+
id: string;
|
|
592
|
+
/** The provider state now on disk; absent when the row has none. */
|
|
593
|
+
providerState?: unknown;
|
|
594
|
+
/**
|
|
595
|
+
* `unchanged`: the mutator returned what the row already shows (or cleared
|
|
596
|
+
* a row that holds none); nothing was written.
|
|
597
|
+
*/
|
|
598
|
+
outcome: 'updated' | 'cleared' | 'unchanged';
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* Returned by the provider-state mutator of an attributed `disable` or
|
|
602
|
+
* `enable` to decline the whole transition: nothing is written, neither the
|
|
603
|
+
* provider state nor the row's enabled flag, and the call resolves with
|
|
604
|
+
* `declined: true`. A mutator declines when the state it is shown is newer
|
|
605
|
+
* than what its caller saw, such as an eligibility recorded after the
|
|
606
|
+
* request whose refusal is being acted on. It is a value of its own because
|
|
607
|
+
* `undefined` already means "clear the provider state". `Symbol.for` keeps it
|
|
608
|
+
* equal across two copies of this module loaded in one process.
|
|
609
|
+
*/
|
|
610
|
+
declare const DECLINE_TRANSITION: unique symbol;
|
|
611
|
+
/**
|
|
612
|
+
* The provider-state mutator of an attributed `disable` or `enable`: as
|
|
613
|
+
* `ProviderStateMutator`, and it may also return `DECLINE_TRANSITION`.
|
|
614
|
+
*/
|
|
615
|
+
type RowTransitionMutator = (current: unknown | undefined, row: PoolRow) => unknown | typeof DECLINE_TRANSITION | Promise<unknown | typeof DECLINE_TRANSITION>;
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/publication.d.ts
|
|
618
|
+
interface PublishPlan {
|
|
619
|
+
operationId: string;
|
|
620
|
+
remove: Array<{
|
|
621
|
+
id: string;
|
|
622
|
+
attribution: Attribution;
|
|
623
|
+
fingerprint?: string;
|
|
624
|
+
}>;
|
|
625
|
+
finalize: Array<{
|
|
626
|
+
id: string;
|
|
627
|
+
attribution: Attribution;
|
|
628
|
+
reservation: string;
|
|
629
|
+
enabled: boolean;
|
|
630
|
+
disabledReason?: string;
|
|
631
|
+
}>;
|
|
632
|
+
order: string[];
|
|
633
|
+
}
|
|
634
|
+
interface PublicationReceipt {
|
|
635
|
+
operationId: string;
|
|
636
|
+
planDigest: string;
|
|
637
|
+
phase: 'committed' | 'cleaned';
|
|
638
|
+
removed: Array<{
|
|
639
|
+
id: string;
|
|
640
|
+
credentialEpoch: number;
|
|
641
|
+
}>;
|
|
642
|
+
finalized: Array<{
|
|
643
|
+
id: string;
|
|
644
|
+
credentialEpoch: number;
|
|
645
|
+
reservation: string;
|
|
646
|
+
enabled: boolean;
|
|
647
|
+
}>;
|
|
648
|
+
}
|
|
649
|
+
interface PublishOptions {
|
|
650
|
+
protect?: ProtectFn;
|
|
651
|
+
extraLocks?: PoolLockSpec[];
|
|
652
|
+
providerLock?: PoolLockSpec;
|
|
653
|
+
onFailure?: FailureHook;
|
|
654
|
+
}
|
|
655
|
+
interface PublishResult {
|
|
656
|
+
outcome: 'published' | 'cleaned' | 'already-cleaned';
|
|
657
|
+
receipt: PublicationReceipt;
|
|
658
|
+
}
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/pull.d.ts
|
|
661
|
+
/** What a pull is issued with: the credential and its attribution tuple. */
|
|
662
|
+
interface PullRequest {
|
|
663
|
+
id: string;
|
|
664
|
+
credential: StoredCredential;
|
|
665
|
+
credentialEpoch: number;
|
|
666
|
+
identity?: string;
|
|
667
|
+
reason: PullReason;
|
|
668
|
+
}
|
|
669
|
+
type PullHook = (request: PullRequest) => Promise<unknown>;
|
|
670
|
+
//#endregion
|
|
671
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/refresh.d.ts
|
|
672
|
+
/** What the injected provider refresh function returns. */
|
|
673
|
+
interface ProviderRefreshResult {
|
|
674
|
+
access: string;
|
|
675
|
+
refresh: string;
|
|
676
|
+
expires: number;
|
|
677
|
+
expiresIn?: number;
|
|
678
|
+
/** The account's wire identity, when the provider reports one. */
|
|
679
|
+
identity?: string;
|
|
680
|
+
/**
|
|
681
|
+
* Provider state that changes with the new token (needs the store's
|
|
682
|
+
* provider-state codec). It is merged with the row's value on disk
|
|
683
|
+
* (`ProviderStateCodec.merge`) and written in the same state write as the
|
|
684
|
+
* rotated credential, under the same commit fence. Left out, the row keeps
|
|
685
|
+
* its value.
|
|
686
|
+
*/
|
|
687
|
+
providerState?: unknown;
|
|
688
|
+
}
|
|
689
|
+
type ProviderRefresh = (credential: OAuthCredential & {
|
|
690
|
+
lastRefreshedAt?: number;
|
|
691
|
+
}, row: PoolRow) => Promise<ProviderRefreshResult>;
|
|
692
|
+
interface RefreshOptions {
|
|
693
|
+
/** The one provider-wide lock serialising every provider call. */
|
|
694
|
+
providerLock?: PoolLockSpec;
|
|
695
|
+
/** Taken after the provider-wide lock in this order, released in reverse. */
|
|
696
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
697
|
+
/**
|
|
698
|
+
* Awaited once an ordinary rotation is persisted and the store locks released.
|
|
699
|
+
* Never called for `identity-contradicted`: its credential must not propagate
|
|
700
|
+
* as the row's recorded account.
|
|
701
|
+
*/
|
|
702
|
+
onPersisted?: (rowId: string, credential: StoredCredential) => void | Promise<void>;
|
|
703
|
+
onFailure?: FailureHook;
|
|
704
|
+
/**
|
|
705
|
+
* Awaited before any lock is taken, on the locked re-read, and at commit
|
|
706
|
+
* time under the store locks; a reason refuses the refresh there, leaving
|
|
707
|
+
* the stored credential untouched and discarding any rotated material.
|
|
708
|
+
*/
|
|
709
|
+
refuse?: (row: PoolRow) => string | undefined | Promise<string | undefined>;
|
|
710
|
+
}
|
|
711
|
+
type RefreshOutcome = {
|
|
712
|
+
status: 'rotated';
|
|
713
|
+
rowId: string;
|
|
714
|
+
credential: StoredCredential;
|
|
715
|
+
identity?: string;
|
|
716
|
+
} |
|
|
717
|
+
/**
|
|
718
|
+
* The provider's successor credential is stored bound to expectedIdentity,
|
|
719
|
+
* not returnedIdentity. The row stays disabled until the adapter supplies
|
|
720
|
+
* an identity-validated replacement credential through replace.
|
|
721
|
+
*/
|
|
722
|
+
{
|
|
723
|
+
status: 'identity-contradicted';
|
|
724
|
+
rowId: string;
|
|
725
|
+
expectedIdentity: string;
|
|
726
|
+
returnedIdentity: string;
|
|
727
|
+
credential: StoredCredential;
|
|
728
|
+
} | {
|
|
729
|
+
status: 'refused';
|
|
730
|
+
rowId: string;
|
|
731
|
+
reason: string;
|
|
732
|
+
};
|
|
733
|
+
//#endregion
|
|
734
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/settings.d.ts
|
|
735
|
+
/** The plugin's settings: every top-level config key except the pool-owned ones. */
|
|
736
|
+
type PoolSettings = Record<string, unknown>;
|
|
737
|
+
type SettingsRead = {
|
|
738
|
+
status: 'ready';
|
|
739
|
+
settings: PoolSettings;
|
|
740
|
+
} |
|
|
741
|
+
/**
|
|
742
|
+
* The config still holds a legacy roster with no pool key. Its settings
|
|
743
|
+
* read the same way; `updateSettings` refuses until the pool is initialized.
|
|
744
|
+
*/
|
|
745
|
+
{
|
|
746
|
+
status: 'pending-migration';
|
|
747
|
+
settings: PoolSettings;
|
|
748
|
+
} | {
|
|
749
|
+
status: 'error';
|
|
750
|
+
file: 'config' | 'state';
|
|
751
|
+
reason: string;
|
|
752
|
+
};
|
|
753
|
+
/**
|
|
754
|
+
* Receives a private copy of the current settings and either edits it in
|
|
755
|
+
* place (returning nothing) or returns the complete next settings object.
|
|
756
|
+
* It runs under the store locks, so it must not call back into the store:
|
|
757
|
+
* a store operation called from inside it is refused (`PoolReentryError`).
|
|
758
|
+
*/
|
|
759
|
+
type SettingsMutator = (settings: PoolSettings) => PoolSettings | undefined | Promise<PoolSettings | undefined>;
|
|
760
|
+
/**
|
|
761
|
+
* Options of `updateSettings`. It names no row, so its failure hook is
|
|
762
|
+
* handed only the failure; like `reorder` it takes the extra locks, then the
|
|
763
|
+
* store locks, and no row or provider-wide lock.
|
|
764
|
+
*/
|
|
765
|
+
interface UpdateSettingsOptions {
|
|
766
|
+
/** Called once, awaited, on every non-success path, before the extra locks release. */
|
|
767
|
+
onFailure?: (error: PoolOperationError) => void | Promise<void>;
|
|
768
|
+
/** Locks taken, in this order, before the store locks. */
|
|
769
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
770
|
+
}
|
|
771
|
+
type UpdateSettingsResult = {
|
|
772
|
+
/** The settings now on disk. */
|
|
773
|
+
settings: PoolSettings;
|
|
774
|
+
/** `unchanged` when the mutator left the settings as they were; nothing was written. */
|
|
775
|
+
outcome: 'updated' | 'unchanged';
|
|
776
|
+
};
|
|
777
|
+
//#endregion
|
|
778
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/pool.d.ts
|
|
779
|
+
interface OpenPoolStoreOptions {
|
|
780
|
+
/** The provider every row of this pool belongs to; keys the provider-wide lock. */
|
|
781
|
+
provider: string;
|
|
782
|
+
configPath: string;
|
|
783
|
+
statePath: string;
|
|
784
|
+
quota: QuotaCodec;
|
|
785
|
+
/**
|
|
786
|
+
* The codec of the provider state kept beside each row's credential (see
|
|
787
|
+
* `ProviderStateCodec`). Without it no row shows a provider state, and
|
|
788
|
+
* every write that would set one refuses (`invalid-input`); writes that
|
|
789
|
+
* leave it alone keep the value on disk as it is, and `replace` clears it.
|
|
790
|
+
*/
|
|
791
|
+
providerState?: ProviderStateCodec;
|
|
792
|
+
/**
|
|
793
|
+
* Refuse every credential this store did not stamp (default false, which
|
|
794
|
+
* loads unstamped and mis-stamped credentials as older writers left them).
|
|
795
|
+
* When true, a row whose `stamp` is not `bound` loads `unbound` and is no
|
|
796
|
+
* candidate, and every operation that would use or keep its credential or
|
|
797
|
+
* what was observed about it (`refresh`, quota pulls, `recordQuota`,
|
|
798
|
+
* `recordIdentity`, `rotate`, and an `add` of the same secret or onto the
|
|
799
|
+
* same credential-less row) refuses with `unbound-credential` before any
|
|
800
|
+
* provider call or write, checked again under the locks and at commit.
|
|
801
|
+
* Nothing makes such a row bound except `replace`, which starts a new
|
|
802
|
+
* credential epoch and drops what was observed about the old one.
|
|
803
|
+
* An interrupted add's state-only orphan is recovered only when its stamp
|
|
804
|
+
* binds the stored and incoming material, including a supplied identity and
|
|
805
|
+
* an API key's endpoint/header. Otherwise add refuses `unbound-credential`
|
|
806
|
+
* without writing; `remove(id)` explicitly discards the orphan.
|
|
807
|
+
*/
|
|
808
|
+
requireCredentialStamps?: boolean;
|
|
809
|
+
/** Require an exact secret fingerprint for every roster-publication removal. */
|
|
810
|
+
requireRemovedFingerprint?: boolean;
|
|
811
|
+
/** Injected clock for leases, refresh stamps and `addedAt`. */
|
|
812
|
+
now?: () => number;
|
|
813
|
+
/**
|
|
814
|
+
* Ordered store-lock list held across every read-modify-write. Defaults to
|
|
815
|
+
* the older writers' `save` lock at the config path, then at the state path.
|
|
816
|
+
*/
|
|
817
|
+
storeLocks?: readonly PoolLockSpec[];
|
|
818
|
+
/** Defaults for every lock the store takes (see `POOL_LOCK_DEFAULTS`). */
|
|
819
|
+
lockOptions?: Partial<PoolLockOptions>;
|
|
820
|
+
/** Overrides for the row locks only. */
|
|
821
|
+
rowLockOptions?: Partial<PoolLockOptions>;
|
|
822
|
+
/** The provider-wide lock; defaults to `provider-<provider>` beside the state file. */
|
|
823
|
+
providerLock?: PoolLockSpec;
|
|
824
|
+
/** Quota pull hook, fired without being awaited. */
|
|
825
|
+
pull?: PullHook;
|
|
826
|
+
/** Receives every pull failure, since no caller awaits a pull. */
|
|
827
|
+
onPullFailure?: (rowId: string, error: PoolOperationError) => void | Promise<void>;
|
|
828
|
+
logger?: PoolLogger;
|
|
829
|
+
/** Named write steps, awaited; a test seam for crash and ownership rows. */
|
|
830
|
+
onStep?: StoreContext['onStep'];
|
|
831
|
+
/** Awaitable hold points on the refresh and pull paths; a test seam. */
|
|
832
|
+
hold?: (point: HoldPoint, rowId: string) => void | Promise<void>;
|
|
833
|
+
onLockEvent?: LockEnvironment['onLockEvent'];
|
|
834
|
+
onLockStep?: LockEnvironment['onLockStep'];
|
|
835
|
+
}
|
|
836
|
+
type PoolLoad = {
|
|
837
|
+
status: 'ready';
|
|
838
|
+
schemaVersion: number;
|
|
839
|
+
rows: PoolRow[];
|
|
840
|
+
} | {
|
|
841
|
+
status: 'pending-migration';
|
|
842
|
+
roster: unknown[];
|
|
843
|
+
} | {
|
|
844
|
+
status: 'error';
|
|
845
|
+
file: 'config' | 'state';
|
|
846
|
+
reason: string;
|
|
847
|
+
kind?: 'snapshot-contended';
|
|
848
|
+
retryable?: true;
|
|
849
|
+
};
|
|
850
|
+
interface PoolStore {
|
|
851
|
+
/** Reads the pool and fires first-reading pulls; never writes a file itself. */
|
|
852
|
+
load(): Promise<PoolLoad>;
|
|
853
|
+
/** Reads the pool without firing anything. */
|
|
854
|
+
read(): Promise<PoolLoad>;
|
|
855
|
+
/**
|
|
856
|
+
* Turns a pending-migration config into an empty pool (the pool key with no
|
|
857
|
+
* row entries) in one locked config write, dropping the named top-level
|
|
858
|
+
* keys and keeping the rest. The start of a plugin's migration; a ready
|
|
859
|
+
* pool is left alone. Failures carry operation `initialize`.
|
|
860
|
+
*/
|
|
861
|
+
initialize(input?: {
|
|
862
|
+
dropKeys?: readonly string[];
|
|
863
|
+
}): Promise<{
|
|
864
|
+
status: InitializeOutcome;
|
|
865
|
+
}>;
|
|
866
|
+
/**
|
|
867
|
+
* Adds a row, or completes or rotates the row already holding the id or
|
|
868
|
+
* the secret. A new row starts at credential epoch 1; since 0.8.0 one
|
|
869
|
+
* whose id the pool held before starts one past the highest epoch that id
|
|
870
|
+
* held (see `Attribution`), and an id that held `Number.MAX_SAFE_INTEGER`
|
|
871
|
+
* refuses (`id-removed`) before writing.
|
|
872
|
+
*/
|
|
873
|
+
add(input: AddInput, options?: AddOptions): Promise<AddResult>;
|
|
874
|
+
publishRoster(plan: PublishPlan, options?: PublishOptions): Promise<PublishResult>;
|
|
875
|
+
publication(operationId: string): Promise<PublicationReceipt | undefined>;
|
|
876
|
+
/**
|
|
877
|
+
* Gives a row a new credential and a new credential epoch. Since 0.6.0 the
|
|
878
|
+
* row's provider state is whatever `ProviderStateCodec.onReplace` returns;
|
|
879
|
+
* without that hook it is `input.providerState`, else cleared.
|
|
880
|
+
* Optional `attribution` fences the write on the prior credential under the
|
|
881
|
+
* locks, before any write or replacement hook; see `RowWriteOptions`.
|
|
882
|
+
*/
|
|
883
|
+
replace(id: string, credential: PoolCredential, input?: CredentialWriteInput, options?: RowWriteOptions): Promise<{
|
|
884
|
+
id: string;
|
|
885
|
+
credential: StoredCredential;
|
|
886
|
+
credentialEpoch: number;
|
|
887
|
+
}>;
|
|
888
|
+
/**
|
|
889
|
+
* Refreshes the secret a row holds without changing its account or
|
|
890
|
+
* endpoint. Since 0.4.1 an API key may leave out `baseURL` and `authHeader`
|
|
891
|
+
* to keep the row's, and one that gives another is refused
|
|
892
|
+
* (`endpoint-mismatch`) before writing: that is a `replace`.
|
|
893
|
+
* Takes the same optional attribution fence as `replace` (`RowWriteOptions`).
|
|
894
|
+
*/
|
|
895
|
+
rotate(id: string, credential: RotateCredential, input?: CredentialWriteInput, options?: RowWriteOptions): Promise<{
|
|
896
|
+
id: string;
|
|
897
|
+
credential: StoredCredential;
|
|
898
|
+
}>;
|
|
899
|
+
/**
|
|
900
|
+
* Changes a row's provider state without touching its credential (since
|
|
901
|
+
* 0.6.0), under the row lock, `extraLocks` and the store locks. Refuses
|
|
902
|
+
* (`attribution`) once the row has moved off the credential epoch or
|
|
903
|
+
* identity in `fence`, and (`unknown-row`) once it is removed.
|
|
904
|
+
*/
|
|
905
|
+
updateProviderState(id: string, fence: Attribution, mutator: ProviderStateMutator, options?: RowToggleOptions): Promise<UpdateProviderStateResult>;
|
|
906
|
+
/**
|
|
907
|
+
* Sets `enabled: false` and the entry's `disabledReason`. Takes the row
|
|
908
|
+
* lock, then `extraLocks`, then the store locks (the row lock and
|
|
909
|
+
* `extraLocks` since 0.2.3). Since 0.7.0 it may be fenced on the
|
|
910
|
+
* credential the caller's evidence is about (`attribution`) and carry a
|
|
911
|
+
* provider-state change that lands with it (`providerState`); see
|
|
912
|
+
* `RowTransitionOptions`.
|
|
913
|
+
*/
|
|
914
|
+
disable(id: string, reason: string, options?: RowTransitionOptions): Promise<RowTransitionResult>;
|
|
915
|
+
/**
|
|
916
|
+
* Clears `enabled: false` and `disabledReason` (since 0.2.3); refuses with
|
|
917
|
+
* `duplicate-identity` when another enabled OAuth row holds the row's
|
|
918
|
+
* identity. Locks as `disable`, and takes the same options since 0.7.0.
|
|
919
|
+
*/
|
|
920
|
+
enable(id: string, options?: RowTransitionOptions): Promise<RowTransitionResult>;
|
|
921
|
+
/**
|
|
922
|
+
* Deletes the roster row, its per-row entry and its state-file credential
|
|
923
|
+
* (since 0.2.3). Locks as `disable`; `protect` can refuse the id.
|
|
924
|
+
*/
|
|
925
|
+
remove(id: string, options?: RemoveOptions): Promise<RemoveResult>;
|
|
926
|
+
/**
|
|
927
|
+
* Sets the roster order (since 0.2.4) in one config write. `ids` must name
|
|
928
|
+
* every roster id exactly once; anything else refuses with `invalid-order`
|
|
929
|
+
* and writes nothing. Takes `extraLocks`, then the store locks; no row or
|
|
930
|
+
* provider-wide lock. Roster rows and their entries are left unchanged.
|
|
931
|
+
*/
|
|
932
|
+
reorder(ids: readonly string[], options?: ReorderOptions): Promise<ReorderResult>;
|
|
933
|
+
/**
|
|
934
|
+
* The plugin's settings (since 0.2.6): every top-level key of the config
|
|
935
|
+
* file except the pool-owned ones (`POOL_OWNED_KEYS`). Never writes.
|
|
936
|
+
*/
|
|
937
|
+
readSettings(): Promise<SettingsRead>;
|
|
938
|
+
/**
|
|
939
|
+
* One locked write of the plugin's settings (since 0.2.6) beside the pool,
|
|
940
|
+
* in the config file. Refuses a result that sets a pool-owned key
|
|
941
|
+
* (`invalid-input`). Takes `extraLocks`, then the store locks.
|
|
942
|
+
*/
|
|
943
|
+
updateSettings(mutator: SettingsMutator, options?: UpdateSettingsOptions): Promise<UpdateSettingsResult>;
|
|
944
|
+
/**
|
|
945
|
+
* Records the identity a lookup found for the row's credential. Since
|
|
946
|
+
* 0.3.1 it takes the credential epoch the lookup was issued for, and
|
|
947
|
+
* refuses a lookup that completes after the row was replaced
|
|
948
|
+
* (`attribution`) or a row recorded for another account
|
|
949
|
+
* (`identity-mismatch`).
|
|
950
|
+
*/
|
|
951
|
+
recordIdentity(id: string, identity: string, attribution: Pick<Attribution, 'credentialEpoch'>, options?: RowOperationOptions): Promise<{
|
|
952
|
+
id: string;
|
|
953
|
+
disabled: string[];
|
|
954
|
+
}>;
|
|
955
|
+
refresh(id: string, provider: ProviderRefresh, options?: RefreshOptions): Promise<RefreshOutcome>;
|
|
956
|
+
recordQuota(id: string, attribution: Attribution, observation: unknown): Promise<void>;
|
|
957
|
+
/** Fires a pull for a row admission refused for want of a reading. */
|
|
958
|
+
requestReading(id: string): void;
|
|
959
|
+
/** Resolves once every pull fired so far has settled. */
|
|
960
|
+
pullsSettled(): Promise<void>;
|
|
961
|
+
}
|
|
962
|
+
//#endregion
|
|
963
|
+
//#region ../core/dist/paths.d.ts
|
|
964
|
+
/**
|
|
965
|
+
* The config file and the runtime-state file a store operation reads and writes.
|
|
966
|
+
*
|
|
967
|
+
* Both are required. A store function never derives one from the other, because
|
|
968
|
+
* a host may point its state file somewhere the derivation would not reach and
|
|
969
|
+
* a silently derived path would lock one file while writing another.
|
|
970
|
+
*/
|
|
971
|
+
interface AccountPaths {
|
|
972
|
+
configPath: string;
|
|
973
|
+
statePath: string;
|
|
974
|
+
}
|
|
975
|
+
//#endregion
|
|
976
|
+
//#region ../core/dist/oauth.d.ts
|
|
977
|
+
interface IdTokenClaims {
|
|
978
|
+
chatgpt_account_id?: string;
|
|
979
|
+
email?: string;
|
|
980
|
+
organizations?: Array<{
|
|
981
|
+
id: string;
|
|
982
|
+
}>;
|
|
983
|
+
'https://api.openai.com/auth'?: {
|
|
984
|
+
chatgpt_account_id?: string;
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
|
|
988
|
+
declare function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined;
|
|
989
|
+
interface TokenResponse {
|
|
990
|
+
id_token: string;
|
|
991
|
+
access_token: string;
|
|
992
|
+
refresh_token: string;
|
|
993
|
+
expires_in?: number;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Minimal shape of a fallback OAuth account for ingestion. Matches the
|
|
997
|
+
* fields used by upsertAccount and beginAccountLogin, compatible with
|
|
998
|
+
* the full OAuthAccount type in accounts.ts.
|
|
999
|
+
*/
|
|
1000
|
+
interface IngestAccount {
|
|
1001
|
+
id: string;
|
|
1002
|
+
label?: string;
|
|
1003
|
+
type: 'oauth';
|
|
1004
|
+
access?: string;
|
|
1005
|
+
refresh: string;
|
|
1006
|
+
expires?: number;
|
|
1007
|
+
enabled: boolean;
|
|
1008
|
+
addedAt: number;
|
|
1009
|
+
lastUsed: number;
|
|
1010
|
+
/**
|
|
1011
|
+
* When the token was obtained. Stamped at login so a freshly added account
|
|
1012
|
+
* carries a refresh marker — without it, the runtime-state merge cannot tell a
|
|
1013
|
+
* rotated token from a stale one (both default to 0) and a concurrent stale
|
|
1014
|
+
* save could roll the token back.
|
|
1015
|
+
*/
|
|
1016
|
+
lastRefreshedAt?: number;
|
|
1017
|
+
/** Stable ChatGPT account identifier from the OAuth token claims. */
|
|
1018
|
+
accountId?: string;
|
|
1019
|
+
}
|
|
1020
|
+
interface BeginAccountLoginOptions {
|
|
1021
|
+
label?: string;
|
|
1022
|
+
headless?: boolean;
|
|
1023
|
+
signal?: AbortSignal;
|
|
1024
|
+
/** Host package version, sent as the version half of the `User-Agent`. */
|
|
1025
|
+
version: string;
|
|
1026
|
+
}
|
|
1027
|
+
interface BeginAccountLoginResult {
|
|
1028
|
+
url: string;
|
|
1029
|
+
instructions: string;
|
|
1030
|
+
/** Resolves after the user completes the OAuth flow with a ready-to-ingest account. */
|
|
1031
|
+
completion: Promise<IngestAccount>;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Split-return OAuth flow entry point.
|
|
1035
|
+
*
|
|
1036
|
+
* Browser flow (default):
|
|
1037
|
+
* 1. Start OAuth server, generate PKCE, build authorize URL
|
|
1038
|
+
* 2. Return { url, instructions, completion } — url is ready immediately
|
|
1039
|
+
* 3. completion resolves after browser callback + token exchange
|
|
1040
|
+
*
|
|
1041
|
+
* Headless flow:
|
|
1042
|
+
* 1. Begin device auth
|
|
1043
|
+
* 2. Return { url, instructions, completion }
|
|
1044
|
+
* 3. completion polls device endpoint + exchanges for tokens
|
|
1045
|
+
*
|
|
1046
|
+
* The split return allows the TUI command to show the URL before the
|
|
1047
|
+
* (potentially 30-60s) wait, avoiding a deadlock.
|
|
1048
|
+
*/
|
|
1049
|
+
declare function beginAccountLogin(opts: BeginAccountLoginOptions): Promise<BeginAccountLoginResult>;
|
|
1050
|
+
//#endregion
|
|
1051
|
+
//#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/connection-file.d.ts
|
|
1052
|
+
interface Endpoint {
|
|
1053
|
+
host: string;
|
|
1054
|
+
port: number;
|
|
1055
|
+
}
|
|
1056
|
+
interface ConnectionInfo {
|
|
1057
|
+
schema: number;
|
|
1058
|
+
endpoints: Endpoint[];
|
|
1059
|
+
/** Transport key bytes. Serialized on disk as a JSON array of numbers. */
|
|
1060
|
+
key: Uint8Array;
|
|
1061
|
+
/** 16-byte daemon identity. Serialized on disk as a JSON array of numbers. */
|
|
1062
|
+
daemonId: Uint8Array;
|
|
1063
|
+
pid: number;
|
|
1064
|
+
daemonVer: string;
|
|
1065
|
+
}
|
|
1066
|
+
//#endregion
|
|
1067
|
+
//#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/envelope.d.ts
|
|
1068
|
+
/** Scheduling priority carried in flags bits 1-2. */
|
|
1069
|
+
declare enum Priority {
|
|
1070
|
+
Passive = 0,
|
|
1071
|
+
Interactive = 1,
|
|
1072
|
+
Background = 2
|
|
1073
|
+
}
|
|
1074
|
+
/** Admission behavior carried in flags bits 4-5. */
|
|
1075
|
+
declare enum AdmissionClass {
|
|
1076
|
+
Normal = 0,
|
|
1077
|
+
Expedite = 1,
|
|
1078
|
+
Sheddable = 2
|
|
1079
|
+
}
|
|
1080
|
+
//#endregion
|
|
1081
|
+
//#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/route-handle.d.ts
|
|
1082
|
+
interface ReverseRequestContext {
|
|
1083
|
+
readonly corr: bigint;
|
|
1084
|
+
readonly method: string;
|
|
1085
|
+
}
|
|
1086
|
+
type ReverseRequestHandler = (body: Uint8Array, ctx: ReverseRequestContext) => Promise<Uint8Array> | Uint8Array;
|
|
1087
|
+
/**
|
|
1088
|
+
* Mutable handler registry prepared before route.open. The client derives
|
|
1089
|
+
* consumer_capabilities from its method families and seals that set when the
|
|
1090
|
+
* route opens; handlers for declared families may still be replaced afterward.
|
|
1091
|
+
*/
|
|
1092
|
+
declare class ReverseRequestRegistry {
|
|
1093
|
+
private readonly handlers;
|
|
1094
|
+
private declaredFamilies;
|
|
1095
|
+
onRequest(methodFamily: string, handler: ReverseRequestHandler): void;
|
|
1096
|
+
/** @internal */
|
|
1097
|
+
capabilities(): string[];
|
|
1098
|
+
/** @internal */
|
|
1099
|
+
handler(methodFamily: string): ReverseRequestHandler | undefined;
|
|
1100
|
+
/** @internal */
|
|
1101
|
+
seal(): void;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Immutable identity for one route binding on one live socket. Only channel and
|
|
1105
|
+
* epoch cross the wire; the connection token remains private to this SDK.
|
|
1106
|
+
*/
|
|
1107
|
+
declare class RouteHandle {
|
|
1108
|
+
readonly channel: number;
|
|
1109
|
+
readonly epoch: number;
|
|
1110
|
+
private constructor();
|
|
1111
|
+
/** Replace the handler for a capability declared when this route opened. */
|
|
1112
|
+
onRequest(methodFamily: string, handler: ReverseRequestHandler): void;
|
|
1113
|
+
private static create;
|
|
1114
|
+
}
|
|
1115
|
+
//#endregion
|
|
1116
|
+
//#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/client.d.ts
|
|
1117
|
+
interface BindIdentity {
|
|
1118
|
+
project_root: string;
|
|
1119
|
+
harness: string;
|
|
1120
|
+
session: string;
|
|
1121
|
+
}
|
|
1122
|
+
type RouteTarget = {
|
|
1123
|
+
kind: "tool_provider";
|
|
1124
|
+
module_id: string;
|
|
1125
|
+
} | {
|
|
1126
|
+
kind: "management_surface";
|
|
1127
|
+
module_id: string;
|
|
1128
|
+
} | {
|
|
1129
|
+
kind: "internal_service";
|
|
1130
|
+
module_id: string;
|
|
1131
|
+
service_id: string;
|
|
1132
|
+
};
|
|
1133
|
+
type ManagedRouteKind = "management_surface" | "tool_provider";
|
|
1134
|
+
interface ConsumerIdentity {
|
|
1135
|
+
module_id: string;
|
|
1136
|
+
launch_nonce: string;
|
|
1137
|
+
}
|
|
1138
|
+
interface RouteOpenOptions {
|
|
1139
|
+
/** Optional override for the consumer identity; by default the SUBC_MODULE_ID and SUBC_LAUNCH_NONCE environment variables are used when both are non-empty. Set null to send route.open without consumer_identity. */
|
|
1140
|
+
consumerIdentity?: ConsumerIdentity | null;
|
|
1141
|
+
/**
|
|
1142
|
+
* Handlers prepared before route.open. The client derives consumer_capabilities
|
|
1143
|
+
* from this registry; callers cannot declare a capability without a handler.
|
|
1144
|
+
*/
|
|
1145
|
+
reverseRequests?: ReverseRequestRegistry;
|
|
1146
|
+
}
|
|
1147
|
+
interface CatalogCapabilityRequirement {
|
|
1148
|
+
capability: string;
|
|
1149
|
+
need: "required" | "optional";
|
|
1150
|
+
}
|
|
1151
|
+
interface CatalogCapabilities {
|
|
1152
|
+
provides: string[];
|
|
1153
|
+
requires: CatalogCapabilityRequirement[];
|
|
1154
|
+
must_never_reach: string[];
|
|
1155
|
+
}
|
|
1156
|
+
/** A self-signal's anchor relative to the external surface it shapes. */
|
|
1157
|
+
type CatalogSignalAnchor = "fixed_interval" | {
|
|
1158
|
+
event: {
|
|
1159
|
+
event: string;
|
|
1160
|
+
};
|
|
1161
|
+
};
|
|
1162
|
+
/** The source of a self-signal's effective cadence. */
|
|
1163
|
+
type CatalogSignalCadence = {
|
|
1164
|
+
literal: {
|
|
1165
|
+
interval_ms: number;
|
|
1166
|
+
};
|
|
1167
|
+
} | {
|
|
1168
|
+
derived: {
|
|
1169
|
+
source: string;
|
|
1170
|
+
};
|
|
1171
|
+
};
|
|
1172
|
+
/** A self-signal declaration mirrored from a registered module manifest. */
|
|
1173
|
+
interface CatalogSelfSignalDeclaration {
|
|
1174
|
+
name: string;
|
|
1175
|
+
/** Open string for forward-compatible self-signal kinds. */
|
|
1176
|
+
kind: string;
|
|
1177
|
+
effect: "observe" | "mutate";
|
|
1178
|
+
anchored_to: CatalogSignalAnchor;
|
|
1179
|
+
cadence?: CatalogSignalCadence | null;
|
|
1180
|
+
domain?: string | null;
|
|
1181
|
+
note?: string | null;
|
|
1182
|
+
}
|
|
1183
|
+
interface CatalogEntry {
|
|
1184
|
+
module_id: string;
|
|
1185
|
+
roles: unknown[];
|
|
1186
|
+
control_ops: string[];
|
|
1187
|
+
/** Static capability claims mirrored from the registered module manifest. */
|
|
1188
|
+
capabilities?: CatalogCapabilities | null;
|
|
1189
|
+
/** Self-signal declarations mirrored verbatim from the registered manifest. */
|
|
1190
|
+
self_signals?: CatalogSelfSignalDeclaration[] | null;
|
|
1191
|
+
}
|
|
1192
|
+
interface RequestOptions {
|
|
1193
|
+
priority?: Priority;
|
|
1194
|
+
admissionClass?: AdmissionClass;
|
|
1195
|
+
timeoutMs?: number;
|
|
1196
|
+
/**
|
|
1197
|
+
* Set when the request body is opaque bytes rather than JSON. This flag is the
|
|
1198
|
+
* receiver's only signal about the body representation; reply decoding follows
|
|
1199
|
+
* the response frame's flag instead of this request option.
|
|
1200
|
+
*/
|
|
1201
|
+
binary?: boolean;
|
|
1202
|
+
/** Called for each interim PUSH / StreamData frame before the terminal reply. */
|
|
1203
|
+
onProgress?: (body: Uint8Array) => void;
|
|
1204
|
+
/**
|
|
1205
|
+
* Abort the request: when this fires while the request is still in flight, the
|
|
1206
|
+
* client emits a CANCEL frame carrying that request's own corr.
|
|
1207
|
+
*
|
|
1208
|
+
* The signal exists instead of exposing corr because corr lifetime is already
|
|
1209
|
+
* tracked here to settle replies; handing it out would make every caller keep a
|
|
1210
|
+
* second map that can disagree with this one, and would let a caller cancel a
|
|
1211
|
+
* corr it does not own.
|
|
1212
|
+
*
|
|
1213
|
+
* Cancellation is best-effort by the wire's construction: the daemon forwards
|
|
1214
|
+
* the frame on a live route and silently drops it on a departed one, and no
|
|
1215
|
+
* acknowledgement exists at any layer. Only the module's own reply proves what
|
|
1216
|
+
* happened, so the promise is NOT rejected here -- it settles however the module
|
|
1217
|
+
* answers, which may be a normal completion that beat the cancel.
|
|
1218
|
+
*/
|
|
1219
|
+
signal?: AbortSignal;
|
|
1220
|
+
}
|
|
1221
|
+
interface ManagedCallOptions extends RequestOptions {
|
|
1222
|
+
/** Overrides the per-client identity used for route.open before this call. */
|
|
1223
|
+
identity?: BindIdentity;
|
|
1224
|
+
/** Defaults to management_surface, matching the store/host management APIs. */
|
|
1225
|
+
targetKind?: ManagedRouteKind;
|
|
1226
|
+
/** Optional override for the consumer identity; by default the SUBC_MODULE_ID and SUBC_LAUNCH_NONCE environment variables are used when both are non-empty. Set null to send route.open without consumer_identity. */
|
|
1227
|
+
consumerIdentity?: ConsumerIdentity | null;
|
|
1228
|
+
/** Reverse-request handlers used by the managed route and all of its reconnect reopens. */
|
|
1229
|
+
reverseRequests?: ReverseRequestRegistry;
|
|
1230
|
+
}
|
|
1231
|
+
interface SubscribeOptions {
|
|
1232
|
+
priority?: Priority;
|
|
1233
|
+
admissionClass?: AdmissionClass;
|
|
1234
|
+
}
|
|
1235
|
+
type RoutePollKind = "status" | "liveness";
|
|
1236
|
+
interface RoutePollResult {
|
|
1237
|
+
route_channel: number;
|
|
1238
|
+
route_epoch: number;
|
|
1239
|
+
status: string | null;
|
|
1240
|
+
live: boolean | null;
|
|
1241
|
+
}
|
|
1242
|
+
interface CloseRouteOptions {
|
|
1243
|
+
/**
|
|
1244
|
+
* Await in-flight UNARY requests on the route to settle before tearing it down.
|
|
1245
|
+
* Subscriptions are always aborted (a held-open stream cannot be drained).
|
|
1246
|
+
* Defaults to false: close immediately, aborting everything in flight.
|
|
1247
|
+
*/
|
|
1248
|
+
drain?: boolean;
|
|
1249
|
+
}
|
|
1250
|
+
interface ManagedCloseRouteOptions extends CloseRouteOptions {
|
|
1251
|
+
/** Consumer identity used by the cached managed route. */
|
|
1252
|
+
consumerIdentity?: ConsumerIdentity | null;
|
|
1253
|
+
/** The registry whose derived capability set identifies the cached route. */
|
|
1254
|
+
reverseRequests?: ReverseRequestRegistry;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Capped exponential reconnect backoff. maxAttempts includes the first immediate
|
|
1258
|
+
* reconnect attempt; sleeps happen only between failed transient attempts.
|
|
1259
|
+
*/
|
|
1260
|
+
interface ReconnectBackoff {
|
|
1261
|
+
/** First retry delay. */
|
|
1262
|
+
baseMs: number;
|
|
1263
|
+
/** Delay ceiling (doubling is capped here). */
|
|
1264
|
+
capMs: number;
|
|
1265
|
+
/** Max attempts (including the first) before giving up. */
|
|
1266
|
+
maxAttempts: number;
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* A live subscription to a provider's event stream, riding a single held-open
|
|
1270
|
+
* request. `onEvent` fires for each StreamData frame; `closed` resolves when the
|
|
1271
|
+
* provider ends the stream (StreamEnd) or the consumer unsubscribes, and rejects on
|
|
1272
|
+
* an Error terminal or a route GOODBYE. `unsubscribe` cancels the held-open request
|
|
1273
|
+
* so the provider unwinds.
|
|
1274
|
+
*/
|
|
1275
|
+
interface Subscription {
|
|
1276
|
+
/** Cancel the subscription: sends Cancel on the held-open request; idempotent. */
|
|
1277
|
+
unsubscribe(): void;
|
|
1278
|
+
/** Resolves on StreamEnd or local unsubscribe; rejects on an Error terminal or route close. */
|
|
1279
|
+
readonly closed: Promise<void>;
|
|
1280
|
+
}
|
|
1281
|
+
interface ConnectOptions {
|
|
1282
|
+
connectionFile: string;
|
|
1283
|
+
handshakeTimeoutMs?: number;
|
|
1284
|
+
/** Default route identity used by managed call(); can be overridden per call. */
|
|
1285
|
+
identity?: BindIdentity;
|
|
1286
|
+
/** Default route target kind used by managed call(); defaults to management_surface. */
|
|
1287
|
+
targetKind?: ManagedRouteKind;
|
|
1288
|
+
/** Backoff for managed reconnect after a connection drop. */
|
|
1289
|
+
reconnectBackoff?: ReconnectBackoff;
|
|
1290
|
+
/** Injectable sleep for timer-free reconnect tests. */
|
|
1291
|
+
sleep?: (ms: number) => Promise<void>;
|
|
1292
|
+
/**
|
|
1293
|
+
* How long managed calls keep retrying route.open in-place on retryable
|
|
1294
|
+
* refusals (module_reloading, module_warming, target_unavailable, …) before
|
|
1295
|
+
* settling not_sent. This deadline is the ONLY binder on those retries —
|
|
1296
|
+
* module reloads legitimately take tens of seconds (the daemon's drain alone
|
|
1297
|
+
* defaults to 30s), so the default matches the daemon's drain ceiling.
|
|
1298
|
+
*/
|
|
1299
|
+
routeOpenRetryDeadlineMs?: number;
|
|
1300
|
+
/**
|
|
1301
|
+
* Window the post-deadline liveness probe waits for ANY inbound frame after
|
|
1302
|
+
* sending its channel-0 Ping before convicting the socket as half-open.
|
|
1303
|
+
* Genuine event-loop starvation self-protects at any setting: a loop starved
|
|
1304
|
+
* enough to delay the probe's check also delays the read loop, and when it
|
|
1305
|
+
* wakes the buffered Pong dispatches first. Exposed for deterministic tests.
|
|
1306
|
+
*/
|
|
1307
|
+
livenessProbeWindowMs?: number;
|
|
1308
|
+
/**
|
|
1309
|
+
* Hard cap on the timeout-arbitration grace window (see
|
|
1310
|
+
* TIMEOUT_ARBITRATION_GRACE_MS). A reply whose bytes are actively arriving when
|
|
1311
|
+
* the request deadline fires is given up to this long to finish dispatching
|
|
1312
|
+
* before the call settles as a timeout. Bounded and never a deadline extension;
|
|
1313
|
+
* exposed mainly so tests can prove the arbitration deterministically.
|
|
1314
|
+
*/
|
|
1315
|
+
timeoutArbitrationGraceMs?: number;
|
|
1316
|
+
/**
|
|
1317
|
+
* Observer for daemon-originated channel-0 control pushes (`route.closing`,
|
|
1318
|
+
* `route.closed`, and any op added later). Purely advisory: the daemon's
|
|
1319
|
+
* load-bearing route-death signal remains the GOODBYE frame, and nothing in
|
|
1320
|
+
* the client's own route lifecycle consumes these. The contract is the wire
|
|
1321
|
+
* contract verbatim -- unrecognized ops still arrive here (callers ignore
|
|
1322
|
+
* what they don't know, per the MUST-ignore clause), a push that fails to
|
|
1323
|
+
* parse as JSON is dropped without surfacing, and an observer throw is
|
|
1324
|
+
* swallowed like every other caller callback so it cannot fail the read loop
|
|
1325
|
+
* or unrelated requests.
|
|
1326
|
+
*/
|
|
1327
|
+
onControlPush?: (push: ControlPush) => void;
|
|
1328
|
+
}
|
|
1329
|
+
/** A parsed daemon-originated channel-0 control push. */
|
|
1330
|
+
interface ControlPush {
|
|
1331
|
+
/** The push discriminator, e.g. "route.closing" | "route.closed". */
|
|
1332
|
+
op: string;
|
|
1333
|
+
/** The full parsed body, `op` included, for op-specific fields. */
|
|
1334
|
+
body: Record<string, unknown>;
|
|
1335
|
+
}
|
|
1336
|
+
declare class SubcClient {
|
|
1337
|
+
private sock;
|
|
1338
|
+
private currentConn;
|
|
1339
|
+
private readonly opts;
|
|
1340
|
+
private nextCorr;
|
|
1341
|
+
private readonly pending;
|
|
1342
|
+
private readonly lateResponses;
|
|
1343
|
+
private readonly routes;
|
|
1344
|
+
private readonly liveRoutes;
|
|
1345
|
+
private connectionToken;
|
|
1346
|
+
private ingressEpochDropCount;
|
|
1347
|
+
private closedErr;
|
|
1348
|
+
private closeStarted;
|
|
1349
|
+
private reconnecting;
|
|
1350
|
+
private generation;
|
|
1351
|
+
private readerActive;
|
|
1352
|
+
private constructor();
|
|
1353
|
+
get conn(): ConnectionInfo;
|
|
1354
|
+
/** Read the connection file, connect, authenticate, and start the read loop. */
|
|
1355
|
+
static connect(opts: ConnectOptions): Promise<SubcClient>;
|
|
1356
|
+
/** List modules subc knows about (channel-0 catalog.list). */
|
|
1357
|
+
catalogList(moduleId?: string): Promise<CatalogEntry[]>;
|
|
1358
|
+
/**
|
|
1359
|
+
* Resolve the sole catalog claimant for a capability.
|
|
1360
|
+
*
|
|
1361
|
+
* This expresses singular intent even when the fleet permits plural claims;
|
|
1362
|
+
* ambiguity is returned instead of selecting an arbitrary module.
|
|
1363
|
+
*/
|
|
1364
|
+
resolveProvider(capability: string): Promise<string>;
|
|
1365
|
+
/** Resolve every catalog claimant in deterministic module-id order. */
|
|
1366
|
+
resolveProviders(capability: string): Promise<string[]>;
|
|
1367
|
+
/** Open a route and return its connection-bound immutable handle. */
|
|
1368
|
+
routeOpen(target: RouteTarget, identity: BindIdentity, opts?: RouteOpenOptions): Promise<RouteHandle>;
|
|
1369
|
+
/** Send a data-plane request on exactly the supplied route generation. */
|
|
1370
|
+
request(handle: RouteHandle, body: unknown, opts?: RequestOptions): Promise<unknown>;
|
|
1371
|
+
/**
|
|
1372
|
+
* Managed route + request convenience. Opens and caches a route for the module,
|
|
1373
|
+
* reconnecting and re-opening cached routes after connection drops.
|
|
1374
|
+
*/
|
|
1375
|
+
call<Response = unknown>(moduleId: string, method: string, params?: unknown, opts?: ManagedCallOptions): Promise<Response>;
|
|
1376
|
+
/**
|
|
1377
|
+
* Managed route + raw opaque-body request convenience. Unlike call(), this
|
|
1378
|
+
* sends bytes without a JSON method envelope because the BINARY flag is the
|
|
1379
|
+
* receiver's only signal that the body is not JSON. A BINARY reply resolves
|
|
1380
|
+
* to Uint8Array; a non-binary reply is decoded as JSON.
|
|
1381
|
+
*/
|
|
1382
|
+
callBinary(moduleId: string, body: Uint8Array, opts?: ManagedCallOptions): Promise<Uint8Array | unknown>;
|
|
1383
|
+
private managedCall;
|
|
1384
|
+
/** Open a held request on exactly one route generation. */
|
|
1385
|
+
subscribe(handle: RouteHandle, body: unknown, onEvent: (event: Uint8Array) => void, opts?: SubscribeOptions): Subscription;
|
|
1386
|
+
/**
|
|
1387
|
+
* Emit CANCEL for one in-flight request when its caller's signal fires.
|
|
1388
|
+
*
|
|
1389
|
+
* Emits only while the request is unsettled by this client's own book, which is
|
|
1390
|
+
* a fact it owns and can check without racing. It deliberately does NOT check
|
|
1391
|
+
* whether the route still exists: that would be a guess, and a wrong guess turns
|
|
1392
|
+
* a frame the daemon would harmlessly drop into a frame never sent -- removing
|
|
1393
|
+
* the caller's only chance at the cost of saving nothing.
|
|
1394
|
+
*/
|
|
1395
|
+
private attachCancelSignal;
|
|
1396
|
+
/** Send a pure-header cancellation for an in-flight request. */
|
|
1397
|
+
cancel(handle: RouteHandle, corr: bigint, priority?: Priority): void;
|
|
1398
|
+
/** Poll status or liveness for exactly the supplied route generation. */
|
|
1399
|
+
routePoll(handle: RouteHandle, kind: RoutePollKind): Promise<RoutePollResult>;
|
|
1400
|
+
/** Tear down exactly the supplied route generation. */
|
|
1401
|
+
closeRoute(handle: RouteHandle, opts?: CloseRouteOptions): Promise<void>;
|
|
1402
|
+
/** Close a cached managed route by its route-open identity tuple. */
|
|
1403
|
+
closeManagedRoute(target: Extract<RouteTarget, {
|
|
1404
|
+
kind: ManagedRouteKind;
|
|
1405
|
+
}>, identity: BindIdentity, opts?: ManagedCloseRouteOptions): Promise<void>;
|
|
1406
|
+
/** Alias retained for callers that name the operation by protocol channel; it still requires a full handle. */
|
|
1407
|
+
closeRouteChannel(handle: RouteHandle, opts?: CloseRouteOptions): Promise<void>;
|
|
1408
|
+
close(): void;
|
|
1409
|
+
private drainUnaryOnHandle;
|
|
1410
|
+
private sendRouteGoodbye;
|
|
1411
|
+
private static openConnection;
|
|
1412
|
+
private controlRpc;
|
|
1413
|
+
private send;
|
|
1414
|
+
/**
|
|
1415
|
+
* A request-deadline timer has fired. Before settling as a timeout, arbitrate
|
|
1416
|
+
* the timer-vs-poll race: a reply may already be in the socket buffer, unread
|
|
1417
|
+
* only because the loop was starved. Yield one check phase (setImmediate) so a
|
|
1418
|
+
* fully-buffered reply dispatches and wins via settle()'s identity guard; then,
|
|
1419
|
+
* only while the reader is actively draining THIS socket (a frame mid-arrival),
|
|
1420
|
+
* grant a single hard-capped grace before finally settling. Absent replies
|
|
1421
|
+
* still settle right after the check phase. The settle carries the deadline
|
|
1422
|
+
* marker so the managed classifier reports deadline-not-drop.
|
|
1423
|
+
*/
|
|
1424
|
+
private arbitrateTimeout;
|
|
1425
|
+
private managedRequest;
|
|
1426
|
+
private sendManaged;
|
|
1427
|
+
private cachedRouteHandle;
|
|
1428
|
+
private openCachedRoute;
|
|
1429
|
+
private lastInboundAtMs;
|
|
1430
|
+
private livenessProbe;
|
|
1431
|
+
/**
|
|
1432
|
+
* Discriminate event-loop starvation from a half-open socket after a
|
|
1433
|
+
* deadline-no-drop settle. The arbitration deliberately keeps the socket on
|
|
1434
|
+
* that verdict (a late-read reply under load must not cost a healthy
|
|
1435
|
+
* connection), but a half-open socket — peer vanished with no FIN/RST, as
|
|
1436
|
+
* after host sleep/wake — yields the SAME verdict forever, so the keep
|
|
1437
|
+
* becomes a permanent pin to a dead transport. The discriminator is
|
|
1438
|
+
* socket-level liveness evidence: send a channel-0 Ping (the daemon always
|
|
1439
|
+
* answers — subc-core control.rs) and require ANY inbound frame within the
|
|
1440
|
+
* window; the Pong suffices, and a busy socket's other traffic proves the
|
|
1441
|
+
* link just as well. Silence convicts: the socket is failed with a named
|
|
1442
|
+
* cause and closed, so the ordinary drop path (pending rejection now,
|
|
1443
|
+
* reconnect on the next call) takes over.
|
|
1444
|
+
*
|
|
1445
|
+
* Starvation cannot be falsely convicted by a short window: a loop starved
|
|
1446
|
+
* enough to delay the read loop delays this probe's own timer identically,
|
|
1447
|
+
* and when both wake the buffered Pong dispatches before the check runs.
|
|
1448
|
+
*
|
|
1449
|
+
* A PENDING CHANNEL-0 REQUEST SUSPENDS THE PROBE (both at launch and at the
|
|
1450
|
+
* conviction check). The daemon's connection loop handles frames one at a
|
|
1451
|
+
* time, and some channel-0 ops legally park it for seconds — route.open
|
|
1452
|
+
* awaits the module's bind ack inline for up to route_bind_relay_timeout
|
|
1453
|
+
* (~12s in production) — during which OUR Ping sits unread in the daemon's
|
|
1454
|
+
* socket buffer. On an otherwise-quiet connection that silence is fully
|
|
1455
|
+
* explained by our own in-flight control op, and convicting on it would
|
|
1456
|
+
* tear down a healthy connection mid-bind (BROCA's Athena panel flagged
|
|
1457
|
+
* this exact premise; the FIFO fact is verified in subc-core server.rs
|
|
1458
|
+
* connection_loop + control.rs handle_route_open). The client always knows
|
|
1459
|
+
* its own channel-0 pendings, so the gate is local and exact: no probe
|
|
1460
|
+
* while one is in flight, no conviction if one appeared during the window.
|
|
1461
|
+
*
|
|
1462
|
+
* Scope: hooked from the managed-call path only. Control-plane requests
|
|
1463
|
+
* (route.open, catalog.list) are short-lived and their failures already
|
|
1464
|
+
* escalate through reconnect classification; the managed path is where a
|
|
1465
|
+
* plugin lives for hours and where the pin was observed in production.
|
|
1466
|
+
*/
|
|
1467
|
+
/** Any in-flight channel-0 request (pendings keyed without a route handle). */
|
|
1468
|
+
private hasControlPending;
|
|
1469
|
+
private probeLivenessAfterDeadline;
|
|
1470
|
+
private ensureConnectedForManaged;
|
|
1471
|
+
private scheduleReconnectAfterDrop;
|
|
1472
|
+
private reconnectAfterDrop;
|
|
1473
|
+
private reconnectWithRetry;
|
|
1474
|
+
private replaceConnection;
|
|
1475
|
+
private reopenCachedRoutes;
|
|
1476
|
+
private timeoutMessage;
|
|
1477
|
+
private routeClosedDuringOpen;
|
|
1478
|
+
private readLoop;
|
|
1479
|
+
private dispatch;
|
|
1480
|
+
/**
|
|
1481
|
+
* Settle a pending exactly once. The object-identity guard (the map still
|
|
1482
|
+
* holds THIS pending under `key`) is the single-winner primitive: whichever of
|
|
1483
|
+
* dispatch, a timeout, fail(), failChannel(), a GOODBYE, or a deferred timeout
|
|
1484
|
+
* arbitration reaches it first wins, and every later caller no-ops. This is what
|
|
1485
|
+
* makes the deferred-timeout arbitration safe — it cannot double-settle, reject
|
|
1486
|
+
* an already-resolved promise, or delete a pending re-created for a later corr.
|
|
1487
|
+
* Returns true when this call was the settler.
|
|
1488
|
+
*/
|
|
1489
|
+
private settle;
|
|
1490
|
+
private rejectPending;
|
|
1491
|
+
private dispatchReverseRequest;
|
|
1492
|
+
private sendReverseError;
|
|
1493
|
+
private sendReverseReply;
|
|
1494
|
+
private errorFromFrame;
|
|
1495
|
+
private evictRouteHandle;
|
|
1496
|
+
private failHandle;
|
|
1497
|
+
private fail;
|
|
1498
|
+
private notSentCallError;
|
|
1499
|
+
private outcomeUnknownCallError;
|
|
1500
|
+
private terminalCallError;
|
|
1501
|
+
private notSentRecoveryError;
|
|
1502
|
+
/** Number of nonzero-channel ingress frames dropped by endpoint epoch validation. */
|
|
1503
|
+
get droppedIngressFrames(): number;
|
|
1504
|
+
private installRoute;
|
|
1505
|
+
private isLiveHandle;
|
|
1506
|
+
private assertLiveConnection;
|
|
1507
|
+
private assertLiveHandle;
|
|
1508
|
+
private allocateCorr;
|
|
1509
|
+
private closeConnectionAfterCleanupFailure;
|
|
1510
|
+
private encode;
|
|
1511
|
+
/** Decode a terminal response according to the representation on the wire. */
|
|
1512
|
+
private decodeReply;
|
|
1513
|
+
private parseJson;
|
|
1514
|
+
}
|
|
1515
|
+
//#endregion
|
|
1516
|
+
//#region ../../node_modules/.bun/@cortexkit+claustrum-client@0.6.2/node_modules/@cortexkit/claustrum-client/dist/wire.d.ts
|
|
1517
|
+
type ClaustrumConnector = (options: {
|
|
1518
|
+
connectionFile: string;
|
|
1519
|
+
handshakeTimeoutMs?: number;
|
|
1520
|
+
}) => Promise<SubcClient>;
|
|
1521
|
+
type ClaustrumClientOptions = {
|
|
1522
|
+
connectionFile?: string;
|
|
1523
|
+
handshakeTimeoutMs?: number;
|
|
1524
|
+
projectRoot?: string;
|
|
1525
|
+
storagePath?: string;
|
|
1526
|
+
identity?: BindIdentity;
|
|
1527
|
+
connector?: ClaustrumConnector;
|
|
1528
|
+
logger?: (errorClass: string) => void;
|
|
1529
|
+
};
|
|
1530
|
+
/**
|
|
1531
|
+
* Credential material plus optional non-secret identity metadata. Missing wire fields remain
|
|
1532
|
+
* `undefined`; a present non-string identity value rejects the response as invalid.
|
|
1533
|
+
*
|
|
1534
|
+
* An absent identity field means the vault had nothing to assert — NOT that identity failed.
|
|
1535
|
+
* Consumers must not collapse absence into mismatch: assert on presence, refuse on a present
|
|
1536
|
+
* difference, and serve (log, if it matters) when the field is missing. Absence proves neither
|
|
1537
|
+
* the right identity nor the wrong one, so treating it as a failure converts a vault that could
|
|
1538
|
+
* not answer into a consumer that cannot serve. The vault records no per-read success (at most
|
|
1539
|
+
* the first scoped read per principal), and nothing at all when a consumer declines to serve, so
|
|
1540
|
+
* an outage caused that way is visible only to the consumer that caused it.
|
|
1541
|
+
*/
|
|
1542
|
+
type ServedCredential = {
|
|
1543
|
+
material: string;
|
|
1544
|
+
recordVersion: number;
|
|
1545
|
+
expiresAtMs: number | null;
|
|
1546
|
+
/**
|
|
1547
|
+
* Operator-chosen record label for verifying a caller-held binding. It is not a routing key:
|
|
1548
|
+
* account-scoped routing joins `accountId` with `recordVersion`.
|
|
1549
|
+
*/
|
|
1550
|
+
credentialId?: string;
|
|
1551
|
+
/** Non-secret Code Assist project identity, present only for antigravity credentials. */
|
|
1552
|
+
projectId?: string;
|
|
1553
|
+
/**
|
|
1554
|
+
* Provider account identity the served token executes under. Account-scoped routing joins this
|
|
1555
|
+
* value with `recordVersion`; it is neither the operator's credential label nor the bearer handle.
|
|
1556
|
+
*
|
|
1557
|
+
* BEST-EFFORT, NEVER GUARANTEED, including for JWT providers. The vault parses the claim live
|
|
1558
|
+
* from the served access token and falls back to stored login-time identity; both legs can be
|
|
1559
|
+
* empty, and the serve path yields nothing rather than fabricating an id. It is absent when the
|
|
1560
|
+
* provider has no known claim, the token does not carry one, or no identity was captured at
|
|
1561
|
+
* login. Do not gate serving on its presence.
|
|
1562
|
+
*/
|
|
1563
|
+
accountId?: string;
|
|
1564
|
+
/** Non-secret account display metadata captured at login. */
|
|
1565
|
+
email?: string;
|
|
1566
|
+
/** Non-secret organization or workspace display metadata captured at login. */
|
|
1567
|
+
orgName?: string;
|
|
1568
|
+
};
|
|
1569
|
+
/**
|
|
1570
|
+
* Non-secret health for one handle, read without minting anything.
|
|
1571
|
+
*
|
|
1572
|
+
* An unresolved handle (unknown or revoked) is an ordinary answer, not an error: it decodes
|
|
1573
|
+
* as `ready: false, lastErrorCode: 'not_found'` with `credentialId`, `recordVersion` and
|
|
1574
|
+
* `stalePending` all absent. The vault omits them on purpose so a probe learns nothing about
|
|
1575
|
+
* what exists and no placeholder value is asserted about a record it never saw.
|
|
1576
|
+
*/
|
|
1577
|
+
type CredentialStatus = {
|
|
1578
|
+
ready: boolean;
|
|
1579
|
+
lastErrorCode: string | null;
|
|
1580
|
+
leaseHeld: boolean;
|
|
1581
|
+
/**
|
|
1582
|
+
* Operator-chosen record label the handle resolved to, for verifying a binding the caller
|
|
1583
|
+
* already holds. Not a routing key. Absent when the handle did not resolve.
|
|
1584
|
+
*/
|
|
1585
|
+
credentialId?: string;
|
|
1586
|
+
/**
|
|
1587
|
+
* The record's change cursor, present only when the handle resolved to a record.
|
|
1588
|
+
*
|
|
1589
|
+
* Optional, and OMITTED from the object rather than defaulted, because there is no honest
|
|
1590
|
+
* default: 0 or -1 would compare as older than every real version, so a poller would read a
|
|
1591
|
+
* revoked handle as a change it had yet to see, forever. With the key absent, TypeScript
|
|
1592
|
+
* refuses arithmetic or ordering on it until the caller has handled `undefined`, and
|
|
1593
|
+
* `'recordVersion' in status` is false. Never replace absence with a number (`?? 0`).
|
|
1594
|
+
*/
|
|
1595
|
+
recordVersion?: number;
|
|
1596
|
+
stalePending?: boolean;
|
|
1597
|
+
};
|
|
1598
|
+
type ClaustrumReporterSource = 'direct' | 'relay_status_field' | 'relay_message_parse';
|
|
1599
|
+
declare class ClaustrumClient {
|
|
1600
|
+
#private;
|
|
1601
|
+
private constructor();
|
|
1602
|
+
static connect(options?: ClaustrumClientOptions): Promise<ClaustrumClient>;
|
|
1603
|
+
getCredential(handle: string, minTtlMs?: number): Promise<ServedCredential>;
|
|
1604
|
+
statusCredential(handle: string): Promise<CredentialStatus>;
|
|
1605
|
+
reportAuthFailure(input: {
|
|
1606
|
+
handle: string;
|
|
1607
|
+
providerStatus: number;
|
|
1608
|
+
recordVersion: number;
|
|
1609
|
+
reporterSource: ClaustrumReporterSource;
|
|
1610
|
+
}): Promise<void>;
|
|
1611
|
+
/**
|
|
1612
|
+
* Enumerate what this caller's grants cover.
|
|
1613
|
+
*
|
|
1614
|
+
* `params` is `{}` and must be PRESENT: the vault rejects an absent or null params
|
|
1615
|
+
* object, so a caller cannot ask a different question by omitting it.
|
|
1616
|
+
*/
|
|
1617
|
+
listScoped(enrollmentToken?: string): Promise<ScopedInventory>;
|
|
1618
|
+
/**
|
|
1619
|
+
* Fetch by credential id, authorized by a grant rather than a bearer handle.
|
|
1620
|
+
*
|
|
1621
|
+
* `minTtlMs` is a DEMAND, not a hint: if a real upstream exchange still cannot satisfy
|
|
1622
|
+
* it, the vault refuses with `ttl_unsatisfiable` (class `context_overflow`) rather than
|
|
1623
|
+
* serving a token that will die inside the caller's own margin. That class means
|
|
1624
|
+
* reduce-and-retry, never wait-and-retry.
|
|
1625
|
+
*/
|
|
1626
|
+
getScoped(input: {
|
|
1627
|
+
credentialId: string;
|
|
1628
|
+
enrollmentToken?: string;
|
|
1629
|
+
minTtlMs?: number;
|
|
1630
|
+
}): Promise<ServedCredential>;
|
|
1631
|
+
/**
|
|
1632
|
+
* Report a served credential dead, addressed by id rather than by handle.
|
|
1633
|
+
*
|
|
1634
|
+
* VERSION-FENCED: `recordVersion` must be the one this caller was SERVED. A report
|
|
1635
|
+
* against a since-refreshed version is accepted and does nothing, which is the point --
|
|
1636
|
+
* a stale report must not kill a fresh token. `accepted: true` is the receipt that the
|
|
1637
|
+
* report was taken, never evidence that it applied.
|
|
1638
|
+
*/
|
|
1639
|
+
reportAuthFailureScoped(input: {
|
|
1640
|
+
credentialId: string;
|
|
1641
|
+
enrollmentToken?: string;
|
|
1642
|
+
providerStatus: number;
|
|
1643
|
+
recordVersion: number;
|
|
1644
|
+
reporterSource: ClaustrumReporterSource;
|
|
1645
|
+
}): Promise<void>;
|
|
1646
|
+
/**
|
|
1647
|
+
* Propose an enrollment. The consumer mints `requestSecret` itself and sends only its
|
|
1648
|
+
* hash; the raw secret NEVER leaves the process, and it is what authorizes the poll.
|
|
1649
|
+
*
|
|
1650
|
+
* IDEMPOTENT ON (name, secret): re-proposing with the same secret returns the SAME
|
|
1651
|
+
* `requestId`. That exists because `requestId` is minted server-side, so a consumer
|
|
1652
|
+
* cannot persist it before proposing -- a crash in that window would otherwise leave it
|
|
1653
|
+
* holding a secret it cannot poll with and a name held until TTL. Persist the secret
|
|
1654
|
+
* BEFORE calling this, and a crash costs nothing.
|
|
1655
|
+
*
|
|
1656
|
+
* A different secret on the same name is a different caller and is refused.
|
|
1657
|
+
*/
|
|
1658
|
+
enrollPropose(input: {
|
|
1659
|
+
name: string;
|
|
1660
|
+
requestSecretHash: string;
|
|
1661
|
+
}): Promise<{
|
|
1662
|
+
requestId: string;
|
|
1663
|
+
}>;
|
|
1664
|
+
/**
|
|
1665
|
+
* Poll a proposal. Returns `pending` until an operator decides, then exactly once
|
|
1666
|
+
* returns the token.
|
|
1667
|
+
*
|
|
1668
|
+
* THE TOKEN IS RETURNED ONCE. Persist it before doing anything else with it; a lost
|
|
1669
|
+
* token needs a fresh ceremony, not a second poll.
|
|
1670
|
+
*/
|
|
1671
|
+
enrollPoll(input: {
|
|
1672
|
+
requestId: string;
|
|
1673
|
+
requestSecret: string;
|
|
1674
|
+
}): Promise<EnrollmentPollOutcome>;
|
|
1675
|
+
/**
|
|
1676
|
+
* Exchange a live token for its successor. The old token dies when the new one is issued.
|
|
1677
|
+
*
|
|
1678
|
+
* `expectedTokenGeneration` IS REQUIRED AND IS A FENCE, not bookkeeping: it must be the
|
|
1679
|
+
* generation this caller currently holds. Two rotations racing — a retry after an
|
|
1680
|
+
* uncertain reply, or two instances of the same consumer — would otherwise each mint a
|
|
1681
|
+
* successor and each invalidate the other's, leaving a consumer holding a token the
|
|
1682
|
+
* vault has already replaced. The vault refuses a rotation whose expectation does not
|
|
1683
|
+
* match, so the loser learns it lost instead of discovering it on a later spend.
|
|
1684
|
+
*/
|
|
1685
|
+
enrollRotate(input: {
|
|
1686
|
+
token: string;
|
|
1687
|
+
expectedTokenGeneration: number;
|
|
1688
|
+
}): Promise<{
|
|
1689
|
+
token: string;
|
|
1690
|
+
tokenGeneration: number;
|
|
1691
|
+
}>;
|
|
1692
|
+
close(): void;
|
|
1693
|
+
}
|
|
1694
|
+
/**
|
|
1695
|
+
* A row from the caller's own grant-covered inventory.
|
|
1696
|
+
*
|
|
1697
|
+
* Selection fields answer different questions. Pick by what you are about
|
|
1698
|
+
* to do with the token:
|
|
1699
|
+
*
|
|
1700
|
+
* - `providerIds` — operator-assigned catalog provider ids; match exactly, with no fallback.
|
|
1701
|
+
* - `authMethod` — the closed authentication method derived from the unsealed record,
|
|
1702
|
+
* not the id spelling. Absent on sign/open-only rows or when no method is defined.
|
|
1703
|
+
*
|
|
1704
|
+
* - `refreshAdapter` — whose PROTOCOL the credential speaks. Use it when the token
|
|
1705
|
+
* goes to a provider's own endpoints. Anything else is invalid there.
|
|
1706
|
+
* - `serves` — which model VENDORS are reachable through it. Use it when choosing
|
|
1707
|
+
* where a model can be served from, and the protocol is not yours to care about.
|
|
1708
|
+
*
|
|
1709
|
+
* Never infer these fields from the id spelling. A credential reaching Anthropic models
|
|
1710
|
+
* through OpenRouter still speaks OpenRouter's protocol, not Anthropic's.
|
|
1711
|
+
*/
|
|
1712
|
+
interface ScopedInventoryRow {
|
|
1713
|
+
readonly id: string;
|
|
1714
|
+
readonly categories: readonly string[];
|
|
1715
|
+
readonly credentialType: string;
|
|
1716
|
+
readonly serves: readonly string[];
|
|
1717
|
+
/**
|
|
1718
|
+
* Operator-assigned catalog ids; empty when none are set. Always present on this type.
|
|
1719
|
+
* A daemon older than the field omits it from the wire, and that decodes as empty,
|
|
1720
|
+
* which is also what an unmapped credential reports.
|
|
1721
|
+
*/
|
|
1722
|
+
readonly providerIds: readonly string[];
|
|
1723
|
+
readonly authMethod?: 'apikey' | 'chatgpt' | 'antigravity' | 'oauth';
|
|
1724
|
+
/**
|
|
1725
|
+
* Which provider protocol this credential speaks. Absent for static keys.
|
|
1726
|
+
*
|
|
1727
|
+
* SELECT ON THIS, NOT ON `serves`, WHEN THE TOKEN GOES TO A PROVIDER'S OWN ENDPOINTS.
|
|
1728
|
+
* Measured on a live vault: eight rows serve Anthropic models and only five are Claude
|
|
1729
|
+
* OAuth -- openrouter, antigravity and cursor reach Anthropic models through their own
|
|
1730
|
+
* APIs. The id spelling does not separate them either: two contain no "anthropic" at
|
|
1731
|
+
* all, and `credentialType === 'oauth'` catches antigravity and cursor too.
|
|
1732
|
+
*/
|
|
1733
|
+
readonly refreshAdapter?: string;
|
|
1734
|
+
readonly state: string;
|
|
1735
|
+
readonly recordVersion: number;
|
|
1736
|
+
readonly operations: readonly string[];
|
|
1737
|
+
/**
|
|
1738
|
+
* NOT SERVED TODAY. The field is absent from `ListScopedCredential`, so this is always
|
|
1739
|
+
* null; it is declared because a consumer's discovery high-water mark needs it and the
|
|
1740
|
+
* absence should be visible in the type rather than discovered at runtime.
|
|
1741
|
+
*/
|
|
1742
|
+
readonly createdAtMs: number | null;
|
|
1743
|
+
readonly accountId?: string;
|
|
1744
|
+
readonly email?: string;
|
|
1745
|
+
readonly orgName?: string;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* An inventory reply: the covered rows, plus the cursor that says whether they moved.
|
|
1749
|
+
*
|
|
1750
|
+
* `view` is a DIGEST OVER WHAT THIS CALLER CAN SEE — ids, categories, state, operations —
|
|
1751
|
+
* and deliberately NOT over `record_version`, so a routine token refresh does not move it.
|
|
1752
|
+
* Compare it against the previous call's to decide whether to reconcile at all; it is an
|
|
1753
|
+
* opaque string and nothing but equality is defined on it.
|
|
1754
|
+
*/
|
|
1755
|
+
interface ScopedInventory {
|
|
1756
|
+
readonly rows: readonly ScopedInventoryRow[];
|
|
1757
|
+
readonly view: string;
|
|
1758
|
+
}
|
|
1759
|
+
/** What a poll found. `pending` is not an error: the operator has not decided yet. */
|
|
1760
|
+
type EnrollmentPollOutcome = {
|
|
1761
|
+
readonly status: 'pending';
|
|
1762
|
+
} | {
|
|
1763
|
+
readonly status: 'approved';
|
|
1764
|
+
readonly name: string;
|
|
1765
|
+
readonly token: string;
|
|
1766
|
+
readonly tokenGeneration: number;
|
|
1767
|
+
} | {
|
|
1768
|
+
readonly status: 'denied';
|
|
1769
|
+
};
|
|
1770
|
+
//#endregion
|
|
1771
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/custody.d.ts
|
|
1772
|
+
type ClaustrumScopedClient = Pick<ClaustrumClient, 'listScoped' | 'getScoped' | 'reportAuthFailureScoped' | 'close'>;
|
|
1773
|
+
/** The two credential types a plugin's family can hold; routing differs by type. */
|
|
1774
|
+
type VaultCredentialType = 'oauth' | 'api_key';
|
|
1775
|
+
/**
|
|
1776
|
+
* Why a listed vault record could not be used. A closed set of fixed codes, so
|
|
1777
|
+
* a log line or a roster file that carries one never echoes vault data.
|
|
1778
|
+
*/
|
|
1779
|
+
type SkippedVaultReason = 'empty credential id' | 'duplicate credential id' | 'blank account identity' | 'empty state';
|
|
1780
|
+
/**
|
|
1781
|
+
* A vault record this consumer could not use. `credentialId` is absent when
|
|
1782
|
+
* the record's id itself was unusable, so nothing can say which account the
|
|
1783
|
+
* record was.
|
|
1784
|
+
*/
|
|
1785
|
+
interface SkippedVaultRecord {
|
|
1786
|
+
readonly credentialId?: string;
|
|
1787
|
+
readonly reason: SkippedVaultReason;
|
|
1788
|
+
}
|
|
1789
|
+
/**
|
|
1790
|
+
* Where a receipt's `accountIdentity` came from: the vault asserted it in the
|
|
1791
|
+
* served reply, the plugin's `parseIdentity` read it from the served token, or
|
|
1792
|
+
* neither did and it is only the roster's expectation (`none`: no identity at
|
|
1793
|
+
* all).
|
|
1794
|
+
*/
|
|
1795
|
+
type AccountIdentitySource = 'asserted' | 'parsed' | 'expected' | 'none';
|
|
1796
|
+
/**
|
|
1797
|
+
* A receipt: what the vault served for one physical send. Each attempt gets
|
|
1798
|
+
* its own. It records the exact record version served, because a 401 for
|
|
1799
|
+
* this send is reported to the vault against that version.
|
|
1800
|
+
*/
|
|
1801
|
+
interface ClaustrumScopedAttempt {
|
|
1802
|
+
readonly credentialId: string;
|
|
1803
|
+
readonly credentialType: VaultCredentialType;
|
|
1804
|
+
/**
|
|
1805
|
+
* The account this receipt is bound to: the vault's assertion, else the
|
|
1806
|
+
* plugin's parse of the token, else the roster's expectation. Check
|
|
1807
|
+
* `accountIdentitySource` before treating it as proof.
|
|
1808
|
+
*/
|
|
1809
|
+
readonly accountIdentity?: string;
|
|
1810
|
+
readonly accountIdentitySource: AccountIdentitySource;
|
|
1811
|
+
/** The account the roster row named when this receipt was requested. */
|
|
1812
|
+
readonly expectedAccountIdentity?: string;
|
|
1813
|
+
/** The credential id the vault itself put in the served reply, if any. */
|
|
1814
|
+
readonly assertedCredentialId?: string;
|
|
1815
|
+
/**
|
|
1816
|
+
* The account the vault itself put in the served reply, if any. Never filled
|
|
1817
|
+
* in from the roster or from a token parse.
|
|
1818
|
+
*/
|
|
1819
|
+
readonly assertedAccountIdentity?: string;
|
|
1820
|
+
/**
|
|
1821
|
+
* The non-secret Google Cloud project id the vault served in get_scoped for
|
|
1822
|
+
* this attempt, if any. Never filled in from list_scoped, the roster or a
|
|
1823
|
+
* token parse. A project change in the vault takes effect on the next send.
|
|
1824
|
+
*/
|
|
1825
|
+
readonly projectId?: string;
|
|
1826
|
+
/**
|
|
1827
|
+
* Kept in memory only and hidden from JSON.stringify and object spreads, so
|
|
1828
|
+
* logging a receipt never leaks it. Authorize again for every dispatch and retry.
|
|
1829
|
+
*/
|
|
1830
|
+
readonly accessToken: string;
|
|
1831
|
+
readonly recordVersion: number;
|
|
1832
|
+
readonly expiresAtMs: number | null;
|
|
1833
|
+
}
|
|
1834
|
+
//#endregion
|
|
1835
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/quota/map.d.ts
|
|
1836
|
+
interface QuotaReadingEntry {
|
|
1837
|
+
scope: string;
|
|
1838
|
+
label: string;
|
|
1839
|
+
kind: 'reading';
|
|
1840
|
+
checkedAt: number;
|
|
1841
|
+
usedPercent: number;
|
|
1842
|
+
/** ISO timestamp at which the window resets, as the provider reported it. */
|
|
1843
|
+
resetsAt?: string;
|
|
1844
|
+
/** Window length in minutes, when the provider reported one. */
|
|
1845
|
+
windowMinutes?: number;
|
|
1846
|
+
}
|
|
1847
|
+
interface QuotaRetiredEntry {
|
|
1848
|
+
scope: string;
|
|
1849
|
+
label: string;
|
|
1850
|
+
kind: 'retired';
|
|
1851
|
+
retiredAt: number;
|
|
1852
|
+
}
|
|
1853
|
+
interface QuotaAbsentEntry {
|
|
1854
|
+
scope: string;
|
|
1855
|
+
label: string;
|
|
1856
|
+
kind: 'absent';
|
|
1857
|
+
checkedAt: number;
|
|
1858
|
+
}
|
|
1859
|
+
type QuotaEntry = QuotaReadingEntry | QuotaRetiredEntry | QuotaAbsentEntry;
|
|
1860
|
+
interface CreditBudgetReading {
|
|
1861
|
+
kind: 'reading';
|
|
1862
|
+
checkedAt: number;
|
|
1863
|
+
/** The provider's own verdict that the budget is spent. */
|
|
1864
|
+
reached: boolean;
|
|
1865
|
+
remainingPercent?: number;
|
|
1866
|
+
usedPercent?: number;
|
|
1867
|
+
resetsAt?: string;
|
|
1868
|
+
limit?: number;
|
|
1869
|
+
used?: number;
|
|
1870
|
+
remaining?: number;
|
|
1871
|
+
unit?: string;
|
|
1872
|
+
}
|
|
1873
|
+
interface CreditBudgetCleared {
|
|
1874
|
+
kind: 'cleared';
|
|
1875
|
+
checkedAt: number;
|
|
1876
|
+
}
|
|
1877
|
+
type CreditBudgetEntry = CreditBudgetReading | CreditBudgetCleared;
|
|
1878
|
+
interface QuotaMap {
|
|
1879
|
+
limits: QuotaEntry[];
|
|
1880
|
+
/** Absent means no observation has reported on the budget yet. */
|
|
1881
|
+
budget?: CreditBudgetEntry;
|
|
1882
|
+
}
|
|
1883
|
+
//#endregion
|
|
1884
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/interlock.d.ts
|
|
1885
|
+
/**
|
|
1886
|
+
* The declined-account interlock: the user's "do not use this vault account",
|
|
1887
|
+
* kept on the consumer side because the vault has no notion of it.
|
|
1888
|
+
*
|
|
1889
|
+
* A decline follows the provider account, not the vault record: an entry made
|
|
1890
|
+
* while the account was known matches any credential id or alias that logs
|
|
1891
|
+
* into that same account, so relabelling, adding an alias or removing and
|
|
1892
|
+
* re-adding the account never lifts it. A credential id that now logs into a
|
|
1893
|
+
* different known account does not match, because that account has its own
|
|
1894
|
+
* policy. While either side's account is unknown the entry falls back to the
|
|
1895
|
+
* credential id, so an adapter that makes no identity claim cannot slip past
|
|
1896
|
+
* it. Never keyed on the record version, so a token refresh cannot lift it.
|
|
1897
|
+
*/
|
|
1898
|
+
interface DeclinedAccount {
|
|
1899
|
+
readonly credentialId: string;
|
|
1900
|
+
readonly accountIdentity?: string;
|
|
1901
|
+
}
|
|
1902
|
+
//#endregion
|
|
1903
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/roster.d.ts
|
|
1904
|
+
/**
|
|
1905
|
+
* One vault account as the pool sees it. It carries no bearer material: the
|
|
1906
|
+
* access token is fetched from the vault for every send. Several vault
|
|
1907
|
+
* records logged into the same provider account collapse into one row, so
|
|
1908
|
+
* duplicate logins never count as extra quota.
|
|
1909
|
+
*/
|
|
1910
|
+
interface VaultRosterRow {
|
|
1911
|
+
routeId: string;
|
|
1912
|
+
credentialId: string;
|
|
1913
|
+
credentialType: VaultCredentialType;
|
|
1914
|
+
accountIdentity?: string;
|
|
1915
|
+
/** Other credential ids logged into the same provider account. */
|
|
1916
|
+
aliases?: string[];
|
|
1917
|
+
state: string;
|
|
1918
|
+
label: string;
|
|
1919
|
+
email?: string;
|
|
1920
|
+
orgName?: string;
|
|
1921
|
+
enabled: boolean;
|
|
1922
|
+
addedAt: number;
|
|
1923
|
+
quota?: QuotaMap;
|
|
1924
|
+
/**
|
|
1925
|
+
* The vault listed this record in a form this consumer could not use, so the
|
|
1926
|
+
* row is the last good projection kept as it was rather than dropped.
|
|
1927
|
+
*/
|
|
1928
|
+
stale?: true;
|
|
1929
|
+
/**
|
|
1930
|
+
* The vault's latest list named no account for `credentialId`, so
|
|
1931
|
+
* `accountIdentity` is the last account that credential was known to log
|
|
1932
|
+
* into, kept until the vault names one again. It proves neither that the
|
|
1933
|
+
* credential still logs into that account nor that it changed accounts.
|
|
1934
|
+
*/
|
|
1935
|
+
unclaimed?: true;
|
|
1936
|
+
}
|
|
1937
|
+
interface VaultRosterFile {
|
|
1938
|
+
version: 1;
|
|
1939
|
+
view?: string;
|
|
1940
|
+
/**
|
|
1941
|
+
* False when the vault's reply carried records this consumer could not use.
|
|
1942
|
+
* An incomplete reply never removes an account it may still hold: every
|
|
1943
|
+
* previous member it does not account for is kept.
|
|
1944
|
+
*/
|
|
1945
|
+
complete: boolean;
|
|
1946
|
+
/** The unusable records of an incomplete reply: a safe id and a fixed reason. */
|
|
1947
|
+
rejected?: SkippedVaultRecord[];
|
|
1948
|
+
rows: VaultRosterRow[];
|
|
1949
|
+
declined: DeclinedAccount[];
|
|
1950
|
+
}
|
|
1951
|
+
/**
|
|
1952
|
+
* The receipt fields a quota or profile observation must carry to say which
|
|
1953
|
+
* send (credential and account) it came from. Pass the
|
|
1954
|
+
* `ClaustrumScopedAttempt` that send was authorized with.
|
|
1955
|
+
*/
|
|
1956
|
+
type QuotaReceipt = Pick<ClaustrumScopedAttempt, 'credentialId' | 'accountIdentity' | 'accountIdentitySource' | 'expectedAccountIdentity'>;
|
|
1957
|
+
//#endregion
|
|
1958
|
+
//#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.d.ts
|
|
1959
|
+
interface ClaustrumEnrollmentClient {
|
|
1960
|
+
enrollPropose(input: {
|
|
1961
|
+
name: string;
|
|
1962
|
+
requestSecretHash: string;
|
|
1963
|
+
}): Promise<{
|
|
1964
|
+
requestId: string;
|
|
1965
|
+
}>;
|
|
1966
|
+
enrollPoll(input: {
|
|
1967
|
+
requestId: string;
|
|
1968
|
+
requestSecret: string;
|
|
1969
|
+
}): Promise<EnrollmentPollOutcome>;
|
|
1970
|
+
}
|
|
1971
|
+
interface ClaustrumEnrollmentConnection extends ClaustrumEnrollmentClient {
|
|
1972
|
+
close(): void;
|
|
1973
|
+
}
|
|
1974
|
+
type ClaustrumEnrollmentStatus = {
|
|
1975
|
+
state: 'idle';
|
|
1976
|
+
} | {
|
|
1977
|
+
state: 'pending';
|
|
1978
|
+
proposedName: string;
|
|
1979
|
+
requestId?: string;
|
|
1980
|
+
retryCode?: string;
|
|
1981
|
+
} | {
|
|
1982
|
+
state: 'approved';
|
|
1983
|
+
proposedName: string;
|
|
1984
|
+
approvedName?: string;
|
|
1985
|
+
tokenGeneration: number;
|
|
1986
|
+
} | {
|
|
1987
|
+
state: 'denied';
|
|
1988
|
+
proposedName: string;
|
|
1989
|
+
} | {
|
|
1990
|
+
state: 'blocked';
|
|
1991
|
+
proposedName: string;
|
|
1992
|
+
code: string;
|
|
1993
|
+
} | {
|
|
1994
|
+
state: 'unavailable';
|
|
1995
|
+
proposedName: string;
|
|
1996
|
+
code: string;
|
|
1997
|
+
} | {
|
|
1998
|
+
state: 'busy';
|
|
1999
|
+
};
|
|
2000
|
+
interface ClaustrumEnrollmentPaths {
|
|
2001
|
+
statePath: string;
|
|
2002
|
+
tokenPath: string;
|
|
2003
|
+
}
|
|
2004
|
+
//#endregion
|
|
2005
|
+
//#region ../core/dist/vault.d.ts
|
|
2006
|
+
type VaultHost = 'opencode' | 'pi';
|
|
2007
|
+
interface VaultPaths extends ClaustrumEnrollmentPaths {
|
|
2008
|
+
/** The roster: the vault accounts, their quota and the declined ones. Holds no token. */
|
|
2009
|
+
rosterPath: string;
|
|
2010
|
+
}
|
|
2011
|
+
/** One vault account as routing sees it. */
|
|
2012
|
+
interface VaultRoute {
|
|
2013
|
+
id: string;
|
|
2014
|
+
kind: 'oauth' | 'api-key';
|
|
2015
|
+
/** The ChatGPT account it signs in as, when the vault knows it. */
|
|
2016
|
+
identity?: string;
|
|
2017
|
+
quota?: QuotaMap;
|
|
2018
|
+
}
|
|
2019
|
+
interface VaultStatus {
|
|
2020
|
+
host: VaultHost;
|
|
2021
|
+
/** The name this host enrolls as. */
|
|
2022
|
+
name: string;
|
|
2023
|
+
enrollment: ClaustrumEnrollmentStatus;
|
|
2024
|
+
/** Every vault account this host can see, declined and cold ones included. */
|
|
2025
|
+
accounts: readonly VaultRosterRow[];
|
|
2026
|
+
lastError?: string;
|
|
2027
|
+
}
|
|
2028
|
+
interface VaultWaitOptions {
|
|
2029
|
+
/** Called with each status while the request waits for approval. */
|
|
2030
|
+
onPending?: (status: ClaustrumEnrollmentStatus) => void;
|
|
2031
|
+
pollIntervalMs?: number;
|
|
2032
|
+
timeoutMs?: number;
|
|
2033
|
+
sleep?: (ms: number) => Promise<void>;
|
|
2034
|
+
}
|
|
2035
|
+
interface OpenAiVaultOptions {
|
|
2036
|
+
host: VaultHost;
|
|
2037
|
+
/** This host's vault directory; see `vaultStateDir`. */
|
|
2038
|
+
stateDir: string;
|
|
2039
|
+
/** The vault's connection file; `CLAUSTRUM_SUBC_CONNECTION` or the default by default. */
|
|
2040
|
+
connectionFile?: () => string;
|
|
2041
|
+
/** The project this host runs in, part of the identity the vault sees. */
|
|
2042
|
+
projectRoot?: string;
|
|
2043
|
+
/** Replaces the request-path connection (tests). */
|
|
2044
|
+
connectScoped?: () => Promise<ClaustrumScopedClient>;
|
|
2045
|
+
/** Replaces the setup-only enrollment connection (tests). */
|
|
2046
|
+
connectEnrollment?: () => Promise<ClaustrumEnrollmentConnection>;
|
|
2047
|
+
/** Ids of the local pool rows; no vault route takes one. */
|
|
2048
|
+
reservedRouteIds?: () => Iterable<string>;
|
|
2049
|
+
/** How often the roster is re-read from the vault; 0 stops the poll. */
|
|
2050
|
+
pollIntervalMs?: number;
|
|
2051
|
+
fetchImpl?: () => typeof fetch;
|
|
2052
|
+
now?: () => number;
|
|
2053
|
+
}
|
|
2054
|
+
/** One host's view of its OpenAI accounts in the vault. */
|
|
2055
|
+
declare class OpenAiVault {
|
|
2056
|
+
#private;
|
|
2057
|
+
readonly host: VaultHost;
|
|
2058
|
+
readonly name: string;
|
|
2059
|
+
readonly paths: VaultPaths;
|
|
2060
|
+
constructor(options: OpenAiVaultOptions);
|
|
2061
|
+
/** Read enrollment files before a request, menu action or background pass, using common-auth's mode rules. */
|
|
2062
|
+
authority(): Promise<'vault' | 'local' | 'unreadable'>;
|
|
2063
|
+
/**
|
|
2064
|
+
* Callbacks that cannot await use the last authority value only while the
|
|
2065
|
+
* enrollment files are unchanged. Before the first read, or after a change,
|
|
2066
|
+
* local token refreshes, quota polls and account writes are blocked.
|
|
2067
|
+
* Requests and menus await authority() instead of trusting the cached value.
|
|
2068
|
+
*/
|
|
2069
|
+
enrolled(): boolean;
|
|
2070
|
+
/**
|
|
2071
|
+
* Polls enrollment files and the vault's accounts. With local authority the
|
|
2072
|
+
* consumer sends no vault request. A new enrollment completed by another
|
|
2073
|
+
* process is detected on the next poll.
|
|
2074
|
+
*/
|
|
2075
|
+
start(): void;
|
|
2076
|
+
/**
|
|
2077
|
+
* Resolves once this instance's first roster discovery has ended, whether
|
|
2078
|
+
* it read the vault or failed, or once the instance is closed. Never
|
|
2079
|
+
* rejects. A vault-mode request waits for it, bounded by
|
|
2080
|
+
* `VAULT_REQUEST_ROSTER_WAIT_MS`.
|
|
2081
|
+
*/
|
|
2082
|
+
firstRoster(): Promise<void>;
|
|
2083
|
+
/**
|
|
2084
|
+
* Re-reads the accounts from the vault now. Never rejects. It resolves only
|
|
2085
|
+
* after a discovery that began after this call: one already in flight (the
|
|
2086
|
+
* poll, or a refresh another caller started) may have read the enrollment
|
|
2087
|
+
* and the vault before what this caller just changed, so it is waited out
|
|
2088
|
+
* and a new one runs. Callers that arrive while that new one runs share it.
|
|
2089
|
+
*/
|
|
2090
|
+
refresh(): Promise<VaultRosterFile | undefined>;
|
|
2091
|
+
snapshot(): VaultRosterFile | undefined;
|
|
2092
|
+
/** Whether the vault serves this host any account (whatever its state). */
|
|
2093
|
+
serves(): boolean;
|
|
2094
|
+
/**
|
|
2095
|
+
* The ChatGPT accounts the vault holds for this host, declined and cold
|
|
2096
|
+
* ones included. Empty unless this host is enrolled; while it is, no local
|
|
2097
|
+
* row is used at all (vault mode), so this only names which vault account
|
|
2098
|
+
* a set-aside local row belongs to.
|
|
2099
|
+
*/
|
|
2100
|
+
identities(): ReadonlySet<string>;
|
|
2101
|
+
/** The vault accounts that may route now: enabled and active. */
|
|
2102
|
+
routes(): VaultRoute[];
|
|
2103
|
+
/** Whether a route id names a vault account. */
|
|
2104
|
+
owns(routeId: string): boolean;
|
|
2105
|
+
/**
|
|
2106
|
+
* Sends one request on a vault account. `dispatch` sends with the token
|
|
2107
|
+
* the vault serves for this attempt and may be called twice (a 401 is
|
|
2108
|
+
* retried once when the vault has a newer version of the same login), so
|
|
2109
|
+
* it must be able to rebuild its body. Returns undefined when the vault
|
|
2110
|
+
* refused before anything was sent (not enrolled, declined, cold,
|
|
2111
|
+
* unreachable): the caller treats the account like a row with no token.
|
|
2112
|
+
* An error from `dispatch` itself (a transport failure, an abort) is
|
|
2113
|
+
* rethrown.
|
|
2114
|
+
*/
|
|
2115
|
+
send(routeId: string, dispatch: (token: string, attempt: ClaustrumScopedAttempt) => Promise<Response>, options: {
|
|
2116
|
+
site: string;
|
|
2117
|
+
signal?: AbortSignal;
|
|
2118
|
+
}): Promise<Response | undefined>;
|
|
2119
|
+
/**
|
|
2120
|
+
* Authorizes one send on a vault account for a caller that sends the
|
|
2121
|
+
* request itself (OpenCode 2's host does): the receipt holds the token to
|
|
2122
|
+
* send with and the record version a 401 on that send is reported
|
|
2123
|
+
* against (`reportFailure`). Undefined when the vault refused (not
|
|
2124
|
+
* enrolled, declined, cold, unreachable): the caller treats the account
|
|
2125
|
+
* like a row with no token. Authorize again for every send; a receipt is
|
|
2126
|
+
* never reused.
|
|
2127
|
+
*/
|
|
2128
|
+
authorize(routeId: string, options?: {
|
|
2129
|
+
signal?: AbortSignal;
|
|
2130
|
+
}): Promise<ClaustrumScopedAttempt | undefined>;
|
|
2131
|
+
/**
|
|
2132
|
+
* Reports the provider's answer to a send made with `authorize`'s receipt.
|
|
2133
|
+
* Only a 401 is reported, against the receipt's record version; anything
|
|
2134
|
+
* else is ignored. The roster is re-read afterwards so an account the
|
|
2135
|
+
* vault now marks as needing a new login stops routing. Never rejects.
|
|
2136
|
+
*/
|
|
2137
|
+
reportFailure(attempt: ClaustrumScopedAttempt, status: number): Promise<void>;
|
|
2138
|
+
/**
|
|
2139
|
+
* Records a quota snapshot (response headers, a WebSocket rate-limit frame,
|
|
2140
|
+
* a usage poll) for a vault account. `receipt` is what the send that
|
|
2141
|
+
* produced the reading was served with (its credential id and the account
|
|
2142
|
+
* it was bound to, and how that account was known); the reading is kept
|
|
2143
|
+
* only while the route still holds that credential and account, so a
|
|
2144
|
+
* reading taken before the vault replaced the account is dropped. Runs in
|
|
2145
|
+
* the background; a failure is logged.
|
|
2146
|
+
*/
|
|
2147
|
+
recordSnapshot(routeId: string, snapshot: unknown, complete: boolean, receipt: QuotaReceipt): Promise<void>;
|
|
2148
|
+
/** Takes one quota reading for a vault account through the usage endpoint. */
|
|
2149
|
+
pollQuota(routeId: string): Promise<{
|
|
2150
|
+
ok: boolean;
|
|
2151
|
+
error?: string;
|
|
2152
|
+
}>;
|
|
2153
|
+
/**
|
|
2154
|
+
* Asks for a quota reading of a vault account that admission refused
|
|
2155
|
+
* because it has no reading yet. At most one reading per account is in
|
|
2156
|
+
* flight.
|
|
2157
|
+
*/
|
|
2158
|
+
requestReading(routeId: string): void;
|
|
2159
|
+
/** Readings for the routable vault accounts whose last one is older than `maxAgeMs`. */
|
|
2160
|
+
pollStale(maxAgeMs: number): Promise<Array<{
|
|
2161
|
+
id: string;
|
|
2162
|
+
ok: boolean;
|
|
2163
|
+
error?: string;
|
|
2164
|
+
}>>;
|
|
2165
|
+
/** Declines a vault account: it stays listed and never routes until accepted. */
|
|
2166
|
+
decline(routeId: string): Promise<void>;
|
|
2167
|
+
accept(routeId: string): Promise<void>;
|
|
2168
|
+
status(): Promise<VaultStatus>;
|
|
2169
|
+
/**
|
|
2170
|
+
* One step of enrollment: proposes this host to the vault, or polls the
|
|
2171
|
+
* proposal already on disk. A denied or blocked request is cleared first,
|
|
2172
|
+
* so Connect always starts a usable request.
|
|
2173
|
+
*/
|
|
2174
|
+
connectStep(): Promise<ClaustrumEnrollmentStatus>;
|
|
2175
|
+
/**
|
|
2176
|
+
* Polls the enrollment until the operator approves or denies it, or until
|
|
2177
|
+
* `timeoutMs`. One wait runs at a time; a second caller shares it.
|
|
2178
|
+
*/
|
|
2179
|
+
waitForApproval(options?: VaultWaitOptions): Promise<ClaustrumEnrollmentStatus>;
|
|
2180
|
+
/**
|
|
2181
|
+
* Forgets this host's enrollment: its token and ceremony state are
|
|
2182
|
+
* deleted, and the vault accounts stop routing at once. The roster (the
|
|
2183
|
+
* declined accounts and their quota) is kept for a later Connect. The
|
|
2184
|
+
* enrollment itself stays approved in the vault until the operator revokes
|
|
2185
|
+
* it there.
|
|
2186
|
+
*/
|
|
2187
|
+
disconnect(): Promise<void>;
|
|
2188
|
+
/**
|
|
2189
|
+
* Refuses a real login in the host's own slot while the vault serves this
|
|
2190
|
+
* host's accounts: serving either one would silently pick one of two
|
|
2191
|
+
* accounts the user may not mean. The pool placeholder and the old
|
|
2192
|
+
* tombstone are not logins and must be screened out by the caller.
|
|
2193
|
+
*/
|
|
2194
|
+
assertHostSlot(auth: unknown): void;
|
|
2195
|
+
close(): void;
|
|
2196
|
+
}
|
|
2197
|
+
//#endregion
|
|
2198
|
+
//#region src/core/version-fence.d.ts
|
|
2199
|
+
/** One live process that keeps the fence shut. */
|
|
2200
|
+
interface VersionFenceBlocker {
|
|
2201
|
+
/** `'unknown'` when a whole directory could not be read. */
|
|
2202
|
+
pid: number | 'unknown';
|
|
2203
|
+
/** The version its heartbeat names, or `'unknown'`. */
|
|
2204
|
+
version: string;
|
|
2205
|
+
/** The file or directory that showed it. */
|
|
2206
|
+
detail: string;
|
|
2207
|
+
}
|
|
2208
|
+
type VersionFenceResult = {
|
|
2209
|
+
open: true;
|
|
2210
|
+
} | {
|
|
2211
|
+
open: false;
|
|
2212
|
+
blockers: VersionFenceBlocker[];
|
|
2213
|
+
};
|
|
2214
|
+
//#endregion
|
|
2215
|
+
//#region src/core/pool-migration.d.ts
|
|
2216
|
+
/** The host login slot, shaped like the plugin's `client.auth`. */
|
|
2217
|
+
interface HostSlotAdapter {
|
|
2218
|
+
/** The shared auth.json path, independent of a plugin's config root. */
|
|
2219
|
+
path?: string;
|
|
2220
|
+
migrationDisabledReason?: () => string | undefined;
|
|
2221
|
+
get(input: {
|
|
2222
|
+
path: {
|
|
2223
|
+
id: string;
|
|
2224
|
+
};
|
|
2225
|
+
}): Promise<unknown>;
|
|
2226
|
+
set(input: {
|
|
2227
|
+
path: {
|
|
2228
|
+
id: string;
|
|
2229
|
+
};
|
|
2230
|
+
body: unknown;
|
|
2231
|
+
}): Promise<unknown>;
|
|
2232
|
+
all(): Promise<Record<string, unknown>>;
|
|
2233
|
+
}
|
|
2234
|
+
interface PoolMigrationLogger {
|
|
2235
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
2236
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
2237
|
+
}
|
|
2238
|
+
/** Named points between this module's own writes; awaited, for crash tests. */
|
|
2239
|
+
type PoolMigrationStep = 'after-pool-key-write' | 'after-record-write' | 'after-row-write' | 'after-verify' | 'after-carry-over' | 'before-placeholder-write' | 'after-placeholder-write' | 'after-record-clear' | 'after-marker-write';
|
|
2240
|
+
/** Timing of the legacy file locks and of waits on them. */
|
|
2241
|
+
interface LegacyLockOptions {
|
|
2242
|
+
mainRefreshTtlMs: number;
|
|
2243
|
+
fallbackTtlMs: number;
|
|
2244
|
+
/** Lease of the `save` lock pair around this module's own config writes. */
|
|
2245
|
+
saveTtlMs: number;
|
|
2246
|
+
renew: boolean;
|
|
2247
|
+
renewIntervalMs?: number;
|
|
2248
|
+
/** How long to wait for a held legacy lock before giving up (real clock). */
|
|
2249
|
+
timeoutMs: number;
|
|
2250
|
+
retryMs: number;
|
|
2251
|
+
}
|
|
2252
|
+
interface PoolMigrationDeps {
|
|
2253
|
+
paths: AccountPaths;
|
|
2254
|
+
slot: HostSlotAdapter;
|
|
2255
|
+
now?: () => number;
|
|
2256
|
+
sleep?: (ms: number) => Promise<void>;
|
|
2257
|
+
/** Id for a new row whose login carries no usable wire identity. */
|
|
2258
|
+
newId?: () => string;
|
|
2259
|
+
log?: PoolMigrationLogger;
|
|
2260
|
+
legacyLocks?: Partial<LegacyLockOptions>;
|
|
2261
|
+
/** Bound and poll interval for waiting out an active legacy main lease. */
|
|
2262
|
+
leaseWait?: {
|
|
2263
|
+
timeoutMs: number;
|
|
2264
|
+
pollMs: number;
|
|
2265
|
+
};
|
|
2266
|
+
/** Pass-through options for the pool store this module opens. */
|
|
2267
|
+
store?: Partial<Pick<OpenPoolStoreOptions, 'lockOptions' | 'rowLockOptions' | 'providerLock' | 'storeLocks' | 'onStep' | 'onLockEvent'>>;
|
|
2268
|
+
onStep?: (step: PoolMigrationStep) => void | Promise<void>;
|
|
2269
|
+
/**
|
|
2270
|
+
* Whether the Claustrum vault serves this host's accounts. The built-in
|
|
2271
|
+
* adopter does not change course on it: a pool row for an account the
|
|
2272
|
+
* vault also holds is skipped by the account source (`pool-account-source.ts`),
|
|
2273
|
+
* which neither routes nor refreshes it locally, so adoption can safely
|
|
2274
|
+
* move a slot login into the pool and put the placeholder back. The
|
|
2275
|
+
* placeholder has to be back: OpenCode 1 installs the plugin's fetch only
|
|
2276
|
+
* when its `openai` slot holds an OAuth value.
|
|
2277
|
+
*/
|
|
2278
|
+
vaultServes?: () => boolean;
|
|
2279
|
+
}
|
|
2280
|
+
type SlotNothingKind = 'api' | 'placeholder' | 'empty' | 'tombstone' | 'slot-absent' | 'declined';
|
|
2281
|
+
type PoolTransferOutcome = {
|
|
2282
|
+
status: 'slot-read-only';
|
|
2283
|
+
reason: string;
|
|
2284
|
+
} |
|
|
2285
|
+
/**
|
|
2286
|
+
* The adoption left the slot alone because the vault serves this host's
|
|
2287
|
+
* accounts. The built-in adopter (`adoptHostSlotLogin`) no longer returns
|
|
2288
|
+
* this; it can still come from a custom adopter passed to the background
|
|
2289
|
+
* runner (`adopt` in `pool-lifecycle.ts`).
|
|
2290
|
+
*/
|
|
2291
|
+
{
|
|
2292
|
+
status: 'vault-owns-accounts';
|
|
2293
|
+
} |
|
|
2294
|
+
/**
|
|
2295
|
+
* An openai-auth process older than this one is running (see
|
|
2296
|
+
* `version-fence.ts`); nothing was written. The migration runs once they
|
|
2297
|
+
* are gone.
|
|
2298
|
+
*/
|
|
2299
|
+
{
|
|
2300
|
+
status: 'deferred';
|
|
2301
|
+
reason: 'older-version-running';
|
|
2302
|
+
blockers: VersionFenceBlocker[];
|
|
2303
|
+
} |
|
|
2304
|
+
/** Migration already recorded as done; nothing was imported. */
|
|
2305
|
+
{
|
|
2306
|
+
status: 'already-migrated';
|
|
2307
|
+
} |
|
|
2308
|
+
/**
|
|
2309
|
+
* The slot holds the placeholder, but it was not this store that moved the
|
|
2310
|
+
* login out of the slot. The transfer record below is the pending-transfer
|
|
2311
|
+
* record in this store's config, written before a transfer touches a row.
|
|
2312
|
+
* - `placeholder-without-main`: another store sharing this login slot
|
|
2313
|
+
* moved the login, so the login is that store's. Either this store has
|
|
2314
|
+
* no `main` row and no transfer record, and nothing is written; or this
|
|
2315
|
+
* store's own transfer was under way and found the placeholder tagged
|
|
2316
|
+
* with another config root, and only the copy that transfer had put into
|
|
2317
|
+
* a row is removed (the other store holds the login now) and the record
|
|
2318
|
+
* cleared.
|
|
2319
|
+
* - `placeholder-origin-unknown`: this store has a transfer record, but
|
|
2320
|
+
* the placeholder is untagged (it has no `accountId` naming the config
|
|
2321
|
+
* root that wrote it; builds before this one wrote it that way). The
|
|
2322
|
+
* row copy may be this store's only copy of the credential, so it is not
|
|
2323
|
+
* deleted; another store may own the login, so the row is disabled
|
|
2324
|
+
* rather than routed or refreshed. The record is cleared so that a later
|
|
2325
|
+
* background run does not find it and disable the row again after
|
|
2326
|
+
* someone has re-enabled it.
|
|
2327
|
+
*/
|
|
2328
|
+
{
|
|
2329
|
+
status: 'refused';
|
|
2330
|
+
reason: 'placeholder-without-main' | 'placeholder-origin-unknown';
|
|
2331
|
+
} |
|
|
2332
|
+
/** Adoption asked for before the migration ran. */
|
|
2333
|
+
{
|
|
2334
|
+
status: 'not-migrated';
|
|
2335
|
+
} | {
|
|
2336
|
+
status: 'nothing-to-import';
|
|
2337
|
+
slot: SlotNothingKind;
|
|
2338
|
+
} | {
|
|
2339
|
+
status: 'completed';
|
|
2340
|
+
rowId: string;
|
|
2341
|
+
operation: 'add' | 'rotate' | 'replace' | 'resumed';
|
|
2342
|
+
/**
|
|
2343
|
+
* `written`: the placeholder was written and read back.
|
|
2344
|
+
* `already-present`: a resumed run found the placeholder in place.
|
|
2345
|
+
* `slot-moved-on`: the slot changed to another value before the fence;
|
|
2346
|
+
* it is left for the next adoption. (A placeholder replaced between its
|
|
2347
|
+
* write and the readback ends the run as `retry`,
|
|
2348
|
+
* `placeholder-overwritten`, not here.)
|
|
2349
|
+
*/
|
|
2350
|
+
placeholder: 'written' | 'already-present' | 'slot-moved-on';
|
|
2351
|
+
} |
|
|
2352
|
+
/**
|
|
2353
|
+
* An interrupted transfer's row holds neither its old credential nor the
|
|
2354
|
+
* slot's: someone rotated it after the interruption, so the slot copy may
|
|
2355
|
+
* be stale. The slot is left alone and this exact slot value is declined
|
|
2356
|
+
* for adoption; the user's next login resolves it.
|
|
2357
|
+
*/
|
|
2358
|
+
{
|
|
2359
|
+
status: 'ambiguous';
|
|
2360
|
+
rowId: string;
|
|
2361
|
+
} | {
|
|
2362
|
+
status: 'retry';
|
|
2363
|
+
reason: 'host-slot-indeterminate' | 'legacy-refresh-in-progress' | 'lock-contention' | 'verify-failed' | 'torn-read' | 'slot-changed' |
|
|
2364
|
+
/**
|
|
2365
|
+
* Something replaced the placeholder between its write and the
|
|
2366
|
+
* readback. The record and the shield stay, since the slot may hold
|
|
2367
|
+
* the very token the row now holds; the next run reads the slot
|
|
2368
|
+
* again and finishes the transfer from what it finds.
|
|
2369
|
+
*/
|
|
2370
|
+
'placeholder-overwritten' | 'unsettled' |
|
|
2371
|
+
/**
|
|
2372
|
+
* An adoption found the vault's first roster read still unfinished
|
|
2373
|
+
* after its wait, so whether the vault serves this host was unknown;
|
|
2374
|
+
* nothing was adopted.
|
|
2375
|
+
*/
|
|
2376
|
+
'vault-roster-pending' | `store-${string}`;
|
|
2377
|
+
} | {
|
|
2378
|
+
status: 'error';
|
|
2379
|
+
reason: string;
|
|
2380
|
+
};
|
|
2381
|
+
/** What the migration needs beyond an adoption run. */
|
|
2382
|
+
interface PoolMigrationFenceDeps {
|
|
2383
|
+
/**
|
|
2384
|
+
* The version fence (`migrationFenceOpen` in `version-fence.ts`, bound to
|
|
2385
|
+
* this build's version). While it is shut the migration writes nothing.
|
|
2386
|
+
*/
|
|
2387
|
+
fence: () => Promise<VersionFenceResult>;
|
|
2388
|
+
}
|
|
2389
|
+
/**
|
|
2390
|
+
* One-time move of the host-slot credential into the pool row `main`
|
|
2391
|
+
* (fallback rows are already pool rows: same ids, same files). It writes
|
|
2392
|
+
* nothing while an older openai-auth process runs (`deferred`). A re-run
|
|
2393
|
+
* after completion does nothing.
|
|
2394
|
+
*/
|
|
2395
|
+
declare function migrateToPool(deps: PoolMigrationDeps & PoolMigrationFenceDeps): Promise<PoolTransferOutcome>;
|
|
2396
|
+
/**
|
|
2397
|
+
* After migration: a real login found in the host slot (someone ran
|
|
2398
|
+
* `/login openai` in OpenCode) moves into the pool, matched by wire identity,
|
|
2399
|
+
* and the placeholder goes back into the slot.
|
|
2400
|
+
*/
|
|
2401
|
+
declare function adoptHostSlotLogin(deps: PoolMigrationDeps): Promise<PoolTransferOutcome>;
|
|
2402
|
+
//#endregion
|
|
2403
|
+
//#region src/core/pool-lifecycle.d.ts
|
|
2404
|
+
interface PoolLifecycleTimers {
|
|
2405
|
+
set(run: () => void, ms: number): unknown;
|
|
2406
|
+
clear(handle: unknown): void;
|
|
2407
|
+
}
|
|
2408
|
+
interface PoolLifecycleDeps {
|
|
2409
|
+
/** Read at every run, so it follows the configured store path. */
|
|
2410
|
+
paths: () => AccountPaths;
|
|
2411
|
+
slot: HostSlotAdapter;
|
|
2412
|
+
/** This build's version, for the version fence. */
|
|
2413
|
+
version: string;
|
|
2414
|
+
log?: PoolMigrationLogger;
|
|
2415
|
+
/** Defaults to `migrationFenceOpen` for `version`. */
|
|
2416
|
+
fence?: () => Promise<VersionFenceResult>;
|
|
2417
|
+
migrate?: typeof migrateToPool;
|
|
2418
|
+
adopt?: typeof adoptHostSlotLogin;
|
|
2419
|
+
timers?: PoolLifecycleTimers;
|
|
2420
|
+
random?: () => number;
|
|
2421
|
+
/** Passed through to every migration and adoption run (tests). */
|
|
2422
|
+
runDeps?: Partial<PoolMigrationDeps>;
|
|
2423
|
+
/**
|
|
2424
|
+
* True while no migration or adoption may run: the host is in vault mode,
|
|
2425
|
+
* which writes no local account file. Read before every run.
|
|
2426
|
+
*/
|
|
2427
|
+
paused?: () => boolean | Promise<boolean>;
|
|
2428
|
+
}
|
|
2429
|
+
//#endregion
|
|
2430
|
+
export { BeginAccountLoginOptions as a, TokenResponse as c, parseJwtClaims as d, AccountPaths as f, OpenAiVaultOptions as i, beginAccountLogin as l, HostSlotAdapter as n, BeginAccountLoginResult as o, PoolStore as p, OpenAiVault as r, IdTokenClaims as s, PoolLifecycleDeps as t, extractAccountIdFromClaims as u };
|