@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
@@ -1,25 +1,32 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
 
4
- import { Hono } from 'hono';
4
+ import { type Context, Hono } from 'hono';
5
5
 
6
6
  import type { Cursor, TenantId, Timestamp } from '@kindgi/types';
7
7
 
8
+ import { type ResourceRef, denyPayload, ref } from '@kindgi/authz';
9
+ import type { ProjectBinding } from '@kindgi/platform';
8
10
  import {
9
11
  COST_AGGREGATE_DEFAULT_LIMIT,
10
12
  COST_AGGREGATE_MAX_LIMIT,
11
13
  COST_GROUP_DIMENSIONS,
12
14
  type CostAggregateGroup,
15
+ type CostAggregateInput,
13
16
  type CostBinding,
14
17
  type CostGroupDimension,
15
18
  type CostRecord,
16
19
  type CostRecordFilter,
17
20
  type CostTokenTotals,
18
21
  } from '../cost-binding.js';
22
+
19
23
  import { statusFor, toWireError } from '../errors.js';
24
+ import type { Authorizer } from '../middleware/authorize.js';
20
25
  import type { AppEnv } from '../types.js';
26
+ import { deniedBy } from './denied.js';
21
27
  import { clampLimit } from './pagination.js';
22
- import { parseScopeParams } from './scope-params.js';
28
+ import { projectIdsCallerMay } from './readable-projects.js';
29
+ import { parseScopeParams, scopeResourceRef } from './scope-params.js';
23
30
 
24
31
  /**
25
32
  * Cost readback routes — part of the admin control plane. Three
@@ -38,8 +45,23 @@ import { parseScopeParams } from './scope-params.js';
38
45
  *
39
46
  * Budgets are not part of this surface.
40
47
  */
41
- export function costRouter(binding: CostBinding): Hono<AppEnv> {
48
+ export function costRouter(
49
+ binding: CostBinding,
50
+ /**
51
+ * With one: a record needs `read` on its project (the tenant, for one
52
+ * with no project); an aggregate, `read` on the scope it's asked for,
53
+ * and across projects (no scope, or an org) it counts only the projects
54
+ * the caller may read, unless the caller is a tenant admin.
55
+ */
56
+ authorizer?: Authorizer,
57
+ /** The tenant's projects, to check one by one when the authorizer can't list them. */
58
+ projects?: Pick<ProjectBinding, 'list'>,
59
+ ): Hono<AppEnv> {
42
60
  const r = new Hono<AppEnv>();
61
+ const recordRef = (tenantId: TenantId, rec: { readonly projectId?: unknown }): ResourceRef =>
62
+ rec.projectId !== undefined && rec.projectId !== null
63
+ ? ref('project', rec.projectId as string)
64
+ : ref('tenant', tenantId as unknown as string);
43
65
 
44
66
  const DEFAULT_AGGREGATE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
45
67
 
@@ -81,8 +103,12 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
81
103
  ...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
82
104
  ...(include.rawUsage && { includeRawUsage: true }),
83
105
  });
106
+ const visible =
107
+ authorizer === undefined
108
+ ? page.data
109
+ : await authorizer.filterByCan(c, 'read', page.data, (rec) => recordRef(tenantId, rec));
84
110
  return c.json({
85
- data: page.data.map(serializeRecord),
111
+ data: visible.map(serializeRecord),
86
112
  hasMore: page.nextCursor !== undefined,
87
113
  ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
88
114
  });
@@ -117,6 +143,8 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
117
143
  ),
118
144
  );
119
145
  }
146
+ const refused = await deniedBy(authorizer, c, 'read', recordRef(tenantId, record));
147
+ if (refused !== undefined) return refused;
120
148
  return c.json(serializeRecord(record));
121
149
  });
122
150
 
@@ -249,6 +277,24 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
249
277
  );
250
278
  }
251
279
 
280
+ const refused = await deniedBy(
281
+ authorizer,
282
+ c,
283
+ 'read',
284
+ scopeResourceRef(scopeParsed.scope, tenantId),
285
+ );
286
+ if (refused !== undefined) return refused;
287
+
288
+ // Across projects, only what the caller may read counts (`aggregateReach`).
289
+ const reach = await aggregateReach(c, {
290
+ binding,
291
+ tenantId,
292
+ authorizer,
293
+ projects,
294
+ scope: scopeParsed.scope,
295
+ });
296
+ if (reach.kind === 'refused') return reach.response;
297
+
252
298
  const result = await binding.aggregate({
253
299
  tenantId,
254
300
  groupBy,
@@ -257,6 +303,7 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
257
303
  ...(Object.keys(filter.value).length > 0 && { filter: filter.value }),
258
304
  ...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
259
305
  ...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
306
+ ...(reach.kind === 'projects' && { readableProjectIds: reach.ids }),
260
307
  limit,
261
308
  });
262
309
 
@@ -285,6 +332,65 @@ export function costRouter(binding: CostBinding): Hono<AppEnv> {
285
332
 
286
333
  // -------- helpers --------
287
334
 
335
+ /**
336
+ * What an aggregate may count for this caller. Across projects (no scope,
337
+ * the tenant, or an org), `read` on the scope lets a member ask, not see
338
+ * every project's spend: only the projects they may read count, applied in
339
+ * the binding's query (`readableProjectIds`). A tenant admin's, a project
340
+ * scope's (already checked) and one without authorization count everything
341
+ * the scope holds. When the readable projects can't be worked out, or the
342
+ * binding can't apply them, the aggregate is refused rather than
343
+ * over-counted.
344
+ */
345
+ async function aggregateReach(
346
+ c: Context<AppEnv>,
347
+ args: {
348
+ readonly binding: CostBinding;
349
+ readonly tenantId: TenantId;
350
+ readonly authorizer: Authorizer | undefined;
351
+ readonly projects: Pick<ProjectBinding, 'list'> | undefined;
352
+ readonly scope: CostAggregateInput['scope'] | undefined;
353
+ },
354
+ ): Promise<
355
+ | { readonly kind: 'all' }
356
+ | { readonly kind: 'projects'; readonly ids: readonly string[] }
357
+ | { readonly kind: 'refused'; readonly response: Response }
358
+ > {
359
+ const { binding, tenantId, authorizer, projects, scope } = args;
360
+ if (authorizer === undefined || scope?.kind === 'project') return { kind: 'all' };
361
+ if (await authorizer.can(c, 'admin', ref('tenant', tenantId as unknown as string))) {
362
+ return { kind: 'all' };
363
+ }
364
+ const ids = await projectIdsCallerMay(c, authorizer, projects, 'read');
365
+ if (ids !== undefined && binding.aggregatesReadableProjects === true) {
366
+ return { kind: 'projects', ids };
367
+ }
368
+ const deny = denyPayload(
369
+ 'read',
370
+ scope?.kind === 'org' ? 'org' : 'tenant',
371
+ scope?.kind === 'org' ? (scope.orgId as unknown as string) : (tenantId as unknown as string),
372
+ ids === undefined
373
+ ? "the projects you may read can't be listed here, so an aggregate across projects can't be limited to them; ask per project (scopeKind=project)"
374
+ : "this deployment's cost store can't limit an aggregate to the projects you may read; ask per project (scopeKind=project)",
375
+ );
376
+ c.status(403);
377
+ return {
378
+ kind: 'refused',
379
+ response: c.json(
380
+ toWireError(
381
+ {
382
+ code: deny.code,
383
+ message: `Permission denied: ${deny.reason}`,
384
+ action: deny.action,
385
+ resource: deny.resource,
386
+ reason: deny.reason,
387
+ },
388
+ c.get('requestId'),
389
+ ),
390
+ ),
391
+ };
392
+ }
393
+
288
394
  function parseRecordFilter(
289
395
  query: Readonly<Record<string, string | undefined>>,
290
396
  opts: { skipTime?: boolean } = {},
@@ -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
+ }
@@ -9,7 +9,12 @@ import type { Agent, AgentId, AgentPins } from '@kindgi/agents';
9
9
  import { tuplesForCreate } from '@kindgi/authz';
10
10
  import { parsePublicKeyPem, verifyEd25519 } from '@kindgi/crypto';
11
11
  import type { Flow, FlowPins } from '@kindgi/flow';
12
- import { type Guardrail, validateGuardrailSpec } from '@kindgi/guardrails';
12
+ import {
13
+ GUARDRAIL_SPEC_KEYS,
14
+ type Guardrail,
15
+ createCheckRegistry,
16
+ validateGuardrailSpec,
17
+ } from '@kindgi/guardrails';
13
18
  import type { ProjectBinding, Scope } from '@kindgi/platform';
14
19
  import { validateToolManifest } from '@kindgi/tools';
15
20
  import type {
@@ -42,6 +47,7 @@ import { type FlowPinsLive, publishDeployedFlow, resolveFlowPins } from '../flow
42
47
  import type { GuardrailRegistryBinding } from '../guardrail-binding.js';
43
48
  import type { ImageRegistryBinding } from '../image-registry-binding.js';
44
49
  import type { LiveVersionBinding } from '../live-version-binding.js';
50
+ import type { Authorizer } from '../middleware/authorize.js';
45
51
  import { PublishRefused } from '../publish-refused.js';
46
52
  import { type RegistryReadOnly, refuseReadOnly } from '../registry-read-only.js';
47
53
  import type { SecretBinding } from '../secrets-binding.js';
@@ -51,6 +57,7 @@ import type { AppEnv } from '../types.js';
51
57
  import { hasCapability, requireEnvName } from './env.js';
52
58
  import type { GuardrailWriteHook } from './guardrails.js';
53
59
  import { clampLimit } from './pagination.js';
60
+ import { tenantResourceAccess } from './tenant-access.js';
54
61
  import type { ToolWriteHook } from './tools.js';
55
62
 
56
63
  /**
@@ -167,8 +174,12 @@ export interface DeploymentsRouterBindings {
167
174
  readonly onGuardrailWrite?: GuardrailWriteHook;
168
175
  }
169
176
 
170
- export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<AppEnv> {
177
+ export function deploymentsRouter(
178
+ bindings: DeploymentsRouterBindings,
179
+ authorizer?: Authorizer,
180
+ ): Hono<AppEnv> {
171
181
  const r = new Hono<AppEnv>();
182
+ r.use('*', tenantResourceAccess(authorizer));
172
183
 
173
184
  // ---------- GET / (list, cursor-paginated) ----------
174
185
  r.get('/', async (c) => {
@@ -476,10 +487,11 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
476
487
  }
477
488
 
478
489
  // ---- Manifest validation ----
479
- const validation = validatePrimitives(imageIndex, {
480
- imageRef: wire.imageRef,
481
- artifactVersion: wire.artifactVersion,
482
- });
490
+ const validation = validatePrimitives(
491
+ imageIndex,
492
+ { imageRef: wire.imageRef, artifactVersion: wire.artifactVersion },
493
+ c.get('log'),
494
+ );
483
495
  if (validation.kind === 'err') {
484
496
  c.status(statusFor('deployment-validation-failed') as never);
485
497
  return c.json(
@@ -580,7 +592,7 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
580
592
  await bindings.toolRegistry?.unregister({ tenantId, toolId, version });
581
593
  });
582
594
  } else if (outcome.kind !== 'already-registered') {
583
- throw new PublishRefused('tool', `${tool.id}@${tool.version}`, outcome.kind);
595
+ throw new PublishRefused('tool', `${tool.id}@${tool.version}`, outcome);
584
596
  }
585
597
  }
586
598
  }
@@ -604,8 +616,22 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
604
616
  rolled.push(async () => {
605
617
  await bindings.guardrailRegistry?.unregister({ tenantId, guardrailId });
606
618
  });
607
- } else if (outcome.kind !== 'already-registered') {
608
- throw new PublishRefused('guardrail', guardrail.id, outcome.kind);
619
+ } else if (outcome.kind === 'already-registered') {
620
+ const kept = await keepRegisteredGuardrail(
621
+ bindings.guardrailRegistry,
622
+ tenantId,
623
+ projectIdForGuardrail,
624
+ guardrail,
625
+ );
626
+ // Unregistered since the registry answered: registered afresh.
627
+ if (kept === 'registered') {
628
+ const guardrailId = guardrail.id;
629
+ rolled.push(async () => {
630
+ await bindings.guardrailRegistry?.unregister({ tenantId, guardrailId });
631
+ });
632
+ }
633
+ } else {
634
+ throw new PublishRefused('guardrail', guardrail.id, outcome);
609
635
  }
610
636
  }
611
637
  }
@@ -645,6 +671,13 @@ export function deploymentsRouter(bindings: DeploymentsRouterBindings): Hono<App
645
671
  // A primitive refused with a typed outcome is the caller's to fix:
646
672
  // that outcome's own status and code. Anything thrown is a 500.
647
673
  if (cause instanceof PublishRefused) {
674
+ if (cause.projectId !== undefined) {
675
+ c.get('log').info(`${cause.message}: deploy refused`, {
676
+ primitive: cause.primitive,
677
+ id: cause.id,
678
+ ownerProjectId: cause.projectId as unknown as string,
679
+ });
680
+ }
648
681
  c.status(statusFor(cause.code) as never);
649
682
  return c.json(
650
683
  toWireError(
@@ -1215,6 +1248,139 @@ interface DeployedImage {
1215
1248
  readonly artifactVersion: string;
1216
1249
  }
1217
1250
 
1251
+ /**
1252
+ * A deploy keeps a guardrail id that's already live only when it's the
1253
+ * deploy's own: in the project the deploy registers into, with the same
1254
+ * definition (`sameGuardrailDefinition`, what its author declares). An id live in another project
1255
+ * is refused (`guardrail-project-mismatch`, its project never named): the
1256
+ * pack's agents would otherwise run that project's guardrail. One in this
1257
+ * project with another definition is refused too
1258
+ * (`guardrail-already-registered`): a deploy never changes a guardrail,
1259
+ * and keeping the old one would run what the pack no longer says.
1260
+ *
1261
+ * `get` answers a guardrail without its project, so whether the id is in
1262
+ * this project comes from the project's list. When the row is gone by the
1263
+ * time it's looked at (unregistered meanwhile), the guardrail is
1264
+ * registered again: `'registered'`, for the deploy to roll back.
1265
+ */
1266
+ async function keepRegisteredGuardrail(
1267
+ registry: GuardrailRegistryBinding,
1268
+ tenantId: TenantId,
1269
+ projectId: ProjectId,
1270
+ guardrail: Guardrail,
1271
+ ): Promise<'kept' | 'registered'> {
1272
+ for (let attempt = 0; attempt < 3; attempt++) {
1273
+ const existing = await registry.get({ tenantId, guardrailId: guardrail.id });
1274
+ if (existing !== null) {
1275
+ if (!(await guardrailInProject(registry, tenantId, projectId, guardrail.id))) {
1276
+ throw new PublishRefused('guardrail', guardrail.id, {
1277
+ code: 'guardrail-project-mismatch',
1278
+ reason: 'it belongs to another project',
1279
+ });
1280
+ }
1281
+ if (!sameGuardrailDefinition(existing, guardrail)) {
1282
+ throw new PublishRefused('guardrail', guardrail.id, {
1283
+ code: 'guardrail-already-registered',
1284
+ reason: `it is already registered with a different definition; unregister it (\`kindgi guardrails unregister ${guardrail.id}\`) and deploy again`,
1285
+ });
1286
+ }
1287
+ return 'kept';
1288
+ }
1289
+ const again = await registry.register({
1290
+ tenantId,
1291
+ projectId,
1292
+ guardrail,
1293
+ enqueueTuples: (guardrailId) =>
1294
+ tuplesForCreate({
1295
+ kind: 'guardrail',
1296
+ id: guardrailId as GuardrailId,
1297
+ tenantId,
1298
+ projectId,
1299
+ }),
1300
+ });
1301
+ if (again.kind === 'ok') return 'registered';
1302
+ if (again.kind !== 'already-registered') {
1303
+ throw new PublishRefused('guardrail', guardrail.id, again);
1304
+ }
1305
+ }
1306
+ throw new Error(`guardrail ${guardrail.id}: registered and unregistered while deploying`);
1307
+ }
1308
+
1309
+ /** Whether the live guardrail `id` is in `projectId`, by that project's list. */
1310
+ async function guardrailInProject(
1311
+ registry: GuardrailRegistryBinding,
1312
+ tenantId: TenantId,
1313
+ projectId: ProjectId,
1314
+ id: GuardrailId,
1315
+ ): Promise<boolean> {
1316
+ let cursor: Cursor | undefined;
1317
+ do {
1318
+ const page = await registry.list({
1319
+ tenantId,
1320
+ limit: 100,
1321
+ nameFilter: id,
1322
+ scope: { kind: 'project', tenantId, projectId },
1323
+ ...(cursor !== undefined && { cursor }),
1324
+ });
1325
+ if (page.data.some((g) => g.id === id)) return true;
1326
+ cursor = page.nextCursor;
1327
+ } while (cursor !== undefined);
1328
+ return false;
1329
+ }
1330
+
1331
+ /**
1332
+ * The fields of a guardrail its author declares, which a deploy compares.
1333
+ * Never compared: what a deploy or a release derives. That includes
1334
+ * `configSchema`, which the deploy route dropped before 0.1.5, so a row a
1335
+ * 0.1.4 deploy stored has none; the image and artifact version a code
1336
+ * pointer names, which every new image changes; and any field a later
1337
+ * release adds. So an unchanged pack redeploys across releases.
1338
+ */
1339
+ const DECLARED_GUARDRAIL_FIELDS = [
1340
+ 'name',
1341
+ 'description',
1342
+ 'kind',
1343
+ 'check',
1344
+ 'config',
1345
+ 'action',
1346
+ 'severity',
1347
+ 'scope',
1348
+ 'budget',
1349
+ 'judgeCapabilities',
1350
+ 'sandbox',
1351
+ 'limits',
1352
+ 'network',
1353
+ 'needsSpec',
1354
+ ] as const;
1355
+
1356
+ /**
1357
+ * The same guardrail definition: equal in what its author declares
1358
+ * (`DECLARED_GUARDRAIL_FIELDS`, and of where its code lives only the
1359
+ * module path), as JSON with keys in any order (a registry may store it as
1360
+ * JSONB) and an absent field the same as an `undefined` one.
1361
+ */
1362
+ export function sameGuardrailDefinition(a: Guardrail, b: Guardrail): boolean {
1363
+ return canonicalJson(definitionOf(a)) === canonicalJson(definitionOf(b));
1364
+ }
1365
+
1366
+ function definitionOf(guardrail: Guardrail): Record<string, unknown> {
1367
+ const declared: Record<string, unknown> = {};
1368
+ for (const field of DECLARED_GUARDRAIL_FIELDS) {
1369
+ declared[field] = (guardrail as unknown as Record<string, unknown>)[field];
1370
+ }
1371
+ declared.modulePath = guardrail.codeArtifactRef?.modulePath;
1372
+ return declared;
1373
+ }
1374
+
1375
+ /** JSON with every object's keys sorted, and absent and `undefined` alike. */
1376
+ function canonicalJson(value: unknown): string {
1377
+ return JSON.stringify(JSON.parse(JSON.stringify(value) ?? 'null'), (_key, v: unknown) =>
1378
+ v !== null && typeof v === 'object' && !Array.isArray(v)
1379
+ ? Object.fromEntries(Object.entries(v).sort(([x], [y]) => (x < y ? -1 : x > y ? 1 : 0)))
1380
+ : v,
1381
+ );
1382
+ }
1383
+
1218
1384
  /** The pointer to a tool's or guardrail's module inside the deployed image. */
1219
1385
  function ociCodeArtifactRef(image: DeployedImage, modulePath: unknown) {
1220
1386
  return typeof modulePath === 'string' && modulePath.length > 0
@@ -1236,9 +1402,13 @@ function ociCodeArtifactRef(image: DeployedImage, modulePath: unknown) {
1236
1402
  * a guardrail's `checkId` becomes its `check`, as `kindgi dev`'s disk
1237
1403
  * registry maps it.
1238
1404
  */
1405
+ /** The built-in checks, for the config of a guardrail naming one. */
1406
+ const builtInChecks = createCheckRegistry();
1407
+
1239
1408
  function validatePrimitives(
1240
1409
  index: Readonly<Record<string, unknown>>,
1241
1410
  image: DeployedImage,
1411
+ log?: { debug(message: string): void },
1242
1412
  ): ValidateResult {
1243
1413
  const details: ValidationDetail[] = [];
1244
1414
 
@@ -1286,12 +1456,20 @@ function validatePrimitives(
1286
1456
  details.push({ primitive: 'guardrail', index: i, path: '', message: 'must be an object' });
1287
1457
  return;
1288
1458
  }
1289
- const {
1290
- checkModulePath,
1291
- checkId,
1292
- configSchema: _configSchema,
1293
- ...rest
1294
- } = raw as Record<string, unknown>;
1459
+ // The rest is the guardrail as registered, its `configSchema` included:
1460
+ // the runtime checks a guardrail naming this check against it. A field
1461
+ // the guardrail spec doesn't have (an index from a newer CLI) is dropped,
1462
+ // never refused, so a newer CLI never breaks a deployment.
1463
+ const { checkModulePath, checkId, ...indexed } = raw as Record<string, unknown>;
1464
+ const dropped = Object.keys(indexed).filter((k) => !GUARDRAIL_SPEC_KEYS.includes(k));
1465
+ const rest = Object.fromEntries(
1466
+ Object.entries(indexed).filter(([k]) => GUARDRAIL_SPEC_KEYS.includes(k)),
1467
+ );
1468
+ if (dropped.length > 0) {
1469
+ log?.debug(
1470
+ `deployment: guardrail ${String(indexed.id)}: ignored index field(s) this runtime doesn't know: ${dropped.join(', ')}`,
1471
+ );
1472
+ }
1295
1473
  const r = validateGuardrailSpec({
1296
1474
  ...rest,
1297
1475
  check: checkId ?? rest.check ?? rest.id,
@@ -1325,6 +1503,21 @@ function validatePrimitives(
1325
1503
  }
1326
1504
  return;
1327
1505
  }
1506
+ // A guardrail naming a built-in check: its config against the built-in's.
1507
+ const builtIn = builtInChecks.get(r.value.check);
1508
+ const configProblems = builtIn?.configProblems?.(r.value.config) ?? [];
1509
+ if (configProblems.length > 0) {
1510
+ for (const problem of configProblems) {
1511
+ details.push({
1512
+ primitive: 'guardrail',
1513
+ index: i,
1514
+ id: r.value.id as unknown as string,
1515
+ path: problem.path,
1516
+ message: problem.message,
1517
+ });
1518
+ }
1519
+ return;
1520
+ }
1328
1521
  validatedGuardrails.push(r.value);
1329
1522
  });
1330
1523
 
@@ -1524,7 +1717,7 @@ async function registerAgents(input: {
1524
1717
  const outcome = await agents.publish({ tenantId, projectId, agent, enqueueTuples });
1525
1718
  if (outcome.kind === 'ok') written(outcome.agentId, outcome.version);
1526
1719
  else if (outcome.kind !== 'already-registered') {
1527
- throw new PublishRefused('agent', `${agent.id}@${agent.version}`, outcome.kind);
1720
+ throw new PublishRefused('agent', `${agent.id}@${agent.version}`, outcome);
1528
1721
  }
1529
1722
  }
1530
1723
  return input.defined.map(deployedPrimitive);
@@ -1588,7 +1781,7 @@ async function registerFlows(input: {
1588
1781
  const outcome = await flows.publish({ tenantId, projectId, flow, enqueueTuples });
1589
1782
  if (outcome.kind === 'ok') written(outcome.flowId, outcome.version as unknown as string);
1590
1783
  else if (outcome.kind !== 'already-registered') {
1591
- throw new PublishRefused('flow', `${flow.id}@${flow.version}`, outcome.kind);
1784
+ throw new PublishRefused('flow', `${flow.id}@${flow.version}`, outcome);
1592
1785
  }
1593
1786
  }
1594
1787
  return input.defined.map(deployedPrimitive);
@@ -5,12 +5,18 @@ import type { AgentId } from '@kindgi/agents';
5
5
  import type { FlowVersionOverrides } from '@kindgi/flow';
6
6
  import type { ProjectId, Semver } from '@kindgi/types';
7
7
 
8
- import type { EvalBaseline, EvalComparison } from '../eval-run-binding.js';
8
+ import type {
9
+ EvalBaseline,
10
+ EvalComparison,
11
+ EvalOverrides,
12
+ EvalSample,
13
+ } from '../eval-run-binding.js';
9
14
  import { DEFAULT_COMPARISON } from '../judged-dispatcher.js';
10
15
  import { parseSegmentsBody } from './segments.js';
11
16
 
12
17
  const MAX_REPETITIONS = 10;
13
18
  const MAX_K = 100;
19
+ const MAX_OVERRIDDEN_BLOCKS = 20;
14
20
 
15
21
  function obj(value: unknown): Record<string, unknown> | undefined {
16
22
  return typeof value === 'object' && value !== null && !Array.isArray(value)
@@ -84,6 +90,71 @@ function integerIn(raw: unknown, name: string, max: number): number | string {
84
90
  : `\`${name}\` must be an integer from 1 to ${max}`;
85
91
  }
86
92
 
93
+ /** `overrides: { settings?, prompts? }`; `undefined` when it names nothing. */
94
+ function parseOverrides(raw: unknown): EvalOverrides | undefined | string {
95
+ const o = obj(raw);
96
+ if (o === undefined) return '`overrides` must be an object: { settings?, prompts? }';
97
+ const extra = Object.keys(o).filter((key) => key !== 'settings' && key !== 'prompts');
98
+ if (extra.length > 0) {
99
+ return `\`overrides\` takes \`settings\` and \`prompts\`, not \`${extra[0]}\``;
100
+ }
101
+ const settings = o.settings === undefined ? {} : obj(o.settings);
102
+ const prompts = o.prompts === undefined ? {} : obj(o.prompts);
103
+ const settingsBlocks = settings === undefined ? [] : Object.entries(settings);
104
+ const promptBlocks = prompts === undefined ? [] : Object.entries(prompts);
105
+ if (
106
+ settings === undefined ||
107
+ settingsBlocks.length > MAX_OVERRIDDEN_BLOCKS ||
108
+ settingsBlocks.some(([id, values]) => id === '' || obj(values) === undefined)
109
+ ) {
110
+ return `\`overrides.settings\` must be an object of { blockId: { …values } } (at most ${MAX_OVERRIDDEN_BLOCKS} blocks)`;
111
+ }
112
+ if (
113
+ prompts === undefined ||
114
+ promptBlocks.length > 1 ||
115
+ promptBlocks.some(([id, content]) => {
116
+ const c = obj(content);
117
+ return (
118
+ id === '' ||
119
+ c === undefined ||
120
+ typeof c.template !== 'string' ||
121
+ Object.keys(c).length !== 1
122
+ );
123
+ })
124
+ ) {
125
+ return '`overrides.prompts` must be { blockId: { template } } for the prompt block (one)';
126
+ }
127
+ if (settingsBlocks.length === 0 && promptBlocks.length === 0) return undefined;
128
+ return {
129
+ ...(settingsBlocks.length > 0 && {
130
+ settings: settings as Readonly<Record<string, Readonly<Record<string, unknown>>>>,
131
+ }),
132
+ ...(promptBlocks.length > 0 && {
133
+ prompts: prompts as Readonly<Record<string, { readonly template: string }>>,
134
+ }),
135
+ };
136
+ }
137
+
138
+ /** `sample: { part, seed, holdOutShare }`, or an error message. */
139
+ function parseSample(raw: unknown): EvalSample | string {
140
+ const o = obj(raw);
141
+ const share = o?.holdOutShare;
142
+ if (
143
+ o === undefined ||
144
+ (o.part !== 'search' && o.part !== 'hold-out') ||
145
+ typeof o.seed !== 'string' ||
146
+ o.seed === '' ||
147
+ o.seed.length > 200 ||
148
+ typeof share !== 'number' ||
149
+ share < 0.1 ||
150
+ share > 0.9 ||
151
+ Object.keys(o).some((key) => !['part', 'seed', 'holdOutShare'].includes(key))
152
+ ) {
153
+ return "`sample` must be { part: 'search' | 'hold-out', seed, holdOutShare } with holdOutShare from 0.1 to 0.9";
154
+ }
155
+ return { part: o.part, seed: o.seed, holdOutShare: share };
156
+ }
157
+
87
158
  /**
88
159
  * A comparison eval run's settings from the start body: `baseline`,
89
160
  * `reads`, `repetitions`, `k`, `classWeights` and a flow candidate's
@@ -99,13 +170,19 @@ export function parseComparison(
99
170
  const { baseline, reads, repetitions, k, classWeights } = b;
100
171
  const versions = b.versions === undefined ? undefined : parseVersions(b.versions);
101
172
  if (typeof versions === 'string') return { kind: 'err', message: versions };
173
+ const overrides = b.overrides === undefined ? undefined : parseOverrides(b.overrides);
174
+ if (typeof overrides === 'string') return { kind: 'err', message: overrides };
175
+ const sample = b.sample === undefined ? undefined : parseSample(b.sample);
176
+ if (typeof sample === 'string') return { kind: 'err', message: sample };
102
177
  if (
103
178
  baseline === undefined &&
104
179
  reads === undefined &&
105
180
  repetitions === undefined &&
106
181
  k === undefined &&
107
182
  versions === undefined &&
108
- classWeights === undefined
183
+ classWeights === undefined &&
184
+ overrides === undefined &&
185
+ sample === undefined
109
186
  ) {
110
187
  return { kind: 'ok' };
111
188
  }
@@ -144,6 +221,8 @@ export function parseComparison(
144
221
  k: topK,
145
222
  ...(versions !== undefined && { versions }),
146
223
  ...(classWeights !== undefined && { classWeights }),
224
+ ...(overrides !== undefined && { overrides }),
225
+ ...(sample !== undefined && { sample }),
147
226
  },
148
227
  };
149
228
  }