@greatwait/contracts 0.2.3 → 0.3.1

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 (90) hide show
  1. package/dist/attempt-search.d.ts +235 -0
  2. package/dist/attempt-search.js +101 -0
  3. package/dist/authority.js +9 -9
  4. package/dist/billing.d.ts +4 -4
  5. package/dist/bulk-operations.d.ts +1832 -0
  6. package/dist/bulk-operations.js +610 -0
  7. package/dist/configuration-bounds.d.ts +12 -0
  8. package/dist/configuration-bounds.js +12 -0
  9. package/dist/configuration.d.ts +75 -0
  10. package/dist/configuration.js +242 -0
  11. package/dist/data-export.d.ts +3 -3
  12. package/dist/delivery.d.ts +1 -0
  13. package/dist/delivery.js +1 -0
  14. package/dist/effective-limits.d.ts +4 -4
  15. package/dist/endpoints.js +25 -25
  16. package/dist/execution-selection.d.ts +48 -0
  17. package/dist/execution-selection.js +21 -0
  18. package/dist/http-request.d.ts +1 -1
  19. package/dist/http-request.js +25 -23
  20. package/dist/identifiers.d.ts +2 -0
  21. package/dist/identifiers.js +21 -19
  22. package/dist/identity.d.ts +3 -3
  23. package/dist/index.d.ts +5 -0
  24. package/dist/index.js +5 -0
  25. package/dist/occurrence-states.d.ts +14 -0
  26. package/dist/occurrence-states.js +13 -0
  27. package/dist/operational-config.js +7 -6
  28. package/dist/operations.d.ts +573 -89
  29. package/dist/operations.js +67 -0
  30. package/dist/protocol.d.ts +19 -5
  31. package/dist/protocol.js +47 -40
  32. package/dist/schedule-selection.d.ts +28 -0
  33. package/dist/schedule-selection.js +48 -0
  34. package/dist/scheduling-records.d.ts +20 -20
  35. package/dist/scheduling.d.ts +109 -63
  36. package/dist/scheduling.js +101 -117
  37. package/dist/signatures.d.ts +6 -6
  38. package/dist/signatures.js +24 -24
  39. package/dist/stored-http.d.ts +18 -0
  40. package/dist/stored-http.js +106 -0
  41. package/dist/test-sink.d.ts +6 -6
  42. package/dist/time.js +7 -7
  43. package/dist/usage.d.ts +3 -3
  44. package/generated/v1/examples/attempts.search.response.json +42 -0
  45. package/generated/v1/examples/bulk.cancel.request.json +3 -0
  46. package/generated/v1/examples/bulk.cancel.response.json +59 -0
  47. package/generated/v1/examples/bulk.confirm.request.json +5 -0
  48. package/generated/v1/examples/bulk.confirm.response.json +59 -0
  49. package/generated/v1/examples/bulk.items.response.json +3 -0
  50. package/generated/v1/examples/bulk.list.response.json +63 -0
  51. package/generated/v1/examples/bulk.pause.request.json +3 -0
  52. package/generated/v1/examples/bulk.pause.response.json +59 -0
  53. package/generated/v1/examples/bulk.preview.request.json +12 -0
  54. package/generated/v1/examples/bulk.preview.response.json +59 -0
  55. package/generated/v1/examples/bulk.read.response.json +59 -0
  56. package/generated/v1/examples/bulk.resume.request.json +3 -0
  57. package/generated/v1/examples/bulk.resume.response.json +59 -0
  58. package/generated/v1/manifest.json +243 -1
  59. package/generated/v1/openapi.json +21569 -2418
  60. package/generated/v1/policy-matrix.json +63 -0
  61. package/generated/v1/schemas/attempts.search.query.json +96 -0
  62. package/generated/v1/schemas/attempts.search.response.json +271 -0
  63. package/generated/v1/schemas/bulk.cancel.request.json +13 -0
  64. package/generated/v1/schemas/bulk.cancel.response.json +1717 -0
  65. package/generated/v1/schemas/bulk.confirm.request-headers.json +13 -0
  66. package/generated/v1/schemas/bulk.confirm.request.json +19 -0
  67. package/generated/v1/schemas/bulk.confirm.response.json +1717 -0
  68. package/generated/v1/schemas/bulk.items.query.json +29 -0
  69. package/generated/v1/schemas/bulk.items.response.json +194 -0
  70. package/generated/v1/schemas/bulk.list.query.json +32 -0
  71. package/generated/v1/schemas/bulk.list.response.json +1789 -0
  72. package/generated/v1/schemas/bulk.pause.request.json +13 -0
  73. package/generated/v1/schemas/bulk.pause.response.json +1717 -0
  74. package/generated/v1/schemas/bulk.preview.request.json +1218 -0
  75. package/generated/v1/schemas/bulk.preview.response.json +1717 -0
  76. package/generated/v1/schemas/bulk.read.response.json +1717 -0
  77. package/generated/v1/schemas/bulk.resume.request.json +13 -0
  78. package/generated/v1/schemas/bulk.resume.response.json +1717 -0
  79. package/generated/v1/schemas/executions.list.query.json +33 -12
  80. package/generated/v1/schemas/schedules.list.query.json +32 -3
  81. package/generated/v1/snippets/attempts.search.json +6 -0
  82. package/generated/v1/snippets/bulk.cancel.json +6 -0
  83. package/generated/v1/snippets/bulk.confirm.json +6 -0
  84. package/generated/v1/snippets/bulk.items.json +6 -0
  85. package/generated/v1/snippets/bulk.list.json +6 -0
  86. package/generated/v1/snippets/bulk.pause.json +6 -0
  87. package/generated/v1/snippets/bulk.preview.json +6 -0
  88. package/generated/v1/snippets/bulk.read.json +6 -0
  89. package/generated/v1/snippets/bulk.resume.json +6 -0
  90. package/package.json +1 -1
@@ -34,9 +34,9 @@ export const SIGNATURE_TOLERANCE_SECONDS = 300;
34
34
  export const CALLBACK_DELIVERY_PROTOCOL_VERSION = "2026-08-23";
35
35
  /** The media type sent on every occurrence delivery. */
36
36
  export const CALLBACK_CONTENT_TYPE = "application/json";
37
- export const signatureHeaderSchema = z
37
+ export const signatureHeaderSchema = /* @__PURE__ */ (() => z
38
38
  .string()
39
- .regex(/^v1=[0-9a-f]{64}$/u, "must be v1= followed by a lowercase hex SHA-256 HMAC");
39
+ .regex(/^v1=[0-9a-f]{64}$/u, "must be v1= followed by a lowercase hex SHA-256 HMAC"))();
40
40
  /**
41
41
  * The exact bytes that are signed: `<timestamp>.<delivery-id>.` followed by the
42
42
  * raw body, with no re-serialization anywhere in the path. Re-encoding JSON
@@ -130,13 +130,13 @@ export function isTimestampFresh(timestamp, nowMs, toleranceSeconds = SIGNATURE_
130
130
  * an unauthenticated hint has handed anyone who can reach its endpoint a
131
131
  * duplicate-execution button.
132
132
  */
133
- export const callbackTriggerSchema = z.discriminatedUnion("kind", [
133
+ export const callbackTriggerSchema = /* @__PURE__ */ (() => z.discriminatedUnion("kind", [
134
134
  z.object({ kind: z.literal("automatic") }),
135
135
  z.object({
136
136
  kind: z.literal("redelivery"),
137
137
  sourceAttemptId: attemptIdSchema,
138
138
  }),
139
- ]);
139
+ ]))();
140
140
  /**
141
141
  * The envelope version this service emits.
142
142
  *
@@ -178,7 +178,7 @@ export const CALLBACK_ENVELOPE_VERSIONS = [
178
178
  CALLBACK_ENVELOPE_VERSION_2026_08_08,
179
179
  CALLBACK_ENVELOPE_VERSION,
180
180
  ];
181
- const callbackEnvelopeShape = {
181
+ const callbackEnvelopeShape = /* @__PURE__ */ (() => ({
182
182
  attempt: z.number().int().positive(),
183
183
  /**
184
184
  * The customer's payload, delivered verbatim. Deliberately any JSON value:
@@ -190,7 +190,7 @@ const callbackEnvelopeShape = {
190
190
  plannedFor: timestampSchema,
191
191
  scheduleId: scheduleIdSchema,
192
192
  type: z.literal("schedule.occurrence"),
193
- };
193
+ }))();
194
194
  /**
195
195
  * Where a `callback` receiver reports that it finished, and with what.
196
196
  *
@@ -207,12 +207,12 @@ const callbackEnvelopeShape = {
207
207
  * later attempt is refused by the same fence that refuses a late executor
208
208
  * result.
209
209
  */
210
- export const callbackCompletionSchema = z.object({
210
+ export const callbackCompletionSchema = /* @__PURE__ */ (() => z.object({
211
211
  /** Bearer credential for the report. Send it, do not inspect it. */
212
212
  token: z.string().min(1),
213
213
  /** Absolute URL to POST to when the work is done. */
214
214
  url: z.url(),
215
- });
215
+ }))();
216
216
  /**
217
217
  * The completion material every `2026-08-23` delivery carries.
218
218
  *
@@ -227,21 +227,21 @@ export const callbackCompletionSchema = z.object({
227
227
  * ask for an earlier instant in its acknowledgement and may not ask for a
228
228
  * later one.
229
229
  */
230
- export const callbackDeferredCompletionSchema = z.object({
230
+ export const callbackDeferredCompletionSchema = /* @__PURE__ */ (() => z.object({
231
231
  /** When this attempt stops being waited for. Absolute, not a duration. */
232
232
  deadline: timestampSchema,
233
233
  /** Bearer credential for the report. Send it, do not inspect it. */
234
234
  token: z.string().min(1),
235
235
  /** Absolute URL to POST to when the work is done. */
236
236
  url: z.url(),
237
- });
237
+ }))();
238
238
  /**
239
239
  * The report body, whose vocabulary lives in the Zod-free `delivery` module so
240
240
  * the scheduler's completion route can read it without importing Zod.
241
241
  */
242
- export const callbackCompletionReportSchema = z.object({
242
+ export const callbackCompletionReportSchema = /* @__PURE__ */ (() => z.object({
243
243
  outcome: z.enum(CALLBACK_COMPLETION_OUTCOMES).default("succeeded"),
244
- });
244
+ }))();
245
245
  /**
246
246
  * The versioned JSON envelope delivered to a customer endpoint.
247
247
  *
@@ -251,7 +251,7 @@ export const callbackCompletionReportSchema = z.object({
251
251
  * envelope. Collapsing the two would leave a receiver unable to know whether
252
252
  * silence about a redelivery is an answer or an absence.
253
253
  */
254
- export const callbackEnvelopeSchema = z.discriminatedUnion("version", [
254
+ export const callbackEnvelopeSchema = /* @__PURE__ */ (() => z.discriminatedUnion("version", [
255
255
  z.object({
256
256
  ...callbackEnvelopeShape,
257
257
  /** Envelope version, dated and independent of the contract version. */
@@ -284,7 +284,7 @@ export const callbackEnvelopeSchema = z.discriminatedUnion("version", [
284
284
  trigger: callbackTriggerSchema,
285
285
  version: z.literal(CALLBACK_ENVELOPE_VERSION),
286
286
  }),
287
- ]);
287
+ ]))();
288
288
  /**
289
289
  * What caused a delivery, for an envelope of any published version.
290
290
  *
@@ -436,20 +436,20 @@ export function extractCanonicalEnvelopeIds(rawBody) {
436
436
  ? { occurrenceId: occurrenceId.data, scheduleId: scheduleId.data }
437
437
  : undefined;
438
438
  }
439
- export const callbackHeadersSchema = z.object({
439
+ export const callbackHeadersSchema = /* @__PURE__ */ (() => z.object({
440
440
  [CALLBACK_HEADERS.deliveryId]: deliveryIdSchema,
441
441
  [CALLBACK_HEADERS.keyId]: callbackSigningKeyIdSchema,
442
442
  [CALLBACK_HEADERS.occurrenceId]: occurrenceIdSchema,
443
443
  [CALLBACK_HEADERS.signature]: signatureHeaderSchema,
444
444
  [CALLBACK_HEADERS.timestamp]: timestampSchema,
445
- });
445
+ }))();
446
446
  const VECTOR_PREFIX = "2026-07-28T15:00:00.000Z.dlv_0123456789abcdefghjkmnpqrs.";
447
447
  const CALLBACK_DELIVERY_VECTOR_BODY = '{"version":"2026-08-23","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":1,"completion":{"token":"v2.example-claim-not-a-real-token.example-mac","url":"https://greatwait-scheduler.example/callbacks/completion","deadline":"2026-07-28T15:00:05.000Z"},"trigger":{"kind":"automatic"},"data":{}}';
448
- const CALLBACK_DELIVERY_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_VECTOR_BODY}`;
448
+ const CALLBACK_DELIVERY_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_VECTOR_BODY}`)();
449
449
  const CALLBACK_DELIVERY_UNICODE_VECTOR_BODY = '{"version":"2026-08-23","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":1,"completion":{"token":"v2.example-claim-not-a-real-token.example-mac","url":"https://greatwait-scheduler.example/callbacks/completion","deadline":"2026-07-28T15:00:05.000Z"},"trigger":{"kind":"automatic"},"data":{"note":"café ☃"}}';
450
- const CALLBACK_DELIVERY_UNICODE_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_UNICODE_VECTOR_BODY}`;
450
+ const CALLBACK_DELIVERY_UNICODE_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_UNICODE_VECTOR_BODY}`)();
451
451
  const CALLBACK_DELIVERY_REDELIVERY_VECTOR_BODY = '{"version":"2026-08-23","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":2,"completion":{"token":"v2.example-claim-not-a-real-token.example-mac","url":"https://greatwait-scheduler.example/callbacks/completion","deadline":"2026-07-28T15:00:05.000Z"},"trigger":{"kind":"redelivery","sourceAttemptId":"att_0123456789abcdefghjkmnpqrs"},"data":{}}';
452
- const CALLBACK_DELIVERY_REDELIVERY_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_REDELIVERY_VECTOR_BODY}`;
452
+ const CALLBACK_DELIVERY_REDELIVERY_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_REDELIVERY_VECTOR_BODY}`)();
453
453
  /**
454
454
  * The `2026-08-08` body with no `completion`, byte for byte as published.
455
455
  *
@@ -461,9 +461,9 @@ const CALLBACK_DELIVERY_REDELIVERY_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DE
461
461
  * receiver mid-rollout is still being handed.
462
462
  */
463
463
  const CALLBACK_DELIVERY_TRIGGER_VECTOR_BODY = '{"version":"2026-08-08","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":1,"trigger":{"kind":"automatic"},"data":{}}';
464
- const CALLBACK_DELIVERY_TRIGGER_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_TRIGGER_VECTOR_BODY}`;
464
+ const CALLBACK_DELIVERY_TRIGGER_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_TRIGGER_VECTOR_BODY}`)();
465
465
  const CALLBACK_DELIVERY_COMPLETION_VECTOR_BODY = '{"version":"2026-08-08","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":1,"completion":{"token":"v1.example-claim-not-a-real-token.example-mac","url":"https://greatwait-scheduler.example/callbacks/completion"},"trigger":{"kind":"automatic"},"data":{}}';
466
- const CALLBACK_DELIVERY_COMPLETION_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_COMPLETION_VECTOR_BODY}`;
466
+ const CALLBACK_DELIVERY_COMPLETION_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_COMPLETION_VECTOR_BODY}`)();
467
467
  /**
468
468
  * The `2026-07-01` body, byte for byte as it was published, with the MAC it was
469
469
  * published with.
@@ -476,12 +476,12 @@ const CALLBACK_DELIVERY_COMPLETION_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DE
476
476
  * published verifier is wrong.
477
477
  */
478
478
  const CALLBACK_DELIVERY_LEGACY_VECTOR_BODY = '{"version":"2026-07-01","type":"schedule.occurrence","scheduleId":"sch_0123456789abcdefghjkmnpqrs","occurrenceId":"occ_0123456789abcdefghjkmnpqrs","plannedFor":"2026-07-28T15:00:00.000Z","attempt":1,"data":{}}';
479
- const CALLBACK_DELIVERY_LEGACY_VECTOR_INPUT = `${VECTOR_PREFIX}${CALLBACK_DELIVERY_LEGACY_VECTOR_BODY}`;
479
+ const CALLBACK_DELIVERY_LEGACY_VECTOR_INPUT = /* @__PURE__ */ (() => `${VECTOR_PREFIX}${CALLBACK_DELIVERY_LEGACY_VECTOR_BODY}`)();
480
480
  /**
481
481
  * Language-neutral known-answer contract for one complete delivery request.
482
482
  * The secret is synthetic and deliberately not shaped like a credential.
483
483
  */
484
- export const CALLBACK_DELIVERY_PROTOCOL = {
484
+ export const CALLBACK_DELIVERY_PROTOCOL = /* @__PURE__ */ (() => ({
485
485
  envelope: {
486
486
  /**
487
487
  * The frozen wire order, and `completion` sits inside it.
@@ -790,7 +790,7 @@ export const CALLBACK_DELIVERY_PROTOCOL = {
790
790
  signingInputUtf8: CALLBACK_DELIVERY_UNICODE_VECTOR_INPUT,
791
791
  },
792
792
  version: CALLBACK_DELIVERY_PROTOCOL_VERSION,
793
- };
793
+ }))();
794
794
  /**
795
795
  * Every published vector, derived from the protocol rather than listed.
796
796
  *
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The headers a send carries: the endpoint's defaults with the schedule's own
3
+ * headers over them, matched case-insensitively, the later entry winning, and
4
+ * suppressed names removed — kept in the order they were written.
5
+ */
6
+ export declare function mergeStoredHttpHeaders(defaults: readonly unknown[] | null | undefined, overrides: readonly unknown[] | null | undefined): unknown[];
7
+ /**
8
+ * Whether stored headers fit their bounds: an array of at most 32, each name
9
+ * present, at most 128 bytes and distinct case-insensitively, and each value
10
+ * that is not suppressed at most 8,192 bytes, 16,384 bytes in all.
11
+ */
12
+ export declare function validStoredHttpHeaders(headers: unknown): boolean;
13
+ /**
14
+ * Whether a schedule's stored HTTP settings, sent through an endpoint with
15
+ * these default headers, are within bounds: the settings' own shape and
16
+ * headers, and the headers a send would carry after the merge.
17
+ */
18
+ export declare function validScheduleHttp(request: unknown, endpointHeaders: readonly unknown[] | null | undefined): boolean;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The stored custom-HTTP invariants, as pure functions (W9-73).
3
+ *
4
+ * Until W9-73 a schedule insert ran these inside PostgreSQL, in the
5
+ * `greatwait_schedule_http_bounds` trigger (migration 0050): a lock and read of
6
+ * the endpoint's default headers, `http_merge_headers_v1` and
7
+ * `http_validate_headers_v1`. They are the same rules here, over the same JSON,
8
+ * so the create can validate before it writes and spend no statement on it.
9
+ * Schedule edits keep the trigger; the endpoint's own trigger still guards an
10
+ * endpoint header change against every schedule using it.
11
+ */
12
+ import { HTTP_HEADER_BOUNDS, HTTP_METHODS } from "./http-request.js";
13
+ const encoder = new TextEncoder();
14
+ const BODY_MODES = ["envelope", "json", "none"];
15
+ function record(value) {
16
+ return typeof value === "object" && value !== null && !Array.isArray(value)
17
+ ? value
18
+ : undefined;
19
+ }
20
+ /** `value->>'suppressed' = 'true'`: the JSON `true`, or the string. */
21
+ function suppressed(header) {
22
+ const flag = record(header)?.["suppressed"];
23
+ return flag === true || flag === "true";
24
+ }
25
+ function headerName(header) {
26
+ const name = record(header)?.["name"];
27
+ return typeof name === "string" ? name : undefined;
28
+ }
29
+ /**
30
+ * The headers a send carries: the endpoint's defaults with the schedule's own
31
+ * headers over them, matched case-insensitively, the later entry winning, and
32
+ * suppressed names removed — kept in the order they were written.
33
+ */
34
+ export function mergeStoredHttpHeaders(defaults, overrides) {
35
+ // Positions as the SQL numbered them: defaults from 1, overrides from 101,
36
+ // so an override always outranks a default of the same name.
37
+ const winners = new Map();
38
+ const consider = (headers, offset) => {
39
+ headers.forEach((header, index) => {
40
+ const key = headerName(header)?.toLowerCase();
41
+ const position = offset + index + 1;
42
+ const prior = winners.get(key);
43
+ if (prior === undefined || position > prior[0])
44
+ winners.set(key, [position, header]);
45
+ });
46
+ };
47
+ consider(defaults ?? [], 0);
48
+ consider(overrides ?? [], 100);
49
+ return [...winners.values()]
50
+ .filter(([, header]) => !suppressed(header))
51
+ .sort(([left], [right]) => left - right)
52
+ .map(([, header]) => header);
53
+ }
54
+ /**
55
+ * Whether stored headers fit their bounds: an array of at most 32, each name
56
+ * present, at most 128 bytes and distinct case-insensitively, and each value
57
+ * that is not suppressed at most 8,192 bytes, 16,384 bytes in all.
58
+ */
59
+ export function validStoredHttpHeaders(headers) {
60
+ if (!Array.isArray(headers) || headers.length > HTTP_HEADER_BOUNDS.count)
61
+ return false;
62
+ const names = new Set();
63
+ let total = 0;
64
+ for (const header of headers) {
65
+ const name = headerName(header);
66
+ if (name === undefined || name.length === 0)
67
+ return false;
68
+ const nameBytes = encoder.encode(name).byteLength;
69
+ if (nameBytes > HTTP_HEADER_BOUNDS.nameBytes)
70
+ return false;
71
+ if (names.has(name.toLowerCase()))
72
+ return false;
73
+ names.add(name.toLowerCase());
74
+ if (suppressed(header))
75
+ continue;
76
+ const size = record(header)?.["valueBytes"];
77
+ // The SQL read the number as text and required one to five digits.
78
+ if (typeof size !== "number" ||
79
+ !Number.isSafeInteger(size) ||
80
+ size < 0 ||
81
+ size > HTTP_HEADER_BOUNDS.valueBytes)
82
+ return false;
83
+ total += nameBytes + size;
84
+ }
85
+ return total <= HTTP_HEADER_BOUNDS.totalBytes;
86
+ }
87
+ /**
88
+ * Whether a schedule's stored HTTP settings, sent through an endpoint with
89
+ * these default headers, are within bounds: the settings' own shape and
90
+ * headers, and the headers a send would carry after the merge.
91
+ */
92
+ export function validScheduleHttp(request, endpointHeaders) {
93
+ const settings = record(request);
94
+ if (request !== null && request !== undefined) {
95
+ const method = settings?.["method"];
96
+ const bodyMode = settings?.["bodyMode"];
97
+ if (settings === undefined ||
98
+ !HTTP_METHODS.includes(method) ||
99
+ !BODY_MODES.includes(bodyMode) ||
100
+ (method === "GET") !== (bodyMode === "none") ||
101
+ !validStoredHttpHeaders(settings["headers"]))
102
+ return false;
103
+ }
104
+ const overrides = settings?.["headers"];
105
+ return validStoredHttpHeaders(mergeStoredHttpHeaders(endpointHeaders, Array.isArray(overrides) ? overrides : undefined));
106
+ }
@@ -376,11 +376,11 @@ export declare function resolveTestSinkAction(program: TestSinkProgram, delivery
376
376
  */
377
377
  export declare const CALLBACK_RECEIVER_DISPOSITIONS: readonly ["body_too_large", "duplicate", "handler_failed", "in_flight", "invalid_envelope", "invalid_headers", "invalid_signature", "processed", "replay", "stale_timestamp"];
378
378
  export declare const callbackReceiverDispositionSchema: import("zod").ZodEnum<{
379
+ in_flight: "in_flight";
379
380
  duplicate: "duplicate";
380
381
  invalid_signature: "invalid_signature";
381
382
  body_too_large: "body_too_large";
382
383
  handler_failed: "handler_failed";
383
- in_flight: "in_flight";
384
384
  invalid_envelope: "invalid_envelope";
385
385
  invalid_headers: "invalid_headers";
386
386
  processed: "processed";
@@ -400,11 +400,11 @@ export type CallbackReceiverDisposition = z.infer<typeof callbackReceiverDisposi
400
400
  */
401
401
  export declare const TEST_SINK_DISPOSITIONS: readonly ["body_too_large", "duplicate", "handler_failed", "in_flight", "invalid_envelope", "invalid_headers", "invalid_signature", "processed", "replay", "stale_timestamp", "connection_dropped"];
402
402
  export declare const testSinkDispositionSchema: import("zod").ZodEnum<{
403
+ in_flight: "in_flight";
403
404
  duplicate: "duplicate";
404
405
  invalid_signature: "invalid_signature";
405
406
  body_too_large: "body_too_large";
406
407
  handler_failed: "handler_failed";
407
- in_flight: "in_flight";
408
408
  invalid_envelope: "invalid_envelope";
409
409
  invalid_headers: "invalid_headers";
410
410
  processed: "processed";
@@ -464,11 +464,11 @@ export declare const CALLBACK_RECEIVER_STATUS: {
464
464
  */
465
465
  export declare const callbackReceiverAcknowledgementSchema: import("zod").ZodObject<{
466
466
  disposition: import("zod").ZodEnum<{
467
+ in_flight: "in_flight";
467
468
  duplicate: "duplicate";
468
469
  invalid_signature: "invalid_signature";
469
470
  body_too_large: "body_too_large";
470
471
  handler_failed: "handler_failed";
471
- in_flight: "in_flight";
472
472
  invalid_envelope: "invalid_envelope";
473
473
  invalid_headers: "invalid_headers";
474
474
  processed: "processed";
@@ -642,11 +642,11 @@ export declare const testSinkDeliverySchema: import("zod").ZodObject<{
642
642
  timeout: "timeout";
643
643
  }>;
644
644
  disposition: import("zod").ZodEnum<{
645
+ in_flight: "in_flight";
645
646
  duplicate: "duplicate";
646
647
  invalid_signature: "invalid_signature";
647
648
  body_too_large: "body_too_large";
648
649
  handler_failed: "handler_failed";
649
- in_flight: "in_flight";
650
650
  invalid_envelope: "invalid_envelope";
651
651
  invalid_headers: "invalid_headers";
652
652
  processed: "processed";
@@ -681,11 +681,11 @@ export declare const testSinkDeliveryPageSchema: import("zod").ZodObject<{
681
681
  timeout: "timeout";
682
682
  }>;
683
683
  disposition: import("zod").ZodEnum<{
684
+ in_flight: "in_flight";
684
685
  duplicate: "duplicate";
685
686
  invalid_signature: "invalid_signature";
686
687
  body_too_large: "body_too_large";
687
688
  handler_failed: "handler_failed";
688
- in_flight: "in_flight";
689
689
  invalid_envelope: "invalid_envelope";
690
690
  invalid_headers: "invalid_headers";
691
691
  processed: "processed";
@@ -747,11 +747,11 @@ export declare const testSinkDeliveryBodySchema: import("zod").ZodObject<{
747
747
  timeout: "timeout";
748
748
  }>;
749
749
  disposition: import("zod").ZodEnum<{
750
+ in_flight: "in_flight";
750
751
  duplicate: "duplicate";
751
752
  invalid_signature: "invalid_signature";
752
753
  body_too_large: "body_too_large";
753
754
  handler_failed: "handler_failed";
754
- in_flight: "in_flight";
755
755
  invalid_envelope: "invalid_envelope";
756
756
  invalid_headers: "invalid_headers";
757
757
  processed: "processed";
package/dist/time.js CHANGED
@@ -16,7 +16,7 @@ import { z } from "./zod.js";
16
16
  * into the instant.
17
17
  */
18
18
  const RFC3339_UTC_MS = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
19
- export const timestampSchema = z
19
+ export const timestampSchema = /* @__PURE__ */ (() => z
20
20
  .string()
21
21
  .regex(RFC3339_UTC_MS, "must be an RFC 3339 UTC timestamp with millisecond precision, e.g. 2026-07-28T15:00:00.000Z")
22
22
  // A regex alone is not enough: JavaScript happily "parses" 2026-02-31 and
@@ -28,8 +28,8 @@ export const timestampSchema = z
28
28
  const parsed = new Date(value);
29
29
  // Guarded because checks still run after the pattern fails, and
30
30
  // `toISOString` throws rather than returning NaN on an invalid Date.
31
- return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;
32
- }, { message: "must be a real instant on the calendar" });
31
+ return (!Number.isNaN(parsed.getTime()) && parsed.toISOString() === value);
32
+ }, { message: "must be a real instant on the calendar" }))();
33
33
  /** Formats an instant in the one representation the wire accepts. */
34
34
  export function toTimestamp(instant) {
35
35
  if (Number.isNaN(instant.getTime())) {
@@ -41,10 +41,10 @@ export function toTimestamp(instant) {
41
41
  * Durations are whole seconds, never strings. Bounds belong to the resource
42
42
  * that uses them; this only fixes the representation.
43
43
  */
44
- export const durationSecondsSchema = z
44
+ export const durationSecondsSchema = /* @__PURE__ */ (() => z
45
45
  .number()
46
46
  .int("must be a whole number of seconds")
47
- .nonnegative("must not be negative");
47
+ .nonnegative("must not be negative"))();
48
48
  let canonicalZones;
49
49
  /**
50
50
  * The zone identifiers this runtime recognizes, plus `UTC`.
@@ -95,7 +95,7 @@ export function toTimeZone(value) {
95
95
  return new Intl.DateTimeFormat("en", { timeZone: value }).resolvedOptions()
96
96
  .timeZone;
97
97
  }
98
- export const timeZoneSchema = z
98
+ export const timeZoneSchema = /* @__PURE__ */ (() => z
99
99
  .string()
100
100
  .min(1)
101
101
  .refine((value) => {
@@ -125,4 +125,4 @@ export const timeZoneSchema = z
125
125
  // spelling would bump the optimistic version and write a spurious audit
126
126
  // diff. Deciding this now is free; after W2 persists the first raw string it
127
127
  // is a breaking response change plus a data migration.
128
- .transform(toTimeZone);
128
+ .transform(toTimeZone))();
package/dist/usage.d.ts CHANGED
@@ -73,8 +73,8 @@ export declare const USAGE_BOUNDS: {
73
73
  export declare const BILLABLE_TERMINAL_STATES: readonly ["cancelled", "skipped_stale", "succeeded", "terminal_failed"];
74
74
  export declare const billableTerminalStateSchema: import("zod").ZodEnum<{
75
75
  succeeded: "succeeded";
76
- cancelled: "cancelled";
77
76
  terminal_failed: "terminal_failed";
77
+ cancelled: "cancelled";
78
78
  skipped_stale: "skipped_stale";
79
79
  }>;
80
80
  export type BillableTerminalStateName = z.infer<typeof billableTerminalStateSchema>;
@@ -107,8 +107,8 @@ export declare const usageDaySchema: import("zod").ZodObject<{
107
107
  billableOccurrences: import("zod").ZodNumber;
108
108
  byTerminalState: import("zod").ZodRecord<import("zod").ZodEnum<{
109
109
  succeeded: "succeeded";
110
- cancelled: "cancelled";
111
110
  terminal_failed: "terminal_failed";
111
+ cancelled: "cancelled";
112
112
  skipped_stale: "skipped_stale";
113
113
  }> & import("zod/v4/core").$partial, import("zod").ZodNumber>;
114
114
  start: import("zod").ZodString;
@@ -120,8 +120,8 @@ export declare const usageSchema: import("zod").ZodObject<{
120
120
  billableOccurrences: import("zod").ZodNumber;
121
121
  byTerminalState: import("zod").ZodRecord<import("zod").ZodEnum<{
122
122
  succeeded: "succeeded";
123
- cancelled: "cancelled";
124
123
  terminal_failed: "terminal_failed";
124
+ cancelled: "cancelled";
125
125
  skipped_stale: "skipped_stale";
126
126
  }> & import("zod/v4/core").$partial, import("zod").ZodNumber>;
127
127
  start: import("zod").ZodString;
@@ -0,0 +1,42 @@
1
+ {
2
+ "data": [
3
+ {
4
+ "attempt": {
5
+ "id": "att_01h8xyz9k2m4n6p8r0t2v4w6y8",
6
+ "attemptNumber": 1,
7
+ "occurrence": "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
8
+ "startedAt": "2026-07-28T15:00:00.000Z",
9
+ "state": "retryable_failure",
10
+ "classifiedAt": "2026-07-28T15:00:00.071Z",
11
+ "durationMs": 71,
12
+ "responseStatus": 503,
13
+ "diagnostic": "http_retryable",
14
+ "remediation": "review_retry_policy",
15
+ "trigger": {
16
+ "kind": "automatic"
17
+ }
18
+ },
19
+ "occurrence": {
20
+ "attemptCount": 2,
21
+ "generation": 1,
22
+ "id": "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
23
+ "plannedFor": "2026-07-28T14:50:00.000Z",
24
+ "schedule": "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
25
+ "sequence": 1,
26
+ "settledAt": "2026-07-28T15:00:04.000Z",
27
+ "state": "succeeded"
28
+ },
29
+ "schedule": {
30
+ "id": "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
31
+ "name": "Recovered delivery"
32
+ }
33
+ }
34
+ ],
35
+ "freshness": {
36
+ "kind": "authoritative"
37
+ },
38
+ "retention": {
39
+ "from": "2026-07-21T15:00:00.000Z",
40
+ "detailsFrom": "2026-07-21T15:00:00.000Z"
41
+ }
42
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "expectedVersion": 1
3
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "id": "bjo_01h8xyz9k2m4n6p8r0t2v4w6y8",
3
+ "authority": {
4
+ "environment": "env_01h8xyz9k2m4n6p8r0t2v4w6y8",
5
+ "environmentKind": "test",
6
+ "organization": "org_01h8xyz9k2m4n6p8r0t2v4w6y8",
7
+ "project": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8"
8
+ },
9
+ "intent": {
10
+ "target": "schedules",
11
+ "selection": {
12
+ "kind": "all_matching",
13
+ "resource": "schedules",
14
+ "filter": {
15
+ "tag": "reminders"
16
+ }
17
+ },
18
+ "operation": "pause",
19
+ "parameters": {}
20
+ },
21
+ "state": "cancelled",
22
+ "version": 1,
23
+ "createdAt": "2035-06-01T00:00:00.000Z",
24
+ "updatedAt": "2035-06-01T00:00:00.000Z",
25
+ "referenceAt": "2035-06-01T00:00:00.000Z",
26
+ "preparationExpiresAt": "2035-06-08T00:00:00.000Z",
27
+ "previewExpiresAt": "2035-06-01T00:05:00.000Z",
28
+ "intentDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
29
+ "complete": true,
30
+ "counts": {
31
+ "matched": 0,
32
+ "eligible": 0,
33
+ "ineligible": 0,
34
+ "pending": 0,
35
+ "running": 0,
36
+ "succeeded": 0,
37
+ "noOp": 0,
38
+ "skipped": 0,
39
+ "conflicted": 0,
40
+ "failed": 0,
41
+ "cancelled": 0
42
+ },
43
+ "reasons": [],
44
+ "warnings": [],
45
+ "samples": [],
46
+ "limits": {
47
+ "maxTargets": 100000,
48
+ "executionLifetimeSeconds": 604800,
49
+ "previewLifetimeSeconds": 300,
50
+ "resultRetentionSeconds": 1209600,
51
+ "batchSize": 25,
52
+ "workerConcurrency": 1
53
+ },
54
+ "billing": {
55
+ "additionalAttemptsMinimum": 0,
56
+ "exactChargeKnown": false,
57
+ "note": "Ordinary per-attempt billing and quota admission apply; preview creates no delivery or charge."
58
+ }
59
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "intentDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
3
+ "confirmed": true,
4
+ "acknowledgeDuplicateEffects": false
5
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "id": "bjo_01h8xyz9k2m4n6p8r0t2v4w6y8",
3
+ "authority": {
4
+ "environment": "env_01h8xyz9k2m4n6p8r0t2v4w6y8",
5
+ "environmentKind": "test",
6
+ "organization": "org_01h8xyz9k2m4n6p8r0t2v4w6y8",
7
+ "project": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8"
8
+ },
9
+ "intent": {
10
+ "target": "schedules",
11
+ "selection": {
12
+ "kind": "all_matching",
13
+ "resource": "schedules",
14
+ "filter": {
15
+ "tag": "reminders"
16
+ }
17
+ },
18
+ "operation": "pause",
19
+ "parameters": {}
20
+ },
21
+ "state": "queued",
22
+ "version": 1,
23
+ "createdAt": "2035-06-01T00:00:00.000Z",
24
+ "updatedAt": "2035-06-01T00:00:00.000Z",
25
+ "referenceAt": "2035-06-01T00:00:00.000Z",
26
+ "preparationExpiresAt": "2035-06-08T00:00:00.000Z",
27
+ "previewExpiresAt": "2035-06-01T00:05:00.000Z",
28
+ "intentDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
29
+ "complete": true,
30
+ "counts": {
31
+ "matched": 0,
32
+ "eligible": 0,
33
+ "ineligible": 0,
34
+ "pending": 0,
35
+ "running": 0,
36
+ "succeeded": 0,
37
+ "noOp": 0,
38
+ "skipped": 0,
39
+ "conflicted": 0,
40
+ "failed": 0,
41
+ "cancelled": 0
42
+ },
43
+ "reasons": [],
44
+ "warnings": [],
45
+ "samples": [],
46
+ "limits": {
47
+ "maxTargets": 100000,
48
+ "executionLifetimeSeconds": 604800,
49
+ "previewLifetimeSeconds": 300,
50
+ "resultRetentionSeconds": 1209600,
51
+ "batchSize": 25,
52
+ "workerConcurrency": 1
53
+ },
54
+ "billing": {
55
+ "additionalAttemptsMinimum": 0,
56
+ "exactChargeKnown": false,
57
+ "note": "Ordinary per-attempt billing and quota admission apply; preview creates no delivery or charge."
58
+ }
59
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "data": []
3
+ }