@kindgi/api 0.1.4 → 0.1.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 (516) hide show
  1. package/dist/agent-binding.d.ts +13 -0
  2. package/dist/agent-binding.d.ts.map +1 -1
  3. package/dist/agent-pins.d.ts.map +1 -1
  4. package/dist/agent-pins.js +18 -2
  5. package/dist/agent-pins.js.map +1 -1
  6. package/dist/app.d.ts +110 -17
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +163 -35
  9. package/dist/app.js.map +1 -1
  10. package/dist/block-publish.d.ts +56 -0
  11. package/dist/block-publish.d.ts.map +1 -0
  12. package/dist/block-publish.js +132 -0
  13. package/dist/block-publish.js.map +1 -0
  14. package/dist/caller.d.ts +24 -0
  15. package/dist/caller.d.ts.map +1 -0
  16. package/dist/caller.js +47 -0
  17. package/dist/caller.js.map +1 -0
  18. package/dist/capability-binding.d.ts +11 -0
  19. package/dist/capability-binding.d.ts.map +1 -1
  20. package/dist/cost-binding.d.ts +19 -0
  21. package/dist/cost-binding.d.ts.map +1 -1
  22. package/dist/cost-binding.js.map +1 -1
  23. package/dist/derive-agent-version.d.ts +7 -0
  24. package/dist/derive-agent-version.d.ts.map +1 -1
  25. package/dist/derive-agent-version.js +4 -0
  26. package/dist/derive-agent-version.js.map +1 -1
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +75 -7
  29. package/dist/errors.js.map +1 -1
  30. package/dist/eval-case-binding.d.ts +16 -4
  31. package/dist/eval-case-binding.d.ts.map +1 -1
  32. package/dist/eval-run-binding.d.ts +31 -0
  33. package/dist/eval-run-binding.d.ts.map +1 -1
  34. package/dist/eval-run-dispatcher.d.ts +7 -0
  35. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  36. package/dist/eval-run-dispatcher.js.map +1 -1
  37. package/dist/eval-sample.d.ts +11 -0
  38. package/dist/eval-sample.d.ts.map +1 -0
  39. package/dist/eval-sample.js +34 -0
  40. package/dist/eval-sample.js.map +1 -0
  41. package/dist/eval-suite-binding.d.ts +13 -0
  42. package/dist/eval-suite-binding.d.ts.map +1 -1
  43. package/dist/eval-suite-binding.js.map +1 -1
  44. package/dist/flow-binding.d.ts +18 -0
  45. package/dist/flow-binding.d.ts.map +1 -1
  46. package/dist/flow-pins.d.ts.map +1 -1
  47. package/dist/flow-pins.js +18 -2
  48. package/dist/flow-pins.js.map +1 -1
  49. package/dist/gate.d.ts.map +1 -1
  50. package/dist/gate.js +25 -0
  51. package/dist/gate.js.map +1 -1
  52. package/dist/handler-binding.d.ts +32 -0
  53. package/dist/handler-binding.d.ts.map +1 -1
  54. package/dist/hitl-binding.d.ts +23 -0
  55. package/dist/hitl-binding.d.ts.map +1 -1
  56. package/dist/identity-directory-binding.d.ts +82 -4
  57. package/dist/identity-directory-binding.d.ts.map +1 -1
  58. package/dist/identity-provider-binding.d.ts +197 -17
  59. package/dist/identity-provider-binding.d.ts.map +1 -1
  60. package/dist/improvement-pass-binding.d.ts +196 -0
  61. package/dist/improvement-pass-binding.d.ts.map +1 -0
  62. package/dist/improvement-pass-binding.js +9 -0
  63. package/dist/improvement-pass-binding.js.map +1 -0
  64. package/dist/index.d.ts +35 -17
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +11 -3
  67. package/dist/index.js.map +1 -1
  68. package/dist/judged-dispatcher.d.ts +25 -4
  69. package/dist/judged-dispatcher.d.ts.map +1 -1
  70. package/dist/judged-dispatcher.js +43 -6
  71. package/dist/judged-dispatcher.js.map +1 -1
  72. package/dist/judgment-binding.d.ts +25 -1
  73. package/dist/judgment-binding.d.ts.map +1 -1
  74. package/dist/mcp-endpoint-binding.d.ts +7 -0
  75. package/dist/mcp-endpoint-binding.d.ts.map +1 -1
  76. package/dist/memory-binding.d.ts +124 -17
  77. package/dist/memory-binding.d.ts.map +1 -1
  78. package/dist/memory-erasure-binding.d.ts +145 -0
  79. package/dist/memory-erasure-binding.d.ts.map +1 -0
  80. package/dist/memory-erasure-binding.js +4 -0
  81. package/dist/memory-erasure-binding.js.map +1 -0
  82. package/dist/middleware/auth.d.ts +66 -13
  83. package/dist/middleware/auth.d.ts.map +1 -1
  84. package/dist/middleware/auth.js +150 -50
  85. package/dist/middleware/auth.js.map +1 -1
  86. package/dist/middleware/authorize.d.ts +9 -0
  87. package/dist/middleware/authorize.d.ts.map +1 -1
  88. package/dist/middleware/authorize.js +122 -4
  89. package/dist/middleware/authorize.js.map +1 -1
  90. package/dist/middleware/error-mapper.d.ts +5 -0
  91. package/dist/middleware/error-mapper.d.ts.map +1 -1
  92. package/dist/middleware/error-mapper.js +14 -1
  93. package/dist/middleware/error-mapper.js.map +1 -1
  94. package/dist/middleware/idempotency.d.ts +70 -5
  95. package/dist/middleware/idempotency.d.ts.map +1 -1
  96. package/dist/middleware/idempotency.js +174 -41
  97. package/dist/middleware/idempotency.js.map +1 -1
  98. package/dist/middleware/key-project.d.ts +17 -0
  99. package/dist/middleware/key-project.d.ts.map +1 -0
  100. package/dist/middleware/key-project.js +75 -0
  101. package/dist/middleware/key-project.js.map +1 -0
  102. package/dist/middleware/principal.d.ts.map +1 -1
  103. package/dist/middleware/principal.js +9 -5
  104. package/dist/middleware/principal.js.map +1 -1
  105. package/dist/middleware/project-ref.d.ts.map +1 -1
  106. package/dist/middleware/project-ref.js +3 -0
  107. package/dist/middleware/project-ref.js.map +1 -1
  108. package/dist/openapi/generate.d.ts.map +1 -1
  109. package/dist/openapi/generate.js +5 -2
  110. package/dist/openapi/generate.js.map +1 -1
  111. package/dist/openapi/operations.d.ts.map +1 -1
  112. package/dist/openapi/operations.js +919 -140
  113. package/dist/openapi/operations.js.map +1 -1
  114. package/dist/openapi/schemas.d.ts +90 -13
  115. package/dist/openapi/schemas.d.ts.map +1 -1
  116. package/dist/openapi/schemas.js +2081 -359
  117. package/dist/openapi/schemas.js.map +1 -1
  118. package/dist/person-grants-binding.d.ts +77 -0
  119. package/dist/person-grants-binding.d.ts.map +1 -0
  120. package/dist/person-grants-binding.js +4 -0
  121. package/dist/person-grants-binding.js.map +1 -0
  122. package/dist/proposal-service.d.ts +121 -0
  123. package/dist/proposal-service.d.ts.map +1 -0
  124. package/dist/proposal-service.js +447 -0
  125. package/dist/proposal-service.js.map +1 -0
  126. package/dist/proposal-status.d.ts +60 -0
  127. package/dist/proposal-status.d.ts.map +1 -0
  128. package/dist/proposal-status.js +109 -0
  129. package/dist/proposal-status.js.map +1 -0
  130. package/dist/provider-binding.d.ts +10 -0
  131. package/dist/provider-binding.d.ts.map +1 -1
  132. package/dist/publish-refused.d.ts +28 -3
  133. package/dist/publish-refused.d.ts.map +1 -1
  134. package/dist/publish-refused.js +24 -3
  135. package/dist/publish-refused.js.map +1 -1
  136. package/dist/routes/adapters.d.ts +2 -1
  137. package/dist/routes/adapters.d.ts.map +1 -1
  138. package/dist/routes/adapters.js +3 -1
  139. package/dist/routes/adapters.js.map +1 -1
  140. package/dist/routes/agent-releases.d.ts +55 -3
  141. package/dist/routes/agent-releases.d.ts.map +1 -1
  142. package/dist/routes/agent-releases.js +85 -55
  143. package/dist/routes/agent-releases.js.map +1 -1
  144. package/dist/routes/agents.d.ts +12 -1
  145. package/dist/routes/agents.d.ts.map +1 -1
  146. package/dist/routes/agents.js +100 -2
  147. package/dist/routes/agents.js.map +1 -1
  148. package/dist/routes/approvals.d.ts +15 -3
  149. package/dist/routes/approvals.d.ts.map +1 -1
  150. package/dist/routes/approvals.js +133 -122
  151. package/dist/routes/approvals.js.map +1 -1
  152. package/dist/routes/artifacts.d.ts +25 -3
  153. package/dist/routes/artifacts.d.ts.map +1 -1
  154. package/dist/routes/artifacts.js +116 -7
  155. package/dist/routes/artifacts.js.map +1 -1
  156. package/dist/routes/auth.d.ts +25 -1
  157. package/dist/routes/auth.d.ts.map +1 -1
  158. package/dist/routes/auth.js +655 -281
  159. package/dist/routes/auth.js.map +1 -1
  160. package/dist/routes/blocks.d.ts.map +1 -1
  161. package/dist/routes/blocks.js +2 -42
  162. package/dist/routes/blocks.js.map +1 -1
  163. package/dist/routes/capabilities.d.ts +2 -1
  164. package/dist/routes/capabilities.d.ts.map +1 -1
  165. package/dist/routes/capabilities.js +6 -1
  166. package/dist/routes/capabilities.js.map +1 -1
  167. package/dist/routes/compliance.d.ts +9 -10
  168. package/dist/routes/compliance.d.ts.map +1 -1
  169. package/dist/routes/compliance.js +42 -61
  170. package/dist/routes/compliance.js.map +1 -1
  171. package/dist/routes/conversations.d.ts +8 -1
  172. package/dist/routes/conversations.d.ts.map +1 -1
  173. package/dist/routes/conversations.js +87 -8
  174. package/dist/routes/conversations.js.map +1 -1
  175. package/dist/routes/cost.d.ts +12 -1
  176. package/dist/routes/cost.d.ts.map +1 -1
  177. package/dist/routes/cost.js +74 -3
  178. package/dist/routes/cost.js.map +1 -1
  179. package/dist/routes/denied.d.ts +11 -0
  180. package/dist/routes/denied.d.ts.map +1 -0
  181. package/dist/routes/denied.js +17 -0
  182. package/dist/routes/denied.js.map +1 -0
  183. package/dist/routes/deployments.d.ts +10 -1
  184. package/dist/routes/deployments.d.ts.map +1 -1
  185. package/dist/routes/deployments.js +171 -13
  186. package/dist/routes/deployments.js.map +1 -1
  187. package/dist/routes/eval-comparison.d.ts.map +1 -1
  188. package/dist/routes/eval-comparison.js +69 -1
  189. package/dist/routes/eval-comparison.js.map +1 -1
  190. package/dist/routes/eval-overrides.d.ts +18 -0
  191. package/dist/routes/eval-overrides.d.ts.map +1 -0
  192. package/dist/routes/eval-overrides.js +81 -0
  193. package/dist/routes/eval-overrides.js.map +1 -0
  194. package/dist/routes/eval-runs.d.ts +10 -1
  195. package/dist/routes/eval-runs.d.ts.map +1 -1
  196. package/dist/routes/eval-runs.js +66 -7
  197. package/dist/routes/eval-runs.js.map +1 -1
  198. package/dist/routes/eval-suites.d.ts.map +1 -1
  199. package/dist/routes/eval-suites.js +28 -2
  200. package/dist/routes/eval-suites.js.map +1 -1
  201. package/dist/routes/event-triggers.d.ts +5 -1
  202. package/dist/routes/event-triggers.d.ts.map +1 -1
  203. package/dist/routes/event-triggers.js +26 -3
  204. package/dist/routes/event-triggers.js.map +1 -1
  205. package/dist/routes/export-signing-keys.d.ts +12 -0
  206. package/dist/routes/export-signing-keys.d.ts.map +1 -0
  207. package/dist/routes/export-signing-keys.js +24 -0
  208. package/dist/routes/export-signing-keys.js.map +1 -0
  209. package/dist/routes/flows.d.ts.map +1 -1
  210. package/dist/routes/flows.js +9 -1
  211. package/dist/routes/flows.js.map +1 -1
  212. package/dist/routes/gate-policies.d.ts +4 -1
  213. package/dist/routes/gate-policies.d.ts.map +1 -1
  214. package/dist/routes/gate-policies.js +29 -5
  215. package/dist/routes/gate-policies.js.map +1 -1
  216. package/dist/routes/guardrails.d.ts +16 -14
  217. package/dist/routes/guardrails.d.ts.map +1 -1
  218. package/dist/routes/guardrails.js +39 -3
  219. package/dist/routes/guardrails.js.map +1 -1
  220. package/dist/routes/identity.d.ts +20 -4
  221. package/dist/routes/identity.d.ts.map +1 -1
  222. package/dist/routes/identity.js +246 -6
  223. package/dist/routes/identity.js.map +1 -1
  224. package/dist/routes/improvement-passes.d.ts +52 -0
  225. package/dist/routes/improvement-passes.d.ts.map +1 -0
  226. package/dist/routes/improvement-passes.js +449 -0
  227. package/dist/routes/improvement-passes.js.map +1 -0
  228. package/dist/routes/judged-suites.d.ts +50 -0
  229. package/dist/routes/judged-suites.d.ts.map +1 -1
  230. package/dist/routes/judged-suites.js +66 -27
  231. package/dist/routes/judged-suites.js.map +1 -1
  232. package/dist/routes/judgment-context.d.ts +18 -2
  233. package/dist/routes/judgment-context.d.ts.map +1 -1
  234. package/dist/routes/judgment-context.js +63 -5
  235. package/dist/routes/judgment-context.js.map +1 -1
  236. package/dist/routes/judgment-flow-context.d.ts.map +1 -1
  237. package/dist/routes/judgment-flow-context.js +14 -2
  238. package/dist/routes/judgment-flow-context.js.map +1 -1
  239. package/dist/routes/judgments.d.ts.map +1 -1
  240. package/dist/routes/judgments.js +8 -1
  241. package/dist/routes/judgments.js.map +1 -1
  242. package/dist/routes/mcp.d.ts.map +1 -1
  243. package/dist/routes/mcp.js +26 -1
  244. package/dist/routes/mcp.js.map +1 -1
  245. package/dist/routes/memory-access.d.ts +43 -0
  246. package/dist/routes/memory-access.d.ts.map +1 -0
  247. package/dist/routes/memory-access.js +114 -0
  248. package/dist/routes/memory-access.js.map +1 -0
  249. package/dist/routes/memory-erasures.d.ts +25 -0
  250. package/dist/routes/memory-erasures.d.ts.map +1 -0
  251. package/dist/routes/memory-erasures.js +214 -0
  252. package/dist/routes/memory-erasures.js.map +1 -0
  253. package/dist/routes/memory-parse.d.ts +38 -0
  254. package/dist/routes/memory-parse.d.ts.map +1 -0
  255. package/dist/routes/memory-parse.js +199 -0
  256. package/dist/routes/memory-parse.js.map +1 -0
  257. package/dist/routes/memory.d.ts +9 -4
  258. package/dist/routes/memory.d.ts.map +1 -1
  259. package/dist/routes/memory.js +226 -234
  260. package/dist/routes/memory.js.map +1 -1
  261. package/dist/routes/observations.d.ts +4 -1
  262. package/dist/routes/observations.d.ts.map +1 -1
  263. package/dist/routes/observations.js +8 -2
  264. package/dist/routes/observations.js.map +1 -1
  265. package/dist/routes/pagination.d.ts +7 -0
  266. package/dist/routes/pagination.d.ts.map +1 -1
  267. package/dist/routes/pagination.js +10 -0
  268. package/dist/routes/pagination.js.map +1 -1
  269. package/dist/routes/policies.d.ts +2 -1
  270. package/dist/routes/policies.d.ts.map +1 -1
  271. package/dist/routes/policies.js +3 -1
  272. package/dist/routes/policies.js.map +1 -1
  273. package/dist/routes/project-mismatch.d.ts +22 -0
  274. package/dist/routes/project-mismatch.d.ts.map +1 -0
  275. package/dist/routes/project-mismatch.js +34 -0
  276. package/dist/routes/project-mismatch.js.map +1 -0
  277. package/dist/routes/projects.d.ts +15 -4
  278. package/dist/routes/projects.d.ts.map +1 -1
  279. package/dist/routes/projects.js +100 -9
  280. package/dist/routes/projects.js.map +1 -1
  281. package/dist/routes/proposals.d.ts +25 -17
  282. package/dist/routes/proposals.d.ts.map +1 -1
  283. package/dist/routes/proposals.js +340 -507
  284. package/dist/routes/proposals.js.map +1 -1
  285. package/dist/routes/provenance.d.ts +17 -3
  286. package/dist/routes/provenance.d.ts.map +1 -1
  287. package/dist/routes/provenance.js +79 -103
  288. package/dist/routes/provenance.js.map +1 -1
  289. package/dist/routes/providers.d.ts +17 -1
  290. package/dist/routes/providers.d.ts.map +1 -1
  291. package/dist/routes/providers.js +110 -3
  292. package/dist/routes/providers.js.map +1 -1
  293. package/dist/routes/public-run-tokens.d.ts.map +1 -1
  294. package/dist/routes/public-run-tokens.js +3 -0
  295. package/dist/routes/public-run-tokens.js.map +1 -1
  296. package/dist/routes/readable-projects.d.ts +26 -0
  297. package/dist/routes/readable-projects.d.ts.map +1 -0
  298. package/dist/routes/readable-projects.js +39 -0
  299. package/dist/routes/readable-projects.js.map +1 -0
  300. package/dist/routes/runs.d.ts +10 -0
  301. package/dist/routes/runs.d.ts.map +1 -1
  302. package/dist/routes/runs.js +92 -42
  303. package/dist/routes/runs.js.map +1 -1
  304. package/dist/routes/schedules.d.ts +21 -13
  305. package/dist/routes/schedules.d.ts.map +1 -1
  306. package/dist/routes/schedules.js +416 -55
  307. package/dist/routes/schedules.js.map +1 -1
  308. package/dist/routes/segments.d.ts +2 -0
  309. package/dist/routes/segments.d.ts.map +1 -1
  310. package/dist/routes/segments.js +5 -0
  311. package/dist/routes/segments.js.map +1 -1
  312. package/dist/routes/service-accounts.d.ts +17 -0
  313. package/dist/routes/service-accounts.d.ts.map +1 -0
  314. package/dist/routes/service-accounts.js +212 -0
  315. package/dist/routes/service-accounts.js.map +1 -0
  316. package/dist/routes/sign-in-options.d.ts +50 -0
  317. package/dist/routes/sign-in-options.d.ts.map +1 -0
  318. package/dist/routes/sign-in-options.js +98 -0
  319. package/dist/routes/sign-in-options.js.map +1 -0
  320. package/dist/routes/signing-keys.d.ts +2 -1
  321. package/dist/routes/signing-keys.d.ts.map +1 -1
  322. package/dist/routes/signing-keys.js +3 -1
  323. package/dist/routes/signing-keys.js.map +1 -1
  324. package/dist/routes/tenant-access.d.ts +13 -0
  325. package/dist/routes/tenant-access.d.ts.map +1 -0
  326. package/dist/routes/tenant-access.js +26 -0
  327. package/dist/routes/tenant-access.js.map +1 -0
  328. package/dist/routes/tenant.d.ts.map +1 -1
  329. package/dist/routes/tenant.js +4 -0
  330. package/dist/routes/tenant.js.map +1 -1
  331. package/dist/routes/token-sign-in.d.ts +36 -0
  332. package/dist/routes/token-sign-in.d.ts.map +1 -0
  333. package/dist/routes/token-sign-in.js +101 -0
  334. package/dist/routes/token-sign-in.js.map +1 -0
  335. package/dist/routes/tokens.d.ts +15 -5
  336. package/dist/routes/tokens.d.ts.map +1 -1
  337. package/dist/routes/tokens.js +162 -43
  338. package/dist/routes/tokens.js.map +1 -1
  339. package/dist/routes/tools.d.ts.map +1 -1
  340. package/dist/routes/tools.js +9 -1
  341. package/dist/routes/tools.js.map +1 -1
  342. package/dist/routes/trigger-access.d.ts +29 -0
  343. package/dist/routes/trigger-access.d.ts.map +1 -0
  344. package/dist/routes/trigger-access.js +33 -0
  345. package/dist/routes/trigger-access.js.map +1 -0
  346. package/dist/routes/webhook-endpoints.d.ts +2 -1
  347. package/dist/routes/webhook-endpoints.d.ts.map +1 -1
  348. package/dist/routes/webhook-endpoints.js +11 -3
  349. package/dist/routes/webhook-endpoints.js.map +1 -1
  350. package/dist/routes/webhooks.d.ts +5 -1
  351. package/dist/routes/webhooks.d.ts.map +1 -1
  352. package/dist/routes/webhooks.js +25 -2
  353. package/dist/routes/webhooks.js.map +1 -1
  354. package/dist/run-failure.d.ts +21 -0
  355. package/dist/run-failure.d.ts.map +1 -0
  356. package/dist/run-failure.js +29 -0
  357. package/dist/run-failure.js.map +1 -0
  358. package/dist/service-account-binding.d.ts +108 -0
  359. package/dist/service-account-binding.d.ts.map +1 -0
  360. package/dist/service-account-binding.js +4 -0
  361. package/dist/service-account-binding.js.map +1 -0
  362. package/dist/session-store-binding.d.ts +61 -13
  363. package/dist/session-store-binding.d.ts.map +1 -1
  364. package/dist/signed-export.d.ts +89 -0
  365. package/dist/signed-export.d.ts.map +1 -0
  366. package/dist/signed-export.js +149 -0
  367. package/dist/signed-export.js.map +1 -0
  368. package/dist/supervisor-binding.d.ts +186 -413
  369. package/dist/supervisor-binding.d.ts.map +1 -1
  370. package/dist/testing/app-bindings.d.ts +33 -0
  371. package/dist/testing/app-bindings.d.ts.map +1 -0
  372. package/dist/testing/app-bindings.js +112 -0
  373. package/dist/testing/app-bindings.js.map +1 -0
  374. package/dist/testing/index.d.ts +11 -0
  375. package/dist/testing/index.d.ts.map +1 -0
  376. package/dist/testing/index.js +13 -0
  377. package/dist/testing/index.js.map +1 -0
  378. package/dist/testing/stub-binding.d.ts +34 -0
  379. package/dist/testing/stub-binding.d.ts.map +1 -0
  380. package/dist/testing/stub-binding.js +42 -0
  381. package/dist/testing/stub-binding.js.map +1 -0
  382. package/dist/testing/trigger-registry.d.ts +21 -0
  383. package/dist/testing/trigger-registry.d.ts.map +1 -0
  384. package/dist/testing/trigger-registry.js +206 -0
  385. package/dist/testing/trigger-registry.js.map +1 -0
  386. package/dist/token-admin.d.ts +46 -8
  387. package/dist/token-admin.d.ts.map +1 -1
  388. package/dist/token-admin.js.map +1 -1
  389. package/dist/tool-binding.d.ts +13 -0
  390. package/dist/tool-binding.d.ts.map +1 -1
  391. package/dist/trigger-binding.d.ts +2 -2
  392. package/dist/trigger-binding.d.ts.map +1 -1
  393. package/dist/trigger-binding.js +1 -1
  394. package/dist/trigger-binding.js.map +1 -1
  395. package/dist/types.d.ts +16 -0
  396. package/dist/types.d.ts.map +1 -1
  397. package/dist/webhook-endpoint-binding.d.ts +19 -3
  398. package/dist/webhook-endpoint-binding.d.ts.map +1 -1
  399. package/dist/webhook-endpoint-binding.js +1 -1
  400. package/dist/webhook-endpoint-binding.js.map +1 -1
  401. package/openapi.json +15387 -8789
  402. package/package.json +26 -22
  403. package/src/agent-binding.ts +14 -0
  404. package/src/agent-pins.ts +18 -2
  405. package/src/app.ts +366 -80
  406. package/src/block-publish.ts +181 -0
  407. package/src/caller.ts +62 -0
  408. package/src/capability-binding.ts +12 -0
  409. package/src/cost-binding.ts +19 -0
  410. package/src/derive-agent-version.ts +9 -1
  411. package/src/errors.ts +75 -7
  412. package/src/eval-case-binding.ts +17 -1
  413. package/src/eval-run-binding.ts +31 -0
  414. package/src/eval-run-dispatcher.ts +7 -0
  415. package/src/eval-sample.ts +42 -0
  416. package/src/eval-suite-binding.ts +14 -0
  417. package/src/flow-binding.ts +19 -0
  418. package/src/flow-pins.ts +18 -2
  419. package/src/gate.ts +26 -0
  420. package/src/handler-binding.ts +36 -1
  421. package/src/hitl-binding.ts +24 -0
  422. package/src/identity-directory-binding.ts +85 -4
  423. package/src/identity-provider-binding.ts +216 -21
  424. package/src/improvement-pass-binding.ts +193 -0
  425. package/src/index.ts +153 -31
  426. package/src/judged-dispatcher.ts +78 -11
  427. package/src/judgment-binding.ts +25 -1
  428. package/src/mcp-endpoint-binding.ts +7 -0
  429. package/src/memory-binding.ts +121 -17
  430. package/src/memory-erasure-binding.ts +156 -0
  431. package/src/middleware/auth.ts +228 -62
  432. package/src/middleware/authorize.ts +155 -3
  433. package/src/middleware/error-mapper.ts +15 -1
  434. package/src/middleware/idempotency.ts +230 -43
  435. package/src/middleware/key-project.ts +86 -0
  436. package/src/middleware/principal.ts +9 -5
  437. package/src/middleware/project-ref.ts +3 -0
  438. package/src/openapi/generate.ts +11 -2
  439. package/src/openapi/operations.ts +1060 -143
  440. package/src/openapi/schemas.ts +2387 -469
  441. package/src/person-grants-binding.ts +76 -0
  442. package/src/proposal-service.ts +640 -0
  443. package/src/proposal-status.ts +176 -0
  444. package/src/provider-binding.ts +10 -0
  445. package/src/publish-refused.ts +56 -9
  446. package/src/routes/adapters.ts +4 -0
  447. package/src/routes/agent-releases.ts +121 -69
  448. package/src/routes/agents.ts +128 -1
  449. package/src/routes/approvals.ts +164 -154
  450. package/src/routes/artifacts.ts +181 -11
  451. package/src/routes/auth.ts +804 -336
  452. package/src/routes/blocks.ts +2 -53
  453. package/src/routes/capabilities.ts +10 -1
  454. package/src/routes/compliance.ts +60 -99
  455. package/src/routes/conversations.ts +101 -7
  456. package/src/routes/cost.ts +110 -4
  457. package/src/routes/denied.ts +28 -0
  458. package/src/routes/deployments.ts +210 -17
  459. package/src/routes/eval-comparison.ts +81 -2
  460. package/src/routes/eval-overrides.ts +108 -0
  461. package/src/routes/eval-runs.ts +89 -6
  462. package/src/routes/eval-suites.ts +32 -2
  463. package/src/routes/event-triggers.ts +27 -3
  464. package/src/routes/export-signing-keys.ts +31 -0
  465. package/src/routes/flows.ts +12 -1
  466. package/src/routes/gate-policies.ts +37 -6
  467. package/src/routes/guardrails.ts +61 -2
  468. package/src/routes/identity.ts +328 -10
  469. package/src/routes/improvement-passes.ts +541 -0
  470. package/src/routes/judged-suites.ts +113 -43
  471. package/src/routes/judgment-context.ts +76 -5
  472. package/src/routes/judgment-flow-context.ts +16 -2
  473. package/src/routes/judgments.ts +17 -3
  474. package/src/routes/mcp.ts +29 -1
  475. package/src/routes/memory-access.ts +160 -0
  476. package/src/routes/memory-erasures.ts +240 -0
  477. package/src/routes/memory-parse.ts +250 -0
  478. package/src/routes/memory.ts +244 -286
  479. package/src/routes/observations.ts +15 -2
  480. package/src/routes/pagination.ts +12 -0
  481. package/src/routes/policies.ts +7 -1
  482. package/src/routes/project-mismatch.ts +56 -0
  483. package/src/routes/projects.ts +107 -13
  484. package/src/routes/proposals.ts +370 -611
  485. package/src/routes/provenance.ts +99 -133
  486. package/src/routes/providers.ts +142 -3
  487. package/src/routes/public-run-tokens.ts +3 -0
  488. package/src/routes/readable-projects.ts +66 -0
  489. package/src/routes/runs.ts +119 -39
  490. package/src/routes/schedules.ts +472 -60
  491. package/src/routes/segments.ts +11 -0
  492. package/src/routes/service-accounts.ts +262 -0
  493. package/src/routes/sign-in-options.ts +168 -0
  494. package/src/routes/signing-keys.ts +7 -1
  495. package/src/routes/tenant-access.ts +37 -0
  496. package/src/routes/tenant.ts +6 -0
  497. package/src/routes/token-sign-in.ts +161 -0
  498. package/src/routes/tokens.ts +172 -46
  499. package/src/routes/tools.ts +12 -1
  500. package/src/routes/trigger-access.ts +72 -0
  501. package/src/routes/webhook-endpoints.ts +15 -3
  502. package/src/routes/webhooks.ts +26 -2
  503. package/src/run-failure.ts +42 -0
  504. package/src/service-account-binding.ts +113 -0
  505. package/src/session-store-binding.ts +65 -13
  506. package/src/signed-export.ts +250 -0
  507. package/src/supervisor-binding.ts +169 -409
  508. package/src/testing/app-bindings.ts +142 -0
  509. package/src/testing/index.ts +21 -0
  510. package/src/testing/stub-binding.ts +53 -0
  511. package/src/testing/trigger-registry.ts +259 -0
  512. package/src/token-admin.ts +40 -8
  513. package/src/tool-binding.ts +14 -0
  514. package/src/trigger-binding.ts +8 -1
  515. package/src/types.ts +16 -0
  516. package/src/webhook-endpoint-binding.ts +18 -3
@@ -4,36 +4,88 @@
4
4
  import { Hono } from 'hono';
5
5
  import type { Context } from 'hono';
6
6
 
7
- import type { Cursor, TenantId, TriggerId } from '@kindgi/types';
7
+ import { type Action, type ResourceRef, ref } from '@kindgi/authz';
8
+ import type { ProjectBinding } from '@kindgi/platform';
9
+ import type { Cursor, ProjectId, TenantId, TriggerId } from '@kindgi/types';
8
10
 
9
11
  import { statusFor, toWireError } from '../errors.js';
10
- import type {
11
- CronTriggerRecord,
12
- RegisterCronTriggerInput,
13
- TriggerRegistryBinding,
14
- UpdateCronTriggerInput,
12
+ import type { Authorizer } from '../middleware/authorize.js';
13
+ import {
14
+ type CronTriggerRecord,
15
+ type RegisterCronTriggerInput,
16
+ SCHEDULE_DEFAULTS,
17
+ type ScheduleCatchUp,
18
+ type ScheduleOverlap,
19
+ type TriggerFire,
20
+ type TriggerOwner,
21
+ type TriggerRegistryBinding,
22
+ type TriggerTarget,
23
+ type UpdateCronTriggerInput,
15
24
  } from '../trigger-binding.js';
16
25
  import type { AppEnv } from '../types.js';
26
+ import { parseImproveScheduleInput } from './improvement-passes.js';
27
+ import { liveScopeToWire, parseLiveScopeBody } from './live-scope-wire.js';
17
28
  import { clampLimit } from './pagination.js';
29
+ import { UUID_RE } from './uuid-param.js';
18
30
 
19
31
  /**
20
- * Schedules — cron-kind triggers.
32
+ * Schedules: cron-kind triggers that start a run of an agent or a flow.
21
33
  *
22
- * Seven routes, all soft-delete-shaped per framework convention:
23
- * - POST /v1/schedules (register)
24
- * - GET /v1/schedules (list, cursor-paginated)
25
- * - GET /v1/schedules/:triggerId (get)
26
- * - PATCH /v1/schedules/:triggerId (update cron/label/flowVersion)
27
- * - POST /v1/schedules/:triggerId/pause
28
- * - POST /v1/schedules/:triggerId/resume
29
- * - POST /v1/schedules/:triggerId/unregister (tombstone — GC per policy)
34
+ * POST /v1/schedules register
35
+ * GET /v1/schedules list (cursor-paginated)
36
+ * GET /v1/schedules/:triggerId[?upcoming=N] get, with its next N occurrences
37
+ * PATCH /v1/schedules/:triggerId update
38
+ * POST /v1/schedules/:triggerId/pause | resume | unregister
39
+ * GET /v1/schedules/:triggerId/fires its fire history, newest first
40
+ * POST /v1/schedules/:triggerId/run-now fire it now, outside the schedule
41
+ * POST /v1/schedules/:triggerId/owner the caller becomes the owner
30
42
  *
31
- * The `triggerId` URL param is the trigger's id; the response body
32
- * aliases it as `scheduleId` for a friendlier client surface.
43
+ * A schedule's runs act as its owner (whoever registered it, until an
44
+ * admin takes it over), checked again at every fire. With an authorizer:
45
+ * reads need `read` on the schedule's project, changes `write`, taking
46
+ * ownership `admin`, and registering or retargeting also needs `execute`
47
+ * on what it runs, as starting that run does. The `triggerId` is aliased
48
+ * as `scheduleId` in bodies.
33
49
  */
34
- export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
50
+ export function schedulesRouter(
51
+ binding: TriggerRegistryBinding,
52
+ authorizer?: Authorizer,
53
+ /** The tenant's Default project: where a schedule that names no project goes. */
54
+ projects?: Pick<ProjectBinding, 'getDefault'>,
55
+ ): Hono<AppEnv> {
35
56
  const r = new Hono<AppEnv>();
36
57
 
58
+ /** Nothing, when allowed; else the authorizer's own 403. */
59
+ async function denied(
60
+ c: Context<AppEnv>,
61
+ action: Action,
62
+ resource: ResourceRef,
63
+ ): Promise<Response | undefined> {
64
+ if (authorizer === undefined) return undefined;
65
+ let allowed = false;
66
+ const answer = await authorizer.authorize(action, async () => resource)(c, async () => {
67
+ allowed = true;
68
+ });
69
+ return allowed ? undefined : (answer as Response);
70
+ }
71
+
72
+ /** The schedule, if it is one (another kind's id is not found here), and the caller may `action` it. */
73
+ async function scheduleFor(
74
+ c: Context<AppEnv>,
75
+ action: Action,
76
+ ): Promise<{ kind: 'ok'; value: CronTriggerRecord } | { kind: 'err'; response: Response }> {
77
+ const requestId = c.get('requestId');
78
+ const tenantId = c.get('tenantId') as TenantId;
79
+ const triggerId = c.req.param('triggerId') as TriggerId;
80
+ const rec = UUID_RE.test(triggerId) ? await binding.get({ tenantId, triggerId }) : null;
81
+ if (rec === null || rec.kind !== 'cron') {
82
+ return { kind: 'err', response: notFound(c, requestId, triggerId) };
83
+ }
84
+ const refused = await denied(c, action, ref('project', rec.projectId as unknown as string));
85
+ if (refused !== undefined) return { kind: 'err', response: refused };
86
+ return { kind: 'ok', value: rec };
87
+ }
88
+
37
89
  // ---------- POST / (register) ----------
38
90
  r.post('/', async (c) => {
39
91
  const requestId = c.get('requestId');
@@ -43,24 +95,49 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
43
95
  if (parsed.kind === 'err') return parsed.response;
44
96
  const body = parsed.value;
45
97
 
46
- const flowId = requireString(body, 'flowId');
47
- const flowVersion = requireString(body, 'flowVersion');
48
- const cronExpression = requireString(body.config, 'config.cronExpression');
49
- if (flowId.kind === 'err') return bad(c, requestId, flowId.message);
50
- if (flowVersion.kind === 'err') return bad(c, requestId, flowVersion.message);
98
+ const target = parseTarget(body);
99
+ if (target.kind === 'err') return bad(c, requestId, target.message);
100
+ const cronExpression = requireString(body, 'config.cronExpression');
51
101
  if (cronExpression.kind === 'err') return bad(c, requestId, cronExpression.message);
52
-
102
+ const policy = parsePolicy(body);
103
+ if (policy.kind === 'err') return bad(c, requestId, policy.message);
104
+ const projectId = body.projectId;
105
+ if (projectId !== undefined && (typeof projectId !== 'string' || !UUID_RE.test(projectId))) {
106
+ return bad(c, requestId, '`projectId` must be a project id (a UUID)');
107
+ }
53
108
  const rawConfig = (body.config ?? {}) as Record<string, unknown>;
109
+ const input = targetInput(target.value, rawConfig.input);
110
+ if (input.kind === 'err') return bad(c, requestId, input.message);
111
+
112
+ // A schedule that names no project goes in its improve scope's
113
+ // project, else the tenant's Default project: checked and stored as
114
+ // that project. With no Default to find, the registry picks it, and
115
+ // only a tenant admin may.
116
+ const project =
117
+ (projectId as string | undefined) ??
118
+ scopeProjectOf(target.value) ??
119
+ ((await projects?.getDefault(tenantId))?.id as string | undefined);
120
+ const scopeProblem = improveScopeProblem(target.value, project);
121
+ if (scopeProblem !== undefined) return bad(c, requestId, scopeProblem);
122
+ const refused =
123
+ (project === undefined
124
+ ? await denied(c, 'admin', ref('tenant', tenantId as unknown as string))
125
+ : await denied(c, 'write', ref('project', project))) ??
126
+ (await denied(c, ...targetAccess(target.value)));
127
+ if (refused !== undefined) return refused;
128
+
54
129
  const registerInput: RegisterCronTriggerInput = {
55
130
  kind: 'cron',
56
131
  tenantId,
57
- flowId: flowId.value,
58
- flowVersion: flowVersion.value,
132
+ target: target.value,
133
+ ...(project !== undefined && { projectId: project as ProjectId }),
134
+ owner: ownerOf(c),
59
135
  config: {
60
136
  cronExpression: cronExpression.value,
61
137
  ...(typeof rawConfig.timezone === 'string' && { timezone: rawConfig.timezone }),
62
- ...('input' in rawConfig && { input: rawConfig.input }),
138
+ ...(input.input !== undefined && { input: input.input }),
63
139
  },
140
+ ...policy.value,
64
141
  ...(typeof body.label === 'string' && body.label.length > 0 && { label: body.label }),
65
142
  };
66
143
 
@@ -76,6 +153,10 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
76
153
  });
77
154
 
78
155
  // ---------- GET / (list) ----------
156
+ // The tenant's schedules, then only those whose project the caller may
157
+ // read (`read` on it, as reading one schedule needs): a schedule's input
158
+ // and target are its project's. The page and its cursor are the
159
+ // tenant's, so a page can hold fewer than `limit` rows and still have more.
79
160
  r.get('/', async (c) => {
80
161
  const tenantId = c.get('tenantId') as TenantId;
81
162
  const limit = clampLimit(c.req.query('limit'));
@@ -92,8 +173,15 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
92
173
  ...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
93
174
  ...(statusFilter !== undefined && { status: statusFilter }),
94
175
  });
176
+ const rows = page.data as CronTriggerRecord[];
177
+ const visible =
178
+ authorizer === undefined
179
+ ? rows
180
+ : await authorizer.filterByCan(c, 'read', rows, (rec) =>
181
+ ref('project', rec.projectId as unknown as string),
182
+ );
95
183
  return c.json({
96
- data: page.data.map((row) => serializeSchedule(row as CronTriggerRecord)),
184
+ data: visible.map((row) => serializeSchedule(row)),
97
185
  hasMore: page.nextCursor !== undefined,
98
186
  ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
99
187
  });
@@ -102,24 +190,54 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
102
190
  // ---------- GET /:triggerId (get) ----------
103
191
  r.get('/:triggerId', async (c) => {
104
192
  const requestId = c.get('requestId');
105
- const tenantId = c.get('tenantId') as TenantId;
106
- const triggerId = c.req.param('triggerId') as TriggerId;
107
-
108
- const rec = await binding.get({ tenantId, triggerId });
109
- if (rec === null || rec.kind !== 'cron') return notFound(c, requestId, triggerId);
110
- return c.json(serializeSchedule(rec));
193
+ const upcomingRaw = c.req.query('upcoming');
194
+ const upcoming = upcomingRaw === undefined ? undefined : Number(upcomingRaw);
195
+ if (upcoming !== undefined && (!Number.isInteger(upcoming) || upcoming < 1 || upcoming > 20)) {
196
+ return bad(c, requestId, '`upcoming` must be a whole number from 1 to 20');
197
+ }
198
+ const found = await scheduleFor(c, 'read');
199
+ if (found.kind === 'err') return found.response;
200
+ if (upcoming === undefined) return c.json(serializeSchedule(found.value));
201
+ const rec = await binding.get({
202
+ tenantId: c.get('tenantId') as TenantId,
203
+ triggerId: found.value.triggerId,
204
+ upcoming,
205
+ });
206
+ return c.json(serializeSchedule((rec ?? found.value) as CronTriggerRecord));
111
207
  });
112
208
 
113
209
  // ---------- PATCH /:triggerId (update) ----------
114
210
  r.patch('/:triggerId', async (c) => {
115
211
  const requestId = c.get('requestId');
116
212
  const tenantId = c.get('tenantId') as TenantId;
117
- const triggerId = c.req.param('triggerId') as TriggerId;
118
213
 
119
214
  const parsed = await parseJsonObject(c, requestId);
120
215
  if (parsed.kind === 'err') return parsed.response;
121
216
  const body = parsed.value;
122
217
 
218
+ const retarget =
219
+ 'flowId' in body ||
220
+ 'agentId' in body ||
221
+ 'flowVersion' in body ||
222
+ 'agentVersion' in body ||
223
+ 'improve' in body;
224
+ const target = retarget ? parseTarget(body) : undefined;
225
+ if (target?.kind === 'err') return bad(c, requestId, target.message);
226
+ const policy = parsePolicy(body);
227
+ if (policy.kind === 'err') return bad(c, requestId, policy.message);
228
+
229
+ const found = await scheduleFor(c, 'write');
230
+ if (found.kind === 'err') return found.response;
231
+ if (target !== undefined) {
232
+ const scopeProblem = improveScopeProblem(
233
+ target.value,
234
+ found.value.projectId as unknown as string,
235
+ );
236
+ if (scopeProblem !== undefined) return bad(c, requestId, scopeProblem);
237
+ const refused = await denied(c, ...targetAccess(target.value));
238
+ if (refused !== undefined) return refused;
239
+ }
240
+
123
241
  const patchConfig = body.config as Record<string, unknown> | undefined;
124
242
  const cfg: Partial<{ cronExpression: string; timezone: string; input: unknown }> = {};
125
243
  if (patchConfig !== undefined) {
@@ -128,14 +246,24 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
128
246
  if (typeof patchConfig.timezone === 'string') cfg.timezone = patchConfig.timezone;
129
247
  if ('input' in patchConfig) cfg.input = patchConfig.input;
130
248
  }
249
+ if (target !== undefined || 'input' in cfg) {
250
+ const input = targetInput(
251
+ target?.value ?? found.value.target,
252
+ 'input' in cfg ? cfg.input : found.value.config.input,
253
+ );
254
+ if (input.kind === 'err') return bad(c, requestId, input.message);
255
+ if (input.input !== undefined) cfg.input = input.input;
256
+ }
131
257
 
258
+ const triggerId = found.value.triggerId;
132
259
  const updateInput: UpdateCronTriggerInput = {
133
260
  kind: 'cron',
134
261
  tenantId,
135
262
  triggerId,
136
263
  ...(Object.keys(cfg).length > 0 && { config: cfg }),
264
+ ...(target !== undefined && { target: target.value }),
265
+ ...policy.value,
137
266
  ...('label' in body && { label: body.label === null ? null : (body.label as string) }),
138
- ...(typeof body.flowVersion === 'string' && { flowVersion: body.flowVersion }),
139
267
  };
140
268
 
141
269
  const result = await binding.update(updateInput);
@@ -155,30 +283,24 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
155
283
  return c.json(serializeSchedule(result.value as CronTriggerRecord));
156
284
  });
157
285
 
158
- // ---------- POST /:triggerId/pause ----------
159
- r.post('/:triggerId/pause', async (c) => {
160
- const requestId = c.get('requestId');
161
- const tenantId = c.get('tenantId') as TenantId;
162
- const triggerId = c.req.param('triggerId') as TriggerId;
163
- const result = await binding.pause({ tenantId, triggerId });
164
- if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
165
- return c.json(serializeSchedule(result.value as CronTriggerRecord));
166
- });
167
-
168
- // ---------- POST /:triggerId/resume ----------
169
- r.post('/:triggerId/resume', async (c) => {
170
- const requestId = c.get('requestId');
171
- const tenantId = c.get('tenantId') as TenantId;
172
- const triggerId = c.req.param('triggerId') as TriggerId;
173
- const result = await binding.resume({ tenantId, triggerId });
174
- if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
175
- return c.json(serializeSchedule(result.value as CronTriggerRecord));
176
- });
286
+ // ---------- POST /:triggerId/pause | resume ----------
287
+ for (const verb of ['pause', 'resume'] as const) {
288
+ r.post(`/:triggerId/${verb}`, async (c) => {
289
+ const requestId = c.get('requestId');
290
+ const found = await scheduleFor(c, 'write');
291
+ if (found.kind === 'err') return found.response;
292
+ const { tenantId, triggerId } = found.value;
293
+ const result = await binding[verb]({ tenantId, triggerId });
294
+ if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
295
+ return c.json(serializeSchedule(result.value as CronTriggerRecord));
296
+ });
297
+ }
177
298
 
178
299
  // ---------- POST /:triggerId/unregister (soft delete) ----------
179
300
  r.post('/:triggerId/unregister', async (c) => {
180
- const tenantId = c.get('tenantId') as TenantId;
181
- const triggerId = c.req.param('triggerId') as TriggerId;
301
+ const found = await scheduleFor(c, 'write');
302
+ if (found.kind === 'err') return found.response;
303
+ const { tenantId, triggerId } = found.value;
182
304
  const outcome = await binding.unregister({ tenantId, triggerId });
183
305
  return c.json({
184
306
  scheduleId: triggerId as unknown as string,
@@ -186,6 +308,53 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
186
308
  });
187
309
  });
188
310
 
311
+ // ---------- GET /:triggerId/fires (history) ----------
312
+ r.get('/:triggerId/fires', async (c) => {
313
+ const requestId = c.get('requestId');
314
+ const found = await scheduleFor(c, 'read');
315
+ if (found.kind === 'err') return found.response;
316
+ if (binding.listFires === undefined) return unsupported(c, requestId, 'fire history');
317
+ const cursorRaw = c.req.query('cursor');
318
+ const page = await binding.listFires({
319
+ tenantId: found.value.tenantId,
320
+ triggerId: found.value.triggerId,
321
+ limit: clampLimit(c.req.query('limit')),
322
+ ...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
323
+ });
324
+ return c.json({
325
+ data: page.data.map(serializeFire),
326
+ hasMore: page.nextCursor !== undefined,
327
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
328
+ });
329
+ });
330
+
331
+ // ---------- POST /:triggerId/run-now ----------
332
+ r.post('/:triggerId/run-now', async (c) => {
333
+ const requestId = c.get('requestId');
334
+ const found = await scheduleFor(c, 'write');
335
+ if (found.kind === 'err') return found.response;
336
+ if (binding.fireNow === undefined) return unsupported(c, requestId, 'run-now');
337
+ const { tenantId, triggerId } = found.value;
338
+ const result = await binding.fireNow({ tenantId, triggerId });
339
+ if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
340
+ c.status(202);
341
+ return c.json(serializeFire(result.value));
342
+ });
343
+
344
+ // ---------- POST /:triggerId/owner (take ownership) ----------
345
+ r.post('/:triggerId/owner', async (c) => {
346
+ const requestId = c.get('requestId');
347
+ const found = await scheduleFor(c, 'admin');
348
+ if (found.kind === 'err') return found.response;
349
+ if (binding.setOwner === undefined) return unsupported(c, requestId, 'changing the owner');
350
+ const refused = await denied(c, ...targetAccess(found.value.target));
351
+ if (refused !== undefined) return refused;
352
+ const { tenantId, triggerId } = found.value;
353
+ const result = await binding.setOwner({ tenantId, triggerId, owner: ownerOf(c) });
354
+ if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
355
+ return c.json(serializeSchedule(result.value as CronTriggerRecord));
356
+ });
357
+
189
358
  return r;
190
359
  }
191
360
 
@@ -193,24 +362,254 @@ export function schedulesRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
193
362
  // Shared helpers (co-located to keep each router self-contained).
194
363
  // -----------------------------------------------------------------------
195
364
 
365
+ /** A target on the wire: `flowId` + `flowVersion`, `agentId` (+ `agentVersion`), or `improve`. */
366
+ function targetFields(target: TriggerTarget): Record<string, unknown> {
367
+ switch (target.kind) {
368
+ case 'flow':
369
+ return { flowId: target.flowId, flowVersion: target.flowVersion };
370
+ case 'agent':
371
+ return {
372
+ agentId: target.agentId,
373
+ ...(target.agentVersion !== undefined && { agentVersion: target.agentVersion }),
374
+ };
375
+ case 'improve':
376
+ return { improve: { agentId: target.agentId, scope: liveScopeToWire(target.scope) } };
377
+ }
378
+ }
379
+
196
380
  function serializeSchedule(r: CronTriggerRecord): Record<string, unknown> {
197
381
  return {
198
382
  scheduleId: r.triggerId as unknown as string,
199
383
  triggerId: r.triggerId as unknown as string,
200
- flowId: r.flowId,
201
- flowVersion: r.flowVersion,
384
+ ...targetFields(r.target),
385
+ projectId: r.projectId as unknown as string,
386
+ owner: { kind: r.owner.kind, id: r.owner.id },
202
387
  cronExpression: r.config.cronExpression,
203
388
  ...(r.config.timezone !== undefined && { timezone: r.config.timezone }),
204
389
  ...(r.config.input !== undefined && { input: r.config.input }),
390
+ catchUp: r.catchUp,
391
+ overlap: r.overlap,
392
+ startingDeadlineSeconds: r.startingDeadlineSeconds,
205
393
  label: r.label,
206
394
  status: r.status,
395
+ ...(r.statusReason !== undefined && { statusReason: r.statusReason }),
207
396
  nextFireAt: r.nextFireAt,
397
+ ...(r.upcoming !== undefined && { upcoming: r.upcoming }),
208
398
  lastFiredAt: r.lastFiredAt,
209
399
  createdAt: r.createdAt,
210
400
  updatedAt: r.updatedAt,
211
401
  };
212
402
  }
213
403
 
404
+ function serializeFire(f: TriggerFire): Record<string, unknown> {
405
+ return {
406
+ fireId: f.fireId,
407
+ scheduleId: f.triggerId as unknown as string,
408
+ triggerId: f.triggerId as unknown as string,
409
+ ...(f.scheduledFor !== undefined && { scheduledFor: f.scheduledFor }),
410
+ firedAt: f.firedAt,
411
+ outcome: f.outcome,
412
+ ...(f.runId !== undefined && { runId: f.runId }),
413
+ ...(f.passId !== undefined && { passId: f.passId }),
414
+ ...(f.detail !== undefined && { detail: f.detail }),
415
+ ...(f.missedCount !== undefined && { missedCount: f.missedCount }),
416
+ ...(f.manual === true && { manual: true }),
417
+ };
418
+ }
419
+
420
+ /**
421
+ * What firing the target needs, as starting it by hand does: `execute` on
422
+ * the agent or flow a run starts; `publish` on the agent an improvement
423
+ * pass works on (as `POST /v1/proposals/improve`).
424
+ */
425
+ function targetAccess(target: TriggerTarget): [Action, ResourceRef] {
426
+ switch (target.kind) {
427
+ case 'flow':
428
+ return ['execute', ref('flow', target.flowId)];
429
+ case 'agent':
430
+ return ['execute', ref('agent', target.agentId)];
431
+ case 'improve':
432
+ return ['publish', ref('agent', target.agentId)];
433
+ }
434
+ }
435
+
436
+ /** Who a schedule's runs act as: the request's principal. */
437
+ function ownerOf(c: Context<AppEnv>): TriggerOwner {
438
+ const actor = c.get('principal')?.actor;
439
+ if (actor === undefined) return { kind: 'service', id: 'unknown' };
440
+ return { kind: actor.kind === 'user' ? 'user' : 'service', id: actor.id };
441
+ }
442
+
443
+ /** `flowId` + `flowVersion`, `agentId` (+ `agentVersion`), or `improve`: exactly one target. */
444
+ function parseTarget(
445
+ body: Record<string, unknown>,
446
+ ): { kind: 'ok'; value: TriggerTarget } | { kind: 'err'; message: string } {
447
+ const { flowId, flowVersion, agentId, agentVersion, improve } = body;
448
+ const named = (v: unknown) => typeof v === 'string' && v.length > 0;
449
+ if ([named(flowId), named(agentId), improve !== undefined].filter(Boolean).length !== 1) {
450
+ return {
451
+ kind: 'err',
452
+ message:
453
+ 'Name what the schedule runs: `flowId` (with `flowVersion`), `agentId`, or `improve` ({ agentId, scope }), one of them',
454
+ };
455
+ }
456
+ if (improve !== undefined) return parseImproveTarget(improve, flowVersion, agentVersion);
457
+ if (named(flowId)) {
458
+ if (!named(flowVersion))
459
+ return { kind: 'err', message: '`flowVersion` is required with `flowId`' };
460
+ if (agentVersion !== undefined) {
461
+ return { kind: 'err', message: '`agentVersion` goes with `agentId`, not `flowId`' };
462
+ }
463
+ return {
464
+ kind: 'ok',
465
+ value: { kind: 'flow', flowId: flowId as string, flowVersion: flowVersion as string },
466
+ };
467
+ }
468
+ if (flowVersion !== undefined) {
469
+ return { kind: 'err', message: '`flowVersion` goes with `flowId`, not `agentId`' };
470
+ }
471
+ if (agentVersion !== undefined && !named(agentVersion)) {
472
+ return { kind: 'err', message: '`agentVersion` must be a version (semver)' };
473
+ }
474
+ return {
475
+ kind: 'ok',
476
+ value: {
477
+ kind: 'agent',
478
+ agentId: agentId as string,
479
+ ...(agentVersion !== undefined && { agentVersion: agentVersion as string }),
480
+ },
481
+ };
482
+ }
483
+
484
+ /** An improve scope's project, when it names one. */
485
+ function scopeProjectOf(target: TriggerTarget): string | undefined {
486
+ if (target.kind !== 'improve') return undefined;
487
+ const { scope } = target;
488
+ return scope.kind === 'project' || scope.kind === 'segment'
489
+ ? (scope.projectId as unknown as string)
490
+ : undefined;
491
+ }
492
+
493
+ /**
494
+ * A pass's evidence must cover the scope it changes: an improve schedule
495
+ * learns from its project's runs (for a segment scope, that segment's),
496
+ * so its scope is the schedule's own project or a segment of it. The
497
+ * tenant and an org span projects: going wider stays a promotion by hand,
498
+ * through that scope's gate.
499
+ */
500
+ function improveScopeProblem(
501
+ target: TriggerTarget,
502
+ project: string | undefined,
503
+ ): string | undefined {
504
+ if (target.kind !== 'improve') return undefined;
505
+ if (target.scope.kind === 'tenant' || target.scope.kind === 'org') {
506
+ return `An improve schedule's scope is a project or a segment of it, not the ${target.scope.kind === 'org' ? 'org' : 'tenant'}: a pass's evidence must cover the scope it changes, and it learns from one project's runs. Use the project (or a segment) scope; promote to the ${target.scope.kind === 'org' ? 'org' : 'tenant'} by hand after review.`;
507
+ }
508
+ const own = scopeProjectOf(target);
509
+ if (own !== undefined && project !== undefined && own !== project) {
510
+ return "An improve schedule's scope must be in the schedule's project (`projectId`): it learns from that project's runs";
511
+ }
512
+ return undefined;
513
+ }
514
+
515
+ function parseImproveTarget(
516
+ improve: unknown,
517
+ flowVersion: unknown,
518
+ agentVersion: unknown,
519
+ ): { kind: 'ok'; value: TriggerTarget } | { kind: 'err'; message: string } {
520
+ const shape =
521
+ 'An improve schedule names `improve: { agentId, scope }`: the agent its passes work on, and the live scope they propose for';
522
+ if (flowVersion !== undefined || agentVersion !== undefined) {
523
+ return {
524
+ kind: 'err',
525
+ message: `${shape}; \`flowVersion\` and \`agentVersion\` don't go with it`,
526
+ };
527
+ }
528
+ const o =
529
+ typeof improve === 'object' && improve !== null && !Array.isArray(improve)
530
+ ? (improve as Record<string, unknown>)
531
+ : undefined;
532
+ if (
533
+ o === undefined ||
534
+ Object.keys(o).some((k) => k !== 'agentId' && k !== 'scope') ||
535
+ typeof o.agentId !== 'string' ||
536
+ o.agentId.length === 0
537
+ ) {
538
+ return { kind: 'err', message: shape };
539
+ }
540
+ const scope = parseLiveScopeBody(o.scope);
541
+ if (scope.kind === 'err') return { kind: 'err', message: `\`improve.scope\`: ${scope.message}` };
542
+ return { kind: 'ok', value: { kind: 'improve', agentId: o.agentId, scope: scope.scope } };
543
+ }
544
+
545
+ /**
546
+ * The input a target's fires get, or why it can't be: an agent's run takes
547
+ * the agent payload, so an agent schedule's input must carry the message
548
+ * each run sends (without it every fire would be refused); an improve
549
+ * schedule's input is its pass options, kept with the defaults applied; a
550
+ * flow's input is the flow's own.
551
+ */
552
+ function targetInput(
553
+ target: TriggerTarget,
554
+ input: unknown,
555
+ ): { kind: 'ok'; input?: unknown } | { kind: 'err'; message: string } {
556
+ if (target.kind === 'improve') {
557
+ const parsed = parseImproveScheduleInput(input);
558
+ return parsed.kind === 'ok' ? { kind: 'ok', input: parsed.input } : parsed;
559
+ }
560
+ if (target.kind === 'flow') return { kind: 'ok', ...(input !== undefined && { input }) };
561
+ const message =
562
+ typeof input === 'object' && input !== null
563
+ ? (input as Record<string, unknown>).userMessage
564
+ : undefined;
565
+ if (typeof message === 'string' && message.length > 0) return { kind: 'ok', input };
566
+ return {
567
+ kind: 'err',
568
+ message:
569
+ 'An agent schedule needs `config.input.userMessage`: the message each run sends the agent (`{ userMessage, parameters? }`)',
570
+ };
571
+ }
572
+
573
+ /** `catchUp`, `overlap` and `startingDeadlineSeconds`, each optional. */
574
+ function parsePolicy(body: Record<string, unknown>):
575
+ | {
576
+ kind: 'ok';
577
+ value: {
578
+ catchUp?: ScheduleCatchUp;
579
+ overlap?: ScheduleOverlap;
580
+ startingDeadlineSeconds?: number;
581
+ };
582
+ }
583
+ | { kind: 'err'; message: string } {
584
+ const { catchUp, overlap, startingDeadlineSeconds } = body;
585
+ if (catchUp !== undefined && catchUp !== 'latest' && catchUp !== 'skip') {
586
+ return { kind: 'err', message: '`catchUp` must be `latest` or `skip`' };
587
+ }
588
+ if (overlap !== undefined && overlap !== 'skip' && overlap !== 'allow') {
589
+ return { kind: 'err', message: '`overlap` must be `skip` or `allow`' };
590
+ }
591
+ if (
592
+ startingDeadlineSeconds !== undefined &&
593
+ (typeof startingDeadlineSeconds !== 'number' ||
594
+ !Number.isInteger(startingDeadlineSeconds) ||
595
+ startingDeadlineSeconds < 1 ||
596
+ startingDeadlineSeconds > 86_400)
597
+ ) {
598
+ return {
599
+ kind: 'err',
600
+ message: `\`startingDeadlineSeconds\` must be a whole number of seconds from 1 to 86400 (default ${SCHEDULE_DEFAULTS.startingDeadlineSeconds})`,
601
+ };
602
+ }
603
+ return {
604
+ kind: 'ok',
605
+ value: {
606
+ ...(catchUp !== undefined && { catchUp }),
607
+ ...(overlap !== undefined && { overlap }),
608
+ ...(startingDeadlineSeconds !== undefined && { startingDeadlineSeconds }),
609
+ },
610
+ };
611
+ }
612
+
214
613
  type ParseOk<T> = { readonly kind: 'ok'; readonly value: T };
215
614
  type ParseErr = { readonly kind: 'err'; readonly response: Response };
216
615
 
@@ -270,13 +669,26 @@ function bad(c: Context<AppEnv>, requestId: string, message: string): Response {
270
669
  return c.json(toWireError({ code: 'bad-input', message }, requestId));
271
670
  }
272
671
 
672
+ function unsupported(c: Context<AppEnv>, requestId: string, what: string): Response {
673
+ c.status(statusFor('trigger-operation-unsupported') as never);
674
+ return c.json(
675
+ toWireError(
676
+ {
677
+ code: 'trigger-operation-unsupported',
678
+ message: `This deployment's schedules don't support ${what} yet.`,
679
+ },
680
+ requestId,
681
+ ),
682
+ );
683
+ }
684
+
273
685
  function notFound(c: Context<AppEnv>, requestId: string, triggerId: TriggerId): Response {
274
686
  c.status(statusFor('trigger-not-found') as never);
275
687
  return c.json(
276
688
  toWireError(
277
689
  {
278
690
  code: 'trigger-not-found',
279
- message: `No trigger with id "${triggerId as unknown as string}"`,
691
+ message: `No schedule with id "${triggerId as unknown as string}"`,
280
692
  triggerId: triggerId as unknown as string,
281
693
  },
282
694
  requestId,