@greatwait/contracts 0.3.0 → 0.3.2

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 (104) 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/attempt-search.js +22 -19
  5. package/dist/authority.js +9 -9
  6. package/dist/billing.d.ts +46 -0
  7. package/dist/billing.js +29 -0
  8. package/dist/callback-safety.js +5 -1
  9. package/dist/configuration.d.ts +6 -2
  10. package/dist/configuration.js +93 -52
  11. package/dist/delivery.d.ts +13 -1
  12. package/dist/delivery.js +2 -0
  13. package/dist/effective-limits.d.ts +4 -4
  14. package/dist/endpoints.d.ts +29 -0
  15. package/dist/endpoints.js +57 -26
  16. package/dist/forecast.d.ts +2 -2
  17. package/dist/http-request.d.ts +12 -2
  18. package/dist/http-request.js +56 -24
  19. package/dist/identifiers.js +20 -20
  20. package/dist/index.d.ts +8 -7
  21. package/dist/index.js +8 -7
  22. package/dist/mcp.js +1 -0
  23. package/dist/operational-config.d.ts +174 -22
  24. package/dist/operational-config.js +213 -79
  25. package/dist/operations.d.ts +334 -52
  26. package/dist/operations.js +195 -34
  27. package/dist/project-notifications.d.ts +35 -9
  28. package/dist/project-notifications.js +43 -12
  29. package/dist/protocol.d.ts +28 -0
  30. package/dist/protocol.js +56 -33
  31. package/dist/schedule-selection.js +2 -2
  32. package/dist/scheduling-records.d.ts +106 -16
  33. package/dist/scheduling-records.js +36 -12
  34. package/dist/scheduling.d.ts +200 -43
  35. package/dist/scheduling.js +280 -131
  36. package/dist/service-mode.d.ts +88 -0
  37. package/dist/service-mode.js +130 -0
  38. package/dist/signatures.d.ts +6 -6
  39. package/dist/signatures.js +24 -24
  40. package/dist/stored-http.d.ts +18 -0
  41. package/dist/stored-http.js +106 -0
  42. package/dist/tenancy.d.ts +54 -30
  43. package/dist/tenancy.js +35 -17
  44. package/dist/time.js +7 -7
  45. package/dist/timing.d.ts +39 -0
  46. package/dist/timing.js +51 -0
  47. package/dist/zod-values.d.ts +1 -1
  48. package/dist/zod-values.js +1 -1
  49. package/dist/zod.d.ts +1 -1
  50. package/dist/zod.js +1 -1
  51. package/generated/v1/examples/billing.noticesdismiss.request.json +3 -0
  52. package/generated/v1/examples/billing.noticesdismiss.response.json +6 -0
  53. package/generated/v1/examples/billing.reconcile.response.json +12 -0
  54. package/generated/v1/examples/billing.summary.response.json +12 -0
  55. package/generated/v1/examples/executions.list.response.json +1 -0
  56. package/generated/v1/examples/limits.read.response.json +1 -1
  57. package/generated/v1/examples/projectnotifications.rotateSigningKey.response.json +1 -0
  58. package/generated/v1/examples/projects.list.response.json +0 -6
  59. package/generated/v1/examples/projects.read.response.json +14 -0
  60. package/generated/v1/examples/schedules.list.response.json +1 -3
  61. package/generated/v1/examples/schedules.summary.response.json +174 -0
  62. package/generated/v1/examples/timing.summary.response.json +33 -1
  63. package/generated/v1/manifest.json +79 -2
  64. package/generated/v1/openapi.json +4084 -2023
  65. package/generated/v1/policy-matrix.json +22 -1
  66. package/generated/v1/schemas/attempts.list.response.json +10 -0
  67. package/generated/v1/schemas/attempts.read.response.json +10 -0
  68. package/generated/v1/schemas/attempts.search.response.json +4 -0
  69. package/generated/v1/schemas/billing.notices.query.json +4 -0
  70. package/generated/v1/schemas/billing.noticesdismiss.request.json +12 -0
  71. package/generated/v1/schemas/billing.noticesdismiss.response.json +22 -0
  72. package/generated/v1/schemas/billing.reconcile.response.json +43 -0
  73. package/generated/v1/schemas/billing.summary.response.json +43 -0
  74. package/generated/v1/schemas/endpoints.list.query.json +15 -0
  75. package/generated/v1/schemas/executions.list.response.json +4 -0
  76. package/generated/v1/schemas/occurrences.list.response.json +4 -0
  77. package/generated/v1/schemas/occurrences.read.response.json +4 -0
  78. package/generated/v1/schemas/occurrences.redeliver.response.json +10 -0
  79. package/generated/v1/schemas/projectnotifications.read.response.json +4 -0
  80. package/generated/v1/schemas/projectnotifications.rotateSigningKey.response.json +4 -0
  81. package/generated/v1/schemas/projectnotifications.update.request.json +41 -17
  82. package/generated/v1/schemas/projectnotifications.update.response.json +4 -0
  83. package/generated/v1/schemas/projects.list.response.json +0 -27
  84. package/generated/v1/schemas/projects.read.response-headers.json +11 -0
  85. package/generated/v1/schemas/projects.read.response.json +79 -0
  86. package/generated/v1/schemas/schedules.archive.response.json +8 -0
  87. package/generated/v1/schemas/schedules.cancel.response.json +8 -0
  88. package/generated/v1/schemas/schedules.create.request.json +1 -1
  89. package/generated/v1/schemas/schedules.create.response.json +8 -0
  90. package/generated/v1/schemas/schedules.list.query.json +6 -0
  91. package/generated/v1/schemas/schedules.list.response.json +4 -0
  92. package/generated/v1/schemas/schedules.pause.response.json +8 -0
  93. package/generated/v1/schemas/schedules.read.response.json +8 -0
  94. package/generated/v1/schemas/schedules.replace.request.json +1 -1
  95. package/generated/v1/schemas/schedules.replace.response.json +8 -0
  96. package/generated/v1/schemas/schedules.resume.response.json +8 -0
  97. package/generated/v1/schemas/schedules.summary.query.json +11 -0
  98. package/generated/v1/schemas/schedules.summary.response.json +144 -0
  99. package/generated/v1/schemas/timing.summary.response.json +69 -0
  100. package/generated/v1/snippets/billing.noticesdismiss.json +6 -0
  101. package/generated/v1/snippets/projectnotifications.rotateSigningKey.json +1 -1
  102. package/generated/v1/snippets/projects.read.json +6 -0
  103. package/generated/v1/snippets/schedules.summary.json +6 -0
  104. 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
@@ -16,7 +16,7 @@ import { timestampSchema } from "./time.js";
16
16
  * exactly what they were given.
17
17
  */
18
18
  export const PAGE_SIZE = PUBLIC_PAGE_SIZE;
19
- export const pageRequestSchema = z.object({
19
+ export const pageRequestSchema = /* @__PURE__ */ (() => z.object({
20
20
  cursor: z.string().min(1).optional(),
21
21
  limit: z
22
22
  .number()
@@ -24,7 +24,7 @@ export const pageRequestSchema = z.object({
24
24
  .min(PAGE_SIZE.min)
25
25
  .max(PAGE_SIZE.max)
26
26
  .default(PAGE_SIZE.default),
27
- });
27
+ }))();
28
28
  /**
29
29
  * A schedules listing: the page, and optionally one endpoint to keep to.
30
30
  *
@@ -43,6 +43,17 @@ export const pageRequestSchema = 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
  *
@@ -55,10 +66,14 @@ export const SCHEDULE_ORDERS = ["created", "due"];
55
66
  * a schedule with nothing on the books matches no `dueBefore`, because it has
56
67
  * no instant to compare and inventing one either way would be a guess.
57
68
  */
58
- export const scheduleListRequestSchema = pageRequestSchema.extend({
69
+ export const scheduleListRequestSchema = /* @__PURE__ */ (() => pageRequestSchema.extend({
59
70
  ...scheduleSelectionSchema.shape,
60
71
  order: z.enum(SCHEDULE_ORDERS).default("created"),
61
- });
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."),
76
+ }))();
62
77
  /**
63
78
  * Which end of a history a page walks from.
64
79
  *
@@ -70,9 +85,9 @@ export const scheduleListRequestSchema = pageRequestSchema.extend({
70
85
  */
71
86
  export const HISTORY_ORDERS = ["oldest", "newest"];
72
87
  /** A page request over a history, which may be walked from either end. */
73
- export const historyPageRequestSchema = pageRequestSchema.extend({
88
+ export const historyPageRequestSchema = /* @__PURE__ */ (() => pageRequestSchema.extend({
74
89
  order: z.enum(HISTORY_ORDERS).default("oldest"),
75
- });
90
+ }))();
76
91
  /**
77
92
  * A page of results.
78
93
  *
@@ -82,14 +97,14 @@ export const historyPageRequestSchema = pageRequestSchema.extend({
82
97
  * stale data as fact. `authoritative` means the answer came from the owning
83
98
  * partition; `projected` means it may lag and carries the age.
84
99
  */
85
- export const freshnessSchema = z.discriminatedUnion("kind", [
100
+ export const freshnessSchema = /* @__PURE__ */ (() => z.discriminatedUnion("kind", [
86
101
  z.object({ kind: z.literal("authoritative") }),
87
102
  z.object({
88
103
  asOf: timestampSchema,
89
104
  kind: z.literal("projected"),
90
105
  lagSeconds: z.number().int().nonnegative(),
91
106
  }),
92
- ]);
107
+ ]))();
93
108
  /**
94
109
  * The `projected` arm alone, for a response that is never authoritative.
95
110
  *
@@ -100,11 +115,11 @@ export const freshnessSchema = z.discriminatedUnion("kind", [
100
115
  * taken, were unreachable without narrowing that no consumer could justify.
101
116
  * Naming the narrower shape moves the claim into the type.
102
117
  */
103
- export const projectedFreshnessSchema = z.object({
118
+ export const projectedFreshnessSchema = /* @__PURE__ */ (() => z.object({
104
119
  asOf: timestampSchema,
105
120
  kind: z.literal("projected"),
106
121
  lagSeconds: z.number().int().nonnegative(),
107
- });
122
+ }))();
108
123
  export function pageSchema(item) {
109
124
  return z.object({
110
125
  data: z.array(item),
@@ -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);
@@ -337,7 +360,7 @@ function parseListing(query, schema) {
337
360
  * `version_conflict` rather than silently overwriting — a cancel racing a
338
361
  * replace must not resolve by luck.
339
362
  */
340
- export const versionSchema = z.number().int().positive();
363
+ export const versionSchema = /* @__PURE__ */ (() => z.number().int().positive())();
341
364
  /**
342
365
  * A strong entity tag over a version: a quoted decimal, and nothing else.
343
366
  *
@@ -383,10 +406,10 @@ export function fromETag(etag) {
383
406
  * refinement is the extra strictness the OpenAPI preamble already discloses
384
407
  * that a described schema does not capture.
385
408
  */
386
- export const etagSchema = z
409
+ export const etagSchema = /* @__PURE__ */ (() => z
387
410
  .string()
388
411
  .regex(ETAG_PATTERN, ETAG_MESSAGE)
389
- .refine((value) => fromETag(value) !== undefined, ETAG_MESSAGE);
412
+ .refine((value) => fromETag(value) !== undefined, ETAG_MESSAGE))();
390
413
  /* -------------------------------------------------------------------------- */
391
414
  /* Idempotency */
392
415
  /* -------------------------------------------------------------------------- */
@@ -400,11 +423,11 @@ export const etagSchema = z
400
423
  * silent second write — that distinction is the whole point, and the legacy
401
424
  * scheduler had no equivalent.
402
425
  */
403
- export const idempotencyKeySchema = z
426
+ export const idempotencyKeySchema = /* @__PURE__ */ (() => z
404
427
  .string()
405
428
  .min(16, "must be at least 16 characters so keys do not collide by accident")
406
429
  .max(255)
407
- .regex(/^[\x20-\x7e]+$/u, "must be printable ASCII");
430
+ .regex(/^[\x20-\x7e]+$/u, "must be printable ASCII"))();
408
431
  /**
409
432
  * The scope a key was used in. Carried on the receipt rather than assumed,
410
433
  * because an implementation that keys its receipt store on the idempotency key
@@ -412,13 +435,13 @@ export const idempotencyKeySchema = z
412
435
  * send the same key. The scope is part of the record so that mistake cannot be
413
436
  * made silently.
414
437
  */
415
- export const idempotencyScopeSchema = z.object({
438
+ export const idempotencyScopeSchema = /* @__PURE__ */ (() => z.object({
416
439
  environment: environmentIdSchema,
417
440
  operation: z.string().min(1),
418
441
  organization: organizationIdSchema,
419
442
  project: projectIdSchema,
420
- });
421
- export const idempotencyReceiptSchema = z.object({
443
+ }))();
444
+ export const idempotencyReceiptSchema = /* @__PURE__ */ (() => z.object({
422
445
  /**
423
446
  * Hash of the canonical request the key was first used with. Canonical
424
447
  * means: the operation name, then the request body serialized with object
@@ -431,7 +454,7 @@ export const idempotencyReceiptSchema = z.object({
431
454
  replayed: z.boolean(),
432
455
  scope: idempotencyScopeSchema,
433
456
  storedAt: timestampSchema,
434
- });
457
+ }))();
435
458
  /**
436
459
  * The canonical form of a request, as the receipt's `requestFingerprint`
437
460
  * describes it: the operation name, then the body with object keys sorted and
@@ -535,9 +558,9 @@ export const CONCURRENCY_HEADERS = {
535
558
  ifMatch: "If-Match",
536
559
  replayed: "Idempotency-Replayed",
537
560
  };
538
- export const idempotencyRequestHeaderSchema = z.object({
561
+ export const idempotencyRequestHeaderSchema = /* @__PURE__ */ (() => z.object({
539
562
  [CONCURRENCY_HEADERS.idempotencyKey]: idempotencyKeySchema.optional(),
540
- });
563
+ }))();
541
564
  /**
542
565
  * A write for which idempotency is mandatory, rather than an optional
543
566
  * protection a caller may opt into.
@@ -547,12 +570,12 @@ export const idempotencyRequestHeaderSchema = z.object({
547
570
  * `idempotencyRequestHeaderSchema` lets schedule creation retain its published
548
571
  * optional behavior without weakening the redelivery promise.
549
572
  */
550
- export const requiredIdempotencyRequestHeaderSchema = z.object({
573
+ export const requiredIdempotencyRequestHeaderSchema = /* @__PURE__ */ (() => z.object({
551
574
  [CONCURRENCY_HEADERS.idempotencyKey]: idempotencyKeySchema,
552
- });
553
- export const conditionalRequestHeaderSchema = z.object({
575
+ }))();
576
+ export const conditionalRequestHeaderSchema = /* @__PURE__ */ (() => z.object({
554
577
  [CONCURRENCY_HEADERS.ifMatch]: etagSchema.optional(),
555
- });
578
+ }))();
556
579
  /**
557
580
  * A conditional write that refuses an unversioned request.
558
581
  *
@@ -561,18 +584,18 @@ export const conditionalRequestHeaderSchema = z.object({
561
584
  * silently accepting a missing precondition would let a stale General page
562
585
  * overwrite a newer decision.
563
586
  */
564
- export const requiredConditionalRequestHeaderSchema = z.object({
587
+ export const requiredConditionalRequestHeaderSchema = /* @__PURE__ */ (() => z.object({
565
588
  [CONCURRENCY_HEADERS.ifMatch]: etagSchema,
566
- });
589
+ }))();
567
590
  /**
568
591
  * Required rather than optional, deliberately: an operation that declares this
569
592
  * promises the header on every success, and a client that has to test for its
570
593
  * presence before making a conditional write will write the untested branch
571
594
  * wrong.
572
595
  */
573
- export const versionResponseHeaderSchema = z.object({
596
+ export const versionResponseHeaderSchema = /* @__PURE__ */ (() => z.object({
574
597
  [CONCURRENCY_HEADERS.etag]: etagSchema,
575
- });
598
+ }))();
576
599
  /**
577
600
  * What a replayed write answers with, on top of the version.
578
601
  *
@@ -588,11 +611,11 @@ export const versionResponseHeaderSchema = z.object({
588
611
  * header is the ordinary case, and a client that has to read a header to learn
589
612
  * nothing happened is a client that will not read it.
590
613
  */
591
- export const replayedResponseHeaderSchema = z.object({
614
+ export const replayedResponseHeaderSchema = /* @__PURE__ */ (() => z.object({
592
615
  [CONCURRENCY_HEADERS.etag]: etagSchema,
593
616
  [CONCURRENCY_HEADERS.replayed]: z.literal("true").optional(),
594
- });
617
+ }))();
595
618
  /** Replay marker for an idempotent create whose result has no ETag. */
596
- export const idempotencyReplayResponseHeaderSchema = z.object({
619
+ export const idempotencyReplayResponseHeaderSchema = /* @__PURE__ */ (() => z.object({
597
620
  [CONCURRENCY_HEADERS.replayed]: z.literal("true").optional(),
598
- });
621
+ }))();
@@ -3,7 +3,7 @@ import { endpointIdSchema, scheduleIdSchema } from "./identifiers.js";
3
3
  import { externalIdentifierSchema, scheduleTagSchema, } from "./host-correlation.js";
4
4
  import { timestampSchema } from "./time.js";
5
5
  /** Shared schedule predicates. Every populated field intersects before paging. */
6
- export const scheduleSelectionSchema = z.object({
6
+ export const scheduleSelectionSchema = /* @__PURE__ */ (() => z.object({
7
7
  external_identifier: externalIdentifierSchema.optional(),
8
8
  tag: scheduleTagSchema.optional(),
9
9
  status: z.enum(["active", "paused", "cancelled", "completed"]).optional(),
@@ -18,7 +18,7 @@ export const scheduleSelectionSchema = z.object({
18
18
  schedule: scheduleIdSchema.optional(),
19
19
  dueAfter: timestampSchema.optional(),
20
20
  dueBefore: timestampSchema.optional(),
21
- });
21
+ }))();
22
22
  /** Canonical predicate shape for lists, cursor bindings and bulk selections. */
23
23
  export function normalizeScheduleSelection(selection) {
24
24
  const text = selection.text?.trim();