@greatwait/contracts 0.1.0-alpha.3 → 0.1.0-alpha.5

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 (345) hide show
  1. package/README.md +12 -10
  2. package/dist/authority.d.ts +33 -27
  3. package/dist/authority.js +12 -2
  4. package/dist/billing.d.ts +1231 -0
  5. package/dist/billing.js +833 -0
  6. package/dist/callback-safety.d.ts +2 -2
  7. package/dist/callback-safety.js +15 -5
  8. package/dist/compatibility.d.ts +3 -3
  9. package/dist/compatibility.js +1 -1
  10. package/dist/configuration-bounds.d.ts +13 -0
  11. package/dist/configuration-bounds.js +13 -0
  12. package/dist/data-export.d.ts +67 -0
  13. package/dist/data-export.js +182 -0
  14. package/dist/effective-limits.d.ts +40 -0
  15. package/dist/effective-limits.js +42 -0
  16. package/dist/endpoints.d.ts +186 -245
  17. package/dist/endpoints.js +82 -86
  18. package/dist/events.d.ts +17 -17
  19. package/dist/events.js +1 -1
  20. package/dist/first-value-journey.d.ts +50 -56
  21. package/dist/first-value-journey.js +17 -20
  22. package/dist/forecast.d.ts +182 -92
  23. package/dist/forecast.js +88 -25
  24. package/dist/identifiers.d.ts +20 -20
  25. package/dist/identifiers.js +1 -1
  26. package/dist/identity.d.ts +41 -37
  27. package/dist/identity.js +5 -4
  28. package/dist/index.d.ts +12 -6
  29. package/dist/index.js +12 -6
  30. package/dist/mcp.d.ts +21 -19
  31. package/dist/mcp.js +2 -2
  32. package/dist/naming.d.ts +45 -0
  33. package/dist/naming.js +159 -0
  34. package/dist/oauth.d.ts +186 -172
  35. package/dist/oauth.js +1 -1
  36. package/dist/operation-definitions.d.ts +9 -0
  37. package/dist/operation-definitions.js +7 -0
  38. package/dist/operational-config.d.ts +101 -0
  39. package/dist/operational-config.js +341 -0
  40. package/dist/operations.d.ts +4742 -2170
  41. package/dist/operations.js +3064 -932
  42. package/dist/organization-lifecycle.d.ts +34 -0
  43. package/dist/organization-lifecycle.js +122 -0
  44. package/dist/partition.d.ts +43 -9
  45. package/dist/partition.js +3 -3
  46. package/dist/policy.d.ts +4 -4
  47. package/dist/policy.js +9 -5
  48. package/dist/problems.d.ts +57 -28
  49. package/dist/problems.js +55 -3
  50. package/dist/protocol.d.ts +209 -80
  51. package/dist/protocol.js +110 -37
  52. package/dist/scheduling-records.d.ts +349 -285
  53. package/dist/scheduling-records.js +1 -1
  54. package/dist/scheduling.d.ts +707 -361
  55. package/dist/scheduling.js +443 -61
  56. package/dist/secrets.d.ts +119 -105
  57. package/dist/secrets.js +1 -1
  58. package/dist/signatures.d.ts +74 -74
  59. package/dist/signatures.js +1 -1
  60. package/dist/tenancy.d.ts +142 -68
  61. package/dist/tenancy.js +70 -17
  62. package/dist/test-sink.d.ts +127 -127
  63. package/dist/test-sink.js +1 -1
  64. package/dist/time.d.ts +4 -4
  65. package/dist/time.js +1 -1
  66. package/dist/timing.d.ts +65 -0
  67. package/dist/timing.js +82 -0
  68. package/dist/usage.d.ts +103 -47
  69. package/dist/usage.js +183 -32
  70. package/dist/workspace.d.ts +34 -34
  71. package/dist/workspace.js +1 -1
  72. package/dist/zod-values.d.ts +3 -0
  73. package/dist/zod-values.js +2 -0
  74. package/dist/zod.d.ts +2 -0
  75. package/dist/zod.js +2 -0
  76. package/generated/v1/examples/attempts.list.response.json +6 -0
  77. package/generated/v1/examples/attempts.read.response.json +6 -0
  78. package/generated/v1/examples/billing.autotopup.request.json +5 -0
  79. package/generated/v1/examples/billing.autotopup.response.json +120 -0
  80. package/generated/v1/examples/billing.autotopuppreview.request.json +19 -0
  81. package/generated/v1/examples/billing.autotopuppreview.response.json +45 -0
  82. package/generated/v1/examples/billing.budgets.request.json +13 -0
  83. package/generated/v1/examples/billing.budgets.response.json +22 -0
  84. package/generated/v1/examples/billing.ceiling.request.json +8 -0
  85. package/generated/v1/examples/billing.ceiling.response.json +120 -0
  86. package/generated/v1/examples/billing.change.request.json +5 -0
  87. package/generated/v1/examples/billing.change.response.json +12 -0
  88. package/generated/v1/examples/billing.funding.response.json +120 -0
  89. package/generated/v1/examples/billing.fundingconfirm.response.json +120 -0
  90. package/generated/v1/examples/billing.fundingquote.request.json +7 -0
  91. package/generated/v1/examples/billing.fundingquote.response.json +13 -0
  92. package/generated/v1/examples/billing.invoicehistory.response.json +6 -0
  93. package/generated/v1/examples/billing.invoices.response.json +15 -0
  94. package/generated/v1/examples/billing.ledger.response.json +23 -0
  95. package/generated/v1/examples/billing.notices.response.json +41 -0
  96. package/generated/v1/examples/billing.notificationsettings.response.json +17 -0
  97. package/generated/v1/examples/billing.notificationsettingsupdate.request.json +9 -0
  98. package/generated/v1/examples/billing.notificationsettingsupdate.response.json +17 -0
  99. package/generated/v1/examples/billing.paymenthistory.response.json +6 -0
  100. package/generated/v1/examples/billing.paymentmethod.response.json +16 -0
  101. package/generated/v1/examples/billing.paymentmethodconfirm.request.json +3 -0
  102. package/generated/v1/examples/billing.paymentmethodconfirm.response.json +16 -0
  103. package/generated/v1/examples/billing.paymentmethodremove.request.json +3 -0
  104. package/generated/v1/examples/billing.paymentmethodremove.response.json +4 -0
  105. package/generated/v1/examples/billing.paymentmethodsetup.request.json +1 -0
  106. package/generated/v1/examples/billing.paymentmethodsetup.response.json +3 -0
  107. package/generated/v1/examples/billing.portal.response.json +3 -0
  108. package/generated/v1/examples/billing.projects.response.json +12 -0
  109. package/generated/v1/examples/billing.purchase.request.json +5 -0
  110. package/generated/v1/examples/billing.purchase.response.json +120 -0
  111. package/generated/v1/examples/billing.quote.request.json +4 -0
  112. package/generated/v1/examples/billing.quote.response.json +19 -0
  113. package/generated/v1/examples/billing.reconcile.response.json +73 -0
  114. package/generated/v1/examples/billing.refundrequest.request.json +10 -0
  115. package/generated/v1/examples/billing.refundrequest.response.json +11 -0
  116. package/generated/v1/examples/billing.refundresolution.request.json +4 -0
  117. package/generated/v1/examples/billing.refundresolution.response.json +120 -0
  118. package/generated/v1/examples/billing.summary.response.json +73 -0
  119. package/generated/v1/examples/endpoints.acknowledgeSigningKeyRotation.response.json +18 -0
  120. package/generated/v1/examples/endpoints.create.response.json +1 -1
  121. package/generated/v1/examples/endpoints.disable.response.json +0 -1
  122. package/generated/v1/examples/{endpoints.verify.response.json → endpoints.enable.response.json} +4 -5
  123. package/generated/v1/examples/endpoints.list.response.json +1 -2
  124. package/generated/v1/examples/endpoints.read.response.json +2 -2
  125. package/generated/v1/examples/endpoints.revealSigningSecret.response.json +7 -0
  126. package/generated/v1/examples/endpoints.rotateSigningKey.response.json +1 -2
  127. package/generated/v1/examples/endpoints.update.response.json +1 -1
  128. package/generated/v1/examples/executions.list.response.json +20 -0
  129. package/generated/v1/examples/exports.cancel.response.json +11 -0
  130. package/generated/v1/examples/exports.create.request.json +1 -0
  131. package/generated/v1/examples/exports.create.response.json +8 -0
  132. package/generated/v1/examples/exports.part.response.json +5 -0
  133. package/generated/v1/examples/exports.read.response.json +8 -0
  134. package/generated/v1/examples/limits.read.response.json +16 -0
  135. package/generated/v1/examples/occurrences.read.response.json +4 -0
  136. package/generated/v1/examples/occurrences.redeliver.response.json +2 -0
  137. package/generated/v1/examples/organizations.close.request.json +5 -0
  138. package/generated/v1/examples/organizations.close.response.json +10 -0
  139. package/generated/v1/examples/organizations.lifecycle.response.json +10 -0
  140. package/generated/v1/examples/organizations.restore.request.json +3 -0
  141. package/generated/v1/examples/organizations.restore.response.json +10 -0
  142. package/generated/v1/examples/projects.archive.request.json +3 -0
  143. package/generated/v1/examples/projects.archive.response.json +14 -0
  144. package/generated/v1/examples/projects.create.response.json +10 -1
  145. package/generated/v1/examples/projects.delete.response.json +9 -0
  146. package/generated/v1/examples/projects.list.response.json +12 -2
  147. package/generated/v1/examples/projects.rename.request.json +3 -0
  148. package/generated/v1/examples/projects.rename.response.json +14 -0
  149. package/generated/v1/examples/schedules.archive.response.json +3 -0
  150. package/generated/v1/examples/schedules.cancel.response.json +3 -0
  151. package/generated/v1/examples/schedules.create.request.json +4 -0
  152. package/generated/v1/examples/schedules.create.response.json +3 -0
  153. package/generated/v1/examples/schedules.list.response.json +3 -0
  154. package/generated/v1/examples/schedules.pause.response.json +3 -0
  155. package/generated/v1/examples/schedules.read.response.json +6 -0
  156. package/generated/v1/examples/schedules.replace.request.json +4 -0
  157. package/generated/v1/examples/schedules.replace.response.json +3 -0
  158. package/generated/v1/examples/schedules.resume.response.json +3 -0
  159. package/generated/v1/examples/timing.summary.response.json +35 -0
  160. package/generated/v1/examples/usage.read.response.json +1 -0
  161. package/generated/v1/first-value-journey.json +43 -18
  162. package/generated/v1/manifest.json +1287 -42
  163. package/generated/v1/openapi.json +36033 -5982
  164. package/generated/v1/policy-matrix.json +341 -47
  165. package/generated/v1/schemas/attempts.list.response.json +39 -1
  166. package/generated/v1/schemas/attempts.read.response.json +39 -1
  167. package/generated/v1/schemas/billing.autotopup.request-headers.json +13 -0
  168. package/generated/v1/schemas/billing.autotopup.request.json +22 -0
  169. package/generated/v1/schemas/billing.autotopup.response-headers.json +10 -0
  170. package/generated/v1/schemas/billing.autotopup.response.json +552 -0
  171. package/generated/v1/schemas/billing.autotopuppreview.request.json +77 -0
  172. package/generated/v1/schemas/billing.autotopuppreview.response.json +277 -0
  173. package/generated/v1/schemas/billing.budgets.request-headers.json +13 -0
  174. package/generated/v1/schemas/billing.budgets.request.json +66 -0
  175. package/generated/v1/schemas/billing.budgets.response-headers.json +10 -0
  176. package/generated/v1/schemas/billing.budgets.response.json +92 -0
  177. package/generated/v1/schemas/billing.ceiling.request-headers.json +13 -0
  178. package/generated/v1/schemas/billing.ceiling.request.json +40 -0
  179. package/generated/v1/schemas/billing.ceiling.response-headers.json +10 -0
  180. package/generated/v1/schemas/billing.ceiling.response.json +552 -0
  181. package/generated/v1/schemas/billing.change.request-headers.json +13 -0
  182. package/generated/v1/schemas/billing.change.request.json +22 -0
  183. package/generated/v1/schemas/billing.change.response.json +119 -0
  184. package/generated/v1/schemas/billing.funding.response.json +552 -0
  185. package/generated/v1/schemas/billing.fundingconfirm.response.json +552 -0
  186. package/generated/v1/schemas/billing.fundingquote.request.json +28 -0
  187. package/generated/v1/schemas/billing.fundingquote.response.json +61 -0
  188. package/generated/v1/schemas/billing.invoicehistory.query.json +16 -0
  189. package/generated/v1/schemas/billing.invoicehistory.response.json +88 -0
  190. package/generated/v1/schemas/billing.invoices.response.json +51 -0
  191. package/generated/v1/schemas/billing.ledger.query.json +16 -0
  192. package/generated/v1/schemas/billing.ledger.response.json +130 -0
  193. package/generated/v1/schemas/billing.notices.query.json +16 -0
  194. package/generated/v1/schemas/billing.notices.response.json +278 -0
  195. package/generated/v1/schemas/billing.notificationsettings.response.json +70 -0
  196. package/generated/v1/schemas/billing.notificationsettingsupdate.request-headers.json +13 -0
  197. package/generated/v1/schemas/billing.notificationsettingsupdate.request.json +43 -0
  198. package/generated/v1/schemas/billing.notificationsettingsupdate.response-headers.json +10 -0
  199. package/generated/v1/schemas/billing.notificationsettingsupdate.response.json +70 -0
  200. package/generated/v1/schemas/billing.paymenthistory.query.json +16 -0
  201. package/generated/v1/schemas/billing.paymenthistory.response.json +182 -0
  202. package/generated/v1/schemas/billing.paymentmethod.response.json +137 -0
  203. package/generated/v1/schemas/billing.paymentmethodconfirm.request.json +14 -0
  204. package/generated/v1/schemas/billing.paymentmethodconfirm.response.json +137 -0
  205. package/generated/v1/schemas/billing.paymentmethodremove.request.json +12 -0
  206. package/generated/v1/schemas/billing.paymentmethodremove.response.json +137 -0
  207. package/generated/v1/schemas/billing.paymentmethodsetup.request.json +12 -0
  208. package/generated/v1/schemas/billing.paymentmethodsetup.response.json +11 -0
  209. package/generated/v1/schemas/billing.portal.response.json +11 -0
  210. package/generated/v1/schemas/billing.projects.response.json +119 -0
  211. package/generated/v1/schemas/billing.purchase.request-headers.json +13 -0
  212. package/generated/v1/schemas/billing.purchase.request.json +26 -0
  213. package/generated/v1/schemas/billing.purchase.response-headers.json +10 -0
  214. package/generated/v1/schemas/billing.purchase.response.json +552 -0
  215. package/generated/v1/schemas/billing.quote.request.json +20 -0
  216. package/generated/v1/schemas/billing.quote.response.json +86 -0
  217. package/generated/v1/schemas/billing.reconcile.response.json +468 -0
  218. package/generated/v1/schemas/billing.refundrequest.request-headers.json +13 -0
  219. package/generated/v1/schemas/billing.refundrequest.request.json +42 -0
  220. package/generated/v1/schemas/billing.refundrequest.response-headers.json +10 -0
  221. package/generated/v1/schemas/billing.refundrequest.response.json +45 -0
  222. package/generated/v1/schemas/billing.refundresolution.request-headers.json +13 -0
  223. package/generated/v1/schemas/billing.refundresolution.request.json +61 -0
  224. package/generated/v1/schemas/billing.refundresolution.response-headers.json +10 -0
  225. package/generated/v1/schemas/billing.refundresolution.response.json +552 -0
  226. package/generated/v1/schemas/billing.summary.response.json +468 -0
  227. package/generated/v1/schemas/context.read.response.json +2 -0
  228. package/generated/v1/schemas/credentials.connection.response.json +2 -0
  229. package/generated/v1/schemas/credentials.create.request.json +2 -0
  230. package/generated/v1/schemas/credentials.create.response.json +2 -0
  231. package/generated/v1/schemas/credentials.list.response.json +2 -0
  232. package/generated/v1/schemas/credentials.revoke.response.json +2 -0
  233. package/generated/v1/schemas/credentials.rotate.response.json +4 -0
  234. package/generated/v1/schemas/{endpoints.verify.request-headers.json → endpoints.acknowledgeSigningKeyRotation.request-headers.json} +2 -1
  235. package/generated/v1/schemas/{endpoints.verify.response.json → endpoints.acknowledgeSigningKeyRotation.response.json} +8 -21
  236. package/generated/v1/schemas/endpoints.create.request.json +5 -0
  237. package/generated/v1/schemas/endpoints.create.response.json +8 -21
  238. package/generated/v1/schemas/endpoints.disable.response.json +8 -21
  239. package/generated/v1/schemas/endpoints.enable.response-headers.json +11 -0
  240. package/generated/v1/schemas/endpoints.enable.response.json +87 -0
  241. package/generated/v1/schemas/endpoints.list.response.json +8 -21
  242. package/generated/v1/schemas/endpoints.read.response.json +8 -21
  243. package/generated/v1/schemas/endpoints.revealSigningSecret.response.json +43 -0
  244. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +8 -21
  245. package/generated/v1/schemas/endpoints.update.request.json +5 -0
  246. package/generated/v1/schemas/endpoints.update.response.json +8 -21
  247. package/generated/v1/schemas/executions.list.query.json +46 -0
  248. package/generated/v1/schemas/executions.list.response.json +116 -0
  249. package/generated/v1/schemas/exports.cancel.response.json +48 -0
  250. package/generated/v1/schemas/exports.create.request.json +6 -0
  251. package/generated/v1/schemas/exports.create.response.json +38 -0
  252. package/generated/v1/schemas/exports.part.query.json +11 -0
  253. package/generated/v1/schemas/exports.part.response.json +22 -0
  254. package/generated/v1/schemas/exports.read.response.json +38 -0
  255. package/generated/v1/schemas/forecast.read.request-headers.json +10 -0
  256. package/generated/v1/schemas/forecast.read.response.json +148 -0
  257. package/generated/v1/schemas/grants.list.response.json +2 -0
  258. package/generated/v1/schemas/grants.revoke.response.json +2 -0
  259. package/generated/v1/schemas/limits.read.response.json +79 -0
  260. package/generated/v1/schemas/occurrences.list.query.json +5 -0
  261. package/generated/v1/schemas/occurrences.list.response.json +23 -0
  262. package/generated/v1/schemas/occurrences.read.response.json +23 -0
  263. package/generated/v1/schemas/occurrences.redeliver.response.json +39 -1
  264. package/generated/v1/schemas/organizations.close.request.json +20 -0
  265. package/generated/v1/schemas/organizations.close.response.json +68 -0
  266. package/generated/v1/schemas/organizations.lifecycle.response.json +68 -0
  267. package/generated/v1/schemas/organizations.restore.request.json +13 -0
  268. package/generated/v1/schemas/organizations.restore.response.json +68 -0
  269. package/generated/v1/schemas/projects.archive.request-headers.json +11 -0
  270. package/generated/v1/schemas/projects.archive.request.json +10 -0
  271. package/generated/v1/schemas/projects.archive.response-headers.json +11 -0
  272. package/generated/v1/schemas/projects.archive.response.json +79 -0
  273. package/generated/v1/schemas/projects.create.response.json +55 -1
  274. package/generated/v1/schemas/projects.delete.request-headers.json +11 -0
  275. package/generated/v1/schemas/projects.delete.response.json +37 -0
  276. package/generated/v1/schemas/projects.list.response.json +61 -2
  277. package/generated/v1/schemas/projects.rename.request-headers.json +11 -0
  278. package/generated/v1/schemas/projects.rename.request.json +12 -0
  279. package/generated/v1/schemas/projects.rename.response-headers.json +11 -0
  280. package/generated/v1/schemas/projects.rename.response.json +79 -0
  281. package/generated/v1/schemas/schedules.archive.response.json +90 -2
  282. package/generated/v1/schemas/schedules.cancel.response.json +90 -2
  283. package/generated/v1/schemas/schedules.create.request.json +24 -3
  284. package/generated/v1/schemas/schedules.create.response.json +90 -2
  285. package/generated/v1/schemas/schedules.list.query.json +13 -0
  286. package/generated/v1/schemas/schedules.list.response.json +67 -2
  287. package/generated/v1/schemas/schedules.pause.response.json +90 -2
  288. package/generated/v1/schemas/schedules.read.response.json +90 -2
  289. package/generated/v1/schemas/schedules.replace.request.json +24 -3
  290. package/generated/v1/schemas/schedules.replace.response.json +90 -2
  291. package/generated/v1/schemas/schedules.resume.response.json +90 -2
  292. package/generated/v1/schemas/timing.summary.response.json +191 -0
  293. package/generated/v1/schemas/usage.read.query.json +7 -0
  294. package/generated/v1/schemas/usage.read.response.json +36 -1
  295. package/generated/v1/snippets/billing.autotopup.json +6 -0
  296. package/generated/v1/snippets/billing.autotopuppreview.json +6 -0
  297. package/generated/v1/snippets/billing.budgets.json +6 -0
  298. package/generated/v1/snippets/billing.ceiling.json +6 -0
  299. package/generated/v1/snippets/billing.change.json +6 -0
  300. package/generated/v1/snippets/billing.funding.json +6 -0
  301. package/generated/v1/snippets/billing.fundingconfirm.json +6 -0
  302. package/generated/v1/snippets/billing.fundingquote.json +6 -0
  303. package/generated/v1/snippets/billing.invoicehistory.json +6 -0
  304. package/generated/v1/snippets/billing.invoices.json +6 -0
  305. package/generated/v1/snippets/billing.ledger.json +6 -0
  306. package/generated/v1/snippets/billing.notices.json +6 -0
  307. package/generated/v1/snippets/billing.notificationsettings.json +6 -0
  308. package/generated/v1/snippets/billing.notificationsettingsupdate.json +6 -0
  309. package/generated/v1/snippets/billing.paymenthistory.json +6 -0
  310. package/generated/v1/snippets/billing.paymentmethod.json +6 -0
  311. package/generated/v1/snippets/billing.paymentmethodconfirm.json +6 -0
  312. package/generated/v1/snippets/billing.paymentmethodremove.json +6 -0
  313. package/generated/v1/snippets/billing.paymentmethodsetup.json +6 -0
  314. package/generated/v1/snippets/billing.portal.json +6 -0
  315. package/generated/v1/snippets/billing.projects.json +6 -0
  316. package/generated/v1/snippets/billing.purchase.json +6 -0
  317. package/generated/v1/snippets/billing.quote.json +6 -0
  318. package/generated/v1/snippets/billing.reconcile.json +6 -0
  319. package/generated/v1/snippets/billing.refundrequest.json +6 -0
  320. package/generated/v1/snippets/billing.refundresolution.json +6 -0
  321. package/generated/v1/snippets/billing.summary.json +6 -0
  322. package/generated/v1/snippets/endpoints.acknowledgeSigningKeyRotation.json +6 -0
  323. package/generated/v1/snippets/{endpoints.verify.json → endpoints.enable.json} +3 -3
  324. package/generated/v1/snippets/endpoints.revealSigningSecret.json +6 -0
  325. package/generated/v1/snippets/executions.list.json +6 -0
  326. package/generated/v1/snippets/exports.cancel.json +6 -0
  327. package/generated/v1/snippets/exports.create.json +6 -0
  328. package/generated/v1/snippets/exports.part.json +6 -0
  329. package/generated/v1/snippets/exports.read.json +6 -0
  330. package/generated/v1/snippets/forecast.windows.json +1 -1
  331. package/generated/v1/snippets/limits.read.json +6 -0
  332. package/generated/v1/snippets/organizations.close.json +6 -0
  333. package/generated/v1/snippets/organizations.lifecycle.json +6 -0
  334. package/generated/v1/snippets/organizations.restore.json +6 -0
  335. package/generated/v1/snippets/projects.archive.json +6 -0
  336. package/generated/v1/snippets/projects.delete.json +6 -0
  337. package/generated/v1/snippets/projects.rename.json +6 -0
  338. package/generated/v1/snippets/schedules.create.json +3 -3
  339. package/generated/v1/snippets/schedules.replace.json +3 -3
  340. package/generated/v1/snippets/timing.summary.json +6 -0
  341. package/package.json +7 -7
  342. package/dist/callback-ownership.d.ts +0 -58
  343. package/dist/callback-ownership.js +0 -71
  344. package/generated/v1/callback-endpoint-verification.json +0 -59
  345. /package/generated/v1/schemas/{endpoints.verify.response-headers.json → endpoints.acknowledgeSigningKeyRotation.response-headers.json} +0 -0
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "./zod.js";
2
2
  import type { FieldError } from "./problems.js";
3
3
  import { type Freshness } from "./protocol.js";
4
4
  import type { ForecastPartitionBucket } from "./partition.js";
@@ -53,10 +53,11 @@ export declare const FORECAST_BOUNDS: {
53
53
  * argument for refusing rather than under-reporting collapses if staleness is
54
54
  * the one degradation that gets through as a number.
55
55
  */
56
- readonly maxLagSeconds: 600;
56
+ readonly maxLagSeconds: number;
57
57
  /**
58
- * Instants one partition may project into a single snapshot before it reports
59
- * the answer as short.
58
+ * Actual recurrence work units (shared cron advances or interval-series
59
+ * calculations) before a partition reports the answer as short. Output-cell
60
+ * allocation is bounded independently by maxGroupsPerPartition.
60
61
  *
61
62
  * Published rather than kept internal so a refusal is classifiable: a shadow
62
63
  * comparison that sees a refusal needs to be able to tell "we are near a
@@ -83,7 +84,7 @@ export declare const FORECAST_BOUNDS: {
83
84
  * an incident. `freshness.lagSeconds` reports the actual age on every answer;
84
85
  * this is the bound it lives inside.
85
86
  */
86
- readonly refreshCeilingSeconds: 300;
87
+ readonly refreshCeilingSeconds: number;
87
88
  /**
88
89
  * Shortest gap between refreshes once something *has* been written.
89
90
  *
@@ -92,7 +93,7 @@ export declare const FORECAST_BOUNDS: {
92
93
  * projection that rebuilt on every poll would be the cost this whole design
93
94
  * exists to avoid.
94
95
  */
95
- readonly refreshFloorSeconds: 30;
96
+ readonly refreshFloorSeconds: number;
96
97
  /**
97
98
  * How far below `now` a window may begin.
98
99
  *
@@ -102,7 +103,7 @@ export declare const FORECAST_BOUNDS: {
102
103
  * because the caller's `now` is a second behind. Further back than that is a
103
104
  * question about the past, which a forecast does not answer.
104
105
  */
105
- readonly slackSeconds: 120;
106
+ readonly slackSeconds: number;
106
107
  /**
107
108
  * Customer keys named individually in one bucket before the rest are summed.
108
109
  *
@@ -120,20 +121,20 @@ export declare const FORECAST_BOUNDS: {
120
121
  * the total and the latency split, which every answer carries.
121
122
  */
122
123
  export declare const FORECAST_BREAKDOWNS: readonly ["none", "partitionKey"];
123
- export declare const forecastBreakdownSchema: z.ZodEnum<{
124
+ export declare const forecastBreakdownSchema: import("zod").ZodEnum<{
124
125
  none: "none";
125
126
  partitionKey: "partitionKey";
126
127
  }>;
127
128
  export type ForecastBreakdown = z.infer<typeof forecastBreakdownSchema>;
128
- export declare const forecastRequestSchema: z.ZodObject<{
129
- breakdown: z.ZodDefault<z.ZodEnum<{
129
+ export declare const forecastRequestSchema: import("zod").ZodObject<{
130
+ breakdown: import("zod").ZodDefault<import("zod").ZodEnum<{
130
131
  none: "none";
131
132
  partitionKey: "partitionKey";
132
133
  }>>;
133
- bucketSeconds: z.ZodDefault<z.ZodNumber>;
134
- from: z.ZodOptional<z.ZodString>;
135
- to: z.ZodOptional<z.ZodString>;
136
- }, z.core.$strip>;
134
+ bucketSeconds: import("zod").ZodDefault<import("zod").ZodNumber>;
135
+ from: import("zod").ZodOptional<import("zod").ZodString>;
136
+ to: import("zod").ZodOptional<import("zod").ZodString>;
137
+ }, import("zod/v4/core").$strip>;
137
138
  export type ForecastRequest = z.infer<typeof forecastRequestSchema>;
138
139
  export type ForecastRequestParse = {
139
140
  readonly errors: readonly FieldError[];
@@ -197,46 +198,145 @@ export declare function forecastBucketStartMs(instantMs: number, bucketSeconds:
197
198
  * third latency class fails a test here rather than silently vanishing from
198
199
  * every forecast.
199
200
  */
200
- export declare const forecastLatencyCountsSchema: z.ZodObject<{
201
- bulk: z.ZodNumber;
202
- realtime: z.ZodNumber;
203
- }, z.core.$strip>;
201
+ export declare const forecastLatencyCountsSchema: import("zod").ZodObject<{
202
+ bulk: import("zod").ZodNumber;
203
+ realtime: import("zod").ZodNumber;
204
+ }, import("zod/v4/core").$strip>;
204
205
  export type ForecastLatencyCounts = z.infer<typeof forecastLatencyCountsSchema>;
205
- export declare const forecastBucketSchema: z.ZodObject<{
206
- byLatencyClass: z.ZodObject<{
207
- bulk: z.ZodNumber;
208
- realtime: z.ZodNumber;
209
- }, z.core.$strip>;
210
- byPartitionKey: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
211
- count: z.ZodNumber;
212
- nextFireCount: z.ZodNumber;
213
- otherPartitionKeyCount: z.ZodOptional<z.ZodNumber>;
214
- start: z.ZodString;
215
- }, z.core.$strip>;
206
+ export declare const forecastBucketSchema: import("zod").ZodObject<{
207
+ byLatencyClass: import("zod").ZodObject<{
208
+ bulk: import("zod").ZodNumber;
209
+ realtime: import("zod").ZodNumber;
210
+ }, import("zod/v4/core").$strip>;
211
+ byPartitionKey: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>>;
212
+ count: import("zod").ZodNumber;
213
+ nextFireCount: import("zod").ZodNumber;
214
+ otherPartitionKeyCount: import("zod").ZodOptional<import("zod").ZodNumber>;
215
+ start: import("zod").ZodString;
216
+ }, import("zod/v4/core").$strip>;
216
217
  export type ForecastBucket = z.infer<typeof forecastBucketSchema>;
217
- export declare const forecastSchema: z.ZodObject<{
218
- buckets: z.ZodArray<z.ZodObject<{
219
- byLatencyClass: z.ZodObject<{
220
- bulk: z.ZodNumber;
221
- realtime: z.ZodNumber;
222
- }, z.core.$strip>;
223
- byPartitionKey: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
224
- count: z.ZodNumber;
225
- nextFireCount: z.ZodNumber;
226
- otherPartitionKeyCount: z.ZodOptional<z.ZodNumber>;
227
- start: z.ZodString;
228
- }, z.core.$strip>>;
229
- freshness: z.ZodObject<{
230
- asOf: z.ZodString;
231
- kind: z.ZodLiteral<"projected">;
232
- lagSeconds: z.ZodNumber;
233
- }, z.core.$strip>;
234
- window: z.ZodObject<{
235
- bucketSeconds: z.ZodNumber;
236
- from: z.ZodString;
237
- to: z.ZodString;
238
- }, z.core.$strip>;
239
- }, z.core.$strip>;
218
+ /** Capability opt-in prevents old clients that read only counts from mistaking
219
+ * a lower bound for complete work. Older servers safely ignore this header. */
220
+ export declare const FORECAST_PARTIAL_ACCEPT_HEADER = "X-Greatwait-Accept-Partial-Forecast";
221
+ export declare const forecastRequestHeadersSchema: import("zod").ZodObject<{
222
+ "X-Greatwait-Accept-Partial-Forecast": import("zod").ZodOptional<import("zod").ZodLiteral<"true">>;
223
+ }, import("zod/v4/core").$strip>;
224
+ export declare const forecastCoverageSchema: import("zod").ZodObject<{
225
+ complete: import("zod").ZodBoolean;
226
+ countMeaning: import("zod").ZodEnum<{
227
+ "complete-total": "complete-total";
228
+ "lower-bound": "lower-bound";
229
+ }>;
230
+ projectedWindow: import("zod").ZodObject<{
231
+ from: import("zod").ZodString;
232
+ to: import("zod").ZodString;
233
+ }, import("zod/v4/core").$strip>;
234
+ completeThrough: import("zod").ZodString;
235
+ heads: import("zod").ZodObject<{
236
+ groupsRead: import("zod").ZodNumber;
237
+ occurrencesCounted: import("zod").ZodNumber;
238
+ complete: import("zod").ZodBoolean;
239
+ selection: import("zod").ZodLiteral<"earliest bucket, latency class, partition key groups">;
240
+ lastGroup: import("zod").ZodOptional<import("zod").ZodObject<{
241
+ start: import("zod").ZodString;
242
+ latencyClass: import("zod").ZodEnum<{
243
+ realtime: "realtime";
244
+ bulk: "bulk";
245
+ }>;
246
+ partitionKey: import("zod").ZodString;
247
+ }, import("zod/v4/core").$strip>>;
248
+ }, import("zod/v4/core").$strip>;
249
+ recurring: import("zod").ZodObject<{
250
+ schedulesRead: import("zod").ZodNumber;
251
+ populationComplete: import("zod").ZodBoolean;
252
+ selection: import("zod").ZodLiteral<"oldest eligible active recurring schedules by createdAt and scheduleId">;
253
+ firstScheduleId: import("zod").ZodOptional<import("zod").ZodString>;
254
+ lastScheduleId: import("zod").ZodOptional<import("zod").ZodString>;
255
+ }, import("zod/v4/core").$strip>;
256
+ work: import("zod").ZodObject<{
257
+ usedUnits: import("zod").ZodNumber;
258
+ limitUnits: import("zod").ZodNumber;
259
+ }, import("zod/v4/core").$strip>;
260
+ boundsReached: import("zod").ZodArray<import("zod").ZodObject<{
261
+ kind: import("zod").ZodEnum<{
262
+ "head-cells": "head-cells";
263
+ "recurring-series": "recurring-series";
264
+ "projection-work": "projection-work";
265
+ "projection-cells": "projection-cells";
266
+ }>;
267
+ limit: import("zod").ZodNumber;
268
+ }, import("zod/v4/core").$strip>>;
269
+ }, import("zod/v4/core").$strip>;
270
+ export type ForecastCoverage = z.infer<typeof forecastCoverageSchema>;
271
+ export declare const forecastSchema: import("zod").ZodObject<{
272
+ coverage: import("zod").ZodOptional<import("zod").ZodObject<{
273
+ complete: import("zod").ZodBoolean;
274
+ countMeaning: import("zod").ZodEnum<{
275
+ "complete-total": "complete-total";
276
+ "lower-bound": "lower-bound";
277
+ }>;
278
+ projectedWindow: import("zod").ZodObject<{
279
+ from: import("zod").ZodString;
280
+ to: import("zod").ZodString;
281
+ }, import("zod/v4/core").$strip>;
282
+ completeThrough: import("zod").ZodString;
283
+ heads: import("zod").ZodObject<{
284
+ groupsRead: import("zod").ZodNumber;
285
+ occurrencesCounted: import("zod").ZodNumber;
286
+ complete: import("zod").ZodBoolean;
287
+ selection: import("zod").ZodLiteral<"earliest bucket, latency class, partition key groups">;
288
+ lastGroup: import("zod").ZodOptional<import("zod").ZodObject<{
289
+ start: import("zod").ZodString;
290
+ latencyClass: import("zod").ZodEnum<{
291
+ realtime: "realtime";
292
+ bulk: "bulk";
293
+ }>;
294
+ partitionKey: import("zod").ZodString;
295
+ }, import("zod/v4/core").$strip>>;
296
+ }, import("zod/v4/core").$strip>;
297
+ recurring: import("zod").ZodObject<{
298
+ schedulesRead: import("zod").ZodNumber;
299
+ populationComplete: import("zod").ZodBoolean;
300
+ selection: import("zod").ZodLiteral<"oldest eligible active recurring schedules by createdAt and scheduleId">;
301
+ firstScheduleId: import("zod").ZodOptional<import("zod").ZodString>;
302
+ lastScheduleId: import("zod").ZodOptional<import("zod").ZodString>;
303
+ }, import("zod/v4/core").$strip>;
304
+ work: import("zod").ZodObject<{
305
+ usedUnits: import("zod").ZodNumber;
306
+ limitUnits: import("zod").ZodNumber;
307
+ }, import("zod/v4/core").$strip>;
308
+ boundsReached: import("zod").ZodArray<import("zod").ZodObject<{
309
+ kind: import("zod").ZodEnum<{
310
+ "head-cells": "head-cells";
311
+ "recurring-series": "recurring-series";
312
+ "projection-work": "projection-work";
313
+ "projection-cells": "projection-cells";
314
+ }>;
315
+ limit: import("zod").ZodNumber;
316
+ }, import("zod/v4/core").$strip>>;
317
+ }, import("zod/v4/core").$strip>>;
318
+ buckets: import("zod").ZodArray<import("zod").ZodObject<{
319
+ byLatencyClass: import("zod").ZodObject<{
320
+ bulk: import("zod").ZodNumber;
321
+ realtime: import("zod").ZodNumber;
322
+ }, import("zod/v4/core").$strip>;
323
+ byPartitionKey: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>>;
324
+ count: import("zod").ZodNumber;
325
+ nextFireCount: import("zod").ZodNumber;
326
+ otherPartitionKeyCount: import("zod").ZodOptional<import("zod").ZodNumber>;
327
+ start: import("zod").ZodString;
328
+ }, import("zod/v4/core").$strip>>;
329
+ freshness: import("zod").ZodObject<{
330
+ asOf: import("zod").ZodString;
331
+ kind: import("zod").ZodLiteral<"projected">;
332
+ lagSeconds: import("zod").ZodNumber;
333
+ }, import("zod/v4/core").$strip>;
334
+ window: import("zod").ZodObject<{
335
+ bucketSeconds: import("zod").ZodNumber;
336
+ from: import("zod").ZodString;
337
+ to: import("zod").ZodString;
338
+ }, import("zod/v4/core").$strip>;
339
+ }, import("zod/v4/core").$strip>;
240
340
  export type Forecast = z.infer<typeof forecastSchema>;
241
341
  /** One bucket, summed across every shard, before it is rendered. */
242
342
  export interface ForecastMergedBucket {
@@ -245,6 +345,7 @@ export interface ForecastMergedBucket {
245
345
  readonly byPartitionKey: Record<string, number>;
246
346
  count: number;
247
347
  nextFireCount: number;
348
+ omittedPartitionKeyCount?: number;
248
349
  unkeyedCount: number;
249
350
  }
250
351
  /**
@@ -301,26 +402,15 @@ export type ForecastAnswerDecision = {
301
402
  /**
302
403
  * Whether a gathered forecast may be published, and how old it is.
303
404
  *
304
- * **Every degradation this operation can suffer ends here, and every one of
305
- * them is a refusal.** That is the whole safety argument of the shape, and it
306
- * follows from a measured fact about the consumer it exists for: it reads the
307
- * bucket total and nothing else — not a degraded flag, not `freshness` — so a
308
- * degraded answer reads to it as a quiet book, and a quiet book makes it
309
- * release capacity. Its own failure path is fail-safe: a request that errors
310
- * makes it hold its last good reading. So the honest degradation is the one
311
- * that errors.
312
- *
313
- * The three are distinct because they mean different things to whoever is
314
- * looking: a partition that did not answer is an availability problem, a book
315
- * past the projection bound is a capacity problem with a published number
316
- * beside it, and an answer older than the bound is a partition that has stopped
317
- * refreshing.
405
+ * Unavailable and stale sources always refuse. Work-bound partial answers are
406
+ * permitted only for a reader that explicitly understands coverage; the
407
+ * default retains the count-only legacy consumer's safe failure behavior.
318
408
  *
319
409
  * `asOfMs` is the **oldest** across the shards, for the reason
320
410
  * `projectionCoverage` takes the oldest checkpoint: one busy shard must not be
321
411
  * allowed to vouch for three quiet ones.
322
412
  */
323
- export declare function decideForecastAnswer(answers: readonly ForecastShardAnswer[], nowMs: number): ForecastAnswerDecision;
413
+ export declare function decideForecastAnswer(answers: readonly ForecastShardAnswer[], nowMs: number, acceptPartial?: boolean): ForecastAnswerDecision;
324
414
  /**
325
415
  * The version of the transitional window shape.
326
416
  *
@@ -329,32 +419,32 @@ export declare function decideForecastAnswer(answers: readonly ForecastShardAnsw
329
419
  * rather than one it discovers.
330
420
  */
331
421
  export declare const FORECAST_WINDOW_VERSION = "2026-08-09";
332
- export declare const forecastWindowBucketSchema: z.ZodObject<{
333
- byTenant: z.ZodRecord<z.ZodString, z.ZodNumber>;
334
- count: z.ZodNumber;
335
- nextFireCount: z.ZodNumber;
336
- otherCount: z.ZodNumber;
337
- start: z.ZodString;
338
- }, z.core.$strip>;
422
+ export declare const forecastWindowBucketSchema: import("zod").ZodObject<{
423
+ byTenant: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
424
+ count: import("zod").ZodNumber;
425
+ nextFireCount: import("zod").ZodNumber;
426
+ otherCount: import("zod").ZodNumber;
427
+ start: import("zod").ZodString;
428
+ }, import("zod/v4/core").$strip>;
339
429
  export type ForecastWindowBucket = z.infer<typeof forecastWindowBucketSchema>;
340
- export declare const forecastWindowsSchema: z.ZodObject<{
341
- bucketSeconds: z.ZodNumber;
342
- buckets: z.ZodArray<z.ZodObject<{
343
- byTenant: z.ZodRecord<z.ZodString, z.ZodNumber>;
344
- count: z.ZodNumber;
345
- nextFireCount: z.ZodNumber;
346
- otherCount: z.ZodNumber;
347
- start: z.ZodString;
348
- }, z.core.$strip>>;
349
- freshness: z.ZodDiscriminatedUnion<[z.ZodObject<{
350
- kind: z.ZodLiteral<"authoritative">;
351
- }, z.core.$strip>, z.ZodObject<{
352
- asOf: z.ZodString;
353
- kind: z.ZodLiteral<"projected">;
354
- lagSeconds: z.ZodNumber;
355
- }, z.core.$strip>], "kind">;
356
- version: z.ZodLiteral<"2026-08-09">;
357
- }, z.core.$strip>;
430
+ export declare const forecastWindowsSchema: import("zod").ZodObject<{
431
+ bucketSeconds: import("zod").ZodNumber;
432
+ buckets: import("zod").ZodArray<import("zod").ZodObject<{
433
+ byTenant: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
434
+ count: import("zod").ZodNumber;
435
+ nextFireCount: import("zod").ZodNumber;
436
+ otherCount: import("zod").ZodNumber;
437
+ start: import("zod").ZodString;
438
+ }, import("zod/v4/core").$strip>>;
439
+ freshness: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
440
+ kind: import("zod").ZodLiteral<"authoritative">;
441
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
442
+ asOf: import("zod").ZodString;
443
+ kind: import("zod").ZodLiteral<"projected">;
444
+ lagSeconds: import("zod").ZodNumber;
445
+ }, import("zod/v4/core").$strip>], "kind">;
446
+ version: import("zod").ZodLiteral<"2026-08-09">;
447
+ }, import("zod/v4/core").$strip>;
358
448
  export type ForecastWindows = z.infer<typeof forecastWindowsSchema>;
359
449
  /**
360
450
  * What the migrating consumer may rely on, published as data.
package/dist/forecast.js CHANGED
@@ -1,4 +1,6 @@
1
- import { z } from "zod";
1
+ import { MAX_FORECAST_HORIZON_SECONDS } from "./configuration-bounds.js";
2
+ import { OPERATIONAL_TIMING } from "./operational-config.js";
3
+ import { z } from "./zod.js";
2
4
  import { freshnessSchema, projectedFreshnessSchema, } from "./protocol.js";
3
5
  import { timestampSchema } from "./time.js";
4
6
  /**
@@ -55,10 +57,11 @@ export const FORECAST_BOUNDS = {
55
57
  * argument for refusing rather than under-reporting collapses if staleness is
56
58
  * the one degradation that gets through as a number.
57
59
  */
58
- maxLagSeconds: 600,
60
+ maxLagSeconds: (OPERATIONAL_TIMING.forecastRefreshMaximumMs * 2) / 1000,
59
61
  /**
60
- * Instants one partition may project into a single snapshot before it reports
61
- * the answer as short.
62
+ * Actual recurrence work units (shared cron advances or interval-series
63
+ * calculations) before a partition reports the answer as short. Output-cell
64
+ * allocation is bounded independently by maxGroupsPerPartition.
62
65
  *
63
66
  * Published rather than kept internal so a refusal is classifiable: a shadow
64
67
  * comparison that sees a refusal needs to be able to tell "we are near a
@@ -75,7 +78,7 @@ export const FORECAST_BOUNDS = {
75
78
  * legacy service's seven-day ceiling bounded the *query* with no snapshot
76
79
  * behind it at all.
77
80
  */
78
- maxWindowSeconds: 25 * 60 * 60,
81
+ maxWindowSeconds: MAX_FORECAST_HORIZON_SECONDS,
79
82
  minBucketSeconds: 60,
80
83
  /**
81
84
  * Longest a partition lets its snapshot stand when nothing has been written.
@@ -85,7 +88,7 @@ export const FORECAST_BOUNDS = {
85
88
  * an incident. `freshness.lagSeconds` reports the actual age on every answer;
86
89
  * this is the bound it lives inside.
87
90
  */
88
- refreshCeilingSeconds: 300,
91
+ refreshCeilingSeconds: OPERATIONAL_TIMING.forecastRefreshMaximumMs / 1000,
89
92
  /**
90
93
  * Shortest gap between refreshes once something *has* been written.
91
94
  *
@@ -94,7 +97,7 @@ export const FORECAST_BOUNDS = {
94
97
  * projection that rebuilt on every poll would be the cost this whole design
95
98
  * exists to avoid.
96
99
  */
97
- refreshFloorSeconds: 30,
100
+ refreshFloorSeconds: OPERATIONAL_TIMING.forecastRefreshFloorMs / 1000,
98
101
  /**
99
102
  * How far below `now` a window may begin.
100
103
  *
@@ -104,7 +107,7 @@ export const FORECAST_BOUNDS = {
104
107
  * because the caller's `now` is a second behind. Further back than that is a
105
108
  * question about the past, which a forecast does not answer.
106
109
  */
107
- slackSeconds: 120,
110
+ slackSeconds: OPERATIONAL_TIMING.forecastCoverageSlackMs / 1000,
108
111
  /**
109
112
  * Customer keys named individually in one bucket before the rest are summed.
110
113
  *
@@ -337,7 +340,73 @@ export const forecastBucketSchema = z.object({
337
340
  /** The bucket's epoch-aligned start. May precede the requested `from`. */
338
341
  start: timestampSchema,
339
342
  });
343
+ /** Capability opt-in prevents old clients that read only counts from mistaking
344
+ * a lower bound for complete work. Older servers safely ignore this header. */
345
+ export const FORECAST_PARTIAL_ACCEPT_HEADER = "X-Greatwait-Accept-Partial-Forecast";
346
+ export const forecastRequestHeadersSchema = z.object({
347
+ [FORECAST_PARTIAL_ACCEPT_HEADER]: z.literal("true").optional(),
348
+ });
349
+ export const forecastCoverageSchema = z
350
+ .object({
351
+ complete: z.boolean(),
352
+ countMeaning: z.enum(["complete-total", "lower-bound"]),
353
+ projectedWindow: z.object({ from: timestampSchema, to: timestampSchema }),
354
+ /** No interval after this can be assumed quiet from absent buckets. */
355
+ completeThrough: timestampSchema,
356
+ heads: z.object({
357
+ groupsRead: z.number().int().nonnegative(),
358
+ occurrencesCounted: z.number().int().nonnegative(),
359
+ complete: z.boolean(),
360
+ selection: z.literal("earliest bucket, latency class, partition key groups"),
361
+ lastGroup: z
362
+ .object({
363
+ start: timestampSchema,
364
+ latencyClass: z.enum(["realtime", "bulk"]),
365
+ partitionKey: z.string(),
366
+ })
367
+ .optional(),
368
+ }),
369
+ recurring: z.object({
370
+ schedulesRead: z.number().int().nonnegative(),
371
+ /** The selected population is complete, not necessarily its expansion. */
372
+ populationComplete: z.boolean(),
373
+ selection: z.literal("oldest eligible active recurring schedules by createdAt and scheduleId"),
374
+ firstScheduleId: z.string().optional(),
375
+ lastScheduleId: z.string().optional(),
376
+ }),
377
+ work: z.object({
378
+ usedUnits: z.number().int().nonnegative(),
379
+ limitUnits: z.number().int().nonnegative(),
380
+ }),
381
+ boundsReached: z.array(z.object({
382
+ kind: z.enum([
383
+ "head-cells",
384
+ "recurring-series",
385
+ "projection-work",
386
+ "projection-cells",
387
+ ]),
388
+ limit: z.number().int().nonnegative(),
389
+ })),
390
+ })
391
+ .superRefine((coverage, context) => {
392
+ if ((coverage.countMeaning === "complete-total") !== coverage.complete ||
393
+ (coverage.complete &&
394
+ (coverage.boundsReached.length !== 0 ||
395
+ !coverage.heads.complete ||
396
+ !coverage.recurring.populationComplete ||
397
+ coverage.completeThrough !== coverage.projectedWindow.to)) ||
398
+ (!coverage.complete &&
399
+ (coverage.boundsReached.length === 0 ||
400
+ coverage.completeThrough !== coverage.projectedWindow.from))) {
401
+ context.addIssue({
402
+ code: "custom",
403
+ message: "Coverage must distinguish complete totals from lower bounds without claiming an unproven time prefix",
404
+ });
405
+ }
406
+ });
340
407
  export const forecastSchema = z.object({
408
+ /** Optional for older servers and callers without the coverage capability. */
409
+ coverage: forecastCoverageSchema.optional(),
341
410
  /** Ascending by `start`. A bucket with no occurrences is omitted. */
342
411
  buckets: z.array(forecastBucketSchema),
343
412
  /**
@@ -391,6 +460,10 @@ export function mergeForecastBuckets(buckets) {
391
460
  }
392
461
  into.count += bucket.count;
393
462
  into.nextFireCount += bucket.nextFireCount;
463
+ if (bucket.omittedPartitionKeyCount !== undefined) {
464
+ into.omittedPartitionKeyCount =
465
+ (into.omittedPartitionKeyCount ?? 0) + bucket.omittedPartitionKeyCount;
466
+ }
394
467
  into.unkeyedCount += bucket.unkeyedCount;
395
468
  }
396
469
  return [...merged.values()].sort((left, right) => left.bucketStartMs - right.bucketStartMs);
@@ -412,7 +485,7 @@ export function mergeForecastBuckets(buckets) {
412
485
  export function topPartitionKeys(bucket) {
413
486
  const ranked = Object.entries(bucket.byPartitionKey).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]));
414
487
  const byPartitionKey = Object.create(null);
415
- let otherPartitionKeyCount = bucket.unkeyedCount;
488
+ let otherPartitionKeyCount = bucket.unkeyedCount + (bucket.omittedPartitionKeyCount ?? 0);
416
489
  ranked.forEach(([key, n], index) => {
417
490
  if (index < FORECAST_BOUNDS.topPartitionKeys) {
418
491
  byPartitionKey[key] = n;
@@ -426,30 +499,20 @@ export function topPartitionKeys(bucket) {
426
499
  /**
427
500
  * Whether a gathered forecast may be published, and how old it is.
428
501
  *
429
- * **Every degradation this operation can suffer ends here, and every one of
430
- * them is a refusal.** That is the whole safety argument of the shape, and it
431
- * follows from a measured fact about the consumer it exists for: it reads the
432
- * bucket total and nothing else — not a degraded flag, not `freshness` — so a
433
- * degraded answer reads to it as a quiet book, and a quiet book makes it
434
- * release capacity. Its own failure path is fail-safe: a request that errors
435
- * makes it hold its last good reading. So the honest degradation is the one
436
- * that errors.
437
- *
438
- * The three are distinct because they mean different things to whoever is
439
- * looking: a partition that did not answer is an availability problem, a book
440
- * past the projection bound is a capacity problem with a published number
441
- * beside it, and an answer older than the bound is a partition that has stopped
442
- * refreshing.
502
+ * Unavailable and stale sources always refuse. Work-bound partial answers are
503
+ * permitted only for a reader that explicitly understands coverage; the
504
+ * default retains the count-only legacy consumer's safe failure behavior.
443
505
  *
444
506
  * `asOfMs` is the **oldest** across the shards, for the reason
445
507
  * `projectionCoverage` takes the oldest checkpoint: one busy shard must not be
446
508
  * allowed to vouch for three quiet ones.
447
509
  */
448
- export function decideForecastAnswer(answers, nowMs) {
510
+ export function decideForecastAnswer(answers, nowMs, acceptPartial = false) {
449
511
  if (answers.some((answer) => "refused" in answer)) {
450
512
  return { ok: false, refusal: "partition-unavailable" };
451
513
  }
452
- if (answers.some((answer) => "truncated" in answer && answer.truncated)) {
514
+ if (!acceptPartial &&
515
+ answers.some((answer) => "truncated" in answer && answer.truncated)) {
453
516
  return { ok: false, refusal: "book-too-large" };
454
517
  }
455
518
  // **Only a partition that built a snapshot vouches for freshness.** One that
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "./zod.js";
2
2
  /**
3
3
  * Public identifiers.
4
4
  *
@@ -37,25 +37,25 @@ export type IdResource = keyof typeof ID_PREFIXES;
37
37
  export declare function idPattern(resource: IdResource): RegExp;
38
38
  /** Any well-formed public identifier, whatever it names. */
39
39
  export declare const ANY_ID_PATTERN: RegExp;
40
- export declare function idSchema(resource: IdResource): z.ZodString;
41
- export declare const apiCredentialIdSchema: z.ZodString;
42
- export declare const apiCredentialEventIdSchema: z.ZodString;
43
- export declare const authorizationRequestIdSchema: z.ZodString;
44
- export declare const callbackSigningKeyIdSchema: z.ZodString;
45
- export declare const oauthClientIdSchema: z.ZodString;
46
- export declare const oauthGrantIdSchema: z.ZodString;
47
- export declare const oauthGrantEventIdSchema: z.ZodString;
48
- export declare const scheduleIdSchema: z.ZodString;
49
- export declare const occurrenceIdSchema: z.ZodString;
50
- export declare const attemptIdSchema: z.ZodString;
51
- export declare const deliveryIdSchema: z.ZodString;
52
- export declare const endpointIdSchema: z.ZodString;
53
- export declare const organizationIdSchema: z.ZodString;
54
- export declare const projectIdSchema: z.ZodString;
55
- export declare const environmentIdSchema: z.ZodString;
56
- export declare const eventIdSchema: z.ZodString;
57
- export declare const testSinkIdSchema: z.ZodString;
58
- export declare const testSinkDeliveryIdSchema: z.ZodString;
40
+ export declare function idSchema(resource: IdResource): import("zod").ZodString;
41
+ export declare const apiCredentialIdSchema: import("zod").ZodString;
42
+ export declare const apiCredentialEventIdSchema: import("zod").ZodString;
43
+ export declare const authorizationRequestIdSchema: import("zod").ZodString;
44
+ export declare const callbackSigningKeyIdSchema: import("zod").ZodString;
45
+ export declare const oauthClientIdSchema: import("zod").ZodString;
46
+ export declare const oauthGrantIdSchema: import("zod").ZodString;
47
+ export declare const oauthGrantEventIdSchema: import("zod").ZodString;
48
+ export declare const scheduleIdSchema: import("zod").ZodString;
49
+ export declare const occurrenceIdSchema: import("zod").ZodString;
50
+ export declare const attemptIdSchema: import("zod").ZodString;
51
+ export declare const deliveryIdSchema: import("zod").ZodString;
52
+ export declare const endpointIdSchema: import("zod").ZodString;
53
+ export declare const organizationIdSchema: import("zod").ZodString;
54
+ export declare const projectIdSchema: import("zod").ZodString;
55
+ export declare const environmentIdSchema: import("zod").ZodString;
56
+ export declare const eventIdSchema: import("zod").ZodString;
57
+ export declare const testSinkIdSchema: import("zod").ZodString;
58
+ export declare const testSinkDeliveryIdSchema: import("zod").ZodString;
59
59
  export type ApiCredentialId = z.infer<typeof apiCredentialIdSchema>;
60
60
  export type ApiCredentialEventId = z.infer<typeof apiCredentialEventIdSchema>;
61
61
  export type AuthorizationRequestId = z.infer<typeof authorizationRequestIdSchema>;
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import { z } from "./zod.js";
2
2
  /**
3
3
  * Public identifiers.
4
4
  *