@omnicross/contracts 0.1.2 → 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 (41) hide show
  1. package/dist/account-tokens-types.d.cts +157 -1
  2. package/dist/account-tokens-types.d.ts +157 -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 +48 -0
  20. package/dist/index.d.cts +8 -3
  21. package/dist/index.d.ts +8 -3
  22. package/dist/index.js +42 -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/provider-presets/index.d.cts +2 -2
  28. package/dist/provider-presets/index.d.ts +2 -2
  29. package/dist/thinking-config.d.cts +1 -1
  30. package/dist/thinking-config.d.ts +1 -1
  31. package/dist/usage-stats-types.d.cts +22 -1
  32. package/dist/usage-stats-types.d.ts +22 -1
  33. package/dist/voucher-types.cjs +32 -0
  34. package/dist/voucher-types.d.cts +153 -0
  35. package/dist/voucher-types.d.ts +153 -0
  36. package/dist/voucher-types.js +7 -0
  37. package/dist/webhook-types.cjs +40 -0
  38. package/dist/webhook-types.d.cts +122 -0
  39. package/dist/webhook-types.d.ts +122 -0
  40. package/dist/webhook-types.js +14 -0
  41. package/package.json +26 -1
package/dist/index.js CHANGED
@@ -1,3 +1,18 @@
1
+ // src/audit-types.ts
2
+ var DEFAULT_AUDIT_CONFIG = {
3
+ enabled: false,
4
+ captureBodies: false,
5
+ maxBodyBytes: 8192,
6
+ retentionDays: 7,
7
+ trustForwardedFor: false
8
+ };
9
+
10
+ // src/billing-types.ts
11
+ var DEFAULT_BILLING_CONFIG = {
12
+ enabled: false,
13
+ maxRetryAgeMs: 24 * 60 * 6e4
14
+ };
15
+
1
16
  // src/canonical-models.ts
2
17
  var OPENAI_MODELS = {
3
18
  "gpt-5.5": { category: "reasoning", contextLength: 105e4, maxTokens: 128e3, reasoning: true, vision: true, functionCall: true, thinkingLevels: ["none", "low", "medium", "high", "xhigh"], thinkingTokenLimit: { min: 0, max: 128e3 } },
@@ -260,6 +275,11 @@ function isExtendedContextCapable(model) {
260
275
  return EXTENDED_CONTEXT_CAPABLE_MODELS.has(model);
261
276
  }
262
277
 
278
+ // src/health-logging-types.ts
279
+ function healthHttpStatus(status) {
280
+ return status === "ok" ? 200 : 503;
281
+ }
282
+
263
283
  // src/mcp-types.ts
264
284
  var DEFAULT_MCP_SESSION_CONFIG = {
265
285
  mode: "auto",
@@ -2606,6 +2626,22 @@ function buildQwenThinkingConfig(level, userMaxTokens) {
2606
2626
  };
2607
2627
  }
2608
2628
 
2629
+ // src/voucher-types.ts
2630
+ var DEFAULT_VOUCHER_CONFIG = {
2631
+ enabled: false
2632
+ };
2633
+
2634
+ // src/webhook-types.ts
2635
+ var WEBHOOK_EVENT_KINDS = [
2636
+ "account.recovery",
2637
+ "account.anomaly",
2638
+ "key.quotaWarning",
2639
+ "key.quotaExceeded",
2640
+ "server.error",
2641
+ "test"
2642
+ ];
2643
+ var WEBHOOK_DESTINATION_TYPES = ["custom", "feishu"];
2644
+
2609
2645
  // src/websearch-types.ts
2610
2646
  function isApiProvider(id) {
2611
2647
  return !id.startsWith("local-");
@@ -2618,10 +2654,13 @@ export {
2618
2654
  CANNOT_DISABLE_THINKING_PATTERNS,
2619
2655
  CATALOG_VERSION,
2620
2656
  CODING_PLAN_URL_PRESETS,
2657
+ DEFAULT_AUDIT_CONFIG,
2658
+ DEFAULT_BILLING_CONFIG,
2621
2659
  DEFAULT_LITELLM_PRICING_URL,
2622
2660
  DEFAULT_MAX_TOKENS,
2623
2661
  DEFAULT_MCP_SESSION_CONFIG,
2624
2662
  DEFAULT_SEED_PRESET_IDS,
2663
+ DEFAULT_VOUCHER_CONFIG,
2625
2664
  EFFORT_RATIO,
2626
2665
  EXTENDED_CONTEXT_CAPABLE_MODELS,
2627
2666
  KNOWN_MODELS,
@@ -2632,6 +2671,8 @@ export {
2632
2671
  PROVIDER_SEARCH_CONFIGS,
2633
2672
  REASONING_MODEL_PATTERNS,
2634
2673
  THINKING_TOKEN_MAP,
2674
+ WEBHOOK_DESTINATION_TYPES,
2675
+ WEBHOOK_EVENT_KINDS,
2635
2676
  applyAlias,
2636
2677
  buildAnthropicThinking,
2637
2678
  buildGeminiThinkingConfig,
@@ -2646,6 +2687,7 @@ export {
2646
2687
  getPresetById,
2647
2688
  getPresetRevision,
2648
2689
  getProviderSearchConfig,
2690
+ healthHttpStatus,
2649
2691
  isApiProvider,
2650
2692
  isExtendedContextCapable,
2651
2693
  isLocalProvider,
@@ -286,6 +286,14 @@ interface LLMProvider {
286
286
  modelGroups?: ModelGroup[];
287
287
  modelsEndpoint?: string;
288
288
  enabled: boolean;
289
+ /**
290
+ * For `apiFormat: 'anthropic'` providers, authenticate with
291
+ * `Authorization: Bearer <apiKey>` instead of the default `x-api-key` header.
292
+ * Set this for third-party Anthropic-Messages relays that gate on a Bearer
293
+ * token (the native/base header path; the transformer path uses the
294
+ * `UseBearer` transformer option independently).
295
+ */
296
+ useBearer?: boolean;
289
297
  transformer?: TransformerConfig;
290
298
  rerouterEnabled?: boolean;
291
299
  icon?: string;
@@ -294,7 +302,6 @@ interface LLMProvider {
294
302
  defaultSettings?: CompletionSettings;
295
303
  isSystem?: boolean;
296
304
  isOfficial?: boolean;
297
- rateLimit?: number;
298
305
  maxConcurrency?: number;
299
306
  notes?: string;
300
307
  apiVersion?: string;
@@ -286,6 +286,14 @@ interface LLMProvider {
286
286
  modelGroups?: ModelGroup[];
287
287
  modelsEndpoint?: string;
288
288
  enabled: boolean;
289
+ /**
290
+ * For `apiFormat: 'anthropic'` providers, authenticate with
291
+ * `Authorization: Bearer <apiKey>` instead of the default `x-api-key` header.
292
+ * Set this for third-party Anthropic-Messages relays that gate on a Bearer
293
+ * token (the native/base header path; the transformer path uses the
294
+ * `UseBearer` transformer option independently).
295
+ */
296
+ useBearer?: boolean;
289
297
  transformer?: TransformerConfig;
290
298
  rerouterEnabled?: boolean;
291
299
  icon?: string;
@@ -294,7 +302,6 @@ interface LLMProvider {
294
302
  defaultSettings?: CompletionSettings;
295
303
  isSystem?: boolean;
296
304
  isOfficial?: boolean;
297
- rateLimit?: number;
298
305
  maxConcurrency?: number;
299
306
  notes?: string;
300
307
  apiVersion?: string;
@@ -1,2 +1,2 @@
1
1
  import './thinking-CBWSLel8.cjs';
2
- export { a as AgentDefaultModels, b as ApiFormat, c as ApiKeyEntry, C as ChatApiFormat, g as CompletionSettings, G as GlobalModelParameters, L as LLMProvider, M as ModelConfig, h as ModelGroup, i as ModelParameter, j as ModelRef, O as OpenRouterDataCollection, k as OpenRouterMaxPrice, l as OpenRouterProviderRouting, m as OpenRouterProviderSort, n as OpenRouterQuantization, o as ProviderApiType, r as ProviderTemplate, T as TransformerConfig, s as TransformerEntry } from './llm-config-CQjOimv2.cjs';
2
+ export { a as AgentDefaultModels, b as ApiFormat, c as ApiKeyEntry, C as ChatApiFormat, g as CompletionSettings, G as GlobalModelParameters, L as LLMProvider, M as ModelConfig, h as ModelGroup, i as ModelParameter, j as ModelRef, O as OpenRouterDataCollection, k as OpenRouterMaxPrice, l as OpenRouterProviderRouting, m as OpenRouterProviderSort, n as OpenRouterQuantization, o as ProviderApiType, r as ProviderTemplate, T as TransformerConfig, s as TransformerEntry } from './llm-config-DeWNx1ig.cjs';
@@ -1,2 +1,2 @@
1
1
  import './thinking-CBWSLel8.js';
2
- export { a as AgentDefaultModels, b as ApiFormat, c as ApiKeyEntry, C as ChatApiFormat, g as CompletionSettings, G as GlobalModelParameters, L as LLMProvider, M as ModelConfig, h as ModelGroup, i as ModelParameter, j as ModelRef, O as OpenRouterDataCollection, k as OpenRouterMaxPrice, l as OpenRouterProviderRouting, m as OpenRouterProviderSort, n as OpenRouterQuantization, o as ProviderApiType, r as ProviderTemplate, T as TransformerConfig, s as TransformerEntry } from './llm-config-D1jKQLVp.js';
2
+ export { a as AgentDefaultModels, b as ApiFormat, c as ApiKeyEntry, C as ChatApiFormat, g as CompletionSettings, G as GlobalModelParameters, L as LLMProvider, M as ModelConfig, h as ModelGroup, i as ModelParameter, j as ModelRef, O as OpenRouterDataCollection, k as OpenRouterMaxPrice, l as OpenRouterProviderRouting, m as OpenRouterProviderSort, n as OpenRouterQuantization, o as ProviderApiType, r as ProviderTemplate, T as TransformerConfig, s as TransformerEntry } from './llm-config-CKOaFFdy.js';
@@ -1,5 +1,5 @@
1
- import { p as ProviderModelMapping, q as ProviderSearchConfig, P as PresetProviderTemplate } from '../llm-config-CQjOimv2.cjs';
2
- export { A as API_MODE_IDS, d as ApiMode, e as ApiModeId, f as CodingPlanConfig, S as SearchCapability } from '../llm-config-CQjOimv2.cjs';
1
+ import { p as ProviderModelMapping, q as ProviderSearchConfig, P as PresetProviderTemplate } from '../llm-config-DeWNx1ig.cjs';
2
+ export { A as API_MODE_IDS, d as ApiMode, e as ApiModeId, f as CodingPlanConfig, S as SearchCapability } from '../llm-config-DeWNx1ig.cjs';
3
3
  import '../thinking-CBWSLel8.cjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { p as ProviderModelMapping, q as ProviderSearchConfig, P as PresetProviderTemplate } from '../llm-config-D1jKQLVp.js';
2
- export { A as API_MODE_IDS, d as ApiMode, e as ApiModeId, f as CodingPlanConfig, S as SearchCapability } from '../llm-config-D1jKQLVp.js';
1
+ import { p as ProviderModelMapping, q as ProviderSearchConfig, P as PresetProviderTemplate } from '../llm-config-CKOaFFdy.js';
2
+ export { A as API_MODE_IDS, d as ApiMode, e as ApiModeId, f as CodingPlanConfig, S as SearchCapability } from '../llm-config-CKOaFFdy.js';
3
3
  import '../thinking-CBWSLel8.js';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { T as ThinkLevel } from './thinking-CBWSLel8.cjs';
2
- import { M as ModelConfig } from './llm-config-CQjOimv2.cjs';
2
+ import { M as ModelConfig } from './llm-config-DeWNx1ig.cjs';
3
3
 
4
4
  /**
5
5
  * thinking-config — dependency-light thinking-budget / reasoning-effort helpers.
@@ -1,5 +1,5 @@
1
1
  import { T as ThinkLevel } from './thinking-CBWSLel8.js';
2
- import { M as ModelConfig } from './llm-config-D1jKQLVp.js';
2
+ import { M as ModelConfig } from './llm-config-CKOaFFdy.js';
3
3
 
4
4
  /**
5
5
  * thinking-config — dependency-light thinking-budget / reasoning-effort helpers.
@@ -70,6 +70,27 @@ interface UsageTotals {
70
70
  /** Number of events contributing to these totals. */
71
71
  eventCount: number;
72
72
  }
73
+ /** Granularity for a usage time-series query. `week` is NOT a bucket — a "week" view is a `day` bucket over a 7-day range. */
74
+ type UsageTimeBucket = 'hour' | 'day' | 'month';
75
+ /**
76
+ * One bucket of a usage time-series (trend chart). Buckets are query-time
77
+ * aggregations over the daemon's LOCAL-time boundaries and every bucket in the
78
+ * requested range is present (empty buckets are zero-filled), ascending by
79
+ * `bucketStartTs`.
80
+ */
81
+ interface UsageTimeSeriesBucket {
82
+ /** Unix-millis of the LOCAL-time bucket boundary (hour start / local midnight / local 1st-of-month). */
83
+ bucketStartTs: number;
84
+ /** Frozen locale-agnostic label from LOCAL parts: hour `MM-DD HH:00`, day `YYYY-MM-DD`, month `YYYY-MM`. */
85
+ label: string;
86
+ /** Event count in the bucket (0 for a zero-filled bucket). */
87
+ requests: number;
88
+ inputTokens: number;
89
+ outputTokens: number;
90
+ cacheReadTokens: number;
91
+ cacheCreationTokens: number;
92
+ costUsd: number;
93
+ }
73
94
  /** One row of the per-model breakdown. */
74
95
  interface ModelUsageRow {
75
96
  providerId: string;
@@ -140,4 +161,4 @@ interface MessageUsageRow {
140
161
  costSavedByCacheUsd: number;
141
162
  }
142
163
 
143
- export type { ApiKeyUsageRow, MessageUsageRow, ModelUsageRow, SessionCacheStats, UsageDateRange, UsageEventInput, UsageEventRecord, UsageQueryParams, UsageTotals };
164
+ export type { ApiKeyUsageRow, MessageUsageRow, ModelUsageRow, SessionCacheStats, UsageDateRange, UsageEventInput, UsageEventRecord, UsageQueryParams, UsageTimeBucket, UsageTimeSeriesBucket, UsageTotals };
@@ -70,6 +70,27 @@ interface UsageTotals {
70
70
  /** Number of events contributing to these totals. */
71
71
  eventCount: number;
72
72
  }
73
+ /** Granularity for a usage time-series query. `week` is NOT a bucket — a "week" view is a `day` bucket over a 7-day range. */
74
+ type UsageTimeBucket = 'hour' | 'day' | 'month';
75
+ /**
76
+ * One bucket of a usage time-series (trend chart). Buckets are query-time
77
+ * aggregations over the daemon's LOCAL-time boundaries and every bucket in the
78
+ * requested range is present (empty buckets are zero-filled), ascending by
79
+ * `bucketStartTs`.
80
+ */
81
+ interface UsageTimeSeriesBucket {
82
+ /** Unix-millis of the LOCAL-time bucket boundary (hour start / local midnight / local 1st-of-month). */
83
+ bucketStartTs: number;
84
+ /** Frozen locale-agnostic label from LOCAL parts: hour `MM-DD HH:00`, day `YYYY-MM-DD`, month `YYYY-MM`. */
85
+ label: string;
86
+ /** Event count in the bucket (0 for a zero-filled bucket). */
87
+ requests: number;
88
+ inputTokens: number;
89
+ outputTokens: number;
90
+ cacheReadTokens: number;
91
+ cacheCreationTokens: number;
92
+ costUsd: number;
93
+ }
73
94
  /** One row of the per-model breakdown. */
74
95
  interface ModelUsageRow {
75
96
  providerId: string;
@@ -140,4 +161,4 @@ interface MessageUsageRow {
140
161
  costSavedByCacheUsd: number;
141
162
  }
142
163
 
143
- export type { ApiKeyUsageRow, MessageUsageRow, ModelUsageRow, SessionCacheStats, UsageDateRange, UsageEventInput, UsageEventRecord, UsageQueryParams, UsageTotals };
164
+ export type { ApiKeyUsageRow, MessageUsageRow, ModelUsageRow, SessionCacheStats, UsageDateRange, UsageEventInput, UsageEventRecord, UsageQueryParams, UsageTimeBucket, UsageTimeSeriesBucket, UsageTotals };
@@ -0,0 +1,32 @@
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/voucher-types.ts
21
+ var voucher_types_exports = {};
22
+ __export(voucher_types_exports, {
23
+ DEFAULT_VOUCHER_CONFIG: () => DEFAULT_VOUCHER_CONFIG
24
+ });
25
+ module.exports = __toCommonJS(voucher_types_exports);
26
+ var DEFAULT_VOUCHER_CONFIG = {
27
+ enabled: false
28
+ };
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ DEFAULT_VOUCHER_CONFIG
32
+ });
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Voucher (redemption-card) contracts (voucher-redemption #9, design D2/D8).
3
+ *
4
+ * A voucher is a redeemable credit/renewal card layered on top of the outbound
5
+ * key-policy (#4): an admin generates a card (`CC_<entropy>`), a key-holder
6
+ * redeems it to raise their key's `totalCostLimitUsd` (credit) or extend its
7
+ * `expiresAt` (renewal). Dependency-light shapes shared across `@omnicross/*`:
8
+ *
9
+ * - `VoucherRecord` — the FROZEN stored card. It is a CREDENTIAL RECORD but holds
10
+ * NO plaintext code: only the sha256 `codeHash` (the redeem lookup key) + a
11
+ * short display `codePrefix`. The plaintext `CC_…` is returned ONCE at
12
+ * generation and NEVER persisted or logged. A secret-scan test asserts no
13
+ * `CC_` plaintext survives in a written record.
14
+ * - `VoucherGrant` — the ABSOLUTE target recorded on the card at redeem time so
15
+ * the apply step (`outboundApiKeysSetPolicy`) is idempotently re-appliable
16
+ * after a crash between the CAS flip and the apply (design D4).
17
+ * - `VoucherInfo` — the admin-safe DTO (prefix + status + value + caps only,
18
+ * NEVER the `codeHash`).
19
+ * - `VoucherConfig` — the `voucher` config segment. `enabled` default OFF ⇒ the
20
+ * redeem endpoint is inert + no key is ever mutated ⇒ byte-identical zero
21
+ * regression, purely additive on #4.
22
+ *
23
+ * @module voucher-types
24
+ */
25
+ /** A card either adds USD credit or extends the key's lifetime. */
26
+ type VoucherType = 'credit' | 'renewal';
27
+ /** Card lifecycle. A card leaves `unredeemed` exactly once (CAS, design D4). */
28
+ type VoucherStatus = 'unredeemed' | 'redeemed' | 'revoked';
29
+ /**
30
+ * The ABSOLUTE grant a redemption applies to a key (design D4/D5). Recorded on
31
+ * the voucher AT the CAS flip so re-applying it after an interrupted redeem is a
32
+ * no-op (idempotent to the absolute value → never double-spends). A `credit`
33
+ * card records `totalCostLimitUsd`; a `renewal` card records `expiresAt`.
34
+ */
35
+ interface VoucherGrant {
36
+ /** Absolute new `totalCostLimitUsd` for the key (credit cards). */
37
+ totalCostLimitUsd?: number;
38
+ /** Absolute new `expiresAt` (epoch ms) for the key (renewal cards). */
39
+ expiresAt?: number;
40
+ }
41
+ /**
42
+ * One stored redemption card (design D2, FROZEN). Holds a HASH of the code
43
+ * (never the plaintext) + a display prefix. The `granted*` fields are the
44
+ * absolute target recorded at redeem time (idempotent re-apply, design D4).
45
+ */
46
+ interface VoucherRecord {
47
+ /** Card id (independent of the code). */
48
+ id: string;
49
+ /** sha256 of the `CC_<entropy>` code — the redeem lookup key. NEVER plaintext. */
50
+ codeHash: string;
51
+ /** Short display prefix for the admin list (e.g. `CC_AB…`). NEVER the full code. */
52
+ codePrefix: string;
53
+ /** Credit (adds USD) or renewal (extends expiry). */
54
+ type: VoucherType;
55
+ /** `credit`: USD added to the key's `totalCostLimitUsd`. */
56
+ creditUsd?: number;
57
+ /** `renewal`: days added to the key's `expiresAt`. */
58
+ renewalDays?: number;
59
+ /** Anti-abuse cap on the RESULTING key `totalCostLimitUsd` (design D5). */
60
+ maxTotalCostLimitUsd?: number;
61
+ /** Anti-abuse cap on the RESULTING key lifetime, in days from now (design D5). */
62
+ maxExpiryDays?: number;
63
+ /** Lifecycle status. */
64
+ status: VoucherStatus;
65
+ /** Epoch ms the card was generated. */
66
+ createdAt: number;
67
+ /** Epoch ms the card was redeemed (set on the CAS flip). */
68
+ redeemedAt?: number;
69
+ /** The key id that redeemed the card (single-key binding). */
70
+ redeemedByKeyId?: string;
71
+ /**
72
+ * Whether the grant has been APPLIED to the key (design D4, revised). The CAS
73
+ * flip sets this `false`; the apply sets it `true` after a successful
74
+ * `outboundApiKeysSetPolicy`. `redeemed && grantApplied !== true` means "flipped
75
+ * but not (yet) applied" — the apply (of the recorded ABSOLUTE below) re-runs on
76
+ * the next redeem for the key, before that redeem computes anything. It is
77
+ * `grantApplied` that says "no work left"; the apply itself is idempotent
78
+ * (re-applying the same absolute is a no-op), so a crash between the apply and
79
+ * this mark never double-credits.
80
+ */
81
+ grantApplied?: boolean;
82
+ /**
83
+ * The recorded ABSOLUTE `totalCostLimitUsd` target (the intended final key
84
+ * value), computed at flip time from the CURRENT policy read INSIDE the per-key
85
+ * mutex. This is the AUTHORITATIVE apply source on BOTH the first pass and the
86
+ * reconcile/replay path — re-applying it is idempotent (never double-credits).
87
+ * Because redemptions for a key are serialized and a stranded card is reconciled
88
+ * before the next card computes, the recorded absolute is never stale.
89
+ */
90
+ grantedTotalCostLimitUsd?: number;
91
+ /** The recorded ABSOLUTE `expiresAt` target (see `grantedTotalCostLimitUsd`). */
92
+ grantedExpiresAt?: number;
93
+ /** Epoch ms the card was revoked. */
94
+ revokedAt?: number;
95
+ }
96
+ /**
97
+ * The admin-safe voucher DTO (design D2). NEVER carries the `codeHash` — the
98
+ * admin sees the display prefix + status + value + caps only. This is the ONLY
99
+ * projection an admin GET returns.
100
+ */
101
+ interface VoucherInfo {
102
+ id: string;
103
+ codePrefix: string;
104
+ type: VoucherType;
105
+ creditUsd?: number;
106
+ renewalDays?: number;
107
+ maxTotalCostLimitUsd?: number;
108
+ maxExpiryDays?: number;
109
+ status: VoucherStatus;
110
+ createdAt: number;
111
+ redeemedAt?: number;
112
+ redeemedByKeyId?: string;
113
+ grantApplied?: boolean;
114
+ grantedTotalCostLimitUsd?: number;
115
+ grantedExpiresAt?: number;
116
+ revokedAt?: number;
117
+ }
118
+ /**
119
+ * The one-time create result: `plaintextOnce` (the `CC_…` code) is shown exactly
120
+ * once at generation and never again — only its hash is stored (design D3).
121
+ */
122
+ interface VoucherCreated {
123
+ id: string;
124
+ codePrefix: string;
125
+ type: VoucherType;
126
+ createdAt: number;
127
+ /** The plaintext `CC_…` code — the ONLY time it crosses the wire. */
128
+ plaintextOnce: string;
129
+ }
130
+ /**
131
+ * The result a successful redeem returns to the key-holder (design D2). Reveals
132
+ * ONLY this key's own new balance/expiry — never any other card or key.
133
+ */
134
+ interface VoucherRedeemResult {
135
+ type: VoucherType;
136
+ /** The key's new absolute `totalCostLimitUsd` (credit cards). */
137
+ totalCostLimitUsd?: number;
138
+ /** The key's new absolute `expiresAt` (epoch ms) (renewal cards). */
139
+ expiresAt?: number;
140
+ }
141
+ /**
142
+ * The `voucher` config segment (design D8), normalized like `audit`/`billing`.
143
+ * `enabled` default FALSE ⇒ the redeem endpoint rejects + no admin generate ⇒ no
144
+ * key is ever mutated ⇒ byte-identical zero regression, purely additive on #4.
145
+ */
146
+ interface VoucherConfig {
147
+ /** Master switch; default FALSE (zero regression, inert product). */
148
+ enabled: boolean;
149
+ }
150
+ /** Frozen defaults for the `voucher` segment (SSOT). */
151
+ declare const DEFAULT_VOUCHER_CONFIG: VoucherConfig;
152
+
153
+ export { DEFAULT_VOUCHER_CONFIG, type VoucherConfig, type VoucherCreated, type VoucherGrant, type VoucherInfo, type VoucherRecord, type VoucherRedeemResult, type VoucherStatus, type VoucherType };
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Voucher (redemption-card) contracts (voucher-redemption #9, design D2/D8).
3
+ *
4
+ * A voucher is a redeemable credit/renewal card layered on top of the outbound
5
+ * key-policy (#4): an admin generates a card (`CC_<entropy>`), a key-holder
6
+ * redeems it to raise their key's `totalCostLimitUsd` (credit) or extend its
7
+ * `expiresAt` (renewal). Dependency-light shapes shared across `@omnicross/*`:
8
+ *
9
+ * - `VoucherRecord` — the FROZEN stored card. It is a CREDENTIAL RECORD but holds
10
+ * NO plaintext code: only the sha256 `codeHash` (the redeem lookup key) + a
11
+ * short display `codePrefix`. The plaintext `CC_…` is returned ONCE at
12
+ * generation and NEVER persisted or logged. A secret-scan test asserts no
13
+ * `CC_` plaintext survives in a written record.
14
+ * - `VoucherGrant` — the ABSOLUTE target recorded on the card at redeem time so
15
+ * the apply step (`outboundApiKeysSetPolicy`) is idempotently re-appliable
16
+ * after a crash between the CAS flip and the apply (design D4).
17
+ * - `VoucherInfo` — the admin-safe DTO (prefix + status + value + caps only,
18
+ * NEVER the `codeHash`).
19
+ * - `VoucherConfig` — the `voucher` config segment. `enabled` default OFF ⇒ the
20
+ * redeem endpoint is inert + no key is ever mutated ⇒ byte-identical zero
21
+ * regression, purely additive on #4.
22
+ *
23
+ * @module voucher-types
24
+ */
25
+ /** A card either adds USD credit or extends the key's lifetime. */
26
+ type VoucherType = 'credit' | 'renewal';
27
+ /** Card lifecycle. A card leaves `unredeemed` exactly once (CAS, design D4). */
28
+ type VoucherStatus = 'unredeemed' | 'redeemed' | 'revoked';
29
+ /**
30
+ * The ABSOLUTE grant a redemption applies to a key (design D4/D5). Recorded on
31
+ * the voucher AT the CAS flip so re-applying it after an interrupted redeem is a
32
+ * no-op (idempotent to the absolute value → never double-spends). A `credit`
33
+ * card records `totalCostLimitUsd`; a `renewal` card records `expiresAt`.
34
+ */
35
+ interface VoucherGrant {
36
+ /** Absolute new `totalCostLimitUsd` for the key (credit cards). */
37
+ totalCostLimitUsd?: number;
38
+ /** Absolute new `expiresAt` (epoch ms) for the key (renewal cards). */
39
+ expiresAt?: number;
40
+ }
41
+ /**
42
+ * One stored redemption card (design D2, FROZEN). Holds a HASH of the code
43
+ * (never the plaintext) + a display prefix. The `granted*` fields are the
44
+ * absolute target recorded at redeem time (idempotent re-apply, design D4).
45
+ */
46
+ interface VoucherRecord {
47
+ /** Card id (independent of the code). */
48
+ id: string;
49
+ /** sha256 of the `CC_<entropy>` code — the redeem lookup key. NEVER plaintext. */
50
+ codeHash: string;
51
+ /** Short display prefix for the admin list (e.g. `CC_AB…`). NEVER the full code. */
52
+ codePrefix: string;
53
+ /** Credit (adds USD) or renewal (extends expiry). */
54
+ type: VoucherType;
55
+ /** `credit`: USD added to the key's `totalCostLimitUsd`. */
56
+ creditUsd?: number;
57
+ /** `renewal`: days added to the key's `expiresAt`. */
58
+ renewalDays?: number;
59
+ /** Anti-abuse cap on the RESULTING key `totalCostLimitUsd` (design D5). */
60
+ maxTotalCostLimitUsd?: number;
61
+ /** Anti-abuse cap on the RESULTING key lifetime, in days from now (design D5). */
62
+ maxExpiryDays?: number;
63
+ /** Lifecycle status. */
64
+ status: VoucherStatus;
65
+ /** Epoch ms the card was generated. */
66
+ createdAt: number;
67
+ /** Epoch ms the card was redeemed (set on the CAS flip). */
68
+ redeemedAt?: number;
69
+ /** The key id that redeemed the card (single-key binding). */
70
+ redeemedByKeyId?: string;
71
+ /**
72
+ * Whether the grant has been APPLIED to the key (design D4, revised). The CAS
73
+ * flip sets this `false`; the apply sets it `true` after a successful
74
+ * `outboundApiKeysSetPolicy`. `redeemed && grantApplied !== true` means "flipped
75
+ * but not (yet) applied" — the apply (of the recorded ABSOLUTE below) re-runs on
76
+ * the next redeem for the key, before that redeem computes anything. It is
77
+ * `grantApplied` that says "no work left"; the apply itself is idempotent
78
+ * (re-applying the same absolute is a no-op), so a crash between the apply and
79
+ * this mark never double-credits.
80
+ */
81
+ grantApplied?: boolean;
82
+ /**
83
+ * The recorded ABSOLUTE `totalCostLimitUsd` target (the intended final key
84
+ * value), computed at flip time from the CURRENT policy read INSIDE the per-key
85
+ * mutex. This is the AUTHORITATIVE apply source on BOTH the first pass and the
86
+ * reconcile/replay path — re-applying it is idempotent (never double-credits).
87
+ * Because redemptions for a key are serialized and a stranded card is reconciled
88
+ * before the next card computes, the recorded absolute is never stale.
89
+ */
90
+ grantedTotalCostLimitUsd?: number;
91
+ /** The recorded ABSOLUTE `expiresAt` target (see `grantedTotalCostLimitUsd`). */
92
+ grantedExpiresAt?: number;
93
+ /** Epoch ms the card was revoked. */
94
+ revokedAt?: number;
95
+ }
96
+ /**
97
+ * The admin-safe voucher DTO (design D2). NEVER carries the `codeHash` — the
98
+ * admin sees the display prefix + status + value + caps only. This is the ONLY
99
+ * projection an admin GET returns.
100
+ */
101
+ interface VoucherInfo {
102
+ id: string;
103
+ codePrefix: string;
104
+ type: VoucherType;
105
+ creditUsd?: number;
106
+ renewalDays?: number;
107
+ maxTotalCostLimitUsd?: number;
108
+ maxExpiryDays?: number;
109
+ status: VoucherStatus;
110
+ createdAt: number;
111
+ redeemedAt?: number;
112
+ redeemedByKeyId?: string;
113
+ grantApplied?: boolean;
114
+ grantedTotalCostLimitUsd?: number;
115
+ grantedExpiresAt?: number;
116
+ revokedAt?: number;
117
+ }
118
+ /**
119
+ * The one-time create result: `plaintextOnce` (the `CC_…` code) is shown exactly
120
+ * once at generation and never again — only its hash is stored (design D3).
121
+ */
122
+ interface VoucherCreated {
123
+ id: string;
124
+ codePrefix: string;
125
+ type: VoucherType;
126
+ createdAt: number;
127
+ /** The plaintext `CC_…` code — the ONLY time it crosses the wire. */
128
+ plaintextOnce: string;
129
+ }
130
+ /**
131
+ * The result a successful redeem returns to the key-holder (design D2). Reveals
132
+ * ONLY this key's own new balance/expiry — never any other card or key.
133
+ */
134
+ interface VoucherRedeemResult {
135
+ type: VoucherType;
136
+ /** The key's new absolute `totalCostLimitUsd` (credit cards). */
137
+ totalCostLimitUsd?: number;
138
+ /** The key's new absolute `expiresAt` (epoch ms) (renewal cards). */
139
+ expiresAt?: number;
140
+ }
141
+ /**
142
+ * The `voucher` config segment (design D8), normalized like `audit`/`billing`.
143
+ * `enabled` default FALSE ⇒ the redeem endpoint rejects + no admin generate ⇒ no
144
+ * key is ever mutated ⇒ byte-identical zero regression, purely additive on #4.
145
+ */
146
+ interface VoucherConfig {
147
+ /** Master switch; default FALSE (zero regression, inert product). */
148
+ enabled: boolean;
149
+ }
150
+ /** Frozen defaults for the `voucher` segment (SSOT). */
151
+ declare const DEFAULT_VOUCHER_CONFIG: VoucherConfig;
152
+
153
+ export { DEFAULT_VOUCHER_CONFIG, type VoucherConfig, type VoucherCreated, type VoucherGrant, type VoucherInfo, type VoucherRecord, type VoucherRedeemResult, type VoucherStatus, type VoucherType };
@@ -0,0 +1,7 @@
1
+ // src/voucher-types.ts
2
+ var DEFAULT_VOUCHER_CONFIG = {
3
+ enabled: false
4
+ };
5
+ export {
6
+ DEFAULT_VOUCHER_CONFIG
7
+ };
@@ -0,0 +1,40 @@
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/webhook-types.ts
21
+ var webhook_types_exports = {};
22
+ __export(webhook_types_exports, {
23
+ WEBHOOK_DESTINATION_TYPES: () => WEBHOOK_DESTINATION_TYPES,
24
+ WEBHOOK_EVENT_KINDS: () => WEBHOOK_EVENT_KINDS
25
+ });
26
+ module.exports = __toCommonJS(webhook_types_exports);
27
+ var WEBHOOK_EVENT_KINDS = [
28
+ "account.recovery",
29
+ "account.anomaly",
30
+ "key.quotaWarning",
31
+ "key.quotaExceeded",
32
+ "server.error",
33
+ "test"
34
+ ];
35
+ var WEBHOOK_DESTINATION_TYPES = ["custom", "feishu"];
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ WEBHOOK_DESTINATION_TYPES,
39
+ WEBHOOK_EVENT_KINDS
40
+ });