@omnicross/contracts 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/account-tokens-types.d.cts +181 -1
  2. package/dist/account-tokens-types.d.ts +181 -1
  3. package/dist/audit-types.cjs +36 -0
  4. package/dist/audit-types.d.cts +98 -0
  5. package/dist/audit-types.d.ts +98 -0
  6. package/dist/audit-types.js +11 -0
  7. package/dist/billing-types.cjs +33 -0
  8. package/dist/billing-types.d.cts +98 -0
  9. package/dist/billing-types.d.ts +98 -0
  10. package/dist/billing-types.js +8 -0
  11. package/dist/canonical-models.d.cts +1 -1
  12. package/dist/canonical-models.d.ts +1 -1
  13. package/dist/endpoint-resolver.d.cts +1 -1
  14. package/dist/endpoint-resolver.d.ts +1 -1
  15. package/dist/health-logging-types.cjs +32 -0
  16. package/dist/health-logging-types.d.cts +68 -0
  17. package/dist/health-logging-types.d.ts +68 -0
  18. package/dist/health-logging-types.js +7 -0
  19. package/dist/index.cjs +53 -0
  20. package/dist/index.d.cts +9 -2
  21. package/dist/index.d.ts +9 -2
  22. package/dist/index.js +46 -0
  23. package/dist/{llm-config-D1jKQLVp.d.ts → llm-config-CKOaFFdy.d.ts} +8 -1
  24. package/dist/{llm-config-CQjOimv2.d.cts → llm-config-DeWNx1ig.d.cts} +8 -1
  25. package/dist/llm-config.d.cts +1 -1
  26. package/dist/llm-config.d.ts +1 -1
  27. package/dist/pricing-types.cjs +30 -0
  28. package/dist/pricing-types.d.cts +84 -0
  29. package/dist/pricing-types.d.ts +84 -0
  30. package/dist/pricing-types.js +5 -0
  31. package/dist/provider-presets/index.d.cts +2 -2
  32. package/dist/provider-presets/index.d.ts +2 -2
  33. package/dist/thinking-config.d.cts +1 -1
  34. package/dist/thinking-config.d.ts +1 -1
  35. package/dist/usage-stats-types.cjs +18 -0
  36. package/dist/usage-stats-types.d.cts +164 -0
  37. package/dist/usage-stats-types.d.ts +164 -0
  38. package/dist/usage-stats-types.js +0 -0
  39. package/dist/voucher-types.cjs +32 -0
  40. package/dist/voucher-types.d.cts +153 -0
  41. package/dist/voucher-types.d.ts +153 -0
  42. package/dist/voucher-types.js +7 -0
  43. package/dist/webhook-types.cjs +40 -0
  44. package/dist/webhook-types.d.cts +122 -0
  45. package/dist/webhook-types.d.ts +122 -0
  46. package/dist/webhook-types.js +14 -0
  47. package/package.json +36 -1
@@ -9,6 +9,45 @@ import { OpenCodeGoTokenConfig } from './subscription-types.cjs';
9
9
  * sanitized shapes, and the OAuth exchange request types.
10
10
  */
11
11
 
12
+ /**
13
+ * Upstream proxy descriptor (upstream-proxy). Routes an outbound upstream call
14
+ * through an http/https or socks5 proxy. Two interchangeable shapes:
15
+ * - `{ url }` — a full proxy URL, e.g. `http://user:pass@host:1080` or
16
+ * `socks5://host:1080` (userinfo carries basic-auth).
17
+ * - structured — an explicit `{ type, host, port, username?, password? }`.
18
+ *
19
+ * `username`/`password` are SECRETS: encrypted at rest via the same envelope as
20
+ * other credentials, masked in every sanitized/admin view, and never logged
21
+ * (logs carry at most `host:port`). Additive everywhere it appears — absent ⇒ a
22
+ * direct (non-proxied) call, byte-identical to before proxy support.
23
+ */
24
+ type ProxyConfig = {
25
+ url: string;
26
+ } | {
27
+ type: 'http' | 'https' | 'socks5';
28
+ host: string;
29
+ port: number;
30
+ username?: string;
31
+ password?: string;
32
+ };
33
+ /**
34
+ * Persisted per-account client identity (subscription-client-fingerprint #7, P2).
35
+ * The frozen fingerprint headers a real Claude Code client sent for this account,
36
+ * captured + replayed so relayed traffic presents a stable identity across
37
+ * restarts. NON-secret metadata: it holds ONLY whitelisted fingerprint headers
38
+ * (`x-stainless-*` / user-agent / anthropic-beta / x-app / CC headers) — NEVER
39
+ * `authorization` / `x-api-key` / `cookie` (excluded at capture AND at
40
+ * store-normalize). Additive + OPTIONAL — an existing `tokens.json` without it
41
+ * parses unchanged (the account re-captures from a real client). Because it is
42
+ * non-secret it lives on the entry OUTSIDE the encrypted `tokens` block and is
43
+ * not walked by the secrets encryptor.
44
+ */
45
+ type AccountClientIdentity = {
46
+ /** The frozen fingerprint headers (lowercased keys; token/secret excluded). */
47
+ headers: Record<string, string>;
48
+ /** Epoch ms of the freeze / last TTL refresh. */
49
+ capturedAt: number;
50
+ };
12
51
  /**
13
52
  * Authorization method (general)
14
53
  */
@@ -25,6 +64,18 @@ type SubscriptionLevel = 'Free' | 'Pro' | 'Max';
25
64
  * Token configuration status
26
65
  */
27
66
  type TokenStatus = 'unconfigured' | 'authorized' | 'configured' | 'expired' | 'error';
67
+ /**
68
+ * Machine-readable credential-sync warning code (external-cli-sync).
69
+ *
70
+ * - `external-divergent`: the external CLI's native credential file (e.g.
71
+ * `~/.claude/.credentials.json`) holds a DIFFERENT, fresher credential than
72
+ * the stored account — the stored refresh token may have been rotated out.
73
+ * - `external-not-rotated`: a refresh failed and the external file holds the
74
+ * SAME dead credential — a genuine revocation, re-login is required.
75
+ * - `duplicate-token`: two accounts of one provider share the same credential —
76
+ * refreshing one will invalidate the other (single-use refresh tokens).
77
+ */
78
+ type SyncWarningCode = 'external-divergent' | 'external-not-rotated' | 'duplicate-token';
28
79
  /**
29
80
  * Claude token configuration
30
81
  */
@@ -40,6 +91,9 @@ type ClaudeTokenConfig = {
40
91
  setupTokenExpiresAt?: string;
41
92
  lastRefreshedAt?: string;
42
93
  errorMessage?: string;
94
+ /** Persisted credential-sync warning (external-cli-sync); cleared on a
95
+ * successful refresh / import. */
96
+ syncWarning?: SyncWarningCode;
43
97
  };
44
98
  /**
45
99
  * Codex (OpenAI) token configuration
@@ -56,6 +110,9 @@ type CodexTokenConfig = {
56
110
  organizationId?: string;
57
111
  lastRefreshedAt?: string;
58
112
  errorMessage?: string;
113
+ /** Persisted credential-sync warning (external-cli-sync); cleared on a
114
+ * successful refresh / import. */
115
+ syncWarning?: SyncWarningCode;
59
116
  };
60
117
  /**
61
118
  * Gemini token configuration
@@ -84,6 +141,57 @@ type SubscriptionAccountEntry<TConfig> = {
84
141
  label?: string;
85
142
  /** ISO creation timestamp. */
86
143
  createdAt?: string;
144
+ /**
145
+ * Scheduling precedence in the account pool (subscription-account-scheduling).
146
+ * Lower = higher precedence; default `50` when absent (CRS `parseInt(x,10) || 50`
147
+ * parity). OPTIONAL — an existing `tokens.json` without it parses unchanged and
148
+ * every account defaults to 50.
149
+ */
150
+ priority?: number;
151
+ /**
152
+ * ISO timestamp of the last time this account was selected to serve a request
153
+ * (subscription-account-scheduling LRU tie-break input). OPTIONAL, best-effort
154
+ * throttled persist — the selector's in-memory overlay is the authoritative live
155
+ * value; an account without it sorts as least-recently-used (timestamp `0`).
156
+ */
157
+ lastUsedAt?: string;
158
+ /**
159
+ * Per-account upstream proxy override (upstream-proxy). When set, this
160
+ * account's relay + OAuth-refresh traffic is routed through this proxy,
161
+ * WINNING over the per-provider and global proxy layers. OPTIONAL — an
162
+ * existing `tokens.json` without it parses unchanged (no proxy → direct). Its
163
+ * `password` is a secret: encrypted at rest by the tokens `SecretBox` walker
164
+ * and masked in the sanitized view.
165
+ */
166
+ proxy?: ProxyConfig;
167
+ /**
168
+ * Per-account model support + logical→actual remap (subscription-account-model-map).
169
+ * CRS dual-format, OPTIONAL — an existing `tokens.json` without it parses
170
+ * unchanged (the account supports every model and never remaps, byte-identical
171
+ * to before this change):
172
+ * - **array** `["a","b"]` — an ALLOW-LIST: the account supports ONLY these
173
+ * logical models (skip-only, no remap). In a ≥2-account pool the account is
174
+ * routed AROUND for any other model.
175
+ * - **object** `{ "a": "X", "b": "Y" }` — the keys are the same allow-list AND
176
+ * each value is the account's ACTUAL upstream model, so a selected account
177
+ * remaps the logical model to its actual model on the outbound request.
178
+ *
179
+ * Model-support filtering only applies when the provider has ≥2 accounts (the
180
+ * same gate as account health) — a sole account is never model-gated
181
+ * (never-strand; the upstream stays authoritative). A sole account that must
182
+ * serve a logical model AS a different actual model uses the OBJECT map (remap),
183
+ * not skip.
184
+ */
185
+ supportedModels?: string[] | Record<string, string>;
186
+ /**
187
+ * Persisted per-account client fingerprint identity (subscription-client-
188
+ * fingerprint #7, P2). OPTIONAL, additive, NON-secret metadata (kept OUTSIDE the
189
+ * encrypted `tokens` block) — an existing `tokens.json` without it parses
190
+ * unchanged. Written through by the daemon on a first-seen freeze / TTL refresh;
191
+ * seeded back into the in-memory identity store at boot so a claude account's
192
+ * replayed identity survives restart.
193
+ */
194
+ identity?: AccountClientIdentity;
87
195
  /** The provider's existing token config, verbatim. */
88
196
  tokens: TConfig;
89
197
  };
@@ -110,6 +218,22 @@ type AccountTokensConfig = {
110
218
  activeOpencodegoAccountId?: string;
111
219
  updatedAt: string;
112
220
  };
221
+ /**
222
+ * Secret-free view of a per-account/global/provider proxy (upstream-proxy). The
223
+ * password is NEVER carried — only a `hasPassword` presence flag plus a
224
+ * display-safe `host:port` endpoint (userinfo stripped). Rendered in the admin
225
+ * accounts view.
226
+ */
227
+ type SanitizedProxyConfig = {
228
+ /** `'url'` when configured via a full URL, else the structured proxy type. */
229
+ kind: 'url' | 'http' | 'https' | 'socks5';
230
+ /** Display-safe `host:port` (parsed from a url form; userinfo stripped). */
231
+ endpoint?: string;
232
+ /** Optional non-secret username (for display); the password is never returned. */
233
+ username?: string;
234
+ /** Whether a proxy password is set. The password value itself never leaves. */
235
+ hasPassword: boolean;
236
+ };
113
237
  /**
114
238
  * Sanitized view of a single subscription account (frontend display).
115
239
  * NEVER carries raw token material (no accessToken/refreshToken/idToken/apiKey).
@@ -125,6 +249,62 @@ type SubscriptionAccountSanitized = {
125
249
  isSetupToken?: boolean;
126
250
  hasAccessToken: boolean;
127
251
  isActive: boolean;
252
+ /**
253
+ * Scheduling precedence (subscription-account-scheduling) — editable in the
254
+ * admin accounts view so an operator can order a pool. Absent ⇒ default 50.
255
+ */
256
+ priority?: number;
257
+ /**
258
+ * ISO timestamp of the last scheduler selection (display-only in the admin
259
+ * accounts view). Absent ⇒ never selected (or the best-effort persist has not
260
+ * yet flushed).
261
+ */
262
+ lastUsedAt?: string;
263
+ /**
264
+ * Credential-sync warning for this account (external-cli-sync). Carries the
265
+ * persisted code when one was recorded by a failed refresh, plus the
266
+ * list-time computed codes (`external-divergent` / `duplicate-token`).
267
+ */
268
+ syncWarning?: SyncWarningCode;
269
+ /**
270
+ * Live scheduling-health state (subscription-account-health) — in-memory, never
271
+ * persisted. Absent / `'healthy'` ⇒ eligible; the rest mean the account is
272
+ * currently excluded from the pool (multi-account) or would surface the
273
+ * upstream's error (single-account). Secret-free.
274
+ */
275
+ health?: 'healthy' | 'rate_limited' | 'overloaded' | 'transient' | 'blocked';
276
+ /**
277
+ * ISO instant the current health cooldown elapses (absent for healthy /
278
+ * permanently-blocked). Lets the admin view render "rate-limited until …".
279
+ */
280
+ cooldownUntil?: string;
281
+ /**
282
+ * Secret-free view of this account's proxy override (upstream-proxy). Absent ⇒
283
+ * no per-account proxy configured. The password is masked to a `hasPassword`
284
+ * flag — never returned.
285
+ */
286
+ proxy?: SanitizedProxyConfig;
287
+ /**
288
+ * Per-account model support / logical→actual remap (subscription-account-model-map)
289
+ * — editable in the admin accounts view. Carried verbatim (secret-free — model
290
+ * ids are not token material): an array allow-list or an object logical→actual
291
+ * map. Absent ⇒ the account supports every model with no remap.
292
+ */
293
+ supportedModels?: string[] | Record<string, string>;
294
+ /**
295
+ * COARSE client-fingerprint status (subscription-client-fingerprint #7, D7) —
296
+ * whether THIS account has a captured/frozen client identity in the in-memory
297
+ * store. Present only when fingerprint replay is ENABLED (else absent ⇒ the UI
298
+ * shows nothing). Secret-free by construction: it is a BOOLEAN only — the raw
299
+ * captured headers are NEVER surfaced here (nor in any admin view).
300
+ */
301
+ identityCaptured?: boolean;
302
+ /**
303
+ * ISO instant this account's fingerprint identity was frozen / last TTL-refreshed
304
+ * (subscription-client-fingerprint #7, D7). Present only alongside
305
+ * `identityCaptured === true`. Coarse timestamp only — never the headers.
306
+ */
307
+ identityCapturedAt?: string;
128
308
  };
129
309
  /**
130
310
  * OAuth authorization parameters
@@ -143,4 +323,4 @@ type TokenExchangeRequest = {
143
323
  state: string;
144
324
  };
145
325
 
146
- export type { AccountTokensConfig, AuthMethod, ClaudeAuthMethod, ClaudeTokenConfig, CodexTokenConfig, GeminiTokenConfig, OAuthParams, SubscriptionAccountEntry, SubscriptionAccountSanitized, SubscriptionLevel, TokenExchangeRequest, TokenStatus };
326
+ export type { AccountClientIdentity, AccountTokensConfig, AuthMethod, ClaudeAuthMethod, ClaudeTokenConfig, CodexTokenConfig, GeminiTokenConfig, OAuthParams, ProxyConfig, SanitizedProxyConfig, SubscriptionAccountEntry, SubscriptionAccountSanitized, SubscriptionLevel, SyncWarningCode, TokenExchangeRequest, TokenStatus };
@@ -9,6 +9,45 @@ import { OpenCodeGoTokenConfig } from './subscription-types.js';
9
9
  * sanitized shapes, and the OAuth exchange request types.
10
10
  */
11
11
 
12
+ /**
13
+ * Upstream proxy descriptor (upstream-proxy). Routes an outbound upstream call
14
+ * through an http/https or socks5 proxy. Two interchangeable shapes:
15
+ * - `{ url }` — a full proxy URL, e.g. `http://user:pass@host:1080` or
16
+ * `socks5://host:1080` (userinfo carries basic-auth).
17
+ * - structured — an explicit `{ type, host, port, username?, password? }`.
18
+ *
19
+ * `username`/`password` are SECRETS: encrypted at rest via the same envelope as
20
+ * other credentials, masked in every sanitized/admin view, and never logged
21
+ * (logs carry at most `host:port`). Additive everywhere it appears — absent ⇒ a
22
+ * direct (non-proxied) call, byte-identical to before proxy support.
23
+ */
24
+ type ProxyConfig = {
25
+ url: string;
26
+ } | {
27
+ type: 'http' | 'https' | 'socks5';
28
+ host: string;
29
+ port: number;
30
+ username?: string;
31
+ password?: string;
32
+ };
33
+ /**
34
+ * Persisted per-account client identity (subscription-client-fingerprint #7, P2).
35
+ * The frozen fingerprint headers a real Claude Code client sent for this account,
36
+ * captured + replayed so relayed traffic presents a stable identity across
37
+ * restarts. NON-secret metadata: it holds ONLY whitelisted fingerprint headers
38
+ * (`x-stainless-*` / user-agent / anthropic-beta / x-app / CC headers) — NEVER
39
+ * `authorization` / `x-api-key` / `cookie` (excluded at capture AND at
40
+ * store-normalize). Additive + OPTIONAL — an existing `tokens.json` without it
41
+ * parses unchanged (the account re-captures from a real client). Because it is
42
+ * non-secret it lives on the entry OUTSIDE the encrypted `tokens` block and is
43
+ * not walked by the secrets encryptor.
44
+ */
45
+ type AccountClientIdentity = {
46
+ /** The frozen fingerprint headers (lowercased keys; token/secret excluded). */
47
+ headers: Record<string, string>;
48
+ /** Epoch ms of the freeze / last TTL refresh. */
49
+ capturedAt: number;
50
+ };
12
51
  /**
13
52
  * Authorization method (general)
14
53
  */
@@ -25,6 +64,18 @@ type SubscriptionLevel = 'Free' | 'Pro' | 'Max';
25
64
  * Token configuration status
26
65
  */
27
66
  type TokenStatus = 'unconfigured' | 'authorized' | 'configured' | 'expired' | 'error';
67
+ /**
68
+ * Machine-readable credential-sync warning code (external-cli-sync).
69
+ *
70
+ * - `external-divergent`: the external CLI's native credential file (e.g.
71
+ * `~/.claude/.credentials.json`) holds a DIFFERENT, fresher credential than
72
+ * the stored account — the stored refresh token may have been rotated out.
73
+ * - `external-not-rotated`: a refresh failed and the external file holds the
74
+ * SAME dead credential — a genuine revocation, re-login is required.
75
+ * - `duplicate-token`: two accounts of one provider share the same credential —
76
+ * refreshing one will invalidate the other (single-use refresh tokens).
77
+ */
78
+ type SyncWarningCode = 'external-divergent' | 'external-not-rotated' | 'duplicate-token';
28
79
  /**
29
80
  * Claude token configuration
30
81
  */
@@ -40,6 +91,9 @@ type ClaudeTokenConfig = {
40
91
  setupTokenExpiresAt?: string;
41
92
  lastRefreshedAt?: string;
42
93
  errorMessage?: string;
94
+ /** Persisted credential-sync warning (external-cli-sync); cleared on a
95
+ * successful refresh / import. */
96
+ syncWarning?: SyncWarningCode;
43
97
  };
44
98
  /**
45
99
  * Codex (OpenAI) token configuration
@@ -56,6 +110,9 @@ type CodexTokenConfig = {
56
110
  organizationId?: string;
57
111
  lastRefreshedAt?: string;
58
112
  errorMessage?: string;
113
+ /** Persisted credential-sync warning (external-cli-sync); cleared on a
114
+ * successful refresh / import. */
115
+ syncWarning?: SyncWarningCode;
59
116
  };
60
117
  /**
61
118
  * Gemini token configuration
@@ -84,6 +141,57 @@ type SubscriptionAccountEntry<TConfig> = {
84
141
  label?: string;
85
142
  /** ISO creation timestamp. */
86
143
  createdAt?: string;
144
+ /**
145
+ * Scheduling precedence in the account pool (subscription-account-scheduling).
146
+ * Lower = higher precedence; default `50` when absent (CRS `parseInt(x,10) || 50`
147
+ * parity). OPTIONAL — an existing `tokens.json` without it parses unchanged and
148
+ * every account defaults to 50.
149
+ */
150
+ priority?: number;
151
+ /**
152
+ * ISO timestamp of the last time this account was selected to serve a request
153
+ * (subscription-account-scheduling LRU tie-break input). OPTIONAL, best-effort
154
+ * throttled persist — the selector's in-memory overlay is the authoritative live
155
+ * value; an account without it sorts as least-recently-used (timestamp `0`).
156
+ */
157
+ lastUsedAt?: string;
158
+ /**
159
+ * Per-account upstream proxy override (upstream-proxy). When set, this
160
+ * account's relay + OAuth-refresh traffic is routed through this proxy,
161
+ * WINNING over the per-provider and global proxy layers. OPTIONAL — an
162
+ * existing `tokens.json` without it parses unchanged (no proxy → direct). Its
163
+ * `password` is a secret: encrypted at rest by the tokens `SecretBox` walker
164
+ * and masked in the sanitized view.
165
+ */
166
+ proxy?: ProxyConfig;
167
+ /**
168
+ * Per-account model support + logical→actual remap (subscription-account-model-map).
169
+ * CRS dual-format, OPTIONAL — an existing `tokens.json` without it parses
170
+ * unchanged (the account supports every model and never remaps, byte-identical
171
+ * to before this change):
172
+ * - **array** `["a","b"]` — an ALLOW-LIST: the account supports ONLY these
173
+ * logical models (skip-only, no remap). In a ≥2-account pool the account is
174
+ * routed AROUND for any other model.
175
+ * - **object** `{ "a": "X", "b": "Y" }` — the keys are the same allow-list AND
176
+ * each value is the account's ACTUAL upstream model, so a selected account
177
+ * remaps the logical model to its actual model on the outbound request.
178
+ *
179
+ * Model-support filtering only applies when the provider has ≥2 accounts (the
180
+ * same gate as account health) — a sole account is never model-gated
181
+ * (never-strand; the upstream stays authoritative). A sole account that must
182
+ * serve a logical model AS a different actual model uses the OBJECT map (remap),
183
+ * not skip.
184
+ */
185
+ supportedModels?: string[] | Record<string, string>;
186
+ /**
187
+ * Persisted per-account client fingerprint identity (subscription-client-
188
+ * fingerprint #7, P2). OPTIONAL, additive, NON-secret metadata (kept OUTSIDE the
189
+ * encrypted `tokens` block) — an existing `tokens.json` without it parses
190
+ * unchanged. Written through by the daemon on a first-seen freeze / TTL refresh;
191
+ * seeded back into the in-memory identity store at boot so a claude account's
192
+ * replayed identity survives restart.
193
+ */
194
+ identity?: AccountClientIdentity;
87
195
  /** The provider's existing token config, verbatim. */
88
196
  tokens: TConfig;
89
197
  };
@@ -110,6 +218,22 @@ type AccountTokensConfig = {
110
218
  activeOpencodegoAccountId?: string;
111
219
  updatedAt: string;
112
220
  };
221
+ /**
222
+ * Secret-free view of a per-account/global/provider proxy (upstream-proxy). The
223
+ * password is NEVER carried — only a `hasPassword` presence flag plus a
224
+ * display-safe `host:port` endpoint (userinfo stripped). Rendered in the admin
225
+ * accounts view.
226
+ */
227
+ type SanitizedProxyConfig = {
228
+ /** `'url'` when configured via a full URL, else the structured proxy type. */
229
+ kind: 'url' | 'http' | 'https' | 'socks5';
230
+ /** Display-safe `host:port` (parsed from a url form; userinfo stripped). */
231
+ endpoint?: string;
232
+ /** Optional non-secret username (for display); the password is never returned. */
233
+ username?: string;
234
+ /** Whether a proxy password is set. The password value itself never leaves. */
235
+ hasPassword: boolean;
236
+ };
113
237
  /**
114
238
  * Sanitized view of a single subscription account (frontend display).
115
239
  * NEVER carries raw token material (no accessToken/refreshToken/idToken/apiKey).
@@ -125,6 +249,62 @@ type SubscriptionAccountSanitized = {
125
249
  isSetupToken?: boolean;
126
250
  hasAccessToken: boolean;
127
251
  isActive: boolean;
252
+ /**
253
+ * Scheduling precedence (subscription-account-scheduling) — editable in the
254
+ * admin accounts view so an operator can order a pool. Absent ⇒ default 50.
255
+ */
256
+ priority?: number;
257
+ /**
258
+ * ISO timestamp of the last scheduler selection (display-only in the admin
259
+ * accounts view). Absent ⇒ never selected (or the best-effort persist has not
260
+ * yet flushed).
261
+ */
262
+ lastUsedAt?: string;
263
+ /**
264
+ * Credential-sync warning for this account (external-cli-sync). Carries the
265
+ * persisted code when one was recorded by a failed refresh, plus the
266
+ * list-time computed codes (`external-divergent` / `duplicate-token`).
267
+ */
268
+ syncWarning?: SyncWarningCode;
269
+ /**
270
+ * Live scheduling-health state (subscription-account-health) — in-memory, never
271
+ * persisted. Absent / `'healthy'` ⇒ eligible; the rest mean the account is
272
+ * currently excluded from the pool (multi-account) or would surface the
273
+ * upstream's error (single-account). Secret-free.
274
+ */
275
+ health?: 'healthy' | 'rate_limited' | 'overloaded' | 'transient' | 'blocked';
276
+ /**
277
+ * ISO instant the current health cooldown elapses (absent for healthy /
278
+ * permanently-blocked). Lets the admin view render "rate-limited until …".
279
+ */
280
+ cooldownUntil?: string;
281
+ /**
282
+ * Secret-free view of this account's proxy override (upstream-proxy). Absent ⇒
283
+ * no per-account proxy configured. The password is masked to a `hasPassword`
284
+ * flag — never returned.
285
+ */
286
+ proxy?: SanitizedProxyConfig;
287
+ /**
288
+ * Per-account model support / logical→actual remap (subscription-account-model-map)
289
+ * — editable in the admin accounts view. Carried verbatim (secret-free — model
290
+ * ids are not token material): an array allow-list or an object logical→actual
291
+ * map. Absent ⇒ the account supports every model with no remap.
292
+ */
293
+ supportedModels?: string[] | Record<string, string>;
294
+ /**
295
+ * COARSE client-fingerprint status (subscription-client-fingerprint #7, D7) —
296
+ * whether THIS account has a captured/frozen client identity in the in-memory
297
+ * store. Present only when fingerprint replay is ENABLED (else absent ⇒ the UI
298
+ * shows nothing). Secret-free by construction: it is a BOOLEAN only — the raw
299
+ * captured headers are NEVER surfaced here (nor in any admin view).
300
+ */
301
+ identityCaptured?: boolean;
302
+ /**
303
+ * ISO instant this account's fingerprint identity was frozen / last TTL-refreshed
304
+ * (subscription-client-fingerprint #7, D7). Present only alongside
305
+ * `identityCaptured === true`. Coarse timestamp only — never the headers.
306
+ */
307
+ identityCapturedAt?: string;
128
308
  };
129
309
  /**
130
310
  * OAuth authorization parameters
@@ -143,4 +323,4 @@ type TokenExchangeRequest = {
143
323
  state: string;
144
324
  };
145
325
 
146
- export type { AccountTokensConfig, AuthMethod, ClaudeAuthMethod, ClaudeTokenConfig, CodexTokenConfig, GeminiTokenConfig, OAuthParams, SubscriptionAccountEntry, SubscriptionAccountSanitized, SubscriptionLevel, TokenExchangeRequest, TokenStatus };
326
+ export type { AccountClientIdentity, AccountTokensConfig, AuthMethod, ClaudeAuthMethod, ClaudeTokenConfig, CodexTokenConfig, GeminiTokenConfig, OAuthParams, ProxyConfig, SanitizedProxyConfig, SubscriptionAccountEntry, SubscriptionAccountSanitized, SubscriptionLevel, SyncWarningCode, TokenExchangeRequest, TokenStatus };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/audit-types.ts
21
+ var audit_types_exports = {};
22
+ __export(audit_types_exports, {
23
+ DEFAULT_AUDIT_CONFIG: () => DEFAULT_AUDIT_CONFIG
24
+ });
25
+ module.exports = __toCommonJS(audit_types_exports);
26
+ var DEFAULT_AUDIT_CONFIG = {
27
+ enabled: false,
28
+ captureBodies: false,
29
+ maxBodyBytes: 8192,
30
+ retentionDays: 7,
31
+ trustForwardedFor: false
32
+ };
33
+ // Annotate the CommonJS export names for ESM import in node:
34
+ 0 && (module.exports = {
35
+ DEFAULT_AUDIT_CONFIG
36
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Request-audit contracts (request-audit-log, design D1/D2).
3
+ *
4
+ * Two dependency-light shapes shared across the `@omnicross/*` packages:
5
+ * - `AuditRecord` — the FROZEN per-request audit entry. It carries request
6
+ * METADATA (who/where/when/status/latency/model) plus, ONLY when body capture
7
+ * is explicitly enabled, a redacted+truncated request/response body snapshot.
8
+ * It is SECRET-FREE BY CONSTRUCTION: it holds the outbound key ID (NEVER the
9
+ * key material/hash), the client IP + user-agent (PII, hence the whole store
10
+ * is authed-only + TTL-pruned), and NEVER a token, Authorization header, or
11
+ * api-key header value (request headers are NEVER captured). A secret-scan
12
+ * test asserts no key/token pattern survives in a written record.
13
+ * - `AuditConfig` — the `audit` config segment. Two independent switches:
14
+ * `enabled` (record metadata) and `captureBodies` (the sensitive second
15
+ * opt-in — record bodies too), both default OFF (zero regression).
16
+ *
17
+ * @module audit-types
18
+ */
19
+ /**
20
+ * One per-request audit entry (design D1). The metadata fields are recorded
21
+ * whenever audit is `enabled`; the two body snapshots are present ONLY when
22
+ * `captureBodies` is ALSO on, and always after truncation + redaction. NO field
23
+ * ever holds key material, an upstream token, or an Authorization/api-key header.
24
+ */
25
+ interface AuditRecord {
26
+ /** Unique record id (a generated request id — NOT any secret). */
27
+ id: string;
28
+ /** Epoch ms the request was captured. */
29
+ ts: number;
30
+ /** Outbound key id (attribution) — NEVER the key secret/hash. Null when unauthenticated. */
31
+ keyId?: string | null;
32
+ /** Client IP (PII). Socket address by default; a trusted forwarded header only when configured. */
33
+ ip?: string;
34
+ /** Client user-agent (PII). */
35
+ ua?: string;
36
+ /** HTTP method. */
37
+ method: string;
38
+ /** Request path (query string dropped so no secret query param is stored). */
39
+ path: string;
40
+ /** Resolved upstream model. */
41
+ model?: string;
42
+ /** Upstream provider id (or `'byo'`). */
43
+ provider?: string;
44
+ /** HTTP status the client received. */
45
+ status: number;
46
+ /** End-to-end latency (ms). */
47
+ latencyMs: number;
48
+ /** Prompt-side token count (present only when the host correlates usage). */
49
+ inputTokens?: number;
50
+ /** Completion-side token count (present only when the host correlates usage). */
51
+ outputTokens?: number;
52
+ /** Cost in USD (present only when the host correlates usage). */
53
+ costUsd?: number;
54
+ /** Sanitized error message (present only on a failed relay). */
55
+ error?: string;
56
+ /**
57
+ * Request body snapshot — present ONLY when `captureBodies`, truncated to the
58
+ * configured cap, and ALWAYS run through the secret-redaction pass first.
59
+ */
60
+ requestBody?: string;
61
+ /**
62
+ * Response body snapshot — present ONLY when `captureBodies` AND the response
63
+ * was NON-streaming (a streaming response records metadata only), truncated +
64
+ * redacted like `requestBody`.
65
+ */
66
+ responseBody?: string;
67
+ }
68
+ /**
69
+ * The `audit` config segment (design D2), normalized like `accountHealth`.
70
+ * Absent/`enabled:false` ⇒ no sink wired + no capture ⇒ byte-identical zero
71
+ * regression. `captureBodies` is a SEPARATE, sensitive opt-in that does nothing
72
+ * unless `enabled` is also on.
73
+ */
74
+ interface AuditConfig {
75
+ /** Master switch; default FALSE (zero regression). */
76
+ enabled: boolean;
77
+ /** Capture request/response bodies too (redacted+truncated); default FALSE. */
78
+ captureBodies: boolean;
79
+ /** Per-body truncation cap in bytes; default 8192, clamped. */
80
+ maxBodyBytes: number;
81
+ /** TTL retention in days; default 7, clamped `[1, 365]`. */
82
+ retentionDays: number;
83
+ /**
84
+ * Trust the `X-Forwarded-For` header for the client IP (LEAD OQ1 anti-spoof).
85
+ * Default FALSE — the socket remote address is authoritative. Only set true
86
+ * behind a trusted reverse proxy; a client-supplied XFF is NEVER trusted by
87
+ * default.
88
+ */
89
+ trustForwardedFor: boolean;
90
+ }
91
+ /** Frozen defaults for the `audit` segment (SSOT). */
92
+ declare const DEFAULT_AUDIT_CONFIG: AuditConfig;
93
+ /** One page of audit records the authed admin query returns (newest first). */
94
+ interface AuditQueryResult {
95
+ records: AuditRecord[];
96
+ }
97
+
98
+ export { type AuditConfig, type AuditQueryResult, type AuditRecord, DEFAULT_AUDIT_CONFIG };