@greatwait/contracts 0.1.0-alpha.4 → 0.1.0-alpha.6

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 (190) hide show
  1. package/README.md +1 -1
  2. package/dist/authority.d.ts +4 -1
  3. package/dist/authority.js +1 -0
  4. package/dist/billing.d.ts +231 -1
  5. package/dist/billing.js +150 -1
  6. package/dist/callback-safety.js +13 -3
  7. package/dist/configuration-bounds.d.ts +13 -0
  8. package/dist/configuration-bounds.js +13 -0
  9. package/dist/data-export.d.ts +2 -0
  10. package/dist/delivery.d.ts +26 -0
  11. package/dist/delivery.js +2 -0
  12. package/dist/effective-limits.d.ts +40 -0
  13. package/dist/effective-limits.js +42 -0
  14. package/dist/endpoints.d.ts +173 -5
  15. package/dist/endpoints.js +77 -6
  16. package/dist/first-value-journey.d.ts +1 -1
  17. package/dist/first-value-journey.js +11 -7
  18. package/dist/forecast.d.ts +111 -21
  19. package/dist/forecast.js +87 -24
  20. package/dist/http-request.d.ts +193 -0
  21. package/dist/http-request.js +305 -0
  22. package/dist/identity.d.ts +4 -4
  23. package/dist/index.d.ts +9 -6
  24. package/dist/index.js +8 -5
  25. package/dist/mcp.d.ts +2 -1
  26. package/dist/mcp.js +1 -1
  27. package/dist/members.d.ts +141 -0
  28. package/dist/members.js +223 -0
  29. package/dist/oauth.d.ts +7 -0
  30. package/dist/operation-definitions.d.ts +20 -4
  31. package/dist/operation-definitions.js +9 -1
  32. package/dist/operational-config.d.ts +101 -0
  33. package/dist/operational-config.js +341 -0
  34. package/dist/operations.d.ts +1299 -52
  35. package/dist/operations.js +466 -32
  36. package/dist/organization-lifecycle.d.ts +10 -0
  37. package/dist/partition.d.ts +17 -9
  38. package/dist/partition.js +3 -3
  39. package/dist/policy.js +5 -2
  40. package/dist/problems.d.ts +25 -2
  41. package/dist/problems.js +49 -1
  42. package/dist/protocol.d.ts +5 -5
  43. package/dist/protocol.js +2 -1
  44. package/dist/scheduling-records.d.ts +226 -0
  45. package/dist/scheduling-records.js +5 -0
  46. package/dist/scheduling.d.ts +273 -1
  47. package/dist/scheduling.js +91 -4
  48. package/dist/secrets.d.ts +7 -0
  49. package/dist/tenancy.d.ts +1 -1
  50. package/dist/tenancy.js +1 -1
  51. package/dist/usage.js +6 -21
  52. package/dist/zod-values.d.ts +2 -2
  53. package/dist/zod-values.js +1 -1
  54. package/generated/v1/examples/attempts.list.response.json +2 -0
  55. package/generated/v1/examples/attempts.read.response.json +2 -0
  56. package/generated/v1/examples/billing.fundingconfirm.response.json +120 -0
  57. package/generated/v1/examples/billing.invoicehistory.response.json +6 -0
  58. package/generated/v1/examples/billing.invoices.response.json +15 -0
  59. package/generated/v1/examples/billing.paymenthistory.response.json +6 -0
  60. package/generated/v1/examples/billing.paymentmethod.response.json +16 -0
  61. package/generated/v1/examples/billing.paymentmethodconfirm.request.json +3 -0
  62. package/generated/v1/examples/billing.paymentmethodconfirm.response.json +16 -0
  63. package/generated/v1/examples/billing.paymentmethodremove.request.json +3 -0
  64. package/generated/v1/examples/billing.paymentmethodremove.response.json +4 -0
  65. package/generated/v1/examples/billing.paymentmethodsetup.request.json +1 -0
  66. package/generated/v1/examples/billing.paymentmethodsetup.response.json +3 -0
  67. package/generated/v1/examples/endpoints.ensure.request.json +3 -0
  68. package/generated/v1/examples/endpoints.ensure.response.json +20 -0
  69. package/generated/v1/examples/invitations.create.request.json +5 -0
  70. package/generated/v1/examples/invitations.create.response.json +7 -0
  71. package/generated/v1/examples/invitations.list.response.json +11 -0
  72. package/generated/v1/examples/invitations.resend.request.json +1 -0
  73. package/generated/v1/examples/invitations.resend.response.json +4 -0
  74. package/generated/v1/examples/invitations.revoke.request.json +3 -0
  75. package/generated/v1/examples/invitations.revoke.response.json +4 -0
  76. package/generated/v1/examples/limits.read.response.json +16 -0
  77. package/generated/v1/examples/members.list.response.json +13 -0
  78. package/generated/v1/examples/members.remove.request.json +3 -0
  79. package/generated/v1/examples/members.remove.response.json +4 -0
  80. package/generated/v1/examples/members.role.request.json +3 -0
  81. package/generated/v1/examples/members.role.response.json +4 -0
  82. package/generated/v1/examples/occurrences.redeliver.response.json +2 -0
  83. package/generated/v1/examples/projectmembers.add.request.json +1 -0
  84. package/generated/v1/examples/projectmembers.add.response.json +4 -0
  85. package/generated/v1/examples/projectmembers.remove.request.json +3 -0
  86. package/generated/v1/examples/projectmembers.remove.response.json +4 -0
  87. package/generated/v1/first-value-journey.json +24 -8
  88. package/generated/v1/manifest.json +627 -10
  89. package/generated/v1/openapi.json +29081 -15663
  90. package/generated/v1/policy-matrix.json +137 -2
  91. package/generated/v1/schemas/attempts.list.response.json +15 -0
  92. package/generated/v1/schemas/attempts.read.response.json +15 -0
  93. package/generated/v1/schemas/billing.fundingconfirm.response.json +552 -0
  94. package/generated/v1/schemas/billing.invoicehistory.query.json +16 -0
  95. package/generated/v1/schemas/billing.invoicehistory.response.json +88 -0
  96. package/generated/v1/schemas/billing.invoices.response.json +51 -0
  97. package/generated/v1/schemas/billing.ledger.response.json +5 -0
  98. package/generated/v1/schemas/billing.notificationsettingsupdate.request.json +24 -17
  99. package/generated/v1/schemas/billing.paymenthistory.query.json +16 -0
  100. package/generated/v1/schemas/billing.paymenthistory.response.json +182 -0
  101. package/generated/v1/schemas/billing.paymentmethod.response.json +137 -0
  102. package/generated/v1/schemas/billing.paymentmethodconfirm.request.json +14 -0
  103. package/generated/v1/schemas/billing.paymentmethodconfirm.response.json +137 -0
  104. package/generated/v1/schemas/billing.paymentmethodremove.request.json +12 -0
  105. package/generated/v1/schemas/billing.paymentmethodremove.response.json +137 -0
  106. package/generated/v1/schemas/billing.paymentmethodsetup.request.json +12 -0
  107. package/generated/v1/schemas/billing.paymentmethodsetup.response.json +11 -0
  108. package/generated/v1/schemas/billing.purchase.request.json +4 -0
  109. package/generated/v1/schemas/context.read.response.json +1 -0
  110. package/generated/v1/schemas/credentials.connection.response.json +1 -0
  111. package/generated/v1/schemas/credentials.create.request.json +1 -0
  112. package/generated/v1/schemas/credentials.create.response.json +1 -0
  113. package/generated/v1/schemas/credentials.list.response.json +1 -0
  114. package/generated/v1/schemas/credentials.revoke.response.json +1 -0
  115. package/generated/v1/schemas/credentials.rotate.response.json +2 -0
  116. package/generated/v1/schemas/endpoints.acknowledgeSigningKeyRotation.response.json +59 -0
  117. package/generated/v1/schemas/endpoints.create.request.json +74 -0
  118. package/generated/v1/schemas/endpoints.create.response.json +59 -0
  119. package/generated/v1/schemas/endpoints.disable.response.json +59 -0
  120. package/generated/v1/schemas/endpoints.enable.response.json +59 -0
  121. package/generated/v1/schemas/endpoints.ensure.request.json +91 -0
  122. package/generated/v1/schemas/endpoints.ensure.response.json +169 -0
  123. package/generated/v1/schemas/endpoints.list.response.json +59 -0
  124. package/generated/v1/schemas/endpoints.read.response.json +59 -0
  125. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +59 -0
  126. package/generated/v1/schemas/endpoints.update.request.json +74 -0
  127. package/generated/v1/schemas/endpoints.update.response.json +59 -0
  128. package/generated/v1/schemas/forecast.read.request-headers.json +10 -0
  129. package/generated/v1/schemas/forecast.read.response.json +148 -0
  130. package/generated/v1/schemas/grants.list.response.json +1 -0
  131. package/generated/v1/schemas/grants.revoke.response.json +1 -0
  132. package/generated/v1/schemas/invitations.create.request-headers.json +13 -0
  133. package/generated/v1/schemas/invitations.create.request.json +24 -0
  134. package/generated/v1/schemas/invitations.create.response.json +31 -0
  135. package/generated/v1/schemas/invitations.list.response.json +40 -0
  136. package/generated/v1/schemas/invitations.resend.request-headers.json +13 -0
  137. package/generated/v1/schemas/invitations.resend.request.json +6 -0
  138. package/generated/v1/schemas/invitations.resend.response.json +27 -0
  139. package/generated/v1/schemas/invitations.revoke.request-headers.json +13 -0
  140. package/generated/v1/schemas/invitations.revoke.request.json +12 -0
  141. package/generated/v1/schemas/invitations.revoke.response.json +27 -0
  142. package/generated/v1/schemas/limits.read.response.json +79 -0
  143. package/generated/v1/schemas/members.list.response.json +53 -0
  144. package/generated/v1/schemas/members.remove.request-headers.json +13 -0
  145. package/generated/v1/schemas/members.remove.request.json +12 -0
  146. package/generated/v1/schemas/members.remove.response.json +27 -0
  147. package/generated/v1/schemas/members.role.request-headers.json +13 -0
  148. package/generated/v1/schemas/members.role.request.json +12 -0
  149. package/generated/v1/schemas/members.role.response.json +27 -0
  150. package/generated/v1/schemas/occurrences.redeliver.response.json +15 -0
  151. package/generated/v1/schemas/projectmembers.add.request-headers.json +13 -0
  152. package/generated/v1/schemas/projectmembers.add.request.json +6 -0
  153. package/generated/v1/schemas/projectmembers.add.response.json +27 -0
  154. package/generated/v1/schemas/projectmembers.remove.request-headers.json +13 -0
  155. package/generated/v1/schemas/projectmembers.remove.request.json +12 -0
  156. package/generated/v1/schemas/projectmembers.remove.response.json +27 -0
  157. package/generated/v1/schemas/schedules.archive.response.json +138 -1
  158. package/generated/v1/schemas/schedules.cancel.response.json +138 -1
  159. package/generated/v1/schemas/schedules.create.request.json +150 -1
  160. package/generated/v1/schemas/schedules.create.response.json +156 -1
  161. package/generated/v1/schemas/schedules.list.response.json +138 -1
  162. package/generated/v1/schemas/schedules.pause.response.json +138 -1
  163. package/generated/v1/schemas/schedules.read.response.json +138 -1
  164. package/generated/v1/schemas/schedules.replace.request.json +150 -1
  165. package/generated/v1/schemas/schedules.replace.response.json +156 -1
  166. package/generated/v1/schemas/schedules.resume.response.json +138 -1
  167. package/generated/v1/snippets/billing.fundingconfirm.json +6 -0
  168. package/generated/v1/snippets/billing.invoicehistory.json +6 -0
  169. package/generated/v1/snippets/billing.invoices.json +6 -0
  170. package/generated/v1/snippets/billing.notificationsettingsupdate.json +1 -1
  171. package/generated/v1/snippets/billing.paymenthistory.json +6 -0
  172. package/generated/v1/snippets/billing.paymentmethod.json +6 -0
  173. package/generated/v1/snippets/billing.paymentmethodconfirm.json +6 -0
  174. package/generated/v1/snippets/billing.paymentmethodremove.json +6 -0
  175. package/generated/v1/snippets/billing.paymentmethodsetup.json +6 -0
  176. package/generated/v1/snippets/endpoints.create.json +1 -1
  177. package/generated/v1/snippets/endpoints.ensure.json +6 -0
  178. package/generated/v1/snippets/forecast.windows.json +1 -1
  179. package/generated/v1/snippets/invitations.create.json +6 -0
  180. package/generated/v1/snippets/invitations.list.json +6 -0
  181. package/generated/v1/snippets/invitations.resend.json +6 -0
  182. package/generated/v1/snippets/invitations.revoke.json +6 -0
  183. package/generated/v1/snippets/journey/create-destination.json +1 -1
  184. package/generated/v1/snippets/limits.read.json +6 -0
  185. package/generated/v1/snippets/members.list.json +6 -0
  186. package/generated/v1/snippets/members.remove.json +6 -0
  187. package/generated/v1/snippets/members.role.json +6 -0
  188. package/generated/v1/snippets/projectmembers.add.json +6 -0
  189. package/generated/v1/snippets/projectmembers.remove.json +6 -0
  190. package/package.json +7 -2
@@ -0,0 +1,42 @@
1
+ import { z } from "./zod.js";
2
+ import { MAX_INLINE_PAYLOAD_BYTES, MAX_FORECAST_HORIZON_SECONDS, MAX_USAGE_WINDOW_DAYS, MAX_PARTITION_KEY_CEILING, } from "./configuration-bounds.js";
3
+ const layer = z.enum(["default", "global", "deployment", "organization"]);
4
+ export const effectiveCustomerLimitsSchema = z
5
+ .object({
6
+ limits: z
7
+ .object({
8
+ inlinePayloadBytes: z
9
+ .number()
10
+ .int()
11
+ .min(0)
12
+ .max(MAX_INLINE_PAYLOAD_BYTES),
13
+ partitionKeyCeiling: z
14
+ .number()
15
+ .int()
16
+ .min(1)
17
+ .max(MAX_PARTITION_KEY_CEILING)
18
+ .optional(),
19
+ forecastHorizonSeconds: z
20
+ .number()
21
+ .int()
22
+ .min(60)
23
+ .max(MAX_FORECAST_HORIZON_SECONDS),
24
+ usageWindowDays: z.number().int().min(1).max(MAX_USAGE_WINDOW_DAYS),
25
+ })
26
+ .strict(),
27
+ provenance: z
28
+ .object({
29
+ inlinePayloadBytes: layer,
30
+ partitionKeyCeiling: layer.optional(),
31
+ forecastHorizonSeconds: layer,
32
+ usageWindowDays: layer,
33
+ })
34
+ .strict(),
35
+ revision: z
36
+ .object({
37
+ global: z.number().int().nonnegative(),
38
+ organization: z.number().int().nonnegative(),
39
+ })
40
+ .strict(),
41
+ })
42
+ .strict();
@@ -38,9 +38,9 @@ export declare const callbackEgressFailureSchema: import("zod").ZodEnum<{
38
38
  }>;
39
39
  export type CallbackEgressFailure = z.infer<typeof callbackEgressFailureSchema>;
40
40
  /**
41
- * A safety ceiling on retained endpoint records, independent of later
42
- * commercial plan limits. Disabled records remain readable for audit and count
43
- * toward it; changing that lifetime semantic needs a product decision.
41
+ * @deprecated The former retained endpoint count ceiling. W0-15 removes count
42
+ * enforcement after the operator's decision; DNS/mutation admission and paged
43
+ * reads protect bounded work. Retained for source compatibility with old clients.
44
44
  */
45
45
  export declare const CALLBACK_ENDPOINT_LIMIT_PER_ENVIRONMENT = 50;
46
46
  /**
@@ -49,8 +49,8 @@ export declare const CALLBACK_ENDPOINT_LIMIT_PER_ENVIRONMENT = 50;
49
49
  * service resolve names without bound.
50
50
  */
51
51
  export declare const CALLBACK_ADMISSION_RATE_LIMITS: {
52
- readonly destinationPerMinute: 5;
53
- readonly projectPerMinute: 20;
52
+ readonly destinationPerMinute: 15;
53
+ readonly projectPerMinute: 60;
54
54
  readonly windowSeconds: 60;
55
55
  };
56
56
  /** Longest period during which a receiver may accept current and next keys. */
@@ -83,6 +83,19 @@ export declare const callbackEndpointNameSchema: import("zod").ZodString;
83
83
  * field, so list/get/update/disable/enable cannot accidentally recover it.
84
84
  */
85
85
  export declare const callbackEndpointSchema: import("zod").ZodObject<{
86
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
87
+ name: import("zod").ZodString;
88
+ secret: import("zod").ZodLiteral<false>;
89
+ value: import("zod").ZodString;
90
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
91
+ name: import("zod").ZodString;
92
+ secret: import("zod").ZodLiteral<true>;
93
+ configured: import("zod").ZodLiteral<true>;
94
+ value: import("zod").ZodOptional<import("zod").ZodNever>;
95
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
96
+ name: import("zod").ZodString;
97
+ suppressed: import("zod").ZodLiteral<true>;
98
+ }, import("zod/v4/core").$strict>]>>>;
86
99
  createdAt: import("zod").ZodString;
87
100
  disabledAt: import("zod").ZodOptional<import("zod").ZodString>;
88
101
  environmentKind: import("zod").ZodEnum<{
@@ -111,6 +124,19 @@ export declare const callbackEndpointSchema: import("zod").ZodObject<{
111
124
  export type CallbackEndpoint = z.infer<typeof callbackEndpointSchema>;
112
125
  export declare const callbackEndpointPageSchema: import("zod").ZodObject<{
113
126
  data: import("zod").ZodArray<import("zod").ZodObject<{
127
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
128
+ name: import("zod").ZodString;
129
+ secret: import("zod").ZodLiteral<false>;
130
+ value: import("zod").ZodString;
131
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
132
+ name: import("zod").ZodString;
133
+ secret: import("zod").ZodLiteral<true>;
134
+ configured: import("zod").ZodLiteral<true>;
135
+ value: import("zod").ZodOptional<import("zod").ZodNever>;
136
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
137
+ name: import("zod").ZodString;
138
+ suppressed: import("zod").ZodLiteral<true>;
139
+ }, import("zod/v4/core").$strict>]>>>;
114
140
  createdAt: import("zod").ZodString;
115
141
  disabledAt: import("zod").ZodOptional<import("zod").ZodString>;
116
142
  environmentKind: import("zod").ZodEnum<{
@@ -148,6 +174,19 @@ export declare const callbackEndpointPageSchema: import("zod").ZodObject<{
148
174
  export type CallbackEndpointPage = z.infer<typeof callbackEndpointPageSchema>;
149
175
  /** The one response that carries the per-endpoint secret. */
150
176
  export declare const callbackEndpointCreatedSchema: import("zod").ZodObject<{
177
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
178
+ name: import("zod").ZodString;
179
+ secret: import("zod").ZodLiteral<false>;
180
+ value: import("zod").ZodString;
181
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
182
+ name: import("zod").ZodString;
183
+ secret: import("zod").ZodLiteral<true>;
184
+ configured: import("zod").ZodLiteral<true>;
185
+ value: import("zod").ZodOptional<import("zod").ZodNever>;
186
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
187
+ name: import("zod").ZodString;
188
+ suppressed: import("zod").ZodLiteral<true>;
189
+ }, import("zod/v4/core").$strict>]>>>;
151
190
  createdAt: import("zod").ZodString;
152
191
  disabledAt: import("zod").ZodOptional<import("zod").ZodString>;
153
192
  environmentKind: import("zod").ZodEnum<{
@@ -183,6 +222,19 @@ export declare const callbackSigningKeyRotationRequestSchema: import("zod").ZodO
183
222
  export type CallbackSigningKeyRotationRequest = z.infer<typeof callbackSigningKeyRotationRequestSchema>;
184
223
  export declare const callbackEndpointRotatedSchema: import("zod").ZodObject<{
185
224
  endpoint: import("zod").ZodObject<{
225
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
226
+ name: import("zod").ZodString;
227
+ secret: import("zod").ZodLiteral<false>;
228
+ value: import("zod").ZodString;
229
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
230
+ name: import("zod").ZodString;
231
+ secret: import("zod").ZodLiteral<true>;
232
+ configured: import("zod").ZodLiteral<true>;
233
+ value: import("zod").ZodOptional<import("zod").ZodNever>;
234
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
235
+ name: import("zod").ZodString;
236
+ suppressed: import("zod").ZodLiteral<true>;
237
+ }, import("zod/v4/core").$strict>]>>>;
186
238
  createdAt: import("zod").ZodString;
187
239
  disabledAt: import("zod").ZodOptional<import("zod").ZodString>;
188
240
  environmentKind: import("zod").ZodEnum<{
@@ -239,7 +291,123 @@ export declare const callbackEndpointSigningSecretsSchema: import("zod").ZodObje
239
291
  }, import("zod/v4/core").$strip>>;
240
292
  }, import("zod/v4/core").$strip>;
241
293
  export type CallbackEndpointSigningSecrets = z.infer<typeof callbackEndpointSigningSecretsSchema>;
294
+ /**
295
+ * Where an endpoint's signing secret is, for a result that does not carry it
296
+ * (W9-44, FXO-2907).
297
+ *
298
+ * `endpoints.ensure`, and a schedule write that names a `url` instead of an
299
+ * endpoint, may bring an endpoint into existence without handing its secret
300
+ * to the caller. An agent working over MCP is the reason: anything a tool
301
+ * returns lands in ordinary tool history, so the secret is never in the
302
+ * result. What is in it is where a person finds the secret — the endpoint's
303
+ * own page, where a signed-in member reveals it — so the agent can pass that
304
+ * on rather than leave the person to discover that deliveries are signed.
305
+ *
306
+ * `returned` is the literal `false` rather than an absent field because a
307
+ * reader deciding whether it holds a secret should be told so, not left to
308
+ * infer it from what is missing.
309
+ */
310
+ export declare const signingSecretNoticeSchema: import("zod").ZodObject<{
311
+ guidance: import("zod").ZodString;
312
+ returned: import("zod").ZodLiteral<false>;
313
+ revealUrl: import("zod").ZodOptional<import("zod").ZodString>;
314
+ }, import("zod/v4/core").$strip>;
315
+ export type SigningSecretNotice = z.infer<typeof signingSecretNoticeSchema>;
316
+ /**
317
+ * The dashboard path of one endpoint's page, beneath the project and
318
+ * environment it belongs to. The dashboard's router serves it; a test there
319
+ * holds the two to the same shape.
320
+ */
321
+ export declare function endpointDashboardPath(target: {
322
+ readonly endpoint: string;
323
+ readonly environmentKind: string;
324
+ /**
325
+ * The organization **as the dashboard addresses it**: the sign-in
326
+ * provider's organization, not GreatWait's `org_…` identifier.
327
+ */
328
+ readonly organization: string;
329
+ readonly project: string;
330
+ }): string;
331
+ /**
332
+ * The notice a secretless endpoint result carries. `dashboardOrigin` is the
333
+ * deployment's dashboard; without one the notice still says where to look.
334
+ */
335
+ export declare function signingSecretNotice(target: Parameters<typeof endpointDashboardPath>[0], dashboardOrigin: string | undefined): SigningSecretNotice;
336
+ /**
337
+ * What `endpoints.ensure` answers: the endpoint at the requested address,
338
+ * whether this call created it, and where its signing secret is.
339
+ *
340
+ * Metadata only, like every endpoint read. There is no `secret` field to fill
341
+ * by mistake; the shape is what keeps it out of an agent's history.
342
+ */
343
+ export declare const callbackEndpointEnsuredSchema: import("zod").ZodObject<{
344
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
345
+ name: import("zod").ZodString;
346
+ secret: import("zod").ZodLiteral<false>;
347
+ value: import("zod").ZodString;
348
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
349
+ name: import("zod").ZodString;
350
+ secret: import("zod").ZodLiteral<true>;
351
+ configured: import("zod").ZodLiteral<true>;
352
+ value: import("zod").ZodOptional<import("zod").ZodNever>;
353
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
354
+ name: import("zod").ZodString;
355
+ suppressed: import("zod").ZodLiteral<true>;
356
+ }, import("zod/v4/core").$strict>]>>>;
357
+ createdAt: import("zod").ZodString;
358
+ disabledAt: import("zod").ZodOptional<import("zod").ZodString>;
359
+ environmentKind: import("zod").ZodEnum<{
360
+ test: "test";
361
+ live: "live";
362
+ }>;
363
+ id: import("zod").ZodString;
364
+ name: import("zod").ZodOptional<import("zod").ZodString>;
365
+ project: import("zod").ZodString;
366
+ signingKeys: import("zod").ZodObject<{
367
+ current: import("zod").ZodString;
368
+ next: import("zod").ZodOptional<import("zod").ZodObject<{
369
+ acknowledgedAt: import("zod").ZodOptional<import("zod").ZodString>;
370
+ id: import("zod").ZodString;
371
+ overlapEndsAt: import("zod").ZodString;
372
+ }, import("zod/v4/core").$strip>>;
373
+ }, import("zod/v4/core").$strip>;
374
+ status: import("zod").ZodEnum<{
375
+ disabled: "disabled";
376
+ active: "active";
377
+ }>;
378
+ updatedAt: import("zod").ZodString;
379
+ url: import("zod").ZodString;
380
+ version: import("zod").ZodNumber;
381
+ created: import("zod").ZodBoolean;
382
+ signingSecret: import("zod").ZodObject<{
383
+ guidance: import("zod").ZodString;
384
+ returned: import("zod").ZodLiteral<false>;
385
+ revealUrl: import("zod").ZodOptional<import("zod").ZodString>;
386
+ }, import("zod/v4/core").$strip>;
387
+ }, import("zod/v4/core").$strip>;
388
+ export type CallbackEndpointEnsured = z.infer<typeof callbackEndpointEnsuredSchema>;
389
+ /**
390
+ * A callback destination as a caller types it: HTTPS on port 443, no
391
+ * credentials or fragment, a public name or address. The DNS half of the
392
+ * policy runs when an endpoint is created at it.
393
+ */
394
+ export declare function callbackUrlSchema(): import("zod").ZodString;
242
395
  export declare const callbackEndpointRequestSchema: import("zod").ZodObject<{
396
+ headers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
397
+ action: import("zod").ZodLiteral<"set">;
398
+ name: import("zod").ZodString;
399
+ value: import("zod").ZodString;
400
+ secret: import("zod").ZodOptional<import("zod").ZodBoolean>;
401
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
402
+ action: import("zod").ZodLiteral<"keep">;
403
+ name: import("zod").ZodString;
404
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
405
+ action: import("zod").ZodLiteral<"remove">;
406
+ name: import("zod").ZodString;
407
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
408
+ action: import("zod").ZodLiteral<"suppress">;
409
+ name: import("zod").ZodString;
410
+ }, import("zod/v4/core").$strict>], "action">>>;
243
411
  name: import("zod").ZodOptional<import("zod").ZodString>;
244
412
  url: import("zod").ZodString;
245
413
  }, import("zod/v4/core").$strip>;
package/dist/endpoints.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { endpointHeaderChangesSchema, publicHttpHeaderSchema, } from "./http-request.js";
1
2
  import { z } from "./zod.js";
2
3
  import { environmentKindSchema } from "./authority.js";
3
4
  import { evaluateCallbackUrl } from "./callback-safety.js";
@@ -38,9 +39,9 @@ export const CALLBACK_EGRESS_FAILURES = [
38
39
  ];
39
40
  export const callbackEgressFailureSchema = z.enum(CALLBACK_EGRESS_FAILURES);
40
41
  /**
41
- * A safety ceiling on retained endpoint records, independent of later
42
- * commercial plan limits. Disabled records remain readable for audit and count
43
- * toward it; changing that lifetime semantic needs a product decision.
42
+ * @deprecated The former retained endpoint count ceiling. W0-15 removes count
43
+ * enforcement after the operator's decision; DNS/mutation admission and paged
44
+ * reads protect bounded work. Retained for source compatibility with old clients.
44
45
  */
45
46
  export const CALLBACK_ENDPOINT_LIMIT_PER_ENVIRONMENT = 50;
46
47
  /**
@@ -49,8 +50,8 @@ export const CALLBACK_ENDPOINT_LIMIT_PER_ENVIRONMENT = 50;
49
50
  * service resolve names without bound.
50
51
  */
51
52
  export const CALLBACK_ADMISSION_RATE_LIMITS = {
52
- destinationPerMinute: 5,
53
- projectPerMinute: 20,
53
+ destinationPerMinute: 15,
54
+ projectPerMinute: 60,
54
55
  windowSeconds: 60,
55
56
  };
56
57
  /** Longest period during which a receiver may accept current and next keys. */
@@ -89,6 +90,7 @@ export const callbackEndpointNameSchema = z
89
90
  * field, so list/get/update/disable/enable cannot accidentally recover it.
90
91
  */
91
92
  export const callbackEndpointSchema = z.object({
93
+ headers: z.array(publicHttpHeaderSchema).optional(),
92
94
  createdAt: timestampSchema,
93
95
  disabledAt: timestampSchema.optional(),
94
96
  environmentKind: environmentKindSchema,
@@ -148,7 +150,75 @@ export const callbackEndpointSigningSecretsSchema = z.object({
148
150
  .extend({ overlapEndsAt: timestampSchema })
149
151
  .optional(),
150
152
  });
151
- function callbackUrlSchema() {
153
+ /**
154
+ * Where an endpoint's signing secret is, for a result that does not carry it
155
+ * (W9-44, FXO-2907).
156
+ *
157
+ * `endpoints.ensure`, and a schedule write that names a `url` instead of an
158
+ * endpoint, may bring an endpoint into existence without handing its secret
159
+ * to the caller. An agent working over MCP is the reason: anything a tool
160
+ * returns lands in ordinary tool history, so the secret is never in the
161
+ * result. What is in it is where a person finds the secret — the endpoint's
162
+ * own page, where a signed-in member reveals it — so the agent can pass that
163
+ * on rather than leave the person to discover that deliveries are signed.
164
+ *
165
+ * `returned` is the literal `false` rather than an absent field because a
166
+ * reader deciding whether it holds a secret should be told so, not left to
167
+ * infer it from what is missing.
168
+ */
169
+ export const signingSecretNoticeSchema = z.object({
170
+ /** One sentence an agent can relay to the person it is working for. */
171
+ guidance: z.string().min(1),
172
+ /** Never `true`: these results do not carry the secret. */
173
+ returned: z.literal(false),
174
+ /**
175
+ * The endpoint's page in the GreatWait dashboard, where a signed-in member
176
+ * reveals the secret. Absent only where this deployment has no dashboard.
177
+ */
178
+ revealUrl: z.string().url().optional(),
179
+ });
180
+ /**
181
+ * The dashboard path of one endpoint's page, beneath the project and
182
+ * environment it belongs to. The dashboard's router serves it; a test there
183
+ * holds the two to the same shape.
184
+ */
185
+ export function endpointDashboardPath(target) {
186
+ return `/o/${encodeURIComponent(target.organization)}/p/${encodeURIComponent(target.project)}/${encodeURIComponent(target.environmentKind)}/settings/endpoints/${encodeURIComponent(target.endpoint)}`;
187
+ }
188
+ /**
189
+ * The notice a secretless endpoint result carries. `dashboardOrigin` is the
190
+ * deployment's dashboard; without one the notice still says where to look.
191
+ */
192
+ export function signingSecretNotice(target, dashboardOrigin) {
193
+ return {
194
+ guidance: "GreatWait signs every callback to this endpoint. The signing secret is never returned here; a signed-in member of the project reveals it on the endpoint's page in the GreatWait dashboard, and your receiver uses it to verify that a callback came from GreatWait.",
195
+ returned: false,
196
+ ...(dashboardOrigin === undefined
197
+ ? {}
198
+ : {
199
+ revealUrl: new URL(endpointDashboardPath(target), dashboardOrigin)
200
+ .href,
201
+ }),
202
+ };
203
+ }
204
+ /**
205
+ * What `endpoints.ensure` answers: the endpoint at the requested address,
206
+ * whether this call created it, and where its signing secret is.
207
+ *
208
+ * Metadata only, like every endpoint read. There is no `secret` field to fill
209
+ * by mistake; the shape is what keeps it out of an agent's history.
210
+ */
211
+ export const callbackEndpointEnsuredSchema = callbackEndpointSchema.extend({
212
+ /** Whether this call created the endpoint, or found one already there. */
213
+ created: z.boolean(),
214
+ signingSecret: signingSecretNoticeSchema,
215
+ });
216
+ /**
217
+ * A callback destination as a caller types it: HTTPS on port 443, no
218
+ * credentials or fragment, a public name or address. The DNS half of the
219
+ * policy runs when an endpoint is created at it.
220
+ */
221
+ export function callbackUrlSchema() {
152
222
  return z
153
223
  .string()
154
224
  .url()
@@ -164,6 +234,7 @@ function callbackUrlSchema() {
164
234
  });
165
235
  }
166
236
  export const callbackEndpointRequestSchema = z.object({
237
+ headers: endpointHeaderChangesSchema.optional(),
167
238
  /**
168
239
  * A name for people (W4-14, FXO-2255). Omitted on a create, the endpoint
169
240
  * takes its whole URL as its name; omitted on an update, the stored name
@@ -6,7 +6,7 @@ import type { ProblemCode } from "./problems.js";
6
6
  *
7
7
  * **Declared once, here, because W9-03 is not the only story that has to tell
8
8
  * it.** The curl quickstart, the JavaScript quickstart, the website journey
9
- * W9-01 owns, the DocsAlot pages W9-04 publishes, and the command-line
9
+ * W9-01 owns, the documentation pages W9-04 publishes, and the command-line
10
10
  * ergonomics W10 owns are all the *same* sequence rendered for a different
11
11
  * reader. Written separately they diverge silently — the legacy scheduler's
12
12
  * hand-maintained client and documentation are the worked example, and the
@@ -109,20 +109,20 @@ export const CURL_JOURNEY_TOOLS = [
109
109
  ];
110
110
  export const FIRST_VALUE_PREREQUISITES = [
111
111
  {
112
- action: "Accept your Greatwait invitation, sign in, and create a project in the dashboard.",
112
+ action: "Accept your GreatWait invitation, sign in, and create a project in the dashboard.",
113
113
  because: "projects.create accepts only a signed-in member, so a project is created by a person rather than by an API credential.",
114
114
  id: "project",
115
115
  title: "A project",
116
116
  },
117
117
  {
118
- action: "In that project, create an API credential and copy the secret it shows once.",
118
+ action: "In that project, create an API credential with endpoints:write, occurrences:read, schedules:read and schedules:write, and copy the secret it shows once. The key picker starts with nothing selected and refuses an empty one, so those four are the boxes to tick.",
119
119
  because: "credentials.create accepts only a signed-in member: a credential that could mint another credential would make revoking one meaningless.",
120
120
  id: "credential",
121
121
  title: "An API credential",
122
122
  },
123
123
  {
124
124
  action: "Have an HTTPS URL of your own that answers POST with a 2xx status, and can be reached from the public internet.",
125
- because: "Greatwait delivers your callback to an address you control. It does not offer a shared receiver to try, and it will not send your payload to a third-party inspection service on your behalf.",
125
+ because: "GreatWait delivers your callback to an address you control. It does not offer a shared receiver to try, and it will not send your payload to a third-party inspection service on your behalf.",
126
126
  id: "receiver",
127
127
  title: "An HTTPS receiver you control",
128
128
  },
@@ -190,7 +190,7 @@ export const FIRST_VALUE_STEPS = [
190
190
  key: "check-service",
191
191
  observe: "The service name and the environment you meant to work in. If the environment is not the one you expect, stop and fix GREATWAIT_API_URL before creating anything.",
192
192
  operationId: "meta.version",
193
- purpose: "Confirms the origin you are pointed at is a Greatwait API and says which environment it serves. It needs no credential, so it separates 'wrong URL' from 'wrong key'.",
193
+ purpose: "Confirms the origin you are pointed at is a GreatWait API and says which environment it serves. It needs no credential, so it separates 'wrong URL' from 'wrong key'.",
194
194
  recovery: [
195
195
  {
196
196
  nextMove: "Something answered, but not this service. Check GREATWAIT_API_URL — a 404 here comes from a proxy in front of the API rather than from the API, so it carries no problem document to read.",
@@ -235,7 +235,7 @@ export const FIRST_VALUE_STEPS = [
235
235
  { from: "id", variable: "GREATWAIT_ENDPOINTID" },
236
236
  { from: "secret", secret: true, variable: "GREATWAIT_ENDPOINT_SECRET" },
237
237
  ],
238
- observe: "An endpoint identifier, and a signing secret returned by this call and by no other. Store the secret now: reading the endpoint back later will not show it again.",
238
+ observe: "An endpoint identifier, and a signing secret. Store it now: this is the only call that returns it, and reading the endpoint back shows a redacted prefix instead. It is not gone if you lose it — a signed-in member can read it again on the endpoint's own page in the dashboard, which is the one caller `endpoints.revealSigningSecret` accepts.",
239
239
  operationId: "endpoints.create",
240
240
  purpose: "Registers the address every occurrence of this schedule is delivered to, and mints the per-endpoint signing key your receiver verifies callbacks with.",
241
241
  recovery: [
@@ -247,6 +247,10 @@ export const FIRST_VALUE_STEPS = [
247
247
  nextMove: "This project is at its destination ceiling. Disable a destination you no longer deliver to; disabled ones still count, because they stay readable for audit.",
248
248
  when: "plan_limit_reached",
249
249
  },
250
+ {
251
+ nextMove: "An active destination already delivers to this address in this project — usually one a previous run of this journey created. Reuse that destination, disable it first, or give the new one a name of its own.",
252
+ when: "state_conflict",
253
+ },
250
254
  ],
251
255
  request: { url: "{{GREATWAIT_RECEIVER_URL}}" },
252
256
  title: "Create the destination",
@@ -278,7 +282,7 @@ export const FIRST_VALUE_STEPS = [
278
282
  when: "invalid_request",
279
283
  },
280
284
  {
281
- nextMove: "This organization is at a plan ceiling — live schedules, distinct partition keys, or payload size. Nothing was created; reduce the payload or archive a schedule and retry.",
285
+ nextMove: "This organization is at a plan ceiling — the payload is larger than its plan carries, or the schedule names a new partition key when the organization's keys are full. Nothing was created; send a smaller payload or reuse a partition key that is already live, and retry.",
282
286
  when: "plan_limit_reached",
283
287
  },
284
288
  {
@@ -375,7 +379,7 @@ export const FIRST_VALUE_STEPS = [
375
379
  when: "attempt-failed",
376
380
  },
377
381
  {
378
- nextMove: "Nothing reached your receiver. Confirm the URL answers a POST from the public internet, and that it is not behind an allowlist Greatwait is not on.",
382
+ nextMove: "Nothing reached your receiver. Confirm the URL answers a POST from the public internet, and that it is not behind an allowlist GreatWait is not on.",
379
383
  when: "receiver-unreachable",
380
384
  },
381
385
  ],