@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
package/dist/tenancy.d.ts CHANGED
@@ -133,20 +133,19 @@ export declare const provisionedProjectSchema: import("zod").ZodObject<{
133
133
  }, import("zod/v4/core").$strip>;
134
134
  }, import("zod/v4/core").$strip>;
135
135
  export type ProvisionedProject = z.infer<typeof provisionedProjectSchema>;
136
+ /** Exactly what a permanent deletion of the project would destroy now. */
137
+ export declare const projectDeletionCountsSchema: import("zod").ZodObject<{
138
+ endpoints: import("zod").ZodNumber;
139
+ keys: import("zod").ZodNumber;
140
+ runs: import("zod").ZodNumber;
141
+ schedules: import("zod").ZodNumber;
142
+ }, import("zod/v4/core").$strip>;
136
143
  /**
137
- * What a signed-in member is told about a project they may act in.
144
+ * One project, with the exact counts a permanent deletion would destroy now.
138
145
  *
139
- * **Not `provisionedProjectSchema`, deliberately.** That shape carries
140
- * `organization`, `status`, `version` and both environment *identifiers*, and
141
- * publishing environment ids would make them public names — while nothing on
142
- * `/v1` takes one: every operation that names an environment names its
143
- * `kind`. Publishing an identifier no operation accepts invites a client to
144
- * build on it and then constrains us to keep it.
145
- *
146
- * This remains a display aid rather than an authorization control. Whatever the
147
- * list shows, the authority for a request is re-resolved from the member's
148
- * organization when the request arrives. Lifecycle state and version make an
149
- * archived row manageable without making it a valid work target.
146
+ * Returned by the single-project read (`projects.read`) and by the writes that
147
+ * answer with the project they changed. Never by the list: see
148
+ * `projectListItemSchema`.
150
149
  */
151
150
  export declare const projectSummarySchema: import("zod").ZodObject<{
152
151
  createdAt: import("zod").ZodNullable<import("zod").ZodString>;
@@ -169,12 +168,43 @@ export declare const projectSummarySchema: import("zod").ZodObject<{
169
168
  version: import("zod").ZodNumber;
170
169
  }, import("zod/v4/core").$strip>;
171
170
  export type ProjectSummary = z.infer<typeof projectSummarySchema>;
172
- export declare const projectDeletionCountsSchema: import("zod").ZodObject<{
173
- endpoints: import("zod").ZodNumber;
174
- keys: import("zod").ZodNumber;
175
- runs: import("zod").ZodNumber;
176
- schedules: import("zod").ZodNumber;
171
+ /**
172
+ * What a signed-in member is told about a project they may act in.
173
+ *
174
+ * **Not `provisionedProjectSchema`, deliberately.** That shape carries
175
+ * `organization`, `status`, `version` and both environment *identifiers*, and
176
+ * publishing environment ids would make them public names — while nothing on
177
+ * `/v1` takes one: every operation that names an environment names its
178
+ * `kind`. Publishing an identifier no operation accepts invites a client to
179
+ * build on it and then constrains us to keep it.
180
+ *
181
+ * This remains a display aid rather than an authorization control. Whatever the
182
+ * list shows, the authority for a request is re-resolved from the member's
183
+ * organization when the request arrives. Lifecycle state and version make an
184
+ * archived row manageable without making it a valid work target.
185
+ *
186
+ * **No deletion counts (W9-88).** Counting a project's schedules and runs
187
+ * reads every one of them, so a list that counted every project cost the sum
188
+ * of the organization's whole history — 2.2 s for an organization with
189
+ * 290,000 schedules, longer than the API's pool would wait, and the landing
190
+ * page failed every time. Exact counts are a deletion preview; they belong to
191
+ * the one project somebody is about to delete: `projectSummarySchema`.
192
+ */
193
+ export declare const projectListItemSchema: import("zod").ZodObject<{
194
+ status: import("zod").ZodEnum<{
195
+ active: "active";
196
+ archived: "archived";
197
+ }>;
198
+ name: import("zod").ZodString;
199
+ version: import("zod").ZodNumber;
200
+ id: import("zod").ZodString;
201
+ createdAt: import("zod").ZodNullable<import("zod").ZodString>;
202
+ environmentKinds: import("zod").ZodArray<import("zod").ZodEnum<{
203
+ test: "test";
204
+ live: "live";
205
+ }>>;
177
206
  }, import("zod/v4/core").$strip>;
207
+ export type ProjectListItem = z.infer<typeof projectListItemSchema>;
178
208
  export type ProjectDeletionCounts = z.infer<typeof projectDeletionCountsSchema>;
179
209
  /**
180
210
  * Every active or archived project the member can access. Administrators see all.
@@ -190,24 +220,18 @@ export type ProjectDeletionCounts = z.infer<typeof projectDeletionCountsSchema>;
190
220
  export declare const PROJECT_LIST_LIMIT = 200;
191
221
  export declare const projectListSchema: import("zod").ZodObject<{
192
222
  data: import("zod").ZodArray<import("zod").ZodObject<{
193
- createdAt: import("zod").ZodNullable<import("zod").ZodString>;
194
- deletionCounts: import("zod").ZodObject<{
195
- endpoints: import("zod").ZodNumber;
196
- keys: import("zod").ZodNumber;
197
- runs: import("zod").ZodNumber;
198
- schedules: import("zod").ZodNumber;
199
- }, import("zod/v4/core").$strip>;
200
- environmentKinds: import("zod").ZodArray<import("zod").ZodEnum<{
201
- test: "test";
202
- live: "live";
203
- }>>;
204
- id: import("zod").ZodString;
205
- name: import("zod").ZodString;
206
223
  status: import("zod").ZodEnum<{
207
224
  active: "active";
208
225
  archived: "archived";
209
226
  }>;
227
+ name: import("zod").ZodString;
210
228
  version: import("zod").ZodNumber;
229
+ id: import("zod").ZodString;
230
+ createdAt: import("zod").ZodNullable<import("zod").ZodString>;
231
+ environmentKinds: import("zod").ZodArray<import("zod").ZodEnum<{
232
+ test: "test";
233
+ live: "live";
234
+ }>>;
211
235
  }, import("zod/v4/core").$strip>>;
212
236
  total: import("zod").ZodNumber;
213
237
  }, import("zod/v4/core").$strip>;
package/dist/tenancy.js CHANGED
@@ -116,6 +116,31 @@ export const provisionedProjectSchema = z.object({
116
116
  .length(2, "a project has exactly two environments"),
117
117
  project: projectSchema,
118
118
  });
119
+ /** Exactly what a permanent deletion of the project would destroy now. */
120
+ export const projectDeletionCountsSchema = z.object({
121
+ endpoints: z.number().int().nonnegative(),
122
+ keys: z.number().int().nonnegative(),
123
+ runs: z.number().int().nonnegative(),
124
+ schedules: z.number().int().nonnegative(),
125
+ });
126
+ /**
127
+ * One project, with the exact counts a permanent deletion would destroy now.
128
+ *
129
+ * Returned by the single-project read (`projects.read`) and by the writes that
130
+ * answer with the project they changed. Never by the list: see
131
+ * `projectListItemSchema`.
132
+ */
133
+ export const projectSummarySchema = z.object({
134
+ createdAt: timestampSchema.nullable(),
135
+ deletionCounts: projectDeletionCountsSchema,
136
+ environmentKinds: z
137
+ .array(environmentKindSchema)
138
+ .length(2, "a project has exactly two environments"),
139
+ id: projectIdSchema,
140
+ name: projectNameSchema,
141
+ status: projectStatusSchema.exclude(["deleted"]),
142
+ version: versionSchema,
143
+ });
119
144
  /**
120
145
  * What a signed-in member is told about a project they may act in.
121
146
  *
@@ -130,24 +155,17 @@ export const provisionedProjectSchema = z.object({
130
155
  * list shows, the authority for a request is re-resolved from the member's
131
156
  * organization when the request arrives. Lifecycle state and version make an
132
157
  * archived row manageable without making it a valid work target.
158
+ *
159
+ * **No deletion counts (W9-88).** Counting a project's schedules and runs
160
+ * reads every one of them, so a list that counted every project cost the sum
161
+ * of the organization's whole history — 2.2 s for an organization with
162
+ * 290,000 schedules, longer than the API's pool would wait, and the landing
163
+ * page failed every time. Exact counts are a deletion preview; they belong to
164
+ * the one project somebody is about to delete: `projectSummarySchema`.
133
165
  */
134
- export const projectSummarySchema = z.object({
135
- createdAt: timestampSchema.nullable(),
136
- deletionCounts: z.object({
137
- endpoints: z.number().int().nonnegative(),
138
- keys: z.number().int().nonnegative(),
139
- runs: z.number().int().nonnegative(),
140
- schedules: z.number().int().nonnegative(),
141
- }),
142
- environmentKinds: z
143
- .array(environmentKindSchema)
144
- .length(2, "a project has exactly two environments"),
145
- id: projectIdSchema,
146
- name: projectNameSchema,
147
- status: projectStatusSchema.exclude(["deleted"]),
148
- version: versionSchema,
166
+ export const projectListItemSchema = projectSummarySchema.omit({
167
+ deletionCounts: true,
149
168
  });
150
- export const projectDeletionCountsSchema = projectSummarySchema.shape.deletionCounts;
151
169
  /**
152
170
  * Every active or archived project the member can access. Administrators see all.
153
171
  *
@@ -162,7 +180,7 @@ export const projectDeletionCountsSchema = projectSummarySchema.shape.deletionCo
162
180
  export const PROJECT_LIST_LIMIT = 200;
163
181
  export const projectListSchema = z.object({
164
182
  data: z
165
- .array(projectSummarySchema)
183
+ .array(projectListItemSchema)
166
184
  .max(PROJECT_LIST_LIMIT, "more projects than this response can carry; paging is required"),
167
185
  /** Active and archived projects occupy a plan slot; deleted projects do not. */
168
186
  total: z.number().int().nonnegative().max(PROJECT_LIST_LIMIT),
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/timing.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from "./zod.js";
2
+ export declare const DELIVERY_TIMING_POLICY_VERSION = "timing-v2-service-bands";
2
3
  export declare const DELIVERY_TIMING_TARGETS_MS: readonly [5000, 15000];
3
4
  export declare const DELIVERY_TIMING_VERDICTS: readonly ["met", "missed", "unknown"];
4
5
  export declare const timingThresholdSummarySchema: import("zod").ZodObject<{
@@ -15,6 +16,26 @@ export declare const timingThresholdSummarySchema: import("zod").ZodObject<{
15
16
  withinTargetCount: import("zod").ZodInt;
16
17
  }, import("zod/v4/core").$strip>;
17
18
  export type TimingThresholdView = z.infer<typeof timingThresholdSummarySchema>;
19
+ /** One concrete band's first-outbound p95 objective, measured from plannedFor. */
20
+ export declare const bandTimingSummarySchema: import("zod").ZodObject<{
21
+ serviceBand: import("zod").ZodEnum<{
22
+ short_bulk: "short_bulk";
23
+ bulk: "bulk";
24
+ realtime: "realtime";
25
+ }>;
26
+ targetMs: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<1000>, import("zod").ZodLiteral<10000>, import("zod").ZodLiteral<60000>]>;
27
+ breachCount: import("zod").ZodInt;
28
+ customerBlockedCount: import("zod").ZodInt;
29
+ eligibleOutstandingBreachCount: import("zod").ZodInt;
30
+ maturedCount: import("zod").ZodInt;
31
+ verdict: import("zod").ZodEnum<{
32
+ unknown: "unknown";
33
+ met: "met";
34
+ missed: "missed";
35
+ }>;
36
+ withinTargetCount: import("zod").ZodInt;
37
+ }, import("zod/v4/core").$strip>;
38
+ export type BandTimingSummaryView = z.infer<typeof bandTimingSummarySchema>;
18
39
  /**
19
40
  * Exact rolling 24-hour due-time cohort for one project and timing policy.
20
41
  *
@@ -23,6 +44,24 @@ export type TimingThresholdView = z.infer<typeof timingThresholdSummarySchema>;
23
44
  * samples only and remain separate from the exact threshold counters.
24
45
  */
25
46
  export declare const deliveryTimingSummarySchema: import("zod").ZodObject<{
47
+ bandTargets: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
48
+ serviceBand: import("zod").ZodEnum<{
49
+ short_bulk: "short_bulk";
50
+ bulk: "bulk";
51
+ realtime: "realtime";
52
+ }>;
53
+ targetMs: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<1000>, import("zod").ZodLiteral<10000>, import("zod").ZodLiteral<60000>]>;
54
+ breachCount: import("zod").ZodInt;
55
+ customerBlockedCount: import("zod").ZodInt;
56
+ eligibleOutstandingBreachCount: import("zod").ZodInt;
57
+ maturedCount: import("zod").ZodInt;
58
+ verdict: import("zod").ZodEnum<{
59
+ unknown: "unknown";
60
+ met: "met";
61
+ missed: "missed";
62
+ }>;
63
+ withinTargetCount: import("zod").ZodInt;
64
+ }, import("zod/v4/core").$strip>>>;
26
65
  customerBlockedCount: import("zod").ZodInt;
27
66
  deliveredSampleCount: import("zod").ZodInt;
28
67
  freshness: import("zod").ZodObject<{
package/dist/timing.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { z } from "./zod.js";
2
2
  import { timestampSchema } from "./time.js";
3
+ import { SERVICE_MODE_POLICY } from "./operational-config.js";
4
+ import { SERVICE_BANDS } from "./service-mode.js";
5
+ export const DELIVERY_TIMING_POLICY_VERSION = "timing-v2-service-bands";
3
6
  export const DELIVERY_TIMING_TARGETS_MS = [5_000, 15_000];
4
7
  export const DELIVERY_TIMING_VERDICTS = ["met", "missed", "unknown"];
5
8
  const integerSchema = z.int();
@@ -49,6 +52,41 @@ export const timingThresholdSummarySchema = z
49
52
  });
50
53
  }
51
54
  });
55
+ /** One concrete band's first-outbound p95 objective, measured from plannedFor. */
56
+ export const bandTimingSummarySchema = z
57
+ .object({
58
+ serviceBand: z.enum(SERVICE_BANDS),
59
+ targetMs: z.union([
60
+ z.literal(SERVICE_MODE_POLICY.firstOutboundP95TargetMs.realtime),
61
+ z.literal(SERVICE_MODE_POLICY.firstOutboundP95TargetMs.short_bulk),
62
+ z.literal(SERVICE_MODE_POLICY.firstOutboundP95TargetMs.bulk),
63
+ ]),
64
+ breachCount: countSchema,
65
+ customerBlockedCount: countSchema,
66
+ eligibleOutstandingBreachCount: countSchema,
67
+ maturedCount: countSchema,
68
+ verdict: z.enum(DELIVERY_TIMING_VERDICTS),
69
+ withinTargetCount: countSchema,
70
+ })
71
+ .superRefine((value, context) => {
72
+ const matured = BigInt(value.maturedCount);
73
+ const within = BigInt(value.withinTargetCount);
74
+ const expected = matured === 0n
75
+ ? "unknown"
76
+ : within * 100n >= matured * 95n
77
+ ? "met"
78
+ : "missed";
79
+ if (value.targetMs !==
80
+ SERVICE_MODE_POLICY.firstOutboundP95TargetMs[value.serviceBand] ||
81
+ within + BigInt(value.breachCount) !== matured ||
82
+ value.eligibleOutstandingBreachCount > value.breachCount ||
83
+ value.verdict !== expected) {
84
+ context.addIssue({
85
+ code: z.ZodIssueCode.custom,
86
+ message: "band target and verdict must match the exact service-band counts",
87
+ });
88
+ }
89
+ });
52
90
  /**
53
91
  * Exact rolling 24-hour due-time cohort for one project and timing policy.
54
92
  *
@@ -57,6 +95,19 @@ export const timingThresholdSummarySchema = z
57
95
  * samples only and remain separate from the exact threshold counters.
58
96
  */
59
97
  export const deliveryTimingSummarySchema = z.object({
98
+ /** Present on timing-v2: banded work is judged here, legacy work in targets. */
99
+ bandTargets: z
100
+ .array(bandTimingSummarySchema)
101
+ .length(3)
102
+ .superRefine((targets, context) => {
103
+ if (targets.some((target, index) => target.serviceBand !== SERVICE_BANDS[index])) {
104
+ context.addIssue({
105
+ code: z.ZodIssueCode.custom,
106
+ message: "band targets must contain realtime, short_bulk and bulk in order",
107
+ });
108
+ }
109
+ })
110
+ .optional(),
60
111
  customerBlockedCount: countSchema,
61
112
  deliveredSampleCount: countSchema,
62
113
  freshness: z.object({ kind: z.literal("authoritative") }),
@@ -1,3 +1,3 @@
1
- /** The exact Zod constructors used by delivery-runtime contract modules. */
1
+ /** The exact Zod constructors the contract modules use. */
2
2
  export { ZodError, ZodIssueCode, array, boolean, discriminatedUnion, enum, int, json, literal, number, never, object, partialRecord, record, strictObject, string, toJSONSchema, tuple, union, unknown, url, } from "zod";
3
3
  export type { RefinementCtx, ZodType, ZodTypeAny, infer, input } from "zod";
@@ -1,2 +1,2 @@
1
- /** The exact Zod constructors used by delivery-runtime contract modules. */
1
+ /** The exact Zod constructors the contract modules use. */
2
2
  export { ZodError, ZodIssueCode, array, boolean, discriminatedUnion, enum, int, json, literal, number, never, object, partialRecord, record, strictObject, string, toJSONSchema, tuple, union, unknown, url, } from "zod";
package/dist/zod.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- /** Tree-shakeable namespace for delivery-runtime contract modules. */
1
+ /** Tree-shakeable Zod namespace for the contract modules. */
2
2
  export * as z from "./zod-values.js";
package/dist/zod.js CHANGED
@@ -1,2 +1,2 @@
1
- /** Tree-shakeable namespace for delivery-runtime contract modules. */
1
+ /** Tree-shakeable Zod namespace for the contract modules. */
2
2
  export * as z from "./zod-values.js";
@@ -0,0 +1,3 @@
1
+ {
2
+ "through": "2026-09-10T12:00:00.000Z"
3
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "dismissed": 3,
3
+ "freshness": {
4
+ "kind": "authoritative"
5
+ }
6
+ }
@@ -3,6 +3,18 @@
3
3
  "boundary": "2026-09-01T00:00:00.000Z",
4
4
  "mode": "shadow"
5
5
  },
6
+ "attemptPrice": {
7
+ "bulk": {
8
+ "currency": "USD",
9
+ "microdollars": "10",
10
+ "scale": 6
11
+ },
12
+ "realtime": {
13
+ "currency": "USD",
14
+ "microdollars": "10",
15
+ "scale": 6
16
+ }
17
+ },
6
18
  "blockingReasons": [],
7
19
  "budgetPolicy": {
8
20
  "desired": {
@@ -3,6 +3,18 @@
3
3
  "boundary": "2026-09-01T00:00:00.000Z",
4
4
  "mode": "shadow"
5
5
  },
6
+ "attemptPrice": {
7
+ "bulk": {
8
+ "currency": "USD",
9
+ "microdollars": "10",
10
+ "scale": 6
11
+ },
12
+ "realtime": {
13
+ "currency": "USD",
14
+ "microdollars": "10",
15
+ "scale": 6
16
+ }
17
+ },
6
18
  "blockingReasons": [],
7
19
  "budgetPolicy": {
8
20
  "desired": {
@@ -6,6 +6,7 @@
6
6
  "id": "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
7
7
  "plannedFor": "2026-07-28T15:00:00.000Z",
8
8
  "schedule": "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
9
+ "scheduleName": "Nightly report",
9
10
  "sequence": 1,
10
11
  "settledAt": "2026-07-28T15:00:01.000Z",
11
12
  "state": "succeeded"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "limits": {
3
- "inlinePayloadBytes": 65536,
3
+ "inlinePayloadBytes": 8192,
4
4
  "forecastHorizonSeconds": 90000,
5
5
  "usageWindowDays": 366
6
6
  },
@@ -13,6 +13,7 @@
13
13
  "statusWebhook": {
14
14
  "url": "https://hooks.example.com/status",
15
15
  "events": ["failed"],
16
+ "endpoint": "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
16
17
  "signingKey": {
17
18
  "id": "csk_01h8xyz9k2m4n6p8r0t2v4w6y8"
18
19
  },
@@ -2,12 +2,6 @@
2
2
  "data": [
3
3
  {
4
4
  "createdAt": "2026-08-14T11:00:00.000Z",
5
- "deletionCounts": {
6
- "endpoints": 2,
7
- "keys": 4,
8
- "runs": 37,
9
- "schedules": 5
10
- },
11
5
  "environmentKinds": ["test", "live"],
12
6
  "id": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
13
7
  "name": "Billing reminders",
@@ -0,0 +1,14 @@
1
+ {
2
+ "createdAt": "2026-08-14T11:00:00.000Z",
3
+ "deletionCounts": {
4
+ "endpoints": 2,
5
+ "keys": 4,
6
+ "runs": 37,
7
+ "schedules": 5
8
+ },
9
+ "environmentKinds": ["test", "live"],
10
+ "id": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
11
+ "name": "Billing reminders",
12
+ "status": "archived",
13
+ "version": 2
14
+ }
@@ -18,9 +18,7 @@
18
18
  }
19
19
  ],
20
20
  "freshness": {
21
- "asOf": "2026-07-28T15:00:00.000Z",
22
- "kind": "projected",
23
- "lagSeconds": 0
21
+ "kind": "authoritative"
24
22
  },
25
23
  "nextCursor": "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoic2NoXzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0"
26
24
  }