@oxy.so/contracts 4.7.0 → 4.9.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 (64) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/accountGraph.js +13 -5
  3. package/dist/cjs/accountSubject.js +189 -0
  4. package/dist/cjs/agency.js +56 -4
  5. package/dist/cjs/agentKeys.js +67 -0
  6. package/dist/cjs/capabilityBindings.js +72 -0
  7. package/dist/cjs/index.js +68 -13
  8. package/dist/cjs/inference/catalogue.js +5 -2
  9. package/dist/cjs/inference/economics.js +135 -0
  10. package/dist/cjs/inference/request.js +33 -1
  11. package/dist/cjs/inference/scopedExecution.js +87 -0
  12. package/dist/cjs/products/access.js +60 -0
  13. package/dist/cjs/products/billing.js +32 -0
  14. package/dist/cjs/signIn.js +1 -1
  15. package/dist/esm/.tsbuildinfo +1 -1
  16. package/dist/esm/accountGraph.js +13 -5
  17. package/dist/esm/accountSubject.js +182 -0
  18. package/dist/esm/agency.js +55 -3
  19. package/dist/esm/agentKeys.js +63 -0
  20. package/dist/esm/capabilityBindings.js +67 -0
  21. package/dist/esm/index.js +12 -1
  22. package/dist/esm/inference/catalogue.js +3 -0
  23. package/dist/esm/inference/economics.js +132 -0
  24. package/dist/esm/inference/request.js +32 -0
  25. package/dist/esm/inference/scopedExecution.js +83 -0
  26. package/dist/esm/products/access.js +57 -0
  27. package/dist/esm/products/billing.js +29 -0
  28. package/dist/esm/signIn.js +1 -1
  29. package/dist/types/.tsbuildinfo +1 -1
  30. package/dist/types/accountGraph.d.ts +23 -8
  31. package/dist/types/accountSubject.d.ts +210 -0
  32. package/dist/types/agency.d.ts +956 -190
  33. package/dist/types/agentKeys.d.ts +525 -0
  34. package/dist/types/capabilityBindings.d.ts +6 -0
  35. package/dist/types/deviceDirectory.d.ts +50 -50
  36. package/dist/types/deviceSession.d.ts +14 -14
  37. package/dist/types/externalIdentity.d.ts +4 -4
  38. package/dist/types/identity.d.ts +2 -2
  39. package/dist/types/index.d.ts +16 -2
  40. package/dist/types/inference/accountBilling.d.ts +30 -30
  41. package/dist/types/inference/aliaModelRelease.d.ts +4 -4
  42. package/dist/types/inference/catalogue.d.ts +200 -10
  43. package/dist/types/inference/economics.d.ts +376 -0
  44. package/dist/types/inference/entitlement.d.ts +47 -47
  45. package/dist/types/inference/inbox.d.ts +12 -12
  46. package/dist/types/inference/modelDocumentation.d.ts +8 -8
  47. package/dist/types/inference/priceVersion.d.ts +4 -4
  48. package/dist/types/inference/providerConnection.d.ts +38 -38
  49. package/dist/types/inference/realtime.d.ts +32 -32
  50. package/dist/types/inference/request.d.ts +2289 -16
  51. package/dist/types/inference/routingPolicy.d.ts +20 -20
  52. package/dist/types/inference/scopedExecution.d.ts +202 -0
  53. package/dist/types/inference/streamEvents.d.ts +4 -4
  54. package/dist/types/inference/usage.d.ts +12 -12
  55. package/dist/types/keyRotation.d.ts +2 -2
  56. package/dist/types/notifications.d.ts +4 -4
  57. package/dist/types/oauth.d.ts +30 -30
  58. package/dist/types/products/access.d.ts +487 -0
  59. package/dist/types/products/billing.d.ts +563 -0
  60. package/dist/types/recommendations.d.ts +2 -2
  61. package/dist/types/sessionStatus.d.ts +10 -10
  62. package/dist/types/signIn.d.ts +6 -6
  63. package/dist/types/transparency.d.ts +2 -2
  64. package/package.json +1 -1
@@ -25,6 +25,7 @@
25
25
  */
26
26
  import { decisionInputSchema } from './decisions.js';
27
27
  import { z } from "zod";
28
+ import { scopedExecutionSchema, SCOPED_REQUEST_ENVELOPE_VERSION } from "./scopedExecution.js";
28
29
  import { inferenceAttributionSchema } from "./attribution.js";
29
30
  import { inferenceApiFormatSchema, inferenceModalitySchema, reasoningEffortSchema, } from "./catalogue.js";
30
31
  import { idempotencyKeySchema, inferenceTimestampSchema } from "./identifiers.js";
@@ -351,6 +352,8 @@ export const inferenceRequestSchema = z
351
352
  .object({
352
353
  /** See `version.ts`: this is the Oxy→data-plane request envelope. */
353
354
  schemaVersion: z.literal(2),
355
+ /** Recognized so v2 refuses rather than silently stripping a restriction. */
356
+ scopedExecution: scopedExecutionSchema.optional(),
354
357
  attribution: inferenceAttributionSchema,
355
358
  target: routingTargetSchema,
356
359
  modality: inferenceModalitySchema,
@@ -405,6 +408,8 @@ export const inferenceRequestSchema = z
405
408
  authorizedRoutes: z.array(authorizedRouteSchema).min(1).optional(),
406
409
  })
407
410
  .superRefine((request, ctx) => {
411
+ if (request.scopedExecution !== undefined)
412
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution requires envelope v3." });
408
413
  if (request.input.format === "decisions" || request.client.apiFormat === "decisions") {
409
414
  const exactModel = request.target.kind === "model" && request.target.modelReference.includes('@');
410
415
  const foreignRoute = request.authorizedRoutes?.some((route) => request.target.kind !== "model" || route.modelReference !== request.target.modelReference || route.substitution !== "same_model");
@@ -534,3 +539,30 @@ export const inferenceRequestSchema = z
534
539
  });
535
540
  }
536
541
  });
542
+ /** Explicit restrictive generation: old v2 receivers reject this version whole. */
543
+ export const scopedInferenceRequestSchema = inferenceRequestSchema.innerType()
544
+ .extend({ schemaVersion: z.literal(SCOPED_REQUEST_ENVELOPE_VERSION), scopedExecution: scopedExecutionSchema })
545
+ .superRefine((request, ctx) => {
546
+ const { scopedExecution: scope, ...base } = request;
547
+ const legacy = inferenceRequestSchema.safeParse({ ...base, schemaVersion: 2 });
548
+ if (!legacy.success)
549
+ for (const issue of legacy.error.issues)
550
+ ctx.addIssue(issue);
551
+ const principal = request.attribution.principal;
552
+ const route = request.authorizedRoutes?.[0];
553
+ if (request.input.format !== "decisions" || request.client.apiFormat !== "decisions" ||
554
+ scope.requestId !== request.attribution.requestId ||
555
+ scope.idempotencyKey !== request.idempotencyKey ||
556
+ scope.principal.accountId !== principal.billing.accountId ||
557
+ scope.principal.applicationId !== principal.applicationId ||
558
+ scope.principal.credentialId !== principal.credentialId ||
559
+ scope.principal.environment !== principal.environment ||
560
+ scope.policy.routingPolicyId !== request.routingPolicy.routingPolicyId ||
561
+ scope.policy.policyVersion !== request.routingPolicy.policyVersion ||
562
+ request.authorizedRoutes?.length !== 1 || route?.customerProviderCredential !== undefined ||
563
+ route?.deploymentId !== scope.deploymentId || route?.provider !== scope.provider ||
564
+ route?.modelReference !== scope.modelReference ||
565
+ request.target.kind !== "model" || request.target.modelReference !== scope.modelReference) {
566
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution must restrict the exact attributed decisions request and one platform route." });
567
+ }
568
+ });
@@ -0,0 +1,83 @@
1
+ import { z } from "zod";
2
+ import { deploymentIdSchema, idempotencyKeySchema, inferenceEnvironmentSchema, inferenceProviderSlugSchema, modelReferenceSchema, requestIdSchema, } from "./identifiers.js";
3
+ import { exactDecimalSchema } from "./money.js";
4
+ /** Explicit extension negotiation; never replaces the legacy 3.5 handshake. */
5
+ export const SCOPED_EXECUTION_CONTRACT_VERSION = "3.6.0";
6
+ /** Scoped only; normal envelope v2 and metadata 3.5 remain unchanged. */
7
+ export const SCOPED_REQUEST_ENVELOPE_VERSION = 3;
8
+ const identity = z.string().min(1).max(256);
9
+ const sha256 = z.string().regex(/^[0-9a-f]{64}$/);
10
+ const maxCost = exactDecimalSchema.refine((value) => {
11
+ if (!exactDecimalSchema.safeParse(value).success)
12
+ return false;
13
+ const [whole, fraction = ""] = value.split(".");
14
+ const units = BigInt(whole) * 1000000000000n + BigInt(fraction.padEnd(12, "0"));
15
+ return units > 0n && units <= 10000000000n;
16
+ }, "scoped cost must be positive and at most 0.01 USD");
17
+ /** Restriction only: none of these identities grants catalogue eligibility. */
18
+ export const scopedExecutionAudienceSchema = z
19
+ .object({
20
+ permitId: identity,
21
+ idempotencyKey: idempotencyKeySchema,
22
+ fixtureSha256: sha256,
23
+ expiresAt: z.string().datetime(),
24
+ principal: z
25
+ .object({
26
+ accountId: identity,
27
+ applicationId: identity,
28
+ credentialId: identity,
29
+ environment: inferenceEnvironmentSchema,
30
+ })
31
+ .strict(),
32
+ policy: z
33
+ .object({
34
+ routingPolicyId: z.string().min(1).max(128),
35
+ policyVersion: z.number().int().positive().safe(),
36
+ })
37
+ .strict(),
38
+ deploymentId: deploymentIdSchema,
39
+ provider: inferenceProviderSlugSchema,
40
+ keyId: identity,
41
+ modelReference: modelReferenceSchema.refine((value) => value.includes("@"), "must pin a revision"),
42
+ upstreamModelId: identity,
43
+ priceVersionId: identity,
44
+ providerRateCardVersionId: identity,
45
+ providerSourceVersion: identity,
46
+ maxCostUsd: maxCost,
47
+ })
48
+ .strict();
49
+ export const scopedExecutionSchema = scopedExecutionAudienceSchema
50
+ .extend({
51
+ requestId: requestIdSchema,
52
+ snapshotId: identity,
53
+ catalogueEvidenceHash: sha256,
54
+ })
55
+ .strict();
56
+ /**
57
+ * Canonical JSON wire bytes: recursive UTF-16 key order, JSON string/number
58
+ * encoding, arrays in order, no whitespace. Hash the whole signed input, not a
59
+ * reparsed/defaulted decision. Reject non-JSON values rather than dropping them.
60
+ */
61
+ export function canonicalScopedExecutionJson(value) {
62
+ if (value === null || typeof value === "string" || typeof value === "boolean")
63
+ return JSON.stringify(value);
64
+ if (typeof value === "number" && Number.isFinite(value))
65
+ return JSON.stringify(value);
66
+ if (Array.isArray(value)) {
67
+ const entries = Array.from(value, (entry, index) => {
68
+ if (!(index in value))
69
+ throw new Error("Scoped execution requires dense JSON arrays.");
70
+ return canonicalScopedExecutionJson(entry);
71
+ });
72
+ return `[${entries.join(",")}]`;
73
+ }
74
+ if (typeof value === "object" &&
75
+ value !== null &&
76
+ Object.getPrototypeOf(value) === Object.prototype) {
77
+ const entries = Object.keys(value)
78
+ .sort()
79
+ .map((key) => `${JSON.stringify(key)}:${canonicalScopedExecutionJson(value[key])}`);
80
+ return `{${entries.join(",")}}`;
81
+ }
82
+ throw new Error("Scoped execution requires JSON wire values.");
83
+ }
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ import { oxyAccountIdSchema, oxyApplicationIdSchema } from '../inference/identifiers.js';
3
+ const identifier = z.string().min(1).max(160);
4
+ const count = z.number().int().nonnegative().safe();
5
+ const period = z.object({ start: z.string().datetime(), end: z.string().datetime() }).strict()
6
+ .refine(value => Date.parse(value.end) > Date.parse(value.start), 'period end must follow start');
7
+ /** Product ownership and audience are registered together; branding grants no trust. */
8
+ export const productDefinitionSchema = z.object({
9
+ schemaVersion: z.literal(1), id: identifier, ownerAccountId: oxyAccountIdSchema,
10
+ applicationId: oxyApplicationIdSchema,
11
+ }).strict();
12
+ export const subjectProductAccessQuerySchema = z.object({
13
+ schemaVersion: z.literal(1), subjectAccountId: oxyAccountIdSchema, productId: identifier,
14
+ }).strict();
15
+ /** Every quota declares its combination rule; there is no commercial default. */
16
+ export const productBenefitSchema = z.discriminatedUnion('kind', [
17
+ z.object({ kind: z.literal('capability'), productId: identifier, key: identifier }).strict(),
18
+ z.object({ kind: z.literal('quota'), productId: identifier, key: identifier,
19
+ unit: identifier, included: count, combination: z.enum(['maximum', 'sum', 'exclusive']) }).strict(),
20
+ ]);
21
+ /** A version names a frozen offer. An empty bundle grants nothing. */
22
+ export const productOfferSchema = z.object({
23
+ schemaVersion: z.literal(1), id: identifier, version: z.number().int().positive().safe(),
24
+ kind: z.enum(['individual', 'bundle']), benefits: z.array(productBenefitSchema),
25
+ }).strict().refine(value => value.kind === 'bundle' || new Set(value.benefits.map(benefit => benefit.productId)).size <= 1, 'individual offers cannot cover multiple products');
26
+ export const productSubscriptionSourceSchema = z.object({
27
+ schemaVersion: z.literal(1), id: identifier,
28
+ beneficiaryAccountId: oxyAccountIdSchema, payerAccountId: oxyAccountIdSchema,
29
+ provider: z.enum(['stripe', 'peable']), providerSubscriptionId: identifier,
30
+ status: z.enum(['active', 'trialing', 'past_due', 'unpaid', 'canceled', 'paused', 'incomplete', 'incomplete_expired']),
31
+ period, cancelAtPeriodEnd: z.boolean(),
32
+ }).strict();
33
+ /** A frozen paid-period/offer segment; upgrades append, never rewrite it. */
34
+ export const productOfferSegmentSchema = z.object({
35
+ schemaVersion: z.literal(1), id: identifier, subscriptionId: identifier,
36
+ beneficiaryAccountId: oxyAccountIdSchema, offerId: identifier,
37
+ offerVersion: z.number().int().positive().safe(), origin: z.enum(['individual', 'bundle']), period,
38
+ }).strict();
39
+ /** Provenance survives cancellation: deactivate a source, never delete history. */
40
+ export const productAccessGrantSchema = z.object({
41
+ schemaVersion: z.literal(1), id: identifier, sourceSegmentId: identifier,
42
+ beneficiaryAccountId: oxyAccountIdSchema, offerId: identifier,
43
+ offerVersion: z.number().int().positive().safe(),
44
+ origin: z.enum(['individual', 'bundle']), benefit: productBenefitSchema,
45
+ period, revokedAt: z.string().datetime().nullable(),
46
+ }).strict();
47
+ /** Access answers contain no payer, provider reference, price or account balance. */
48
+ export const subjectProductAccessSchema = z.object({
49
+ schemaVersion: z.literal(1), subjectAccountId: oxyAccountIdSchema, productId: identifier,
50
+ evaluatedAt: z.string().datetime(),
51
+ capabilities: z.array(z.object({ key: identifier, grantIds: z.array(identifier) }).strict()),
52
+ quotas: z.array(z.object({ key: identifier, unit: identifier, included: count,
53
+ combination: z.enum(['maximum', 'sum', 'exclusive']), grantIds: z.array(identifier) }).strict()),
54
+ conflicts: z.array(z.object({ key: identifier,
55
+ reason: z.enum(['combination_mismatch', 'unit_mismatch', 'exclusive_overlap', 'unsafe_total']),
56
+ grantIds: z.array(identifier) }).strict()),
57
+ }).strict();
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { oxyAccountIdSchema } from '../inference/identifiers.js';
3
+ const id = z.string().min(1).max(160);
4
+ const name = z.string().min(1).max(100);
5
+ const count = z.number().int().nonnegative().safe();
6
+ const period = z.object({ start: z.string().datetime(), end: z.string().datetime() }).strict()
7
+ .refine(value => Date.parse(value.end) > Date.parse(value.start), 'Period end must follow start');
8
+ /** Self-service provenance; no payer/provider identifiers or balances in access metadata. */
9
+ export const productSubscriptionSummarySchema = z.object({ sourceId: id,
10
+ status: z.enum(['active', 'trialing', 'past_due', 'unpaid', 'canceled', 'paused', 'incomplete', 'incomplete_expired']),
11
+ period, cancelAtPeriodEnd: z.boolean(), canCancel: z.boolean(),
12
+ offers: z.array(z.object({ segmentId: id, offerId: id, offerVersion: z.number().int().positive().safe(),
13
+ displayName: name, origin: z.enum(['individual', 'bundle']), period, current: z.boolean(),
14
+ products: z.array(z.object({ id, displayName: name }).strict()),
15
+ }).strict()),
16
+ }).strict();
17
+ export const productSubscriptionsResponseSchema = z.object({ subscriptions: z.array(productSubscriptionSummarySchema) }).strict();
18
+ export const subscriptionCreditGrantSchema = z.object({ id, invoiceId: id,
19
+ origin: z.enum(['subscription_payment', 'subscription_proration', 'subscription_promotional_grant']),
20
+ period, granted: count, consumed: count, clawed: count, remaining: count,
21
+ promotionId: id.nullable(), createdAt: z.string().datetime(),
22
+ }).strict().refine(value => BigInt(value.consumed) + BigInt(value.clawed) + BigInt(value.remaining) === BigInt(value.granted), 'Grant conservation differs');
23
+ export const subscriptionCreditGrantsResponseSchema = z.object({ grants: z.array(subscriptionCreditGrantSchema) }).strict();
24
+ export const cancelProductSubscriptionSchema = z.object({ sourceId: id, expectedSubjectAccountId: oxyAccountIdSchema.optional() }).strict();
25
+ /** Remote acceptance is distinct from completed local reconciliation. */
26
+ export const productSubscriptionCancellationResultSchema = z.union([
27
+ z.object({ sourceId: id, cancelAtPeriodEnd: z.literal(true) }).strict(),
28
+ z.object({ sourceId: id, reconciliationPending: z.literal(true) }).strict(),
29
+ ]);
@@ -194,7 +194,7 @@ export function isSecondFactorRequired(result) {
194
194
  * What a re-verification email code confirms. The code is bound to it: a code
195
195
  * asked for one change never authorises another, and the email names it.
196
196
  */
197
- export const REAUTH_ACTIONS = ['change_password', 'totp', 'link_commons', 'delete_account'];
197
+ export const REAUTH_ACTIONS = ['change_password', 'totp', 'link_commons', 'delete_account', 'credentials_manage'];
198
198
  /** `POST /users/me/reauth/email` */
199
199
  export const reauthEmailStartRequestSchema = z.object({ action: z.enum(REAUTH_ACTIONS) }).strict();
200
200
  /**