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

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 (349) hide show
  1. package/README.md +11 -9
  2. package/dist/authority.d.ts +84 -21
  3. package/dist/authority.js +47 -2
  4. package/dist/billing.d.ts +1001 -0
  5. package/dist/billing.js +684 -0
  6. package/dist/callback-safety.d.ts +2 -2
  7. package/dist/callback-safety.js +2 -2
  8. package/dist/compatibility.d.ts +3 -3
  9. package/dist/compatibility.js +1 -1
  10. package/dist/data-export.d.ts +67 -0
  11. package/dist/data-export.js +182 -0
  12. package/dist/endpoints.d.ts +181 -240
  13. package/dist/endpoints.js +77 -81
  14. package/dist/events.d.ts +17 -17
  15. package/dist/events.js +1 -1
  16. package/dist/first-value-journey.d.ts +192 -42
  17. package/dist/first-value-journey.js +212 -6
  18. package/dist/forecast.d.ts +71 -71
  19. package/dist/forecast.js +1 -1
  20. package/dist/identifiers.d.ts +20 -20
  21. package/dist/identifiers.js +1 -1
  22. package/dist/identity.d.ts +45 -41
  23. package/dist/identity.js +5 -4
  24. package/dist/index.d.ts +13 -8
  25. package/dist/index.js +13 -8
  26. package/dist/mcp.d.ts +201 -0
  27. package/dist/mcp.js +214 -0
  28. package/dist/naming.d.ts +45 -0
  29. package/dist/naming.js +159 -0
  30. package/dist/oauth.d.ts +186 -172
  31. package/dist/oauth.js +84 -8
  32. package/dist/operation-definitions.d.ts +9 -0
  33. package/dist/operation-definitions.js +7 -0
  34. package/dist/operations.d.ts +4359 -2214
  35. package/dist/operations.js +2754 -881
  36. package/dist/organization-lifecycle.d.ts +34 -0
  37. package/dist/organization-lifecycle.js +122 -0
  38. package/dist/partition.d.ts +26 -0
  39. package/dist/policy.d.ts +4 -4
  40. package/dist/policy.js +9 -5
  41. package/dist/problems.d.ts +32 -26
  42. package/dist/problems.js +6 -2
  43. package/dist/protocol.d.ts +204 -75
  44. package/dist/protocol.js +108 -36
  45. package/dist/scheduling-records.d.ts +343 -285
  46. package/dist/scheduling-records.js +1 -1
  47. package/dist/scheduling.d.ts +670 -360
  48. package/dist/scheduling.js +382 -56
  49. package/dist/secrets.d.ts +119 -105
  50. package/dist/secrets.js +1 -1
  51. package/dist/signatures.d.ts +74 -74
  52. package/dist/signatures.js +1 -1
  53. package/dist/tenancy.d.ts +142 -68
  54. package/dist/tenancy.js +70 -17
  55. package/dist/test-sink.d.ts +127 -127
  56. package/dist/test-sink.js +1 -1
  57. package/dist/time.d.ts +4 -4
  58. package/dist/time.js +1 -1
  59. package/dist/timing.d.ts +65 -0
  60. package/dist/timing.js +82 -0
  61. package/dist/usage.d.ts +103 -47
  62. package/dist/usage.js +197 -31
  63. package/dist/workspace.d.ts +34 -34
  64. package/dist/workspace.js +1 -1
  65. package/dist/zod-values.d.ts +3 -0
  66. package/dist/zod-values.js +2 -0
  67. package/dist/zod.d.ts +2 -0
  68. package/dist/zod.js +2 -0
  69. package/generated/v1/examples/attempts.list.response.json +4 -0
  70. package/generated/v1/examples/attempts.read.response.json +4 -0
  71. package/generated/v1/examples/billing.autotopup.request.json +5 -0
  72. package/generated/v1/examples/billing.autotopup.response.json +120 -0
  73. package/generated/v1/examples/billing.autotopuppreview.request.json +19 -0
  74. package/generated/v1/examples/billing.autotopuppreview.response.json +45 -0
  75. package/generated/v1/examples/billing.budgets.request.json +13 -0
  76. package/generated/v1/examples/billing.budgets.response.json +22 -0
  77. package/generated/v1/examples/billing.ceiling.request.json +8 -0
  78. package/generated/v1/examples/billing.ceiling.response.json +120 -0
  79. package/generated/v1/examples/billing.change.request.json +5 -0
  80. package/generated/v1/examples/billing.change.response.json +12 -0
  81. package/generated/v1/examples/billing.funding.response.json +120 -0
  82. package/generated/v1/examples/billing.fundingquote.request.json +7 -0
  83. package/generated/v1/examples/billing.fundingquote.response.json +13 -0
  84. package/generated/v1/examples/billing.ledger.response.json +23 -0
  85. package/generated/v1/examples/billing.notices.response.json +41 -0
  86. package/generated/v1/examples/billing.notificationsettings.response.json +17 -0
  87. package/generated/v1/examples/billing.notificationsettingsupdate.request.json +9 -0
  88. package/generated/v1/examples/billing.notificationsettingsupdate.response.json +17 -0
  89. package/generated/v1/examples/billing.portal.response.json +3 -0
  90. package/generated/v1/examples/billing.projects.response.json +12 -0
  91. package/generated/v1/examples/billing.purchase.request.json +5 -0
  92. package/generated/v1/examples/billing.purchase.response.json +120 -0
  93. package/generated/v1/examples/billing.quote.request.json +4 -0
  94. package/generated/v1/examples/billing.quote.response.json +19 -0
  95. package/generated/v1/examples/billing.reconcile.response.json +73 -0
  96. package/generated/v1/examples/billing.refundrequest.request.json +10 -0
  97. package/generated/v1/examples/billing.refundrequest.response.json +11 -0
  98. package/generated/v1/examples/billing.refundresolution.request.json +4 -0
  99. package/generated/v1/examples/billing.refundresolution.response.json +120 -0
  100. package/generated/v1/examples/billing.summary.response.json +73 -0
  101. package/generated/v1/examples/context.read.response.json +6 -0
  102. package/generated/v1/examples/credentials.connection.response.json +16 -0
  103. package/generated/v1/examples/endpoints.acknowledgeSigningKeyRotation.response.json +18 -0
  104. package/generated/v1/examples/endpoints.create.response.json +1 -1
  105. package/generated/v1/examples/endpoints.disable.response.json +0 -1
  106. package/generated/v1/examples/{endpoints.verify.response.json → endpoints.enable.response.json} +4 -5
  107. package/generated/v1/examples/endpoints.list.response.json +1 -2
  108. package/generated/v1/examples/endpoints.read.response.json +2 -2
  109. package/generated/v1/examples/endpoints.revealSigningSecret.response.json +7 -0
  110. package/generated/v1/examples/endpoints.rotateSigningKey.response.json +1 -2
  111. package/generated/v1/examples/endpoints.update.response.json +1 -1
  112. package/generated/v1/examples/executions.list.response.json +20 -0
  113. package/generated/v1/examples/exports.cancel.response.json +11 -0
  114. package/generated/v1/examples/exports.create.request.json +1 -0
  115. package/generated/v1/examples/exports.create.response.json +8 -0
  116. package/generated/v1/examples/exports.part.response.json +5 -0
  117. package/generated/v1/examples/exports.read.response.json +8 -0
  118. package/generated/v1/examples/occurrences.read.response.json +4 -0
  119. package/generated/v1/examples/organizations.close.request.json +5 -0
  120. package/generated/v1/examples/organizations.close.response.json +10 -0
  121. package/generated/v1/examples/organizations.lifecycle.response.json +10 -0
  122. package/generated/v1/examples/organizations.restore.request.json +3 -0
  123. package/generated/v1/examples/organizations.restore.response.json +10 -0
  124. package/generated/v1/examples/projects.archive.request.json +3 -0
  125. package/generated/v1/examples/projects.archive.response.json +14 -0
  126. package/generated/v1/examples/projects.create.response.json +10 -1
  127. package/generated/v1/examples/projects.delete.response.json +9 -0
  128. package/generated/v1/examples/projects.list.response.json +12 -2
  129. package/generated/v1/examples/projects.rename.request.json +3 -0
  130. package/generated/v1/examples/projects.rename.response.json +14 -0
  131. package/generated/v1/examples/schedules.archive.response.json +3 -0
  132. package/generated/v1/examples/schedules.cancel.response.json +3 -0
  133. package/generated/v1/examples/schedules.create.request.json +4 -0
  134. package/generated/v1/examples/schedules.create.response.json +3 -0
  135. package/generated/v1/examples/schedules.list.response.json +3 -0
  136. package/generated/v1/examples/schedules.pause.response.json +3 -0
  137. package/generated/v1/examples/schedules.read.response.json +6 -0
  138. package/generated/v1/examples/schedules.replace.request.json +4 -0
  139. package/generated/v1/examples/schedules.replace.response.json +3 -0
  140. package/generated/v1/examples/schedules.resume.response.json +3 -0
  141. package/generated/v1/examples/timing.summary.response.json +35 -0
  142. package/generated/v1/examples/usage.read.response.json +1 -0
  143. package/generated/v1/first-value-journey.json +19 -10
  144. package/generated/v1/manifest.json +1019 -53
  145. package/generated/v1/openapi.json +30597 -5709
  146. package/generated/v1/policy-matrix.json +290 -45
  147. package/generated/v1/schemas/attempts.list.response.json +24 -1
  148. package/generated/v1/schemas/attempts.read.response.json +24 -1
  149. package/generated/v1/schemas/billing.autotopup.request-headers.json +13 -0
  150. package/generated/v1/schemas/billing.autotopup.request.json +22 -0
  151. package/generated/v1/schemas/billing.autotopup.response-headers.json +10 -0
  152. package/generated/v1/schemas/billing.autotopup.response.json +552 -0
  153. package/generated/v1/schemas/billing.autotopuppreview.request.json +77 -0
  154. package/generated/v1/schemas/billing.autotopuppreview.response.json +277 -0
  155. package/generated/v1/schemas/billing.budgets.request-headers.json +13 -0
  156. package/generated/v1/schemas/billing.budgets.request.json +66 -0
  157. package/generated/v1/schemas/billing.budgets.response-headers.json +10 -0
  158. package/generated/v1/schemas/billing.budgets.response.json +92 -0
  159. package/generated/v1/schemas/billing.ceiling.request-headers.json +13 -0
  160. package/generated/v1/schemas/billing.ceiling.request.json +40 -0
  161. package/generated/v1/schemas/billing.ceiling.response-headers.json +10 -0
  162. package/generated/v1/schemas/billing.ceiling.response.json +552 -0
  163. package/generated/v1/schemas/billing.change.request-headers.json +13 -0
  164. package/generated/v1/schemas/billing.change.request.json +22 -0
  165. package/generated/v1/schemas/billing.change.response.json +119 -0
  166. package/generated/v1/schemas/billing.funding.response.json +552 -0
  167. package/generated/v1/schemas/billing.fundingquote.request.json +28 -0
  168. package/generated/v1/schemas/billing.fundingquote.response.json +61 -0
  169. package/generated/v1/schemas/billing.ledger.query.json +16 -0
  170. package/generated/v1/schemas/billing.ledger.response.json +125 -0
  171. package/generated/v1/schemas/billing.notices.query.json +16 -0
  172. package/generated/v1/schemas/billing.notices.response.json +278 -0
  173. package/generated/v1/schemas/billing.notificationsettings.response.json +70 -0
  174. package/generated/v1/schemas/billing.notificationsettingsupdate.request-headers.json +13 -0
  175. package/generated/v1/schemas/billing.notificationsettingsupdate.request.json +36 -0
  176. package/generated/v1/schemas/billing.notificationsettingsupdate.response-headers.json +10 -0
  177. package/generated/v1/schemas/billing.notificationsettingsupdate.response.json +70 -0
  178. package/generated/v1/schemas/billing.portal.response.json +11 -0
  179. package/generated/v1/schemas/billing.projects.response.json +119 -0
  180. package/generated/v1/schemas/billing.purchase.request-headers.json +13 -0
  181. package/generated/v1/schemas/billing.purchase.request.json +22 -0
  182. package/generated/v1/schemas/billing.purchase.response-headers.json +10 -0
  183. package/generated/v1/schemas/billing.purchase.response.json +552 -0
  184. package/generated/v1/schemas/billing.quote.request.json +20 -0
  185. package/generated/v1/schemas/billing.quote.response.json +86 -0
  186. package/generated/v1/schemas/billing.reconcile.response.json +468 -0
  187. package/generated/v1/schemas/billing.refundrequest.request-headers.json +13 -0
  188. package/generated/v1/schemas/billing.refundrequest.request.json +42 -0
  189. package/generated/v1/schemas/billing.refundrequest.response-headers.json +10 -0
  190. package/generated/v1/schemas/billing.refundrequest.response.json +45 -0
  191. package/generated/v1/schemas/billing.refundresolution.request-headers.json +13 -0
  192. package/generated/v1/schemas/billing.refundresolution.request.json +61 -0
  193. package/generated/v1/schemas/billing.refundresolution.response-headers.json +10 -0
  194. package/generated/v1/schemas/billing.refundresolution.response.json +552 -0
  195. package/generated/v1/schemas/billing.summary.response.json +468 -0
  196. package/generated/v1/schemas/context.read.response.json +45 -0
  197. package/generated/v1/schemas/credentials.connection.response.json +66 -0
  198. package/generated/v1/schemas/credentials.create.request.json +2 -0
  199. package/generated/v1/schemas/credentials.create.response.json +2 -0
  200. package/generated/v1/schemas/credentials.list.response.json +2 -0
  201. package/generated/v1/schemas/credentials.revoke.response.json +2 -0
  202. package/generated/v1/schemas/credentials.rotate.response.json +4 -0
  203. package/generated/v1/schemas/{endpoints.verify.request-headers.json → endpoints.acknowledgeSigningKeyRotation.request-headers.json} +2 -1
  204. package/generated/v1/schemas/{endpoints.verify.response.json → endpoints.acknowledgeSigningKeyRotation.response.json} +8 -21
  205. package/generated/v1/schemas/endpoints.create.request.json +5 -0
  206. package/generated/v1/schemas/endpoints.create.response.json +8 -21
  207. package/generated/v1/schemas/endpoints.disable.response.json +8 -21
  208. package/generated/v1/schemas/endpoints.enable.response-headers.json +11 -0
  209. package/generated/v1/schemas/endpoints.enable.response.json +87 -0
  210. package/generated/v1/schemas/endpoints.list.response.json +8 -21
  211. package/generated/v1/schemas/endpoints.read.response.json +8 -21
  212. package/generated/v1/schemas/endpoints.revealSigningSecret.response.json +43 -0
  213. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +8 -21
  214. package/generated/v1/schemas/endpoints.update.request.json +5 -0
  215. package/generated/v1/schemas/endpoints.update.response.json +8 -21
  216. package/generated/v1/schemas/executions.list.query.json +46 -0
  217. package/generated/v1/schemas/executions.list.response.json +116 -0
  218. package/generated/v1/schemas/exports.cancel.response.json +48 -0
  219. package/generated/v1/schemas/exports.create.request.json +6 -0
  220. package/generated/v1/schemas/exports.create.response.json +38 -0
  221. package/generated/v1/schemas/exports.part.query.json +11 -0
  222. package/generated/v1/schemas/exports.part.response.json +22 -0
  223. package/generated/v1/schemas/exports.read.response.json +38 -0
  224. package/generated/v1/schemas/grants.list.response.json +2 -0
  225. package/generated/v1/schemas/grants.revoke.response.json +2 -0
  226. package/generated/v1/schemas/occurrences.list.query.json +5 -0
  227. package/generated/v1/schemas/occurrences.list.response.json +23 -0
  228. package/generated/v1/schemas/occurrences.read.response.json +23 -0
  229. package/generated/v1/schemas/occurrences.redeliver.response.json +24 -1
  230. package/generated/v1/schemas/organizations.close.request.json +20 -0
  231. package/generated/v1/schemas/organizations.close.response.json +68 -0
  232. package/generated/v1/schemas/organizations.lifecycle.response.json +68 -0
  233. package/generated/v1/schemas/organizations.restore.request.json +13 -0
  234. package/generated/v1/schemas/organizations.restore.response.json +68 -0
  235. package/generated/v1/schemas/projects.archive.request-headers.json +11 -0
  236. package/generated/v1/schemas/projects.archive.request.json +10 -0
  237. package/generated/v1/schemas/projects.archive.response-headers.json +11 -0
  238. package/generated/v1/schemas/projects.archive.response.json +79 -0
  239. package/generated/v1/schemas/projects.create.response.json +55 -1
  240. package/generated/v1/schemas/projects.delete.request-headers.json +11 -0
  241. package/generated/v1/schemas/projects.delete.response.json +37 -0
  242. package/generated/v1/schemas/projects.list.response.json +61 -2
  243. package/generated/v1/schemas/projects.rename.request-headers.json +11 -0
  244. package/generated/v1/schemas/projects.rename.request.json +12 -0
  245. package/generated/v1/schemas/projects.rename.response-headers.json +11 -0
  246. package/generated/v1/schemas/projects.rename.response.json +79 -0
  247. package/generated/v1/schemas/schedules.archive.response.json +90 -2
  248. package/generated/v1/schemas/schedules.cancel.response.json +90 -2
  249. package/generated/v1/schemas/schedules.create.request.json +24 -3
  250. package/generated/v1/schemas/schedules.create.response.json +90 -2
  251. package/generated/v1/schemas/schedules.list.query.json +13 -0
  252. package/generated/v1/schemas/schedules.list.response.json +67 -2
  253. package/generated/v1/schemas/schedules.pause.response.json +90 -2
  254. package/generated/v1/schemas/schedules.read.response.json +90 -2
  255. package/generated/v1/schemas/schedules.replace.request.json +24 -3
  256. package/generated/v1/schemas/schedules.replace.response.json +90 -2
  257. package/generated/v1/schemas/schedules.resume.response.json +90 -2
  258. package/generated/v1/schemas/timing.summary.response.json +191 -0
  259. package/generated/v1/schemas/usage.read.query.json +7 -0
  260. package/generated/v1/schemas/usage.read.response.json +36 -1
  261. package/generated/v1/snippets/attempts.list.json +1 -0
  262. package/generated/v1/snippets/attempts.read.json +1 -0
  263. package/generated/v1/snippets/billing.autotopup.json +6 -0
  264. package/generated/v1/snippets/billing.autotopuppreview.json +6 -0
  265. package/generated/v1/snippets/billing.budgets.json +6 -0
  266. package/generated/v1/snippets/billing.ceiling.json +6 -0
  267. package/generated/v1/snippets/billing.change.json +6 -0
  268. package/generated/v1/snippets/billing.funding.json +6 -0
  269. package/generated/v1/snippets/billing.fundingquote.json +6 -0
  270. package/generated/v1/snippets/billing.ledger.json +6 -0
  271. package/generated/v1/snippets/billing.notices.json +6 -0
  272. package/generated/v1/snippets/billing.notificationsettings.json +6 -0
  273. package/generated/v1/snippets/billing.notificationsettingsupdate.json +6 -0
  274. package/generated/v1/snippets/billing.portal.json +6 -0
  275. package/generated/v1/snippets/billing.projects.json +6 -0
  276. package/generated/v1/snippets/billing.purchase.json +6 -0
  277. package/generated/v1/snippets/billing.quote.json +6 -0
  278. package/generated/v1/snippets/billing.reconcile.json +6 -0
  279. package/generated/v1/snippets/billing.refundrequest.json +6 -0
  280. package/generated/v1/snippets/billing.refundresolution.json +6 -0
  281. package/generated/v1/snippets/billing.summary.json +6 -0
  282. package/generated/v1/snippets/context.read.json +6 -0
  283. package/generated/v1/snippets/credentials.connection.json +6 -0
  284. package/generated/v1/snippets/credentials.create.json +1 -0
  285. package/generated/v1/snippets/credentials.list.json +1 -0
  286. package/generated/v1/snippets/credentials.revoke.json +1 -0
  287. package/generated/v1/snippets/credentials.rotate.json +1 -0
  288. package/generated/v1/snippets/endpoints.acknowledgeSigningKeyRotation.json +6 -0
  289. package/generated/v1/snippets/endpoints.create.json +1 -0
  290. package/generated/v1/snippets/endpoints.disable.json +1 -0
  291. package/generated/v1/snippets/{endpoints.verify.json → endpoints.enable.json} +4 -3
  292. package/generated/v1/snippets/endpoints.list.json +1 -0
  293. package/generated/v1/snippets/endpoints.read.json +1 -0
  294. package/generated/v1/snippets/endpoints.revealSigningSecret.json +6 -0
  295. package/generated/v1/snippets/endpoints.rotateSigningKey.json +1 -0
  296. package/generated/v1/snippets/endpoints.update.json +1 -0
  297. package/generated/v1/snippets/executions.list.json +6 -0
  298. package/generated/v1/snippets/exports.cancel.json +6 -0
  299. package/generated/v1/snippets/exports.create.json +6 -0
  300. package/generated/v1/snippets/exports.part.json +6 -0
  301. package/generated/v1/snippets/exports.read.json +6 -0
  302. package/generated/v1/snippets/forecast.read.json +1 -0
  303. package/generated/v1/snippets/forecast.windows.json +1 -0
  304. package/generated/v1/snippets/grants.list.json +1 -0
  305. package/generated/v1/snippets/grants.revoke.json +1 -0
  306. package/generated/v1/snippets/journey/await-occurrence.json +6 -0
  307. package/generated/v1/snippets/journey/check-credential.json +6 -0
  308. package/generated/v1/snippets/journey/check-service.json +6 -0
  309. package/generated/v1/snippets/journey/clean-up.json +6 -0
  310. package/generated/v1/snippets/journey/create-destination.json +6 -0
  311. package/generated/v1/snippets/journey/create-one-shot.json +6 -0
  312. package/generated/v1/snippets/journey/read-attempt.json +6 -0
  313. package/generated/v1/snippets/journey/read-schedule.json +6 -0
  314. package/generated/v1/snippets/journey/replay-one-shot.json +6 -0
  315. package/generated/v1/snippets/meta.scaffold.json +1 -0
  316. package/generated/v1/snippets/meta.version.json +1 -0
  317. package/generated/v1/snippets/occurrences.list.json +1 -0
  318. package/generated/v1/snippets/occurrences.read.json +1 -0
  319. package/generated/v1/snippets/occurrences.redeliver.json +1 -0
  320. package/generated/v1/snippets/organizations.close.json +6 -0
  321. package/generated/v1/snippets/organizations.lifecycle.json +6 -0
  322. package/generated/v1/snippets/organizations.restore.json +6 -0
  323. package/generated/v1/snippets/projects.archive.json +6 -0
  324. package/generated/v1/snippets/projects.create.json +1 -0
  325. package/generated/v1/snippets/projects.delete.json +6 -0
  326. package/generated/v1/snippets/projects.list.json +1 -0
  327. package/generated/v1/snippets/projects.rename.json +6 -0
  328. package/generated/v1/snippets/schedules.archive.json +1 -0
  329. package/generated/v1/snippets/schedules.cancel.json +1 -0
  330. package/generated/v1/snippets/schedules.create.json +4 -3
  331. package/generated/v1/snippets/schedules.list.json +1 -0
  332. package/generated/v1/snippets/schedules.pause.json +1 -0
  333. package/generated/v1/snippets/schedules.read.json +1 -0
  334. package/generated/v1/snippets/schedules.replace.json +4 -3
  335. package/generated/v1/snippets/schedules.resume.json +1 -0
  336. package/generated/v1/snippets/sinkdeliveries.list.json +1 -0
  337. package/generated/v1/snippets/sinkdeliveries.read.json +1 -0
  338. package/generated/v1/snippets/testsinks.configure.json +1 -0
  339. package/generated/v1/snippets/testsinks.create.json +1 -0
  340. package/generated/v1/snippets/testsinks.delete.json +1 -0
  341. package/generated/v1/snippets/testsinks.list.json +1 -0
  342. package/generated/v1/snippets/testsinks.read.json +1 -0
  343. package/generated/v1/snippets/timing.summary.json +6 -0
  344. package/generated/v1/snippets/usage.read.json +1 -0
  345. package/package.json +2 -7
  346. package/dist/callback-ownership.d.ts +0 -58
  347. package/dist/callback-ownership.js +0 -71
  348. package/generated/v1/callback-endpoint-verification.json +0 -59
  349. /package/generated/v1/schemas/{endpoints.verify.response-headers.json → endpoints.acknowledgeSigningKeyRotation.response-headers.json} +0 -0
@@ -1,13 +1,20 @@
1
- import { z } from "zod";
2
- import { callbackEndpointCreatedSchema, callbackEndpointPageSchema, callbackEndpointRequestSchema, callbackEndpointRotatedSchema, callbackEndpointSchema, callbackSigningKeyRotationRequestSchema, } from "./endpoints.js";
1
+ import { z } from "./zod.js";
2
+ import { DATA_EXPORT_OPERATIONS } from "./data-export.js";
3
+ import { ORGANIZATION_LIFECYCLE_OPERATIONS } from "./organization-lifecycle.js";
4
+ import { API_UNUSED_RESPONSE_SCHEMA } from "./operation-definitions.js";
5
+ import { credentialContextSchema } from "./authority.js";
6
+ import { callbackEndpointCreatedSchema, callbackEndpointPageSchema, callbackEndpointRequestSchema, callbackEndpointRotatedSchema, callbackEndpointSchema, callbackEndpointSigningSecretsSchema, callbackSigningKeyRotationRequestSchema, } from "./endpoints.js";
3
7
  import { FORECAST_WINDOW_VERSION, forecastRequestSchema, forecastSchema, forecastWindowsSchema, } from "./forecast.js";
4
8
  import { usageRequestSchema, usageSchema } from "./usage.js";
5
- import { conditionalRequestHeaderSchema, idempotencyReplayResponseHeaderSchema, idempotencyRequestHeaderSchema, pageRequestSchema, replayedResponseHeaderSchema, requiredIdempotencyRequestHeaderSchema, versionResponseHeaderSchema, } from "./protocol.js";
9
+ import { deliveryTimingSummarySchema } from "./timing.js";
10
+ import { billingAutoTopUpApplyRequestSchema, billingAutoTopUpPreviewRequestSchema, billingAutoTopUpPreviewSchema, billingCeilingUpdateRequestSchema, billingFundingQuoteRequestSchema, billingFundingQuoteSchema, billingFundingViewSchema, billingNoticePageSchema, billingNotificationSettingsSchema, billingNotificationSettingsUpdateRequestSchema, billingLedgerPageSchema, billingLedgerRequestSchema, billingBudgetUpdateRequestHeadersSchema, billingBudgetUpdateRequestSchema, billingBudgetUpdateResponseSchema, billingPurchaseRequestSchema, billingRefundRequestCreateSchema, billingRefundResolutionRequestSchema, billingRefundRequestViewSchema, billingSummarySchema, projectBillingStateSchema, projectBillingQuoteSchema, projectBillingQuoteRequestSchema, projectBillingChangeRequestSchema, billingPortalSchema, } from "./billing.js";
11
+ import { conditionalRequestHeaderSchema, idempotencyReplayResponseHeaderSchema, idempotencyRequestHeaderSchema, historyPageRequestSchema, pageRequestSchema, scheduleListRequestSchema, replayedResponseHeaderSchema, requiredConditionalRequestHeaderSchema, requiredIdempotencyRequestHeaderSchema, versionResponseHeaderSchema, } from "./protocol.js";
6
12
  import { oauthGrantListSchema, oauthGrantRevokedSchema } from "./oauth.js";
7
13
  import { credentialCreatedSchema, credentialPageSchema, credentialRequestSchema, credentialRevokedSchema, credentialRotatedSchema, credentialRotationRequestSchema, } from "./secrets.js";
8
- import { attemptPageSchema, attemptViewSchema, occurrencePageSchema, occurrenceViewSchema, schedulePageSchema, scheduleRequestSchema, scheduleViewSchema, } from "./scheduling.js";
14
+ import { attemptPageSchema, attemptViewSchema, occurrencePageSchema, projectOccurrenceListRequestSchema, projectOccurrencePageSchema, occurrenceViewSchema, schedulePageSchema, scheduleRequestSchema, scheduleViewSchema, } from "./scheduling.js";
9
15
  import { testSinkCreateRequestSchema, testSinkDeliveryBodySchema, testSinkDeliveryPageSchema, testSinkPageSchema, testSinkProgramSchema, testSinkSchema, } from "./test-sink.js";
10
- import { projectCreateRequestSchema, projectListSchema, projectSummarySchema, } from "./tenancy.js";
16
+ import { projectArchiveRequestSchema, projectCreateRequestSchema, projectDeletedSchema, projectListSchema, projectSummarySchema, projectUpdateRequestSchema, } from "./tenancy.js";
17
+ import { mcpConnectionSchema } from "./mcp.js";
11
18
  import { scaffoldVersionSchema, workspaceScaffoldSchema } from "./workspace.js";
12
19
  import { timestampSchema } from "./time.js";
13
20
  /**
@@ -47,15 +54,435 @@ export const mockScenarioResponseSchema = z.object({
47
54
  export const fixtureListSchema = z.object({
48
55
  fixtures: z.array(z.object({ id: z.string().min(1), description: z.string().min(1) })),
49
56
  });
57
+ const PROJECT_BILLING_EXAMPLE = {
58
+ desiredRevision: 2,
59
+ effectiveRevision: 2,
60
+ pending: false,
61
+ recurringProjectFees: { currency: "USD", microdollars: "0", scale: 6 },
62
+ projects: [],
63
+ pendingOperations: [],
64
+ };
65
+ const PROJECT_BILLING_QUOTE_EXAMPLE = {
66
+ action: "add",
67
+ project: "proj_00000000000000000000000000",
68
+ quote: "quote-example",
69
+ expectedRevision: 2,
70
+ expiresAt: "2026-09-10T12:05:00.000Z",
71
+ charge: { currency: "USD", microdollars: "5000000", scale: 6 },
72
+ monthlyProjectFees: { currency: "USD", microdollars: "5000000", scale: 6 },
73
+ effectiveAt: "2026-09-10T12:00:00.000Z",
74
+ formerIncludedWillBlock: false,
75
+ };
76
+ const BILLING_SUMMARY_EXAMPLE = {
77
+ activation: {
78
+ boundary: "2026-09-01T00:00:00.000Z",
79
+ mode: "shadow",
80
+ },
81
+ blockingReasons: [],
82
+ budgetPolicy: {
83
+ desired: { advisoryBudget: null, hardCap: null },
84
+ desiredRevision: 0,
85
+ effectiveRevision: 0,
86
+ pending: false,
87
+ },
88
+ credit: {
89
+ available: { currency: "USD", microdollars: "999980", scale: 6 },
90
+ consumed: { currency: "USD", microdollars: "10", scale: 6 },
91
+ reserved: { currency: "USD", microdollars: "10", scale: 6 },
92
+ },
93
+ desiredRevision: 2,
94
+ effectiveRevision: 1,
95
+ freshness: { kind: "authoritative" },
96
+ includedProject: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
97
+ period: {
98
+ automaticExecutionTopUp: {
99
+ pending: { currency: "USD", microdollars: "0", scale: 6 },
100
+ settled: { currency: "USD", microdollars: "0", scale: 6 },
101
+ },
102
+ subscribedProjectFees: {
103
+ currency: "USD",
104
+ microdollars: "0",
105
+ scale: 6,
106
+ },
107
+ reservedUsage: { currency: "USD", microdollars: "10", scale: 6 },
108
+ settledUsage: { currency: "USD", microdollars: "10", scale: 6 },
109
+ start: "2026-09-01T00:00:00.000Z",
110
+ end: "2026-10-01T00:00:00.000Z",
111
+ },
112
+ pending: true,
113
+ priceVersion: "payg-v1",
114
+ trialExpiresAt: "2026-09-15T00:00:00.000Z",
115
+ };
116
+ const BILLING_FUNDING_QUOTE_EXAMPLE = {
117
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
118
+ expectedRevision: 3,
119
+ expiresAt: "2026-09-10T12:05:00.000Z",
120
+ gross: null,
121
+ quote: "funding-quote-example",
122
+ tax: null,
123
+ taxStatus: "calculated-at-checkout",
124
+ };
125
+ const BILLING_FUNDING_EXAMPLE = {
126
+ automaticExecutionTopUp: {
127
+ ceiling: { currency: "USD", microdollars: "50000000", scale: 6 },
128
+ currentPeriod: {
129
+ end: "2026-10-01T00:00:00.000Z",
130
+ pending: { currency: "USD", microdollars: "10830000", scale: 6 },
131
+ remaining: { currency: "USD", microdollars: "29170000", scale: 6 },
132
+ settled: { currency: "USD", microdollars: "10000000", scale: 6 },
133
+ start: "2026-09-01T00:00:00.000Z",
134
+ },
135
+ rule: {
136
+ cooldownUntil: null,
137
+ desired: {
138
+ ceiling: { currency: "USD", microdollars: "50000000", scale: 6 },
139
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
140
+ triggerBelow: {
141
+ currency: "USD",
142
+ microdollars: "2000000",
143
+ scale: 6,
144
+ },
145
+ },
146
+ effective: {
147
+ ceiling: { currency: "USD", microdollars: "50000000", scale: 6 },
148
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
149
+ triggerBelow: {
150
+ currency: "USD",
151
+ microdollars: "2000000",
152
+ scale: 6,
153
+ },
154
+ },
155
+ state: "ready",
156
+ suspension: null,
157
+ },
158
+ revision: 3,
159
+ },
160
+ credit: {
161
+ amountOwed: { currency: "USD", microdollars: "0", scale: 6 },
162
+ available: { currency: "USD", microdollars: "9000000", scale: 6 },
163
+ reserved: { currency: "USD", microdollars: "10", scale: 6 },
164
+ },
165
+ freshness: { kind: "authoritative" },
166
+ paymentOperations: [
167
+ {
168
+ createdAt: "2026-09-10T12:00:00.000Z",
169
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
170
+ gross: { currency: "USD", microdollars: "10830000", scale: 6 },
171
+ id: "funding-operation-example",
172
+ kind: "automatic",
173
+ paymentUrl: "https://pay.stripe.com/receipts/acct_example/example",
174
+ reason: "payment-required",
175
+ state: "pending",
176
+ tax: { currency: "USD", microdollars: "830000", scale: 6 },
177
+ taxStatus: "confirmed",
178
+ updatedAt: "2026-09-10T12:00:01.000Z",
179
+ },
180
+ ],
181
+ subscribedProjectFees: {
182
+ currency: "USD",
183
+ microdollars: "5000000",
184
+ scale: 6,
185
+ },
186
+ };
187
+ const BILLING_NOTICE_PAGE_EXAMPLE = {
188
+ data: [
189
+ {
190
+ amounts: {
191
+ available: { currency: "USD", microdollars: "1750000", scale: 6 },
192
+ threshold: { currency: "USD", microdollars: "2000000", scale: 6 },
193
+ },
194
+ detail: "Available execution credit is below the configured USD 2.00 threshold.",
195
+ email: {
196
+ attempts: 3,
197
+ failureCode: "provider-unavailable",
198
+ lastAttemptAt: "2026-09-10T12:03:00.000Z",
199
+ state: "failed",
200
+ },
201
+ id: "billing-notice-example",
202
+ kind: "low-credit",
203
+ occurredAt: "2026-09-10T12:00:00.000Z",
204
+ payment: null,
205
+ recoveryPath: "#billing-funding",
206
+ resolvedAt: null,
207
+ scope: { kind: "organization" },
208
+ severity: "warning",
209
+ state: "active",
210
+ title: "Execution credit is low",
211
+ updatedAt: "2026-09-10T12:03:00.000Z",
212
+ },
213
+ ],
214
+ freshness: { kind: "authoritative" },
215
+ };
216
+ const BILLING_NOTIFICATION_SETTINGS_EXAMPLE = {
217
+ criticalEmail: true,
218
+ freshness: { kind: "authoritative" },
219
+ lowCreditThreshold: {
220
+ currency: "USD",
221
+ microdollars: "2000000",
222
+ scale: 6,
223
+ },
224
+ noncriticalEmail: true,
225
+ recipients: {
226
+ billingContacts: "active-billing-role-members",
227
+ owners: true,
228
+ },
229
+ revision: 1,
230
+ };
231
+ function withBillingFundingContract(operation) {
232
+ return {
233
+ ...operation,
234
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
235
+ ? {}
236
+ : BILLING_FUNDING_EXAMPLE,
237
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
238
+ ? API_UNUSED_RESPONSE_SCHEMA
239
+ : billingFundingViewSchema,
240
+ };
241
+ }
242
+ const BILLING_AUTO_TOP_UP_PREVIEW_EXAMPLE = {
243
+ action: "enable",
244
+ after: {
245
+ ceiling: { currency: "USD", microdollars: "50000000", scale: 6 },
246
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
247
+ triggerBelow: {
248
+ currency: "USD",
249
+ microdollars: "2000000",
250
+ scale: 6,
251
+ },
252
+ },
253
+ before: null,
254
+ currentPeriod: {
255
+ end: "2026-10-01T00:00:00.000Z",
256
+ pending: { currency: "USD", microdollars: "0", scale: 6 },
257
+ remaining: null,
258
+ settled: { currency: "USD", microdollars: "0", scale: 6 },
259
+ start: "2026-09-01T00:00:00.000Z",
260
+ },
261
+ expectedRevision: 3,
262
+ expandsAuthority: true,
263
+ expiresAt: "2026-09-10T12:05:00.000Z",
264
+ preview: "automatic-top-up-preview-example",
265
+ subscribedProjectFees: {
266
+ currency: "USD",
267
+ microdollars: "5000000",
268
+ scale: 6,
269
+ },
270
+ };
271
+ const BILLING_NOTICE_LIST_OPERATION = {
272
+ creates: false,
273
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
274
+ ? ""
275
+ : "Lists the verified organization's durable billing notices with exact USD amounts, affected scope, payment state, a fixed same-page recovery path, and visible email delivery failure. Raw provider details, payment credentials, callback data and arbitrary URLs have no field.",
276
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
277
+ ? {}
278
+ : BILLING_NOTICE_PAGE_EXAMPLE,
279
+ id: "billing.notices",
280
+ idempotent: true,
281
+ mcp: { destructive: false, kind: "tool", openWorld: false },
282
+ method: "GET",
283
+ mutates: false,
284
+ path: "/v1/billing/notices",
285
+ principals: ["api-credential", "oauth", "session"],
286
+ problems: ["invalid_request", "service_unavailable"],
287
+ query: pageRequestSchema,
288
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
289
+ ? API_UNUSED_RESPONSE_SCHEMA
290
+ : billingNoticePageSchema,
291
+ scopes: ["usage:read"],
292
+ sessionAuthority: "headers",
293
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
294
+ ? ""
295
+ : "List persistent billing notices",
296
+ surfaces: ["api", "mock"],
297
+ };
298
+ const BILLING_NOTIFICATION_SETTINGS_OPERATION = {
299
+ creates: false,
300
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
301
+ ? ""
302
+ : "Reads the USD 2.00 default low-credit threshold and optional-email choice. Critical email remains mandatory for owners and active billing-role members; addresses and contact management are absent.",
303
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
304
+ ? {}
305
+ : BILLING_NOTIFICATION_SETTINGS_EXAMPLE,
306
+ id: "billing.notificationsettings",
307
+ idempotent: true,
308
+ mcp: { destructive: false, kind: "tool", openWorld: false },
309
+ method: "GET",
310
+ mutates: false,
311
+ path: "/v1/billing/notification-settings",
312
+ principals: ["api-credential", "oauth", "session"],
313
+ problems: ["service_unavailable"],
314
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
315
+ ? API_UNUSED_RESPONSE_SCHEMA
316
+ : billingNotificationSettingsSchema,
317
+ scopes: ["usage:read"],
318
+ sessionAuthority: "headers",
319
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
320
+ ? ""
321
+ : "Read billing notification settings",
322
+ surfaces: ["api", "mock"],
323
+ };
324
+ const BILLING_NOTIFICATION_SETTINGS_UPDATE_OPERATION = {
325
+ creates: false,
326
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
327
+ ? ""
328
+ : "Replaces the low-credit threshold and noncritical email choice at an expected revision. Critical email stays mandatory; idempotent retries converge and agents require explicit approval.",
329
+ environments: ["live"],
330
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
331
+ ? {}
332
+ : BILLING_NOTIFICATION_SETTINGS_EXAMPLE,
333
+ id: "billing.notificationsettingsupdate",
334
+ idempotent: true,
335
+ mcp: { destructive: false, kind: "tool", openWorld: false },
336
+ method: "PATCH",
337
+ mutates: true,
338
+ path: "/v1/billing/notification-settings",
339
+ principals: ["api-credential", "oauth", "session"],
340
+ problems: [
341
+ "idempotency_key_reused",
342
+ "invalid_request",
343
+ "revision_conflict",
344
+ "service_unavailable",
345
+ "test_to_live_escalation",
346
+ ],
347
+ request: billingNotificationSettingsUpdateRequestSchema,
348
+ requestExample: globalThis
349
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
350
+ ? {}
351
+ : {
352
+ expectedRevision: 1,
353
+ lowCreditThreshold: {
354
+ currency: "USD",
355
+ microdollars: "2000000",
356
+ scale: 6,
357
+ },
358
+ noncriticalEmail: false,
359
+ },
360
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
361
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
362
+ ? API_UNUSED_RESPONSE_SCHEMA
363
+ : billingNotificationSettingsSchema,
364
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
365
+ ? {}
366
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
367
+ scopes: ["billing:write"],
368
+ sessionAuthority: "headers",
369
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
370
+ ? ""
371
+ : "Update billing notification settings",
372
+ surfaces: ["api", "mock"],
373
+ };
374
+ const BILLING_AUTO_TOP_UP_PREVIEW_OPERATION = {
375
+ creates: false,
376
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
377
+ ? ""
378
+ : "Previews one complete automatic execution-credit top-up rule without changing payment authority or contacting the payment provider. Enable and edit replace the fixed credit amount, usable-balance trigger and UTC-month gross ceiling together; disable and resume name those exact intents. The preview reports the current and proposed rule, whether authority expands, existing monthly commitments and separate recurring project fees. USD 10 below USD 2 within USD 50 is a suggested editable rule, not a platform maximum or target-balance refill.",
379
+ environments: ["live"],
380
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
381
+ ? {}
382
+ : BILLING_AUTO_TOP_UP_PREVIEW_EXAMPLE,
383
+ id: "billing.autotopuppreview",
384
+ idempotent: false,
385
+ mcp: { destructive: false, kind: "tool", openWorld: false },
386
+ method: "POST",
387
+ mutates: false,
388
+ path: "/v1/billing/funding/auto-top-up/preview",
389
+ principals: ["api-credential", "oauth", "session"],
390
+ problems: [
391
+ "invalid_request",
392
+ "revision_conflict",
393
+ "service_unavailable",
394
+ "state_conflict",
395
+ "test_to_live_escalation",
396
+ ],
397
+ request: billingAutoTopUpPreviewRequestSchema,
398
+ requestExample: globalThis
399
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
400
+ ? {}
401
+ : {
402
+ action: "enable",
403
+ ceiling: {
404
+ currency: "USD",
405
+ microdollars: "50000000",
406
+ scale: 6,
407
+ },
408
+ credit: {
409
+ currency: "USD",
410
+ microdollars: "10000000",
411
+ scale: 6,
412
+ },
413
+ expectedRevision: 3,
414
+ triggerBelow: {
415
+ currency: "USD",
416
+ microdollars: "2000000",
417
+ scale: 6,
418
+ },
419
+ },
420
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
421
+ ? API_UNUSED_RESPONSE_SCHEMA
422
+ : billingAutoTopUpPreviewSchema,
423
+ scopes: ["billing:write"],
424
+ sessionAuthority: "headers",
425
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
426
+ ? ""
427
+ : "Preview an automatic top-up rule",
428
+ surfaces: ["api", "mock"],
429
+ };
430
+ const BILLING_AUTO_TOP_UP_APPLY_OPERATION = withBillingFundingContract({
431
+ creates: false,
432
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
433
+ ? ""
434
+ : "Applies the exact unexpired automatic top-up preview a billing owner confirmed. Enable or expanded limits require this explicit approval; edit and disable fence queued unsubmitted work, while submitted or uncertain payments retain their original identity and UTC authorization month. Resume may clear only an authenticated payment-method failure and never an unresolved provider outcome. Applying a rule creates no charge; later low-balance work remains bounded by the approved fixed amount, one outstanding operation, cooldown, usage cap and gross monthly ceiling.",
435
+ environments: ["live"],
436
+ id: "billing.autotopup",
437
+ idempotent: true,
438
+ mcp: { destructive: false, kind: "tool", openWorld: false },
439
+ method: "PATCH",
440
+ mutates: true,
441
+ path: "/v1/billing/funding/auto-top-up",
442
+ principals: ["api-credential", "oauth", "session"],
443
+ problems: [
444
+ "idempotency_key_reused",
445
+ "invalid_request",
446
+ "revision_conflict",
447
+ "service_unavailable",
448
+ "state_conflict",
449
+ "test_to_live_escalation",
450
+ ],
451
+ request: billingAutoTopUpApplyRequestSchema,
452
+ requestExample: globalThis
453
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
454
+ ? {}
455
+ : {
456
+ confirmed: true,
457
+ expectedRevision: 3,
458
+ preview: "automatic-top-up-preview-example",
459
+ },
460
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
461
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
462
+ ? {}
463
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
464
+ scopes: ["billing:write"],
465
+ sessionAuthority: "headers",
466
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
467
+ ? ""
468
+ : "Apply an automatic top-up rule",
469
+ surfaces: ["api", "mock"],
470
+ });
50
471
  export const OPERATIONS = [
472
+ ...DATA_EXPORT_OPERATIONS,
473
+ ...ORGANIZATION_LIFECYCLE_OPERATIONS,
51
474
  {
52
475
  creates: false,
53
- description: "Reports the service, environment, and build the request reached. Unauthenticated: it carries no customer data and is used by canaries and deployment smoke checks.",
54
- example: {
55
- buildSha: "9f2c1ab",
56
- environment: "development",
57
- service: "@greatwait/api",
58
- },
476
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
477
+ ? ""
478
+ : "Reports the service, environment, and build the request reached. Unauthenticated: it carries no customer data and is used by canaries and deployment smoke checks.",
479
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
480
+ ? {}
481
+ : {
482
+ buildSha: "9f2c1ab",
483
+ environment: "development",
484
+ service: "@greatwait/api",
485
+ },
59
486
  id: "meta.version",
60
487
  idempotent: true,
61
488
  // A resource, not a tool. It takes no arguments and reports a fact about
@@ -68,19 +495,27 @@ export const OPERATIONS = [
68
495
  path: "/__greatwait/version",
69
496
  principals: [],
70
497
  problems: [],
71
- response: scaffoldVersionSchema,
498
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
499
+ ? API_UNUSED_RESPONSE_SCHEMA
500
+ : scaffoldVersionSchema,
72
501
  scopes: [],
73
- summary: "Read the deployed version",
502
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
503
+ ? ""
504
+ : "Read the deployed version",
74
505
  surfaces: ["api", "mock"],
75
506
  },
76
507
  {
77
508
  creates: false,
78
- description: "Reports the workspace layer this service occupies and the layers it may depend on. Exists so the architecture boundary is observable at runtime, not only at build time.",
79
- example: {
80
- dependsOn: ["application", "contract", "platform"],
81
- layer: "adapter",
82
- service: "@greatwait/api",
83
- },
509
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
510
+ ? ""
511
+ : "Reports the workspace layer this service occupies and the layers it may depend on. Exists so the architecture boundary is observable at runtime, not only at build time.",
512
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
513
+ ? {}
514
+ : {
515
+ dependsOn: ["application", "contract", "platform"],
516
+ layer: "adapter",
517
+ service: "@greatwait/api",
518
+ },
84
519
  id: "meta.scaffold",
85
520
  idempotent: true,
86
521
  mcp: { kind: "resource", uri: "greatwait://meta/scaffold" },
@@ -89,22 +524,30 @@ export const OPERATIONS = [
89
524
  path: "/_scaffold",
90
525
  principals: [],
91
526
  problems: [],
92
- response: workspaceScaffoldSchema,
527
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
528
+ ? API_UNUSED_RESPONSE_SCHEMA
529
+ : workspaceScaffoldSchema,
93
530
  scopes: [],
94
- summary: "Read the workspace scaffold",
531
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
532
+ ? ""
533
+ : "Read the workspace scaffold",
95
534
  surfaces: ["api", "mock"],
96
535
  },
97
536
  {
98
537
  creates: false,
99
- description: "Lists the committed contract fixtures the mock can serve. Mock-only: the API has no fixtures.",
100
- example: {
101
- fixtures: [
102
- {
103
- description: "The workspace scaffold every service reports.",
104
- id: "workspace-scaffold",
105
- },
106
- ],
107
- },
538
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
539
+ ? ""
540
+ : "Lists the committed contract fixtures the mock can serve. Mock-only: the API has no fixtures.",
541
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
542
+ ? {}
543
+ : {
544
+ fixtures: [
545
+ {
546
+ description: "The workspace scaffold every service reports.",
547
+ id: "workspace-scaffold",
548
+ },
549
+ ],
550
+ },
108
551
  id: "mock.listFixtures",
109
552
  idempotent: true,
110
553
  mcp: {
@@ -116,19 +559,27 @@ export const OPERATIONS = [
116
559
  path: "/_contract/fixtures",
117
560
  principals: [],
118
561
  problems: [],
119
- response: fixtureListSchema,
562
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
563
+ ? API_UNUSED_RESPONSE_SCHEMA
564
+ : fixtureListSchema,
120
565
  scopes: [],
121
- summary: "List contract fixtures",
566
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
567
+ ? ""
568
+ : "List contract fixtures",
122
569
  surfaces: ["mock"],
123
570
  },
124
571
  {
125
572
  creates: false,
126
- description: "Serves one committed fixture, byte-identical on every call. Returns a not_found problem for an unknown identifier.",
127
- example: {
128
- dependsOn: ["application", "contract", "platform"],
129
- layer: "adapter",
130
- service: "@greatwait/contract-mock",
131
- },
573
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
574
+ ? ""
575
+ : "Serves one committed fixture, byte-identical on every call. Returns a not_found problem for an unknown identifier.",
576
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
577
+ ? {}
578
+ : {
579
+ dependsOn: ["application", "contract", "platform"],
580
+ layer: "adapter",
581
+ service: "@greatwait/contract-mock",
582
+ },
132
583
  id: "mock.getFixture",
133
584
  idempotent: true,
134
585
  mcp: {
@@ -140,28 +591,36 @@ export const OPERATIONS = [
140
591
  path: "/_contract/fixtures/{fixtureId}",
141
592
  principals: [],
142
593
  problems: ["not_found"],
143
- response: workspaceScaffoldSchema,
594
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
595
+ ? API_UNUSED_RESPONSE_SCHEMA
596
+ : workspaceScaffoldSchema,
144
597
  scopes: [],
145
- summary: "Read a contract fixture",
598
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
599
+ ? ""
600
+ : "Read a contract fixture",
146
601
  surfaces: ["mock"],
147
602
  },
148
603
  {
149
604
  creates: true,
150
- description: "Creates a reusable callback endpoint in the caller's project and environment. The destination must be HTTPS on effective port 443, contain no URL credentials or fragment, and resolve only to public unicast addresses. The endpoint begins pending. Whether delivery waits for its secret-bound ownership challenge is a deployment policy: where the challenge is not required, which is the default, a pending endpoint is delivered to and answering the challenge only records the instant it proved possession; where it is required, attaching a pending endpoint to a schedule is refused endpoint_unverified until the challenge succeeds. A disabled endpoint is never delivered to under either policy, and a schedule write naming one answers not_found, because disabling is terminal rather than a state to recover from. The per-endpoint secret is returned in this response and nowhere else. The 50-record safety ceiling includes disabled endpoints because they remain readable for audit.",
151
- example: {
152
- createdAt: "2026-08-05T15:00:00.000Z",
153
- environmentKind: "test",
154
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
155
- keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
156
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
157
- secret: "ptsk_test_<the-one-time-endpoint-secret-here>",
158
- shownOnce: true,
159
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
160
- status: "pending",
161
- updatedAt: "2026-08-05T15:00:00.000Z",
162
- url: "https://hooks.example.com/greatwait",
163
- version: 1,
164
- },
605
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
606
+ ? ""
607
+ : "Creates a reusable callback endpoint in the caller's project and environment. The destination must be HTTPS on effective port 443, contain no URL credentials or fragment, and resolve only to public unicast addresses. The endpoint is active and usable the moment it exists; there is nothing to verify. A disabled endpoint is never delivered to, and a schedule write naming one answers not_found, because disabling is terminal rather than a state to recover from. The per-endpoint secret is returned in this response and nowhere else. The 50-record safety ceiling includes disabled endpoints because they remain readable for audit.",
608
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
609
+ ? {}
610
+ : {
611
+ createdAt: "2026-08-05T15:00:00.000Z",
612
+ environmentKind: "test",
613
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
614
+ keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
615
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
616
+ secret: "ptsk_test_<the-one-time-endpoint-secret-here>",
617
+ shownOnce: true,
618
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
619
+ status: "active",
620
+ updatedAt: "2026-08-05T15:00:00.000Z",
621
+ url: "https://hooks.example.com/greatwait",
622
+ version: 1,
623
+ },
165
624
  id: "endpoints.create",
166
625
  idempotent: false,
167
626
  mcp: {
@@ -172,35 +631,50 @@ export const OPERATIONS = [
172
631
  mutates: true,
173
632
  path: "/v1/endpoints",
174
633
  principals: ["api-credential", "oauth", "session"],
175
- problems: ["invalid_request", "plan_limit_reached", "rate_limited"],
634
+ problems: [
635
+ "state_conflict",
636
+ "invalid_request",
637
+ "plan_limit_reached",
638
+ "rate_limited",
639
+ ],
176
640
  request: callbackEndpointRequestSchema,
177
- requestExample: { url: "https://hooks.example.com/greatwait" },
178
- response: callbackEndpointCreatedSchema,
641
+ requestExample: globalThis
642
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
643
+ ? {}
644
+ : { url: "https://hooks.example.com/greatwait" },
645
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
646
+ ? API_UNUSED_RESPONSE_SCHEMA
647
+ : callbackEndpointCreatedSchema,
179
648
  scopes: ["endpoints:write"],
180
649
  sessionAuthority: "headers",
181
- summary: "Create a callback endpoint",
650
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
651
+ ? ""
652
+ : "Create a callback endpoint",
182
653
  surfaces: ["api", "mock"],
183
654
  },
184
655
  {
185
656
  creates: false,
186
- description: "Lists the caller's callback endpoints for exactly its own project and environment. The result is authoritative and metadata-only: no signing secret or sealed key material has a field in this shape.",
187
- example: {
188
- data: [
189
- {
190
- createdAt: "2026-08-05T15:00:00.000Z",
191
- environmentKind: "test",
192
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
193
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
194
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
195
- status: "verified",
196
- updatedAt: "2026-08-05T15:01:00.000Z",
197
- url: "https://hooks.example.com/greatwait",
198
- verifiedAt: "2026-08-05T15:01:00.000Z",
199
- version: 2,
200
- },
201
- ],
202
- freshness: { kind: "authoritative" },
203
- },
657
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
658
+ ? ""
659
+ : "Lists the caller's callback endpoints for exactly its own project and environment. The result is authoritative and metadata-only: no signing secret or sealed key material has a field in this shape.",
660
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
661
+ ? {}
662
+ : {
663
+ data: [
664
+ {
665
+ createdAt: "2026-08-05T15:00:00.000Z",
666
+ environmentKind: "test",
667
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
668
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
669
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
670
+ status: "active",
671
+ updatedAt: "2026-08-05T15:01:00.000Z",
672
+ url: "https://hooks.example.com/greatwait",
673
+ version: 2,
674
+ },
675
+ ],
676
+ freshness: { kind: "authoritative" },
677
+ },
204
678
  id: "endpoints.list",
205
679
  idempotent: true,
206
680
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -210,27 +684,35 @@ export const OPERATIONS = [
210
684
  principals: ["api-credential", "oauth", "session"],
211
685
  problems: ["invalid_request"],
212
686
  query: pageRequestSchema,
213
- response: callbackEndpointPageSchema,
687
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
688
+ ? API_UNUSED_RESPONSE_SCHEMA
689
+ : callbackEndpointPageSchema,
214
690
  scopes: ["endpoints:read"],
215
691
  sessionAuthority: "headers",
216
- summary: "List callback endpoints",
692
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
693
+ ? ""
694
+ : "List callback endpoints",
217
695
  surfaces: ["api", "mock"],
218
696
  },
219
697
  {
220
698
  creates: false,
221
- description: "Reads one callback endpoint from the caller's own project and environment. A well-formed identifier belonging to another authority is indistinguishable from an absent endpoint, and the response never contains secret material.",
222
- example: {
223
- createdAt: "2026-08-05T15:00:00.000Z",
224
- environmentKind: "test",
225
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
226
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
227
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
228
- status: "verified",
229
- updatedAt: "2026-08-05T15:01:00.000Z",
230
- url: "https://hooks.example.com/greatwait",
231
- verifiedAt: "2026-08-05T15:01:00.000Z",
232
- version: 2,
233
- },
699
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
700
+ ? ""
701
+ : "Reads one callback endpoint from the caller's own project and environment. A well-formed identifier belonging to another authority is indistinguishable from an absent endpoint, and the response never contains secret material.",
702
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
703
+ ? {}
704
+ : {
705
+ createdAt: "2026-08-05T15:00:00.000Z",
706
+ environmentKind: "test",
707
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
708
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
709
+ name: "https://hooks.example.com/greatwait",
710
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
711
+ status: "active",
712
+ updatedAt: "2026-08-05T15:01:00.000Z",
713
+ url: "https://hooks.example.com/greatwait",
714
+ version: 2,
715
+ },
234
716
  id: "endpoints.read",
235
717
  idempotent: true,
236
718
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -239,30 +721,40 @@ export const OPERATIONS = [
239
721
  path: "/v1/endpoints/{endpointId}",
240
722
  principals: ["api-credential", "oauth", "session"],
241
723
  problems: ["invalid_request", "not_found"],
242
- response: callbackEndpointSchema,
243
- // The version a conditional update or verification must send back. Published
724
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
725
+ ? API_UNUSED_RESPONSE_SCHEMA
726
+ : callbackEndpointSchema,
727
+ // The version a conditional update must send back. Published
244
728
  // because a caller expected to put a value in `If-Match` needs the operation
245
729
  // that hands it out to say so — the same reason `schedules.read` carries it.
246
- responseHeaders: versionResponseHeaderSchema,
730
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
731
+ ? {}
732
+ : { responseHeaders: versionResponseHeaderSchema }),
247
733
  scopes: ["endpoints:read"],
248
734
  sessionAuthority: "headers",
249
- summary: "Read a callback endpoint",
735
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
736
+ ? ""
737
+ : "Read a callback endpoint",
250
738
  surfaces: ["api", "mock"],
251
739
  },
252
740
  {
253
741
  creates: false,
254
- description: "Replaces an endpoint's destination after applying the complete URL and DNS policy. A changed destination resets verification to pending; the endpoint cannot be used again until ownership of the new URL is proved. Disabled endpoints cannot be updated. Send If-Match with the version the endpoint was read at to be refused rather than overwrite a destination somebody else changed in the meantime.",
255
- example: {
256
- createdAt: "2026-08-05T15:00:00.000Z",
257
- environmentKind: "test",
258
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
259
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
260
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
261
- status: "pending",
262
- updatedAt: "2026-08-05T16:00:00.000Z",
263
- url: "https://hooks.example.com/replacement",
264
- version: 3,
265
- },
742
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
743
+ ? ""
744
+ : "Replaces an endpoint's destination after applying the complete URL and DNS policy, and renames it when a name is given. Deliveries go to the new destination from the next one on. Disabled endpoints cannot be updated. Send If-Match with the version the endpoint was read at to be refused rather than overwrite a destination somebody else changed in the meantime.",
745
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
746
+ ? {}
747
+ : {
748
+ createdAt: "2026-08-05T15:00:00.000Z",
749
+ environmentKind: "test",
750
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
751
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
752
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
753
+ status: "active",
754
+ updatedAt: "2026-08-05T16:00:00.000Z",
755
+ url: "https://hooks.example.com/replacement",
756
+ version: 3,
757
+ },
266
758
  id: "endpoints.update",
267
759
  idempotent: true,
268
760
  mcp: { destructive: true, kind: "tool", openWorld: true },
@@ -278,58 +770,98 @@ export const OPERATIONS = [
278
770
  "version_conflict",
279
771
  ],
280
772
  request: callbackEndpointRequestSchema,
281
- requestExample: { url: "https://hooks.example.com/replacement" },
773
+ requestExample: globalThis
774
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
775
+ ? {}
776
+ : { url: "https://hooks.example.com/replacement" },
282
777
  requestHeaders: conditionalRequestHeaderSchema,
283
- response: callbackEndpointSchema,
284
- responseHeaders: versionResponseHeaderSchema,
778
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
779
+ ? API_UNUSED_RESPONSE_SCHEMA
780
+ : callbackEndpointSchema,
781
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
782
+ ? {}
783
+ : { responseHeaders: versionResponseHeaderSchema }),
285
784
  scopes: ["endpoints:write"],
286
785
  sessionAuthority: "headers",
287
- summary: "Update a callback endpoint",
786
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
787
+ ? ""
788
+ : "Update a callback endpoint",
288
789
  surfaces: ["api", "mock"],
289
790
  },
290
791
  {
291
- creates: false,
292
- description: "Re-resolves the endpoint immediately before sending one bounded ownership challenge with redirects disabled. The receiver proves possession of the one-time endpoint secret in its response. A successful challenge marks the endpoint verified; a failed challenge records only a safe failure category. Send If-Match with the version the endpoint was read at to be refused rather than challenge a destination somebody else has since changed.",
293
- example: {
294
- createdAt: "2026-08-05T15:00:00.000Z",
295
- environmentKind: "test",
296
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
297
- lastVerificationAttemptAt: "2026-08-05T15:01:00.000Z",
298
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
299
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
300
- status: "verified",
301
- updatedAt: "2026-08-05T15:01:00.000Z",
302
- url: "https://hooks.example.com/greatwait",
303
- verifiedAt: "2026-08-05T15:01:00.000Z",
304
- version: 2,
305
- },
306
- id: "endpoints.verify",
792
+ creates: true,
793
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
794
+ ? ""
795
+ : "Creates the next endpoint signing key and selects it immediately for new deliveries while retaining the current key in the receiver acceptance set for a bounded overlap. The overlap defaults to and cannot exceed 24 hours. A second rotation is refused until the current overlap ends. The new secret is returned once and has no recovery operation, so a call whose answer was never read may have rotated a key nobody holds: read the endpoint and compare its signing keys before repeating one. Send If-Match with the version the endpoint was read at to be refused rather than rotate an endpoint that has changed since.",
796
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
797
+ ? {}
798
+ : {
799
+ endpoint: {
800
+ createdAt: "2026-08-05T15:00:00.000Z",
801
+ environmentKind: "test",
802
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
803
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
804
+ signingKeys: {
805
+ current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
806
+ next: {
807
+ id: "csk_11h8xyz9k2m4n6p8r0t2v4w6y8",
808
+ overlapEndsAt: "2026-08-06T15:05:00.000Z",
809
+ },
810
+ },
811
+ status: "active",
812
+ updatedAt: "2026-08-05T15:05:00.000Z",
813
+ url: "https://hooks.example.com/greatwait",
814
+ version: 3,
815
+ },
816
+ keyId: "csk_11h8xyz9k2m4n6p8r0t2v4w6y8",
817
+ secret: "ptsk_test_<the-next-one-time-endpoint-secret-here>",
818
+ shownOnce: true,
819
+ },
820
+ id: "endpoints.rotateSigningKey",
307
821
  idempotent: false,
308
- mcp: { destructive: false, kind: "tool", openWorld: true },
822
+ mcp: {
823
+ kind: "unavailable",
824
+ reason: "Rotation returns a one-time endpoint signing secret, and MCP has no negotiated secure-result channel that can keep it out of ordinary tool history.",
825
+ },
309
826
  method: "POST",
310
827
  mutates: true,
311
- path: "/v1/endpoints/{endpointId}/verify",
828
+ path: "/v1/endpoints/{endpointId}/signing-keys/rotate",
312
829
  principals: ["api-credential", "oauth", "session"],
313
830
  problems: [
314
831
  "invalid_request",
315
832
  "not_found",
316
- "rate_limited",
317
833
  "state_conflict",
318
834
  "version_conflict",
319
835
  ],
836
+ request: callbackSigningKeyRotationRequestSchema,
837
+ requestExample: globalThis
838
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
839
+ ? {}
840
+ : { overlapSeconds: 3600 },
320
841
  requestHeaders: conditionalRequestHeaderSchema,
321
- response: callbackEndpointSchema,
322
- responseHeaders: versionResponseHeaderSchema,
842
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
843
+ ? API_UNUSED_RESPONSE_SCHEMA
844
+ : callbackEndpointRotatedSchema,
845
+ // The endpoint's version after the rotation, so the next conditional write
846
+ // from the same page has something to send.
847
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
848
+ ? {}
849
+ : { responseHeaders: versionResponseHeaderSchema }),
323
850
  scopes: ["endpoints:write"],
324
851
  sessionAuthority: "headers",
325
- summary: "Verify callback endpoint ownership",
852
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
853
+ ? ""
854
+ : "Rotate a callback endpoint signing key",
326
855
  surfaces: ["api", "mock"],
327
856
  },
328
857
  {
329
- creates: true,
330
- description: "Creates the next endpoint signing key and selects it immediately for new deliveries while retaining the current key in the receiver acceptance set for a bounded overlap. The overlap defaults to and cannot exceed 24 hours. A second rotation is refused until the current overlap ends. The new secret is returned once and has no recovery operation, so a call whose answer was never read may have rotated a key nobody holds: read the endpoint and compare its signing keys before repeating one. Send If-Match with the version the endpoint was read at to be refused rather than rotate an endpoint that has changed since.",
331
- example: {
332
- endpoint: {
858
+ creates: false,
859
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
860
+ ? ""
861
+ : "Records that a person has updated their server to accept the next signing key during the active overlap. This only marks the reminder done: it does not retire either key, shorten the overlap, or change which key signs new deliveries. Send If-Match with the version the endpoint was read at so an acknowledgement cannot be applied to a different rotation.",
862
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
863
+ ? {}
864
+ : {
333
865
  createdAt: "2026-08-05T15:00:00.000Z",
334
866
  environmentKind: "test",
335
867
  id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
@@ -337,29 +869,25 @@ export const OPERATIONS = [
337
869
  signingKeys: {
338
870
  current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
339
871
  next: {
872
+ acknowledgedAt: "2026-08-05T15:10:00.000Z",
340
873
  id: "csk_11h8xyz9k2m4n6p8r0t2v4w6y8",
341
874
  overlapEndsAt: "2026-08-06T15:05:00.000Z",
342
875
  },
343
876
  },
344
- status: "verified",
345
- updatedAt: "2026-08-05T15:05:00.000Z",
877
+ status: "active",
878
+ updatedAt: "2026-08-05T15:10:00.000Z",
346
879
  url: "https://hooks.example.com/greatwait",
347
- verifiedAt: "2026-08-05T15:01:00.000Z",
348
- version: 3,
880
+ version: 4,
349
881
  },
350
- keyId: "csk_11h8xyz9k2m4n6p8r0t2v4w6y8",
351
- secret: "ptsk_test_<the-next-one-time-endpoint-secret-here>",
352
- shownOnce: true,
353
- },
354
- id: "endpoints.rotateSigningKey",
355
- idempotent: false,
882
+ id: "endpoints.acknowledgeSigningKeyRotation",
883
+ idempotent: true,
356
884
  mcp: {
357
885
  kind: "unavailable",
358
- reason: "Rotation returns a one-time endpoint signing secret, and MCP has no negotiated secure-result channel that can keep it out of ordinary tool history.",
886
+ reason: "This is a human assertion about a server outside GreatWait; an agent cannot observe that the server has accepted the new secret.",
359
887
  },
360
888
  method: "POST",
361
889
  mutates: true,
362
- path: "/v1/endpoints/{endpointId}/signing-keys/rotate",
890
+ path: "/v1/endpoints/{endpointId}/signing-keys/acknowledge",
363
891
  principals: ["api-credential", "oauth", "session"],
364
892
  problems: [
365
893
  "invalid_request",
@@ -367,34 +895,83 @@ export const OPERATIONS = [
367
895
  "state_conflict",
368
896
  "version_conflict",
369
897
  ],
370
- request: callbackSigningKeyRotationRequestSchema,
371
- requestExample: { overlapSeconds: 3600 },
372
- requestHeaders: conditionalRequestHeaderSchema,
373
- response: callbackEndpointRotatedSchema,
374
- // The endpoint's version after the rotation, so the next conditional write
375
- // from the same page has something to send.
376
- responseHeaders: versionResponseHeaderSchema,
898
+ requestHeaders: requiredConditionalRequestHeaderSchema,
899
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
900
+ ? API_UNUSED_RESPONSE_SCHEMA
901
+ : callbackEndpointSchema,
902
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
903
+ ? {}
904
+ : { responseHeaders: versionResponseHeaderSchema }),
377
905
  scopes: ["endpoints:write"],
378
906
  sessionAuthority: "headers",
379
- summary: "Rotate a callback endpoint signing key",
907
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
908
+ ? ""
909
+ : "Mark a signing-key server update done",
380
910
  surfaces: ["api", "mock"],
381
911
  },
382
912
  {
383
913
  creates: false,
384
- description: "Disables an endpoint immediately and permanently: there is no operation that re-enables one. It stays readable for audit but is no longer eligible for update, verification or callback send admission, and schedules pointed at it deliver nothing. Repeating the disable is idempotent and does not write a second audit event, which is why it takes no precondition — the outcome does not depend on what else has changed.",
385
- example: {
386
- createdAt: "2026-08-05T15:00:00.000Z",
387
- disabledAt: "2026-08-05T17:00:00.000Z",
388
- environmentKind: "test",
389
- id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
390
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
391
- signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
392
- status: "disabled",
393
- updatedAt: "2026-08-05T17:00:00.000Z",
394
- url: "https://hooks.example.com/greatwait",
395
- verifiedAt: "2026-08-05T15:01:00.000Z",
396
- version: 3,
914
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
915
+ ? ""
916
+ : "Reveals an endpoint's signing secret to a signed-in member: the value `endpoints.create` and `endpoints.rotateSigningKey` hand out once, readable again from the endpoint's own page. During a rotation both keys are returned, with the instant the overlap ends. Only a member session is accepted; an API credential or an OAuth token is refused, so an integration that needs the secret keeps the one the create or rotation that minted it returned. A disabled endpoint has nothing to reveal.",
917
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
918
+ ? {}
919
+ : {
920
+ current: {
921
+ keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
922
+ secret: "ptsk_test_<the-current-endpoint-secret-here>",
923
+ },
924
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
925
+ },
926
+ id: "endpoints.revealSigningSecret",
927
+ idempotent: true,
928
+ // The same reason `endpoints.rotateSigningKey` gives, and one more: the
929
+ // route accepts only a signed-in member, and MCP never carries a session.
930
+ // The operator chose reveal-later for people (FXO-2244) and no new
931
+ // machine-callable read; an agent that needs the secret scripts the
932
+ // create or rotation, which keeps it out of tool history by construction.
933
+ mcp: {
934
+ kind: "unavailable",
935
+ reason: "The response is an endpoint signing secret, which MCP has no secure-result channel for — and the route accepts only a signed-in member, which MCP never carries.",
397
936
  },
937
+ method: "GET",
938
+ mutates: false,
939
+ path: "/v1/endpoints/{endpointId}/signing-secret",
940
+ principals: ["session"],
941
+ problems: ["invalid_request", "not_found", "state_conflict"],
942
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
943
+ ? API_UNUSED_RESPONSE_SCHEMA
944
+ : callbackEndpointSigningSecretsSchema,
945
+ // `endpoints:write`, not `endpoints:read`, though nothing is written: it is
946
+ // the standing the two operations that already hand this value out
947
+ // require, and a session that may not rotate the key should not be able
948
+ // to read it either.
949
+ scopes: ["endpoints:write"],
950
+ sessionAuthority: "headers",
951
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
952
+ ? ""
953
+ : "Reveal a callback endpoint signing secret",
954
+ surfaces: ["api", "mock"],
955
+ },
956
+ {
957
+ creates: false,
958
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
959
+ ? ""
960
+ : "Disables an endpoint immediately. It stays readable for audit but can no longer be updated or delivered to, and schedules pointed at it deliver nothing until `endpoints.enable` turns it back on. Repeating the disable is idempotent and does not write a second audit event, which is why it takes no precondition — the outcome does not depend on what else has changed.",
961
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
962
+ ? {}
963
+ : {
964
+ createdAt: "2026-08-05T15:00:00.000Z",
965
+ disabledAt: "2026-08-05T17:00:00.000Z",
966
+ environmentKind: "test",
967
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
968
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
969
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
970
+ status: "disabled",
971
+ updatedAt: "2026-08-05T17:00:00.000Z",
972
+ url: "https://hooks.example.com/greatwait",
973
+ version: 3,
974
+ },
398
975
  id: "endpoints.disable",
399
976
  idempotent: true,
400
977
  mcp: { destructive: true, kind: "tool", openWorld: false },
@@ -403,27 +980,81 @@ export const OPERATIONS = [
403
980
  path: "/v1/endpoints/{endpointId}",
404
981
  principals: ["api-credential", "oauth", "session"],
405
982
  problems: ["invalid_request", "not_found"],
406
- response: callbackEndpointSchema,
407
- responseHeaders: versionResponseHeaderSchema,
983
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
984
+ ? API_UNUSED_RESPONSE_SCHEMA
985
+ : callbackEndpointSchema,
986
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
987
+ ? {}
988
+ : { responseHeaders: versionResponseHeaderSchema }),
989
+ scopes: ["endpoints:write"],
990
+ sessionAuthority: "headers",
991
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
992
+ ? ""
993
+ : "Disable a callback endpoint",
994
+ surfaces: ["api", "mock"],
995
+ },
996
+ {
997
+ creates: false,
998
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
999
+ ? ""
1000
+ : "Enables an endpoint that was disabled, so schedules pointed at it deliver again from the next occurrence on. Its address, name, signing keys and history are exactly as they were; nothing has to be created or re-pointed. Repeating the enable is idempotent and does not write a second audit event, so like `endpoints.disable` it takes no precondition. Somebody who disabled an endpoint by mistake, with many schedules pointed at it, gets it back with one call.",
1001
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1002
+ ? {}
1003
+ : {
1004
+ createdAt: "2026-08-05T15:00:00.000Z",
1005
+ environmentKind: "test",
1006
+ id: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1007
+ name: "https://hooks.example.com/greatwait",
1008
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1009
+ signingKeys: { current: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
1010
+ status: "active",
1011
+ updatedAt: "2026-08-05T18:00:00.000Z",
1012
+ url: "https://hooks.example.com/greatwait",
1013
+ version: 4,
1014
+ },
1015
+ id: "endpoints.enable",
1016
+ idempotent: true,
1017
+ mcp: { destructive: false, kind: "tool", openWorld: false },
1018
+ method: "POST",
1019
+ mutates: true,
1020
+ path: "/v1/endpoints/{endpointId}/enable",
1021
+ principals: ["api-credential", "oauth", "session"],
1022
+ // `state_conflict` when another endpoint took this one's name while it
1023
+ // was off: names are unique among live endpoints, and enabling would make
1024
+ // two.
1025
+ problems: ["invalid_request", "not_found", "state_conflict"],
1026
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1027
+ ? API_UNUSED_RESPONSE_SCHEMA
1028
+ : callbackEndpointSchema,
1029
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
1030
+ ? {}
1031
+ : { responseHeaders: versionResponseHeaderSchema }),
408
1032
  scopes: ["endpoints:write"],
409
1033
  sessionAuthority: "headers",
410
- summary: "Disable a callback endpoint",
1034
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1035
+ ? ""
1036
+ : "Enable a disabled callback endpoint",
411
1037
  surfaces: ["api", "mock"],
412
1038
  },
413
1039
  {
414
1040
  creates: true,
415
- description: "Creates a deterministic receiver for one callback endpoint so failures can be rehearsed before they happen in production. Test environments only: a live principal has no such operation, and there is no request field that could widen the organization, project, or environment the sink belongs to. The sink verifies deliveries with the bound endpoint's own signing keys, so key rotation and a wrong key behave here exactly as they would at the customer's receiver. It receives and never sends: no field names a destination and no configuration makes it forward a delivery. Point the endpoint at the returned url and verify it, and every attempt lands here.",
416
- example: {
417
- createdAt: "2026-08-07T15:00:00.000Z",
418
- deliveryCount: 0,
419
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
420
- environmentKind: "test",
421
- id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
422
- program: { behavior: "success" },
423
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
424
- updatedAt: "2026-08-07T15:00:00.000Z",
425
- url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
426
- },
1041
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1042
+ ? ""
1043
+ : "Creates a deterministic receiver for one callback endpoint so failures can be rehearsed before they happen in production. Test environments only: a live principal has no such operation, and there is no request field that could widen the organization, project, or environment the sink belongs to. The sink verifies deliveries with the bound endpoint's own signing keys, so key rotation and a wrong key behave here exactly as they would at the customer's receiver. It receives and never sends: no field names a destination and no configuration makes it forward a delivery. Point the endpoint at the returned url, and every attempt lands here.",
1044
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1045
+ ? {}
1046
+ : {
1047
+ createdAt: "2026-08-07T15:00:00.000Z",
1048
+ deliveryCount: 0,
1049
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1050
+ environmentKind: "test",
1051
+ id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1052
+ program: { behavior: "success" },
1053
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1054
+ updatedAt: "2026-08-07T15:00:00.000Z",
1055
+ url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1056
+ },
1057
+ environments: ["test"],
427
1058
  id: "testsinks.create",
428
1059
  idempotent: false,
429
1060
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -446,35 +1077,51 @@ export const OPERATIONS = [
446
1077
  "state_conflict",
447
1078
  ],
448
1079
  request: testSinkCreateRequestSchema,
449
- requestExample: {
450
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
451
- program: { behavior: "server_error", forDeliveries: 2, then: "success" },
452
- },
453
- response: testSinkSchema,
1080
+ requestExample: globalThis
1081
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1082
+ ? {}
1083
+ : {
1084
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1085
+ program: {
1086
+ behavior: "server_error",
1087
+ forDeliveries: 2,
1088
+ then: "success",
1089
+ },
1090
+ },
1091
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1092
+ ? API_UNUSED_RESPONSE_SCHEMA
1093
+ : testSinkSchema,
454
1094
  scopes: ["endpoints:write"],
455
1095
  sessionAuthority: "headers",
456
- summary: "Create a test sink",
1096
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1097
+ ? ""
1098
+ : "Create a test sink",
457
1099
  surfaces: ["api", "mock"],
458
1100
  },
459
1101
  {
460
1102
  creates: false,
461
- description: "Lists the caller's test sinks for exactly its own project and test environment. A live principal receives an empty-handed refusal rather than another environment's sinks.",
462
- example: {
463
- data: [
464
- {
465
- createdAt: "2026-08-07T15:00:00.000Z",
466
- deliveryCount: 3,
467
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
468
- environmentKind: "test",
469
- id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
470
- program: { behavior: "success" },
471
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
472
- updatedAt: "2026-08-07T15:02:00.000Z",
473
- url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
474
- },
475
- ],
476
- freshness: { kind: "authoritative" },
477
- },
1103
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1104
+ ? ""
1105
+ : "Lists the caller's test sinks for exactly its own project and test environment. A live principal receives an empty-handed refusal rather than another environment's sinks.",
1106
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1107
+ ? {}
1108
+ : {
1109
+ data: [
1110
+ {
1111
+ createdAt: "2026-08-07T15:00:00.000Z",
1112
+ deliveryCount: 3,
1113
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1114
+ environmentKind: "test",
1115
+ id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1116
+ program: { behavior: "success" },
1117
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1118
+ updatedAt: "2026-08-07T15:02:00.000Z",
1119
+ url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1120
+ },
1121
+ ],
1122
+ freshness: { kind: "authoritative" },
1123
+ },
1124
+ environments: ["test"],
478
1125
  id: "testsinks.list",
479
1126
  idempotent: true,
480
1127
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -484,26 +1131,35 @@ export const OPERATIONS = [
484
1131
  principals: ["api-credential", "oauth", "session"],
485
1132
  problems: ["invalid_request", "state_conflict"],
486
1133
  query: pageRequestSchema,
487
- response: testSinkPageSchema,
1134
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1135
+ ? API_UNUSED_RESPONSE_SCHEMA
1136
+ : testSinkPageSchema,
488
1137
  scopes: ["endpoints:read"],
489
1138
  sessionAuthority: "headers",
490
- summary: "List test sinks",
1139
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1140
+ ? ""
1141
+ : "List test sinks",
491
1142
  surfaces: ["api", "mock"],
492
1143
  },
493
1144
  {
494
1145
  creates: false,
495
- description: "Reads one test sink from the caller's own project and test environment, including how many deliveries it has taken. A well-formed identifier belonging to another authority is indistinguishable from an absent sink.",
496
- example: {
497
- createdAt: "2026-08-07T15:00:00.000Z",
498
- deliveryCount: 3,
499
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
500
- environmentKind: "test",
501
- id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
502
- program: { behavior: "rate_limited", retryAfterSeconds: 5 },
503
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
504
- updatedAt: "2026-08-07T15:02:00.000Z",
505
- url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
506
- },
1146
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1147
+ ? ""
1148
+ : "Reads one test sink from the caller's own project and test environment, including how many deliveries it has taken. A well-formed identifier belonging to another authority is indistinguishable from an absent sink.",
1149
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1150
+ ? {}
1151
+ : {
1152
+ createdAt: "2026-08-07T15:00:00.000Z",
1153
+ deliveryCount: 3,
1154
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1155
+ environmentKind: "test",
1156
+ id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1157
+ program: { behavior: "rate_limited", retryAfterSeconds: 5 },
1158
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1159
+ updatedAt: "2026-08-07T15:02:00.000Z",
1160
+ url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1161
+ },
1162
+ environments: ["test"],
507
1163
  id: "testsinks.read",
508
1164
  idempotent: true,
509
1165
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -512,26 +1168,35 @@ export const OPERATIONS = [
512
1168
  path: "/v1/test-sinks/{sinkId}",
513
1169
  principals: ["api-credential", "oauth", "session"],
514
1170
  problems: ["invalid_request", "not_found", "state_conflict"],
515
- response: testSinkSchema,
1171
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1172
+ ? API_UNUSED_RESPONSE_SCHEMA
1173
+ : testSinkSchema,
516
1174
  scopes: ["endpoints:read"],
517
1175
  sessionAuthority: "headers",
518
- summary: "Read a test sink",
1176
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1177
+ ? ""
1178
+ : "Read a test sink",
519
1179
  surfaces: ["api", "mock"],
520
1180
  },
521
1181
  {
522
1182
  creates: false,
523
- description: "Replaces a sink's behavior program. The program is resolved against the number of deliveries the sink has already taken, so `forDeliveries` counts from the next delivery rather than from the sink's creation. Repeating the identical program is idempotent and changes nothing an integrator can observe.",
524
- example: {
525
- createdAt: "2026-08-07T15:00:00.000Z",
526
- deliveryCount: 3,
527
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
528
- environmentKind: "test",
529
- id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
530
- program: { behavior: "timeout" },
531
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
532
- updatedAt: "2026-08-07T15:03:00.000Z",
533
- url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
534
- },
1183
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1184
+ ? ""
1185
+ : "Replaces a sink's behavior program. The program is resolved against the number of deliveries the sink has already taken, so `forDeliveries` counts from the next delivery rather than from the sink's creation. Repeating the identical program is idempotent and changes nothing an integrator can observe.",
1186
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1187
+ ? {}
1188
+ : {
1189
+ createdAt: "2026-08-07T15:00:00.000Z",
1190
+ deliveryCount: 3,
1191
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1192
+ environmentKind: "test",
1193
+ id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1194
+ program: { behavior: "timeout" },
1195
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1196
+ updatedAt: "2026-08-07T15:03:00.000Z",
1197
+ url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1198
+ },
1199
+ environments: ["test"],
535
1200
  id: "testsinks.configure",
536
1201
  idempotent: true,
537
1202
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -541,33 +1206,45 @@ export const OPERATIONS = [
541
1206
  principals: ["api-credential", "oauth", "session"],
542
1207
  problems: ["invalid_request", "not_found", "state_conflict"],
543
1208
  request: testSinkProgramSchema,
544
- requestExample: { behavior: "timeout" },
545
- response: testSinkSchema,
1209
+ requestExample: globalThis
1210
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1211
+ ? {}
1212
+ : { behavior: "timeout" },
1213
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1214
+ ? API_UNUSED_RESPONSE_SCHEMA
1215
+ : testSinkSchema,
546
1216
  scopes: ["endpoints:write"],
547
1217
  sessionAuthority: "headers",
548
- summary: "Set a test sink behavior program",
1218
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1219
+ ? ""
1220
+ : "Set a test sink behavior program",
549
1221
  surfaces: ["api", "mock"],
550
1222
  },
551
1223
  {
552
1224
  creates: false,
553
- description: "Lists what the sink received, most recent first with the record identifier breaking a tie, bounded by the retained-delivery ceiling. Metadata only: the identifiers, the signing key that authenticated the delivery, how the receiver disposed of it, and what it answered. The delivered body is not in this shape.",
554
- example: {
555
- data: [
556
- {
557
- behavior: "success",
558
- delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
559
- disposition: "processed",
560
- id: "tsd_01h8xyz9k2m4n6p8r0t2v4w6y8",
561
- keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
562
- occurrenceId: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
563
- receivedAt: "2026-08-07T15:02:00.000Z",
564
- respondedWith: 200,
565
- scheduleId: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
566
- sink: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
567
- },
568
- ],
569
- freshness: { kind: "authoritative" },
570
- },
1225
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1226
+ ? ""
1227
+ : "Lists what the sink received, most recent first with the record identifier breaking a tie, bounded by the retained-delivery ceiling. Metadata only: the identifiers, the signing key that authenticated the delivery, how the receiver disposed of it, and what it answered. The delivered body is not in this shape.",
1228
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1229
+ ? {}
1230
+ : {
1231
+ data: [
1232
+ {
1233
+ behavior: "success",
1234
+ delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
1235
+ disposition: "processed",
1236
+ id: "tsd_01h8xyz9k2m4n6p8r0t2v4w6y8",
1237
+ keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1238
+ occurrenceId: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1239
+ receivedAt: "2026-08-07T15:02:00.000Z",
1240
+ respondedWith: 200,
1241
+ scheduleId: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1242
+ sink: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1243
+ },
1244
+ ],
1245
+ freshness: { kind: "authoritative" },
1246
+ },
1247
+ environments: ["test"],
571
1248
  id: "sinkdeliveries.list",
572
1249
  idempotent: true,
573
1250
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -577,31 +1254,40 @@ export const OPERATIONS = [
577
1254
  principals: ["api-credential", "oauth", "session"],
578
1255
  problems: ["invalid_request", "not_found", "state_conflict"],
579
1256
  query: pageRequestSchema,
580
- response: testSinkDeliveryPageSchema,
1257
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1258
+ ? API_UNUSED_RESPONSE_SCHEMA
1259
+ : testSinkDeliveryPageSchema,
581
1260
  scopes: ["endpoints:read"],
582
1261
  sessionAuthority: "headers",
583
- summary: "List test sink deliveries",
1262
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1263
+ ? ""
1264
+ : "List test sink deliveries",
584
1265
  surfaces: ["api", "mock"],
585
1266
  },
586
1267
  {
587
1268
  creates: false,
588
- description: "Reads one recorded delivery including the exact bytes that arrived, truncated at the published cap with the original length stated. This is the one place a callback body is readable, and it is narrow on purpose: a test environment only, the creating authority only, a single record rather than a listing, and never a log. The signature is included because a MAC is not secret and comparing it against a locally computed one is how a body-mutation bug is found; no signing key appears in this shape.",
589
- example: {
590
- behavior: "success",
591
- body: '{"version":"2026-08-08","type":"schedule.occurrence","scheduleId":"sch_01h8xyz9k2m4n6p8r0t2v4w6y8","occurrenceId":"occ_01h8xyz9k2m4n6p8r0t2v4w6y8","plannedFor":"2026-08-07T15:00:00.000Z","attempt":1,"trigger":{"kind":"automatic"},"data":{}}',
592
- bodyTruncated: false,
593
- delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
594
- disposition: "processed",
595
- id: "tsd_01h8xyz9k2m4n6p8r0t2v4w6y8",
596
- keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
597
- occurrenceId: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
598
- receivedAt: "2026-08-07T15:02:00.000Z",
599
- receivedBytes: 240,
600
- respondedWith: 200,
601
- scheduleId: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
602
- signature: "v1=11135fdfc0bc5d49ebcc9d3a0d8df1116179097cefe961c6eca281339e5cfab3",
603
- sink: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
604
- },
1269
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1270
+ ? ""
1271
+ : "Reads one recorded delivery including the exact bytes that arrived, truncated at the published cap with the original length stated. This is the one place a callback body is readable, and it is narrow on purpose: a test environment only, the creating authority only, a single record rather than a listing, and never a log. The signature is included because a MAC is not secret and comparing it against a locally computed one is how a body-mutation bug is found; no signing key appears in this shape.",
1272
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1273
+ ? {}
1274
+ : {
1275
+ behavior: "success",
1276
+ body: '{"version":"2026-08-08","type":"schedule.occurrence","scheduleId":"sch_01h8xyz9k2m4n6p8r0t2v4w6y8","occurrenceId":"occ_01h8xyz9k2m4n6p8r0t2v4w6y8","plannedFor":"2026-08-07T15:00:00.000Z","attempt":1,"trigger":{"kind":"automatic"},"data":{}}',
1277
+ bodyTruncated: false,
1278
+ delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
1279
+ disposition: "processed",
1280
+ id: "tsd_01h8xyz9k2m4n6p8r0t2v4w6y8",
1281
+ keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1282
+ occurrenceId: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1283
+ receivedAt: "2026-08-07T15:02:00.000Z",
1284
+ receivedBytes: 240,
1285
+ respondedWith: 200,
1286
+ scheduleId: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1287
+ signature: "v1=11135fdfc0bc5d49ebcc9d3a0d8df1116179097cefe961c6eca281339e5cfab3",
1288
+ sink: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1289
+ },
1290
+ environments: ["test"],
605
1291
  id: "sinkdeliveries.read",
606
1292
  idempotent: true,
607
1293
  mcp: {
@@ -613,26 +1299,35 @@ export const OPERATIONS = [
613
1299
  path: "/v1/test-sinks/{sinkId}/deliveries/{deliveryRecordId}",
614
1300
  principals: ["api-credential", "oauth", "session"],
615
1301
  problems: ["invalid_request", "not_found", "state_conflict"],
616
- response: testSinkDeliveryBodySchema,
1302
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1303
+ ? API_UNUSED_RESPONSE_SCHEMA
1304
+ : testSinkDeliveryBodySchema,
617
1305
  scopes: ["endpoints:read"],
618
1306
  sessionAuthority: "headers",
619
- summary: "Read a test sink delivery",
1307
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1308
+ ? ""
1309
+ : "Read a test sink delivery",
620
1310
  surfaces: ["api", "mock"],
621
1311
  },
622
1312
  {
623
1313
  creates: false,
624
- description: "Deletes a sink and every delivery it recorded. The bound callback endpoint is untouched and keeps its signing keys; deliveries sent afterwards find nothing at the url and fail the way an unreachable receiver does.",
625
- example: {
626
- createdAt: "2026-08-07T15:00:00.000Z",
627
- deliveryCount: 3,
628
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
629
- environmentKind: "test",
630
- id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
631
- program: { behavior: "success" },
632
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
633
- updatedAt: "2026-08-07T15:04:00.000Z",
634
- url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
635
- },
1314
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1315
+ ? ""
1316
+ : "Deletes a sink and every delivery it recorded. The bound callback endpoint is untouched and keeps its signing keys; deliveries sent afterwards find nothing at the url and fail the way an unreachable receiver does.",
1317
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1318
+ ? {}
1319
+ : {
1320
+ createdAt: "2026-08-07T15:00:00.000Z",
1321
+ deliveryCount: 3,
1322
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1323
+ environmentKind: "test",
1324
+ id: "tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1325
+ program: { behavior: "success" },
1326
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1327
+ updatedAt: "2026-08-07T15:04:00.000Z",
1328
+ url: "https://sink.greatwait.dev/__greatwait/test-sinks/tsk_01h8xyz9k2m4n6p8r0t2v4w6y8",
1329
+ },
1330
+ environments: ["test"],
636
1331
  id: "testsinks.delete",
637
1332
  idempotent: true,
638
1333
  mcp: { destructive: true, kind: "tool", openWorld: false },
@@ -641,20 +1336,28 @@ export const OPERATIONS = [
641
1336
  path: "/v1/test-sinks/{sinkId}",
642
1337
  principals: ["api-credential", "oauth", "session"],
643
1338
  problems: ["invalid_request", "not_found", "state_conflict"],
644
- response: testSinkSchema,
1339
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1340
+ ? API_UNUSED_RESPONSE_SCHEMA
1341
+ : testSinkSchema,
645
1342
  scopes: ["endpoints:write"],
646
1343
  sessionAuthority: "headers",
647
- summary: "Delete a test sink",
1344
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1345
+ ? ""
1346
+ : "Delete a test sink",
648
1347
  surfaces: ["api", "mock"],
649
1348
  },
650
1349
  {
651
1350
  creates: true,
652
- description: "Pins the mock's behavior and clock so an integrator can rehearse success, refusal, retry, timeout, ambiguity, and redelivery deterministically. Mock-only, and never evidence that the real runtime behaves this way.",
653
- example: {
654
- behavior: "retry",
655
- now: "2026-01-01T00:00:00.000Z",
656
- scenarioId: "scenario-1",
657
- },
1351
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1352
+ ? ""
1353
+ : "Pins the mock's behavior and clock so an integrator can rehearse success, refusal, retry, timeout, ambiguity, and redelivery deterministically. Mock-only, and never evidence that the real runtime behaves this way.",
1354
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1355
+ ? {}
1356
+ : {
1357
+ behavior: "retry",
1358
+ now: "2026-01-01T00:00:00.000Z",
1359
+ scenarioId: "scenario-1",
1360
+ },
658
1361
  id: "mock.setScenario",
659
1362
  idempotent: false,
660
1363
  mcp: {
@@ -667,25 +1370,78 @@ export const OPERATIONS = [
667
1370
  principals: [],
668
1371
  problems: ["invalid_request"],
669
1372
  request: mockScenarioRequestSchema,
670
- requestExample: { behavior: "retry", failuresBeforeSuccess: 2 },
671
- response: mockScenarioResponseSchema,
1373
+ requestExample: globalThis
1374
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1375
+ ? {}
1376
+ : { behavior: "retry", failuresBeforeSuccess: 2 },
1377
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1378
+ ? API_UNUSED_RESPONSE_SCHEMA
1379
+ : mockScenarioResponseSchema,
672
1380
  scopes: [],
673
- summary: "Set the mock scenario",
1381
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1382
+ ? ""
1383
+ : "Set the mock scenario",
674
1384
  surfaces: ["mock"],
675
1385
  },
1386
+ {
1387
+ creates: false,
1388
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1389
+ ? ""
1390
+ : "Reports the authority the presented credential carries: the project it acts in, which of that project's two environments, and the scopes the service will enforce for it. The answer comes entirely from the verified principal, so there is no parameter that could name another project and no way for the reply to describe anything but the caller itself. It requires a principal and no scope, because every value in it is a property of the credential being presented rather than of anything the credential may reach: a caller that could not read this could still act, and would simply be acting without being able to say where. A signed-in member is not accepted — a session's authority is an organization and it names its project per request, so there is no single answer to give one.",
1391
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1392
+ ? {}
1393
+ : {
1394
+ environmentKind: "test",
1395
+ principal: "api-credential",
1396
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1397
+ scopes: ["schedules:read", "schedules:write"],
1398
+ },
1399
+ id: "context.read",
1400
+ idempotent: true,
1401
+ // A resource rather than a tool: it takes no arguments, it reports a fact
1402
+ // about the caller, and an agent choosing between tools should not have to
1403
+ // step past "what am I" to find the operations that schedule anything.
1404
+ // Being scopeless is what makes a resource legal here — `check:mcp-parity`
1405
+ // refuses a resource that requires one, because a resource carries no
1406
+ // scope declaration for a host to gate on.
1407
+ mcp: { kind: "resource", uri: "greatwait://context" },
1408
+ method: "GET",
1409
+ mutates: false,
1410
+ path: "/v1/context",
1411
+ principals: ["api-credential", "oauth"],
1412
+ // No `not_found`: the authority tuple exists by the time a principal is
1413
+ // verified, so there is nothing here that can be absent.
1414
+ problems: [],
1415
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1416
+ ? API_UNUSED_RESPONSE_SCHEMA
1417
+ : credentialContextSchema,
1418
+ // **Empty, and that is the point of the operation.** Every other
1419
+ // authenticated operation names the scope it consumes; this one consumes
1420
+ // none, so `scope_missing` is a refusal it can never produce and
1421
+ // `problemsFor` does not publish one for it.
1422
+ scopes: [],
1423
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1424
+ ? ""
1425
+ : "Read this credential's authority",
1426
+ surfaces: ["api", "mock"],
1427
+ },
676
1428
  {
677
1429
  creates: true,
678
- description: "Issues an API credential bound to one project and environment, with scopes capped by the issuing member's current role. The full secret is in this response and in no other, is not recoverable afterwards, and there is deliberately no reveal endpoint. The value is the sixteen-character display prefix followed immediately by thirty-two more characters; the example below is a visible placeholder rather than that shape, because a realistic credential in a committed file is one the repository's own secret scanner refuses.",
679
- example: {
680
- createdAt: "2026-07-28T15:00:00.000Z",
681
- displayPrefix: "pt_test_a1b2c3d4",
682
- environmentKind: "test",
683
- id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
684
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
685
- scopes: ["schedules:write"],
686
- secret: "pt_test_a1b2c3d4<the-32-character-secret-half-here>",
687
- shownOnce: true,
688
- },
1430
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1431
+ ? ""
1432
+ : "Issues an API credential bound to one project and environment, with scopes capped by the issuing member's current role. The full secret is in this response and in no other, is not recoverable afterwards, and there is deliberately no reveal endpoint. The value is the sixteen-character display prefix followed immediately by thirty-two more characters; the example below is a visible placeholder rather than that shape, because a realistic credential in a committed file is one the repository's own secret scanner refuses.",
1433
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1434
+ ? {}
1435
+ : {
1436
+ createdAt: "2026-07-28T15:00:00.000Z",
1437
+ displayPrefix: "pt_test_a1b2c3d4",
1438
+ environmentKind: "test",
1439
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
1440
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1441
+ scopes: ["schedules:write"],
1442
+ secret: "pt_test_a1b2c3d4<the-32-character-secret-half-here>",
1443
+ shownOnce: true,
1444
+ },
689
1445
  id: "credentials.create",
690
1446
  idempotent: false,
691
1447
  // The one API-surface operation an agent cannot reach, and the reason is
@@ -721,43 +1477,54 @@ export const OPERATIONS = [
721
1477
  // where the refusal becomes reachable and declarable.
722
1478
  problems: ["invalid_request", "not_found"],
723
1479
  request: credentialRequestSchema,
724
- requestExample: {
725
- environmentKind: "test",
726
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
727
- scopes: ["schedules:write"],
728
- },
729
- response: credentialCreatedSchema,
1480
+ requestExample: globalThis
1481
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1482
+ ? {}
1483
+ : {
1484
+ environmentKind: "test",
1485
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1486
+ scopes: ["schedules:write"],
1487
+ },
1488
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1489
+ ? API_UNUSED_RESPONSE_SCHEMA
1490
+ : credentialCreatedSchema,
730
1491
  scopes: ["credentials:write"],
731
1492
  sessionAuthority: "request-body",
732
- summary: "Issue an API credential",
1493
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1494
+ ? ""
1495
+ : "Issue an API credential",
733
1496
  surfaces: ["api", "mock"],
734
1497
  },
735
1498
  {
736
1499
  creates: false,
737
- description: "Lists the credentials issued for the caller's own project and environment, oldest first, one page at a time. The authority tuple comes from the verified principal, so there is no parameter that could name another project — a listing is the caller's own book or nothing. Revoked and rotated credentials stay in the listing and carry the fields that say so; a credential nobody can see is a credential nobody can audit. `limit` is bounded by the contract and `cursor` is the opaque value the previous page returned. No page carries a secret: the item is the read shape, which has no field one could be put in.",
738
- example: {
739
- data: [
740
- {
741
- createdAt: "2026-07-28T15:00:00.000Z",
742
- displayPrefix: "pt_test_a1b2c3d4",
743
- environmentKind: "test",
744
- id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
745
- lastUsedAt: "2026-07-28T15:04:00.000Z",
746
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
747
- scopes: ["schedules:write"],
748
- },
749
- ],
750
- // Authoritative rather than projected: credentials are read from the row
751
- // that owns them, not from a cross-partition projection. The
752
- // discriminator is on every page so a client never has to know which
753
- // collections lag.
754
- freshness: { kind: "authoritative" },
755
- // Opaque. Clients pass back exactly what they were given, which is why
756
- // this is the whole value rather than an elided one — a truncated example
757
- // teaches a reader that a cursor has readable parts.
758
- nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoiYWtfMDFoOHh5ejlrMm00bjZwOHIwdDJ2NHc2eTgiLCJrIjoiOTUxMzU0NmYifQ",
759
- },
760
- id: "credentials.list",
1500
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1501
+ ? ""
1502
+ : "Lists the credentials issued for the caller's own project and environment, oldest first, one page at a time. The authority tuple comes from the verified principal, so there is no parameter that could name another project — a listing is the caller's own book or nothing. Revoked and rotated credentials stay in the listing and carry the fields that say so; a credential nobody can see is a credential nobody can audit. `limit` is bounded by the contract and `cursor` is the opaque value the previous page returned. No page carries a secret: the item is the read shape, which has no field one could be put in.",
1503
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1504
+ ? {}
1505
+ : {
1506
+ data: [
1507
+ {
1508
+ createdAt: "2026-07-28T15:00:00.000Z",
1509
+ displayPrefix: "pt_test_a1b2c3d4",
1510
+ environmentKind: "test",
1511
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
1512
+ lastUsedAt: "2026-07-28T15:04:00.000Z",
1513
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1514
+ scopes: ["schedules:write"],
1515
+ },
1516
+ ],
1517
+ // Authoritative rather than projected: credentials are read from the row
1518
+ // that owns them, not from a cross-partition projection. The
1519
+ // discriminator is on every page so a client never has to know which
1520
+ // collections lag.
1521
+ freshness: { kind: "authoritative" },
1522
+ // Opaque. Clients pass back exactly what they were given, which is why
1523
+ // this is the whole value rather than an elided one — a truncated example
1524
+ // teaches a reader that a cursor has readable parts.
1525
+ nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoiYWtfMDFoOHh5ejlrMm00bjZwOHIwdDJ2NHc2eTgiLCJrIjoiOTUxMzU0NmYifQ",
1526
+ },
1527
+ id: "credentials.list",
761
1528
  idempotent: true,
762
1529
  mcp: { destructive: false, kind: "tool", openWorld: false },
763
1530
  method: "GET",
@@ -770,24 +1537,92 @@ export const OPERATIONS = [
770
1537
  // sometimes empty.
771
1538
  problems: ["invalid_request"],
772
1539
  query: pageRequestSchema,
773
- response: credentialPageSchema,
1540
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1541
+ ? API_UNUSED_RESPONSE_SCHEMA
1542
+ : credentialPageSchema,
774
1543
  scopes: ["credentials:read"],
775
1544
  sessionAuthority: "headers",
776
- summary: "List API credentials",
1545
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1546
+ ? ""
1547
+ : "List API credentials",
777
1548
  surfaces: ["api", "mock"],
778
1549
  },
779
1550
  {
780
1551
  creates: false,
781
- description: "Lists the projects in the signed-in member's organization that they may act in, with the environment kinds each one has. This is what a browser asks before it can address anything else: an API credential and an OAuth token each carry one project intrinsically, but a member belongs to an organization and chooses. Archived and deleted projects are omitted, because a member cannot act in one. The result is a display aid rather than an authorization control — naming a project on a later request re-resolves it against the member's own organization, and a project that is not theirs answers exactly as one that does not exist.",
782
- example: {
783
- data: [
784
- {
785
- environmentKinds: ["test", "live"],
786
- id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
787
- name: "Billing reminders",
788
- },
789
- ],
1552
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1553
+ ? ""
1554
+ : "Reads what a key this project issued should be able to do over MCP: the endpoint to point a client at, the discovery document beside it, the scopes fixed into the key when it was made, and the MCP tool names those scopes authorize. It returns no secret and cannot: the transient value is shown once at creation and is never sent here. The credential is addressed by identifier and re-resolved against the signed-in member's own project and environment, so a key belonging to another project answers exactly as one that does not exist. `state` distinguishes a key that still verifies from one that was revoked and one whose rotation overlap has run out, because a client configured with either fails identically and the remedies differ.",
1555
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1556
+ ? {}
1557
+ : {
1558
+ discovery: "https://api.greatwait.dev/.well-known/oauth-protected-resource/mcp",
1559
+ displayPrefix: "pt_test_a1b2c3d4",
1560
+ endpoint: "https://api.greatwait.dev/mcp",
1561
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
1562
+ scopes: ["occurrences:read", "schedules:read", "schedules:write"],
1563
+ state: "usable",
1564
+ tools: [
1565
+ "occurrences_list",
1566
+ "occurrences_read",
1567
+ "schedules_cancel",
1568
+ "schedules_create",
1569
+ "schedules_list",
1570
+ "schedules_read",
1571
+ ],
1572
+ },
1573
+ id: "credentials.connection",
1574
+ idempotent: true,
1575
+ // **Withheld, and the reason is the same one that withholds issuance.** A
1576
+ // member asks this about a key they are holding in a browser, in the window
1577
+ // where its secret is still on screen. An agent is already connected: it has
1578
+ // no transient secret to check and no session to bind one to, so a tool here
1579
+ // would answer `authentication_required` to every caller that could reach
1580
+ // it. Publishing the exclusion is the honest version of that.
1581
+ mcp: {
1582
+ kind: "unavailable",
1583
+ reason: "A signed-in member checking a key whose secret is still on screen. MCP carries API credentials and OAuth tokens, neither of which holds a transient secret or a session to bind one to.",
790
1584
  },
1585
+ method: "GET",
1586
+ mutates: false,
1587
+ path: "/v1/credentials/{credentialId}/connection",
1588
+ principals: ["session"],
1589
+ problems: ["not_found"],
1590
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1591
+ ? API_UNUSED_RESPONSE_SCHEMA
1592
+ : mcpConnectionSchema,
1593
+ scopes: ["credentials:read"],
1594
+ sessionAuthority: "headers",
1595
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1596
+ ? ""
1597
+ : "Read a credential's MCP connection",
1598
+ surfaces: ["api", "mock"],
1599
+ },
1600
+ {
1601
+ creates: false,
1602
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1603
+ ? ""
1604
+ : "Lists the active and archived projects in the signed-in member's organization, with the environment kinds, lifecycle state, version and deletion-preview counts each one has. Active and archived rows both occupy a plan slot; deleted projects are absent. Archived rows are management targets rather than projects work may run inside, so a picker must not offer them as switch targets. The result is a display aid rather than an authorization control — naming a project on a later request re-resolves it against the member's own organization, and a project that is not theirs answers exactly as one that does not exist.",
1605
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1606
+ ? {}
1607
+ : {
1608
+ data: [
1609
+ {
1610
+ createdAt: "2026-08-14T11:00:00.000Z",
1611
+ deletionCounts: {
1612
+ endpoints: 2,
1613
+ keys: 4,
1614
+ runs: 37,
1615
+ schedules: 5,
1616
+ },
1617
+ environmentKinds: ["test", "live"],
1618
+ id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1619
+ name: "Billing reminders",
1620
+ status: "active",
1621
+ version: 1,
1622
+ },
1623
+ ],
1624
+ total: 1,
1625
+ },
791
1626
  id: "projects.list",
792
1627
  idempotent: true,
793
1628
  mcp: {
@@ -801,27 +1636,38 @@ export const OPERATIONS = [
801
1636
  // No `not_found`: the collection is the member's own organization, so it
802
1637
  // always exists and is sometimes empty. No paging, so no `invalid_request`.
803
1638
  problems: [],
804
- response: projectListSchema,
1639
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1640
+ ? API_UNUSED_RESPONSE_SCHEMA
1641
+ : projectListSchema,
805
1642
  scopes: ["projects:read"],
806
1643
  sessionAuthority: "organization",
807
- summary: "List the member's projects",
1644
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1645
+ ? ""
1646
+ : "List the member's projects",
808
1647
  surfaces: ["api", "mock"],
809
1648
  },
810
1649
  {
811
1650
  creates: true,
812
- description: "Creates a project in the signed-in member's organization, with both of its environments. This is the first call a new customer makes: an organization has no project until somebody makes one, and every other operation on this surface acts inside one. The `test` and `live` environments are provisioned with it in a single transaction rather than asked for, so a project is never observable in a half-provisioned state. The organization comes from the verified session and is never read from the request — a member who belongs to one organization cannot create a project in another. `PROJECT_LIST_LIMIT` bounds how many an organization may hold, and it is the same ceiling the listing publishes: a create that would take an organization past a list it can no longer return is refused rather than silently truncating a later read.",
813
- example: {
814
- environmentKinds: ["test", "live"],
815
- id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
816
- name: "Billing reminders",
817
- },
1651
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1652
+ ? ""
1653
+ : "Creates a project in the signed-in member's organization, with both of its environments. This is the first call a new customer makes: an organization has no project until somebody makes one, and every other operation on this surface acts inside one. The `test` and `live` environments are provisioned with it in a single transaction rather than asked for, so a project is never observable in a half-provisioned state. The organization comes from the verified session and is never read from the request — a member who belongs to one organization cannot create a project in another. `PROJECT_LIST_LIMIT` bounds how many an organization may hold, and it is the same ceiling the listing publishes: a create that would take an organization past a list it can no longer return is refused rather than silently truncating a later read. A name is unique within the organization, compared ignoring case and surrounding or repeated spaces; a second project with a name already taken is refused with `state_conflict`, and the refusal says nothing about any other organization's names.",
1654
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1655
+ ? {}
1656
+ : {
1657
+ createdAt: null,
1658
+ deletionCounts: { endpoints: 0, keys: 0, runs: 0, schedules: 0 },
1659
+ environmentKinds: ["test", "live"],
1660
+ id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1661
+ name: "Billing reminders",
1662
+ status: "active",
1663
+ version: 1,
1664
+ },
818
1665
  id: "projects.create",
819
- // Not idempotent, and it cannot be made so here: repeating this makes a
820
- // second project with the same name, because a name is a label rather than
821
- // an identifier — `projectNameSchema` says so, and non-uniqueness is what
822
- // lets somebody rename one without breaking a caller's URLs. No route on
823
- // this Worker reads an idempotency key for it, so declaring `true` would
824
- // publish a promise nothing keeps.
1666
+ // Not idempotent, and it cannot be made so here. Since FXO-2256 a repeat
1667
+ // with the same name is *refused* rather than doubled — the name is unique
1668
+ // in its organization — but a refusal is not the same answer as the first
1669
+ // call's, and no route on this Worker reads an idempotency key for it, so
1670
+ // declaring `true` would publish a promise nothing keeps.
825
1671
  idempotent: false,
826
1672
  // Withheld from MCP for `projects.list`'s reason and one of its own. The
827
1673
  // shared half: this operation accepts only a signed-in member, and MCP
@@ -843,32 +1689,169 @@ export const OPERATIONS = [
843
1689
  // the same shape of refusal. There is no `not_found`: the organization is
844
1690
  // the member's own and is created on first use, so it always exists by the
845
1691
  // time the project is written.
846
- problems: ["invalid_request", "plan_limit_reached"],
1692
+ problems: ["invalid_request", "plan_limit_reached", "state_conflict"],
847
1693
  request: projectCreateRequestSchema,
848
- requestExample: { name: "Billing reminders" },
849
- response: projectSummarySchema,
1694
+ requestExample: globalThis
1695
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1696
+ ? {}
1697
+ : { name: "Billing reminders" },
1698
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1699
+ ? API_UNUSED_RESPONSE_SCHEMA
1700
+ : projectSummarySchema,
850
1701
  scopes: ["projects:write"],
851
1702
  sessionAuthority: "organization",
852
- summary: "Create a project",
1703
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1704
+ ? ""
1705
+ : "Create a project",
853
1706
  surfaces: ["api", "mock"],
854
1707
  },
855
1708
  {
856
1709
  creates: false,
857
- description: "Lists the applications this member has connected to their own account, newest first, across every project in their organization — because a person connects an application, not a project. Revoked connections stay in the listing with the instant and the reason they ended: a connection nobody can see is one nobody can audit. This is a signed-in member's view of their own delegations. An application holding a grant cannot read it, which is why the operation accepts no API credential and no access token, and why it is on no agent's tool list.",
858
- example: {
859
- data: [
860
- {
861
- client: { id: "oc_01h8xyz9k2m4n6p8r0t2v4w6y8", name: "Flow XO" },
862
- createdAt: "2026-08-14T11:00:00.000Z",
863
- environmentKind: "test",
864
- id: "og_01h8xyz9k2m4n6p8r0t2v4w6y8",
865
- lastUsedAt: "2026-08-15T09:12:00.000Z",
866
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
867
- scopes: ["schedules:read", "schedules:write"],
868
- status: "active",
869
- },
870
- ],
871
- },
1710
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1711
+ ? ""
1712
+ : "Renames one project in the caller's own organization without changing its opaque identifier. Names remain unique within the organization ignoring ASCII case and surrounding or repeated whitespace. Send If-Match with the project's current version; a stale version is refused rather than silently overwriting somebody else's change. Members and administrators may rename because the change is cosmetic and reversible.",
1713
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1714
+ ? {}
1715
+ : {
1716
+ createdAt: "2026-08-14T11:00:00.000Z",
1717
+ deletionCounts: { endpoints: 2, keys: 4, runs: 37, schedules: 5 },
1718
+ environmentKinds: ["test", "live"],
1719
+ id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1720
+ name: "Customer reminders",
1721
+ status: "active",
1722
+ version: 2,
1723
+ },
1724
+ id: "projects.rename",
1725
+ idempotent: false,
1726
+ mcp: { destructive: false, kind: "tool", openWorld: false },
1727
+ method: "PATCH",
1728
+ mutates: true,
1729
+ path: "/v1/projects/{projectId}",
1730
+ principals: ["api-credential", "oauth", "session"],
1731
+ problems: [
1732
+ "invalid_request",
1733
+ "not_found",
1734
+ "state_conflict",
1735
+ "version_conflict",
1736
+ ],
1737
+ request: projectUpdateRequestSchema,
1738
+ requestExample: globalThis
1739
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1740
+ ? {}
1741
+ : { name: "Customer reminders" },
1742
+ requestHeaders: requiredConditionalRequestHeaderSchema,
1743
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1744
+ ? API_UNUSED_RESPONSE_SCHEMA
1745
+ : projectSummarySchema,
1746
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
1747
+ ? {}
1748
+ : { responseHeaders: versionResponseHeaderSchema }),
1749
+ scopes: ["projects:write"],
1750
+ sessionAuthority: "headers",
1751
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1752
+ ? ""
1753
+ : "Rename a project",
1754
+ surfaces: ["api", "mock"],
1755
+ },
1756
+ {
1757
+ creates: false,
1758
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1759
+ ? ""
1760
+ : "Archives or restores the caller's project. Archiving parks the complete project: no new occurrence is dispatched, while schedules, endpoints, keys, grants and retained history remain intact. Restoring clears that project-wide hold without rewriting any schedule; an occurrence whose instant passed while archived becomes due, matching schedule pause and resume. Only organization administrators may make this project-wide change.",
1761
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1762
+ ? {}
1763
+ : {
1764
+ createdAt: "2026-08-14T11:00:00.000Z",
1765
+ deletionCounts: { endpoints: 2, keys: 4, runs: 37, schedules: 5 },
1766
+ environmentKinds: ["test", "live"],
1767
+ id: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1768
+ name: "Customer reminders",
1769
+ status: "archived",
1770
+ version: 2,
1771
+ },
1772
+ id: "projects.archive",
1773
+ idempotent: false,
1774
+ mcp: { destructive: false, kind: "tool", openWorld: false },
1775
+ method: "POST",
1776
+ mutates: true,
1777
+ path: "/v1/projects/{projectId}/archive",
1778
+ principals: ["api-credential", "oauth", "session"],
1779
+ problems: [
1780
+ "invalid_request",
1781
+ "not_found",
1782
+ "state_conflict",
1783
+ "version_conflict",
1784
+ ],
1785
+ request: projectArchiveRequestSchema,
1786
+ requestExample: globalThis
1787
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1788
+ ? {}
1789
+ : { archived: true },
1790
+ requestHeaders: requiredConditionalRequestHeaderSchema,
1791
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1792
+ ? API_UNUSED_RESPONSE_SCHEMA
1793
+ : projectSummarySchema,
1794
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
1795
+ ? {}
1796
+ : { responseHeaders: versionResponseHeaderSchema }),
1797
+ scopes: ["projects:administer"],
1798
+ sessionAuthority: "headers",
1799
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1800
+ ? ""
1801
+ : "Archive or restore a project",
1802
+ surfaces: ["api", "mock"],
1803
+ },
1804
+ {
1805
+ creates: false,
1806
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1807
+ ? ""
1808
+ : "Permanently deletes an archived project and everything it owns immediately: schedules and encrypted payloads, occurrences and delivery attempts, endpoints and their signing keys, API credentials and their audit events, OAuth grants and tokens, test sinks, and control-plane projections. The operation is refused while the project is active and names archiving as the required first move. Its response reports the schedules, endpoints, keys and runs destroyed. Only organization administrators may perform it, and there is no restore operation.",
1809
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1810
+ ? {}
1811
+ : {
1812
+ deleted: true,
1813
+ destroyed: { endpoints: 2, keys: 4, runs: 37, schedules: 5 },
1814
+ },
1815
+ id: "projects.delete",
1816
+ idempotent: false,
1817
+ mcp: { destructive: true, kind: "tool", openWorld: false },
1818
+ method: "DELETE",
1819
+ mutates: true,
1820
+ path: "/v1/projects/{projectId}",
1821
+ principals: ["api-credential", "oauth", "session"],
1822
+ problems: ["not_found", "state_conflict", "version_conflict"],
1823
+ requestHeaders: requiredConditionalRequestHeaderSchema,
1824
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1825
+ ? API_UNUSED_RESPONSE_SCHEMA
1826
+ : projectDeletedSchema,
1827
+ scopes: ["projects:administer"],
1828
+ sessionAuthority: "headers",
1829
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1830
+ ? ""
1831
+ : "Delete an archived project",
1832
+ surfaces: ["api", "mock"],
1833
+ },
1834
+ {
1835
+ creates: false,
1836
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1837
+ ? ""
1838
+ : "Lists the applications this member has connected to their own account, newest first, across every project in their organization — because a person connects an application, not a project. Revoked connections stay in the listing with the instant and the reason they ended: a connection nobody can see is one nobody can audit. This is a signed-in member's view of their own delegations. An application holding a grant cannot read it, which is why the operation accepts no API credential and no access token, and why it is on no agent's tool list.",
1839
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1840
+ ? {}
1841
+ : {
1842
+ data: [
1843
+ {
1844
+ client: { id: "oc_01h8xyz9k2m4n6p8r0t2v4w6y8", name: "Flow XO" },
1845
+ createdAt: "2026-08-14T11:00:00.000Z",
1846
+ environmentKind: "test",
1847
+ id: "og_01h8xyz9k2m4n6p8r0t2v4w6y8",
1848
+ lastUsedAt: "2026-08-15T09:12:00.000Z",
1849
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1850
+ scopes: ["schedules:read", "schedules:write"],
1851
+ status: "active",
1852
+ },
1853
+ ],
1854
+ },
872
1855
  id: "grants.list",
873
1856
  idempotent: true,
874
1857
  // **Withheld, and the reason is what the surface is for.** An application
@@ -889,28 +1872,36 @@ export const OPERATIONS = [
889
1872
  // sometimes empty. Its size is how many applications one person has
890
1873
  // connected, which is not a number a cursor helps with.
891
1874
  problems: [],
892
- response: oauthGrantListSchema,
1875
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1876
+ ? API_UNUSED_RESPONSE_SCHEMA
1877
+ : oauthGrantListSchema,
893
1878
  scopes: ["grants:read"],
894
1879
  sessionAuthority: "member",
895
- summary: "List the member's connected applications",
1880
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1881
+ ? ""
1882
+ : "List the member's connected applications",
896
1883
  surfaces: ["api", "mock"],
897
1884
  },
898
1885
  {
899
1886
  creates: false,
900
- description: "Disconnects one application, ending every token that grant ever issued — the access tokens and the refresh token together. The grant stays readable afterwards with the instant and the reason it ended. Only the member who granted it can disconnect it, and a grant belonging to somebody else answers exactly as one that does not exist.",
901
- example: {
902
- grant: {
903
- client: { id: "oc_01h8xyz9k2m4n6p8r0t2v4w6y8", name: "Flow XO" },
904
- createdAt: "2026-08-14T11:00:00.000Z",
905
- environmentKind: "test",
906
- id: "og_01h8xyz9k2m4n6p8r0t2v4w6y8",
907
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
908
- revocationReason: "member-revoked",
909
- revokedAt: "2026-08-15T10:00:00.000Z",
910
- scopes: ["schedules:read", "schedules:write"],
911
- status: "revoked",
1887
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1888
+ ? ""
1889
+ : "Disconnects one application, ending every token that grant ever issued — the access tokens and the refresh token together. The grant stays readable afterwards with the instant and the reason it ended. Only the member who granted it can disconnect it, and a grant belonging to somebody else answers exactly as one that does not exist.",
1890
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1891
+ ? {}
1892
+ : {
1893
+ grant: {
1894
+ client: { id: "oc_01h8xyz9k2m4n6p8r0t2v4w6y8", name: "Flow XO" },
1895
+ createdAt: "2026-08-14T11:00:00.000Z",
1896
+ environmentKind: "test",
1897
+ id: "og_01h8xyz9k2m4n6p8r0t2v4w6y8",
1898
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1899
+ revocationReason: "member-revoked",
1900
+ revokedAt: "2026-08-15T10:00:00.000Z",
1901
+ scopes: ["schedules:read", "schedules:write"],
1902
+ status: "revoked",
1903
+ },
912
1904
  },
913
- },
914
1905
  id: "grants.revoke",
915
1906
  // Repeating it is safe: the grant is already revoked, and the second call
916
1907
  // reports the first one's instant rather than moving it. That is
@@ -925,37 +1916,45 @@ export const OPERATIONS = [
925
1916
  path: "/v1/grants/{grantId}",
926
1917
  principals: ["session"],
927
1918
  problems: ["not_found"],
928
- response: oauthGrantRevokedSchema,
1919
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1920
+ ? API_UNUSED_RESPONSE_SCHEMA
1921
+ : oauthGrantRevokedSchema,
929
1922
  scopes: ["grants:write"],
930
1923
  sessionAuthority: "member",
931
- summary: "Disconnect an application",
1924
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1925
+ ? ""
1926
+ : "Disconnect an application",
932
1927
  surfaces: ["api", "mock"],
933
1928
  },
934
1929
  {
935
1930
  creates: true,
936
- description: "Replaces a credential with a new one and gives the original a deadline, so consumers can pick up the new secret before the old stops working. The replacement is a new credential with its own identifier and the same authority and scopes; the original keeps working until it expires, then refuses with `credential_expired` rather than `credential_revoked`. `overlapSeconds` may only shorten the window — the default is also the maximum — and zero retires the original immediately. The new secret is in this response and in no other.",
937
- example: {
938
- credential: {
939
- createdAt: "2026-07-28T15:00:00.000Z",
940
- displayPrefix: "pt_test_e5f6g7h8",
941
- environmentKind: "test",
942
- id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y9",
943
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
944
- scopes: ["schedules:write"],
945
- secret: "pt_test_e5f6g7h8<the-32-character-secret-half-here>",
946
- shownOnce: true,
947
- },
948
- retired: {
949
- createdAt: "2026-07-28T15:00:00.000Z",
950
- displayPrefix: "pt_test_a1b2c3d4",
951
- environmentKind: "test",
952
- expiresAt: "2026-07-29T15:00:00.000Z",
953
- id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
954
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
955
- scopes: ["schedules:write"],
956
- supersededBy: "ak_01h8xyz9k2m4n6p8r0t2v4w6y9",
1931
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1932
+ ? ""
1933
+ : "Replaces a credential with a new one and gives the original a deadline, so consumers can pick up the new secret before the old stops working. The replacement is a new credential with its own identifier and the same authority and scopes; the original keeps working until it expires, then refuses with `credential_expired` rather than `credential_revoked`. `overlapSeconds` may only shorten the window — the default is also the maximum — and zero retires the original immediately. The new secret is in this response and in no other.",
1934
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1935
+ ? {}
1936
+ : {
1937
+ credential: {
1938
+ createdAt: "2026-07-28T15:00:00.000Z",
1939
+ displayPrefix: "pt_test_e5f6g7h8",
1940
+ environmentKind: "test",
1941
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y9",
1942
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1943
+ scopes: ["schedules:write"],
1944
+ secret: "pt_test_e5f6g7h8<the-32-character-secret-half-here>",
1945
+ shownOnce: true,
1946
+ },
1947
+ retired: {
1948
+ createdAt: "2026-07-28T15:00:00.000Z",
1949
+ displayPrefix: "pt_test_a1b2c3d4",
1950
+ environmentKind: "test",
1951
+ expiresAt: "2026-07-29T15:00:00.000Z",
1952
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
1953
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
1954
+ scopes: ["schedules:write"],
1955
+ supersededBy: "ak_01h8xyz9k2m4n6p8r0t2v4w6y9",
1956
+ },
957
1957
  },
958
- },
959
1958
  id: "credentials.rotate",
960
1959
  // Destructive: the original credential is given a deadline it did not have,
961
1960
  // and whatever is still using it stops working when that deadline passes.
@@ -976,305 +1975,994 @@ export const OPERATIONS = [
976
1975
  principals: ["api-credential", "oauth", "session"],
977
1976
  problems: ["invalid_request", "not_found", "scope_missing"],
978
1977
  request: credentialRotationRequestSchema,
979
- requestExample: { overlapSeconds: 3600 },
980
- response: credentialRotatedSchema,
1978
+ requestExample: globalThis
1979
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1980
+ ? {}
1981
+ : { overlapSeconds: 3600 },
1982
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1983
+ ? API_UNUSED_RESPONSE_SCHEMA
1984
+ : credentialRotatedSchema,
981
1985
  scopes: ["credentials:write"],
982
1986
  sessionAuthority: "headers",
983
- summary: "Rotate an API credential",
1987
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
1988
+ ? ""
1989
+ : "Rotate an API credential",
984
1990
  surfaces: ["api", "mock"],
985
1991
  },
986
1992
  {
987
1993
  creates: false,
988
- description: "Revokes a credential immediately, with no overlap. The credential stops verifying on the next request and refuses with `credential_revoked`. The row survives its revocation so the credential's history remains answerable, and revoking a credential that is already revoked reports the original revocation rather than moving it. A credential belonging to another project is indistinguishable from one that does not exist.",
989
- example: {
990
- credential: {
991
- createdAt: "2026-07-28T15:00:00.000Z",
992
- displayPrefix: "pt_test_a1b2c3d4",
993
- environmentKind: "test",
994
- id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
995
- project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
996
- revokedAt: "2026-07-28T16:00:00.000Z",
997
- scopes: ["schedules:write"],
1994
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
1995
+ ? ""
1996
+ : "Revokes a credential immediately, with no overlap. The credential stops verifying on the next request and refuses with `credential_revoked`. The row survives its revocation so the credential's history remains answerable, and revoking a credential that is already revoked reports the original revocation rather than moving it. A credential belonging to another project is indistinguishable from one that does not exist.",
1997
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
1998
+ ? {}
1999
+ : {
2000
+ credential: {
2001
+ createdAt: "2026-07-28T15:00:00.000Z",
2002
+ displayPrefix: "pt_test_a1b2c3d4",
2003
+ environmentKind: "test",
2004
+ id: "ak_01h8xyz9k2m4n6p8r0t2v4w6y8",
2005
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
2006
+ revokedAt: "2026-07-28T16:00:00.000Z",
2007
+ scopes: ["schedules:write"],
2008
+ },
998
2009
  },
999
- },
1000
2010
  id: "credentials.revoke",
1001
2011
  mcp: { destructive: true, kind: "tool", openWorld: false },
1002
2012
  // Repeating this leaves the same credential revoked at the same instant, so
1003
2013
  // it is idempotent in the sense the field means — no key required, because
1004
2014
  // there is no second effect to suppress.
1005
2015
  idempotent: true,
1006
- method: "DELETE",
2016
+ method: "DELETE",
2017
+ mutates: true,
2018
+ path: "/v1/credentials/{credentialId}",
2019
+ conditionalScopes: ["credentials:administer"],
2020
+ principals: ["api-credential", "oauth", "session"],
2021
+ problems: ["invalid_request", "not_found", "scope_missing"],
2022
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2023
+ ? API_UNUSED_RESPONSE_SCHEMA
2024
+ : credentialRevokedSchema,
2025
+ scopes: ["credentials:write"],
2026
+ sessionAuthority: "headers",
2027
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2028
+ ? ""
2029
+ : "Revoke an API credential",
2030
+ surfaces: ["api", "mock"],
2031
+ },
2032
+ {
2033
+ creates: true,
2034
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2035
+ ? ""
2036
+ : "Creates a schedule and returns it together with its first planned occurrence. Give exactly one of `at`, `delaySeconds`, `everySeconds` and `cron`. An optional `partitionKey` selects a fairness lane inside this project and environment; it is fixed after create. Add a verified `endpoint` to deliver each occurrence there; optional JSON `data` is encrypted before PostgreSQL persistence, placed in the signed callback, and returned as given by a schedule read. `at` and `delaySeconds` fire once; a delay is converted to an absolute instant when the request is accepted, so a schedule created either way reads back the same afterwards. `everySeconds` is a fixed duration and its first occurrence falls one interval after acceptance — it stays the same length across a daylight-saving change, and takes no timezone for that reason. `cron` is a wall clock: it is read against the IANA `timeZone` sent with it, `UTC` when none is, and the first occurrence is the first instant the expression names after acceptance. Where the clocks go forward and the wall time named does not exist that day, the occurrence falls at the first instant after the gap; where they go back and it happens twice, it falls once, at the earlier of the two. A recurring schedule is materialized one occurrence at a time: the next one is planned once the current one is due, so a read always shows one occurrence still to come. `lateness.policy` decides what happens when an occurrence reaches its first attempt after its planned instant: `skipAhead` never carries a recurring arrival across its next scheduled instant (and a shorter custom window may retire it earlier), while `catchUp` admits one arrival within `maxStalenessSeconds` even after later recurrence instants passed. A one-shot has no next recurrence, so either explicit policy uses its window and the default is `catchUp` with 24 hours; recurring schedules default to `skipAhead`, and a `catchUp` without an override has a one-interval window. A retry already in progress is exempt because it arrived and failed; its retry and give-up policy still decide the outcome. The organization, project and environment come from the verified principal; a body cannot name them, and the endpoint must belong to the same tuple, so a credential issued for one project can only ever create schedules in that project. Send an `Idempotency-Key` to make a retry safe: the identical request returns the schedule that key already created, marked `Idempotency-Replayed: true`, and creates nothing further; the same key with a different request is refused `idempotency_key_reused`. A replay reports the schedule **as it stands now**, not a frozen copy of the first response — if it was paused in between, the replay says so.",
2037
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2038
+ ? {}
2039
+ : {
2040
+ occurrence: {
2041
+ attemptCount: 0,
2042
+ generation: 1,
2043
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
2044
+ plannedFor: "2026-07-28T15:00:00.000Z",
2045
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
2046
+ sequence: 1,
2047
+ state: "planned",
2048
+ },
2049
+ schedule: {
2050
+ createdAt: "2026-07-28T14:59:00.000Z",
2051
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
2052
+ generation: 1,
2053
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
2054
+ latencyClass: "realtime",
2055
+ lateness: { policy: "catchUp" },
2056
+ partitionKey: "campaign.spring",
2057
+ recurrence: { kind: "at" },
2058
+ status: "active",
2059
+ updatedAt: "2026-07-28T14:59:00.000Z",
2060
+ version: 1,
2061
+ },
2062
+ },
2063
+ id: "schedules.create",
2064
+ // Additive: it brings a schedule into existence and takes nothing away.
2065
+ // A callback schedule causes a future request to the verified external
2066
+ // endpoint. It does not destructively modify that system, but it does act
2067
+ // beyond Greatwait, so MCP clients must receive the open-world hint.
2068
+ mcp: { destructive: false, kind: "tool", openWorld: true },
2069
+ // False even though this operation reads `Idempotency-Key`, because the
2070
+ // header is optional and this flag is what a client reads before deciding
2071
+ // whether a blind retry is safe. It is not: a retry without the key creates
2072
+ // a second schedule. What says the protection is available is
2073
+ // `requestHeaders`, which publishes the key rather than promising it was
2074
+ // used.
2075
+ idempotent: false,
2076
+ method: "POST",
2077
+ mutates: true,
2078
+ path: "/v1/schedules",
2079
+ principals: ["api-credential", "oauth", "session"],
2080
+ problems: [
2081
+ "idempotency_key_reused",
2082
+ "invalid_request",
2083
+ "not_found",
2084
+ // The organization ceiling, the same code and the same shape
2085
+ // `projects.create` and `endpoints.create` use. A plan may bound the
2086
+ // live schedules an organization holds, the distinct partition keys it
2087
+ // has live, and how large a `data` body it may carry; all three refuse
2088
+ // here rather than truncating, because a schedule created without the
2089
+ // body the caller sent is not the schedule they asked for.
2090
+ "plan_limit_reached",
2091
+ "service_unavailable",
2092
+ // A schedule against a disabled endpoint. Refused rather than accepted
2093
+ // and never fired, and refused by its state rather than as `not_found`,
2094
+ // because the endpoint exists and one call turns it back on.
2095
+ "state_conflict",
2096
+ ],
2097
+ request: scheduleRequestSchema,
2098
+ requestExample: globalThis
2099
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2100
+ ? {}
2101
+ : {
2102
+ cron: "0 9 * * 1-5",
2103
+ data: { report: "daily" },
2104
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
2105
+ lateness: { maxStalenessSeconds: 3_600, policy: "catchUp" },
2106
+ partitionKey: "campaign.spring",
2107
+ timeZone: "Europe/London",
2108
+ },
2109
+ requestHeaders: idempotencyRequestHeaderSchema,
2110
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2111
+ ? API_UNUSED_RESPONSE_SCHEMA
2112
+ : scheduleViewSchema,
2113
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2114
+ ? {}
2115
+ : { responseHeaders: replayedResponseHeaderSchema }),
2116
+ scopes: ["schedules:write"],
2117
+ sessionAuthority: "headers",
2118
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2119
+ ? ""
2120
+ : "Create a schedule",
2121
+ surfaces: ["api", "mock"],
2122
+ },
2123
+ {
2124
+ creates: false,
2125
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2126
+ ? ""
2127
+ : "Reads one schedule and its next occurrence from the partition that owns it. A schedule belonging to another organization, project or environment answers not_found rather than a refusal that would confirm it exists. The response carries the schedule's version as a strong ETag; send it back in `If-Match` to make a later write conditional on nothing having changed in between. The response carries the schedule's `data` when it has one, exactly as it was given; the listing leaves it off.",
2128
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2129
+ ? {}
2130
+ : {
2131
+ occurrence: {
2132
+ attemptCount: 0,
2133
+ generation: 1,
2134
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
2135
+ plannedFor: "2026-07-28T15:00:00.000Z",
2136
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
2137
+ sequence: 1,
2138
+ state: "planned",
2139
+ },
2140
+ schedule: {
2141
+ createdAt: "2026-07-28T14:59:00.000Z",
2142
+ data: { report: "daily" },
2143
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
2144
+ generation: 1,
2145
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
2146
+ latencyClass: "realtime",
2147
+ lateness: { policy: "catchUp" },
2148
+ partitionKey: "campaign.spring",
2149
+ recurrence: { kind: "at" },
2150
+ status: "active",
2151
+ updatedAt: "2026-07-28T14:59:00.000Z",
2152
+ version: 1,
2153
+ },
2154
+ },
2155
+ id: "schedules.read",
2156
+ idempotent: true,
2157
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2158
+ method: "GET",
2159
+ mutates: false,
2160
+ path: "/v1/schedules/{scheduleId}",
2161
+ principals: ["api-credential", "oauth", "session"],
2162
+ problems: ["invalid_request", "not_found"],
2163
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2164
+ ? API_UNUSED_RESPONSE_SCHEMA
2165
+ : scheduleViewSchema,
2166
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2167
+ ? {}
2168
+ : { responseHeaders: versionResponseHeaderSchema }),
2169
+ scopes: ["schedules:read"],
2170
+ sessionAuthority: "headers",
2171
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2172
+ ? ""
2173
+ : "Read a schedule",
2174
+ surfaces: ["api", "mock"],
2175
+ },
2176
+ {
2177
+ creates: false,
2178
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2179
+ ? ""
2180
+ : "Lists the caller's own schedules, oldest first, one page at a time. Archived schedules are left out: archiving is how a schedule leaves the working set, and a listing that still carried them would make the operation pointless. Give `endpoint` to keep the page to the schedules that deliver to that endpoint — the way back from a destination to everything pointed at it, which is what somebody who disabled or is about to move an endpoint needs to see. Items are schedules rather than schedules-with-occurrences, because a cross-partition listing is served from a projection that holds a summary; read a schedule to get its authoritative next occurrence. Every page states whether it is authoritative or projected.",
2181
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2182
+ ? {}
2183
+ : {
2184
+ data: [
2185
+ {
2186
+ createdAt: "2026-07-28T14:59:00.000Z",
2187
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
2188
+ generation: 1,
2189
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
2190
+ latencyClass: "realtime",
2191
+ lateness: { policy: "catchUp" },
2192
+ recurrence: { kind: "at" },
2193
+ status: "active",
2194
+ updatedAt: "2026-07-28T14:59:00.000Z",
2195
+ version: 1,
2196
+ },
2197
+ ],
2198
+ // `projected` since W2-06 served this listing from the control-plane
2199
+ // directory. `asOf` is the instant the projection was last known to hold
2200
+ // everything every partition had handed over, and `lagSeconds` is how long
2201
+ // ago that was — so a page states how far behind it may be rather than
2202
+ // implying it is current.
2203
+ freshness: {
2204
+ asOf: "2026-07-28T15:00:00.000Z",
2205
+ kind: "projected",
2206
+ lagSeconds: 0,
2207
+ },
2208
+ nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoic2NoXzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
2209
+ },
2210
+ id: "schedules.list",
2211
+ idempotent: true,
2212
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2213
+ method: "GET",
2214
+ mutates: false,
2215
+ path: "/v1/schedules",
2216
+ principals: ["api-credential", "oauth", "session"],
2217
+ problems: ["invalid_request"],
2218
+ query: scheduleListRequestSchema,
2219
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2220
+ ? API_UNUSED_RESPONSE_SCHEMA
2221
+ : schedulePageSchema,
2222
+ scopes: ["schedules:read"],
2223
+ sessionAuthority: "headers",
2224
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2225
+ ? ""
2226
+ : "List schedules",
2227
+ surfaces: ["api", "mock"],
2228
+ },
2229
+ {
2230
+ creates: false,
2231
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2232
+ ? ""
2233
+ : "Counts the occurrences this project and environment expect to fire, in epoch-aligned time buckets, with a latency-class split on every bucket and an optional customer partition-key breakdown. A recurring series contributes every instant it fires inside the window rather than only its next one, and `nextFireCount` reports how many of a bucket's occurrences are a schedule's next firing. The answer states its own freshness and is refused rather than shortened when a partition cannot complete it. It carries counts only: no schedule identifier, callback destination, payload or endpoint detail has a field in the response.",
2234
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2235
+ ? {}
2236
+ : {
2237
+ buckets: [
2238
+ {
2239
+ byLatencyClass: { bulk: 12, realtime: 3 },
2240
+ byPartitionKey: { "campaign.spring": 9, "campaign.winter": 4 },
2241
+ count: 15,
2242
+ nextFireCount: 4,
2243
+ otherPartitionKeyCount: 2,
2244
+ start: "2026-07-28T15:00:00.000Z",
2245
+ },
2246
+ ],
2247
+ freshness: {
2248
+ asOf: "2026-07-28T14:58:30.000Z",
2249
+ kind: "projected",
2250
+ lagSeconds: 90,
2251
+ },
2252
+ window: {
2253
+ bucketSeconds: 1800,
2254
+ from: "2026-07-28T15:00:00.000Z",
2255
+ to: "2026-07-29T15:00:00.000Z",
2256
+ },
2257
+ },
2258
+ id: "forecast.read",
2259
+ idempotent: true,
2260
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2261
+ method: "GET",
2262
+ mutates: false,
2263
+ path: "/v1/forecast",
2264
+ principals: ["api-credential", "oauth", "session"],
2265
+ problems: ["invalid_request"],
2266
+ query: forecastRequestSchema,
2267
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2268
+ ? API_UNUSED_RESPONSE_SCHEMA
2269
+ : forecastSchema,
2270
+ scopes: ["forecast:read"],
2271
+ sessionAuthority: "headers",
2272
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2273
+ ? ""
2274
+ : "Forecast upcoming occurrences",
2275
+ surfaces: ["api", "mock"],
2276
+ },
2277
+ {
2278
+ creates: false,
2279
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2280
+ ? ""
2281
+ : "Reads the verified principal's organization-wide prepaid execution position from the authoritative PostgreSQL ledger. Desired and effective revisions remain distinct, and pending stays true until D1 records PostgreSQL confirmation. Amounts are exact integer microdollars encoded as decimal strings; currency is USD and scale is six. Reserved credit has already been committed to a logical attempt but is not yet a settled debit. A missing hard cap means the customer elected no execution spending cap, never zero room. Shadow mode records what enforcement would have done without charging or blocking, and the activation boundary prevents retroactive charges.",
2282
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2283
+ ? {}
2284
+ : BILLING_SUMMARY_EXAMPLE,
2285
+ id: "billing.summary",
2286
+ idempotent: true,
2287
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2288
+ method: "GET",
2289
+ mutates: false,
2290
+ path: "/v1/billing/summary",
2291
+ principals: ["api-credential", "oauth", "session"],
2292
+ problems: [],
2293
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2294
+ ? API_UNUSED_RESPONSE_SCHEMA
2295
+ : billingSummarySchema,
2296
+ scopes: ["usage:read"],
2297
+ sessionAuthority: "headers",
2298
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2299
+ ? ""
2300
+ : "Read exact execution-credit state",
2301
+ surfaces: ["api", "mock"],
2302
+ },
2303
+ BILLING_NOTICE_LIST_OPERATION,
2304
+ BILLING_NOTIFICATION_SETTINGS_OPERATION,
2305
+ BILLING_NOTIFICATION_SETTINGS_UPDATE_OPERATION,
2306
+ withBillingFundingContract({
2307
+ creates: false,
2308
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2309
+ ? ""
2310
+ : "Reads the verified principal's authoritative execution-funding position, including available and reserved credit, amount owed, recurring project fees, the current UTC month's automatic-charge ceiling and its settled, pending and remaining gross authority, and bounded payment history. Manual purchases and project subscriptions are separately authorized and never consume the automatic ceiling. Pending gross charges include applicable tax; refunds never restore monthly automatic purchasing authority. Receipt and payment links are limited to supported provider-hosted HTTPS URLs.",
2311
+ id: "billing.funding",
2312
+ idempotent: true,
2313
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2314
+ method: "GET",
2315
+ mutates: false,
2316
+ path: "/v1/billing/funding",
2317
+ principals: ["api-credential", "oauth", "session"],
2318
+ problems: ["service_unavailable"],
2319
+ scopes: ["usage:read"],
2320
+ sessionAuthority: "headers",
2321
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2322
+ ? ""
2323
+ : "Read execution funding and payments",
2324
+ surfaces: ["api", "mock"],
2325
+ }),
2326
+ {
2327
+ creates: false,
2328
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2329
+ ? ""
2330
+ : "Previews an execution-credit purchase of at least USD 10 without creating a provider payment or granting credit. The quote binds its exact credit and current funding revision; tax and gross remain null with calculated-at-checkout status until an idempotent confirmed purchase creates authenticated hosted Checkout. This manual purchase has separate authority and never consumes the automatic execution top-up ceiling.",
2331
+ environments: ["live"],
2332
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2333
+ ? {}
2334
+ : BILLING_FUNDING_QUOTE_EXAMPLE,
2335
+ id: "billing.fundingquote",
2336
+ idempotent: false,
2337
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2338
+ method: "POST",
2339
+ mutates: false,
2340
+ path: "/v1/billing/funding/quote",
2341
+ principals: ["api-credential", "oauth", "session"],
2342
+ problems: [
2343
+ "invalid_request",
2344
+ "revision_conflict",
2345
+ "service_unavailable",
2346
+ "state_conflict",
2347
+ "test_to_live_escalation",
2348
+ ],
2349
+ request: billingFundingQuoteRequestSchema,
2350
+ requestExample: globalThis
2351
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2352
+ ? {}
2353
+ : {
2354
+ credit: { currency: "USD", microdollars: "10000000", scale: 6 },
2355
+ },
2356
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2357
+ ? API_UNUSED_RESPONSE_SCHEMA
2358
+ : billingFundingQuoteSchema,
2359
+ scopes: ["billing:write"],
2360
+ sessionAuthority: "headers",
2361
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2362
+ ? ""
2363
+ : "Preview manual execution funding",
2364
+ surfaces: ["api", "mock"],
2365
+ },
2366
+ withBillingFundingContract({
2367
+ creates: true,
2368
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2369
+ ? ""
2370
+ : "Confirms one exact manual execution-credit quote and creates or replays its durable payment operation. Billing-owner authority and explicit agent approval apply; the Idempotency-Key preserves one payment identity across retries. Manual funding stays outside the automatic-charge ceiling. A browser redirect never grants credit: only authenticated provider reconciliation can move the operation to paid and grant its exact execution credit once, while the operation reports provider-confirmed tax and gross when known.",
2371
+ environments: ["live"],
2372
+ id: "billing.purchase",
2373
+ idempotent: true,
2374
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2375
+ method: "POST",
2376
+ mutates: true,
2377
+ path: "/v1/billing/funding/purchase",
2378
+ principals: ["api-credential", "oauth", "session"],
2379
+ problems: [
2380
+ "idempotency_key_reused",
2381
+ "invalid_request",
2382
+ "not_found",
2383
+ "revision_conflict",
2384
+ "service_unavailable",
2385
+ "state_conflict",
2386
+ "test_to_live_escalation",
2387
+ ],
2388
+ request: billingPurchaseRequestSchema,
2389
+ requestExample: globalThis
2390
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2391
+ ? {}
2392
+ : {
2393
+ confirmed: true,
2394
+ expectedRevision: 3,
2395
+ quote: "funding-quote-example",
2396
+ },
2397
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
2398
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2399
+ ? {}
2400
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
2401
+ scopes: ["billing:write"],
2402
+ sessionAuthority: "headers",
2403
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2404
+ ? ""
2405
+ : "Confirm manual execution funding",
2406
+ surfaces: ["api", "mock"],
2407
+ }),
2408
+ withBillingFundingContract({
2409
+ creates: false,
2410
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2411
+ ? ""
2412
+ : "Replaces the billing owner's exact calendar-month ceiling for automatic execution-credit charges, or turns automatic payment authority off with null. The expected revision prevents stale authority changes, and the Idempotency-Key makes retries converge. This command requires explicit agent approval because it changes payment authority. Tax and pending gross commitments consume the ceiling; manual purchases and project subscriptions do not. Refunds do not restore authority already used in that UTC month. USD 50 is the suggested editable default, not a platform maximum.",
2413
+ environments: ["live"],
2414
+ id: "billing.ceiling",
2415
+ idempotent: true,
2416
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2417
+ method: "PATCH",
2418
+ mutates: true,
2419
+ path: "/v1/billing/funding/ceiling",
2420
+ principals: ["api-credential", "oauth", "session"],
2421
+ problems: [
2422
+ "idempotency_key_reused",
2423
+ "invalid_request",
2424
+ "revision_conflict",
2425
+ "service_unavailable",
2426
+ "state_conflict",
2427
+ "test_to_live_escalation",
2428
+ ],
2429
+ request: billingCeilingUpdateRequestSchema,
2430
+ requestExample: globalThis
2431
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2432
+ ? {}
2433
+ : {
2434
+ automaticExecutionTopUpCeiling: {
2435
+ currency: "USD",
2436
+ microdollars: "50000000",
2437
+ scale: 6,
2438
+ },
2439
+ expectedRevision: 3,
2440
+ },
2441
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
2442
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2443
+ ? {}
2444
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
2445
+ scopes: ["billing:write"],
2446
+ sessionAuthority: "headers",
2447
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2448
+ ? ""
2449
+ : "Set the automatic payment ceiling",
2450
+ surfaces: ["api", "mock"],
2451
+ }),
2452
+ BILLING_AUTO_TOP_UP_PREVIEW_OPERATION,
2453
+ BILLING_AUTO_TOP_UP_APPLY_OPERATION,
2454
+ {
2455
+ creates: true,
2456
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2457
+ ? ""
2458
+ : "Records an explicitly approved billing-owner request for operator review of unused purchased execution credit. It never submits a refund, cashes out credit or grants an MCP cash-out path; the Idempotency-Key preserves one request across retries. Trial credit has no cash value, provider submission remains an operator action, and any later refund does not restore automatic purchasing authority for the month.",
2459
+ environments: ["live"],
2460
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2461
+ ? {}
2462
+ : {
2463
+ amount: { currency: "USD", microdollars: "5000000", scale: 6 },
2464
+ id: "refund-request-example",
2465
+ paymentOperation: "funding-operation-example",
2466
+ requestedAt: "2026-09-10T12:10:00.000Z",
2467
+ state: "operator-review-pending",
2468
+ },
2469
+ id: "billing.refundrequest",
2470
+ idempotent: true,
2471
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2472
+ method: "POST",
2473
+ mutates: true,
2474
+ path: "/v1/billing/funding/refunds",
2475
+ principals: ["api-credential", "oauth", "session"],
2476
+ problems: [
2477
+ "idempotency_key_reused",
2478
+ "invalid_request",
2479
+ "not_found",
2480
+ "service_unavailable",
2481
+ "state_conflict",
2482
+ "test_to_live_escalation",
2483
+ ],
2484
+ request: billingRefundRequestCreateSchema,
2485
+ requestExample: globalThis
2486
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2487
+ ? {}
2488
+ : {
2489
+ amount: { currency: "USD", microdollars: "5000000", scale: 6 },
2490
+ confirmed: true,
2491
+ paymentOperation: "funding-operation-example",
2492
+ reason: "Duplicate manual purchase",
2493
+ },
2494
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
2495
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2496
+ ? API_UNUSED_RESPONSE_SCHEMA
2497
+ : billingRefundRequestViewSchema,
2498
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2499
+ ? {}
2500
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
2501
+ scopes: ["billing:write"],
2502
+ sessionAuthority: "headers",
2503
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2504
+ ? ""
2505
+ : "Request operator-reviewed refund",
2506
+ surfaces: ["api", "mock"],
2507
+ },
2508
+ withBillingFundingContract({
2509
+ creates: false,
2510
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2511
+ ? ""
2512
+ : "Records an already-made external operator decision on a pending unused-credit refund request. Completion verifies an existing Stripe refund by authenticated provider read before applying the exact credit, tax and gross adjustment; it never creates a provider refund. Decline releases the reserved credit without contacting the provider. The Idempotency-Key makes either decision converge across retries.",
2513
+ environments: ["live"],
2514
+ id: "billing.refundresolution",
2515
+ idempotent: true,
2516
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2517
+ method: "PATCH",
2518
+ mutates: true,
2519
+ path: "/v1/billing/funding/refunds/{refundRequest}",
2520
+ principals: ["api-credential", "oauth", "session"],
2521
+ problems: [
2522
+ "idempotency_key_reused",
2523
+ "invalid_request",
2524
+ "not_found",
2525
+ "service_unavailable",
2526
+ "state_conflict",
2527
+ "test_to_live_escalation",
2528
+ ],
2529
+ request: billingRefundResolutionRequestSchema,
2530
+ requestExample: globalThis
2531
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2532
+ ? {}
2533
+ : {
2534
+ confirmed: true,
2535
+ decision: "declined",
2536
+ },
2537
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
2538
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2539
+ ? {}
2540
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
2541
+ scopes: ["billing:write"],
2542
+ sessionAuthority: "headers",
2543
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2544
+ ? ""
2545
+ : "Record a reviewed refund decision",
2546
+ surfaces: ["api", "mock"],
2547
+ }),
2548
+ {
2549
+ creates: false,
2550
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2551
+ ? ""
2552
+ : "Reads named included and subscribed project access, paid-through and grace deadlines, separate monthly fees, pending provider actions and desired/effective revisions.",
2553
+ id: "billing.projects",
2554
+ method: "GET",
2555
+ path: "/v1/billing/projects",
2556
+ idempotent: true,
2557
+ mutates: false,
2558
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2559
+ principals: ["api-credential", "oauth", "session"],
2560
+ scopes: ["usage:read"],
2561
+ sessionAuthority: "headers",
2562
+ surfaces: ["api", "mock"],
2563
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2564
+ ? API_UNUSED_RESPONSE_SCHEMA
2565
+ : projectBillingStateSchema,
2566
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2567
+ ? {}
2568
+ : PROJECT_BILLING_EXAMPLE,
2569
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2570
+ ? ""
2571
+ : "Read named project billing access",
2572
+ problems: [
2573
+ "service_unavailable",
2574
+ "state_conflict",
2575
+ "not_found",
2576
+ "revision_conflict",
2577
+ "test_to_live_escalation",
2578
+ ],
2579
+ },
2580
+ {
2581
+ creates: false,
2582
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2583
+ ? ""
2584
+ : "Previews one named project addition, paid-through cancellation or included-slot transfer without authorizing a charge. Quotes expire after five minutes and bind the current commercial revision. Amounts describe project fees; Stripe Checkout shows any applicable tax before confirmation.",
2585
+ id: "billing.quote",
2586
+ method: "POST",
2587
+ path: "/v1/billing/projects/quote",
2588
+ idempotent: false,
2589
+ mutates: false,
2590
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2591
+ principals: ["api-credential", "oauth", "session"],
2592
+ scopes: ["billing:write"],
2593
+ sessionAuthority: "headers",
2594
+ surfaces: ["api", "mock"],
2595
+ environments: ["live"],
2596
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2597
+ ? API_UNUSED_RESPONSE_SCHEMA
2598
+ : projectBillingQuoteSchema,
2599
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2600
+ ? {}
2601
+ : PROJECT_BILLING_QUOTE_EXAMPLE,
2602
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2603
+ ? ""
2604
+ : "Preview a named project billing change",
2605
+ problems: [
2606
+ "service_unavailable",
2607
+ "state_conflict",
2608
+ "not_found",
2609
+ "revision_conflict",
2610
+ "test_to_live_escalation",
2611
+ ],
2612
+ request: projectBillingQuoteRequestSchema,
2613
+ requestExample: globalThis
2614
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2615
+ ? {}
2616
+ : {
2617
+ action: "add",
2618
+ project: "proj_00000000000000000000000000",
2619
+ },
2620
+ },
2621
+ {
2622
+ creates: false,
2623
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2624
+ ? ""
2625
+ : "Confirms the exact named-project quote and recurring commitment. Additional access activates only after authenticated successful provider payment; cancellation preserves paid-through access without a refund or renewal grace. Included transfer never subscribes the formerly included project. Retries retain the same operation and payment identity.",
2626
+ id: "billing.change",
2627
+ method: "POST",
2628
+ path: "/v1/billing/projects/change",
2629
+ idempotent: true,
1007
2630
  mutates: true,
1008
- path: "/v1/credentials/{credentialId}",
1009
- conditionalScopes: ["credentials:administer"],
2631
+ mcp: { destructive: false, kind: "tool", openWorld: false },
1010
2632
  principals: ["api-credential", "oauth", "session"],
1011
- problems: ["invalid_request", "not_found", "scope_missing"],
1012
- response: credentialRevokedSchema,
1013
- scopes: ["credentials:write"],
2633
+ scopes: ["billing:write"],
1014
2634
  sessionAuthority: "headers",
1015
- summary: "Revoke an API credential",
1016
2635
  surfaces: ["api", "mock"],
2636
+ environments: ["live"],
2637
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2638
+ ? API_UNUSED_RESPONSE_SCHEMA
2639
+ : projectBillingStateSchema,
2640
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2641
+ ? {}
2642
+ : PROJECT_BILLING_EXAMPLE,
2643
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2644
+ ? ""
2645
+ : "Confirm a quoted project billing change",
2646
+ problems: [
2647
+ "service_unavailable",
2648
+ "idempotency_key_reused",
2649
+ "state_conflict",
2650
+ "not_found",
2651
+ "revision_conflict",
2652
+ "test_to_live_escalation",
2653
+ ],
2654
+ request: projectBillingChangeRequestSchema,
2655
+ requestExample: globalThis
2656
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2657
+ ? {}
2658
+ : {
2659
+ quote: "quote-example",
2660
+ expectedRevision: 2,
2661
+ confirmed: true,
2662
+ },
2663
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
1017
2664
  },
1018
2665
  {
1019
- creates: true,
1020
- description: "Creates a schedule and returns it together with its first planned occurrence. Give exactly one of `at`, `delaySeconds`, `everySeconds` and `cron`. An optional `partitionKey` selects a fairness lane inside this project and environment; it is fixed after create. Add a verified `endpoint` to deliver each occurrence there; optional JSON `data` is encrypted before PostgreSQL persistence and is placed in the signed callback, never returned by schedule reads. `at` and `delaySeconds` fire once; a delay is converted to an absolute instant when the request is accepted, so a schedule created either way reads back the same afterwards. `everySeconds` is a fixed duration and its first occurrence falls one interval after acceptance — it stays the same length across a daylight-saving change, and takes no timezone for that reason. `cron` is a wall clock: it is read against the IANA `timeZone` sent with it, `UTC` when none is, and the first occurrence is the first instant the expression names after acceptance. Where the clocks go forward and the wall time named does not exist that day, the occurrence falls at the first instant after the gap; where they go back and it happens twice, it falls once, at the earlier of the two. A recurring schedule is materialized one occurrence at a time: the next one is planned once the current one is due, so a read always shows one occurrence still to come. The organization, project and environment come from the verified principal; a body cannot name them, and the endpoint must belong to the same tuple, so a credential issued for one project can only ever create schedules in that project. Send an `Idempotency-Key` to make a retry safe: the identical request returns the schedule that key already created, marked `Idempotency-Replayed: true`, and creates nothing further; the same key with a different request is refused `idempotency_key_reused`. A replay reports the schedule **as it stands now**, not a frozen copy of the first response — if it was paused in between, the replay says so.",
1021
- example: {
1022
- occurrence: {
1023
- attemptCount: 0,
1024
- generation: 1,
1025
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1026
- plannedFor: "2026-07-28T15:00:00.000Z",
1027
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1028
- sequence: 1,
1029
- state: "planned",
1030
- },
1031
- schedule: {
1032
- createdAt: "2026-07-28T14:59:00.000Z",
1033
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1034
- generation: 1,
1035
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1036
- latencyClass: "realtime",
1037
- partitionKey: "campaign.spring",
1038
- recurrence: { kind: "at" },
1039
- status: "active",
1040
- updatedAt: "2026-07-28T14:59:00.000Z",
1041
- version: 1,
1042
- },
1043
- },
1044
- id: "schedules.create",
1045
- // Additive: it brings a schedule into existence and takes nothing away.
1046
- // A callback schedule causes a future request to the verified external
1047
- // endpoint. It does not destructively modify that system, but it does act
1048
- // beyond Greatwait, so MCP clients must receive the open-world hint.
1049
- mcp: { destructive: false, kind: "tool", openWorld: true },
1050
- // False even though this operation reads `Idempotency-Key`, because the
1051
- // header is optional and this flag is what a client reads before deciding
1052
- // whether a blind retry is safe. It is not: a retry without the key creates
1053
- // a second schedule. What says the protection is available is
1054
- // `requestHeaders`, which publishes the key rather than promising it was
1055
- // used.
1056
- idempotent: false,
2666
+ creates: false,
2667
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2668
+ ? ""
2669
+ : "Creates a short-lived Stripe-hosted payment-method and invoice recovery session for the verified organization. It does not grant execution credit or additional project access.",
2670
+ id: "billing.portal",
1057
2671
  method: "POST",
2672
+ path: "/v1/billing/portal",
2673
+ idempotent: false,
1058
2674
  mutates: true,
1059
- path: "/v1/schedules",
2675
+ mcp: { destructive: false, kind: "tool", openWorld: false },
1060
2676
  principals: ["api-credential", "oauth", "session"],
2677
+ scopes: ["billing:write"],
2678
+ sessionAuthority: "headers",
2679
+ surfaces: ["api", "mock"],
2680
+ environments: ["live"],
2681
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2682
+ ? API_UNUSED_RESPONSE_SCHEMA
2683
+ : billingPortalSchema,
2684
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2685
+ ? {}
2686
+ : { url: "https://billing.stripe.com/p/session/example" },
2687
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2688
+ ? ""
2689
+ : "Open hosted payment recovery",
1061
2690
  problems: [
1062
- // **Reachable in every deployment, and undeclared until W9-03.** The
1063
- // route refuses here when the endpoint's status is not one this
1064
- // deployment will send to — under the default `not-required` ownership
1065
- // policy that still covers a `disabled` destination, and under
1066
- // `required` it covers a `pending` one as well. An operation that can
1067
- // refuse for a code it never mentions is a document that lies, and a
1068
- // published quickstart could not tell a reader what to do about a
1069
- // refusal the contract said was impossible.
1070
- "endpoint_unverified",
1071
- "idempotency_key_reused",
1072
- "invalid_request",
1073
- "not_found",
1074
- // The organization ceiling, the same code and the same shape
1075
- // `projects.create` and `endpoints.create` use. A plan may bound the
1076
- // live schedules an organization holds, the distinct partition keys it
1077
- // has live, and how large a `data` body it may carry; all three refuse
1078
- // here rather than truncating, because a schedule created without the
1079
- // body the caller sent is not the schedule they asked for.
1080
- "plan_limit_reached",
1081
2691
  "service_unavailable",
2692
+ "state_conflict",
2693
+ "not_found",
2694
+ "revision_conflict",
2695
+ "test_to_live_escalation",
1082
2696
  ],
1083
- request: scheduleRequestSchema,
1084
- requestExample: {
1085
- cron: "0 9 * * 1-5",
1086
- data: { report: "daily" },
1087
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1088
- partitionKey: "campaign.spring",
1089
- timeZone: "Europe/London",
1090
- },
1091
- requestHeaders: idempotencyRequestHeaderSchema,
1092
- response: scheduleViewSchema,
1093
- responseHeaders: replayedResponseHeaderSchema,
1094
- scopes: ["schedules:write"],
2697
+ },
2698
+ {
2699
+ creates: false,
2700
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2701
+ ? ""
2702
+ : "Advances at most one due, already-authorized desired billing-policy revision for the caller's organization into PostgreSQL, then returns the same exact desired/effective summary as billing.summary. The command never changes the desired document. A transport failure is recorded for bounded retry and remains pending. Repeating the command may advance the next queued revision, so each call requires approval.",
2703
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2704
+ ? {}
2705
+ : BILLING_SUMMARY_EXAMPLE,
2706
+ environments: ["live"],
2707
+ id: "billing.reconcile",
2708
+ idempotent: false,
2709
+ mcp: { destructive: false, kind: "tool", openWorld: false },
2710
+ method: "POST",
2711
+ mutates: true,
2712
+ path: "/v1/billing/reconcile",
2713
+ principals: ["api-credential", "oauth", "session"],
2714
+ problems: ["service_unavailable", "test_to_live_escalation"],
2715
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2716
+ ? API_UNUSED_RESPONSE_SCHEMA
2717
+ : billingSummarySchema,
2718
+ scopes: ["billing:write"],
1095
2719
  sessionAuthority: "headers",
1096
- summary: "Create a schedule",
2720
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2721
+ ? ""
2722
+ : "Advance one pending billing policy",
1097
2723
  surfaces: ["api", "mock"],
1098
2724
  },
1099
2725
  {
1100
2726
  creates: false,
1101
- description: "Reads one schedule and its next occurrence from the partition that owns it. A schedule belonging to another organization, project or environment answers not_found rather than a refusal that would confirm it exists. The response carries the schedule's version as a strong ETag; send it back in `If-Match` to make a later write conditional on nothing having changed in between.",
1102
- example: {
1103
- occurrence: {
1104
- attemptCount: 0,
1105
- generation: 1,
1106
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1107
- plannedFor: "2026-07-28T15:00:00.000Z",
1108
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1109
- sequence: 1,
1110
- state: "planned",
1111
- },
1112
- schedule: {
1113
- createdAt: "2026-07-28T14:59:00.000Z",
1114
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1115
- generation: 1,
1116
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1117
- latencyClass: "realtime",
1118
- partitionKey: "campaign.spring",
1119
- recurrence: { kind: "at" },
1120
- status: "active",
1121
- updatedAt: "2026-07-28T14:59:00.000Z",
1122
- version: 1,
2727
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2728
+ ? ""
2729
+ : "Replaces the caller organization's advisory execution budget and optional hard execution-spend cap for the current UTC month. Values are exact whole cents encoded as integer microdollars. The expected budget-policy revision prevents a stale editor overwriting a newer choice, and Idempotency-Key makes retrying one intent safe. Null turns that setting off. This command records desired state durably; billing.reconcile advances it to PostgreSQL, and reads remain pending until PostgreSQL confirms it. It never changes automatic top-up authority, purchases credit, or counts subscription payments as execution usage.",
2730
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2731
+ ? {}
2732
+ : {
2733
+ budgetPolicy: {
2734
+ desired: {
2735
+ advisoryBudget: {
2736
+ currency: "USD",
2737
+ microdollars: "25000000",
2738
+ scale: 6,
2739
+ },
2740
+ hardCap: {
2741
+ currency: "USD",
2742
+ microdollars: "50000000",
2743
+ scale: 6,
2744
+ },
2745
+ },
2746
+ desiredRevision: 2,
2747
+ effectiveRevision: 1,
2748
+ pending: true,
2749
+ },
2750
+ freshness: { kind: "authoritative" },
1123
2751
  },
1124
- },
1125
- id: "schedules.read",
2752
+ environments: ["live"],
2753
+ id: "billing.budgets",
1126
2754
  idempotent: true,
1127
2755
  mcp: { destructive: false, kind: "tool", openWorld: false },
1128
- method: "GET",
1129
- mutates: false,
1130
- path: "/v1/schedules/{scheduleId}",
2756
+ method: "PATCH",
2757
+ mutates: true,
2758
+ path: "/v1/billing/budgets",
1131
2759
  principals: ["api-credential", "oauth", "session"],
1132
- problems: ["invalid_request", "not_found"],
1133
- response: scheduleViewSchema,
1134
- responseHeaders: versionResponseHeaderSchema,
1135
- scopes: ["schedules:read"],
2760
+ problems: [
2761
+ "idempotency_key_reused",
2762
+ "invalid_request",
2763
+ "revision_conflict",
2764
+ "service_unavailable",
2765
+ "test_to_live_escalation",
2766
+ ],
2767
+ request: billingBudgetUpdateRequestSchema,
2768
+ requestExample: globalThis
2769
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2770
+ ? {}
2771
+ : {
2772
+ advisoryBudget: {
2773
+ currency: "USD",
2774
+ microdollars: "25000000",
2775
+ scale: 6,
2776
+ },
2777
+ expectedRevision: 1,
2778
+ hardCap: {
2779
+ currency: "USD",
2780
+ microdollars: "50000000",
2781
+ scale: 6,
2782
+ },
2783
+ },
2784
+ requestHeaders: billingBudgetUpdateRequestHeadersSchema,
2785
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2786
+ ? API_UNUSED_RESPONSE_SCHEMA
2787
+ : billingBudgetUpdateResponseSchema,
2788
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
2789
+ ? {}
2790
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
2791
+ scopes: ["billing:write"],
1136
2792
  sessionAuthority: "headers",
1137
- summary: "Read a schedule",
2793
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2794
+ ? ""
2795
+ : "Set execution budgets",
1138
2796
  surfaces: ["api", "mock"],
1139
2797
  },
1140
2798
  {
1141
2799
  creates: false,
1142
- description: "Lists the caller's own schedules, oldest first, one page at a time. Archived schedules are left out: archiving is how a schedule leaves the working set, and a listing that still carried them would make the operation pointless. Items are schedules rather than schedules-with-occurrences, because a cross-partition listing is served from a projection that holds a summary; read a schedule to get its authoritative next occurrence. Every page states whether it is authoritative or projected.",
1143
- example: {
1144
- data: [
1145
- {
1146
- createdAt: "2026-07-28T14:59:00.000Z",
1147
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1148
- generation: 1,
1149
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1150
- latencyClass: "realtime",
1151
- recurrence: { kind: "at" },
1152
- status: "active",
1153
- updatedAt: "2026-07-28T14:59:00.000Z",
1154
- version: 1,
1155
- },
1156
- ],
1157
- // `projected` since W2-06 served this listing from the control-plane
1158
- // directory. `asOf` is the instant the projection was last known to hold
1159
- // everything every partition had handed over, and `lagSeconds` is how long
1160
- // ago that was — so a page states how far behind it may be rather than
1161
- // implying it is current.
1162
- freshness: {
1163
- asOf: "2026-07-28T15:00:00.000Z",
1164
- kind: "projected",
1165
- lagSeconds: 0,
1166
- },
1167
- nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoic2NoXzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
1168
- },
1169
- id: "schedules.list",
2800
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2801
+ ? ""
2802
+ : "Lists the verified principal's organization ledger in immutable sequence order. Each entry is one exact signed microdollar fact with safe attempt, lot, payment-operation and event references. Raw callback data, card data, internal causal keys and ledger detail have no field in the response. The opaque cursor is bound to the principal's organization, project and environment and cannot widen authority.",
2803
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2804
+ ? {}
2805
+ : {
2806
+ data: [
2807
+ {
2808
+ amount: { currency: "USD", microdollars: "-10", scale: 6 },
2809
+ kind: "attempt_debited",
2810
+ period: "2026-09-01T00:00:00.000Z",
2811
+ recordedAt: "2026-09-09T14:00:00.000Z",
2812
+ reference: {
2813
+ attempt: "att_01h8xyz9k2m4n6p8r0t2v4w6y8",
2814
+ event: "billing-attempt-debited-1",
2815
+ },
2816
+ sequence: "42",
2817
+ },
2818
+ ],
2819
+ freshness: { kind: "authoritative" },
2820
+ nextCursor: "eyJhIjowLCJpIjoiNDIiLCJrIjoiOTUxMzU0NmYifQ",
2821
+ },
2822
+ id: "billing.ledger",
1170
2823
  idempotent: true,
1171
2824
  mcp: { destructive: false, kind: "tool", openWorld: false },
1172
2825
  method: "GET",
1173
2826
  mutates: false,
1174
- path: "/v1/schedules",
2827
+ path: "/v1/billing/ledger",
1175
2828
  principals: ["api-credential", "oauth", "session"],
1176
2829
  problems: ["invalid_request"],
1177
- query: pageRequestSchema,
1178
- response: schedulePageSchema,
1179
- scopes: ["schedules:read"],
2830
+ query: billingLedgerRequestSchema,
2831
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2832
+ ? API_UNUSED_RESPONSE_SCHEMA
2833
+ : billingLedgerPageSchema,
2834
+ scopes: ["usage:read"],
1180
2835
  sessionAuthority: "headers",
1181
- summary: "List schedules",
2836
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2837
+ ? ""
2838
+ : "List immutable billing entries",
1182
2839
  surfaces: ["api", "mock"],
1183
2840
  },
1184
2841
  {
1185
2842
  creates: false,
1186
- description: "Counts the occurrences this project and environment expect to fire, in epoch-aligned time buckets, with a latency-class split on every bucket and an optional customer partition-key breakdown. A recurring series contributes every instant it fires inside the window rather than only its next one, and `nextFireCount` reports how many of a bucket's occurrences are a schedule's next firing. The answer states its own freshness and is refused rather than shortened when a partition cannot complete it. It carries counts only: no schedule identifier, callback destination, payload or endpoint detail has a field in the response.",
1187
- example: {
1188
- buckets: [
1189
- {
1190
- byLatencyClass: { bulk: 12, realtime: 3 },
1191
- byPartitionKey: { "campaign.spring": 9, "campaign.winter": 4 },
1192
- count: 15,
1193
- nextFireCount: 4,
1194
- otherPartitionKeyCount: 2,
1195
- start: "2026-07-28T15:00:00.000Z",
2843
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2844
+ ? ""
2845
+ : "Legacy terminal-occurrence volume by UTC day from the authoritative scheduling model. This is an operational outcome aggregate retained for compatibility; it is not the PAYG invoice meter. Billing is per logical delivery attempt, including retries and redeliveries, and is exposed exactly by billing.summary and billing.ledger. Days with no terminal occurrence are absent rather than zero, and the window states which days the answer covers. `from` and `to` are snapped outward to UTC midnight, so an answer always covers whole days.",
2846
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2847
+ ? {}
2848
+ : {
2849
+ bucketSeconds: 86_400,
2850
+ days: [
2851
+ {
2852
+ billableOccurrences: 42,
2853
+ byTerminalState: { succeeded: 40, terminal_failed: 2 },
2854
+ start: "2026-07-28T00:00:00.000Z",
2855
+ },
2856
+ ],
2857
+ freshness: { kind: "authoritative" },
2858
+ totalBillableOccurrences: 42,
2859
+ window: {
2860
+ from: "2026-07-28T00:00:00.000Z",
2861
+ to: "2026-07-29T00:00:00.000Z",
1196
2862
  },
1197
- ],
1198
- freshness: {
1199
- asOf: "2026-07-28T14:58:30.000Z",
1200
- kind: "projected",
1201
- lagSeconds: 90,
1202
2863
  },
1203
- window: {
1204
- bucketSeconds: 1800,
1205
- from: "2026-07-28T15:00:00.000Z",
1206
- to: "2026-07-29T15:00:00.000Z",
1207
- },
1208
- },
1209
- id: "forecast.read",
2864
+ id: "usage.read",
1210
2865
  idempotent: true,
1211
2866
  mcp: { destructive: false, kind: "tool", openWorld: false },
1212
2867
  method: "GET",
1213
2868
  mutates: false,
1214
- path: "/v1/forecast",
2869
+ path: "/v1/usage",
1215
2870
  principals: ["api-credential", "oauth", "session"],
1216
2871
  problems: ["invalid_request"],
1217
- query: forecastRequestSchema,
1218
- response: forecastSchema,
1219
- scopes: ["forecast:read"],
2872
+ query: usageRequestSchema,
2873
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2874
+ ? API_UNUSED_RESPONSE_SCHEMA
2875
+ : usageSchema,
2876
+ scopes: ["usage:read"],
1220
2877
  sessionAuthority: "headers",
1221
- summary: "Forecast upcoming occurrences",
2878
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2879
+ ? ""
2880
+ : "Read terminal occurrence volume by day",
1222
2881
  surfaces: ["api", "mock"],
1223
2882
  },
1224
2883
  {
1225
2884
  creates: false,
1226
- description: "What this project was charged for, by UTC day, from the authoritative scheduling model. One terminal occurrence is one billable unit however many attempts it took, so a schedule that failed four times and succeeded on the fifth appears here once; the attempts it cost are on that occurrence's own attempt history. Days with no billable occurrence are absent rather than zero, and the window states which days the answer covers. `from` and `to` are snapped outward to UTC midnight, so an answer always covers whole days.",
1227
- example: {
1228
- days: [
1229
- {
1230
- billableOccurrences: 42,
1231
- byTerminalState: { succeeded: 40, terminal_failed: 2 },
1232
- start: "2026-07-28T00:00:00.000Z",
1233
- },
1234
- ],
1235
- freshness: { kind: "authoritative" },
1236
- totalBillableOccurrences: 42,
1237
- window: {
1238
- from: "2026-07-28T00:00:00.000Z",
1239
- to: "2026-07-29T00:00:00.000Z",
2885
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2886
+ ? ""
2887
+ : "Reads the verified principal's project timing cohort over the authoritative rolling 24-hour due-time window. Exact 5,000ms and 15,000ms counters include eligible work that has not fired; customer blocks, platform blocks, skipped work and missing evidence stay visible beside the verdict. Values equal to a target meet it, and a threshold with no matured population is unknown. Delivered-sample p95 and p99 lateness are separate observations, including negative early-delivery defects. These are internal operating objectives, not a contractual SLA or service-credit promise.",
2888
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2889
+ ? {}
2890
+ : {
2891
+ customerBlockedCount: 2,
2892
+ deliveredSampleCount: 98,
2893
+ freshness: { kind: "authoritative" },
2894
+ missingEvidenceCount: 1,
2895
+ p95LatenessMs: 4_200,
2896
+ p99LatenessMs: 12_000,
2897
+ platformBlockedCount: 1,
2898
+ policyVersion: "timing-v1",
2899
+ skippedCount: 3,
2900
+ targets: [
2901
+ {
2902
+ breachCount: 5,
2903
+ customerBlockedCount: 2,
2904
+ eligibleOutstandingBreachCount: 1,
2905
+ maturedCount: 100,
2906
+ targetMs: 5_000,
2907
+ verdict: "met",
2908
+ withinTargetCount: 95,
2909
+ },
2910
+ {
2911
+ breachCount: 1,
2912
+ customerBlockedCount: 2,
2913
+ eligibleOutstandingBreachCount: 1,
2914
+ maturedCount: 100,
2915
+ targetMs: 15_000,
2916
+ verdict: "met",
2917
+ withinTargetCount: 99,
2918
+ },
2919
+ ],
2920
+ windowEnd: "2026-09-09T12:00:00.000Z",
2921
+ windowStart: "2026-09-08T12:00:00.000Z",
1240
2922
  },
1241
- },
1242
- id: "usage.read",
2923
+ id: "timing.summary",
1243
2924
  idempotent: true,
1244
2925
  mcp: { destructive: false, kind: "tool", openWorld: false },
1245
2926
  method: "GET",
1246
2927
  mutates: false,
1247
- path: "/v1/usage",
2928
+ path: "/v1/timing/summary",
1248
2929
  principals: ["api-credential", "oauth", "session"],
1249
- problems: ["invalid_request"],
1250
- query: usageRequestSchema,
1251
- response: usageSchema,
2930
+ problems: [],
2931
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2932
+ ? API_UNUSED_RESPONSE_SCHEMA
2933
+ : deliveryTimingSummarySchema,
1252
2934
  scopes: ["usage:read"],
1253
2935
  sessionAuthority: "headers",
1254
- summary: "Read billable usage by day",
2936
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2937
+ ? ""
2938
+ : "Read rolling delivery timing",
1255
2939
  surfaces: ["api", "mock"],
1256
2940
  },
1257
2941
  {
1258
2942
  creates: false,
1259
- description: "The same forecast in the window shape the legacy scheduler's autoscaler already parses, published under a dated version so a consumer can pin it. It exists for one migration and is expected to be withdrawn once that migration completes; `forecast.read` is the shape this product publishes. `byTenant` is the customer partition-key breakdown under its legacy name, and `count` is always the bucket total rather than the named subtotal.",
1260
- example: {
1261
- bucketSeconds: 600,
1262
- buckets: [
1263
- {
1264
- byTenant: { "campaign.spring": 9, "campaign.winter": 4 },
1265
- count: 15,
1266
- nextFireCount: 4,
1267
- otherCount: 2,
1268
- start: "2026-07-28T15:00:00.000Z",
2943
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2944
+ ? ""
2945
+ : "The same forecast in the window shape the legacy scheduler's autoscaler already parses, published under a dated version so a consumer can pin it. It exists for one migration and is expected to be withdrawn once that migration completes; `forecast.read` is the shape this product publishes. `byTenant` is the customer partition-key breakdown under its legacy name, and `count` is always the bucket total rather than the named subtotal.",
2946
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2947
+ ? {}
2948
+ : {
2949
+ bucketSeconds: 600,
2950
+ buckets: [
2951
+ {
2952
+ byTenant: { "campaign.spring": 9, "campaign.winter": 4 },
2953
+ count: 15,
2954
+ nextFireCount: 4,
2955
+ otherCount: 2,
2956
+ start: "2026-07-28T15:00:00.000Z",
2957
+ },
2958
+ ],
2959
+ freshness: {
2960
+ asOf: "2026-07-28T14:58:30.000Z",
2961
+ kind: "projected",
2962
+ lagSeconds: 90,
1269
2963
  },
1270
- ],
1271
- freshness: {
1272
- asOf: "2026-07-28T14:58:30.000Z",
1273
- kind: "projected",
1274
- lagSeconds: 90,
2964
+ version: FORECAST_WINDOW_VERSION,
1275
2965
  },
1276
- version: FORECAST_WINDOW_VERSION,
1277
- },
1278
2966
  id: "forecast.windows",
1279
2967
  idempotent: true,
1280
2968
  // Withheld from MCP rather than published as a tool. It is a compatibility
@@ -1292,30 +2980,38 @@ export const OPERATIONS = [
1292
2980
  principals: ["api-credential", "oauth", "session"],
1293
2981
  problems: ["invalid_request"],
1294
2982
  query: forecastRequestSchema,
1295
- response: forecastWindowsSchema,
2983
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2984
+ ? API_UNUSED_RESPONSE_SCHEMA
2985
+ : forecastWindowsSchema,
1296
2986
  scopes: ["forecast:read"],
1297
2987
  sessionAuthority: "headers",
1298
- summary: "Forecast in the transitional window shape",
2988
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
2989
+ ? ""
2990
+ : "Forecast in the transitional window shape",
1299
2991
  surfaces: ["api", "mock"],
1300
2992
  },
1301
2993
  {
1302
2994
  creates: false,
1303
- description: "Lists the retained occurrences of one schedule from its authoritative Scheduler Partition, ordered by durable creation instant and occurrence identifier so tied timestamps never duplicate or omit a row. The cursor is opaque and scoped to the verified principal's organization, project and environment. Each item is metadata only: callback payloads, destinations, response bodies and signing material have no field in the response.",
1304
- example: {
1305
- data: [
1306
- {
1307
- attemptCount: 1,
1308
- generation: 1,
1309
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1310
- plannedFor: "2026-07-28T15:00:00.000Z",
1311
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1312
- sequence: 1,
1313
- state: "retry_wait",
1314
- },
1315
- ],
1316
- freshness: { kind: "authoritative" },
1317
- nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoib2NjXzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
1318
- },
2995
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
2996
+ ? ""
2997
+ : "Lists the retained occurrences of one schedule from its authoritative Scheduler Partition, ordered by durable creation instant and occurrence identifier so tied timestamps never duplicate or omit a row — oldest first unless `order=newest`, which walks from the most recent. A run that an edit replaced before it ran is left out; a run skipped because the previous one was still going is listed. The cursor is opaque, scoped to the verified principal's organization, project and environment, and to the order it was issued under. Each item is metadata only: callback payloads, destinations, response bodies and signing material have no field in the response.",
2998
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
2999
+ ? {}
3000
+ : {
3001
+ data: [
3002
+ {
3003
+ attemptCount: 1,
3004
+ generation: 1,
3005
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3006
+ plannedFor: "2026-07-28T15:00:00.000Z",
3007
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3008
+ sequence: 1,
3009
+ state: "retry_wait",
3010
+ },
3011
+ ],
3012
+ freshness: { kind: "authoritative" },
3013
+ nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoib2NjXzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
3014
+ },
1319
3015
  id: "occurrences.list",
1320
3016
  idempotent: true,
1321
3017
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -1324,29 +3020,83 @@ export const OPERATIONS = [
1324
3020
  path: "/v1/schedules/{scheduleId}/occurrences",
1325
3021
  principals: ["api-credential", "oauth", "session"],
1326
3022
  problems: ["invalid_request", "not_found"],
1327
- query: pageRequestSchema,
1328
- response: occurrencePageSchema,
3023
+ query: historyPageRequestSchema,
3024
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3025
+ ? API_UNUSED_RESPONSE_SCHEMA
3026
+ : occurrencePageSchema,
1329
3027
  scopes: ["occurrences:read"],
1330
3028
  sessionAuthority: "headers",
1331
- summary: "List retained occurrences",
3029
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3030
+ ? ""
3031
+ : "List retained occurrences",
1332
3032
  surfaces: ["api", "mock"],
1333
3033
  },
1334
3034
  {
1335
3035
  creates: false,
1336
- description: "Reads one retained occurrence from the Scheduler Partition that owns its schedule. The response explicitly states that it is authoritative; a stale D1 directory or schedule projection is used only to find the partition and never as occurrence truth. An identifier outside the verified principal's organization, project or environment is indistinguishable from an absent occurrence.",
1337
- example: {
1338
- freshness: { kind: "authoritative" },
1339
- occurrence: {
1340
- attemptCount: 2,
1341
- generation: 1,
1342
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1343
- plannedFor: "2026-07-28T15:00:00.000Z",
1344
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1345
- sequence: 1,
1346
- settledAt: "2026-07-28T15:02:00.000Z",
1347
- state: "terminal_failed",
3036
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3037
+ ? ""
3038
+ : "Lists every retained occurrence in the verified principal's project and environment, newest first by planned instant with the occurrence identifier breaking millisecond ties. Optional endpoint, schedule, half-open date-range and outcome filters may be combined; the endpoint is resolved through the schedules that belong to the same authority. The opaque cursor belongs to this operation and the exact normalized filters that issued it, so it cannot be replayed under another view. Every page publishes the authoritative earliest retained instant for the caller's effective plan. Each item is metadata only: callback payloads, destinations, response bodies and signing material have no field in the response.",
3039
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3040
+ ? {}
3041
+ : {
3042
+ data: [
3043
+ {
3044
+ attemptCount: 1,
3045
+ generation: 1,
3046
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3047
+ plannedFor: "2026-07-28T15:00:00.000Z",
3048
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3049
+ sequence: 1,
3050
+ settledAt: "2026-07-28T15:00:01.000Z",
3051
+ state: "succeeded",
3052
+ },
3053
+ ],
3054
+ freshness: { kind: "authoritative" },
3055
+ retention: { from: "2026-07-21T15:00:00.000Z" },
3056
+ },
3057
+ id: "executions.list",
3058
+ idempotent: true,
3059
+ mcp: { destructive: false, kind: "tool", openWorld: false },
3060
+ method: "GET",
3061
+ mutates: false,
3062
+ path: "/v1/occurrences",
3063
+ principals: ["api-credential", "oauth", "session"],
3064
+ problems: ["invalid_request"],
3065
+ query: projectOccurrenceListRequestSchema,
3066
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3067
+ ? API_UNUSED_RESPONSE_SCHEMA
3068
+ : projectOccurrencePageSchema,
3069
+ scopes: ["occurrences:read"],
3070
+ sessionAuthority: "headers",
3071
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3072
+ ? ""
3073
+ : "List project executions",
3074
+ surfaces: ["api", "mock"],
3075
+ },
3076
+ {
3077
+ creates: false,
3078
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3079
+ ? ""
3080
+ : "Reads one retained occurrence from the PostgreSQL authority that owns its schedule. Trusted first-outbound timing is optional for records that predate substantiation; when present, firstAttemptLatenessMs is signed and a negative value exposes an early-delivery defect rather than being clamped to zero. Timing eligibility states whether a customer restriction excluded the occurrence from the internal target cohort. An identifier outside the verified principal's organization, project or environment is indistinguishable from an absent occurrence.",
3081
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3082
+ ? {}
3083
+ : {
3084
+ freshness: { kind: "authoritative" },
3085
+ occurrence: {
3086
+ attemptCount: 2,
3087
+ firstAttemptLatenessMs: 0,
3088
+ firstAttemptStartedAt: "2026-07-28T15:00:00.000Z",
3089
+ generation: 1,
3090
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3091
+ plannedFor: "2026-07-28T15:00:00.000Z",
3092
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3093
+ sequence: 1,
3094
+ settledAt: "2026-07-28T15:02:00.000Z",
3095
+ state: "terminal_failed",
3096
+ timingEligibility: "eligible",
3097
+ timingPolicyVersion: "payg-v1",
3098
+ },
1348
3099
  },
1349
- },
1350
3100
  id: "occurrences.read",
1351
3101
  idempotent: true,
1352
3102
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -1355,35 +3105,47 @@ export const OPERATIONS = [
1355
3105
  path: "/v1/schedules/{scheduleId}/occurrences/{occurrenceId}",
1356
3106
  principals: ["api-credential", "oauth", "session"],
1357
3107
  problems: ["invalid_request", "not_found"],
1358
- response: occurrenceViewSchema,
3108
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3109
+ ? API_UNUSED_RESPONSE_SCHEMA
3110
+ : occurrenceViewSchema,
1359
3111
  scopes: ["occurrences:read"],
1360
3112
  sessionAuthority: "headers",
1361
- summary: "Read an occurrence",
3113
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3114
+ ? ""
3115
+ : "Read an occurrence",
1362
3116
  surfaces: ["api", "mock"],
1363
3117
  },
1364
3118
  {
1365
3119
  creates: false,
1366
- description: "Lists the immutable attempts retained under one occurrence, ordered by start instant and attempt identifier so equal timestamps have a stable position. The owning Scheduler Partition is authoritative and every page says so. Results expose only bounded outcome, response-status, duration, diagnostic, remediation and redelivery-cause metadata; callback payloads, response bodies, destinations, signing material, secrets and transport traces are structurally absent.",
1367
- example: {
1368
- data: [
1369
- {
1370
- attemptNumber: 1,
1371
- classifiedAt: "2026-07-28T15:00:00.071Z",
1372
- delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
1373
- diagnostic: "http_retryable",
1374
- durationMs: 71,
1375
- id: "att_01h8xyz9k2m4n6p8r0t2v4w6y8",
1376
- occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1377
- remediation: "review_retry_policy",
1378
- responseStatus: 503,
1379
- startedAt: "2026-07-28T15:00:00.000Z",
1380
- state: "retryable_failure",
1381
- trigger: { kind: "automatic" },
1382
- },
1383
- ],
1384
- freshness: { kind: "authoritative" },
1385
- nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoiYXR0XzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
1386
- },
3120
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3121
+ ? ""
3122
+ : "Lists the immutable attempts retained under one occurrence, ordered by start instant and attempt identifier so equal timestamps have a stable position. The PostgreSQL authority answers every page. Optional first-outbound fields carry trusted occurrence timing and its pinned policy; absence means unknown, never zero. Results expose only bounded outcome, response-status, duration, timing, diagnostic, remediation and redelivery-cause metadata; callback payloads, response bodies, destinations, signing material, secrets and transport traces are structurally absent.",
3123
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3124
+ ? {}
3125
+ : {
3126
+ data: [
3127
+ {
3128
+ attemptNumber: 1,
3129
+ classifiedAt: "2026-07-28T15:00:00.071Z",
3130
+ delivery: "dlv_01h8xyz9k2m4n6p8r0t2v4w6y8",
3131
+ diagnostic: "http_retryable",
3132
+ durationMs: 71,
3133
+ firstAttemptLatenessMs: 0,
3134
+ firstAttemptStartedAt: "2026-07-28T15:00:00.000Z",
3135
+ id: "att_01h8xyz9k2m4n6p8r0t2v4w6y8",
3136
+ occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3137
+ remediation: "review_retry_policy",
3138
+ responseStatus: 503,
3139
+ startedAt: "2026-07-28T15:00:00.000Z",
3140
+ state: "retryable_failure",
3141
+ timingEligibility: "eligible",
3142
+ timingPolicyVersion: "payg-v1",
3143
+ trigger: { kind: "automatic" },
3144
+ },
3145
+ ],
3146
+ freshness: { kind: "authoritative" },
3147
+ nextCursor: "eyJhIjoxNzg1MjUwODAwMDAwLCJpIjoiYXR0XzAxaDh4eXo5azJtNG42cDhyMHQydjR3Nnk4IiwiayI6Ijk1MTM1NDZmIn0",
3148
+ },
1387
3149
  id: "attempts.list",
1388
3150
  idempotent: true,
1389
3151
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -1393,31 +3155,43 @@ export const OPERATIONS = [
1393
3155
  principals: ["api-credential", "oauth", "session"],
1394
3156
  problems: ["invalid_request", "not_found"],
1395
3157
  query: pageRequestSchema,
1396
- response: attemptPageSchema,
3158
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3159
+ ? API_UNUSED_RESPONSE_SCHEMA
3160
+ : attemptPageSchema,
1397
3161
  scopes: ["occurrences:read"],
1398
3162
  sessionAuthority: "headers",
1399
- summary: "List delivery attempts",
3163
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3164
+ ? ""
3165
+ : "List delivery attempts",
1400
3166
  surfaces: ["api", "mock"],
1401
3167
  },
1402
3168
  {
1403
3169
  creates: false,
1404
- description: "Reads one immutable delivery attempt from its occurrence's authoritative Scheduler Partition. Ambiguous means the receiver may have acted and is never rewritten into certainty without durable result evidence. The bounded response omits callback payloads, response bodies, destinations, signing material, secrets and raw transport failures by construction.",
1405
- example: {
1406
- attempt: {
1407
- attemptNumber: 2,
1408
- classifiedAt: "2026-07-28T15:02:00.000Z",
1409
- delivery: "dlv_11h8xyz9k2m4n6p8r0t2v4w6y8",
1410
- diagnostic: "network_ambiguous",
1411
- durationMs: 10_000,
1412
- id: "att_11h8xyz9k2m4n6p8r0t2v4w6y8",
1413
- occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1414
- remediation: "review_before_redelivery",
1415
- startedAt: "2026-07-28T15:01:50.000Z",
1416
- state: "ambiguous",
1417
- trigger: { kind: "automatic" },
1418
- },
1419
- freshness: { kind: "authoritative" },
1420
- },
3170
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3171
+ ? ""
3172
+ : "Reads one immutable delivery attempt from its occurrence's PostgreSQL authority. Ambiguous means the receiver may have acted and is never rewritten into certainty without durable result evidence. Optional first-outbound fields come only from trusted transport evidence and absence means unknown, never zero. The bounded response omits callback payloads, response bodies, destinations, signing material, secrets and raw transport failures by construction.",
3173
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3174
+ ? {}
3175
+ : {
3176
+ attempt: {
3177
+ attemptNumber: 2,
3178
+ classifiedAt: "2026-07-28T15:02:00.000Z",
3179
+ delivery: "dlv_11h8xyz9k2m4n6p8r0t2v4w6y8",
3180
+ diagnostic: "network_ambiguous",
3181
+ durationMs: 10_000,
3182
+ firstAttemptLatenessMs: 0,
3183
+ firstAttemptStartedAt: "2026-07-28T15:00:00.000Z",
3184
+ id: "att_11h8xyz9k2m4n6p8r0t2v4w6y8",
3185
+ occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3186
+ remediation: "review_before_redelivery",
3187
+ startedAt: "2026-07-28T15:01:50.000Z",
3188
+ state: "ambiguous",
3189
+ timingEligibility: "eligible",
3190
+ timingPolicyVersion: "payg-v1",
3191
+ trigger: { kind: "automatic" },
3192
+ },
3193
+ freshness: { kind: "authoritative" },
3194
+ },
1421
3195
  id: "attempts.read",
1422
3196
  idempotent: true,
1423
3197
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -1426,29 +3200,37 @@ export const OPERATIONS = [
1426
3200
  path: "/v1/schedules/{scheduleId}/occurrences/{occurrenceId}/attempts/{attemptId}",
1427
3201
  principals: ["api-credential", "oauth", "session"],
1428
3202
  problems: ["invalid_request", "not_found"],
1429
- response: attemptViewSchema,
3203
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3204
+ ? API_UNUSED_RESPONSE_SCHEMA
3205
+ : attemptViewSchema,
1430
3206
  scopes: ["occurrences:read"],
1431
3207
  sessionAuthority: "headers",
1432
- summary: "Read a delivery attempt",
3208
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3209
+ ? ""
3210
+ : "Read a delivery attempt",
1433
3211
  surfaces: ["api", "mock"],
1434
3212
  },
1435
3213
  {
1436
3214
  creates: true,
1437
- description: "Creates one new immutable attempt under the same retained terminal occurrence and dispatches it through the ordinary delivery boundary. The required Idempotency-Key makes an identical replay converge on the same attempt and conflicting reuse is refused. The new attempt names the retained attempt that caused the redelivery; no earlier identity or outcome is changed. MCP marks this outbound mutation for explicit approval even though it is non-destructive.",
1438
- example: {
1439
- attempt: {
1440
- attemptNumber: 3,
1441
- delivery: "dlv_21h8xyz9k2m4n6p8r0t2v4w6y8",
1442
- id: "att_21h8xyz9k2m4n6p8r0t2v4w6y8",
1443
- occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1444
- startedAt: "2026-07-28T15:05:00.000Z",
1445
- trigger: {
1446
- kind: "redelivery",
1447
- sourceAttemptId: "att_11h8xyz9k2m4n6p8r0t2v4w6y8",
3215
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3216
+ ? ""
3217
+ : "Creates one new immutable attempt under the same retained terminal occurrence and dispatches it through the ordinary delivery boundary. The required Idempotency-Key makes an identical replay converge on the same attempt and conflicting reuse is refused. The new attempt names the retained attempt that caused the redelivery; no earlier identity or outcome is changed. MCP marks this outbound mutation for explicit approval even though it is non-destructive.",
3218
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3219
+ ? {}
3220
+ : {
3221
+ attempt: {
3222
+ attemptNumber: 3,
3223
+ delivery: "dlv_21h8xyz9k2m4n6p8r0t2v4w6y8",
3224
+ id: "att_21h8xyz9k2m4n6p8r0t2v4w6y8",
3225
+ occurrence: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3226
+ startedAt: "2026-07-28T15:05:00.000Z",
3227
+ trigger: {
3228
+ kind: "redelivery",
3229
+ sourceAttemptId: "att_11h8xyz9k2m4n6p8r0t2v4w6y8",
3230
+ },
1448
3231
  },
3232
+ freshness: { kind: "authoritative" },
1449
3233
  },
1450
- freshness: { kind: "authoritative" },
1451
- },
1452
3234
  id: "occurrences.redeliver",
1453
3235
  idempotent: true,
1454
3236
  mcp: { destructive: false, kind: "tool", openWorld: true },
@@ -1464,39 +3246,50 @@ export const OPERATIONS = [
1464
3246
  "state_conflict",
1465
3247
  ],
1466
3248
  requestHeaders: requiredIdempotencyRequestHeaderSchema,
1467
- response: attemptViewSchema,
1468
- responseHeaders: idempotencyReplayResponseHeaderSchema,
3249
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3250
+ ? API_UNUSED_RESPONSE_SCHEMA
3251
+ : attemptViewSchema,
3252
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3253
+ ? {}
3254
+ : { responseHeaders: idempotencyReplayResponseHeaderSchema }),
1469
3255
  scopes: ["occurrences:redeliver"],
1470
3256
  sessionAuthority: "headers",
1471
- summary: "Redeliver an occurrence",
3257
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3258
+ ? ""
3259
+ : "Redeliver an occurrence",
1472
3260
  surfaces: ["api", "mock"],
1473
3261
  },
1474
3262
  {
1475
3263
  creates: false,
1476
- description: "Replaces a schedule's definition, starting a new generation. Takes the same four ways of saying when as a create, so a one-shot can be replaced by a recurring definition and the other way round. An omitted callback endpoint/data pair preserves the stored callback; sending `data` alone replaces the encrypted data for the current endpoint, and sending `endpoint` selects a verified endpoint in the same authority tuple. The occurrence planned under the old definition is settled `skipped_stale` and can never fire unless it was already in flight, in which case its immutable attempt is allowed to settle honestly; a fresh occurrence is planned under the new definition, and the old definition's series stops advancing. Send `If-Match` with the version you read to make this conditional; without it the replace is unconditional and the last writer wins. A cancelled or completed schedule cannot be replaced. `partitionKey` is fixed when the schedule is created: omit it to preserve the stored value or echo that exact value in a GET → modify → PUT flow. Adding, changing, or clearing it is refused as `invalid_request` with `/partitionKey` identified. `latencyClass` remains derived from the replacement recurrence when the caller omits it.",
1477
- example: {
1478
- occurrence: {
1479
- attemptCount: 0,
1480
- generation: 2,
1481
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y9",
1482
- plannedFor: "2026-07-28T16:00:00.000Z",
1483
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1484
- sequence: 1,
1485
- state: "planned",
1486
- },
1487
- schedule: {
1488
- createdAt: "2026-07-28T14:59:00.000Z",
1489
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1490
- generation: 2,
1491
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1492
- latencyClass: "realtime",
1493
- partitionKey: "campaign.spring",
1494
- recurrence: { kind: "at" },
1495
- status: "active",
1496
- updatedAt: "2026-07-28T15:10:00.000Z",
1497
- version: 2,
3264
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3265
+ ? ""
3266
+ : "Replaces a schedule's definition, starting a new generation. Takes the same four ways of saying when as a create, so a one-shot can be replaced by a recurring definition and the other way round. An omitted callback endpoint/data pair preserves the stored callback; sending `data` alone replaces the encrypted data for the current endpoint, and sending `endpoint` selects a verified endpoint in the same authority tuple. The occurrence planned under the old definition is settled `skipped_stale` and can never fire unless it was already in flight, in which case its immutable attempt is allowed to settle honestly; a fresh occurrence is planned under the new definition, and the old definition's series stops advancing. `lateness` is resolved afresh against the replacement recurrence: omit it for that kind's default, or state `skipAhead`, `catchUp`, and an optional `maxStalenessSeconds` override. The policy applies only before an occurrence's first attempt; a retry already in progress remains on its retry and give-up ladder. Send `If-Match` with the version you read to make this conditional; without it the replace is unconditional and the last writer wins. A cancelled or completed schedule cannot be replaced. `partitionKey` is fixed when the schedule is created: omit it to preserve the stored value or echo that exact value in a GET → modify → PUT flow. Adding, changing, or clearing it is refused as `invalid_request` with `/partitionKey` identified. `latencyClass` remains derived from the replacement recurrence when the caller omits it.",
3267
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3268
+ ? {}
3269
+ : {
3270
+ occurrence: {
3271
+ attemptCount: 0,
3272
+ generation: 2,
3273
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y9",
3274
+ plannedFor: "2026-07-28T16:00:00.000Z",
3275
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3276
+ sequence: 1,
3277
+ state: "planned",
3278
+ },
3279
+ schedule: {
3280
+ createdAt: "2026-07-28T14:59:00.000Z",
3281
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
3282
+ generation: 2,
3283
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3284
+ latencyClass: "realtime",
3285
+ lateness: { policy: "catchUp" },
3286
+ partitionKey: "campaign.spring",
3287
+ recurrence: { kind: "at" },
3288
+ status: "active",
3289
+ updatedAt: "2026-07-28T15:10:00.000Z",
3290
+ version: 2,
3291
+ },
1498
3292
  },
1499
- },
1500
3293
  id: "schedules.replace",
1501
3294
  idempotent: true,
1502
3295
  // Destructive: the occurrence planned under the old definition is settled
@@ -1508,10 +3301,6 @@ export const OPERATIONS = [
1508
3301
  path: "/v1/schedules/{scheduleId}",
1509
3302
  principals: ["api-credential", "oauth", "session"],
1510
3303
  problems: [
1511
- // The same undeclared refusal `schedules.create` carried, for the same
1512
- // reason: a replacement may attach a different endpoint and resolves it
1513
- // through the same status rule.
1514
- "endpoint_unverified",
1515
3304
  "invalid_request",
1516
3305
  "not_found",
1517
3306
  // Only the payload ceiling can produce this here. A replacement adds no
@@ -1526,48 +3315,63 @@ export const OPERATIONS = [
1526
3315
  // The other arm of the same schema, deliberately: the create example shows
1527
3316
  // `at` and this one shows `delaySeconds`, so a reader of the published
1528
3317
  // document meets both ways of naming an instant.
1529
- requestExample: {
1530
- data: { report: "weekly" },
1531
- everySeconds: 86_400,
1532
- endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
1533
- partitionKey: "campaign.spring",
1534
- },
3318
+ requestExample: globalThis
3319
+ .GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3320
+ ? {}
3321
+ : {
3322
+ data: { report: "weekly" },
3323
+ everySeconds: 86_400,
3324
+ endpoint: "ep_01h8xyz9k2m4n6p8r0t2v4w6y8",
3325
+ lateness: { maxStalenessSeconds: 7_200, policy: "catchUp" },
3326
+ partitionKey: "campaign.spring",
3327
+ },
1535
3328
  requestHeaders: conditionalRequestHeaderSchema,
1536
- response: scheduleViewSchema,
1537
- responseHeaders: versionResponseHeaderSchema,
3329
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3330
+ ? API_UNUSED_RESPONSE_SCHEMA
3331
+ : scheduleViewSchema,
3332
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3333
+ ? {}
3334
+ : { responseHeaders: versionResponseHeaderSchema }),
1538
3335
  scopes: ["schedules:write"],
1539
3336
  sessionAuthority: "headers",
1540
- summary: "Replace a schedule",
3337
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3338
+ ? ""
3339
+ : "Replace a schedule",
1541
3340
  surfaces: ["api", "mock"],
1542
3341
  },
1543
3342
  {
1544
3343
  creates: false,
1545
- description: "Suspends a schedule without discarding it: its occurrence stays planned, its timer is released, and resume re-arms the original planned instant so elapsed work becomes due rather than being silently moved. A schedule with a dispatching or ambiguous callback is refused until that attempt settles, because pausing cannot strand its watchdog or turn a proven success into an unreachable completed state. Pausing an already paused schedule changes nothing and returns the same version, so a retry is free. A cancelled or completed schedule cannot be paused.",
1546
- example: {
1547
- occurrence: {
1548
- attemptCount: 0,
1549
- generation: 1,
1550
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1551
- plannedFor: "2026-07-28T15:00:00.000Z",
1552
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1553
- sequence: 1,
1554
- state: "planned",
1555
- },
1556
- schedule: {
1557
- createdAt: "2026-07-28T14:59:00.000Z",
1558
- generation: 1,
1559
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1560
- latencyClass: "realtime",
1561
- recurrence: { kind: "at" },
1562
- status: "paused",
1563
- updatedAt: "2026-07-28T15:10:00.000Z",
1564
- version: 2,
3344
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3345
+ ? ""
3346
+ : "Suspends a schedule without discarding it: its occurrence stays planned, its timer is released, and resume re-arms the original planned instant rather than silently moving it. If that instant has passed, the schedule's lateness policy decides whether the first arrival becomes due or settles `skipped_stale`; a pause defers the decision, it does not promise delivery. A schedule with a dispatching or ambiguous callback is refused until that attempt settles, because pausing cannot strand its watchdog or turn a proven success into an unreachable completed state. Pausing an already paused schedule changes nothing and returns the same version, so a retry is free. A cancelled or completed schedule cannot be paused.",
3347
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3348
+ ? {}
3349
+ : {
3350
+ occurrence: {
3351
+ attemptCount: 0,
3352
+ generation: 1,
3353
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3354
+ plannedFor: "2026-07-28T15:00:00.000Z",
3355
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3356
+ sequence: 1,
3357
+ state: "planned",
3358
+ },
3359
+ schedule: {
3360
+ createdAt: "2026-07-28T14:59:00.000Z",
3361
+ generation: 1,
3362
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3363
+ latencyClass: "realtime",
3364
+ lateness: { policy: "catchUp" },
3365
+ recurrence: { kind: "at" },
3366
+ status: "paused",
3367
+ updatedAt: "2026-07-28T15:10:00.000Z",
3368
+ version: 2,
3369
+ },
1565
3370
  },
1566
- },
1567
3371
  id: "schedules.pause",
1568
3372
  idempotent: true,
1569
3373
  // Not destructive: the occurrence stays planned and the timer stays armed.
1570
- // A pause defers work; resuming delivers it.
3374
+ // A pause defers the first-arrival decision; the lateness policy resolves it.
1571
3375
  mcp: { destructive: false, kind: "tool", openWorld: false },
1572
3376
  method: "POST",
1573
3377
  mutates: true,
@@ -1580,37 +3384,48 @@ export const OPERATIONS = [
1580
3384
  "version_conflict",
1581
3385
  ],
1582
3386
  requestHeaders: conditionalRequestHeaderSchema,
1583
- response: scheduleViewSchema,
1584
- responseHeaders: versionResponseHeaderSchema,
3387
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3388
+ ? API_UNUSED_RESPONSE_SCHEMA
3389
+ : scheduleViewSchema,
3390
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3391
+ ? {}
3392
+ : { responseHeaders: versionResponseHeaderSchema }),
1585
3393
  scopes: ["schedules:write"],
1586
3394
  sessionAuthority: "headers",
1587
- summary: "Pause a schedule",
3395
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3396
+ ? ""
3397
+ : "Pause a schedule",
1588
3398
  surfaces: ["api", "mock"],
1589
3399
  },
1590
3400
  {
1591
3401
  creates: false,
1592
- description: "Returns a paused schedule to active. An occurrence whose instant passed while the schedule was paused becomes due at once rather than being skipped — a pause defers work, it does not discard it. Resuming an already active schedule changes nothing and returns the same version.",
1593
- example: {
1594
- occurrence: {
1595
- attemptCount: 0,
1596
- generation: 1,
1597
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1598
- plannedFor: "2026-07-28T15:00:00.000Z",
1599
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1600
- sequence: 1,
1601
- state: "planned",
1602
- },
1603
- schedule: {
1604
- createdAt: "2026-07-28T14:59:00.000Z",
1605
- generation: 1,
1606
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1607
- latencyClass: "realtime",
1608
- recurrence: { kind: "at" },
1609
- status: "active",
1610
- updatedAt: "2026-07-28T15:20:00.000Z",
1611
- version: 3,
3402
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3403
+ ? ""
3404
+ : "Returns a paused schedule to active and re-arms its original planned instant. When that instant passed during the pause, the schedule's lateness policy applies exactly as it does after an outage: `catchUp` makes an occurrence inside its window due, while `skipAhead` or an expired window settles it `skipped_stale`. An occurrence already on its retry ladder is exempt from this first-arrival decision. Resuming an already active schedule changes nothing and returns the same version.",
3405
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3406
+ ? {}
3407
+ : {
3408
+ occurrence: {
3409
+ attemptCount: 0,
3410
+ generation: 1,
3411
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3412
+ plannedFor: "2026-07-28T15:00:00.000Z",
3413
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3414
+ sequence: 1,
3415
+ state: "planned",
3416
+ },
3417
+ schedule: {
3418
+ createdAt: "2026-07-28T14:59:00.000Z",
3419
+ generation: 1,
3420
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3421
+ latencyClass: "realtime",
3422
+ lateness: { policy: "catchUp" },
3423
+ recurrence: { kind: "at" },
3424
+ status: "active",
3425
+ updatedAt: "2026-07-28T15:20:00.000Z",
3426
+ version: 3,
3427
+ },
1612
3428
  },
1613
- },
1614
3429
  id: "schedules.resume",
1615
3430
  idempotent: true,
1616
3431
  mcp: { destructive: false, kind: "tool", openWorld: false },
@@ -1625,38 +3440,49 @@ export const OPERATIONS = [
1625
3440
  "version_conflict",
1626
3441
  ],
1627
3442
  requestHeaders: conditionalRequestHeaderSchema,
1628
- response: scheduleViewSchema,
1629
- responseHeaders: versionResponseHeaderSchema,
3443
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3444
+ ? API_UNUSED_RESPONSE_SCHEMA
3445
+ : scheduleViewSchema,
3446
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3447
+ ? {}
3448
+ : { responseHeaders: versionResponseHeaderSchema }),
1630
3449
  scopes: ["schedules:write"],
1631
3450
  sessionAuthority: "headers",
1632
- summary: "Resume a schedule",
3451
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3452
+ ? ""
3453
+ : "Resume a schedule",
1633
3454
  surfaces: ["api", "mock"],
1634
3455
  },
1635
3456
  {
1636
3457
  creates: false,
1637
- description: "Cancels a schedule and settles its occurrence `cancelled`, releasing the timer. Terminal: a cancelled schedule cannot be resumed or replaced, and cancelling one that is already cancelled changes nothing and returns the same version. A cancel that races its own occurrence becoming due still wins — the occurrence settles cancelled and no work is delivered — which is why this is a refusal-free retry rather than a race a client has to reason about. The schedule stays readable; archive it to take it out of the listing.",
1638
- example: {
1639
- occurrence: {
1640
- attemptCount: 0,
1641
- generation: 1,
1642
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1643
- plannedFor: "2026-07-28T15:00:00.000Z",
1644
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1645
- sequence: 1,
1646
- settledAt: "2026-07-28T15:10:00.000Z",
1647
- state: "cancelled",
1648
- },
1649
- schedule: {
1650
- createdAt: "2026-07-28T14:59:00.000Z",
1651
- generation: 1,
1652
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1653
- latencyClass: "realtime",
1654
- recurrence: { kind: "at" },
1655
- status: "cancelled",
1656
- updatedAt: "2026-07-28T15:10:00.000Z",
1657
- version: 2,
3458
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3459
+ ? ""
3460
+ : "Cancels a schedule and settles its occurrence `cancelled`, releasing the timer. Terminal: a cancelled schedule cannot be resumed or replaced, and cancelling one that is already cancelled changes nothing and returns the same version. A cancel that races its own occurrence becoming due still wins — the occurrence settles cancelled and no work is delivered — which is why this is a refusal-free retry rather than a race a client has to reason about. The schedule stays readable; archive it to take it out of the listing.",
3461
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3462
+ ? {}
3463
+ : {
3464
+ occurrence: {
3465
+ attemptCount: 0,
3466
+ generation: 1,
3467
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3468
+ plannedFor: "2026-07-28T15:00:00.000Z",
3469
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3470
+ sequence: 1,
3471
+ settledAt: "2026-07-28T15:10:00.000Z",
3472
+ state: "cancelled",
3473
+ },
3474
+ schedule: {
3475
+ createdAt: "2026-07-28T14:59:00.000Z",
3476
+ generation: 1,
3477
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3478
+ latencyClass: "realtime",
3479
+ lateness: { policy: "catchUp" },
3480
+ recurrence: { kind: "at" },
3481
+ status: "cancelled",
3482
+ updatedAt: "2026-07-28T15:10:00.000Z",
3483
+ version: 2,
3484
+ },
1658
3485
  },
1659
- },
1660
3486
  id: "schedules.cancel",
1661
3487
  idempotent: true,
1662
3488
  // Destructive and terminal: the occurrence settles `cancelled`, no work is
@@ -1673,39 +3499,50 @@ export const OPERATIONS = [
1673
3499
  "version_conflict",
1674
3500
  ],
1675
3501
  requestHeaders: conditionalRequestHeaderSchema,
1676
- response: scheduleViewSchema,
1677
- responseHeaders: versionResponseHeaderSchema,
3502
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3503
+ ? API_UNUSED_RESPONSE_SCHEMA
3504
+ : scheduleViewSchema,
3505
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3506
+ ? {}
3507
+ : { responseHeaders: versionResponseHeaderSchema }),
1678
3508
  scopes: ["schedules:write"],
1679
3509
  sessionAuthority: "headers",
1680
- summary: "Cancel a schedule",
3510
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3511
+ ? ""
3512
+ : "Cancel a schedule",
1681
3513
  surfaces: ["api", "mock"],
1682
3514
  },
1683
3515
  {
1684
3516
  creates: false,
1685
- description: "Files a finished schedule away: it leaves the default listing and stays readable by identifier, carrying the instant it was archived. Only a cancelled or completed schedule can be archived — archiving is filing, not stopping, so cancel it first. Archiving an already archived schedule changes nothing and returns the same version.",
1686
- example: {
1687
- occurrence: {
1688
- attemptCount: 0,
1689
- generation: 1,
1690
- id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
1691
- plannedFor: "2026-07-28T15:00:00.000Z",
1692
- schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1693
- sequence: 1,
1694
- settledAt: "2026-07-28T15:10:00.000Z",
1695
- state: "cancelled",
1696
- },
1697
- schedule: {
1698
- archivedAt: "2026-07-28T15:30:00.000Z",
1699
- createdAt: "2026-07-28T14:59:00.000Z",
1700
- generation: 1,
1701
- id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
1702
- latencyClass: "realtime",
1703
- recurrence: { kind: "at" },
1704
- status: "cancelled",
1705
- updatedAt: "2026-07-28T15:30:00.000Z",
1706
- version: 3,
3517
+ description: globalThis.GREATWAIT_RUNTIME_CONTRACTS_ONLY
3518
+ ? ""
3519
+ : "Files a finished schedule away: it leaves the default listing and stays readable by identifier, carrying the instant it was archived. Only a cancelled or completed schedule can be archived — archiving is filing, not stopping, so cancel it first. Archiving an already archived schedule changes nothing and returns the same version.",
3520
+ example: globalThis.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
3521
+ ? {}
3522
+ : {
3523
+ occurrence: {
3524
+ attemptCount: 0,
3525
+ generation: 1,
3526
+ id: "occ_01h8xyz9k2m4n6p8r0t2v4w6y8",
3527
+ plannedFor: "2026-07-28T15:00:00.000Z",
3528
+ schedule: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3529
+ sequence: 1,
3530
+ settledAt: "2026-07-28T15:10:00.000Z",
3531
+ state: "cancelled",
3532
+ },
3533
+ schedule: {
3534
+ archivedAt: "2026-07-28T15:30:00.000Z",
3535
+ createdAt: "2026-07-28T14:59:00.000Z",
3536
+ generation: 1,
3537
+ id: "sch_01h8xyz9k2m4n6p8r0t2v4w6y8",
3538
+ latencyClass: "realtime",
3539
+ lateness: { policy: "catchUp" },
3540
+ recurrence: { kind: "at" },
3541
+ status: "cancelled",
3542
+ updatedAt: "2026-07-28T15:30:00.000Z",
3543
+ version: 3,
3544
+ },
1707
3545
  },
1708
- },
1709
3546
  id: "schedules.archive",
1710
3547
  idempotent: true,
1711
3548
  // Not destructive: archiving is filing. The schedule stays readable by
@@ -1723,11 +3560,17 @@ export const OPERATIONS = [
1723
3560
  "version_conflict",
1724
3561
  ],
1725
3562
  requestHeaders: conditionalRequestHeaderSchema,
1726
- response: scheduleViewSchema,
1727
- responseHeaders: versionResponseHeaderSchema,
3563
+ response: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3564
+ ? API_UNUSED_RESPONSE_SCHEMA
3565
+ : scheduleViewSchema,
3566
+ ...(globalThis.GREATWAIT_API_REQUEST_REGISTRY
3567
+ ? {}
3568
+ : { responseHeaders: versionResponseHeaderSchema }),
1728
3569
  scopes: ["schedules:write"],
1729
3570
  sessionAuthority: "headers",
1730
- summary: "Archive a schedule",
3571
+ summary: globalThis.GREATWAIT_API_REQUEST_REGISTRY
3572
+ ? ""
3573
+ : "Archive a schedule",
1731
3574
  surfaces: ["api", "mock"],
1732
3575
  },
1733
3576
  ];
@@ -1824,14 +3667,44 @@ export const AUTHENTICATED_PROBLEMS = [
1824
3667
  "authentication_required",
1825
3668
  "credential_expired",
1826
3669
  "credential_revoked",
1827
- "scope_missing",
1828
3670
  ];
3671
+ /**
3672
+ * The problem an operation returns when the principal is verified and its scope
3673
+ * list falls short.
3674
+ *
3675
+ * **Separated from the list above at W10-01, because the two were keyed on the
3676
+ * wrong field.** `problemsFor` read `scopes.length > 0` and published all four
3677
+ * problems from it, which was exact only while "requires a scope" and "requires
3678
+ * a credential" were the same sentence. `context.read` is the operation that
3679
+ * needs a credential and no scope, and under the old rule it would have been
3680
+ * published with no authentication problems and — through
3681
+ * `securityRequirements` — no security requirement either: a route that refuses
3682
+ * an anonymous caller, documented as open to one. Keying authentication on
3683
+ * `principals` and this one on `scopes` says what each actually depends on, and
3684
+ * it also stops publishing a `scope_missing` that no request to such an
3685
+ * operation could ever produce.
3686
+ */
3687
+ export const SCOPED_PROBLEMS = ["scope_missing"];
3688
+ /** Whether an authenticated operation needs a project that accepts work. */
3689
+ function canMeetArchivedProject(operation) {
3690
+ if (operation.principals.length === 0)
3691
+ return false;
3692
+ if (operation.sessionAuthority === "organization" ||
3693
+ operation.sessionAuthority === "member") {
3694
+ return false;
3695
+ }
3696
+ return !["projects.archive", "projects.delete", "projects.rename"].includes(operation.id);
3697
+ }
1829
3698
  export function problemsFor(operation) {
1830
3699
  return [
1831
3700
  ...new Set([
1832
3701
  ...operation.problems,
1833
3702
  ...UNIVERSAL_PROBLEMS,
1834
- ...(operation.scopes.length > 0 ? AUTHENTICATED_PROBLEMS : []),
3703
+ ...(operation.principals.length > 0 ? AUTHENTICATED_PROBLEMS : []),
3704
+ ...(operation.scopes.length > 0 ? SCOPED_PROBLEMS : []),
3705
+ ...(canMeetArchivedProject(operation)
3706
+ ? ["project_archived"]
3707
+ : []),
1835
3708
  ]),
1836
3709
  ].sort();
1837
3710
  }