@greatwait/contracts 0.3.1 → 0.3.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 (95) hide show
  1. package/dist/attempt-diagnostics.d.ts +1 -1
  2. package/dist/attempt-diagnostics.js +13 -1
  3. package/dist/attempt-search.d.ts +2 -0
  4. package/dist/billing.d.ts +46 -0
  5. package/dist/billing.js +29 -0
  6. package/dist/callback-safety.js +5 -1
  7. package/dist/configuration.d.ts +2 -2
  8. package/dist/configuration.js +6 -3
  9. package/dist/delivery.d.ts +12 -1
  10. package/dist/delivery.js +1 -0
  11. package/dist/effective-limits.d.ts +4 -4
  12. package/dist/endpoints.d.ts +29 -0
  13. package/dist/endpoints.js +32 -1
  14. package/dist/forecast.d.ts +2 -2
  15. package/dist/http-request.d.ts +12 -2
  16. package/dist/http-request.js +31 -1
  17. package/dist/index.d.ts +8 -7
  18. package/dist/index.js +8 -7
  19. package/dist/mcp.js +1 -0
  20. package/dist/operational-config.d.ts +174 -22
  21. package/dist/operational-config.js +207 -74
  22. package/dist/operations.d.ts +334 -52
  23. package/dist/operations.js +195 -34
  24. package/dist/project-notifications.d.ts +35 -9
  25. package/dist/project-notifications.js +43 -12
  26. package/dist/protocol.d.ts +28 -0
  27. package/dist/protocol.js +23 -0
  28. package/dist/scheduling-records.d.ts +106 -16
  29. package/dist/scheduling-records.js +36 -12
  30. package/dist/scheduling.d.ts +155 -43
  31. package/dist/scheduling.js +188 -50
  32. package/dist/service-mode.d.ts +88 -0
  33. package/dist/service-mode.js +130 -0
  34. package/dist/tenancy.d.ts +54 -30
  35. package/dist/tenancy.js +35 -17
  36. package/dist/timing.d.ts +39 -0
  37. package/dist/timing.js +51 -0
  38. package/dist/zod-values.d.ts +1 -1
  39. package/dist/zod-values.js +1 -1
  40. package/dist/zod.d.ts +1 -1
  41. package/dist/zod.js +1 -1
  42. package/generated/v1/examples/billing.noticesdismiss.request.json +3 -0
  43. package/generated/v1/examples/billing.noticesdismiss.response.json +6 -0
  44. package/generated/v1/examples/billing.reconcile.response.json +12 -0
  45. package/generated/v1/examples/billing.summary.response.json +12 -0
  46. package/generated/v1/examples/executions.list.response.json +1 -0
  47. package/generated/v1/examples/limits.read.response.json +1 -1
  48. package/generated/v1/examples/projectnotifications.rotateSigningKey.response.json +1 -0
  49. package/generated/v1/examples/projects.list.response.json +0 -6
  50. package/generated/v1/examples/projects.read.response.json +14 -0
  51. package/generated/v1/examples/schedules.list.response.json +1 -3
  52. package/generated/v1/examples/schedules.summary.response.json +174 -0
  53. package/generated/v1/examples/timing.summary.response.json +33 -1
  54. package/generated/v1/manifest.json +79 -2
  55. package/generated/v1/openapi.json +4084 -2023
  56. package/generated/v1/policy-matrix.json +22 -1
  57. package/generated/v1/schemas/attempts.list.response.json +10 -0
  58. package/generated/v1/schemas/attempts.read.response.json +10 -0
  59. package/generated/v1/schemas/attempts.search.response.json +4 -0
  60. package/generated/v1/schemas/billing.notices.query.json +4 -0
  61. package/generated/v1/schemas/billing.noticesdismiss.request.json +12 -0
  62. package/generated/v1/schemas/billing.noticesdismiss.response.json +22 -0
  63. package/generated/v1/schemas/billing.reconcile.response.json +43 -0
  64. package/generated/v1/schemas/billing.summary.response.json +43 -0
  65. package/generated/v1/schemas/endpoints.list.query.json +15 -0
  66. package/generated/v1/schemas/executions.list.response.json +4 -0
  67. package/generated/v1/schemas/occurrences.list.response.json +4 -0
  68. package/generated/v1/schemas/occurrences.read.response.json +4 -0
  69. package/generated/v1/schemas/occurrences.redeliver.response.json +10 -0
  70. package/generated/v1/schemas/projectnotifications.read.response.json +4 -0
  71. package/generated/v1/schemas/projectnotifications.rotateSigningKey.response.json +4 -0
  72. package/generated/v1/schemas/projectnotifications.update.request.json +41 -17
  73. package/generated/v1/schemas/projectnotifications.update.response.json +4 -0
  74. package/generated/v1/schemas/projects.list.response.json +0 -27
  75. package/generated/v1/schemas/projects.read.response-headers.json +11 -0
  76. package/generated/v1/schemas/projects.read.response.json +79 -0
  77. package/generated/v1/schemas/schedules.archive.response.json +8 -0
  78. package/generated/v1/schemas/schedules.cancel.response.json +8 -0
  79. package/generated/v1/schemas/schedules.create.request.json +1 -1
  80. package/generated/v1/schemas/schedules.create.response.json +8 -0
  81. package/generated/v1/schemas/schedules.list.query.json +6 -0
  82. package/generated/v1/schemas/schedules.list.response.json +4 -0
  83. package/generated/v1/schemas/schedules.pause.response.json +8 -0
  84. package/generated/v1/schemas/schedules.read.response.json +8 -0
  85. package/generated/v1/schemas/schedules.replace.request.json +1 -1
  86. package/generated/v1/schemas/schedules.replace.response.json +8 -0
  87. package/generated/v1/schemas/schedules.resume.response.json +8 -0
  88. package/generated/v1/schemas/schedules.summary.query.json +11 -0
  89. package/generated/v1/schemas/schedules.summary.response.json +144 -0
  90. package/generated/v1/schemas/timing.summary.response.json +69 -0
  91. package/generated/v1/snippets/billing.noticesdismiss.json +6 -0
  92. package/generated/v1/snippets/projectnotifications.rotateSigningKey.json +1 -1
  93. package/generated/v1/snippets/projects.read.json +6 -0
  94. package/generated/v1/snippets/schedules.summary.json +6 -0
  95. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { z } from "./zod.js";
2
2
  import { environmentKindSchema } from "./authority.js";
3
- import { callbackSigningKeyIdSchema, occurrenceIdSchema, projectIdSchema, scheduleIdSchema, } from "./identifiers.js";
3
+ import { callbackSigningKeyIdSchema, endpointIdSchema, occurrenceIdSchema, projectIdSchema, scheduleIdSchema, } from "./identifiers.js";
4
4
  import { memberIdSchema } from "./members.js";
5
5
  import { timestampSchema } from "./time.js";
6
6
  import { pageRequestSchema, requiredIdempotencyRequestHeaderSchema, } from "./protocol.js";
@@ -23,13 +23,26 @@ export const notificationEmailSettingsSchema = z.strictObject({
23
23
  scheduleKinds: z.enum(["both", "one-shot", "recurring"]),
24
24
  });
25
25
  export const statusWebhookEventSchema = z.enum(["failed"]);
26
+ const statusWebhookEventsSchema = z
27
+ .array(statusWebhookEventSchema)
28
+ .min(1)
29
+ .max(1)
30
+ .refine((events) => new Set(events).size === events.length, "events must be unique");
31
+ /**
32
+ * The earlier configuration: a bare URL. Still accepted (W9-84): the endpoint
33
+ * at that URL is found or created, as endpoints.ensure does, and linked.
34
+ */
26
35
  export const statusWebhookConfigurationSchema = z.strictObject({
27
36
  url: z.string().url().max(2_048),
28
- events: z
29
- .array(statusWebhookEventSchema)
30
- .min(1)
31
- .max(1)
32
- .refine((events) => new Set(events).size === events.length, "events must be unique"),
37
+ events: statusWebhookEventsSchema,
38
+ });
39
+ /**
40
+ * The status webhook's destination (W9-84): a callback endpoint in this
41
+ * project and environment, whose URL, headers and signing keys apply.
42
+ */
43
+ export const statusWebhookEndpointConfigurationSchema = z.strictObject({
44
+ endpoint: endpointIdSchema,
45
+ events: statusWebhookEventsSchema,
33
46
  });
34
47
  export const projectNotificationSettingsSchema = z.strictObject({
35
48
  project: projectIdSchema,
@@ -38,6 +51,9 @@ export const projectNotificationSettingsSchema = z.strictObject({
38
51
  email: notificationEmailSettingsSchema,
39
52
  statusWebhook: statusWebhookConfigurationSchema
40
53
  .extend({
54
+ /** The destination endpoint; absent only for a URL saved before W9-84 without a key. */
55
+ endpoint: endpointIdSchema.optional(),
56
+ /** The key that signs: the endpoint's next key while one is staged, else its current one. */
41
57
  signingKey: z.strictObject({ id: callbackSigningKeyIdSchema }).optional(),
42
58
  revision: z.number().int().positive(),
43
59
  })
@@ -47,7 +63,13 @@ export const projectNotificationSettingsUpdateRequestSchema = z
47
63
  .strictObject({
48
64
  expectedRevision: z.number().int().positive(),
49
65
  email: notificationEmailSettingsSchema.optional(),
50
- statusWebhook: statusWebhookConfigurationSchema.nullable().optional(),
66
+ statusWebhook: z
67
+ .union([
68
+ statusWebhookEndpointConfigurationSchema,
69
+ statusWebhookConfigurationSchema,
70
+ ])
71
+ .nullable()
72
+ .optional(),
51
73
  })
52
74
  .refine((request) => request.email !== undefined || request.statusWebhook !== undefined, "choose settings to change");
53
75
  export const statusSigningKeyRequestSchema = z.strictObject({
@@ -57,6 +79,11 @@ export const statusSigningKeyCreatedSchema = z.strictObject({
57
79
  settings: projectNotificationSettingsSchema,
58
80
  keyId: callbackSigningKeyIdSchema,
59
81
  secret: z.string().min(1),
82
+ /**
83
+ * Kept for compatibility (W9-84). The secret is the destination endpoint's,
84
+ * so a signed-in member can also reveal it on the endpoint's page, as for
85
+ * every endpoint secret; `shownOnce` no longer means this is the only copy.
86
+ */
60
87
  shownOnce: z.literal(true),
61
88
  });
62
89
  /** Safe notification payload: no customer request or response content. */
@@ -144,6 +171,8 @@ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
144
171
  "revision_conflict",
145
172
  "idempotency_key_reused",
146
173
  "rate_limited",
174
+ "scope_missing",
175
+ "state_conflict",
147
176
  ],
148
177
  requestHeaders: requiredIdempotencyRequestHeaderSchema,
149
178
  request: projectNotificationSettingsUpdateRequestSchema,
@@ -161,7 +190,7 @@ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
161
190
  : "Update delivery notification settings",
162
191
  description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
163
192
  ? ""
164
- : "An admin updates this project's environment preferences at an expected revision. Selected recipients must be current organization members; arbitrary email addresses are not accepted. Null disables the status webhook. Changing URL or filters never reveals a signing secret. Mint the first key through the secure signing-key operation before webhook delivery starts. Failed means final unsuccessful settlement. Redelivery never repeats it. Failed-event webhook calls and their retries are free. Every failed occurrence is emailed separately; no summary window suppresses failures.",
193
+ : "An admin updates this project's environment preferences at an expected revision. Selected recipients must be current organization members; arbitrary email addresses are not accepted. The status webhook names its destination as `endpoint`, an enabled callback endpoint in this project and environment, which needs `endpoints:read`: failure events go to its URL with its headers, signed with its key, and delivery starts at once. A `url` instead is the earlier form: the endpoint at that address is found or created (the endpoints.ensure rules; creating needs `endpoints:write`) and linked. Without the scope a form needs, the request is refused as `scope_missing`. Null disables the status webhook. No signing secret is returned; a signed-in member reveals it on the endpoint's page. Failed means final unsuccessful settlement. Redelivery never repeats it. Failed-event webhook calls and their retries are free. Every failed occurrence is emailed separately; no summary window suppresses failures.",
165
194
  },
166
195
  {
167
196
  ...common,
@@ -172,14 +201,15 @@ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
172
201
  mutates: true,
173
202
  mcp: {
174
203
  kind: "unavailable",
175
- reason: "Minting or rotating returns a one-time signing secret. MCP has no negotiated secure-result channel that keeps it out of ordinary tool history. Configure preferences with projectnotifications_update, then use the dashboard or an authenticated REST/SDK/CLI client for the secret.",
204
+ reason: "Rotating returns a signing secret, and MCP has no negotiated secure-result channel that keeps it out of ordinary tool history. Choose the status webhook's endpoint with projectnotifications_update; reveal or rotate that endpoint's key on its page in the dashboard, or with endpoints.rotateSigningKey through an authenticated REST/SDK/CLI client.",
176
205
  },
177
- scopes: ["projects:administer"],
206
+ scopes: ["projects:administer", "endpoints:write"],
178
207
  problems: [
179
208
  ...common.problems,
180
209
  "revision_conflict",
181
210
  "state_conflict",
182
211
  "capability_not_configured",
212
+ "scope_missing",
183
213
  ],
184
214
  request: statusSigningKeyRequestSchema,
185
215
  requestExample: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
@@ -197,6 +227,7 @@ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
197
227
  statusWebhook: {
198
228
  url: "https://hooks.example.com/status",
199
229
  events: ["failed"],
230
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
200
231
  revision: 2,
201
232
  signingKey: { id: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
202
233
  },
@@ -207,10 +238,10 @@ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
207
238
  },
208
239
  summary: globals.GREATWAIT_API_REQUEST_REGISTRY
209
240
  ? ""
210
- : "Mint or rotate the status webhook signing key",
241
+ : "Rotate the status webhook endpoint's signing key",
211
242
  description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
212
243
  ? ""
213
- : "An admin mints the first key or replaces the current key for an already configured status webhook at an expected revision. The secret appears only in this successful response and cannot be read back. A lost response requires a fresh revision read and another rotation. Queued deliveries using the replaced signing key are suppressed. The request is not automatically replayable; stale retries are refused. The signature covers the exact emitted body bytes.",
244
+ : "The earlier form, kept for existing clients: at an expected revision, rotate the signing key of the configured status webhook's endpoint exactly as endpoints.rotateSigningKey does with its default overlap. The key is the endpoint's and is shared with every schedule using it, so this also needs `endpoints:write`; without it the request is refused as `scope_missing`. A webhook saved as a bare URL is first linked to the endpoint at that address. New deliveries are signed with the new key at once, and receivers keep accepting the previous key until the overlap ends. The secret appears in this successful response and, like every endpoint secret, is also revealable by a signed-in member on the endpoint's page; `shownOnce` is kept for compatibility. The request is not automatically replayable; stale retries are refused. The signature covers the exact emitted body bytes.",
214
245
  },
215
246
  {
216
247
  ...common,
@@ -39,6 +39,18 @@ export type PageRequest = z.infer<typeof pageRequestSchema>;
39
39
  */
40
40
  export declare const SCHEDULE_ORDERS: readonly ["created", "due"];
41
41
  export type ScheduleOrder = (typeof SCHEDULE_ORDERS)[number];
42
+ /**
43
+ * Which way a schedules listing walks its order (W9-80, FXO-3446).
44
+ *
45
+ * `asc` is what every listing has always done and keeps by default, so a
46
+ * client that never heard of this parameter sees nothing change. `desc` is
47
+ * newest-created first under `created` (the newest schedule is one row away
48
+ * rather than a whole book away) and latest-due first under `due`. A cursor is
49
+ * a position in one direction only: one issued walking `desc` is refused under
50
+ * `asc`, and the other way round.
51
+ */
52
+ export declare const SCHEDULE_DIRECTIONS: readonly ["asc", "desc"];
53
+ export type ScheduleDirection = (typeof SCHEDULE_DIRECTIONS)[number];
42
54
  /**
43
55
  * A schedules listing: the page, optionally one endpoint, and how to order it.
44
56
  *
@@ -58,6 +70,10 @@ export declare const scheduleListRequestSchema: import("zod").ZodObject<{
58
70
  due: "due";
59
71
  created: "created";
60
72
  }>>;
73
+ direction: import("zod").ZodDefault<import("zod").ZodEnum<{
74
+ asc: "asc";
75
+ desc: "desc";
76
+ }>>;
61
77
  external_identifier: import("zod").ZodOptional<import("zod").ZodString>;
62
78
  tag: import("zod").ZodOptional<import("zod").ZodString>;
63
79
  status: import("zod").ZodOptional<import("zod").ZodEnum<{
@@ -245,6 +261,18 @@ export type ScheduleListRequestParse = {
245
261
  readonly ok: false;
246
262
  readonly errors: readonly FieldError[];
247
263
  };
264
+ /**
265
+ * Any listing request whose fields are page parameters plus string filters,
266
+ * read from a query string under the same rules as {@link parsePageRequest}
267
+ * (W9-80: the endpoints listing's filters).
268
+ */
269
+ export declare function parseListingRequest<TSchema extends z.ZodTypeAny>(query: URLSearchParams, schema: TSchema): {
270
+ readonly ok: true;
271
+ readonly page: z.infer<TSchema>;
272
+ } | {
273
+ readonly ok: false;
274
+ readonly errors: readonly FieldError[];
275
+ };
248
276
  /** A schedules listing request: the page, and the endpoint filter if given. */
249
277
  export declare function parseScheduleListRequest(query: URLSearchParams): ScheduleListRequestParse;
250
278
  export type HistoryPageRequestParse = {
package/dist/protocol.js CHANGED
@@ -43,6 +43,17 @@ export const pageRequestSchema = /* @__PURE__ */ (() => z.object({
43
43
  * creation instant.
44
44
  */
45
45
  export const SCHEDULE_ORDERS = ["created", "due"];
46
+ /**
47
+ * Which way a schedules listing walks its order (W9-80, FXO-3446).
48
+ *
49
+ * `asc` is what every listing has always done and keeps by default, so a
50
+ * client that never heard of this parameter sees nothing change. `desc` is
51
+ * newest-created first under `created` (the newest schedule is one row away
52
+ * rather than a whole book away) and latest-due first under `due`. A cursor is
53
+ * a position in one direction only: one issued walking `desc` is refused under
54
+ * `asc`, and the other way round.
55
+ */
56
+ export const SCHEDULE_DIRECTIONS = ["asc", "desc"];
46
57
  /**
47
58
  * A schedules listing: the page, optionally one endpoint, and how to order it.
48
59
  *
@@ -58,6 +69,10 @@ export const SCHEDULE_ORDERS = ["created", "due"];
58
69
  export const scheduleListRequestSchema = /* @__PURE__ */ (() => pageRequestSchema.extend({
59
70
  ...scheduleSelectionSchema.shape,
60
71
  order: z.enum(SCHEDULE_ORDERS).default("created"),
72
+ direction: z
73
+ .enum(SCHEDULE_DIRECTIONS)
74
+ .default("asc")
75
+ .describe("asc (default) walks the order oldest-created or soonest-due first; desc walks it newest-created or latest-due first. A cursor continues only in the direction that issued it."),
61
76
  }))();
62
77
  /**
63
78
  * Which end of a history a page walks from.
@@ -287,6 +302,14 @@ function parametersOf(schema) {
287
302
  export function parsePageRequest(query) {
288
303
  return parseListing(query, pageRequestSchema);
289
304
  }
305
+ /**
306
+ * Any listing request whose fields are page parameters plus string filters,
307
+ * read from a query string under the same rules as {@link parsePageRequest}
308
+ * (W9-80: the endpoints listing's filters).
309
+ */
310
+ export function parseListingRequest(query, schema) {
311
+ return parseListing(query, schema);
312
+ }
290
313
  /** A schedules listing request: the page, and the endpoint filter if given. */
291
314
  export function parseScheduleListRequest(query) {
292
315
  return parseListing(query, scheduleListRequestSchema);
@@ -34,11 +34,21 @@ export declare const portableScheduleRecordSchema: import("zod").ZodObject<{
34
34
  name: import("zod").ZodString;
35
35
  suppressed: import("zod").ZodLiteral<true>;
36
36
  }, import("zod/v4/core").$strict>]>>;
37
- encryptedTemplate: import("zod").ZodOptional<import("zod").ZodObject<{
37
+ encryptedTemplate: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
38
38
  keyId: import("zod").ZodLiteral<"v1">;
39
39
  nonce: import("zod").ZodString;
40
40
  ciphertext: import("zod").ZodString;
41
- }, import("zod/v4/core").$strict>>;
41
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
42
+ keyId: import("zod").ZodLiteral<"v1">;
43
+ nonce: import("zod").ZodString;
44
+ ciphertext: import("zod").ZodString;
45
+ version: import("zod").ZodLiteral<2>;
46
+ codec: import("zod").ZodEnum<{
47
+ identity: "identity";
48
+ gzip: "gzip";
49
+ }>;
50
+ originalBytes: import("zod").ZodNumber;
51
+ }, import("zod/v4/core").$strict>]>>;
42
52
  }, import("zod/v4/core").$strict>>;
43
53
  httpTemplateRetentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
44
54
  authority: import("zod").ZodObject<{
@@ -106,9 +116,14 @@ export declare const portableScheduleRecordSchema: import("zod").ZodObject<{
106
116
  generation: import("zod").ZodNumber;
107
117
  id: import("zod").ZodString;
108
118
  latencyClass: import("zod").ZodEnum<{
109
- realtime: "realtime";
110
119
  bulk: "bulk";
120
+ realtime: "realtime";
111
121
  }>;
122
+ requestedLatencyClass: import("zod").ZodOptional<import("zod").ZodEnum<{
123
+ bulk: "bulk";
124
+ realtime: "realtime";
125
+ auto: "auto";
126
+ }>>;
112
127
  lateness: import("zod").ZodObject<{
113
128
  maxStalenessSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
114
129
  policy: import("zod").ZodEnum<{
@@ -169,6 +184,7 @@ export declare const portableOccurrenceRecordSchema: import("zod").ZodObject<{
169
184
  id: import("zod").ZodString;
170
185
  plannedFor: import("zod").ZodString;
171
186
  schedule: import("zod").ZodString;
187
+ scheduleName: import("zod").ZodOptional<import("zod").ZodString>;
172
188
  sequence: import("zod").ZodNumber;
173
189
  settledAt: import("zod").ZodOptional<import("zod").ZodString>;
174
190
  state: import("zod").ZodEnum<{
@@ -269,6 +285,12 @@ export declare const portableAttemptRecordSchema: import("zod").ZodObject<{
269
285
  expired: "expired";
270
286
  not_captured: "not_captured";
271
287
  }>>;
288
+ requestUnavailable: import("zod").ZodOptional<import("zod").ZodEnum<{
289
+ schedule_changed: "schedule_changed";
290
+ endpoint_changed: "endpoint_changed";
291
+ endpoint_deleted: "endpoint_deleted";
292
+ payload_deleted: "payload_deleted";
293
+ }>>;
272
294
  responseHeaders: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
273
295
  name: import("zod").ZodString;
274
296
  value: import("zod").ZodString;
@@ -349,11 +371,21 @@ export declare const portableAttemptRecordSchema: import("zod").ZodObject<{
349
371
  name: import("zod").ZodString;
350
372
  suppressed: import("zod").ZodLiteral<true>;
351
373
  }, import("zod/v4/core").$strict>]>>;
352
- encryptedTemplate: import("zod").ZodOptional<import("zod").ZodObject<{
374
+ encryptedTemplate: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
353
375
  keyId: import("zod").ZodLiteral<"v1">;
354
376
  nonce: import("zod").ZodString;
355
377
  ciphertext: import("zod").ZodString;
356
- }, import("zod/v4/core").$strict>>;
378
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
379
+ keyId: import("zod").ZodLiteral<"v1">;
380
+ nonce: import("zod").ZodString;
381
+ ciphertext: import("zod").ZodString;
382
+ version: import("zod").ZodLiteral<2>;
383
+ codec: import("zod").ZodEnum<{
384
+ identity: "identity";
385
+ gzip: "gzip";
386
+ }>;
387
+ originalBytes: import("zod").ZodNumber;
388
+ }, import("zod/v4/core").$strict>]>>;
357
389
  }, import("zod/v4/core").$strict>>;
358
390
  httpPayloadRetentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
359
391
  authority: import("zod").ZodObject<{
@@ -371,7 +403,10 @@ export declare const portableAttemptRecordSchema: import("zod").ZodObject<{
371
403
  }, import("zod/v4/core").$strict>;
372
404
  export type PortableAttemptRecord = z.infer<typeof portableAttemptRecordSchema>;
373
405
  export declare const portableEncryptedPayloadRecordSchema: import("zod").ZodObject<{
374
- aadVersion: import("zod").ZodLiteral<"greatwait.schedule-payload.v1">;
406
+ aadVersion: import("zod").ZodEnum<{
407
+ "greatwait.schedule-payload.v1": "greatwait.schedule-payload.v1";
408
+ "greatwait.schedule-payload.v2": "greatwait.schedule-payload.v2";
409
+ }>;
375
410
  authority: import("zod").ZodObject<{
376
411
  environment: import("zod").ZodString;
377
412
  environmentKind: import("zod").ZodEnum<{
@@ -381,11 +416,21 @@ export declare const portableEncryptedPayloadRecordSchema: import("zod").ZodObje
381
416
  organization: import("zod").ZodString;
382
417
  project: import("zod").ZodString;
383
418
  }, import("zod/v4/core").$strict>;
384
- envelope: import("zod").ZodObject<{
419
+ envelope: import("zod").ZodUnion<readonly [import("zod").ZodObject<{
385
420
  ciphertext: import("zod").ZodString;
386
421
  keyId: import("zod").ZodString;
387
422
  nonce: import("zod").ZodString;
388
- }, import("zod/v4/core").$strict>;
423
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
424
+ ciphertext: import("zod").ZodString;
425
+ keyId: import("zod").ZodString;
426
+ nonce: import("zod").ZodString;
427
+ version: import("zod").ZodLiteral<2>;
428
+ codec: import("zod").ZodEnum<{
429
+ identity: "identity";
430
+ gzip: "gzip";
431
+ }>;
432
+ originalBytes: import("zod").ZodNumber;
433
+ }, import("zod/v4/core").$strict>]>;
389
434
  plaintextBytes: import("zod").ZodNumber;
390
435
  retentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
391
436
  schedule: import("zod").ZodString;
@@ -457,6 +502,12 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
457
502
  expired: "expired";
458
503
  not_captured: "not_captured";
459
504
  }>>;
505
+ requestUnavailable: import("zod").ZodOptional<import("zod").ZodEnum<{
506
+ schedule_changed: "schedule_changed";
507
+ endpoint_changed: "endpoint_changed";
508
+ endpoint_deleted: "endpoint_deleted";
509
+ payload_deleted: "payload_deleted";
510
+ }>>;
460
511
  responseHeaders: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
461
512
  name: import("zod").ZodString;
462
513
  value: import("zod").ZodString;
@@ -537,11 +588,21 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
537
588
  name: import("zod").ZodString;
538
589
  suppressed: import("zod").ZodLiteral<true>;
539
590
  }, import("zod/v4/core").$strict>]>>;
540
- encryptedTemplate: import("zod").ZodOptional<import("zod").ZodObject<{
591
+ encryptedTemplate: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
541
592
  keyId: import("zod").ZodLiteral<"v1">;
542
593
  nonce: import("zod").ZodString;
543
594
  ciphertext: import("zod").ZodString;
544
- }, import("zod/v4/core").$strict>>;
595
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
596
+ keyId: import("zod").ZodLiteral<"v1">;
597
+ nonce: import("zod").ZodString;
598
+ ciphertext: import("zod").ZodString;
599
+ version: import("zod").ZodLiteral<2>;
600
+ codec: import("zod").ZodEnum<{
601
+ identity: "identity";
602
+ gzip: "gzip";
603
+ }>;
604
+ originalBytes: import("zod").ZodNumber;
605
+ }, import("zod/v4/core").$strict>]>>;
545
606
  }, import("zod/v4/core").$strict>>;
546
607
  httpPayloadRetentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
547
608
  authority: import("zod").ZodObject<{
@@ -562,6 +623,7 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
562
623
  id: import("zod").ZodString;
563
624
  plannedFor: import("zod").ZodString;
564
625
  schedule: import("zod").ZodString;
626
+ scheduleName: import("zod").ZodOptional<import("zod").ZodString>;
565
627
  sequence: import("zod").ZodNumber;
566
628
  settledAt: import("zod").ZodOptional<import("zod").ZodString>;
567
629
  state: import("zod").ZodEnum<{
@@ -599,7 +661,10 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
599
661
  updatedAt: import("zod").ZodString;
600
662
  }, import("zod/v4/core").$strict>>;
601
663
  payload: import("zod").ZodOptional<import("zod").ZodObject<{
602
- aadVersion: import("zod").ZodLiteral<"greatwait.schedule-payload.v1">;
664
+ aadVersion: import("zod").ZodEnum<{
665
+ "greatwait.schedule-payload.v1": "greatwait.schedule-payload.v1";
666
+ "greatwait.schedule-payload.v2": "greatwait.schedule-payload.v2";
667
+ }>;
603
668
  authority: import("zod").ZodObject<{
604
669
  environment: import("zod").ZodString;
605
670
  environmentKind: import("zod").ZodEnum<{
@@ -609,11 +674,21 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
609
674
  organization: import("zod").ZodString;
610
675
  project: import("zod").ZodString;
611
676
  }, import("zod/v4/core").$strict>;
612
- envelope: import("zod").ZodObject<{
677
+ envelope: import("zod").ZodUnion<readonly [import("zod").ZodObject<{
613
678
  ciphertext: import("zod").ZodString;
614
679
  keyId: import("zod").ZodString;
615
680
  nonce: import("zod").ZodString;
616
- }, import("zod/v4/core").$strict>;
681
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
682
+ ciphertext: import("zod").ZodString;
683
+ keyId: import("zod").ZodString;
684
+ nonce: import("zod").ZodString;
685
+ version: import("zod").ZodLiteral<2>;
686
+ codec: import("zod").ZodEnum<{
687
+ identity: "identity";
688
+ gzip: "gzip";
689
+ }>;
690
+ originalBytes: import("zod").ZodNumber;
691
+ }, import("zod/v4/core").$strict>]>;
617
692
  plaintextBytes: import("zod").ZodNumber;
618
693
  retentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
619
694
  schedule: import("zod").ZodString;
@@ -677,11 +752,21 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
677
752
  name: import("zod").ZodString;
678
753
  suppressed: import("zod").ZodLiteral<true>;
679
754
  }, import("zod/v4/core").$strict>]>>;
680
- encryptedTemplate: import("zod").ZodOptional<import("zod").ZodObject<{
755
+ encryptedTemplate: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
756
+ keyId: import("zod").ZodLiteral<"v1">;
757
+ nonce: import("zod").ZodString;
758
+ ciphertext: import("zod").ZodString;
759
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
681
760
  keyId: import("zod").ZodLiteral<"v1">;
682
761
  nonce: import("zod").ZodString;
683
762
  ciphertext: import("zod").ZodString;
684
- }, import("zod/v4/core").$strict>>;
763
+ version: import("zod").ZodLiteral<2>;
764
+ codec: import("zod").ZodEnum<{
765
+ identity: "identity";
766
+ gzip: "gzip";
767
+ }>;
768
+ originalBytes: import("zod").ZodNumber;
769
+ }, import("zod/v4/core").$strict>]>>;
685
770
  }, import("zod/v4/core").$strict>>;
686
771
  httpTemplateRetentionDueAt: import("zod").ZodOptional<import("zod").ZodString>;
687
772
  authority: import("zod").ZodObject<{
@@ -749,9 +834,14 @@ export declare const portableSchedulingRecordSetSchema: import("zod").ZodObject<
749
834
  generation: import("zod").ZodNumber;
750
835
  id: import("zod").ZodString;
751
836
  latencyClass: import("zod").ZodEnum<{
752
- realtime: "realtime";
753
837
  bulk: "bulk";
838
+ realtime: "realtime";
754
839
  }>;
840
+ requestedLatencyClass: import("zod").ZodOptional<import("zod").ZodEnum<{
841
+ bulk: "bulk";
842
+ realtime: "realtime";
843
+ auto: "auto";
844
+ }>>;
755
845
  lateness: import("zod").ZodObject<{
756
846
  maxStalenessSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
757
847
  policy: import("zod").ZodEnum<{
@@ -116,19 +116,35 @@ const base64UrlBytesSchema = z
116
116
  .refine((value) => decodeBase64UrlBytes(value) !== undefined, {
117
117
  message: "must canonically encode base64url bytes",
118
118
  });
119
+ const portableLegacyPayloadEnvelopeSchema = z.strictObject({
120
+ ciphertext: base64UrlBytesSchema,
121
+ keyId: z
122
+ .string()
123
+ .min(1)
124
+ .max(128)
125
+ .regex(/^[A-Za-z0-9._:-]+$/u, "must be a safe key identifier"),
126
+ nonce: base64UrlBytesSchema.refine((value) => decodeBase64UrlBytes(value)?.length === 12, { message: "must encode exactly 12 bytes" }),
127
+ });
128
+ const portableV2PayloadEnvelopeSchema = portableLegacyPayloadEnvelopeSchema.extend({
129
+ version: z.literal(2),
130
+ codec: z.enum(["identity", "gzip"]),
131
+ originalBytes: z
132
+ .number()
133
+ .int()
134
+ .nonnegative()
135
+ .max(SCHEDULING_BOUNDS.payloadBytes),
136
+ });
119
137
  export const portableEncryptedPayloadRecordSchema = z
120
138
  .strictObject({
121
- aadVersion: z.literal(SCHEDULE_PAYLOAD_AAD_VERSION),
139
+ aadVersion: z.enum([
140
+ SCHEDULE_PAYLOAD_AAD_VERSION,
141
+ "greatwait.schedule-payload.v2",
142
+ ]),
122
143
  authority: portableAuthoritySchema,
123
- envelope: z.strictObject({
124
- ciphertext: base64UrlBytesSchema,
125
- keyId: z
126
- .string()
127
- .min(1)
128
- .max(128)
129
- .regex(/^[A-Za-z0-9._:-]+$/u, "must be a safe key identifier"),
130
- nonce: base64UrlBytesSchema.refine((value) => decodeBase64UrlBytes(value)?.length === 12, { message: "must encode exactly 12 bytes" }),
131
- }),
144
+ envelope: z.union([
145
+ portableLegacyPayloadEnvelopeSchema,
146
+ portableV2PayloadEnvelopeSchema,
147
+ ]),
132
148
  plaintextBytes: z
133
149
  .number()
134
150
  .int()
@@ -142,10 +158,18 @@ export const portableEncryptedPayloadRecordSchema = z
142
158
  .superRefine((payload, context) => {
143
159
  const ciphertext = decodeBase64UrlBytes(payload.envelope.ciphertext);
144
160
  if (ciphertext !== undefined &&
145
- ciphertext.length !== payload.plaintextBytes + 16) {
161
+ ("version" in payload.envelope
162
+ ? payload.aadVersion !== "greatwait.schedule-payload.v2" ||
163
+ payload.envelope.originalBytes !== payload.plaintextBytes ||
164
+ ciphertext.length < 16 ||
165
+ ciphertext.length > payload.plaintextBytes + 16 ||
166
+ (payload.envelope.codec === "identity" &&
167
+ ciphertext.length !== payload.plaintextBytes + 16)
168
+ : payload.aadVersion !== SCHEDULE_PAYLOAD_AAD_VERSION ||
169
+ ciphertext.length !== payload.plaintextBytes + 16)) {
146
170
  context.addIssue({
147
171
  code: "custom",
148
- message: "ciphertext must contain the plaintext bytes and a 16-byte AES-GCM tag",
172
+ message: "ciphertext and authenticated envelope metadata must match the payload version and size",
149
173
  path: ["envelope", "ciphertext"],
150
174
  });
151
175
  }