@kindgi/api 0.1.4-rc.5 → 0.1.5-rc.0

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 (507) 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/derive-agent-version.d.ts +7 -0
  21. package/dist/derive-agent-version.d.ts.map +1 -1
  22. package/dist/derive-agent-version.js +4 -0
  23. package/dist/derive-agent-version.js.map +1 -1
  24. package/dist/errors.d.ts.map +1 -1
  25. package/dist/errors.js +73 -7
  26. package/dist/errors.js.map +1 -1
  27. package/dist/eval-case-binding.d.ts +16 -4
  28. package/dist/eval-case-binding.d.ts.map +1 -1
  29. package/dist/eval-run-binding.d.ts +31 -0
  30. package/dist/eval-run-binding.d.ts.map +1 -1
  31. package/dist/eval-run-dispatcher.d.ts +7 -0
  32. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  33. package/dist/eval-run-dispatcher.js.map +1 -1
  34. package/dist/eval-sample.d.ts +11 -0
  35. package/dist/eval-sample.d.ts.map +1 -0
  36. package/dist/eval-sample.js +34 -0
  37. package/dist/eval-sample.js.map +1 -0
  38. package/dist/eval-suite-binding.d.ts +13 -0
  39. package/dist/eval-suite-binding.d.ts.map +1 -1
  40. package/dist/eval-suite-binding.js.map +1 -1
  41. package/dist/flow-binding.d.ts +18 -0
  42. package/dist/flow-binding.d.ts.map +1 -1
  43. package/dist/flow-pins.d.ts.map +1 -1
  44. package/dist/flow-pins.js +18 -2
  45. package/dist/flow-pins.js.map +1 -1
  46. package/dist/gate.d.ts.map +1 -1
  47. package/dist/gate.js +25 -0
  48. package/dist/gate.js.map +1 -1
  49. package/dist/handler-binding.d.ts +32 -0
  50. package/dist/handler-binding.d.ts.map +1 -1
  51. package/dist/hitl-binding.d.ts +23 -0
  52. package/dist/hitl-binding.d.ts.map +1 -1
  53. package/dist/identity-directory-binding.d.ts +82 -4
  54. package/dist/identity-directory-binding.d.ts.map +1 -1
  55. package/dist/identity-provider-binding.d.ts +197 -17
  56. package/dist/identity-provider-binding.d.ts.map +1 -1
  57. package/dist/improvement-pass-binding.d.ts +196 -0
  58. package/dist/improvement-pass-binding.d.ts.map +1 -0
  59. package/dist/improvement-pass-binding.js +9 -0
  60. package/dist/improvement-pass-binding.js.map +1 -0
  61. package/dist/index.d.ts +35 -17
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +11 -3
  64. package/dist/index.js.map +1 -1
  65. package/dist/judged-dispatcher.d.ts +25 -4
  66. package/dist/judged-dispatcher.d.ts.map +1 -1
  67. package/dist/judged-dispatcher.js +43 -6
  68. package/dist/judged-dispatcher.js.map +1 -1
  69. package/dist/judgment-binding.d.ts +25 -1
  70. package/dist/judgment-binding.d.ts.map +1 -1
  71. package/dist/mcp-endpoint-binding.d.ts +7 -0
  72. package/dist/mcp-endpoint-binding.d.ts.map +1 -1
  73. package/dist/memory-binding.d.ts +124 -17
  74. package/dist/memory-binding.d.ts.map +1 -1
  75. package/dist/memory-erasure-binding.d.ts +145 -0
  76. package/dist/memory-erasure-binding.d.ts.map +1 -0
  77. package/dist/memory-erasure-binding.js +4 -0
  78. package/dist/memory-erasure-binding.js.map +1 -0
  79. package/dist/middleware/auth.d.ts +66 -13
  80. package/dist/middleware/auth.d.ts.map +1 -1
  81. package/dist/middleware/auth.js +150 -50
  82. package/dist/middleware/auth.js.map +1 -1
  83. package/dist/middleware/authorize.d.ts +6 -0
  84. package/dist/middleware/authorize.d.ts.map +1 -1
  85. package/dist/middleware/authorize.js +113 -4
  86. package/dist/middleware/authorize.js.map +1 -1
  87. package/dist/middleware/error-mapper.d.ts +5 -0
  88. package/dist/middleware/error-mapper.d.ts.map +1 -1
  89. package/dist/middleware/error-mapper.js +14 -1
  90. package/dist/middleware/error-mapper.js.map +1 -1
  91. package/dist/middleware/idempotency.d.ts +70 -5
  92. package/dist/middleware/idempotency.d.ts.map +1 -1
  93. package/dist/middleware/idempotency.js +174 -41
  94. package/dist/middleware/idempotency.js.map +1 -1
  95. package/dist/middleware/key-project.d.ts +17 -0
  96. package/dist/middleware/key-project.d.ts.map +1 -0
  97. package/dist/middleware/key-project.js +75 -0
  98. package/dist/middleware/key-project.js.map +1 -0
  99. package/dist/middleware/principal.d.ts.map +1 -1
  100. package/dist/middleware/principal.js +9 -5
  101. package/dist/middleware/principal.js.map +1 -1
  102. package/dist/middleware/project-ref.d.ts.map +1 -1
  103. package/dist/middleware/project-ref.js +3 -0
  104. package/dist/middleware/project-ref.js.map +1 -1
  105. package/dist/openapi/generate.d.ts.map +1 -1
  106. package/dist/openapi/generate.js +5 -2
  107. package/dist/openapi/generate.js.map +1 -1
  108. package/dist/openapi/operations.d.ts.map +1 -1
  109. package/dist/openapi/operations.js +918 -139
  110. package/dist/openapi/operations.js.map +1 -1
  111. package/dist/openapi/schemas.d.ts +92 -13
  112. package/dist/openapi/schemas.d.ts.map +1 -1
  113. package/dist/openapi/schemas.js +2122 -370
  114. package/dist/openapi/schemas.js.map +1 -1
  115. package/dist/person-grants-binding.d.ts +77 -0
  116. package/dist/person-grants-binding.d.ts.map +1 -0
  117. package/dist/person-grants-binding.js +4 -0
  118. package/dist/person-grants-binding.js.map +1 -0
  119. package/dist/proposal-service.d.ts +121 -0
  120. package/dist/proposal-service.d.ts.map +1 -0
  121. package/dist/proposal-service.js +447 -0
  122. package/dist/proposal-service.js.map +1 -0
  123. package/dist/proposal-status.d.ts +60 -0
  124. package/dist/proposal-status.d.ts.map +1 -0
  125. package/dist/proposal-status.js +109 -0
  126. package/dist/proposal-status.js.map +1 -0
  127. package/dist/provider-binding.d.ts +10 -0
  128. package/dist/provider-binding.d.ts.map +1 -1
  129. package/dist/publish-refused.d.ts +18 -3
  130. package/dist/publish-refused.d.ts.map +1 -1
  131. package/dist/publish-refused.js +18 -3
  132. package/dist/publish-refused.js.map +1 -1
  133. package/dist/routes/adapters.d.ts +2 -1
  134. package/dist/routes/adapters.d.ts.map +1 -1
  135. package/dist/routes/adapters.js +3 -1
  136. package/dist/routes/adapters.js.map +1 -1
  137. package/dist/routes/agent-releases.d.ts +55 -3
  138. package/dist/routes/agent-releases.d.ts.map +1 -1
  139. package/dist/routes/agent-releases.js +85 -55
  140. package/dist/routes/agent-releases.js.map +1 -1
  141. package/dist/routes/agents.d.ts +12 -1
  142. package/dist/routes/agents.d.ts.map +1 -1
  143. package/dist/routes/agents.js +100 -2
  144. package/dist/routes/agents.js.map +1 -1
  145. package/dist/routes/approvals.d.ts +15 -3
  146. package/dist/routes/approvals.d.ts.map +1 -1
  147. package/dist/routes/approvals.js +133 -122
  148. package/dist/routes/approvals.js.map +1 -1
  149. package/dist/routes/artifacts.d.ts +25 -3
  150. package/dist/routes/artifacts.d.ts.map +1 -1
  151. package/dist/routes/artifacts.js +116 -7
  152. package/dist/routes/artifacts.js.map +1 -1
  153. package/dist/routes/auth.d.ts +25 -1
  154. package/dist/routes/auth.d.ts.map +1 -1
  155. package/dist/routes/auth.js +655 -281
  156. package/dist/routes/auth.js.map +1 -1
  157. package/dist/routes/blocks.d.ts.map +1 -1
  158. package/dist/routes/blocks.js +2 -42
  159. package/dist/routes/blocks.js.map +1 -1
  160. package/dist/routes/capabilities.d.ts +2 -1
  161. package/dist/routes/capabilities.d.ts.map +1 -1
  162. package/dist/routes/capabilities.js +6 -1
  163. package/dist/routes/capabilities.js.map +1 -1
  164. package/dist/routes/compliance.d.ts +9 -10
  165. package/dist/routes/compliance.d.ts.map +1 -1
  166. package/dist/routes/compliance.js +42 -61
  167. package/dist/routes/compliance.js.map +1 -1
  168. package/dist/routes/conversations.d.ts +8 -1
  169. package/dist/routes/conversations.d.ts.map +1 -1
  170. package/dist/routes/conversations.js +87 -8
  171. package/dist/routes/conversations.js.map +1 -1
  172. package/dist/routes/cost.d.ts +7 -1
  173. package/dist/routes/cost.d.ts.map +1 -1
  174. package/dist/routes/cost.js +22 -3
  175. package/dist/routes/cost.js.map +1 -1
  176. package/dist/routes/denied.d.ts +11 -0
  177. package/dist/routes/denied.d.ts.map +1 -0
  178. package/dist/routes/denied.js +17 -0
  179. package/dist/routes/denied.js.map +1 -0
  180. package/dist/routes/deployments.d.ts +2 -1
  181. package/dist/routes/deployments.d.ts.map +1 -1
  182. package/dist/routes/deployments.js +44 -12
  183. package/dist/routes/deployments.js.map +1 -1
  184. package/dist/routes/eval-comparison.d.ts.map +1 -1
  185. package/dist/routes/eval-comparison.js +69 -1
  186. package/dist/routes/eval-comparison.js.map +1 -1
  187. package/dist/routes/eval-overrides.d.ts +18 -0
  188. package/dist/routes/eval-overrides.d.ts.map +1 -0
  189. package/dist/routes/eval-overrides.js +81 -0
  190. package/dist/routes/eval-overrides.js.map +1 -0
  191. package/dist/routes/eval-runs.d.ts +10 -1
  192. package/dist/routes/eval-runs.d.ts.map +1 -1
  193. package/dist/routes/eval-runs.js +63 -7
  194. package/dist/routes/eval-runs.js.map +1 -1
  195. package/dist/routes/eval-suites.d.ts.map +1 -1
  196. package/dist/routes/eval-suites.js +20 -1
  197. package/dist/routes/eval-suites.js.map +1 -1
  198. package/dist/routes/event-triggers.d.ts +5 -1
  199. package/dist/routes/event-triggers.d.ts.map +1 -1
  200. package/dist/routes/event-triggers.js +26 -3
  201. package/dist/routes/event-triggers.js.map +1 -1
  202. package/dist/routes/export-signing-keys.d.ts +12 -0
  203. package/dist/routes/export-signing-keys.d.ts.map +1 -0
  204. package/dist/routes/export-signing-keys.js +24 -0
  205. package/dist/routes/export-signing-keys.js.map +1 -0
  206. package/dist/routes/flows.d.ts.map +1 -1
  207. package/dist/routes/flows.js +9 -1
  208. package/dist/routes/flows.js.map +1 -1
  209. package/dist/routes/gate-policies.d.ts +4 -1
  210. package/dist/routes/gate-policies.d.ts.map +1 -1
  211. package/dist/routes/gate-policies.js +29 -5
  212. package/dist/routes/gate-policies.js.map +1 -1
  213. package/dist/routes/guardrails.d.ts +16 -14
  214. package/dist/routes/guardrails.d.ts.map +1 -1
  215. package/dist/routes/guardrails.js +39 -3
  216. package/dist/routes/guardrails.js.map +1 -1
  217. package/dist/routes/identity.d.ts +20 -4
  218. package/dist/routes/identity.d.ts.map +1 -1
  219. package/dist/routes/identity.js +246 -6
  220. package/dist/routes/identity.js.map +1 -1
  221. package/dist/routes/improvement-passes.d.ts +52 -0
  222. package/dist/routes/improvement-passes.d.ts.map +1 -0
  223. package/dist/routes/improvement-passes.js +449 -0
  224. package/dist/routes/improvement-passes.js.map +1 -0
  225. package/dist/routes/judged-suites.d.ts +50 -0
  226. package/dist/routes/judged-suites.d.ts.map +1 -1
  227. package/dist/routes/judged-suites.js +66 -27
  228. package/dist/routes/judged-suites.js.map +1 -1
  229. package/dist/routes/judgment-context.d.ts +18 -2
  230. package/dist/routes/judgment-context.d.ts.map +1 -1
  231. package/dist/routes/judgment-context.js +63 -5
  232. package/dist/routes/judgment-context.js.map +1 -1
  233. package/dist/routes/judgment-flow-context.d.ts.map +1 -1
  234. package/dist/routes/judgment-flow-context.js +14 -2
  235. package/dist/routes/judgment-flow-context.js.map +1 -1
  236. package/dist/routes/judgments.d.ts.map +1 -1
  237. package/dist/routes/judgments.js +8 -1
  238. package/dist/routes/judgments.js.map +1 -1
  239. package/dist/routes/mcp.d.ts.map +1 -1
  240. package/dist/routes/mcp.js +26 -1
  241. package/dist/routes/mcp.js.map +1 -1
  242. package/dist/routes/memory-access.d.ts +43 -0
  243. package/dist/routes/memory-access.d.ts.map +1 -0
  244. package/dist/routes/memory-access.js +129 -0
  245. package/dist/routes/memory-access.js.map +1 -0
  246. package/dist/routes/memory-erasures.d.ts +25 -0
  247. package/dist/routes/memory-erasures.d.ts.map +1 -0
  248. package/dist/routes/memory-erasures.js +214 -0
  249. package/dist/routes/memory-erasures.js.map +1 -0
  250. package/dist/routes/memory-parse.d.ts +38 -0
  251. package/dist/routes/memory-parse.d.ts.map +1 -0
  252. package/dist/routes/memory-parse.js +199 -0
  253. package/dist/routes/memory-parse.js.map +1 -0
  254. package/dist/routes/memory.d.ts +9 -4
  255. package/dist/routes/memory.d.ts.map +1 -1
  256. package/dist/routes/memory.js +226 -234
  257. package/dist/routes/memory.js.map +1 -1
  258. package/dist/routes/observations.d.ts +4 -1
  259. package/dist/routes/observations.d.ts.map +1 -1
  260. package/dist/routes/observations.js +8 -2
  261. package/dist/routes/observations.js.map +1 -1
  262. package/dist/routes/pagination.d.ts +7 -0
  263. package/dist/routes/pagination.d.ts.map +1 -1
  264. package/dist/routes/pagination.js +10 -0
  265. package/dist/routes/pagination.js.map +1 -1
  266. package/dist/routes/policies.d.ts +2 -1
  267. package/dist/routes/policies.d.ts.map +1 -1
  268. package/dist/routes/policies.js +3 -1
  269. package/dist/routes/policies.js.map +1 -1
  270. package/dist/routes/project-mismatch.d.ts +22 -0
  271. package/dist/routes/project-mismatch.d.ts.map +1 -0
  272. package/dist/routes/project-mismatch.js +34 -0
  273. package/dist/routes/project-mismatch.js.map +1 -0
  274. package/dist/routes/projects.d.ts +15 -4
  275. package/dist/routes/projects.d.ts.map +1 -1
  276. package/dist/routes/projects.js +100 -9
  277. package/dist/routes/projects.js.map +1 -1
  278. package/dist/routes/proposals.d.ts +25 -17
  279. package/dist/routes/proposals.d.ts.map +1 -1
  280. package/dist/routes/proposals.js +340 -507
  281. package/dist/routes/proposals.js.map +1 -1
  282. package/dist/routes/provenance.d.ts +17 -3
  283. package/dist/routes/provenance.d.ts.map +1 -1
  284. package/dist/routes/provenance.js +79 -103
  285. package/dist/routes/provenance.js.map +1 -1
  286. package/dist/routes/providers.d.ts +17 -1
  287. package/dist/routes/providers.d.ts.map +1 -1
  288. package/dist/routes/providers.js +188 -8
  289. package/dist/routes/providers.js.map +1 -1
  290. package/dist/routes/public-run-tokens.d.ts.map +1 -1
  291. package/dist/routes/public-run-tokens.js +3 -0
  292. package/dist/routes/public-run-tokens.js.map +1 -1
  293. package/dist/routes/runs.d.ts +10 -0
  294. package/dist/routes/runs.d.ts.map +1 -1
  295. package/dist/routes/runs.js +92 -42
  296. package/dist/routes/runs.js.map +1 -1
  297. package/dist/routes/schedules.d.ts +21 -13
  298. package/dist/routes/schedules.d.ts.map +1 -1
  299. package/dist/routes/schedules.js +416 -55
  300. package/dist/routes/schedules.js.map +1 -1
  301. package/dist/routes/segments.d.ts +2 -0
  302. package/dist/routes/segments.d.ts.map +1 -1
  303. package/dist/routes/segments.js +5 -0
  304. package/dist/routes/segments.js.map +1 -1
  305. package/dist/routes/service-accounts.d.ts +17 -0
  306. package/dist/routes/service-accounts.d.ts.map +1 -0
  307. package/dist/routes/service-accounts.js +212 -0
  308. package/dist/routes/service-accounts.js.map +1 -0
  309. package/dist/routes/sign-in-options.d.ts +50 -0
  310. package/dist/routes/sign-in-options.d.ts.map +1 -0
  311. package/dist/routes/sign-in-options.js +98 -0
  312. package/dist/routes/sign-in-options.js.map +1 -0
  313. package/dist/routes/signing-keys.d.ts +2 -1
  314. package/dist/routes/signing-keys.d.ts.map +1 -1
  315. package/dist/routes/signing-keys.js +3 -1
  316. package/dist/routes/signing-keys.js.map +1 -1
  317. package/dist/routes/tenant-access.d.ts +13 -0
  318. package/dist/routes/tenant-access.d.ts.map +1 -0
  319. package/dist/routes/tenant-access.js +26 -0
  320. package/dist/routes/tenant-access.js.map +1 -0
  321. package/dist/routes/tenant.d.ts.map +1 -1
  322. package/dist/routes/tenant.js +4 -0
  323. package/dist/routes/tenant.js.map +1 -1
  324. package/dist/routes/token-sign-in.d.ts +36 -0
  325. package/dist/routes/token-sign-in.d.ts.map +1 -0
  326. package/dist/routes/token-sign-in.js +101 -0
  327. package/dist/routes/token-sign-in.js.map +1 -0
  328. package/dist/routes/tokens.d.ts +15 -5
  329. package/dist/routes/tokens.d.ts.map +1 -1
  330. package/dist/routes/tokens.js +162 -43
  331. package/dist/routes/tokens.js.map +1 -1
  332. package/dist/routes/tools.d.ts.map +1 -1
  333. package/dist/routes/tools.js +9 -1
  334. package/dist/routes/tools.js.map +1 -1
  335. package/dist/routes/trigger-access.d.ts +29 -0
  336. package/dist/routes/trigger-access.d.ts.map +1 -0
  337. package/dist/routes/trigger-access.js +33 -0
  338. package/dist/routes/trigger-access.js.map +1 -0
  339. package/dist/routes/webhook-endpoints.d.ts +2 -1
  340. package/dist/routes/webhook-endpoints.d.ts.map +1 -1
  341. package/dist/routes/webhook-endpoints.js +11 -3
  342. package/dist/routes/webhook-endpoints.js.map +1 -1
  343. package/dist/routes/webhooks.d.ts +5 -1
  344. package/dist/routes/webhooks.d.ts.map +1 -1
  345. package/dist/routes/webhooks.js +25 -2
  346. package/dist/routes/webhooks.js.map +1 -1
  347. package/dist/run-failure.d.ts +21 -0
  348. package/dist/run-failure.d.ts.map +1 -0
  349. package/dist/run-failure.js +29 -0
  350. package/dist/run-failure.js.map +1 -0
  351. package/dist/service-account-binding.d.ts +108 -0
  352. package/dist/service-account-binding.d.ts.map +1 -0
  353. package/dist/service-account-binding.js +4 -0
  354. package/dist/service-account-binding.js.map +1 -0
  355. package/dist/session-store-binding.d.ts +61 -13
  356. package/dist/session-store-binding.d.ts.map +1 -1
  357. package/dist/signed-export.d.ts +89 -0
  358. package/dist/signed-export.d.ts.map +1 -0
  359. package/dist/signed-export.js +149 -0
  360. package/dist/signed-export.js.map +1 -0
  361. package/dist/supervisor-binding.d.ts +186 -413
  362. package/dist/supervisor-binding.d.ts.map +1 -1
  363. package/dist/testing/app-bindings.d.ts +33 -0
  364. package/dist/testing/app-bindings.d.ts.map +1 -0
  365. package/dist/testing/app-bindings.js +112 -0
  366. package/dist/testing/app-bindings.js.map +1 -0
  367. package/dist/testing/index.d.ts +11 -0
  368. package/dist/testing/index.d.ts.map +1 -0
  369. package/dist/testing/index.js +13 -0
  370. package/dist/testing/index.js.map +1 -0
  371. package/dist/testing/stub-binding.d.ts +34 -0
  372. package/dist/testing/stub-binding.d.ts.map +1 -0
  373. package/dist/testing/stub-binding.js +42 -0
  374. package/dist/testing/stub-binding.js.map +1 -0
  375. package/dist/testing/trigger-registry.d.ts +21 -0
  376. package/dist/testing/trigger-registry.d.ts.map +1 -0
  377. package/dist/testing/trigger-registry.js +206 -0
  378. package/dist/testing/trigger-registry.js.map +1 -0
  379. package/dist/token-admin.d.ts +46 -8
  380. package/dist/token-admin.d.ts.map +1 -1
  381. package/dist/token-admin.js.map +1 -1
  382. package/dist/tool-binding.d.ts +13 -0
  383. package/dist/tool-binding.d.ts.map +1 -1
  384. package/dist/trigger-binding.d.ts +2 -2
  385. package/dist/trigger-binding.d.ts.map +1 -1
  386. package/dist/trigger-binding.js +1 -1
  387. package/dist/trigger-binding.js.map +1 -1
  388. package/dist/types.d.ts +16 -0
  389. package/dist/types.d.ts.map +1 -1
  390. package/dist/webhook-endpoint-binding.d.ts +19 -3
  391. package/dist/webhook-endpoint-binding.d.ts.map +1 -1
  392. package/dist/webhook-endpoint-binding.js +1 -1
  393. package/dist/webhook-endpoint-binding.js.map +1 -1
  394. package/openapi.json +15286 -8653
  395. package/package.json +26 -22
  396. package/src/agent-binding.ts +14 -0
  397. package/src/agent-pins.ts +18 -2
  398. package/src/app.ts +366 -80
  399. package/src/block-publish.ts +181 -0
  400. package/src/caller.ts +62 -0
  401. package/src/capability-binding.ts +12 -0
  402. package/src/derive-agent-version.ts +9 -1
  403. package/src/errors.ts +73 -7
  404. package/src/eval-case-binding.ts +17 -1
  405. package/src/eval-run-binding.ts +31 -0
  406. package/src/eval-run-dispatcher.ts +7 -0
  407. package/src/eval-sample.ts +42 -0
  408. package/src/eval-suite-binding.ts +14 -0
  409. package/src/flow-binding.ts +19 -0
  410. package/src/flow-pins.ts +18 -2
  411. package/src/gate.ts +26 -0
  412. package/src/handler-binding.ts +36 -1
  413. package/src/hitl-binding.ts +24 -0
  414. package/src/identity-directory-binding.ts +85 -4
  415. package/src/identity-provider-binding.ts +216 -21
  416. package/src/improvement-pass-binding.ts +193 -0
  417. package/src/index.ts +153 -31
  418. package/src/judged-dispatcher.ts +78 -11
  419. package/src/judgment-binding.ts +25 -1
  420. package/src/mcp-endpoint-binding.ts +7 -0
  421. package/src/memory-binding.ts +121 -17
  422. package/src/memory-erasure-binding.ts +156 -0
  423. package/src/middleware/auth.ts +228 -62
  424. package/src/middleware/authorize.ts +139 -3
  425. package/src/middleware/error-mapper.ts +15 -1
  426. package/src/middleware/idempotency.ts +230 -43
  427. package/src/middleware/key-project.ts +86 -0
  428. package/src/middleware/principal.ts +9 -5
  429. package/src/middleware/project-ref.ts +3 -0
  430. package/src/openapi/generate.ts +11 -2
  431. package/src/openapi/operations.ts +1059 -142
  432. package/src/openapi/schemas.ts +2438 -485
  433. package/src/person-grants-binding.ts +76 -0
  434. package/src/proposal-service.ts +640 -0
  435. package/src/proposal-status.ts +176 -0
  436. package/src/provider-binding.ts +10 -0
  437. package/src/publish-refused.ts +38 -9
  438. package/src/routes/adapters.ts +4 -0
  439. package/src/routes/agent-releases.ts +121 -69
  440. package/src/routes/agents.ts +128 -1
  441. package/src/routes/approvals.ts +164 -154
  442. package/src/routes/artifacts.ts +181 -11
  443. package/src/routes/auth.ts +804 -336
  444. package/src/routes/blocks.ts +2 -53
  445. package/src/routes/capabilities.ts +10 -1
  446. package/src/routes/compliance.ts +60 -99
  447. package/src/routes/conversations.ts +101 -7
  448. package/src/routes/cost.ts +32 -3
  449. package/src/routes/denied.ts +28 -0
  450. package/src/routes/deployments.ts +62 -16
  451. package/src/routes/eval-comparison.ts +81 -2
  452. package/src/routes/eval-overrides.ts +108 -0
  453. package/src/routes/eval-runs.ts +86 -6
  454. package/src/routes/eval-suites.ts +25 -1
  455. package/src/routes/event-triggers.ts +27 -3
  456. package/src/routes/export-signing-keys.ts +31 -0
  457. package/src/routes/flows.ts +12 -1
  458. package/src/routes/gate-policies.ts +37 -6
  459. package/src/routes/guardrails.ts +61 -2
  460. package/src/routes/identity.ts +328 -10
  461. package/src/routes/improvement-passes.ts +541 -0
  462. package/src/routes/judged-suites.ts +113 -43
  463. package/src/routes/judgment-context.ts +76 -5
  464. package/src/routes/judgment-flow-context.ts +16 -2
  465. package/src/routes/judgments.ts +17 -3
  466. package/src/routes/mcp.ts +29 -1
  467. package/src/routes/memory-access.ts +179 -0
  468. package/src/routes/memory-erasures.ts +240 -0
  469. package/src/routes/memory-parse.ts +250 -0
  470. package/src/routes/memory.ts +244 -286
  471. package/src/routes/observations.ts +15 -2
  472. package/src/routes/pagination.ts +12 -0
  473. package/src/routes/policies.ts +7 -1
  474. package/src/routes/project-mismatch.ts +56 -0
  475. package/src/routes/projects.ts +107 -13
  476. package/src/routes/proposals.ts +370 -611
  477. package/src/routes/provenance.ts +99 -133
  478. package/src/routes/providers.ts +223 -8
  479. package/src/routes/public-run-tokens.ts +3 -0
  480. package/src/routes/runs.ts +119 -39
  481. package/src/routes/schedules.ts +472 -60
  482. package/src/routes/segments.ts +11 -0
  483. package/src/routes/service-accounts.ts +262 -0
  484. package/src/routes/sign-in-options.ts +168 -0
  485. package/src/routes/signing-keys.ts +7 -1
  486. package/src/routes/tenant-access.ts +37 -0
  487. package/src/routes/tenant.ts +6 -0
  488. package/src/routes/token-sign-in.ts +161 -0
  489. package/src/routes/tokens.ts +172 -46
  490. package/src/routes/tools.ts +12 -1
  491. package/src/routes/trigger-access.ts +72 -0
  492. package/src/routes/webhook-endpoints.ts +15 -3
  493. package/src/routes/webhooks.ts +26 -2
  494. package/src/run-failure.ts +42 -0
  495. package/src/service-account-binding.ts +113 -0
  496. package/src/session-store-binding.ts +65 -13
  497. package/src/signed-export.ts +250 -0
  498. package/src/supervisor-binding.ts +169 -409
  499. package/src/testing/app-bindings.ts +142 -0
  500. package/src/testing/index.ts +21 -0
  501. package/src/testing/stub-binding.ts +53 -0
  502. package/src/testing/trigger-registry.ts +259 -0
  503. package/src/token-admin.ts +40 -8
  504. package/src/tool-binding.ts +14 -0
  505. package/src/trigger-binding.ts +8 -1
  506. package/src/types.ts +16 -0
  507. package/src/webhook-endpoint-binding.ts +18 -3
@@ -3,17 +3,12 @@
3
3
 
4
4
  import { type Context, Hono } from 'hono';
5
5
 
6
- import {
7
- BLOCK_KINDS,
8
- type BlockDefinition,
9
- type BlockKind,
10
- settingsSchemaIssues,
11
- validateBlock,
12
- } from '@kindgi/agents';
6
+ import { BLOCK_KINDS, type BlockKind, validateBlock } from '@kindgi/agents';
13
7
  import { ref } from '@kindgi/authz';
14
8
  import type { Cursor, ProjectId, TenantId } from '@kindgi/types';
15
9
 
16
10
  import type { BlockPublishOutcome, BlockRecord, BlockRegistryBinding } from '../block-binding.js';
11
+ import { continuityIssues, withCarriedSchema } from '../block-publish.js';
17
12
  import { statusFor, toWireError } from '../errors.js';
18
13
  import type { Authorizer } from '../middleware/authorize.js';
19
14
  import type { AppEnv } from '../types.js';
@@ -249,52 +244,6 @@ function isBlockKind(value: string): value is BlockKind {
249
244
  return (BLOCK_KINDS as readonly string[]).includes(value);
250
245
  }
251
246
 
252
- /**
253
- * A new version against the block's latest: the same kind, and a
254
- * settings version without a schema of its own satisfies the schema it
255
- * keeps (`carriedSchema`).
256
- */
257
- function continuityIssues(
258
- latest: BlockRecord | null,
259
- block: BlockDefinition,
260
- ): { path: string; message: string }[] {
261
- if (latest === null) return [];
262
- if (latest.kind !== block.kind) {
263
- return [
264
- {
265
- path: '/kind',
266
- message: `block "${block.id}" is a ${latest.kind} block; a version can't change its kind`,
267
- },
268
- ];
269
- }
270
- const carried = carriedSchema(latest, block);
271
- if (block.kind !== 'settings' || carried === undefined) return [];
272
- return settingsSchemaIssues(block.content.values, carried).map((i) => ({
273
- ...i,
274
- message: `${i.message} (the schema of version ${latest.version})`,
275
- }));
276
- }
277
-
278
- /**
279
- * The schema a settings version that gives none keeps: the latest
280
- * version's. A version that gives a schema replaces it (`{}` drops the
281
- * check on purpose).
282
- */
283
- function carriedSchema(
284
- latest: BlockRecord | null,
285
- block: BlockDefinition,
286
- ): Readonly<Record<string, unknown>> | undefined {
287
- if (latest?.kind !== 'settings' || block.kind !== 'settings') return undefined;
288
- return block.content.schema === undefined ? latest.content.schema : undefined;
289
- }
290
-
291
- /** The version as stored: with the schema it keeps, if any. */
292
- function withCarriedSchema(latest: BlockRecord | null, block: BlockDefinition): BlockDefinition {
293
- const schema = carriedSchema(latest, block);
294
- if (schema === undefined || block.kind !== 'settings') return block;
295
- return { ...block, content: { ...block.content, schema } };
296
- }
297
-
298
247
  /** The response to a publish outcome. */
299
248
  function published(c: Context<AppEnv>, outcome: BlockPublishOutcome) {
300
249
  const requestId = c.get('requestId');
@@ -7,8 +7,10 @@ import type { Cursor, TenantId } from '@kindgi/types';
7
7
 
8
8
  import type { CapabilityDescriptor, CapabilityRegistryBinding } from '../capability-binding.js';
9
9
  import { statusFor, toWireError } from '../errors.js';
10
+ import type { Authorizer } from '../middleware/authorize.js';
10
11
  import type { AppEnv } from '../types.js';
11
12
  import { clampLimit } from './pagination.js';
13
+ import { tenantResourceAccess } from './tenant-access.js';
12
14
 
13
15
  /**
14
16
  * Capabilities resource routes — part of the admin control plane.
@@ -19,8 +21,12 @@ import { clampLimit } from './pagination.js';
19
21
  * the HTTP surface — that would fork the closed-enum feature set the
20
22
  * router depends on.
21
23
  */
22
- export function capabilitiesRouter(binding: CapabilityRegistryBinding): Hono<AppEnv> {
24
+ export function capabilitiesRouter(
25
+ binding: CapabilityRegistryBinding,
26
+ authorizer?: Authorizer,
27
+ ): Hono<AppEnv> {
23
28
  const r = new Hono<AppEnv>();
29
+ r.use('*', tenantResourceAccess(authorizer));
24
30
 
25
31
  // ---------- GET / (list, cursor-paginated) ----------
26
32
  r.get('/', async (c) => {
@@ -75,5 +81,8 @@ function serializeCapability(d: CapabilityDescriptor): Record<string, unknown> {
75
81
  description: d.description,
76
82
  ...(d.kind !== undefined && { kind: d.kind }),
77
83
  ...(d.paramsSchema !== undefined && { paramsSchema: d.paramsSchema }),
84
+ ...(d.providers !== undefined && {
85
+ providers: d.providers.map((p) => ({ providerId: p.providerId, models: [...p.models] })),
86
+ }),
78
87
  };
79
88
  }
@@ -4,27 +4,31 @@
4
4
  import { Hono } from 'hono';
5
5
 
6
6
  import type { AuditEvent, AuditEventBinding, AuditEventFilter } from '@kindgi/audit-events';
7
- import type {
8
- ComplianceEvidence,
9
- ComplianceEvidenceGenerator,
10
- EvidenceFilter,
11
- LoadedClassifier,
12
- } from '@kindgi/compliance';
13
- import { auditEventToEvidence } from '@kindgi/compliance';
14
- import type { SigningKeyBinding } from '@kindgi/crypto';
7
+ import type { ComplianceEvidence, EvidenceFilter, LoadedClassifier } from '@kindgi/compliance';
8
+ import { auditEventToEvidence, collectEvidence } from '@kindgi/compliance';
9
+ import type { ExportSigningBinding } from '@kindgi/crypto';
15
10
  import type {
16
11
  AgentId,
17
12
  ComplianceEvidenceId,
18
13
  FlowId,
19
14
  RunId,
20
- SigningKeyId,
21
15
  TenantId,
22
16
  Timestamp,
23
17
  } from '@kindgi/types';
24
18
 
25
19
  import { statusFor, toWireError } from '../errors.js';
20
+ import type { Authorizer } from '../middleware/authorize.js';
21
+ import {
22
+ exportActor,
23
+ parseSigningKeyId,
24
+ readExportBody,
25
+ signExport,
26
+ signExportFailure,
27
+ signingNotConfigured,
28
+ } from '../signed-export.js';
26
29
  import type { AppEnv } from '../types.js';
27
30
  import { clampLimit } from './pagination.js';
31
+ import { tenantAdminAccess } from './tenant-access.js';
28
32
 
29
33
  /**
30
34
  * Compliance-evidence readback + signed-export routes over the unified
@@ -44,20 +48,26 @@ import { clampLimit } from './pagination.js';
44
48
  export interface ComplianceRouterOptions {
45
49
  readonly auditEvents: AuditEventBinding;
46
50
  readonly classifier: LoadedClassifier;
47
- readonly signingKey?: SigningKeyBinding;
48
51
  /**
49
- * Caller-plugged evidence generator. Supplied at app-composition
50
- * time by the host (the Kindgi runtime provides one). Kept
51
- * required — signed export routes cannot run without it, and the
52
- * route mount guards (auditEvents + classifier) already imply
53
- * signed-export capability.
52
+ * Signs evidence exports. Absent: `POST /evidence/export` answers
53
+ * `404 signing-not-configured`. The route collects the evidence from
54
+ * `auditEvents` itself (`collectEvidence`), signs it, and records the
55
+ * export there (`export-signed`).
54
56
  */
55
- readonly complianceGenerator: ComplianceEvidenceGenerator;
57
+ readonly exportSigning?: ExportSigningBinding;
56
58
  }
57
59
 
58
- export function complianceRouter(options: ComplianceRouterOptions): Hono<AppEnv> {
60
+ /** The evidence bundle body's version. Unchanged: the body is the one the runtime's generator signed. */
61
+ const BUNDLE_SCHEMA_VERSION = '1.0.0';
62
+
63
+ export function complianceRouter(
64
+ options: ComplianceRouterOptions,
65
+ authorizer?: Authorizer,
66
+ ): Hono<AppEnv> {
59
67
  const r = new Hono<AppEnv>();
60
- const { auditEvents, classifier, signingKey, complianceGenerator } = options;
68
+ // Evidence across the tenant, as the audit routes: an admin's.
69
+ r.use('*', tenantAdminAccess(authorizer));
70
+ const { auditEvents, classifier, exportSigning } = options;
61
71
 
62
72
  const isExportable = (kind: string): boolean => classifier.resolve(kind).exportable;
63
73
  const exportableKinds = (): readonly string[] =>
@@ -165,36 +175,10 @@ export function complianceRouter(options: ComplianceRouterOptions): Hono<AppEnv>
165
175
  const requestId = c.get('requestId');
166
176
  const tenantId = c.get('tenantId') as TenantId;
167
177
 
168
- if (signingKey === undefined) {
169
- c.status(statusFor('signing-not-configured') as never);
170
- return c.json(
171
- toWireError(
172
- {
173
- code: 'signing-not-configured',
174
- message:
175
- 'This deployment does not have a `signingKey` binding mounted; signed compliance exports are unavailable.',
176
- },
177
- requestId,
178
- ),
179
- );
180
- }
178
+ if (exportSigning === undefined) return signingNotConfigured(c, 'signed compliance exports');
181
179
 
182
- let body: unknown;
183
- try {
184
- body = await c.req.json();
185
- } catch {
186
- c.status(statusFor('bad-input') as never);
187
- return c.json(
188
- toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
189
- );
190
- }
191
- if (body === null || typeof body !== 'object' || Array.isArray(body)) {
192
- c.status(statusFor('bad-input') as never);
193
- return c.json(
194
- toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
195
- );
196
- }
197
- const parsed = parseExportBody(body as Record<string, unknown>);
180
+ const read = await readExportBody(c);
181
+ const parsed = read.kind === 'ok' ? parseExportBody(read.value) : read;
198
182
  if (parsed.kind === 'err') {
199
183
  c.status(statusFor('bad-input') as never);
200
184
  return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
@@ -223,52 +207,34 @@ export function complianceRouter(options: ComplianceRouterOptions): Hono<AppEnv>
223
207
  );
224
208
  }
225
209
 
226
- const generator = complianceGenerator;
227
- const bundle = await generator.exportSigned(tenantId, filter, signingKeyId);
228
- if (bundle.kind === 'err') {
229
- const err = bundle.error;
230
- if (err.code === 'signing-key-missing') {
231
- c.status(statusFor('signing-key-not-found') as never);
232
- return c.json(
233
- toWireError(
234
- {
235
- code: 'signing-key-not-found',
236
- message: err.message,
237
- signingKeyId: err.signingKeyId as unknown as string,
238
- },
239
- requestId,
240
- ),
241
- );
242
- }
243
- if (err.code === 'signing-failure') {
244
- c.status(statusFor('compliance-export-failed') as never);
245
- return c.json(
246
- toWireError(
247
- {
248
- code: 'compliance-export-failed',
249
- message: err.message,
250
- signingKeyId: err.signingKeyId as unknown as string,
251
- },
252
- requestId,
253
- ),
254
- );
255
- }
256
- if (err.code === 'persistence-error') {
257
- c.status(statusFor('persistence-error') as never);
258
- return c.json(toWireError({ code: 'persistence-error', message: err.message }, requestId));
259
- }
260
- c.status(statusFor('compliance-export-failed') as never);
210
+ const records = await collectEvidence(auditEvents, tenantId, filter);
211
+ if (records.kind === 'err') {
212
+ c.status(statusFor('persistence-error') as never);
261
213
  return c.json(
262
- toWireError(
263
- {
264
- code: 'compliance-export-failed',
265
- message: `Signed export failed: ${(err as { readonly message: string }).message}`,
266
- },
267
- requestId,
268
- ),
214
+ toWireError({ code: 'persistence-error', message: records.error.message }, requestId),
269
215
  );
270
216
  }
271
- return c.json(bundle.value);
217
+ const signed = await signExport({
218
+ signer: exportSigning,
219
+ kind: 'compliance',
220
+ bundleSchemaVersion: BUNDLE_SCHEMA_VERSION,
221
+ ...(signingKeyId !== undefined && { signingKeyId }),
222
+ body: {
223
+ tenantId: tenantId as unknown as string,
224
+ filter,
225
+ records: records.value,
226
+ recordCount: records.value.length,
227
+ },
228
+ record: {
229
+ auditEvents,
230
+ tenantId,
231
+ actor: exportActor(c),
232
+ subject: { filter },
233
+ },
234
+ });
235
+ if (signed.kind === 'err')
236
+ return signExportFailure(c, signed.error, 'compliance-export-failed');
237
+ return c.json({ tenantId: tenantId as unknown as string, ...signed.value });
272
238
  });
273
239
 
274
240
  return r;
@@ -352,15 +318,13 @@ function buildAuditFilter(
352
318
  }
353
319
 
354
320
  interface ValidatedExportBody {
355
- readonly signingKeyId: SigningKeyId;
321
+ readonly signingKeyId: string | undefined;
356
322
  readonly filter: EvidenceFilter;
357
323
  }
358
324
 
359
325
  function parseExportBody(body: Record<string, unknown>): ParseResult<ValidatedExportBody> {
360
- const rawKey = body.signingKeyId;
361
- if (typeof rawKey !== 'string' || rawKey.length === 0) {
362
- return { kind: 'err', message: 'Field `signingKeyId` must be a non-empty string' };
363
- }
326
+ const signingKeyId = parseSigningKeyId(body);
327
+ if (signingKeyId.kind === 'err') return signingKeyId;
364
328
  const filterRaw = body.filter;
365
329
  if (
366
330
  filterRaw !== undefined &&
@@ -372,10 +336,7 @@ function parseExportBody(body: Record<string, unknown>): ParseResult<ValidatedEx
372
336
  if (parsedFilter.kind === 'err') return parsedFilter;
373
337
  return {
374
338
  kind: 'ok',
375
- value: {
376
- signingKeyId: rawKey as SigningKeyId,
377
- filter: parsedFilter.value ?? {},
378
- },
339
+ value: { signingKeyId: signingKeyId.value, filter: parsedFilter.value ?? {} },
379
340
  };
380
341
  }
381
342
 
@@ -10,13 +10,16 @@ import type {
10
10
  ConversationMessage,
11
11
  ConversationPageCursor,
12
12
  } from '@kindgi/agents';
13
+ import { type ResourceRef, ref } from '@kindgi/authz';
13
14
  import type { ProjectBinding } from '@kindgi/platform';
14
15
  import type { RunBinding } from '@kindgi/runtime';
15
16
  import type { AgentId, ProjectId, Semver, TenantId } from '@kindgi/types';
16
17
 
17
18
  import { statusFor, toWireError } from '../errors.js';
19
+ import type { Authorizer } from '../middleware/authorize.js';
18
20
  import type { AppEnv } from '../types.js';
19
- import { clampLimit, decodeCursor, encodeCursor } from './pagination.js';
21
+ import { deniedBy } from './denied.js';
22
+ import { clampLimit, decodeCursor, encodeCursor, isCursorTime } from './pagination.js';
20
23
  import { parseListScope } from './scope-params.js';
21
24
  import { refuseMalformedUuidParam } from './uuid-param.js';
22
25
 
@@ -46,6 +49,12 @@ export function conversationsRouter(
46
49
  * tenant's projects, and an omitted one is the tenant's Default project.
47
50
  */
48
51
  projectBinding?: ProjectBinding,
52
+ /**
53
+ * With one (T243 A): reading a conversation or its messages needs `read`
54
+ * on its project (its agent, for one from before projects); opening or
55
+ * closing one needs `execute` on its agent, as starting a run does.
56
+ */
57
+ authorizer?: Authorizer,
49
58
  ): Hono<AppEnv> {
50
59
  const r = new Hono<AppEnv>();
51
60
 
@@ -101,7 +110,7 @@ export function conversationsRouter(
101
110
  const rawCursor = c.req.query('cursor');
102
111
  if (rawCursor !== undefined && rawCursor.length > 0) {
103
112
  const decoded = decodeCursor(rawCursor);
104
- if (decoded === null) {
113
+ if (decoded === null || !isCursorTime(decoded.createdAt)) {
105
114
  c.status(statusFor('bad-input') as never);
106
115
  return c.json(
107
116
  toWireError({ code: 'bad-input', message: '`cursor` is malformed' }, requestId),
@@ -123,17 +132,25 @@ export function conversationsRouter(
123
132
  c.status(statusFor(listResult.error.code) as never);
124
133
  return c.json(toWireError(listResult.error as never, requestId));
125
134
  }
126
- const { data, hasMore } = listResult.value;
135
+ const { data, hasMore, next } = listResult.value;
127
136
  const last = data[data.length - 1];
137
+ // The binding's exact position when it gives one (`openedAt` to the
138
+ // microsecond); else the last row's, as a binding before it answers.
139
+ const position =
140
+ next ?? (last !== undefined ? { openedAt: last.openedAt, id: last.id } : undefined);
128
141
  const nextCursor =
129
- hasMore && last !== undefined
142
+ hasMore && position !== undefined
130
143
  ? encodeCursor({
131
- createdAt: last.openedAt as unknown as string,
132
- id: last.id as unknown as string,
144
+ createdAt: position.openedAt as unknown as string,
145
+ id: position.id as unknown as string,
133
146
  })
134
147
  : undefined;
148
+ const visible =
149
+ authorizer === undefined
150
+ ? data
151
+ : await authorizer.filterByCan(c, 'read', data, conversationRef);
135
152
  return c.json({
136
- data: data.map(serializeConversation),
153
+ data: visible.map(serializeConversation),
137
154
  hasMore,
138
155
  ...(nextCursor !== undefined && { nextCursor }),
139
156
  });
@@ -150,6 +167,8 @@ export function conversationsRouter(
150
167
  c.status(statusFor(got.error.code) as never);
151
168
  return c.json(toWireError(got.error as never, requestId));
152
169
  }
170
+ const refused = await deniedBy(authorizer, c, 'read', conversationRef(got.value));
171
+ if (refused !== undefined) return refused;
153
172
  return c.json(serializeConversation(got.value));
154
173
  });
155
174
 
@@ -192,6 +211,13 @@ export function conversationsRouter(
192
211
  // Omitted: the tenant's Default project, as for a run. No Default (or
193
212
  // no project binding): no project, never a refusal.
194
213
  const projectId = supplied ?? (await projectBinding?.getDefault(tenantId))?.id;
214
+ const refused = await deniedBy(
215
+ authorizer,
216
+ c,
217
+ 'execute',
218
+ ref('agent', parsed.value.agentId as unknown as string),
219
+ );
220
+ if (refused !== undefined) return refused;
195
221
 
196
222
  const opened = await conversationBinding.openConversation({
197
223
  tenantId,
@@ -224,6 +250,13 @@ export function conversationsRouter(
224
250
  c.status(statusFor(existing.error.code) as never);
225
251
  return c.json(toWireError(existing.error as never, requestId));
226
252
  }
253
+ const refused = await deniedBy(
254
+ authorizer,
255
+ c,
256
+ 'execute',
257
+ ref('agent', existing.value.agentId as unknown as string),
258
+ );
259
+ if (refused !== undefined) return refused;
227
260
  // Close is idempotent — closing an already-closed conversation
228
261
  // returns 200 with the current row, no error and no timestamp bump.
229
262
  if (existing.value.closedAt !== undefined) {
@@ -241,6 +274,44 @@ export function conversationsRouter(
241
274
  return c.json(serializeConversation(closed.value));
242
275
  });
243
276
 
277
+ // ---------- POST /:conversationId/unregister ----------
278
+ // A tombstone: from now on no read, list or recall returns the
279
+ // conversation, and no message can be added; the retention sweep
280
+ // removes it after the tenant's grace. Unregistered already, or never: 404.
281
+ // It needs `write` on the conversation's project (its agent, for one from
282
+ // before projects): an editor or above. Reading it isn't enough, nor is
283
+ // `execute`, which opening and closing one take.
284
+ r.post('/:conversationId/unregister', refuseMalformedConversationId, async (c) => {
285
+ const requestId = c.get('requestId');
286
+ const tenantId = c.get('tenantId') as TenantId;
287
+ const conversationId = c.req.param('conversationId') as ConversationId;
288
+ if (conversationBinding.unregisterConversation === undefined) {
289
+ c.status(statusFor('conversation-unregister-unsupported') as never);
290
+ return c.json(
291
+ toWireError(
292
+ {
293
+ code: 'conversation-unregister-unsupported',
294
+ message: "This runtime can't unregister conversations.",
295
+ },
296
+ requestId,
297
+ ),
298
+ );
299
+ }
300
+ const existing = await conversationBinding.getConversation(tenantId, conversationId);
301
+ if (existing.kind === 'err') {
302
+ c.status(statusFor(existing.error.code) as never);
303
+ return c.json(toWireError(existing.error as never, requestId));
304
+ }
305
+ const refused = await deniedBy(authorizer, c, 'write', conversationRef(existing.value));
306
+ if (refused !== undefined) return refused;
307
+ const unregistered = await conversationBinding.unregisterConversation(tenantId, conversationId);
308
+ if (unregistered.kind === 'err') {
309
+ c.status(statusFor(unregistered.error.code) as never);
310
+ return c.json(toWireError(unregistered.error as never, requestId));
311
+ }
312
+ return c.json(serializeConversation(unregistered.value));
313
+ });
314
+
244
315
  // ---------- GET /:conversationId/messages (cursor-paginated, sequence asc) ----------
245
316
  r.get('/:conversationId/messages', refuseMalformedConversationId, async (c) => {
246
317
  const requestId = c.get('requestId');
@@ -263,6 +334,15 @@ export function conversationsRouter(
263
334
  sinceSequence = decoded + 1;
264
335
  }
265
336
 
337
+ if (authorizer !== undefined) {
338
+ const got = await conversationBinding.getConversation(tenantId, conversationId);
339
+ if (got.kind === 'err') {
340
+ c.status(statusFor(got.error.code) as never);
341
+ return c.json(toWireError(got.error as never, requestId));
342
+ }
343
+ const refused = await deniedBy(authorizer, c, 'read', conversationRef(got.value));
344
+ if (refused !== undefined) return refused;
345
+ }
266
346
  const result = await conversationBinding.readMessages({
267
347
  tenantId,
268
348
  conversationId,
@@ -289,6 +369,17 @@ export function conversationsRouter(
289
369
  return r;
290
370
  }
291
371
 
372
+ /**
373
+ * What a conversation is checked on: its project, or its agent for one
374
+ * opened before conversations recorded a project. (A `conversation`
375
+ * object has no parent tuple, so a check on it would refuse everyone.)
376
+ */
377
+ function conversationRef(conv: Conversation): ResourceRef {
378
+ return conv.projectId !== undefined
379
+ ? ref('project', conv.projectId as unknown as string)
380
+ : ref('agent', conv.agentId as unknown as string);
381
+ }
382
+
292
383
  // ============ serializers ============
293
384
 
294
385
  function serializeConversation(c: Conversation): Record<string, unknown> {
@@ -304,6 +395,9 @@ function serializeConversation(c: Conversation): Record<string, unknown> {
304
395
  status: (c.closedAt === undefined ? 'open' : 'closed') as 'open' | 'closed',
305
396
  openedAt: c.openedAt as unknown as string,
306
397
  ...(c.closedAt !== undefined && { closedAt: c.closedAt as unknown as string }),
398
+ ...(c.unregisteredAt !== undefined && {
399
+ unregisteredAt: c.unregisteredAt as unknown as string,
400
+ }),
307
401
  turnCount: c.turnCount,
308
402
  ...(c.lastMessageAt !== undefined && { lastMessageAt: c.lastMessageAt as unknown as string }),
309
403
  ...(c.metadata !== undefined && { metadata: c.metadata }),
@@ -5,6 +5,7 @@ import { Hono } from 'hono';
5
5
 
6
6
  import type { Cursor, TenantId, Timestamp } from '@kindgi/types';
7
7
 
8
+ import { type ResourceRef, ref } from '@kindgi/authz';
8
9
  import {
9
10
  COST_AGGREGATE_DEFAULT_LIMIT,
10
11
  COST_AGGREGATE_MAX_LIMIT,
@@ -16,10 +17,13 @@ import {
16
17
  type CostRecordFilter,
17
18
  type CostTokenTotals,
18
19
  } from '../cost-binding.js';
20
+
19
21
  import { statusFor, toWireError } from '../errors.js';
22
+ import type { Authorizer } from '../middleware/authorize.js';
20
23
  import type { AppEnv } from '../types.js';
24
+ import { deniedBy } from './denied.js';
21
25
  import { clampLimit } from './pagination.js';
22
- import { parseScopeParams } from './scope-params.js';
26
+ import { parseScopeParams, scopeResourceRef } from './scope-params.js';
23
27
 
24
28
  /**
25
29
  * Cost readback routes — part of the admin control plane. Three
@@ -38,8 +42,19 @@ import { parseScopeParams } from './scope-params.js';
38
42
  *
39
43
  * Budgets are not part of this surface.
40
44
  */
41
- export function costRouter(binding: CostBinding): Hono<AppEnv> {
45
+ export function costRouter(
46
+ binding: CostBinding,
47
+ /**
48
+ * With one (T243 A): a record needs `read` on its project (the tenant,
49
+ * for one with no project); an aggregate, on the scope it's asked for.
50
+ */
51
+ authorizer?: Authorizer,
52
+ ): Hono<AppEnv> {
42
53
  const r = new Hono<AppEnv>();
54
+ const recordRef = (tenantId: TenantId, rec: { readonly projectId?: unknown }): ResourceRef =>
55
+ rec.projectId !== undefined && rec.projectId !== null
56
+ ? ref('project', rec.projectId as string)
57
+ : ref('tenant', tenantId as unknown as string);
43
58
 
44
59
  const DEFAULT_AGGREGATE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
45
60
 
@@ -81,8 +96,12 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
81
96
  ...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
82
97
  ...(include.rawUsage && { includeRawUsage: true }),
83
98
  });
99
+ const visible =
100
+ authorizer === undefined
101
+ ? page.data
102
+ : await authorizer.filterByCan(c, 'read', page.data, (rec) => recordRef(tenantId, rec));
84
103
  return c.json({
85
- data: page.data.map(serializeRecord),
104
+ data: visible.map(serializeRecord),
86
105
  hasMore: page.nextCursor !== undefined,
87
106
  ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
88
107
  });
@@ -117,6 +136,8 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
117
136
  ),
118
137
  );
119
138
  }
139
+ const refused = await deniedBy(authorizer, c, 'read', recordRef(tenantId, record));
140
+ if (refused !== undefined) return refused;
120
141
  return c.json(serializeRecord(record));
121
142
  });
122
143
 
@@ -249,6 +270,14 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
249
270
  );
250
271
  }
251
272
 
273
+ const refused = await deniedBy(
274
+ authorizer,
275
+ c,
276
+ 'read',
277
+ scopeResourceRef(scopeParsed.scope, tenantId),
278
+ );
279
+ if (refused !== undefined) return refused;
280
+
252
281
  const result = await binding.aggregate({
253
282
  tenantId,
254
283
  groupBy,
@@ -0,0 +1,28 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import type { Context } from 'hono';
5
+
6
+ import type { Action, ResourceRef } from '@kindgi/authz';
7
+
8
+ import type { Authorizer } from '../middleware/authorize.js';
9
+ import type { AppEnv } from '../types.js';
10
+
11
+ /**
12
+ * An in-handler check, for a resource known only once the request is
13
+ * read: nothing when the caller may take `action` on `resource` (or there
14
+ * is no authorizer), else the authorizer's own 403, to return as is.
15
+ */
16
+ export async function deniedBy(
17
+ authorizer: Authorizer | undefined,
18
+ c: Context<AppEnv>,
19
+ action: Action,
20
+ resource: ResourceRef,
21
+ ): Promise<Response | undefined> {
22
+ if (authorizer === undefined) return undefined;
23
+ let allowed = false;
24
+ const answer = await authorizer.authorize(action, () => resource)(c, async () => {
25
+ allowed = true;
26
+ });
27
+ return allowed ? undefined : (answer as Response);
28
+ }