@oxy.so/contracts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +16 -0
  3. package/dist/cjs/.tsbuildinfo +1 -0
  4. package/dist/cjs/accountGraph.js +489 -0
  5. package/dist/cjs/agency.js +439 -0
  6. package/dist/cjs/browserHub.js +215 -0
  7. package/dist/cjs/civic.js +163 -0
  8. package/dist/cjs/commonsSignIn.js +59 -0
  9. package/dist/cjs/deviceBoot.js +50 -0
  10. package/dist/cjs/deviceDirectory.js +189 -0
  11. package/dist/cjs/devicePairing.js +138 -0
  12. package/dist/cjs/deviceSession.js +164 -0
  13. package/dist/cjs/emailAgentContext.js +32 -0
  14. package/dist/cjs/followGraph.js +28 -0
  15. package/dist/cjs/identity.js +258 -0
  16. package/dist/cjs/inboxPush.js +24 -0
  17. package/dist/cjs/index.js +618 -0
  18. package/dist/cjs/inference/accountBilling.js +334 -0
  19. package/dist/cjs/inference/aliaModelRelease.js +262 -0
  20. package/dist/cjs/inference/attribution.js +106 -0
  21. package/dist/cjs/inference/catalogue.js +487 -0
  22. package/dist/cjs/inference/entitlement.js +217 -0
  23. package/dist/cjs/inference/errors.js +309 -0
  24. package/dist/cjs/inference/identifiers.js +224 -0
  25. package/dist/cjs/inference/inbox.js +105 -0
  26. package/dist/cjs/inference/modelDocumentation.js +433 -0
  27. package/dist/cjs/inference/money.js +188 -0
  28. package/dist/cjs/inference/priceVersion.js +110 -0
  29. package/dist/cjs/inference/providerConnection.js +455 -0
  30. package/dist/cjs/inference/request.js +477 -0
  31. package/dist/cjs/inference/routingPolicy.js +318 -0
  32. package/dist/cjs/inference/streamEvents.js +258 -0
  33. package/dist/cjs/inference/usage.js +329 -0
  34. package/dist/cjs/inference/version.js +105 -0
  35. package/dist/cjs/keyRecovery.js +91 -0
  36. package/dist/cjs/keyRotation.js +75 -0
  37. package/dist/cjs/links.js +68 -0
  38. package/dist/cjs/moderationReputation.js +298 -0
  39. package/dist/cjs/oauth.js +66 -0
  40. package/dist/cjs/oxyRecordTypes.js +71 -0
  41. package/dist/cjs/protocol.js +53 -0
  42. package/dist/cjs/recommendations.js +168 -0
  43. package/dist/cjs/reputation.js +297 -0
  44. package/dist/cjs/sessionStatus.js +121 -0
  45. package/dist/cjs/transparency.js +89 -0
  46. package/dist/cjs/updates.js +252 -0
  47. package/dist/cjs/userInvalidation.js +89 -0
  48. package/dist/cjs/userResponse.js +245 -0
  49. package/dist/cjs/username.js +290 -0
  50. package/dist/cjs/webauthn.js +71 -0
  51. package/dist/esm/.tsbuildinfo +1 -0
  52. package/dist/esm/accountGraph.js +480 -0
  53. package/dist/esm/agency.js +436 -0
  54. package/dist/esm/browserHub.js +212 -0
  55. package/dist/esm/civic.js +160 -0
  56. package/dist/esm/commonsSignIn.js +56 -0
  57. package/dist/esm/deviceBoot.js +47 -0
  58. package/dist/esm/deviceDirectory.js +186 -0
  59. package/dist/esm/devicePairing.js +135 -0
  60. package/dist/esm/deviceSession.js +161 -0
  61. package/dist/esm/emailAgentContext.js +29 -0
  62. package/dist/esm/followGraph.js +27 -0
  63. package/dist/esm/identity.js +255 -0
  64. package/dist/esm/inboxPush.js +21 -0
  65. package/dist/esm/index.js +172 -0
  66. package/dist/esm/inference/accountBilling.js +331 -0
  67. package/dist/esm/inference/aliaModelRelease.js +259 -0
  68. package/dist/esm/inference/attribution.js +103 -0
  69. package/dist/esm/inference/catalogue.js +484 -0
  70. package/dist/esm/inference/entitlement.js +214 -0
  71. package/dist/esm/inference/errors.js +306 -0
  72. package/dist/esm/inference/identifiers.js +221 -0
  73. package/dist/esm/inference/inbox.js +102 -0
  74. package/dist/esm/inference/modelDocumentation.js +430 -0
  75. package/dist/esm/inference/money.js +185 -0
  76. package/dist/esm/inference/priceVersion.js +107 -0
  77. package/dist/esm/inference/providerConnection.js +452 -0
  78. package/dist/esm/inference/request.js +474 -0
  79. package/dist/esm/inference/routingPolicy.js +315 -0
  80. package/dist/esm/inference/streamEvents.js +255 -0
  81. package/dist/esm/inference/usage.js +326 -0
  82. package/dist/esm/inference/version.js +102 -0
  83. package/dist/esm/keyRecovery.js +88 -0
  84. package/dist/esm/keyRotation.js +72 -0
  85. package/dist/esm/links.js +65 -0
  86. package/dist/esm/moderationReputation.js +295 -0
  87. package/dist/esm/oauth.js +63 -0
  88. package/dist/esm/oxyRecordTypes.js +68 -0
  89. package/dist/esm/protocol.js +50 -0
  90. package/dist/esm/recommendations.js +165 -0
  91. package/dist/esm/reputation.js +293 -0
  92. package/dist/esm/sessionStatus.js +118 -0
  93. package/dist/esm/transparency.js +86 -0
  94. package/dist/esm/updates.js +249 -0
  95. package/dist/esm/userInvalidation.js +85 -0
  96. package/dist/esm/userResponse.js +240 -0
  97. package/dist/esm/username.js +283 -0
  98. package/dist/esm/webauthn.js +68 -0
  99. package/dist/types/.tsbuildinfo +1 -0
  100. package/dist/types/accountGraph.d.ts +378 -0
  101. package/dist/types/agency.d.ts +2162 -0
  102. package/dist/types/browserHub.d.ts +856 -0
  103. package/dist/types/civic.d.ts +338 -0
  104. package/dist/types/commonsSignIn.d.ts +58 -0
  105. package/dist/types/deviceBoot.d.ts +74 -0
  106. package/dist/types/deviceDirectory.d.ts +1317 -0
  107. package/dist/types/devicePairing.d.ts +130 -0
  108. package/dist/types/deviceSession.d.ts +411 -0
  109. package/dist/types/emailAgentContext.d.ts +248 -0
  110. package/dist/types/followGraph.d.ts +150 -0
  111. package/dist/types/identity.d.ts +402 -0
  112. package/dist/types/inboxPush.d.ts +30 -0
  113. package/dist/types/index.d.ts +100 -0
  114. package/dist/types/inference/accountBilling.d.ts +738 -0
  115. package/dist/types/inference/aliaModelRelease.d.ts +609 -0
  116. package/dist/types/inference/attribution.d.ts +176 -0
  117. package/dist/types/inference/catalogue.d.ts +1618 -0
  118. package/dist/types/inference/entitlement.d.ts +519 -0
  119. package/dist/types/inference/errors.d.ts +242 -0
  120. package/dist/types/inference/identifiers.d.ts +182 -0
  121. package/dist/types/inference/inbox.d.ts +374 -0
  122. package/dist/types/inference/modelDocumentation.d.ts +1603 -0
  123. package/dist/types/inference/money.d.ts +185 -0
  124. package/dist/types/inference/priceVersion.d.ts +182 -0
  125. package/dist/types/inference/providerConnection.d.ts +968 -0
  126. package/dist/types/inference/request.d.ts +2800 -0
  127. package/dist/types/inference/routingPolicy.d.ts +616 -0
  128. package/dist/types/inference/streamEvents.d.ts +950 -0
  129. package/dist/types/inference/usage.d.ts +1164 -0
  130. package/dist/types/inference/version.d.ts +102 -0
  131. package/dist/types/keyRecovery.d.ts +138 -0
  132. package/dist/types/keyRotation.d.ts +103 -0
  133. package/dist/types/links.d.ts +96 -0
  134. package/dist/types/moderationReputation.d.ts +487 -0
  135. package/dist/types/oauth.d.ts +86 -0
  136. package/dist/types/oxyRecordTypes.d.ts +62 -0
  137. package/dist/types/protocol.d.ts +86 -0
  138. package/dist/types/recommendations.d.ts +542 -0
  139. package/dist/types/reputation.d.ts +457 -0
  140. package/dist/types/sessionStatus.d.ts +231 -0
  141. package/dist/types/transparency.d.ts +392 -0
  142. package/dist/types/updates.d.ts +545 -0
  143. package/dist/types/userInvalidation.d.ts +94 -0
  144. package/dist/types/userResponse.d.ts +1706 -0
  145. package/dist/types/username.d.ts +265 -0
  146. package/dist/types/webauthn.d.ts +77 -0
  147. package/package.json +87 -0
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * Price versions — the immutable snapshots customer pricing is quoted and
4
+ * settled against.
5
+ *
6
+ * A price is never edited in place. A change publishes a NEW version that
7
+ * supersedes the old one, and every settled receipt keeps the id of the version
8
+ * it was priced with. That is what makes an invoice reproducible a year later:
9
+ * the receipt does not say "3.00 per million tokens", it says "priced under
10
+ * `pv_2026_08`", and that version still exists, unchanged, with its own
11
+ * effective window.
12
+ *
13
+ * Prices are exact decimal strings (see `money.ts`), never floats, and they are
14
+ * quoted per unit. The amount a customer owes is computed from them and is
15
+ * carried in the same exact form, so no step of the calculation passes through
16
+ * a representation that cannot hold the value.
17
+ *
18
+ * Decided in: docs/adr/0009-usage-reservation-and-settlement.md.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.priceSnapshotSchema = exports.priceVersionSchema = exports.priceVersionStatusSchema = void 0;
22
+ const zod_1 = require("zod");
23
+ const identifiers_1 = require("./identifiers");
24
+ const money_1 = require("./money");
25
+ /**
26
+ * Lifecycle of a price version.
27
+ *
28
+ * `draft` is quotable in Console previews but may never price a receipt;
29
+ * `active` is what live requests are priced with; `superseded` priced receipts
30
+ * in the past and still resolves for them forever.
31
+ */
32
+ exports.priceVersionStatusSchema = zod_1.z.enum(['draft', 'active', 'superseded']);
33
+ /**
34
+ * A published set of customer prices for one model reference on one provider.
35
+ *
36
+ * Scoped to a `(modelReference, provider)` pair rather than to a model alone
37
+ * because the same model costs different amounts on different providers, and a
38
+ * receipt has to be reproducible against the route that actually served it.
39
+ */
40
+ exports.priceVersionSchema = zod_1.z
41
+ .object({
42
+ /** See `version.ts`: served on its own by the catalogue, so it is versioned. */
43
+ schemaVersion: zod_1.z.literal(1),
44
+ priceVersionId: zod_1.z.string().min(1).max(128),
45
+ status: exports.priceVersionStatusSchema,
46
+ modelReference: identifiers_1.modelReferenceSchema,
47
+ provider: identifiers_1.inferenceProviderSlugSchema,
48
+ currency: money_1.currencyCodeSchema,
49
+ unitPrices: zod_1.z.array(money_1.unitPriceSchema).min(1),
50
+ effectiveFrom: identifiers_1.inferenceTimestampSchema,
51
+ /** Absent while this version is the current one. */
52
+ effectiveUntil: identifiers_1.inferenceTimestampSchema.optional(),
53
+ /** The version this one replaced, absent for the first version of a route. */
54
+ supersedesPriceVersionId: zod_1.z.string().min(1).max(128).optional(),
55
+ createdAt: identifiers_1.inferenceTimestampSchema,
56
+ })
57
+ .superRefine((priceVersion, ctx) => {
58
+ const units = priceVersion.unitPrices.map((price) => price.unit);
59
+ if (new Set(units).size !== units.length) {
60
+ ctx.addIssue({
61
+ code: zod_1.z.ZodIssueCode.custom,
62
+ path: ['unitPrices'],
63
+ message: 'a unit may be priced only once per price version',
64
+ });
65
+ }
66
+ for (const [index, price] of priceVersion.unitPrices.entries()) {
67
+ if (price.currency !== priceVersion.currency) {
68
+ ctx.addIssue({
69
+ code: zod_1.z.ZodIssueCode.custom,
70
+ path: ['unitPrices', index, 'currency'],
71
+ message: 'every unit price must be quoted in the price version currency',
72
+ });
73
+ }
74
+ }
75
+ // Compared as instants, not as strings: `…T00:00:00Z` and `…T00:00:00.000Z`
76
+ // are the same moment and sort differently as text.
77
+ if (priceVersion.effectiveUntil !== undefined &&
78
+ Date.parse(priceVersion.effectiveUntil) <= Date.parse(priceVersion.effectiveFrom)) {
79
+ ctx.addIssue({
80
+ code: zod_1.z.ZodIssueCode.custom,
81
+ path: ['effectiveUntil'],
82
+ message: 'a price version must stop applying after it started applying',
83
+ });
84
+ }
85
+ // A superseded version priced requests during a window that has closed. Left
86
+ // open, it is indistinguishable from the current one when a receipt is
87
+ // re-priced years later — which is the one job this record exists to do.
88
+ if (priceVersion.status === 'superseded' && priceVersion.effectiveUntil === undefined) {
89
+ ctx.addIssue({
90
+ code: zod_1.z.ZodIssueCode.custom,
91
+ path: ['effectiveUntil'],
92
+ message: 'a superseded price version must record when it stopped applying',
93
+ });
94
+ }
95
+ });
96
+ /**
97
+ * The price snapshot a settled receipt keeps.
98
+ *
99
+ * The unit prices are COPIED onto the receipt, not just referenced, so a receipt
100
+ * remains readable even if the price version record is later archived, and so
101
+ * that a mistake in the copy is visible as a disagreement with the version it
102
+ * names rather than silently invisible.
103
+ */
104
+ exports.priceSnapshotSchema = zod_1.z
105
+ .object({
106
+ priceVersionId: zod_1.z.string().min(1).max(128),
107
+ currency: money_1.currencyCodeSchema,
108
+ unitPrices: zod_1.z.array(money_1.unitPriceSchema).min(1),
109
+ })
110
+ .strict();
@@ -0,0 +1,455 @@
1
+ "use strict";
2
+ /**
3
+ * BYOK provider connections — the metadata Oxy holds about a customer's own
4
+ * upstream provider credential.
5
+ *
6
+ * The credential itself is NOT here and cannot be put here. This shape carries
7
+ * an opaque Kaana credential handle, its exact revision and validation state.
8
+ * Three mechanisms
9
+ * make that structural rather than a convention somebody must remember:
10
+ *
11
+ * - The object is `.strict()`. A producer that attaches `apiKey`, `secret`,
12
+ * `token`, `privateKey` or `headers` fails the parse. Nothing is silently
13
+ * stripped, because a stripped field is one that still exists upstream of
14
+ * the parse, in a log line or an error report.
15
+ * - No prefix or digest derived from the credential exists in this contract;
16
+ * even a partial value can make a short credential recoverable by guessing.
17
+ * - `credentialHandle` is an opaque, closed-format identifier minted by Kaana.
18
+ * Oxy cannot resolve it and never stores either plaintext or ciphertext.
19
+ *
20
+ * BYOK does not move the billing relationship: the upstream provider bills the
21
+ * customer's own account directly, and Oxy charges only its platform fee. The
22
+ * record says so explicitly so a receipt against a BYOK route can be read
23
+ * correctly without consulting anything else.
24
+ *
25
+ * Decided in: issue #972 workstream 10.
26
+ */
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.providerConnectionSchema = exports.providerConnectionStatusSchema = exports.providerConnectionValidationSchema = exports.providerCredentialCustodyStateSchema = exports.providerCredentialValidationDeploymentSchema = exports.providerCredentialValidationOperationSchema = exports.kaanaCredentialValidationOutcomeSchema = exports.kaanaCredentialValidationFailureCodeSchema = exports.kaanaCredentialValidationOutcomeStateSchema = exports.kaanaCredentialValidationTaskSchema = exports.kaanaCredentialOutcomeSchema = exports.kaanaCredentialConflictOutcomeSchema = exports.kaanaCredentialAppliedOutcomeSchema = exports.kaanaCredentialOutcomeRequestSchema = exports.kaanaCredentialRevokeOutcomeRequestSchema = exports.kaanaCredentialRotateOutcomeRequestSchema = exports.kaanaCredentialCreateOutcomeRequestSchema = exports.kaanaCredentialMutationSchema = exports.kaanaCredentialRevokeMutationSchema = exports.kaanaCredentialRotateMutationSchema = exports.kaanaCredentialCreateMutationSchema = exports.kaanaCredentialIdentitySchema = exports.kaanaCredentialOperationActionSchema = exports.kaanaCredentialOperationIdSchema = exports.kaanaCredentialHandleSchema = exports.providerConnectionScopeSchema = void 0;
29
+ const zod_1 = require("zod");
30
+ const identifiers_1 = require("./identifiers");
31
+ /**
32
+ * How widely a connection applies.
33
+ *
34
+ * In the unified account graph a project IS an account, so `account` and
35
+ * `project` differ by INHERITANCE, not by id space: an `account` connection is
36
+ * inherited by every descendant project and application, a `project` one
37
+ * applies to that project account alone, and an `application` one to a single
38
+ * application. Recording which the customer chose is what makes a later
39
+ * "why did this app use that key" answerable.
40
+ */
41
+ exports.providerConnectionScopeSchema = zod_1.z.discriminatedUnion('kind', [
42
+ zod_1.z.object({ kind: zod_1.z.literal('account'), accountId: identifiers_1.oxyAccountIdSchema }).strict(),
43
+ zod_1.z.object({ kind: zod_1.z.literal('project'), accountId: identifiers_1.oxyAccountIdSchema }).strict(),
44
+ zod_1.z
45
+ .object({
46
+ kind: zod_1.z.literal('application'),
47
+ accountId: identifiers_1.oxyAccountIdSchema,
48
+ applicationId: identifiers_1.oxyApplicationIdSchema,
49
+ })
50
+ .strict(),
51
+ ]);
52
+ /** Opaque reference minted by Kaana. It is not a KMS/Vault/SSM locator. */
53
+ exports.kaanaCredentialHandleSchema = zod_1.z
54
+ .string()
55
+ .regex(/^kcred_[a-z2-7]{26}$/, 'a Kaana credential handle is kcred_ plus 26 base32 characters');
56
+ /** Oxy-minted, case-sensitive replay identity for one exact Kaana mutation. */
57
+ exports.kaanaCredentialOperationIdSchema = zod_1.z
58
+ .string()
59
+ .regex(/^[A-Za-z0-9_-]{1,128}$/, 'a Kaana credential operation id is 1-128 opaque characters');
60
+ exports.kaanaCredentialOperationActionSchema = zod_1.z.enum(['create', 'rotate', 'revoke']);
61
+ /** Exact immutable Oxy identity repeated by both mutation and reconciliation. */
62
+ exports.kaanaCredentialIdentitySchema = zod_1.z
63
+ .object({
64
+ provider: identifiers_1.inferenceProviderSlugSchema,
65
+ ownerAccountId: zod_1.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
66
+ connectionId: zod_1.z.string().regex(/^[A-Za-z0-9_-]{1,128}$/),
67
+ environment: identifiers_1.inferenceEnvironmentSchema,
68
+ })
69
+ .strict();
70
+ const kaanaCredentialOperationActorSchema = zod_1.z
71
+ .string()
72
+ .min(1)
73
+ .refine((value) => new TextEncoder().encode(value).byteLength <= 256 &&
74
+ value === value.trim() &&
75
+ !/[\r\n]/.test(value), {
76
+ message: 'a credential operation actor is one trimmed line of at most 256 bytes',
77
+ });
78
+ const base64Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
79
+ /**
80
+ * Decode only enough of a strict base64 value to prove every output byte is
81
+ * visible ASCII. Keeping this implementation local avoids a Node Buffer or
82
+ * browser atob dependency in the universal contracts package.
83
+ */
84
+ function isVisibleASCIIProviderCredential(value) {
85
+ const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;
86
+ const decodedLength = (value.length / 4) * 3 - padding;
87
+ if (decodedLength < 1 || decodedLength > 4096)
88
+ return false;
89
+ for (let offset = 0, output = 0; offset < value.length; offset += 4, output += 3) {
90
+ const first = base64Alphabet.indexOf(value[offset] ?? '');
91
+ const second = base64Alphabet.indexOf(value[offset + 1] ?? '');
92
+ const third = value[offset + 2] === '=' ? 0 : base64Alphabet.indexOf(value[offset + 2] ?? '');
93
+ const fourth = value[offset + 3] === '=' ? 0 : base64Alphabet.indexOf(value[offset + 3] ?? '');
94
+ if (first < 0 || second < 0 || third < 0 || fourth < 0)
95
+ return false;
96
+ const finalQuartet = offset + 4 === value.length;
97
+ if (finalQuartet &&
98
+ ((padding === 2 && (second & 0x0f) !== 0) ||
99
+ (padding === 1 && (third & 0x03) !== 0))) {
100
+ return false;
101
+ }
102
+ const packed = (first << 18) | (second << 12) | (third << 6) | fourth;
103
+ const bytes = [(packed >> 16) & 0xff, (packed >> 8) & 0xff, packed & 0xff];
104
+ const count = Math.min(3, decodedLength - output);
105
+ for (let index = 0; index < count; index += 1) {
106
+ const byte = bytes[index];
107
+ if (byte === undefined || byte < 0x21 || byte > 0x7e)
108
+ return false;
109
+ }
110
+ }
111
+ return true;
112
+ }
113
+ const kaanaCredentialSecretBase64Schema = zod_1.z
114
+ .string()
115
+ .min(1)
116
+ .max(8192)
117
+ .regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/)
118
+ .refine(isVisibleASCIIProviderCredential, {
119
+ message: 'a decoded provider credential is 1-4096 visible ASCII bytes',
120
+ });
121
+ exports.kaanaCredentialCreateMutationSchema = exports.kaanaCredentialIdentitySchema
122
+ .extend({
123
+ schemaVersion: zod_1.z.literal(1),
124
+ action: zod_1.z.literal('create'),
125
+ operationId: exports.kaanaCredentialOperationIdSchema,
126
+ operationActor: kaanaCredentialOperationActorSchema,
127
+ secretBase64: kaanaCredentialSecretBase64Schema,
128
+ })
129
+ .strict();
130
+ exports.kaanaCredentialRotateMutationSchema = exports.kaanaCredentialIdentitySchema
131
+ .extend({
132
+ schemaVersion: zod_1.z.literal(1),
133
+ action: zod_1.z.literal('rotate'),
134
+ operationId: exports.kaanaCredentialOperationIdSchema,
135
+ operationActor: kaanaCredentialOperationActorSchema,
136
+ credentialHandle: exports.kaanaCredentialHandleSchema,
137
+ expectedRevision: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER - 1),
138
+ secretBase64: kaanaCredentialSecretBase64Schema,
139
+ })
140
+ .strict();
141
+ exports.kaanaCredentialRevokeMutationSchema = exports.kaanaCredentialIdentitySchema
142
+ .extend({
143
+ schemaVersion: zod_1.z.literal(1),
144
+ action: zod_1.z.literal('revoke'),
145
+ operationId: exports.kaanaCredentialOperationIdSchema,
146
+ operationActor: kaanaCredentialOperationActorSchema,
147
+ credentialHandle: exports.kaanaCredentialHandleSchema,
148
+ expectedRevision: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER - 1),
149
+ })
150
+ .strict();
151
+ exports.kaanaCredentialMutationSchema = zod_1.z.discriminatedUnion('action', [
152
+ exports.kaanaCredentialCreateMutationSchema,
153
+ exports.kaanaCredentialRotateMutationSchema,
154
+ exports.kaanaCredentialRevokeMutationSchema,
155
+ ]);
156
+ exports.kaanaCredentialCreateOutcomeRequestSchema = exports.kaanaCredentialIdentitySchema
157
+ .extend({
158
+ schemaVersion: zod_1.z.literal(1),
159
+ action: zod_1.z.literal('create'),
160
+ operationId: exports.kaanaCredentialOperationIdSchema,
161
+ })
162
+ .strict();
163
+ exports.kaanaCredentialRotateOutcomeRequestSchema = exports.kaanaCredentialIdentitySchema
164
+ .extend({
165
+ schemaVersion: zod_1.z.literal(1),
166
+ action: zod_1.z.literal('rotate'),
167
+ operationId: exports.kaanaCredentialOperationIdSchema,
168
+ credentialHandle: exports.kaanaCredentialHandleSchema,
169
+ expectedRevision: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER - 1),
170
+ })
171
+ .strict();
172
+ exports.kaanaCredentialRevokeOutcomeRequestSchema = exports.kaanaCredentialIdentitySchema
173
+ .extend({
174
+ schemaVersion: zod_1.z.literal(1),
175
+ action: zod_1.z.literal('revoke'),
176
+ operationId: exports.kaanaCredentialOperationIdSchema,
177
+ credentialHandle: exports.kaanaCredentialHandleSchema,
178
+ expectedRevision: zod_1.z.number().int().positive().max(Number.MAX_SAFE_INTEGER - 1),
179
+ })
180
+ .strict();
181
+ exports.kaanaCredentialOutcomeRequestSchema = zod_1.z.discriminatedUnion('action', [
182
+ exports.kaanaCredentialCreateOutcomeRequestSchema,
183
+ exports.kaanaCredentialRotateOutcomeRequestSchema,
184
+ exports.kaanaCredentialRevokeOutcomeRequestSchema,
185
+ ]);
186
+ exports.kaanaCredentialAppliedOutcomeSchema = zod_1.z
187
+ .object({
188
+ schemaVersion: zod_1.z.literal(1),
189
+ operationId: exports.kaanaCredentialOperationIdSchema,
190
+ action: exports.kaanaCredentialOperationActionSchema,
191
+ status: zod_1.z.literal('applied'),
192
+ credentialHandle: exports.kaanaCredentialHandleSchema,
193
+ revision: zod_1.z.number().int().positive().safe(),
194
+ })
195
+ .strict();
196
+ exports.kaanaCredentialConflictOutcomeSchema = zod_1.z
197
+ .object({
198
+ schemaVersion: zod_1.z.literal(1),
199
+ operationId: exports.kaanaCredentialOperationIdSchema,
200
+ action: exports.kaanaCredentialOperationActionSchema,
201
+ status: zod_1.z.literal('conflict'),
202
+ })
203
+ .strict();
204
+ exports.kaanaCredentialOutcomeSchema = zod_1.z.discriminatedUnion('status', [
205
+ exports.kaanaCredentialAppliedOutcomeSchema,
206
+ exports.kaanaCredentialConflictOutcomeSchema,
207
+ ]);
208
+ /**
209
+ * One separately authenticated check of a quarantined BYOK generation.
210
+ *
211
+ * This is deliberately not an inference request. It carries no prompt, user
212
+ * response, routing policy or billing principal, and it can select only one
213
+ * exact Kaana deployment plus one exact credential generation.
214
+ */
215
+ exports.kaanaCredentialValidationTaskSchema = exports.kaanaCredentialIdentitySchema
216
+ .extend({
217
+ schemaVersion: zod_1.z.literal(1),
218
+ operationId: exports.kaanaCredentialOperationIdSchema,
219
+ applicationId: identifiers_1.oxyApplicationIdSchema,
220
+ credentialHandle: exports.kaanaCredentialHandleSchema,
221
+ credentialRevision: zod_1.z.number().int().positive().safe(),
222
+ deploymentId: identifiers_1.deploymentIdSchema,
223
+ })
224
+ .strict();
225
+ exports.kaanaCredentialValidationOutcomeStateSchema = zod_1.z.enum([
226
+ 'pending',
227
+ 'valid',
228
+ 'invalid',
229
+ 'inconclusive',
230
+ ]);
231
+ exports.kaanaCredentialValidationFailureCodeSchema = zod_1.z.enum([
232
+ 'unauthorized',
233
+ 'forbidden',
234
+ 'not_found',
235
+ 'rate_limited',
236
+ 'network',
237
+ 'unknown',
238
+ ]);
239
+ /**
240
+ * Durable result for one exact validation operation. `inconclusive` is a
241
+ * terminal answer about the attempt, never evidence that the credential is
242
+ * invalid; Oxy leaves the generation quarantined and may start a new exact
243
+ * operation. Kaana reports terminal outcomes through its service principal.
244
+ */
245
+ exports.kaanaCredentialValidationOutcomeSchema = exports.kaanaCredentialValidationTaskSchema
246
+ .extend({
247
+ state: exports.kaanaCredentialValidationOutcomeStateSchema,
248
+ failureCode: exports.kaanaCredentialValidationFailureCodeSchema.optional(),
249
+ })
250
+ .strict()
251
+ .superRefine((outcome, ctx) => {
252
+ if ((outcome.state === 'pending' || outcome.state === 'valid') &&
253
+ outcome.failureCode !== undefined) {
254
+ ctx.addIssue({
255
+ code: zod_1.z.ZodIssueCode.custom,
256
+ path: ['failureCode'],
257
+ message: 'a valid credential validation carries no failure code',
258
+ });
259
+ }
260
+ if ((outcome.state === 'invalid' || outcome.state === 'inconclusive') &&
261
+ outcome.failureCode === undefined) {
262
+ ctx.addIssue({
263
+ code: zod_1.z.ZodIssueCode.custom,
264
+ path: ['failureCode'],
265
+ message: 'a failed credential validation must state its closed failure code',
266
+ });
267
+ }
268
+ if (outcome.state === 'invalid' && outcome.failureCode !== 'unauthorized') {
269
+ ctx.addIssue({
270
+ code: zod_1.z.ZodIssueCode.custom,
271
+ path: ['failureCode'],
272
+ message: 'only a provider authentication refusal proves invalidity',
273
+ });
274
+ }
275
+ if (outcome.state === 'inconclusive' && outcome.failureCode === 'unauthorized') {
276
+ ctx.addIssue({
277
+ code: zod_1.z.ZodIssueCode.custom,
278
+ path: ['failureCode'],
279
+ message: 'an explicit authentication refusal is invalid, not inconclusive',
280
+ });
281
+ }
282
+ });
283
+ /**
284
+ * Customer-safe view of one explicit bootstrap attempt.
285
+ *
286
+ * `deploymentId` is the exact Oxy catalogue row selected by the customer. The
287
+ * internal Kaana route id remains protected; Oxy binds the two in its durable
288
+ * ledger and signs the latter to Kaana.
289
+ */
290
+ exports.providerCredentialValidationOperationSchema = zod_1.z
291
+ .object({
292
+ schemaVersion: zod_1.z.literal(1),
293
+ operationId: exports.kaanaCredentialOperationIdSchema,
294
+ connectionId: zod_1.z.string().min(1).max(128),
295
+ applicationId: identifiers_1.oxyApplicationIdSchema,
296
+ deploymentId: identifiers_1.deploymentIdSchema,
297
+ state: exports.kaanaCredentialValidationOutcomeStateSchema,
298
+ failureCode: exports.kaanaCredentialValidationFailureCodeSchema.optional(),
299
+ createdAt: identifiers_1.inferenceTimestampSchema,
300
+ completedAt: identifiers_1.inferenceTimestampSchema.optional(),
301
+ })
302
+ .strict()
303
+ .superRefine((operation, ctx) => {
304
+ const terminal = operation.state !== 'pending';
305
+ if (terminal !== (operation.completedAt !== undefined)) {
306
+ ctx.addIssue({
307
+ code: zod_1.z.ZodIssueCode.custom,
308
+ path: ['completedAt'],
309
+ message: 'only a terminal validation operation has a completion time',
310
+ });
311
+ }
312
+ if ((operation.state === 'pending' || operation.state === 'valid') &&
313
+ operation.failureCode !== undefined) {
314
+ ctx.addIssue({
315
+ code: zod_1.z.ZodIssueCode.custom,
316
+ path: ['failureCode'],
317
+ message: 'pending and valid validation operations carry no failure code',
318
+ });
319
+ }
320
+ if ((operation.state === 'invalid' || operation.state === 'inconclusive') &&
321
+ operation.failureCode === undefined) {
322
+ ctx.addIssue({
323
+ code: zod_1.z.ZodIssueCode.custom,
324
+ path: ['failureCode'],
325
+ message: 'a failed validation operation must state its closed failure code',
326
+ });
327
+ }
328
+ if (operation.state === 'invalid' && operation.failureCode !== 'unauthorized') {
329
+ ctx.addIssue({
330
+ code: zod_1.z.ZodIssueCode.custom,
331
+ path: ['failureCode'],
332
+ message: 'only a provider authentication refusal proves invalidity',
333
+ });
334
+ }
335
+ if (operation.state === 'inconclusive' && operation.failureCode === 'unauthorized') {
336
+ ctx.addIssue({
337
+ code: zod_1.z.ZodIssueCode.custom,
338
+ path: ['failureCode'],
339
+ message: 'an explicit authentication refusal is invalid, not inconclusive',
340
+ });
341
+ }
342
+ });
343
+ /** Exact customer-selectable catalogue ids; no internal Kaana route is exposed. */
344
+ exports.providerCredentialValidationDeploymentSchema = zod_1.z
345
+ .object({ deploymentId: identifiers_1.deploymentIdSchema })
346
+ .strict();
347
+ /**
348
+ * Oxy's view of the cross-service mutation. Only `ready` may be routed.
349
+ * `reconcile` is the fail-closed state after an outcome could not be proven.
350
+ */
351
+ exports.providerCredentialCustodyStateSchema = zod_1.z.enum([
352
+ 'pending',
353
+ 'ready',
354
+ 'reconcile',
355
+ 'revoked',
356
+ ]);
357
+ /** Why a credential check failed, as a closed set the Console can render. */
358
+ exports.providerConnectionValidationSchema = zod_1.z
359
+ .object({
360
+ state: zod_1.z.enum(['unvalidated', 'valid', 'invalid', 'expired']),
361
+ lastValidatedAt: identifiers_1.inferenceTimestampSchema.optional(),
362
+ /** Required when `invalid`: a failure nobody can act on is not a result. */
363
+ failureCode: zod_1.z
364
+ .enum(['unauthorized', 'forbidden', 'not_found', 'rate_limited', 'network', 'unknown'])
365
+ .optional(),
366
+ })
367
+ .strict();
368
+ /**
369
+ * Lifecycle of a connection. `pending_validation` is quarantined from normal
370
+ * serving, `revoked` is terminal, and `disabled` is reversible.
371
+ */
372
+ exports.providerConnectionStatusSchema = zod_1.z.enum([
373
+ 'pending_validation',
374
+ 'active',
375
+ 'disabled',
376
+ 'revoked',
377
+ ]);
378
+ /**
379
+ * A customer's provider connection, without secrets.
380
+ *
381
+ * This is the whole of what Oxy stores, and the whole of what the data plane
382
+ * is given.
383
+ * Resolving the opaque handle to plaintext happens only inside Kaana inference.
384
+ */
385
+ exports.providerConnectionSchema = zod_1.z
386
+ .object({
387
+ /** See `version.ts`: exchanged with the data plane and rendered by Console. */
388
+ schemaVersion: zod_1.z.literal(2),
389
+ connectionId: zod_1.z.string().min(1).max(128),
390
+ provider: identifiers_1.inferenceProviderSlugSchema,
391
+ /** The Oxy account that owns the connection and answers for its use. */
392
+ ownerAccountId: identifiers_1.oxyAccountIdSchema,
393
+ scope: exports.providerConnectionScopeSchema,
394
+ environment: identifiers_1.inferenceEnvironmentSchema,
395
+ status: exports.providerConnectionStatusSchema,
396
+ custodyState: exports.providerCredentialCustodyStateSchema,
397
+ credentialHandle: exports.kaanaCredentialHandleSchema.optional(),
398
+ credentialRevision: zod_1.z.number().int().positive().safe().optional(),
399
+ validation: exports.providerConnectionValidationSchema,
400
+ /**
401
+ * Always `true` for a BYOK connection: the provider bills the customer's own
402
+ * upstream account, and Oxy charges only its platform fee. Stated as data so
403
+ * a receipt against this route is readable without a second lookup.
404
+ */
405
+ upstreamBillsCustomerDirectly: zod_1.z.literal(true),
406
+ /** Set when the provider's terms require a per-customer acknowledgement. */
407
+ termsAcknowledgedAt: identifiers_1.inferenceTimestampSchema.optional(),
408
+ createdAt: identifiers_1.inferenceTimestampSchema,
409
+ rotatedAt: identifiers_1.inferenceTimestampSchema.optional(),
410
+ })
411
+ .strict()
412
+ .superRefine((connection, ctx) => {
413
+ if (connection.validation.state === 'invalid' &&
414
+ connection.validation.failureCode === undefined) {
415
+ ctx.addIssue({
416
+ code: zod_1.z.ZodIssueCode.custom,
417
+ path: ['validation', 'failureCode'],
418
+ message: 'an invalid credential must record why the check failed',
419
+ });
420
+ }
421
+ // `active` is evidence that this exact credential generation passed the
422
+ // provider check. Pending, expired or rejected credentials cannot be
423
+ // represented as active.
424
+ if (connection.status === 'active' && connection.validation.state !== 'valid') {
425
+ ctx.addIssue({
426
+ code: zod_1.z.ZodIssueCode.custom,
427
+ path: ['status'],
428
+ message: 'only a successfully validated credential can be active',
429
+ });
430
+ }
431
+ const hasReference = connection.credentialHandle !== undefined && connection.credentialRevision !== undefined;
432
+ if ((connection.custodyState === 'ready' || connection.custodyState === 'revoked') &&
433
+ !hasReference) {
434
+ ctx.addIssue({
435
+ code: zod_1.z.ZodIssueCode.custom,
436
+ path: ['credentialHandle'],
437
+ message: 'ready and revoked custody states require an exact Kaana handle and revision',
438
+ });
439
+ }
440
+ if (connection.custodyState === 'pending' && hasReference) {
441
+ ctx.addIssue({
442
+ code: zod_1.z.ZodIssueCode.custom,
443
+ path: ['custodyState'],
444
+ message: 'a pending create cannot claim a Kaana reference before Kaana acknowledges it',
445
+ });
446
+ }
447
+ if ((connection.credentialHandle === undefined) !==
448
+ (connection.credentialRevision === undefined)) {
449
+ ctx.addIssue({
450
+ code: zod_1.z.ZodIssueCode.custom,
451
+ path: ['credentialRevision'],
452
+ message: 'a Kaana credential handle and revision are present or absent together',
453
+ });
454
+ }
455
+ });