@oxy.so/contracts 4.11.0-oxy-one.0 → 4.12.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 (111) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/accountGraph.js +5 -3
  3. package/dist/cjs/agency.js +178 -96
  4. package/dist/cjs/agentKeys.js +80 -26
  5. package/dist/cjs/capabilityBindings.js +2 -2
  6. package/dist/cjs/capabilityInvocation.js +3 -1
  7. package/dist/cjs/commonsSignIn.js +2 -2
  8. package/dist/cjs/deviceSession.js +5 -1
  9. package/dist/cjs/email/messages.js +70 -4
  10. package/dist/cjs/emailAgentContext.js +16 -8
  11. package/dist/cjs/externalIdentity.js +30 -12
  12. package/dist/cjs/identity.js +14 -6
  13. package/dist/cjs/identityLink.js +7 -2
  14. package/dist/cjs/identityProof.js +2 -1
  15. package/dist/cjs/index.js +12 -8
  16. package/dist/cjs/inference/catalogue.js +2 -12
  17. package/dist/cjs/inference/decisions.js +102 -83
  18. package/dist/cjs/inference/economics.js +15 -5
  19. package/dist/cjs/inference/embeddings.js +44 -6
  20. package/dist/cjs/inference/identifiers.js +14 -1
  21. package/dist/cjs/inference/inbox.js +33 -2
  22. package/dist/cjs/inference/providerConnection.js +21 -6
  23. package/dist/cjs/inference/realtime.js +114 -107
  24. package/dist/cjs/inference/routingPolicy.js +17 -0
  25. package/dist/cjs/inference/scopedExecution.js +12 -12
  26. package/dist/cjs/inference/usage.js +10 -9
  27. package/dist/cjs/inference/version.js +1 -1
  28. package/dist/cjs/notifications.js +25 -5
  29. package/dist/cjs/oauth.js +30 -14
  30. package/dist/cjs/oxyRecordTypes.js +2 -2
  31. package/dist/cjs/products/access.js +146 -57
  32. package/dist/cjs/products/billing.js +71 -17
  33. package/dist/cjs/products/checkout.js +24 -6
  34. package/dist/cjs/products/plans.js +22 -7
  35. package/dist/cjs/recommendations.js +4 -6
  36. package/dist/cjs/reputation.js +3 -6
  37. package/dist/cjs/sessionStatus.js +1 -6
  38. package/dist/cjs/signIn.js +17 -4
  39. package/dist/cjs/transparency.js +3 -1
  40. package/dist/cjs/updates.js +2 -4
  41. package/dist/cjs/userResponse.js +27 -7
  42. package/dist/cjs/username.js +3 -1
  43. package/dist/esm/.tsbuildinfo +1 -1
  44. package/dist/esm/accountGraph.js +5 -3
  45. package/dist/esm/agency.js +178 -96
  46. package/dist/esm/agentKeys.js +80 -26
  47. package/dist/esm/capabilityBindings.js +2 -2
  48. package/dist/esm/capabilityInvocation.js +3 -1
  49. package/dist/esm/commonsSignIn.js +2 -2
  50. package/dist/esm/deviceSession.js +5 -1
  51. package/dist/esm/email/messages.js +69 -3
  52. package/dist/esm/emailAgentContext.js +16 -8
  53. package/dist/esm/externalIdentity.js +30 -12
  54. package/dist/esm/identity.js +14 -6
  55. package/dist/esm/identityLink.js +7 -2
  56. package/dist/esm/identityProof.js +2 -1
  57. package/dist/esm/index.js +10 -8
  58. package/dist/esm/inference/aliaModelRelease.js +1 -1
  59. package/dist/esm/inference/catalogue.js +3 -13
  60. package/dist/esm/inference/decisions.js +108 -89
  61. package/dist/esm/inference/economics.js +16 -6
  62. package/dist/esm/inference/embeddings.js +44 -6
  63. package/dist/esm/inference/identifiers.js +13 -0
  64. package/dist/esm/inference/inbox.js +32 -1
  65. package/dist/esm/inference/providerConnection.js +21 -6
  66. package/dist/esm/inference/realtime.js +123 -116
  67. package/dist/esm/inference/routingPolicy.js +18 -1
  68. package/dist/esm/inference/scopedExecution.js +15 -15
  69. package/dist/esm/inference/usage.js +11 -10
  70. package/dist/esm/inference/version.js +1 -1
  71. package/dist/esm/notifications.js +25 -5
  72. package/dist/esm/oauth.js +30 -14
  73. package/dist/esm/oxyRecordTypes.js +2 -2
  74. package/dist/esm/products/access.js +146 -57
  75. package/dist/esm/products/billing.js +71 -17
  76. package/dist/esm/products/checkout.js +24 -6
  77. package/dist/esm/products/plans.js +22 -7
  78. package/dist/esm/recommendations.js +4 -6
  79. package/dist/esm/reputation.js +3 -6
  80. package/dist/esm/sessionStatus.js +1 -6
  81. package/dist/esm/signIn.js +17 -4
  82. package/dist/esm/transparency.js +3 -1
  83. package/dist/esm/updates.js +2 -4
  84. package/dist/esm/userResponse.js +27 -7
  85. package/dist/esm/username.js +3 -1
  86. package/dist/types/.tsbuildinfo +1 -1
  87. package/dist/types/accountGraph.d.ts +1 -1
  88. package/dist/types/accountSubject.d.ts +4 -4
  89. package/dist/types/commonsSignIn.d.ts +2 -2
  90. package/dist/types/email/messages.d.ts +208 -2
  91. package/dist/types/identity.d.ts +1 -1
  92. package/dist/types/index.d.ts +10 -10
  93. package/dist/types/inference/accountBilling.d.ts +2 -2
  94. package/dist/types/inference/decisions.d.ts +21 -1
  95. package/dist/types/inference/identifiers.d.ts +14 -0
  96. package/dist/types/inference/inbox.d.ts +129 -5
  97. package/dist/types/inference/realtime.d.ts +19 -1
  98. package/dist/types/inference/request.d.ts +54 -0
  99. package/dist/types/inference/routingPolicy.d.ts +10 -0
  100. package/dist/types/inference/scopedExecution.d.ts +1 -1
  101. package/dist/types/inference/usage.d.ts +12 -0
  102. package/dist/types/inference/version.d.ts +1 -1
  103. package/dist/types/moderationReputation.d.ts +1 -1
  104. package/dist/types/oxyRecordTypes.d.ts +2 -2
  105. package/dist/types/products/access.d.ts +102 -102
  106. package/dist/types/products/checkout.d.ts +3 -3
  107. package/dist/types/products/plans.d.ts +40 -40
  108. package/dist/types/reputation.d.ts +4 -4
  109. package/dist/types/updates.d.ts +1 -1
  110. package/dist/types/userResponse.d.ts +22 -23
  111. package/package.json +1 -2
@@ -6,7 +6,7 @@ const zod_1 = require("zod");
6
6
  const identifiers_1 = require("./identifiers");
7
7
  const money_1 = require("./money");
8
8
  /** Explicit extension negotiation; never replaces the legacy 3.5 handshake. */
9
- exports.SCOPED_EXECUTION_CONTRACT_VERSION = "3.6.0";
9
+ exports.SCOPED_EXECUTION_CONTRACT_VERSION = '3.6.0';
10
10
  /** Scoped only; normal envelope v2 and metadata 3.5 remain unchanged. */
11
11
  exports.SCOPED_REQUEST_ENVELOPE_VERSION = 3;
12
12
  const identity = zod_1.z.string().min(1).max(256);
@@ -14,10 +14,10 @@ const sha256 = zod_1.z.string().regex(/^[0-9a-f]{64}$/);
14
14
  const maxCost = money_1.exactDecimalSchema.refine((value) => {
15
15
  if (!money_1.exactDecimalSchema.safeParse(value).success)
16
16
  return false;
17
- const [whole, fraction = ""] = value.split(".");
18
- const units = BigInt(whole) * 1000000000000n + BigInt(fraction.padEnd(12, "0"));
17
+ const [whole, fraction = ''] = value.split('.');
18
+ const units = BigInt(whole) * 1000000000000n + BigInt(fraction.padEnd(12, '0'));
19
19
  return units > 0n && units <= 10000000000n;
20
- }, "scoped cost must be positive and at most 0.01 USD");
20
+ }, 'scoped cost must be positive and at most 0.01 USD');
21
21
  /** Restriction only: none of these identities grants catalogue eligibility. */
22
22
  exports.scopedExecutionAudienceSchema = zod_1.z
23
23
  .object({
@@ -42,7 +42,7 @@ exports.scopedExecutionAudienceSchema = zod_1.z
42
42
  deploymentId: identifiers_1.deploymentIdSchema,
43
43
  provider: identifiers_1.inferenceProviderSlugSchema,
44
44
  keyId: identity,
45
- modelReference: identifiers_1.modelReferenceSchema.refine((value) => value.includes("@"), "must pin a revision"),
45
+ modelReference: identifiers_1.modelReferenceSchema.refine((value) => value.includes('@'), 'must pin a revision'),
46
46
  upstreamModelId: identity,
47
47
  priceVersionId: identity,
48
48
  providerRateCardVersionId: identity,
@@ -63,25 +63,25 @@ exports.scopedExecutionSchema = exports.scopedExecutionAudienceSchema
63
63
  * reparsed/defaulted decision. Reject non-JSON values rather than dropping them.
64
64
  */
65
65
  function canonicalScopedExecutionJson(value) {
66
- if (value === null || typeof value === "string" || typeof value === "boolean")
66
+ if (value === null || typeof value === 'string' || typeof value === 'boolean')
67
67
  return JSON.stringify(value);
68
- if (typeof value === "number" && Number.isFinite(value))
68
+ if (typeof value === 'number' && Number.isFinite(value))
69
69
  return JSON.stringify(value);
70
70
  if (Array.isArray(value)) {
71
71
  const entries = Array.from(value, (entry, index) => {
72
72
  if (!(index in value))
73
- throw new Error("Scoped execution requires dense JSON arrays.");
73
+ throw new Error('Scoped execution requires dense JSON arrays.');
74
74
  return canonicalScopedExecutionJson(entry);
75
75
  });
76
- return `[${entries.join(",")}]`;
76
+ return `[${entries.join(',')}]`;
77
77
  }
78
- if (typeof value === "object" &&
78
+ if (typeof value === 'object' &&
79
79
  value !== null &&
80
80
  Object.getPrototypeOf(value) === Object.prototype) {
81
81
  const entries = Object.keys(value)
82
82
  .sort()
83
83
  .map((key) => `${JSON.stringify(key)}:${canonicalScopedExecutionJson(value[key])}`);
84
- return `{${entries.join(",")}}`;
84
+ return `{${entries.join(',')}}`;
85
85
  }
86
- throw new Error("Scoped execution requires JSON wire values.");
86
+ throw new Error('Scoped execution requires JSON wire values.');
87
87
  }
@@ -65,12 +65,7 @@ exports.usageReservationRequestSchema = zod_1.z.object({
65
65
  expiresInSeconds: zod_1.z.number().int().positive().max(86400),
66
66
  });
67
67
  /** Lifecycle of a hold. Terminal states are `settled`, `released`, `expired`. */
68
- exports.usageReservationStatusSchema = zod_1.z.enum([
69
- 'held',
70
- 'settled',
71
- 'released',
72
- 'expired',
73
- ]);
68
+ exports.usageReservationStatusSchema = zod_1.z.enum(['held', 'settled', 'released', 'expired']);
74
69
  /**
75
70
  * A hold placed against an account's balance.
76
71
  *
@@ -178,6 +173,14 @@ exports.normalizedUsageReportSchema = zod_1.z
178
173
  deploymentId: identifiers_1.deploymentIdSchema,
179
174
  /** How many allowed route switches occurred while serving this request. */
180
175
  routeSwitches: zod_1.z.number().int().nonnegative().max(100),
176
+ /**
177
+ * The funding tier of the platform key that served the final attempt, as
178
+ * the data plane states it (ADR 0038). Absent when the key's economics
179
+ * were never stated, when a customer credential served, or when nothing
180
+ * was served. Oxy reads it to account for what the request cost the
181
+ * platform; it is never a key identity and never reaches a customer.
182
+ */
183
+ fundingTier: identifiers_1.inferenceFundingTierSchema.optional(),
181
184
  startedAt: identifiers_1.inferenceTimestampSchema,
182
185
  completedAt: identifiers_1.inferenceTimestampSchema,
183
186
  timeToFirstTokenMs: zod_1.z.number().int().nonnegative().safe().optional(),
@@ -270,9 +273,7 @@ exports.usageReceiptSchema = zod_1.z
270
273
  * ledger accounts and only the second one is visible on an invoice.
271
274
  */
272
275
  exports.usageRefundSubjectSchema = zod_1.z.discriminatedUnion('kind', [
273
- zod_1.z
274
- .object({ kind: zod_1.z.literal('reservation'), reservationId: zod_1.z.string().min(1).max(128) })
275
- .strict(),
276
+ zod_1.z.object({ kind: zod_1.z.literal('reservation'), reservationId: zod_1.z.string().min(1).max(128) }).strict(),
276
277
  zod_1.z.object({ kind: zod_1.z.literal('receipt'), receiptId: zod_1.z.string().min(1).max(128) }).strict(),
277
278
  ]);
278
279
  /** Why money was given back or a hold was released. */
@@ -102,4 +102,4 @@ exports.INFERENCE_CONTRACT_VERSION = void 0;
102
102
  * change to, say, the catalogue reject every in-flight inference request; the
103
103
  * per-shape `schemaVersion` is what a message is validated against.
104
104
  */
105
- exports.INFERENCE_CONTRACT_VERSION = '3.5.0';
105
+ exports.INFERENCE_CONTRACT_VERSION = '3.8.0';
@@ -64,18 +64,38 @@ exports.createOxyNotificationRequestSchema = zod_1.z
64
64
  .superRefine((value, context) => {
65
65
  if (value.type === 'system') {
66
66
  if (value.actorId !== value.recipientId)
67
- context.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['actorId'], message: 'a system notification is from the recipient\'s own account' });
67
+ context.addIssue({
68
+ code: zod_1.z.ZodIssueCode.custom,
69
+ path: ['actorId'],
70
+ message: "a system notification is from the recipient's own account",
71
+ });
68
72
  if (!value.title)
69
- context.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['title'], message: 'title is required for a system notification' });
73
+ context.addIssue({
74
+ code: zod_1.z.ZodIssueCode.custom,
75
+ path: ['title'],
76
+ message: 'title is required for a system notification',
77
+ });
70
78
  if (!value.message)
71
- context.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['message'], message: 'message is required for a system notification' });
79
+ context.addIssue({
80
+ code: zod_1.z.ZodIssueCode.custom,
81
+ path: ['message'],
82
+ message: 'message is required for a system notification',
83
+ });
72
84
  }
73
85
  else {
74
86
  if (value.url !== undefined) {
75
- context.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['url'], message: 'url is only stored for a system notification' });
87
+ context.addIssue({
88
+ code: zod_1.z.ZodIssueCode.custom,
89
+ path: ['url'],
90
+ message: 'url is only stored for a system notification',
91
+ });
76
92
  }
77
93
  if (value.entityType === 'app') {
78
- context.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['entityType'], message: "entityType 'app' is only valid for a system notification" });
94
+ context.addIssue({
95
+ code: zod_1.z.ZodIssueCode.custom,
96
+ path: ['entityType'],
97
+ message: "entityType 'app' is only valid for a system notification",
98
+ });
79
99
  }
80
100
  }
81
101
  });
package/dist/cjs/oauth.js CHANGED
@@ -71,45 +71,61 @@ exports.oauthAuthorizeCodeResponseSchema = zod_1.z.object({
71
71
  * Reuses the ordinary public application projection and adds only the public
72
72
  * DCR client id needed to bind the consent surface to the request.
73
73
  */
74
- exports.mcpOAuthClientApplicationSchema = sessionStatus_1.publicApplicationSchema.extend({
74
+ exports.mcpOAuthClientApplicationSchema = sessionStatus_1.publicApplicationSchema
75
+ .extend({
75
76
  clientId: zod_1.z.string().min(1),
76
- }).strict();
77
+ })
78
+ .strict();
77
79
  /**
78
80
  * An effectful MCP action the requested capability set can actually invoke.
79
81
  * Every field is picked from the canonical catalog tool schema so consent can
80
82
  * never maintain a second tool description or effect classification.
81
83
  */
82
- exports.mcpOAuthWriteActionSchema = agency_1.catalogToolSchema.innerType().pick({
84
+ exports.mcpOAuthWriteActionSchema = agency_1.catalogToolSchema
85
+ .innerType()
86
+ .pick({
83
87
  name: true,
84
88
  version: true,
85
89
  description: true,
86
90
  requiredCapabilities: true,
87
91
  effect: true,
88
- }).strict().refine((action) => action.effect !== 'read', {
92
+ })
93
+ .strict()
94
+ .refine((action) => action.effect !== 'read', {
89
95
  message: 'MCP consent write actions must be effectful',
90
96
  path: ['effect'],
91
97
  });
92
98
  /** Exact, server-resolved context rendered before an external MCP grant. */
93
- exports.mcpOAuthConsentContextSchema = zod_1.z.object({
99
+ exports.mcpOAuthConsentContextSchema = zod_1.z
100
+ .object({
94
101
  client: exports.mcpOAuthClientApplicationSchema,
95
- account: zod_1.z.object({
102
+ account: zod_1.z
103
+ .object({
96
104
  id: zod_1.z.string().min(1),
97
105
  displayName: zod_1.z.string().min(1).optional(),
98
106
  handle: zod_1.z.string().min(1).optional(),
99
107
  avatar: zod_1.z.string().min(1).optional(),
100
- }).strict(),
101
- resource: zod_1.z.object({
108
+ })
109
+ .strict(),
110
+ resource: zod_1.z
111
+ .object({
102
112
  appId: zod_1.z.string().min(1),
103
113
  uri: zod_1.z.string().url(),
104
114
  application: sessionStatus_1.publicApplicationSchema,
105
- }).strict(),
115
+ })
116
+ .strict(),
106
117
  capabilities: zod_1.z.array(zod_1.z.string().min(1)).min(1),
107
118
  writeActions: zod_1.z.array(exports.mcpOAuthWriteActionSchema),
108
- }).strict();
109
- exports.mcpOAuthClientInfoResponseSchema = zod_1.z.object({
119
+ })
120
+ .strict();
121
+ exports.mcpOAuthClientInfoResponseSchema = zod_1.z
122
+ .object({
110
123
  application: exports.mcpOAuthClientApplicationSchema,
111
- }).strict();
112
- exports.mcpOAuthConsentResponseSchema = zod_1.z.object({
124
+ })
125
+ .strict();
126
+ exports.mcpOAuthConsentResponseSchema = zod_1.z
127
+ .object({
113
128
  consentRequired: zod_1.z.boolean(),
114
129
  context: exports.mcpOAuthConsentContextSchema,
115
- }).strict();
130
+ })
131
+ .strict();
@@ -8,8 +8,8 @@
8
8
  * is rejected as `invalid_envelope`.
9
9
  *
10
10
  * `oxySignedRecordTypeSchema` is that runtime gate (the API's `verifyEnvelope`
11
- * re-narrows with it; the Mongoose `SignedRecord.type` enum and the Postgres
12
- * CHECK on `signed_records.type` are both derived from `.options`);
11
+ * re-narrows with it; the Postgres CHECK on `signed_records.type` is derived
12
+ * from `.options`);
13
13
  * `OxySignedRecordType` is the matching compile-time union the SDK
14
14
  * identity/civic mixins type against.
15
15
  *
@@ -5,86 +5,175 @@ const zod_1 = require("zod");
5
5
  const identifiers_1 = require("../inference/identifiers");
6
6
  const identifier = zod_1.z.string().min(1).max(160);
7
7
  const count = zod_1.z.number().int().nonnegative().safe();
8
- const period = zod_1.z.object({ start: zod_1.z.string().datetime(), end: zod_1.z.string().datetime() }).strict()
9
- .refine(value => Date.parse(value.end) > Date.parse(value.start), 'period end must follow start');
8
+ const period = zod_1.z
9
+ .object({ start: zod_1.z.string().datetime(), end: zod_1.z.string().datetime() })
10
+ .strict()
11
+ .refine((value) => Date.parse(value.end) > Date.parse(value.start), 'period end must follow start');
10
12
  /** Product ownership and audience are registered together; branding grants no trust. */
11
- exports.productDefinitionSchema = zod_1.z.object({
12
- schemaVersion: zod_1.z.literal(1), id: identifier, ownerAccountId: identifiers_1.oxyAccountIdSchema,
13
+ exports.productDefinitionSchema = zod_1.z
14
+ .object({
15
+ schemaVersion: zod_1.z.literal(1),
16
+ id: identifier,
17
+ ownerAccountId: identifiers_1.oxyAccountIdSchema,
13
18
  applicationId: identifiers_1.oxyApplicationIdSchema,
14
- }).strict();
15
- exports.subjectProductAccessQuerySchema = zod_1.z.object({
16
- schemaVersion: zod_1.z.literal(1), subjectAccountId: identifiers_1.oxyAccountIdSchema, productId: identifier,
17
- }).strict();
19
+ })
20
+ .strict();
21
+ exports.subjectProductAccessQuerySchema = zod_1.z
22
+ .object({
23
+ schemaVersion: zod_1.z.literal(1),
24
+ subjectAccountId: identifiers_1.oxyAccountIdSchema,
25
+ productId: identifier,
26
+ })
27
+ .strict();
18
28
  /** Every quota declares its combination rule; there is no commercial default. */
19
29
  exports.productBenefitSchema = zod_1.z.discriminatedUnion('kind', [
20
30
  zod_1.z.object({ kind: zod_1.z.literal('capability'), productId: identifier, key: identifier }).strict(),
21
- zod_1.z.object({ kind: zod_1.z.literal('quota'), productId: identifier, key: identifier,
22
- unit: identifier, included: count, combination: zod_1.z.enum(['maximum', 'sum', 'exclusive']) }).strict(),
31
+ zod_1.z
32
+ .object({
33
+ kind: zod_1.z.literal('quota'),
34
+ productId: identifier,
35
+ key: identifier,
36
+ unit: identifier,
37
+ included: count,
38
+ combination: zod_1.z.enum(['maximum', 'sum', 'exclusive']),
39
+ })
40
+ .strict(),
23
41
  ]);
24
42
  /** A version names a frozen offer. An empty bundle grants nothing. */
25
- exports.productOfferSchema = zod_1.z.object({
26
- schemaVersion: zod_1.z.literal(1), id: identifier, version: zod_1.z.number().int().positive().safe(),
27
- kind: zod_1.z.enum(['individual', 'bundle']), benefits: zod_1.z.array(exports.productBenefitSchema),
28
- }).strict().refine(value => value.kind === 'bundle' || new Set(value.benefits.map(benefit => benefit.productId)).size <= 1, 'individual offers cannot cover multiple products');
29
- exports.productSubscriptionSourceSchema = zod_1.z.object({
30
- schemaVersion: zod_1.z.literal(1), id: identifier,
31
- beneficiaryAccountId: identifiers_1.oxyAccountIdSchema, payerAccountId: identifiers_1.oxyAccountIdSchema,
32
- provider: zod_1.z.enum(['stripe', 'peable']), providerSubscriptionId: identifier,
33
- status: zod_1.z.enum(['active', 'trialing', 'past_due', 'unpaid', 'canceled', 'paused', 'incomplete', 'incomplete_expired']),
34
- period, cancelAtPeriodEnd: zod_1.z.boolean(),
35
- }).strict();
43
+ exports.productOfferSchema = zod_1.z
44
+ .object({
45
+ schemaVersion: zod_1.z.literal(1),
46
+ id: identifier,
47
+ version: zod_1.z.number().int().positive().safe(),
48
+ kind: zod_1.z.enum(['individual', 'bundle']),
49
+ benefits: zod_1.z.array(exports.productBenefitSchema),
50
+ })
51
+ .strict()
52
+ .refine((value) => value.kind === 'bundle' ||
53
+ new Set(value.benefits.map((benefit) => benefit.productId)).size <= 1, 'individual offers cannot cover multiple products');
54
+ exports.productSubscriptionSourceSchema = zod_1.z
55
+ .object({
56
+ schemaVersion: zod_1.z.literal(1),
57
+ id: identifier,
58
+ beneficiaryAccountId: identifiers_1.oxyAccountIdSchema,
59
+ payerAccountId: identifiers_1.oxyAccountIdSchema,
60
+ provider: zod_1.z.enum(['stripe', 'peable']),
61
+ providerSubscriptionId: identifier,
62
+ status: zod_1.z.enum([
63
+ 'active',
64
+ 'trialing',
65
+ 'past_due',
66
+ 'unpaid',
67
+ 'canceled',
68
+ 'paused',
69
+ 'incomplete',
70
+ 'incomplete_expired',
71
+ ]),
72
+ period,
73
+ cancelAtPeriodEnd: zod_1.z.boolean(),
74
+ })
75
+ .strict();
36
76
  /** A frozen paid-period/offer segment; upgrades append, never rewrite it. */
37
- exports.productOfferSegmentSchema = zod_1.z.object({
38
- schemaVersion: zod_1.z.literal(1), id: identifier, subscriptionId: identifier,
39
- beneficiaryAccountId: identifiers_1.oxyAccountIdSchema, offerId: identifier,
40
- offerVersion: zod_1.z.number().int().positive().safe(), origin: zod_1.z.enum(['individual', 'bundle']), period,
41
- }).strict();
77
+ exports.productOfferSegmentSchema = zod_1.z
78
+ .object({
79
+ schemaVersion: zod_1.z.literal(1),
80
+ id: identifier,
81
+ subscriptionId: identifier,
82
+ beneficiaryAccountId: identifiers_1.oxyAccountIdSchema,
83
+ offerId: identifier,
84
+ offerVersion: zod_1.z.number().int().positive().safe(),
85
+ origin: zod_1.z.enum(['individual', 'bundle']),
86
+ period,
87
+ })
88
+ .strict();
42
89
  /** Provenance survives cancellation: deactivate a source, never delete history. */
43
- exports.productAccessGrantSchema = zod_1.z.object({
44
- schemaVersion: zod_1.z.literal(1), id: identifier, sourceSegmentId: identifier,
45
- beneficiaryAccountId: identifiers_1.oxyAccountIdSchema, offerId: identifier,
90
+ exports.productAccessGrantSchema = zod_1.z
91
+ .object({
92
+ schemaVersion: zod_1.z.literal(1),
93
+ id: identifier,
94
+ sourceSegmentId: identifier,
95
+ beneficiaryAccountId: identifiers_1.oxyAccountIdSchema,
96
+ offerId: identifier,
46
97
  offerVersion: zod_1.z.number().int().positive().safe(),
47
- origin: zod_1.z.enum(['individual', 'bundle']), benefit: exports.productBenefitSchema,
48
- period, revokedAt: zod_1.z.string().datetime().nullable(),
49
- }).strict();
98
+ origin: zod_1.z.enum(['individual', 'bundle']),
99
+ benefit: exports.productBenefitSchema,
100
+ period,
101
+ revokedAt: zod_1.z.string().datetime().nullable(),
102
+ })
103
+ .strict();
50
104
  /** Access answers contain no payer, provider reference, price or account balance. */
51
- exports.subjectProductAccessSchema = zod_1.z.object({
52
- schemaVersion: zod_1.z.literal(1), subjectAccountId: identifiers_1.oxyAccountIdSchema, productId: identifier,
105
+ exports.subjectProductAccessSchema = zod_1.z
106
+ .object({
107
+ schemaVersion: zod_1.z.literal(1),
108
+ subjectAccountId: identifiers_1.oxyAccountIdSchema,
109
+ productId: identifier,
53
110
  evaluatedAt: zod_1.z.string().datetime(),
54
111
  capabilities: zod_1.z.array(zod_1.z.object({ key: identifier, grantIds: zod_1.z.array(identifier) }).strict()),
55
- quotas: zod_1.z.array(zod_1.z.object({ key: identifier, unit: identifier, included: count,
56
- combination: zod_1.z.enum(['maximum', 'sum', 'exclusive']), grantIds: zod_1.z.array(identifier) }).strict()),
57
- conflicts: zod_1.z.array(zod_1.z.object({ key: identifier,
58
- reason: zod_1.z.enum(['combination_mismatch', 'unit_mismatch', 'exclusive_overlap', 'unsafe_total']),
59
- grantIds: zod_1.z.array(identifier) }).strict()),
60
- }).strict();
112
+ quotas: zod_1.z.array(zod_1.z
113
+ .object({
114
+ key: identifier,
115
+ unit: identifier,
116
+ included: count,
117
+ combination: zod_1.z.enum(['maximum', 'sum', 'exclusive']),
118
+ grantIds: zod_1.z.array(identifier),
119
+ })
120
+ .strict()),
121
+ conflicts: zod_1.z.array(zod_1.z
122
+ .object({
123
+ key: identifier,
124
+ reason: zod_1.z.enum([
125
+ 'combination_mismatch',
126
+ 'unit_mismatch',
127
+ 'exclusive_overlap',
128
+ 'unsafe_total',
129
+ ]),
130
+ grantIds: zod_1.z.array(identifier),
131
+ })
132
+ .strict()),
133
+ })
134
+ .strict();
61
135
  /** Active grant periods for metering adapters; no financial/provider identity. */
62
- exports.subjectProductGrantSnapshotSchema = zod_1.z.object({
63
- schemaVersion: zod_1.z.literal(1), access: exports.subjectProductAccessSchema, grants: zod_1.z.array(exports.productAccessGrantSchema),
64
- }).strict().superRefine((value, ctx) => {
65
- const active = new Set([...value.access.capabilities, ...value.access.quotas].flatMap(entry => entry.grantIds));
66
- if (active.size !== value.grants.length || new Set(value.grants.map(g => g.id)).size !== value.grants.length
67
- || value.grants.some(g => g.beneficiaryAccountId !== value.access.subjectAccountId
68
- || g.benefit.productId !== value.access.productId || !active.has(g.id)
136
+ exports.subjectProductGrantSnapshotSchema = zod_1.z
137
+ .object({
138
+ schemaVersion: zod_1.z.literal(1),
139
+ access: exports.subjectProductAccessSchema,
140
+ grants: zod_1.z.array(exports.productAccessGrantSchema),
141
+ })
142
+ .strict()
143
+ .superRefine((value, ctx) => {
144
+ const active = new Set([...value.access.capabilities, ...value.access.quotas].flatMap((entry) => entry.grantIds));
145
+ if (active.size !== value.grants.length ||
146
+ new Set(value.grants.map((g) => g.id)).size !== value.grants.length ||
147
+ value.grants.some((g) => g.beneficiaryAccountId !== value.access.subjectAccountId ||
148
+ g.benefit.productId !== value.access.productId ||
149
+ !active.has(g.id) ||
69
150
  // A future revocation is still active at evaluation time, as in access composition.
70
- || (g.revokedAt !== null && Date.parse(g.revokedAt) <= Date.parse(value.access.evaluatedAt))
71
- || Date.parse(g.period.start) > Date.parse(value.access.evaluatedAt)
72
- || Date.parse(g.period.end) <= Date.parse(value.access.evaluatedAt)))
151
+ (g.revokedAt !== null &&
152
+ Date.parse(g.revokedAt) <= Date.parse(value.access.evaluatedAt)) ||
153
+ Date.parse(g.period.start) > Date.parse(value.access.evaluatedAt) ||
154
+ Date.parse(g.period.end) <= Date.parse(value.access.evaluatedAt)))
73
155
  ctx.addIssue({ code: 'custom', message: 'Active grant snapshot attribution differs' });
74
156
  for (const quota of value.access.quotas) {
75
- const benefits = quota.grantIds.map(id => value.grants.find(g => g.id === id)?.benefit);
76
- if (benefits.some(b => !b || b.kind !== 'quota' || b.key !== quota.key || b.unit !== quota.unit || b.combination !== quota.combination)) {
157
+ const benefits = quota.grantIds.map((id) => value.grants.find((g) => g.id === id)?.benefit);
158
+ if (benefits.some((b) => !b ||
159
+ b.kind !== 'quota' ||
160
+ b.key !== quota.key ||
161
+ b.unit !== quota.unit ||
162
+ b.combination !== quota.combination)) {
77
163
  ctx.addIssue({ code: 'custom', message: 'Grant quota terms differ' });
78
164
  continue;
79
165
  }
80
- const amounts = benefits.map(b => b?.kind === 'quota' ? BigInt(b.included) : 0n);
81
- const included = quota.combination === 'sum' ? amounts.reduce((sum, n) => sum + n, 0n) : amounts.reduce((maximum, n) => n > maximum ? n : maximum, 0n);
82
- if (included !== BigInt(quota.included) || (quota.combination === 'exclusive' && benefits.length > 1))
166
+ const amounts = benefits.map((b) => (b?.kind === 'quota' ? BigInt(b.included) : 0n));
167
+ const included = quota.combination === 'sum'
168
+ ? amounts.reduce((sum, n) => sum + n, 0n)
169
+ : amounts.reduce((maximum, n) => (n > maximum ? n : maximum), 0n);
170
+ if (included !== BigInt(quota.included) ||
171
+ (quota.combination === 'exclusive' && benefits.length > 1))
83
172
  ctx.addIssue({ code: 'custom', message: 'Grant quota composition differs' });
84
173
  }
85
174
  for (const capability of value.access.capabilities)
86
- if (capability.grantIds.some(id => {
87
- const benefit = value.grants.find(g => g.id === id)?.benefit;
175
+ if (capability.grantIds.some((id) => {
176
+ const benefit = value.grants.find((g) => g.id === id)?.benefit;
88
177
  return benefit?.kind !== 'capability' || benefit.key !== capability.key;
89
178
  }))
90
179
  ctx.addIssue({ code: 'custom', message: 'Grant capability terms differ' });
@@ -6,25 +6,79 @@ const identifiers_1 = require("../inference/identifiers");
6
6
  const id = zod_1.z.string().min(1).max(160);
7
7
  const name = zod_1.z.string().min(1).max(100);
8
8
  const count = zod_1.z.number().int().nonnegative().safe();
9
- const period = zod_1.z.object({ start: zod_1.z.string().datetime(), end: zod_1.z.string().datetime() }).strict()
10
- .refine(value => Date.parse(value.end) > Date.parse(value.start), 'Period end must follow start');
9
+ const period = zod_1.z
10
+ .object({ start: zod_1.z.string().datetime(), end: zod_1.z.string().datetime() })
11
+ .strict()
12
+ .refine((value) => Date.parse(value.end) > Date.parse(value.start), 'Period end must follow start');
11
13
  /** Self-service provenance; no payer/provider identifiers or balances in access metadata. */
12
- exports.productSubscriptionSummarySchema = zod_1.z.object({ sourceId: id,
13
- status: zod_1.z.enum(['active', 'trialing', 'past_due', 'unpaid', 'canceled', 'paused', 'incomplete', 'incomplete_expired']),
14
- period, cancelAtPeriodEnd: zod_1.z.boolean(), canCancel: zod_1.z.boolean(),
15
- offers: zod_1.z.array(zod_1.z.object({ segmentId: id, offerId: id, offerVersion: zod_1.z.number().int().positive().safe(),
16
- displayName: name, origin: zod_1.z.enum(['individual', 'bundle']), period, current: zod_1.z.boolean(),
14
+ exports.productSubscriptionSummarySchema = zod_1.z
15
+ .object({
16
+ sourceId: id,
17
+ status: zod_1.z.enum([
18
+ 'active',
19
+ 'trialing',
20
+ 'past_due',
21
+ 'unpaid',
22
+ 'canceled',
23
+ 'paused',
24
+ 'incomplete',
25
+ 'incomplete_expired',
26
+ ]),
27
+ period,
28
+ cancelAtPeriodEnd: zod_1.z.boolean(),
29
+ canCancel: zod_1.z.boolean(),
30
+ offers: zod_1.z.array(zod_1.z
31
+ .object({
32
+ segmentId: id,
33
+ offerId: id,
34
+ offerVersion: zod_1.z.number().int().positive().safe(),
35
+ displayName: name,
36
+ origin: zod_1.z.enum(['individual', 'bundle']),
37
+ period,
38
+ current: zod_1.z.boolean(),
17
39
  products: zod_1.z.array(zod_1.z.object({ id, displayName: name }).strict()),
18
- }).strict()),
19
- }).strict();
20
- exports.productSubscriptionsResponseSchema = zod_1.z.object({ subscriptions: zod_1.z.array(exports.productSubscriptionSummarySchema) }).strict();
21
- exports.subscriptionCreditGrantSchema = zod_1.z.object({ id, invoiceId: id,
22
- origin: zod_1.z.enum(['subscription_payment', 'subscription_proration', 'subscription_promotional_grant']),
23
- period, granted: count, consumed: count, clawed: count, remaining: count,
24
- promotionId: id.nullable(), createdAt: zod_1.z.string().datetime(),
25
- }).strict().refine(value => BigInt(value.consumed) + BigInt(value.clawed) + BigInt(value.remaining) === BigInt(value.granted), 'Grant conservation differs');
26
- exports.subscriptionCreditGrantsResponseSchema = zod_1.z.object({ grants: zod_1.z.array(exports.subscriptionCreditGrantSchema) }).strict();
27
- exports.cancelProductSubscriptionSchema = zod_1.z.object({ sourceId: id, actionId: zod_1.z.string().min(8).max(160).regex(/^[a-zA-Z0-9_-]+$/).optional(), expectedSubjectAccountId: identifiers_1.oxyAccountIdSchema.optional() }).strict();
40
+ })
41
+ .strict()),
42
+ })
43
+ .strict();
44
+ exports.productSubscriptionsResponseSchema = zod_1.z
45
+ .object({ subscriptions: zod_1.z.array(exports.productSubscriptionSummarySchema) })
46
+ .strict();
47
+ exports.subscriptionCreditGrantSchema = zod_1.z
48
+ .object({
49
+ id,
50
+ invoiceId: id,
51
+ origin: zod_1.z.enum([
52
+ 'subscription_payment',
53
+ 'subscription_proration',
54
+ 'subscription_promotional_grant',
55
+ ]),
56
+ period,
57
+ granted: count,
58
+ consumed: count,
59
+ clawed: count,
60
+ remaining: count,
61
+ promotionId: id.nullable(),
62
+ createdAt: zod_1.z.string().datetime(),
63
+ })
64
+ .strict()
65
+ .refine((value) => BigInt(value.consumed) + BigInt(value.clawed) + BigInt(value.remaining) ===
66
+ BigInt(value.granted), 'Grant conservation differs');
67
+ exports.subscriptionCreditGrantsResponseSchema = zod_1.z
68
+ .object({ grants: zod_1.z.array(exports.subscriptionCreditGrantSchema) })
69
+ .strict();
70
+ exports.cancelProductSubscriptionSchema = zod_1.z
71
+ .object({
72
+ sourceId: id,
73
+ actionId: zod_1.z
74
+ .string()
75
+ .min(8)
76
+ .max(160)
77
+ .regex(/^[a-zA-Z0-9_-]+$/)
78
+ .optional(),
79
+ expectedSubjectAccountId: identifiers_1.oxyAccountIdSchema.optional(),
80
+ })
81
+ .strict();
28
82
  /** Remote acceptance is distinct from completed local reconciliation. */
29
83
  exports.productSubscriptionCancellationResultSchema = zod_1.z.union([
30
84
  zod_1.z.object({ sourceId: id, cancelAtPeriodEnd: zod_1.z.literal(true) }).strict(),
@@ -3,15 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.personalPlanCheckoutResultSchema = exports.personalPlanCheckoutRequestSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const identifiers_1 = require("../inference/identifiers");
6
- exports.personalPlanCheckoutRequestSchema = zod_1.z.object({
6
+ exports.personalPlanCheckoutRequestSchema = zod_1.z
7
+ .object({
7
8
  expectedSubjectAccountId: identifiers_1.oxyAccountIdSchema,
8
- offerId: zod_1.z.string().min(1).max(160), offerVersion: zod_1.z.number().int().positive().safe(),
9
- idempotencyKey: zod_1.z.string().min(8).max(160).regex(/^[a-zA-Z0-9_-]+$/),
10
- }).strict();
9
+ offerId: zod_1.z.string().min(1).max(160),
10
+ offerVersion: zod_1.z.number().int().positive().safe(),
11
+ idempotencyKey: zod_1.z
12
+ .string()
13
+ .min(8)
14
+ .max(160)
15
+ .regex(/^[a-zA-Z0-9_-]+$/),
16
+ })
17
+ .strict();
11
18
  /** No grant or subscription is created by checkout completion in the browser. */
12
19
  exports.personalPlanCheckoutResultSchema = zod_1.z.discriminatedUnion('state', [
13
- zod_1.z.object({ state: zod_1.z.literal('unconfigured'), reason: zod_1.z.enum(['provider_unconfigured', 'offer_unconfigured', 'price_unconfigured']) }).strict(),
14
- zod_1.z.object({ state: zod_1.z.literal('pending'), intentId: zod_1.z.string().min(1).max(160), checkoutUrl: zod_1.z.string().url().startsWith('https://') }).strict(),
20
+ zod_1.z
21
+ .object({
22
+ state: zod_1.z.literal('unconfigured'),
23
+ reason: zod_1.z.enum(['provider_unconfigured', 'offer_unconfigured', 'price_unconfigured']),
24
+ })
25
+ .strict(),
26
+ zod_1.z
27
+ .object({
28
+ state: zod_1.z.literal('pending'),
29
+ intentId: zod_1.z.string().min(1).max(160),
30
+ checkoutUrl: zod_1.z.string().url().startsWith('https://').optional(),
31
+ })
32
+ .strict(),
15
33
  zod_1.z.object({ state: zod_1.z.literal('closed'), intentId: zod_1.z.string().min(1).max(160) }).strict(),
16
34
  zod_1.z.object({ state: zod_1.z.literal('fulfilled'), intentId: zod_1.z.string().min(1).max(160) }).strict(),
17
35
  ]);