@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
@@ -36,6 +36,7 @@ import {
36
36
  } from './agent-releases.js';
37
37
  import { liveScopeToWire } from './live-scope-wire.js';
38
38
  import { clampLimit } from './pagination.js';
39
+ import { projectMismatch } from './project-mismatch.js';
39
40
  import { parseScopeParams } from './scope-params.js';
40
41
 
41
42
  /**
@@ -64,6 +65,8 @@ export function agentsRouter(
64
65
  releases?: AgentReleaseBindings,
65
66
  /** What a promotion's gate reads besides the releases (evals step 4b). */
66
67
  gateDeps?: AgentReleaseGateDeps,
68
+ /** What the deployment can do for an agent's turns, for publish warnings. */
69
+ capabilities: AgentPublishCapabilities = {},
67
70
  ): Hono<AppEnv> {
68
71
  const r = new Hono<AppEnv>();
69
72
  // A read-only registry (under `kindgi dev`, the pack's files) refuses
@@ -170,8 +173,15 @@ export function agentsRouter(
170
173
  ...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
171
174
  ...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
172
175
  });
176
+ // Only what the caller may read (T243 A), as `GET …/:id` asks.
177
+ const visible =
178
+ authorizer === undefined
179
+ ? page.data
180
+ : await authorizer.filterByCan(c, 'read', page.data, (a) =>
181
+ ref('agent', a.id as unknown as string),
182
+ );
173
183
  return c.json({
174
- data: page.data.map(serializeAgent),
184
+ data: visible.map(serializeAgent),
175
185
  hasMore: page.nextCursor !== undefined,
176
186
  ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
177
187
  });
@@ -383,6 +393,9 @@ export function agentsRouter(
383
393
  if (outcome.kind === 'already-registered') {
384
394
  return alreadyRegistered(c, binding, tenantId, outcome.agentId, outcome.version);
385
395
  }
396
+ if (outcome.kind === 'project-mismatch') {
397
+ return projectMismatch(c, 'agent', outcome.agentId as unknown as string, outcome.projectId);
398
+ }
386
399
  if (outcome.kind === 'project-not-found') {
387
400
  // Caller supplied a `projectId` that does not resolve within
388
401
  // this tenant. Distinct signal from `already-registered` so the
@@ -400,10 +413,12 @@ export function agentsRouter(
400
413
  ),
401
414
  );
402
415
  }
416
+ const warnings = publishWarnings(defined.value, capabilities);
403
417
  c.status(201);
404
418
  return c.json({
405
419
  agentId: outcome.agentId as unknown as string,
406
420
  version: outcome.version as unknown as string,
421
+ ...(warnings.length > 0 && { warnings }),
407
422
  });
408
423
  });
409
424
 
@@ -668,9 +683,120 @@ function derived(
668
683
  code: 'bad-input',
669
684
  message: `\`projectId\` "${outcome.projectId as unknown as string}" does not resolve to a project in this tenant`,
670
685
  });
686
+ case 'project-mismatch':
687
+ return projectMismatch(c, 'agent', agentId as unknown as string, outcome.projectId, 'derive');
671
688
  }
672
689
  }
673
690
 
691
+ /** What the deployment can do for an agent's turns, for publish warnings. */
692
+ export interface AgentPublishCapabilities {
693
+ /** Whether memory can search by meaning (embeddings are on). Absent: unknown, no warning. */
694
+ readonly semanticSearch?: boolean;
695
+ /** Whether agents can remember (`memory.remember`). Absent: unknown, no warning. */
696
+ readonly remember?: boolean;
697
+ /** Whether agent turns can recall earlier conversations. Absent: unknown, no warning. */
698
+ readonly conversationRecall?: boolean;
699
+ }
700
+
701
+ /**
702
+ * What a published agent should know about this deployment before its
703
+ * first turn: an intent that searches by meaning on a runtime without
704
+ * embeddings fails its turns (`semantic`) or searches by keyword only
705
+ * (`both`); an agent that remembers on a runtime that can't store what
706
+ * it remembers gets "not remembered" from every call.
707
+ */
708
+ function publishWarnings(
709
+ agent: Agent,
710
+ capabilities: AgentPublishCapabilities,
711
+ ): { readonly code: string; readonly message: string }[] {
712
+ return [
713
+ ...(capabilities.semanticSearch === false ? semanticWarnings(agent) : []),
714
+ ...(capabilities.remember === false && agent.memory?.remember !== undefined
715
+ ? [
716
+ {
717
+ code: 'remember-unavailable',
718
+ message:
719
+ 'The agent declares memory.remember, and this runtime cannot store agent memories: each remember call answers that nothing was remembered.',
720
+ },
721
+ ]
722
+ : []),
723
+ ...recallWarnings(agent, capabilities),
724
+ ];
725
+ }
726
+
727
+ /**
728
+ * Intents over conversations: `same-segment` and `same-project` quote other
729
+ * people's conversations (always said); on a runtime that can't recall,
730
+ * every such intent recalls nothing.
731
+ */
732
+ function recallWarnings(
733
+ agent: Agent,
734
+ capabilities: AgentPublishCapabilities,
735
+ ): { readonly code: string; readonly message: string }[] {
736
+ const answers = agent.retrieval.findIndex(
737
+ (intent) => intent.source === 'conversations' && intent.roles?.includes('agent') === true,
738
+ );
739
+ const answersWarning =
740
+ answers >= 0 && capabilities.conversationRecall !== false
741
+ ? [
742
+ {
743
+ code: 'recall-agent-answers',
744
+ message: `Retrieval intent ${answers} recalls the agent's own earlier answers: they can carry its earlier mistakes. They are quoted as "earlier answer by the agent, not verified"; recall only the people's own words (the default) to leave them out.`,
745
+ },
746
+ ]
747
+ : [];
748
+ return [...answersWarning, ...perIntentRecallWarnings(agent, capabilities)];
749
+ }
750
+
751
+ function perIntentRecallWarnings(
752
+ agent: Agent,
753
+ capabilities: AgentPublishCapabilities,
754
+ ): { readonly code: string; readonly message: string }[] {
755
+ return agent.retrieval.flatMap((intent, i) => {
756
+ if (intent.source !== 'conversations') return [];
757
+ if (capabilities.conversationRecall === false) {
758
+ return [
759
+ {
760
+ code: 'recall-unavailable',
761
+ message: `Retrieval intent ${i} recalls earlier conversations, and this runtime can't: it recalls nothing, and each turn's journal says so (no-recall).`,
762
+ },
763
+ ];
764
+ }
765
+ if (intent.scope === 'same-segment' || intent.scope === 'same-project') {
766
+ const where = intent.scope === 'same-segment' ? "the run's segment" : "the run's project";
767
+ return [
768
+ {
769
+ code: 'recall-other-people',
770
+ message: `Retrieval intent ${i} recalls conversations in ${where}, whoever had them: this agent can quote other users' conversations in ${where}. Their messages are marked as another person's, without saying whose.`,
771
+ },
772
+ ];
773
+ }
774
+ return [];
775
+ });
776
+ }
777
+
778
+ function semanticWarnings(agent: Agent): { readonly code: string; readonly message: string }[] {
779
+ return agent.retrieval.flatMap((intent, i) => {
780
+ if (intent.mode === 'semantic') {
781
+ return [
782
+ {
783
+ code: 'semantic-unavailable',
784
+ message: `Retrieval intent ${i} searches by meaning (mode "semantic"), and this runtime has no embeddings: its turns fail with semantic-unavailable until an operator turns them on (KINDGI_MEMORY_EMBEDDINGS).`,
785
+ },
786
+ ];
787
+ }
788
+ if (intent.mode === 'both') {
789
+ return [
790
+ {
791
+ code: 'semantic-unavailable',
792
+ message: `Retrieval intent ${i} (mode "both") runs only its keyword search: this runtime has no embeddings (KINDGI_MEMORY_EMBEDDINGS).`,
793
+ },
794
+ ];
795
+ }
796
+ return [];
797
+ });
798
+ }
799
+
674
800
  function serializeAgent(a: AgentVersionRecord): Record<string, unknown> {
675
801
  return {
676
802
  id: a.id as unknown as string,
@@ -684,6 +810,7 @@ function serializeAgent(a: AgentVersionRecord): Record<string, unknown> {
684
810
  capabilities: a.capabilities,
685
811
  tools: a.tools,
686
812
  retrieval: a.retrieval,
813
+ ...(a.memory !== undefined && { memory: a.memory }),
687
814
  guardrails: a.guardrails,
688
815
  ...(a.conversationPolicy !== undefined && { conversationPolicy: a.conversationPolicy }),
689
816
  ...(a.budget !== undefined && { budget: a.budget }),
@@ -2,39 +2,48 @@
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
 
4
4
  import { Hono } from 'hono';
5
+ import type { Context } from 'hono';
5
6
 
6
7
  import { AGENT_GATE_SUBJECTS, TOOL_CALL_GATE_SUBJECT } from '@kindgi/agents';
7
8
  import type { ConversationBinding, GateDecisionValue } from '@kindgi/agents';
8
- import { REVIEWER_ROLE_RANK, type ReviewerRole } from '@kindgi/authz';
9
- import { serializePublicKeyPem, signEd25519 } from '@kindgi/crypto';
10
- import type { SigningKeyBinding } from '@kindgi/crypto';
9
+ import type { AuditEventBinding } from '@kindgi/audit-events';
10
+ import { REVIEWER_ROLE_RANK, type ResourceRef, type ReviewerRole, ref } from '@kindgi/authz';
11
+ import type { ExportSigningBinding } from '@kindgi/crypto';
11
12
  import type { RunBinding } from '@kindgi/runtime';
12
- import { canonicalize } from '@kindgi/schema';
13
13
  import type {
14
14
  ApprovalId,
15
15
  ConversationId,
16
16
  Cursor,
17
17
  ReviewerId,
18
18
  RunId,
19
- SigningKeyId,
20
19
  TenantId,
21
20
  Timestamp,
22
21
  UserId,
23
22
  } from '@kindgi/types';
24
23
 
25
24
  import { statusFor, toWireError } from '../errors.js';
26
- import type { RunHandlerBinding } from '../handler-binding.js';
25
+ import type { RunHandlerBinding, RunTrace } from '../handler-binding.js';
27
26
  import type {
28
27
  Approval,
28
+ ApprovalPosition,
29
29
  ApprovalStatus,
30
30
  HitlBinding,
31
31
  ReviewDecisionKind,
32
32
  ReviewDecisionRecord,
33
33
  } from '../hitl-binding.js';
34
+ import type { Authorizer } from '../middleware/authorize.js';
34
35
  import type { ReviewerBinding } from '../reviewer-binding.js';
35
36
  import { callerReviewerRole } from '../reviewer-role.js';
37
+ import {
38
+ exportActor,
39
+ parseSigningKeyId,
40
+ readExportBody,
41
+ signExport,
42
+ signExportFailure,
43
+ signingNotConfigured,
44
+ } from '../signed-export.js';
36
45
  import type { AppEnv } from '../types.js';
37
- import { clampLimit } from './pagination.js';
46
+ import { clampLimit, decodeCursor, encodeCursor, isCursorTime } from './pagination.js';
38
47
  import { parseListScope } from './scope-params.js';
39
48
 
40
49
  const APPROVAL_STATUSES: ReadonlySet<ApprovalStatus> = new Set([
@@ -73,11 +82,18 @@ const DECIDED_STATUSES: ReadonlySet<ApprovalStatus> = new Set([
73
82
  'withdrawn',
74
83
  ]);
75
84
 
76
- /** Audit-bundle body schema version — bump when the bundle wire shape changes. */
77
- const AUDIT_BUNDLE_SCHEMA_VERSION = 1;
85
+ /**
86
+ * Audit-bundle body schema version — bump when the bundle wire shape changes.
87
+ * 2.0.0: a string like the other exports' (was the integer 1), named
88
+ * `bundleSchemaVersion` in the body too, `exportedAt` signed once.
89
+ */
90
+ const AUDIT_BUNDLE_SCHEMA_VERSION = '2.0.0';
78
91
 
79
92
  export interface ApprovalsRouterOptions {
80
- readonly signingKey?: SigningKeyBinding;
93
+ /** Signs audit bundles. Absent: `POST /:approvalId/audit-bundle` answers `404 signing-not-configured`. */
94
+ readonly exportSigning?: ExportSigningBinding;
95
+ /** Records each signed export (`export-signed`). */
96
+ readonly auditEvents?: AuditEventBinding;
81
97
  /**
82
98
  * When supplied, the POST /:approvalId/complete handler
83
99
  * invokes `runHandler.resumeRun(runId)` INLINE after `completeToken`
@@ -111,11 +127,34 @@ export function approvalsRouter(
111
127
  hitlBinding: HitlBinding,
112
128
  runBinding: RunBinding,
113
129
  options: ApprovalsRouterOptions = {},
130
+ /**
131
+ * With one (T243 A): on top of the reviewer role, a caller sees and
132
+ * decides only approvals whose project it may read (the approval's, or
133
+ * its run's). Another project's approval is not found, as one above the
134
+ * caller's tier is.
135
+ */
136
+ authorizer?: Authorizer,
114
137
  ): Hono<AppEnv> {
115
138
  const r = new Hono<AppEnv>();
116
- const signingKey = options.signingKey;
139
+ const { exportSigning, auditEvents } = options;
117
140
  const runHandler = options.runHandler;
118
141
 
142
+ /** What an approval is checked on: its project, else its run's, else the tenant. */
143
+ const approvalRef = async (tenantId: TenantId, approval: Approval): Promise<ResourceRef> => {
144
+ if (approval.projectId !== undefined) {
145
+ return ref('project', approval.projectId as unknown as string);
146
+ }
147
+ const runId = approval.provenanceRef?.runId;
148
+ const run = runId === undefined ? null : await runBinding.getRun(tenantId, runId as never);
149
+ return run === null
150
+ ? ref('tenant', tenantId as unknown as string)
151
+ : ref('project', run.projectId as unknown as string);
152
+ };
153
+ /** Whether the caller may read the approval's project (always, without an authorizer). */
154
+ const mayRead = async (c: Context<AppEnv>, approval: Approval): Promise<boolean> =>
155
+ authorizer === undefined ||
156
+ authorizer.can(c, 'read', await approvalRef(c.get('tenantId') as TenantId, approval));
157
+
119
158
  // ---------- role gate for the whole resource ----------
120
159
  // A reviewer: a token that carries a role, or whose user the roster
121
160
  // names (a session or API key of a registered reviewer).
@@ -235,10 +274,19 @@ export function approvalsRouter(
235
274
  );
236
275
  }
237
276
 
238
- const cursor = c.req.query('cursor');
239
- if (cursor !== undefined && cursor.length > 0) {
240
- const parsed = new Date(cursor);
241
- if (Number.isNaN(parsed.getTime())) {
277
+ // The cursor: where the last page ended (an approval's exact
278
+ // `createdAt` and its id), or a bare time from before that (milliseconds,
279
+ // no tie-breaker), which still answers as it did.
280
+ const rawCursor = c.req.query('cursor');
281
+ let after: ApprovalPosition | undefined;
282
+ let cursor: string | undefined;
283
+ if (rawCursor !== undefined && rawCursor.length > 0) {
284
+ const decoded = decodeCursor(rawCursor);
285
+ if (decoded !== null && isCursorTime(decoded.createdAt)) {
286
+ after = { createdAt: decoded.createdAt, id: decoded.id as unknown as ApprovalId };
287
+ } else if (decoded === null && Number.isFinite(Date.parse(rawCursor))) {
288
+ cursor = rawCursor;
289
+ } else {
242
290
  c.status(statusFor('bad-input') as never);
243
291
  return c.json(
244
292
  toWireError({ code: 'bad-input', message: '`cursor` is malformed' }, requestId),
@@ -246,10 +294,9 @@ export function approvalsRouter(
246
294
  }
247
295
  }
248
296
 
249
- // `listApprovals` takes an ISO-timestamp cursor. Over-fetch up to 4×
250
- // the page size (capped at 500) so a page still fills when
251
- // role-scoping filters rows out; the extra rows (or the binding's
252
- // own cursor) also tell us `hasMore`.
297
+ // Over-fetch up to 4× the page size (capped at 500) so a page still
298
+ // fills when role-scoping filters rows out; the extra rows (or the
299
+ // binding's own cursor) also tell us `hasMore`.
253
300
  const HITL_LIMIT_CAP = Math.min(limit * 4, 500);
254
301
  const listInput = {
255
302
  tenantId,
@@ -258,7 +305,8 @@ export function approvalsRouter(
258
305
  ...(statusFilter !== undefined && { status: statusFilter }),
259
306
  ...(requiredRoleFilter !== undefined && { requiredRole: requiredRoleFilter }),
260
307
  ...(createdAfterIso !== undefined && { since: createdAfterIso as unknown as Timestamp }),
261
- ...(cursor !== undefined && cursor.length > 0 && { cursor: cursor as Cursor }),
308
+ ...(after !== undefined && { after }),
309
+ ...(cursor !== undefined && { cursor: cursor as Cursor }),
262
310
  ...(waitTokenIds.length > 0 && { waitTokenIds }),
263
311
  };
264
312
  const listed = await hitlBinding.listApprovals(listInput);
@@ -267,14 +315,32 @@ export function approvalsRouter(
267
315
  return c.json(toWireError(listed.error as never, requestId));
268
316
  }
269
317
  const roleRank = REVIEWER_ROLE_RANK[role];
270
- const visible = listed.value.approvals.filter(
318
+ const inTier = listed.value.approvals.filter(
271
319
  (a) => REVIEWER_ROLE_RANK[a.requiredRole] <= roleRank,
272
320
  );
321
+ let visible = inTier;
322
+ if (authorizer !== undefined) {
323
+ const refs = await Promise.all(inTier.map((a) => approvalRef(tenantId, a)));
324
+ const readable = await authorizer.filterByCan(
325
+ c,
326
+ 'read',
327
+ inTier.map((approval, i) => ({ approval, at: refs[i] as ResourceRef })),
328
+ (row) => row.at,
329
+ );
330
+ visible = readable.map((row) => row.approval);
331
+ }
273
332
  const page = visible.slice(0, limit);
274
333
  const hasMore = visible.length > limit || listed.value.nextCursor !== undefined;
275
334
  const last = page[page.length - 1];
335
+ // Continue after the last approval shown: at its exact `createdAt` when
336
+ // the binding gives it, else (a binding from before) at its time.
337
+ const exact = last !== undefined ? listed.value.exactCreatedAt?.[last.id] : undefined;
276
338
  const nextCursor =
277
- hasMore && last !== undefined ? (last.createdAt as unknown as string) : undefined;
339
+ !hasMore || last === undefined
340
+ ? undefined
341
+ : exact !== undefined
342
+ ? encodeCursor({ createdAt: exact, id: last.id as unknown as string })
343
+ : (last.createdAt as unknown as string);
278
344
  return c.json({
279
345
  data: page.map(serializeApproval),
280
346
  hasMore,
@@ -297,7 +363,10 @@ export function approvalsRouter(
297
363
  const approval = got.value;
298
364
  // Out-of-scope reads are 404 (per API-ROUTE-CONVENTIONS.md §2.4 —
299
365
  // avoid leaking existence across role tiers).
300
- if (REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role]) {
366
+ if (
367
+ REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
368
+ !(await mayRead(c, approval))
369
+ ) {
301
370
  c.status(statusFor('approval-not-found') as never);
302
371
  return c.json(
303
372
  toWireError(
@@ -356,7 +425,10 @@ export function approvalsRouter(
356
425
  return c.json(toWireError(found.error as never, requestId));
357
426
  }
358
427
  const approval = found.value;
359
- if (REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role]) {
428
+ if (
429
+ REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
430
+ !(await mayRead(c, approval))
431
+ ) {
360
432
  c.status(statusFor('approval-not-found') as never);
361
433
  return c.json(
362
434
  toWireError(
@@ -468,7 +540,13 @@ export function approvalsRouter(
468
540
  // whose run couldn't go on (a tool version it started with is gone,
469
541
  // say) isn't reported as plain success.
470
542
  if (runHandler !== undefined) {
471
- resume = await resumeInline(runHandler, tenantId, approval.provenanceRef.runId as RunId);
543
+ const trace = c.get('trace');
544
+ resume = await resumeInline(
545
+ runHandler,
546
+ tenantId,
547
+ approval.provenanceRef.runId as RunId,
548
+ trace !== undefined ? { traceId: trace.traceId, spanId: trace.spanId } : undefined,
549
+ );
472
550
  }
473
551
  }
474
552
 
@@ -492,36 +570,10 @@ export function approvalsRouter(
492
570
  const role = c.get('reviewerRole') as ReviewerRole;
493
571
  const approvalId = c.req.param('approvalId') as ApprovalId;
494
572
 
495
- if (signingKey === undefined) {
496
- c.status(statusFor('signing-not-configured') as never);
497
- return c.json(
498
- toWireError(
499
- {
500
- code: 'signing-not-configured',
501
- message:
502
- 'This deployment does not have a `signingKey` binding mounted; signed audit bundles are unavailable.',
503
- },
504
- requestId,
505
- ),
506
- );
507
- }
573
+ if (exportSigning === undefined) return signingNotConfigured(c, 'signed audit bundles');
508
574
 
509
- let body: unknown;
510
- try {
511
- body = await c.req.json();
512
- } catch {
513
- c.status(statusFor('bad-input') as never);
514
- return c.json(
515
- toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
516
- );
517
- }
518
- if (body === null || typeof body !== 'object' || Array.isArray(body)) {
519
- c.status(statusFor('bad-input') as never);
520
- return c.json(
521
- toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
522
- );
523
- }
524
- const parsed = parseAuditBundleBody(body as Record<string, unknown>);
575
+ const read = await readExportBody(c);
576
+ const parsed = read.kind === 'ok' ? parseAuditBundleBody(read.value) : read;
525
577
  if (parsed.kind === 'err') {
526
578
  c.status(statusFor('bad-input') as never);
527
579
  return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
@@ -535,7 +587,10 @@ export function approvalsRouter(
535
587
  return c.json(toWireError(found.error as never, requestId));
536
588
  }
537
589
  const approval = found.value;
538
- if (REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role]) {
590
+ if (
591
+ REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
592
+ !(await mayRead(c, approval))
593
+ ) {
539
594
  c.status(statusFor('approval-not-found') as never);
540
595
  return c.json(
541
596
  toWireError(
@@ -596,96 +651,54 @@ export function approvalsRouter(
596
651
  messages = [];
597
652
  }
598
653
 
599
- // 5. Look up the private key material.
600
- const privateKey = signingKey.getPrivateKey(signingKeyId);
601
- if (privateKey === null) {
602
- c.status(statusFor('signing-key-not-found') as never);
603
- return c.json(
604
- toWireError(
605
- {
606
- code: 'signing-key-not-found',
607
- message: `No signing key registered with id "${signingKeyId as unknown as string}"`,
608
- signingKeyId: signingKeyId as unknown as string,
609
- },
610
- requestId,
611
- ),
612
- );
613
- }
614
- const publicKeyRaw = signingKey.getPublicKey(signingKeyId);
615
- if (publicKeyRaw === null) {
616
- c.status(statusFor('signing-key-not-found') as never);
617
- return c.json(
618
- toWireError(
619
- {
620
- code: 'signing-key-not-found',
621
- message: `Signing key "${signingKeyId as unknown as string}" resolved a private key but no public key`,
622
- signingKeyId: signingKeyId as unknown as string,
623
- },
624
- requestId,
625
- ),
626
- );
627
- }
628
-
629
- // 6. Build the canonical bundle body.
654
+ // 5. Sign the bundle body (and record the export).
630
655
  const guardrailResults = extractGuardrailResults(approval.context);
631
- const bundleBody: Record<string, unknown> = {
632
- bundleVersion: AUDIT_BUNDLE_SCHEMA_VERSION,
633
- approvalId: approval.id as unknown as string,
634
- tenantId: approval.tenantId as unknown as string,
635
- subjectKind: approval.subjectKind,
636
- subjectRef: approval.subjectRef,
637
- requiredRole: approval.requiredRole,
638
- status: approval.status,
639
- createdAt: approval.createdAt as unknown as string,
640
- ...(approval.decidedAt !== undefined && {
641
- decidedAt: approval.decidedAt as unknown as string,
642
- }),
643
- decision:
644
- decisionRow !== null
645
- ? {
646
- kind: decisionRow.decision,
647
- reviewerId: decisionRow.reviewerId,
648
- reviewerRoleAtDecision: decisionRow.reviewerRoleAtDecision,
649
- decidedAt: decisionRow.decidedAt as unknown as string,
650
- ...(decisionRow.rationale !== undefined && { rationale: decisionRow.rationale }),
651
- }
652
- : null,
653
- evidence: {
654
- ...(guardrailResults !== undefined && { guardrailResults }),
655
- ...(messages !== undefined && { messages }),
656
- },
657
- exportedAt: new Date().toISOString(),
658
- };
659
- const canonicalBundleBytes = new TextEncoder().encode(canonicalize(bundleBody));
660
-
661
- // 7. Sign.
662
- const signResult = signEd25519(privateKey, canonicalBundleBytes);
663
- if (signResult.kind === 'err') {
664
- c.status(statusFor('export-key-error') as never);
665
- return c.json(
666
- toWireError(
667
- {
668
- code: 'export-key-error',
669
- message: `Failed to sign audit bundle: ${signResult.error.message}`,
670
- },
671
- requestId,
672
- ),
673
- );
674
- }
675
-
676
- return c.json({
677
- approvalId: approvalId as unknown as string,
678
- bundle: Buffer.from(canonicalBundleBytes).toString('base64'),
656
+ const runId = approval.provenanceRef?.runId as unknown as string | undefined;
657
+ const signed = await signExport({
658
+ signer: exportSigning,
659
+ kind: 'audit-bundle',
679
660
  bundleSchemaVersion: AUDIT_BUNDLE_SCHEMA_VERSION,
680
- algorithm: 'ed25519' as const,
681
- signingKeyId: signingKeyId as unknown as string,
682
- signature: Buffer.from(signResult.value).toString('base64'),
683
- publicKey: serializePublicKeyPem(publicKeyRaw),
684
- canonicalization: 'sorted-key-json' as const,
685
- exportedAt: new Date().toISOString() as unknown as Timestamp,
661
+ ...(signingKeyId !== undefined && { signingKeyId }),
662
+ body: {
663
+ approvalId: approval.id as unknown as string,
664
+ tenantId: approval.tenantId as unknown as string,
665
+ subjectKind: approval.subjectKind,
666
+ subjectRef: approval.subjectRef,
667
+ requiredRole: approval.requiredRole,
668
+ status: approval.status,
669
+ createdAt: approval.createdAt as unknown as string,
670
+ ...(approval.decidedAt !== undefined && {
671
+ decidedAt: approval.decidedAt as unknown as string,
672
+ }),
673
+ decision:
674
+ decisionRow !== null
675
+ ? {
676
+ kind: decisionRow.decision,
677
+ reviewerId: decisionRow.reviewerId,
678
+ reviewerRoleAtDecision: decisionRow.reviewerRoleAtDecision,
679
+ decidedAt: decisionRow.decidedAt as unknown as string,
680
+ ...(decisionRow.rationale !== undefined && { rationale: decisionRow.rationale }),
681
+ }
682
+ : null,
683
+ evidence: {
684
+ ...(guardrailResults !== undefined && { guardrailResults }),
685
+ ...(messages !== undefined && { messages }),
686
+ },
687
+ },
688
+ ...(auditEvents !== undefined && {
689
+ record: {
690
+ auditEvents,
691
+ tenantId,
692
+ ...(approval.projectId !== undefined && { projectId: approval.projectId }),
693
+ ...(runId !== undefined && { runId }),
694
+ actor: exportActor(c),
695
+ subject: { approvalId: approval.id as unknown as string },
696
+ },
697
+ }),
686
698
  });
699
+ if (signed.kind === 'err') return signExportFailure(c, signed.error, 'export-key-error');
700
+ return c.json({ approvalId: approvalId as unknown as string, ...signed.value });
687
701
  });
688
-
689
702
  return r;
690
703
  }
691
704
 
@@ -800,7 +813,7 @@ function parseCompleteBody(
800
813
  }
801
814
 
802
815
  interface ParsedAuditBundle {
803
- readonly signingKeyId: SigningKeyId;
816
+ readonly signingKeyId: string | undefined;
804
817
  readonly includeMessages: boolean;
805
818
  }
806
819
 
@@ -809,10 +822,8 @@ function parseAuditBundleBody(
809
822
  ):
810
823
  | { readonly kind: 'ok'; readonly value: ParsedAuditBundle }
811
824
  | { readonly kind: 'err'; readonly message: string } {
812
- const raw = body.signingKeyId;
813
- if (typeof raw !== 'string' || raw.length === 0) {
814
- return { kind: 'err', message: 'Field `signingKeyId` must be a non-empty string' };
815
- }
825
+ const signingKeyId = parseSigningKeyId(body);
826
+ if (signingKeyId.kind === 'err') return signingKeyId;
816
827
  let includeMessages = false;
817
828
  if ('includeMessages' in body) {
818
829
  const im = body.includeMessages;
@@ -821,13 +832,7 @@ function parseAuditBundleBody(
821
832
  }
822
833
  includeMessages = im;
823
834
  }
824
- return {
825
- kind: 'ok',
826
- value: {
827
- signingKeyId: raw as SigningKeyId,
828
- includeMessages,
829
- },
830
- };
835
+ return { kind: 'ok', value: { signingKeyId: signingKeyId.value, includeMessages } };
831
836
  }
832
837
 
833
838
  /** How the inline resume after a decision went. */
@@ -844,9 +849,14 @@ async function resumeInline(
844
849
  runHandler: RunHandlerBinding,
845
850
  tenantId: TenantId,
846
851
  runId: RunId,
852
+ trace: RunTrace | undefined,
847
853
  ): Promise<ResumeReport> {
848
854
  try {
849
- const outcome = await runHandler.resumeRun({ tenantId, runId });
855
+ const outcome = await runHandler.resumeRun({
856
+ tenantId,
857
+ runId,
858
+ ...(trace !== undefined && { trace }),
859
+ });
850
860
  return outcome.kind === 'ok'
851
861
  ? { kind: 'ok' }
852
862
  : { kind: 'failed', code: outcome.error.code, message: outcome.error.message };