@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
@@ -167,6 +167,31 @@ export const RunAgentSchema: JsonSchema = {
167
167
  },
168
168
  };
169
169
 
170
+ /**
171
+ * The trigger that started a run. A component of its own, so generated
172
+ * clients name it `RunTrigger`.
173
+ */
174
+ export const RunTriggerSchema: JsonSchema = {
175
+ type: 'object',
176
+ additionalProperties: false,
177
+ required: ['triggerId', 'kind', 'fireId'],
178
+ description:
179
+ 'Set on a run a trigger started (a schedule, an event trigger or an inbound webhook): the trigger and the fire that started it. Absent on other runs.',
180
+ properties: {
181
+ triggerId: { type: 'string', format: 'uuid' },
182
+ kind: { type: 'string', enum: ['schedule', 'event', 'webhook'] },
183
+ fireId: {
184
+ type: 'string',
185
+ description: "The fire that started the run: one entry of the trigger's fire history.",
186
+ },
187
+ scheduledFor: {
188
+ type: 'string',
189
+ format: 'date-time',
190
+ description: "A schedule's fire: the occurrence the run is for.",
191
+ },
192
+ },
193
+ };
194
+
170
195
  export const ScopeSegmentSchema: JsonSchema = {
171
196
  type: 'object',
172
197
  additionalProperties: false,
@@ -581,6 +606,22 @@ export const UnpinBodySchema: JsonSchema = {
581
606
  },
582
607
  };
583
608
 
609
+ export const RunFailureSchema: JsonSchema = {
610
+ type: 'object',
611
+ additionalProperties: false,
612
+ required: ['code', 'message'],
613
+ description:
614
+ "Why a failed run failed; present only on a `failed` run. An agent turn's failure carries its own code (`budget-exceeded`, `capability-routing-failed`, `model-invocation-failed`, …); any other failure is `run-failed`, with the run's failure message.",
615
+ properties: {
616
+ code: { type: 'string' },
617
+ message: { type: 'string' },
618
+ cause: {
619
+ description:
620
+ "What the error came from, when it says: e.g. for `capability-routing-failed`, the router's `capability-unsatisfiable` with its reasons, by provider.",
621
+ },
622
+ },
623
+ };
624
+
584
625
  export const RunSchema: JsonSchema = {
585
626
  type: 'object',
586
627
  additionalProperties: false,
@@ -605,11 +646,22 @@ export const RunSchema: JsonSchema = {
605
646
  createdAt: { type: 'string', format: 'date-time' },
606
647
  updatedAt: { type: 'string', format: 'date-time' },
607
648
  completedAt: { type: 'string', format: 'date-time' },
608
- failureMessage: { type: 'string' },
649
+ failureMessage: {
650
+ type: 'string',
651
+ description:
652
+ 'The failure as the runtime recorded it. Read `failure` instead: an agent turn records its typed error here in an internal form.',
653
+ },
654
+ failure: { $ref: '#/components/schemas/RunFailure' },
609
655
  output: {
610
656
  description:
611
657
  "The run's output once it completed. Present on single-run responses; on lists only with `?include=output`.",
612
658
  },
659
+ contentErasedAt: {
660
+ type: 'string',
661
+ format: 'date-time',
662
+ description:
663
+ "When an erasure cleared the run's content (its input, output, failure message and journal payloads): a person's words were erased. Structure (status, times, ids) stays.",
664
+ },
613
665
  parentRunId: {
614
666
  type: 'string',
615
667
  format: 'uuid',
@@ -621,6 +673,7 @@ export const RunSchema: JsonSchema = {
621
673
  description: 'Set on a child run: the node in the parent run that started it.',
622
674
  },
623
675
  agent: { $ref: '#/components/schemas/RunAgent' },
676
+ trigger: { $ref: '#/components/schemas/RunTrigger' },
624
677
  replayOf: {
625
678
  type: 'string',
626
679
  format: 'uuid',
@@ -898,7 +951,18 @@ const ApiTokenRoleSchema: JsonSchema = {
898
951
  type: 'string',
899
952
  enum: ['admin', 'member'],
900
953
  description:
901
- "The key's role in its tenant: `admin` administers the tenant (and manages keys); `member` belongs to it and administers nothing.",
954
+ "The most the key may do, under its principal's grants: an `admin` key may administer the tenant when its principal is a tenant admin; a `member` key takes no admin action on the tenant, whoever it's for; below it, its principal's roles hold (a project admin's member key administers that project).",
955
+ };
956
+
957
+ export const ApiKeyPrincipalSchema: JsonSchema = {
958
+ type: 'object',
959
+ additionalProperties: false,
960
+ required: ['kind', 'id'],
961
+ description: 'Whom an API key acts for: a person, or a service account.',
962
+ properties: {
963
+ kind: { type: 'string', enum: ['user', 'service-account'] },
964
+ id: { type: 'string', minLength: 1, description: 'The user id, or the service account id.' },
965
+ },
902
966
  };
903
967
 
904
968
  const ApiTokenCapabilitiesSchema: JsonSchema = {
@@ -911,10 +975,13 @@ const ApiTokenCapabilitiesSchema: JsonSchema = {
911
975
  export const MintTokenBodySchema: JsonSchema = {
912
976
  type: 'object',
913
977
  additionalProperties: false,
978
+ description:
979
+ 'A new API key. `for` is whom it acts for: the caller by default; only a tenant admin mints for someone else.',
914
980
  properties: {
981
+ for: { $ref: '#/components/schemas/ApiKeyPrincipal' },
915
982
  role: {
916
983
  ...ApiTokenRoleSchema,
917
- description: `${ApiTokenRoleSchema.description} Default \`member\`.`,
984
+ description: `${ApiTokenRoleSchema.description} Default \`member\`; \`admin\` needs a tenant admin minting it.`,
918
985
  },
919
986
  capabilities: {
920
987
  ...ApiTokenCapabilitiesSchema,
@@ -922,24 +989,35 @@ export const MintTokenBodySchema: JsonSchema = {
922
989
  },
923
990
  label: { type: 'string', description: 'Optional human-readable label.' },
924
991
  expiresAt: { type: 'string', format: 'date-time', description: 'ISO 8601 timestamp.' },
925
- projectId: { type: 'string', format: 'uuid' },
992
+ projectId: {
993
+ type: 'string',
994
+ format: 'uuid',
995
+ description:
996
+ 'Limit the key to this project: a request naming another project is refused (`key-project-mismatch`). A key limited to a project mints only keys limited to it.',
997
+ },
926
998
  },
927
999
  };
928
1000
 
929
1001
  export const ApiTokenSchema: JsonSchema = {
930
1002
  type: 'object',
931
1003
  additionalProperties: false,
932
- description: 'An API key: a service account in its tenant. Never includes the secret.',
1004
+ description:
1005
+ 'An API key. Never includes the secret. `principal` is whom it acts for; absent on a key that is a service account of its own (`service_account:<tokenId>`), as keys minted before principals are.',
933
1006
  required: ['tokenId', 'role', 'capabilities', 'createdAt'],
934
1007
  properties: {
935
1008
  tokenId: { type: 'string', format: 'uuid' },
1009
+ principal: { $ref: '#/components/schemas/ApiKeyPrincipal' },
936
1010
  role: ApiTokenRoleSchema,
937
1011
  capabilities: ApiTokenCapabilitiesSchema,
938
1012
  label: { type: 'string' },
939
- projectId: { type: 'string', format: 'uuid' },
1013
+ projectId: {
1014
+ type: 'string',
1015
+ format: 'uuid',
1016
+ description: 'The project the key is limited to.',
1017
+ },
940
1018
  createdBy: {
941
1019
  type: 'string',
942
- description: 'Who minted it: `user:<id>` or `service_account:<tokenId>`.',
1020
+ description: 'Who minted it: `user:<id>` or `service_account:<id>`.',
943
1021
  },
944
1022
  createdAt: { type: 'string', format: 'date-time' },
945
1023
  expiresAt: { type: 'string', format: 'date-time' },
@@ -984,6 +1062,133 @@ export const ApiTokenPageSchema: JsonSchema = {
984
1062
  },
985
1063
  };
986
1064
 
1065
+ // ---------------- service accounts ----------------
1066
+
1067
+ export const ServiceAccountGrantTenantAdminSchema: JsonSchema = {
1068
+ type: 'object',
1069
+ additionalProperties: false,
1070
+ required: ['kind'],
1071
+ description: 'Tenant admin.',
1072
+ properties: { kind: { type: 'string', enum: ['tenant-admin'] } },
1073
+ };
1074
+
1075
+ export const ServiceAccountGrantTenantMemberSchema: JsonSchema = {
1076
+ type: 'object',
1077
+ additionalProperties: false,
1078
+ required: ['kind'],
1079
+ description:
1080
+ "Tenant member: read the tenant's settings (providers, policies, adapters, signing keys, deployments), not its projects. A service account has it only when granted; a person has it from being added.",
1081
+ properties: { kind: { type: 'string', enum: ['tenant-member'] } },
1082
+ };
1083
+
1084
+ export const ServiceAccountGrantProjectSchema: JsonSchema = {
1085
+ type: 'object',
1086
+ additionalProperties: false,
1087
+ required: ['kind', 'projectId', 'role'],
1088
+ description: "A role on one project; it replaces the account's role there.",
1089
+ properties: {
1090
+ kind: { type: 'string', enum: ['project'] },
1091
+ projectId: { type: 'string', format: 'uuid' },
1092
+ role: { $ref: '#/components/schemas/ProjectRole' },
1093
+ },
1094
+ };
1095
+
1096
+ export const ServiceAccountGrantSchema: JsonSchema = {
1097
+ description:
1098
+ "What a service account may do: tenant admin, tenant member (read the tenant's settings), or a role on one project.",
1099
+ oneOf: [
1100
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantAdmin' },
1101
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantMember' },
1102
+ { $ref: '#/components/schemas/ServiceAccountGrantProject' },
1103
+ ],
1104
+ discriminator: { propertyName: 'kind' },
1105
+ };
1106
+
1107
+ export const ServiceAccountGrantBodySchema: JsonSchema = {
1108
+ description: 'The grant to add: tenant admin, tenant member, or a role on one project.',
1109
+ oneOf: [
1110
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantAdmin' },
1111
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantMember' },
1112
+ { $ref: '#/components/schemas/ServiceAccountGrantProject' },
1113
+ ],
1114
+ discriminator: { propertyName: 'kind' },
1115
+ };
1116
+
1117
+ export const ServiceAccountUngrantProjectSchema: JsonSchema = {
1118
+ type: 'object',
1119
+ additionalProperties: false,
1120
+ required: ['kind', 'projectId'],
1121
+ description: 'Whatever role the account has on one project.',
1122
+ properties: {
1123
+ kind: { type: 'string', enum: ['project'] },
1124
+ projectId: { type: 'string', format: 'uuid' },
1125
+ },
1126
+ };
1127
+
1128
+ export const ServiceAccountUngrantBodySchema: JsonSchema = {
1129
+ description: 'The grant to remove: tenant admin, tenant member, or the role on a project.',
1130
+ oneOf: [
1131
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantAdmin' },
1132
+ { $ref: '#/components/schemas/ServiceAccountGrantTenantMember' },
1133
+ { $ref: '#/components/schemas/ServiceAccountUngrantProject' },
1134
+ ],
1135
+ discriminator: { propertyName: 'kind' },
1136
+ };
1137
+
1138
+ export const ServiceAccountSchema: JsonSchema = {
1139
+ type: 'object',
1140
+ additionalProperties: false,
1141
+ description:
1142
+ 'A named, non-human principal (`service_account:<id>`) for an app, a pipeline or a schedule. It acts through API keys minted for it.',
1143
+ required: ['serviceAccountId', 'name', 'grants', 'createdAt'],
1144
+ properties: {
1145
+ serviceAccountId: { type: 'string' },
1146
+ name: { type: 'string', description: "Unique among the tenant's active accounts." },
1147
+ description: { type: 'string' },
1148
+ grants: { type: 'array', items: { $ref: '#/components/schemas/ServiceAccountGrant' } },
1149
+ createdBy: {
1150
+ type: 'string',
1151
+ description: 'Who created it: `user:<id>` or `service_account:<id>`.',
1152
+ },
1153
+ createdAt: { type: 'string', format: 'date-time' },
1154
+ unregisteredAt: {
1155
+ type: 'string',
1156
+ format: 'date-time',
1157
+ description: 'Set once unregistered: it has no grants, and its keys no longer work.',
1158
+ },
1159
+ },
1160
+ };
1161
+
1162
+ export const ServiceAccountPageSchema: JsonSchema = {
1163
+ type: 'object',
1164
+ additionalProperties: false,
1165
+ required: ['data', 'hasMore'],
1166
+ properties: {
1167
+ data: { type: 'array', items: { $ref: '#/components/schemas/ServiceAccount' } },
1168
+ hasMore: { type: 'boolean' },
1169
+ nextCursor: { type: 'string' },
1170
+ },
1171
+ };
1172
+
1173
+ export const CreateServiceAccountBodySchema: JsonSchema = {
1174
+ type: 'object',
1175
+ additionalProperties: false,
1176
+ required: ['name'],
1177
+ properties: {
1178
+ name: {
1179
+ type: 'string',
1180
+ pattern: '^[a-z0-9][a-z0-9-]{0,62}$',
1181
+ description: 'Lowercase letters, digits and hyphens, e.g. `acme-ci`.',
1182
+ },
1183
+ description: { type: 'string', maxLength: 500 },
1184
+ grants: {
1185
+ type: 'array',
1186
+ items: { $ref: '#/components/schemas/ServiceAccountGrant' },
1187
+ description: 'Written before the account is returned, so its first key works at once.',
1188
+ },
1189
+ },
1190
+ };
1191
+
987
1192
  // ---------------- HITL (approvals) ----------------
988
1193
 
989
1194
  export const ReviewerRoleSchema: JsonSchema = {
@@ -1175,75 +1380,156 @@ export const UnregisterReviewerResultSchema: JsonSchema = {
1175
1380
  },
1176
1381
  };
1177
1382
 
1178
- export const ExportAuditBundleBodySchema: JsonSchema = {
1383
+ // ---------------- signed exports: one envelope ----------------
1384
+
1385
+ const SIGNING_KEY_ID_PROPERTY: JsonSchema = {
1386
+ type: 'string',
1387
+ minLength: 1,
1179
1388
  description:
1180
- "Body for `POST /v1/approvals/{approvalId}/audit-bundle`. `signingKeyId` selects the Ed25519 key from the deployment's `signingKey` binding. `includeMessages` optionally hydrates conversation messages tied to the approval's run.",
1389
+ "Optional: sign with this key, one of `GET /v1/export-signing-keys`. Leave it out to sign with the deployment's active key. A key the deployment doesn't sign with is `404 signing-key-not-found`.",
1390
+ };
1391
+
1392
+ /**
1393
+ * The envelope every signed export answers (an audit bundle, a run's
1394
+ * provenance, compliance evidence): the same fields, so one verifier
1395
+ * reads all three. Only the subject field differs.
1396
+ */
1397
+ function signedExportEnvelope(input: {
1398
+ readonly description: string;
1399
+ readonly kind: 'audit-bundle' | 'provenance' | 'compliance';
1400
+ readonly subject: readonly [string, JsonSchema];
1401
+ readonly versionDescription: string;
1402
+ }): JsonSchema {
1403
+ const [subjectKey, subjectSchema] = input.subject;
1404
+ return {
1405
+ description: input.description,
1406
+ type: 'object',
1407
+ additionalProperties: false,
1408
+ required: [
1409
+ subjectKey,
1410
+ 'bundle',
1411
+ 'bundleSchemaVersion',
1412
+ 'algorithm',
1413
+ 'signingKeyId',
1414
+ 'signature',
1415
+ 'publicKey',
1416
+ 'canonicalization',
1417
+ 'exportedAt',
1418
+ ],
1419
+ properties: {
1420
+ [subjectKey]: subjectSchema,
1421
+ kind: {
1422
+ type: 'string',
1423
+ const: input.kind,
1424
+ description:
1425
+ 'Which export this is: `audit-bundle`, `provenance` or `compliance`. Absent from older servers.',
1426
+ },
1427
+ bundle: {
1428
+ type: 'string',
1429
+ description:
1430
+ 'Base64 of the exact bytes that were signed: the body, as sorted-key JSON with no whitespace. Verify these bytes; nothing needs re-serializing.',
1431
+ },
1432
+ bundleSchemaVersion: { type: 'string', description: input.versionDescription },
1433
+ algorithm: {
1434
+ type: 'string',
1435
+ enum: ['ed25519', 'ecdsa-p256-sha256'],
1436
+ description:
1437
+ "The signing key's algorithm. `ecdsa-p256-sha256` signatures are IEEE P1363 `r‖s`. A verifier refuses an algorithm it doesn't know.",
1438
+ },
1439
+ signingKeyId: {
1440
+ type: 'string',
1441
+ description: 'The key that signed it: one of `GET /v1/export-signing-keys`.',
1442
+ },
1443
+ signature: {
1444
+ type: 'string',
1445
+ description:
1446
+ "Base64 of the 64-byte signature over the `bundle` bytes: Ed25519's, or ECDSA P-256's as IEEE P1363 `r‖s`.",
1447
+ },
1448
+ publicKey: {
1449
+ type: 'string',
1450
+ description:
1451
+ "The signing key's public half, PEM SPKI. On its own it only proves the bytes weren't changed; check it against `GET /v1/export-signing-keys` (or a key you pinned) to know who signed them.",
1452
+ },
1453
+ canonicalization: {
1454
+ type: 'string',
1455
+ const: 'sorted-key-json',
1456
+ description: 'Sorted-key JSON, no whitespace (`canonicalize` in `@kindgi/schema`).',
1457
+ },
1458
+ exportedAt: {
1459
+ type: 'string',
1460
+ format: 'date-time',
1461
+ description: "When it was signed: the same instant as the signed body's `exportedAt`.",
1462
+ },
1463
+ },
1464
+ };
1465
+ }
1466
+
1467
+ export const ExportSigningKeySchema: JsonSchema = {
1468
+ description: 'A public key this deployment signs exports with.',
1181
1469
  type: 'object',
1182
1470
  additionalProperties: false,
1183
- required: ['signingKeyId'],
1471
+ required: ['keyId', 'algorithm', 'publicKeyPem', 'fingerprint', 'active'],
1184
1472
  properties: {
1185
- signingKeyId: {
1473
+ keyId: {
1186
1474
  type: 'string',
1187
- minLength: 1,
1188
1475
  description:
1189
- 'The `SigningKeyId` the deployment plugs into its `signingKey` binding. Server looks up the private key via `signingKey.getPrivateKey(signingKeyId)` — 404 if unknown.',
1476
+ 'Derived from the public key (`ex_` and 16 base64url characters), so the same key keeps its id.',
1190
1477
  },
1191
- includeMessages: {
1192
- type: 'boolean',
1478
+ algorithm: {
1479
+ type: 'string',
1480
+ enum: ['ed25519', 'ecdsa-p256-sha256'],
1193
1481
  description:
1194
- "When true, hydrates conversation messages tied to the approval's run (agent turns pin `runId === conversationId`). Empty array for non-agent runs — field always present when requested.",
1195
- default: false,
1482
+ 'An Ed25519 key signs `ed25519`; an EC P-256 key (a KMS without Ed25519) signs `ecdsa-p256-sha256`.',
1483
+ },
1484
+ publicKeyPem: { type: 'string', description: 'PEM SPKI.' },
1485
+ fingerprint: {
1486
+ type: 'string',
1487
+ pattern: '^sha256:[0-9a-f]{64}$',
1488
+ description:
1489
+ '`sha256:` and the hex SHA-256 of the raw public key: to pin it, or compare by eye.',
1196
1490
  },
1491
+ active: { type: 'boolean', description: 'Whether new exports are signed with it.' },
1197
1492
  },
1198
1493
  };
1199
1494
 
1200
- export const ExportAuditBundleResultSchema: JsonSchema = {
1201
- description:
1202
- 'Signed exportable audit bundle. Same envelope shape as `ExportProvenanceResult` — clients can reuse the same `verifyEd25519` wrapper for both. `bundle` is base64 of the exact bytes that were signed (sorted-key canonical JSON, no whitespace). Bundle body: `{ bundleVersion, approvalId, tenantId, subjectKind, subjectRef, requiredRole, status, decision, decidedAt?, evidence: { guardrailResults?, messages? }, createdAt, exportedAt }`.',
1495
+ export const ExportSigningKeyListSchema: JsonSchema = {
1203
1496
  type: 'object',
1204
1497
  additionalProperties: false,
1205
- required: [
1206
- 'approvalId',
1207
- 'bundle',
1208
- 'bundleSchemaVersion',
1209
- 'algorithm',
1210
- 'signingKeyId',
1211
- 'signature',
1212
- 'publicKey',
1213
- 'canonicalization',
1214
- 'exportedAt',
1215
- ],
1498
+ required: ['data'],
1216
1499
  properties: {
1217
- approvalId: { type: 'string', format: 'uuid' },
1218
- bundle: {
1219
- type: 'string',
1220
- description: 'Base64-encoded canonical JSON of the bundle body.',
1221
- },
1222
- bundleSchemaVersion: {
1223
- type: 'integer',
1224
- description: 'Integer schema version for the bundle body shape. Currently `1`.',
1225
- },
1226
- algorithm: { type: 'string', const: 'ed25519' },
1227
- signingKeyId: { type: 'string' },
1228
- signature: {
1229
- type: 'string',
1230
- description: 'Base64-encoded Ed25519 signature over `bundle` (after base64-decode).',
1231
- },
1232
- publicKey: {
1233
- type: 'string',
1234
- description:
1235
- 'PEM-encoded Ed25519 public key (DER SPKI envelope). Pass into `parsePublicKeyPem` for verification.',
1500
+ data: {
1501
+ type: 'array',
1502
+ items: { $ref: '#/components/schemas/ExportSigningKey' },
1503
+ description: "Active first. Empty when the deployment doesn't sign exports.",
1236
1504
  },
1237
- canonicalization: {
1238
- type: 'string',
1239
- const: 'sorted-key-json',
1505
+ },
1506
+ };
1507
+
1508
+ export const ExportAuditBundleBodySchema: JsonSchema = {
1509
+ description:
1510
+ "Body for `POST /v1/approvals/{approvalId}/audit-bundle`, optional: no body signs with the active key. `includeMessages` adds the conversation messages of the approval's run.",
1511
+ type: 'object',
1512
+ additionalProperties: false,
1513
+ properties: {
1514
+ signingKeyId: SIGNING_KEY_ID_PROPERTY,
1515
+ includeMessages: {
1516
+ type: 'boolean',
1240
1517
  description:
1241
- 'Canonicalization algorithm — sorted-key JSON, no whitespace. Same algorithm as `canonicalize`.',
1518
+ "When true, hydrates conversation messages tied to the approval's run (agent turns pin `runId === conversationId`). Empty array for non-agent runs — field always present when requested.",
1519
+ default: false,
1242
1520
  },
1243
- exportedAt: { type: 'string', format: 'date-time' },
1244
1521
  },
1245
1522
  };
1246
1523
 
1524
+ export const ExportAuditBundleResultSchema: JsonSchema = signedExportEnvelope({
1525
+ description:
1526
+ "A decided approval's signed audit bundle. Body: `{ bundleSchemaVersion, approvalId, tenantId, subjectKind, subjectRef, requiredRole, status, createdAt, decidedAt?, decision, evidence: { guardrailResults?, messages? }, exportedAt }`.",
1527
+ kind: 'audit-bundle',
1528
+ subject: ['approvalId', { type: 'string', format: 'uuid' }],
1529
+ versionDescription:
1530
+ "The body's version, semver. `2.0.0`: a string like the other exports' (it was the integer `1`), named `bundleSchemaVersion` in the body too, with `exportedAt` signed once.",
1531
+ });
1532
+
1247
1533
  export const CompleteApprovalResultSchema: JsonSchema = {
1248
1534
  type: 'object',
1249
1535
  additionalProperties: false,
@@ -1306,12 +1592,82 @@ export const PromptParameterSchema: JsonSchema = {
1306
1592
  export const RetrievalIntentSchema: JsonSchema = {
1307
1593
  type: 'object',
1308
1594
  additionalProperties: false,
1309
- required: ['types', 'scope'],
1595
+ required: ['scope'],
1310
1596
  properties: {
1311
- types: { type: 'array', items: { type: 'string' }, minItems: 1 },
1312
- scope: { type: 'string', enum: ['same-conversation', 'same-project', 'tenant'] },
1597
+ source: {
1598
+ type: 'string',
1599
+ enum: ['facts', 'conversations'],
1600
+ description:
1601
+ "What it reads: facts (the default), or messages of this agent's earlier conversations, quoted in the turn's `<memory>` block as earlier conversation, never as turns.",
1602
+ },
1603
+ types: {
1604
+ type: 'array',
1605
+ items: { type: 'string' },
1606
+ minItems: 1,
1607
+ description: 'The fact types it retrieves: required for facts; not used for conversations.',
1608
+ },
1609
+ roles: {
1610
+ type: 'array',
1611
+ items: { type: 'string', enum: ['user', 'agent'] },
1612
+ minItems: 1,
1613
+ uniqueItems: true,
1614
+ description:
1615
+ "For conversations: whose messages it recalls. Default `['user']`, the people's own words. Adding `agent` recalls the agent's earlier answers too, which can carry its mistakes: they are quoted as unverified earlier answers, and publishing warns `recall-agent-answers`.",
1616
+ },
1617
+ scope: {
1618
+ type: 'string',
1619
+ enum: ['same-conversation', 'same-user', 'same-segment', 'same-project', 'tenant'],
1620
+ description:
1621
+ "What the intent selects within what the run may see. Facts: this conversation's; the run's end user's only (`same-user`: none when the run names no `participantId`); the run's project's (none without a project); or every fact of the type it may see (`tenant`). Conversations: this end user's other conversations with the agent (`same-user`: none when the run names no `participantId`); this conversation's messages older than the history window (`same-conversation`); conversations in the run's segment path (`same-segment`) or its project (`same-project`), whoever had them: those two quote other people's conversations, so publishing warns and their messages are marked as another person's. `same-segment` is for conversations only, `tenant` for facts only.",
1622
+ },
1313
1623
  limit: { type: 'integer', minimum: 1 },
1314
- mode: { type: 'string', enum: ['keyword', 'semantic', 'both'] },
1624
+ mode: {
1625
+ type: 'string',
1626
+ enum: ['keyword', 'semantic', 'both'],
1627
+ description:
1628
+ "With the user's message as the query: full-text, by meaning (fails the turn with `semantic-unavailable` on a runtime without embeddings), or both fused by rank (without embeddings, the keyword half). Absent: the newest facts.",
1629
+ },
1630
+ },
1631
+ };
1632
+
1633
+ export const AgentMemoryPolicySchema: JsonSchema = {
1634
+ type: 'object',
1635
+ additionalProperties: false,
1636
+ description: 'How the agent uses what it retrieves.',
1637
+ properties: {
1638
+ instructionTypes: {
1639
+ type: 'array',
1640
+ items: { type: 'string', minLength: 1 },
1641
+ description:
1642
+ "Fact types that are instructions for this agent: a retrieved, verified fact of one of these types goes into the system message under 'Policies (verified)'. Default: none.",
1643
+ },
1644
+ remember: {
1645
+ type: 'object',
1646
+ additionalProperties: false,
1647
+ required: ['types', 'scope'],
1648
+ description:
1649
+ 'Lets the agent remember: its turns offer the built-in tool `kindgi_remember` (built-in tools are `kindgi_<verb>`; an agent cannot list one in `tools`, and a published tool cannot use the prefix). The model picks the type, the text (up to 2,000 characters), an optional slot `key` and when it stops being true; the scope comes from here and the run. Every remembered fact is `unverified`, attributed to the agent version and the call that wrote it, and expires after `keepDays` unless a person verifies it. A person approves it before any read sees it when the scope is wider than one person (`same-project`, `tenant`) or the text reads like an instruction.',
1650
+ properties: {
1651
+ types: {
1652
+ type: 'array',
1653
+ minItems: 1,
1654
+ items: { type: 'string', minLength: 1 },
1655
+ description: 'The fact types it may write.',
1656
+ },
1657
+ scope: {
1658
+ type: 'string',
1659
+ enum: ['same-user', 'same-conversation', 'same-project', 'tenant'],
1660
+ description:
1661
+ "Where its facts go: the conversation's end user (else the user the run acts for), the conversation, the run's project, or the tenant. Each but `tenant` includes the run's project.",
1662
+ },
1663
+ keepDays: {
1664
+ type: 'integer',
1665
+ minimum: 1,
1666
+ maximum: 3650,
1667
+ description: 'Days an unverified fact is kept. Default 30.',
1668
+ },
1669
+ },
1670
+ },
1315
1671
  },
1316
1672
  };
1317
1673
 
@@ -1446,6 +1802,7 @@ export const AgentSchema: JsonSchema = {
1446
1802
  capabilities: { type: 'array', items: { $ref: '#/components/schemas/Capability' } },
1447
1803
  tools: { type: 'array', items: { $ref: '#/components/schemas/ToolRef' } },
1448
1804
  retrieval: { type: 'array', items: { $ref: '#/components/schemas/RetrievalIntent' } },
1805
+ memory: { $ref: '#/components/schemas/AgentMemoryPolicy' },
1449
1806
  guardrails: { type: 'array', items: { type: 'string' } },
1450
1807
  preferredProvider: {
1451
1808
  type: 'string',
@@ -1497,6 +1854,11 @@ export const VersionDerivationSchema: JsonSchema = {
1497
1854
  },
1498
1855
  label: { type: 'string', description: 'For `edited`: a short label for the version.' },
1499
1856
  by: { type: 'string', description: 'For `edited`: who derived it (`user:<id>`).' },
1857
+ proposalId: {
1858
+ type: 'string',
1859
+ description:
1860
+ 'For `edited`: the improvement proposal it was derived for. Such a version serves no scope until a promotion makes it live.',
1861
+ },
1500
1862
  },
1501
1863
  };
1502
1864
 
@@ -1611,6 +1973,7 @@ export const PublishAgentBodySchema: JsonSchema = {
1611
1973
  capabilities: { type: 'array', items: { $ref: '#/components/schemas/Capability' } },
1612
1974
  tools: { type: 'array', items: { $ref: '#/components/schemas/ToolRef' } },
1613
1975
  retrieval: { type: 'array', items: { $ref: '#/components/schemas/RetrievalIntent' } },
1976
+ memory: { $ref: '#/components/schemas/AgentMemoryPolicy' },
1614
1977
  guardrails: { type: 'array', items: { type: 'string' } },
1615
1978
  preferredProvider: {
1616
1979
  type: 'string',
@@ -1639,6 +2002,17 @@ export const PublishAgentResultSchema: JsonSchema = {
1639
2002
  properties: {
1640
2003
  agentId: { type: 'string' },
1641
2004
  version: { type: 'string' },
2005
+ warnings: {
2006
+ type: 'array',
2007
+ description:
2008
+ "What the agent should know about this deployment before its first turn, e.g. `semantic-unavailable` (a retrieval intent searches by meaning and the deployment has no embeddings), `remember-unavailable` (the agent remembers and the deployment cannot store agent memories), `recall-other-people` (an intent recalls conversations in the run's segment or project, whoever had them) or `recall-unavailable` (the deployment cannot recall earlier conversations).",
2009
+ items: {
2010
+ type: 'object',
2011
+ additionalProperties: false,
2012
+ required: ['code', 'message'],
2013
+ properties: { code: { type: 'string' }, message: { type: 'string' } },
2014
+ },
2015
+ },
1642
2016
  },
1643
2017
  };
1644
2018
 
@@ -2382,10 +2756,16 @@ export const ConversationSchema: JsonSchema = {
2382
2756
  status: ConversationStatusSchema,
2383
2757
  openedAt: { type: 'string', format: 'date-time' },
2384
2758
  closedAt: { type: 'string', format: 'date-time' },
2385
- turnCount: { type: 'integer', minimum: 0 },
2386
- lastMessageAt: { type: 'string', format: 'date-time' },
2387
- metadata: { type: 'object', additionalProperties: true },
2388
- },
2759
+ unregisteredAt: {
2760
+ type: 'string',
2761
+ format: 'date-time',
2762
+ description:
2763
+ 'When it was unregistered (`POST /v1/conversations/{conversationId}/unregister`). Only the unregister call returns it: reads no longer do.',
2764
+ },
2765
+ turnCount: { type: 'integer', minimum: 0 },
2766
+ lastMessageAt: { type: 'string', format: 'date-time' },
2767
+ metadata: { type: 'object', additionalProperties: true },
2768
+ },
2389
2769
  };
2390
2770
 
2391
2771
  export const ConversationMessageSchema: JsonSchema = {
@@ -2795,7 +3175,7 @@ export const JudgedRunContextSchema: JsonSchema = {
2795
3175
  type: 'object',
2796
3176
  additionalProperties: false,
2797
3177
  description:
2798
- 'What a judged run needs besides its input to be replayed, captured when it was first judged. For an agent turn: the conversation before it, what its retrievals returned, and the decision at its session approval gate. For a flow run: its tool calls with their results.',
3178
+ 'What a judged run needs besides its input to be replayed, captured when it was first judged. For an agent turn: the conversation before it, what its retrievals returned, and the decision at its session approval gate. For a flow run: its tool calls with their results. For both: the env values its tools were sent.',
2799
3179
  properties: {
2800
3180
  history: {
2801
3181
  type: 'array',
@@ -2808,6 +3188,10 @@ export const JudgedRunContextSchema: JsonSchema = {
2808
3188
  description: 'Whether older messages were left out of `history`.',
2809
3189
  },
2810
3190
  retrieved: { description: "What the turn's retrievals returned." },
3191
+ recalled: {
3192
+ description:
3193
+ 'Messages of earlier conversations the turn recalled (intents over conversations), as quoted to the model.',
3194
+ },
2811
3195
  sessionApproval: {
2812
3196
  type: 'object',
2813
3197
  additionalProperties: false,
@@ -2862,12 +3246,21 @@ export const JudgedRunContextSchema: JsonSchema = {
2862
3246
  agentId: { type: 'string' },
2863
3247
  agentVersion: { type: 'string' },
2864
3248
  retrieved: { description: "What the step's turn retrieved." },
3249
+ recalled: {
3250
+ description: "Messages of earlier conversations the step's turn recalled.",
3251
+ },
2865
3252
  },
2866
3253
  },
2867
3254
  },
2868
3255
  truncated: { type: 'boolean', description: 'More calls were made than were kept.' },
2869
3256
  },
2870
3257
  },
3258
+ toolEnv: {
3259
+ type: 'object',
3260
+ additionalProperties: { type: 'object', additionalProperties: { type: 'string' } },
3261
+ description:
3262
+ "The env values each tool's calls were sent (`needsSpec.env`), by tool id: its first call's, as the run recorded them. A replay sends them to a read-only tool it runs live, so the tool reads the config the run saw, not today's. Absent for a run from before env was recorded.",
3263
+ },
2871
3264
  },
2872
3265
  };
2873
3266
 
@@ -2885,6 +3278,12 @@ export const JudgedRunCopySchema: JsonSchema = {
2885
3278
  $ref: '#/components/schemas/JudgedRunContext',
2886
3279
  },
2887
3280
  output: {},
3281
+ segments: {
3282
+ type: 'array',
3283
+ items: { $ref: '#/components/schemas/ScopeSegment' },
3284
+ description:
3285
+ 'The segment path the run was started with (empty: none). Absent for runs judged before it was recorded.',
3286
+ },
2888
3287
  capturedAt: { type: 'string', format: 'date-time' },
2889
3288
  },
2890
3289
  };
@@ -2983,6 +3382,13 @@ export const JudgedItemSummarySchema: JsonSchema = {
2983
3382
  properties: {
2984
3383
  verdict: { type: 'string', enum: ['yes', 'no'] },
2985
3384
  reason: { type: 'string' },
3385
+ judgeClassId: { type: 'string', description: "The judgment's class, when it had one." },
3386
+ restricted: {
3387
+ type: 'boolean',
3388
+ enum: [true],
3389
+ description:
3390
+ 'Set when the judgment was recorded while its class was restricted (`Judgment.restricted`).',
3391
+ },
2986
3392
  },
2987
3393
  },
2988
3394
  },
@@ -3002,6 +3408,12 @@ export const JudgedEvalCaseSchema: JsonSchema = {
3002
3408
  context: { $ref: '#/components/schemas/JudgedRunContext' },
3003
3409
  output: {},
3004
3410
  items: { type: 'array', items: { $ref: '#/components/schemas/JudgedItemSummary' } },
3411
+ erased: {
3412
+ type: 'boolean',
3413
+ const: true,
3414
+ description:
3415
+ "An erasure cleared this case (a person's words were erased): `input` and `output` are null, `items` empty, and eval runs leave it out (counted as `erased`).",
3416
+ },
3005
3417
  },
3006
3418
  };
3007
3419
 
@@ -3047,6 +3459,12 @@ export const BuildJudgedSuiteBodySchema: JsonSchema = {
3047
3459
  minimum: 1,
3048
3460
  description: 'Leave out runs with fewer counted judgments. Default 1.',
3049
3461
  },
3462
+ segments: {
3463
+ type: 'array',
3464
+ items: { $ref: '#/components/schemas/ScopeSegment' },
3465
+ description:
3466
+ "Only runs started in this segment path or below it, coarse to fine (e.g. `company=acme`). A run judged before its segments were recorded with its judgments is in no segment, so it's left out.",
3467
+ },
3050
3468
  description: { type: 'string' },
3051
3469
  },
3052
3470
  };
@@ -3074,7 +3492,7 @@ export const FactScopeSchema: JsonSchema = {
3074
3492
  additionalProperties: true,
3075
3493
  required: ['tenantId'],
3076
3494
  description:
3077
- 'Fact scope object. `tenantId` is required; every optional key narrows the fact (`userId`, `orgId`, `projectId`, `threadId`, `sessionId`). Additional keys accepted for forward compatibility.',
3495
+ 'Fact scope object. `tenantId` is required; every optional key narrows the fact (`userId`, `orgId`, `projectId`, `threadId`, `sessionId`, `participantId`). A fact is readable by whoever has every container it names. Additional keys accepted for forward compatibility.',
3078
3496
  properties: {
3079
3497
  tenantId: { type: 'string' },
3080
3498
  userId: { type: 'string' },
@@ -3082,6 +3500,47 @@ export const FactScopeSchema: JsonSchema = {
3082
3500
  projectId: { type: 'string' },
3083
3501
  threadId: { type: 'string' },
3084
3502
  sessionId: { type: 'string' },
3503
+ participantId: {
3504
+ type: 'string',
3505
+ minLength: 1,
3506
+ description:
3507
+ "An app's end user, by the app's own id: a fact private to that participant's runs. Needs `projectId`.",
3508
+ },
3509
+ },
3510
+ };
3511
+
3512
+ export const FactSubjectSchema: JsonSchema = {
3513
+ description: 'Whom a fact is about: what access and erasure requests by person find.',
3514
+ type: 'object',
3515
+ additionalProperties: false,
3516
+ required: ['kind', 'id'],
3517
+ properties: {
3518
+ kind: { type: 'string', enum: ['participant', 'user', 'external'] },
3519
+ id: { type: 'string', minLength: 1 },
3520
+ },
3521
+ };
3522
+
3523
+ export const FactAttributionSchema: JsonSchema = {
3524
+ description: 'Who asserted a fact, set by the server from the writer.',
3525
+ type: 'object',
3526
+ additionalProperties: false,
3527
+ required: ['kind', 'id'],
3528
+ properties: {
3529
+ kind: { type: 'string', enum: ['user', 'service', 'agent'] },
3530
+ id: { type: 'string' },
3531
+ agentVersion: { type: 'string' },
3532
+ },
3533
+ };
3534
+
3535
+ export const FactGeneratedBySchema: JsonSchema = {
3536
+ description: 'The run step that wrote a fact, for one an agent wrote.',
3537
+ type: 'object',
3538
+ additionalProperties: false,
3539
+ required: ['runId'],
3540
+ properties: {
3541
+ runId: { type: 'string' },
3542
+ stepId: { type: 'string' },
3543
+ toolCallId: { type: 'string' },
3085
3544
  },
3086
3545
  };
3087
3546
 
@@ -3137,7 +3596,15 @@ export const FactSchema: JsonSchema = {
3137
3596
  additionalProperties: false,
3138
3597
  required: ['id', 'type', 'scope', 'version', 'createdAt'],
3139
3598
  properties: {
3140
- id: { type: 'string', description: 'FactId.' },
3599
+ id: {
3600
+ type: 'string',
3601
+ description:
3602
+ 'The fact id, kept across revisions (for a fact never superseded, also its one revision id).',
3603
+ },
3604
+ revisionId: {
3605
+ type: 'string',
3606
+ description: "This revision's own id; absent where it equals `id`.",
3607
+ },
3141
3608
  type: {
3142
3609
  type: 'string',
3143
3610
  description: 'Fact type identifier (pack-defined; a few are framework-standard).',
@@ -3146,7 +3613,7 @@ export const FactSchema: JsonSchema = {
3146
3613
  version: {
3147
3614
  type: 'integer',
3148
3615
  minimum: 1,
3149
- description: 'Monotonic version within (scope, id). Supersession increments.',
3616
+ description: 'The revision number within the fact: 1, then one more per supersede or verify.',
3150
3617
  },
3151
3618
  createdAt: { type: 'string', format: 'date-time' },
3152
3619
  updatedAt: { type: 'string', format: 'date-time' },
@@ -3163,7 +3630,63 @@ export const FactSchema: JsonSchema = {
3163
3630
  causedByLogId: { type: 'array', items: { type: 'string' } },
3164
3631
  supersedes: {
3165
3632
  type: 'string',
3166
- description: 'FactId of the predecessor when this row supersedes another.',
3633
+ description: 'The revision this one replaced.',
3634
+ },
3635
+ trust: {
3636
+ type: 'string',
3637
+ enum: ['verified', 'asserted', 'unverified'],
3638
+ description:
3639
+ '`verified`: a person with the right checked it. `asserted`: an app or a person wrote it. `unverified`: an agent remembered it during a conversation. Absent on facts from before trust was recorded: `asserted`.',
3640
+ },
3641
+ verifiedBy: { type: 'string' },
3642
+ verifiedAt: { type: 'string', format: 'date-time' },
3643
+ attributedTo: { $ref: '#/components/schemas/FactAttribution' },
3644
+ generatedBy: { $ref: '#/components/schemas/FactGeneratedBy' },
3645
+ subjects: { type: 'array', items: { $ref: '#/components/schemas/FactSubject' } },
3646
+ validFrom: {
3647
+ type: 'string',
3648
+ format: 'date-time',
3649
+ description: 'When the fact starts being true in the world; absent: always.',
3650
+ },
3651
+ validUntil: {
3652
+ type: 'string',
3653
+ format: 'date-time',
3654
+ description: 'When the fact stops being true in the world; absent: still true.',
3655
+ },
3656
+ observedAt: { type: 'string', format: 'date-time', description: 'When it was said or seen.' },
3657
+ invalidatedAt: {
3658
+ type: 'string',
3659
+ format: 'date-time',
3660
+ description: 'When this revision stopped being current; absent: it is current.',
3661
+ },
3662
+ invalidatedBy: { type: 'string', description: '`user:<id>` or `service:<id>`.' },
3663
+ invalidationReason: {
3664
+ type: 'string',
3665
+ enum: ['superseded', 'deleted', 'erased', 'expired'],
3666
+ },
3667
+ review: {
3668
+ type: 'string',
3669
+ enum: ['pending'],
3670
+ description: '`pending` while a person must approve it: a pending fact is never retrieved.',
3671
+ },
3672
+ expiresAt: {
3673
+ type: 'string',
3674
+ format: 'date-time',
3675
+ description:
3676
+ "When this revision stops being readable: from its retention (`keepUntil`, or `keepDays` from the fact's first write), or an agent-remembered fact's unverified window. No read returns it after; absent: it doesn't expire.",
3677
+ },
3678
+ },
3679
+ };
3680
+
3681
+ export const FactRevisionListSchema: JsonSchema = {
3682
+ type: 'object',
3683
+ additionalProperties: false,
3684
+ required: ['data'],
3685
+ properties: {
3686
+ data: {
3687
+ type: 'array',
3688
+ items: { $ref: '#/components/schemas/Fact' },
3689
+ description: 'Every revision, newest first.',
3167
3690
  },
3168
3691
  },
3169
3692
  };
@@ -3184,7 +3707,7 @@ export const FactCollectionPageSchema: JsonSchema = {
3184
3707
 
3185
3708
  export const WriteFactBodySchema: JsonSchema = {
3186
3709
  description:
3187
- "Write a fact. `type` selects the retrieval-policy (which indexes populate); `scope.tenantId` MUST match the caller's tenant. Optional `retention` overrides tenant defaults; optional `contentHash` is a caller-supplied idempotence hint (runtime computes its own hash regardless).",
3710
+ "Write a fact. `type` selects the retrieval-policy (which indexes populate); `scope.tenantId` MUST match the caller's tenant. Optional `retention` overrides tenant defaults; optional `contentHash` is a caller-supplied idempotence hint (runtime computes its own hash regardless). `subjects` names whom it is about; `validFrom`/`validUntil` when it is true in the world; `observedAt` when it was said or seen.",
3188
3711
  type: 'object',
3189
3712
  additionalProperties: false,
3190
3713
  required: ['type', 'scope', 'content'],
@@ -3194,22 +3717,49 @@ export const WriteFactBodySchema: JsonSchema = {
3194
3717
  content: { description: 'Free-form structured payload.' },
3195
3718
  retention: { $ref: '#/components/schemas/Retention' },
3196
3719
  contentHash: { type: 'string' },
3720
+ subjects: {
3721
+ type: 'array',
3722
+ maxItems: 20,
3723
+ items: { $ref: '#/components/schemas/FactSubject' },
3724
+ },
3725
+ validFrom: { type: 'string', format: 'date-time' },
3726
+ validUntil: { type: 'string', format: 'date-time' },
3727
+ observedAt: { type: 'string', format: 'date-time' },
3728
+ },
3729
+ };
3730
+
3731
+ export const SupersedeFactBodySchema: JsonSchema = {
3732
+ description:
3733
+ "The fact's next revision: new `content`, and optionally new `retention`, `subjects` and times (absent ones keep their current values). Its scope and type stay. `expectVersion`: only if the current revision is still this one.",
3734
+ type: 'object',
3735
+ additionalProperties: false,
3736
+ required: ['content'],
3737
+ properties: {
3738
+ content: { description: 'Free-form structured payload.' },
3739
+ expectVersion: { type: 'integer', minimum: 1 },
3740
+ retention: { $ref: '#/components/schemas/Retention' },
3741
+ subjects: {
3742
+ type: 'array',
3743
+ maxItems: 20,
3744
+ items: { $ref: '#/components/schemas/FactSubject' },
3745
+ },
3746
+ validFrom: { type: 'string', format: 'date-time' },
3747
+ validUntil: { type: 'string', format: 'date-time' },
3748
+ observedAt: { type: 'string', format: 'date-time' },
3197
3749
  },
3198
3750
  };
3199
3751
 
3200
- export const SupersedeFactResultSchema: JsonSchema = {
3752
+ export const VerifyFactBodySchema: JsonSchema = {
3201
3753
  type: 'object',
3202
3754
  additionalProperties: false,
3203
- required: ['factId', 'superseded'],
3204
3755
  properties: {
3205
- factId: { type: 'string' },
3206
- superseded: { type: 'boolean', const: true },
3756
+ expectVersion: { type: 'integer', minimum: 1 },
3207
3757
  },
3208
3758
  };
3209
3759
 
3210
3760
  export const RetrieveIntentSchema: JsonSchema = {
3211
3761
  description:
3212
- 'Retrieval intent — mirrors `RetrievalIntent` from `@kindgi/agents`, widened for direct-HTTP use. `mode: "list"` returns a plain scoped list (no query). `mode: "keyword"` runs full-text search. `mode: "semantic"` runs vector similarity search — requires an embedding provider bound on the deployment; if unavailable, the route returns `400 bad-input`. `mode: "both"` unions keyword + semantic results, dedup by fact id.',
3762
+ 'Retrieval intent — mirrors `RetrievalIntent` from `@kindgi/agents`, widened for direct-HTTP use. `mode: "list"` returns a plain scoped list (no query), newest first. `mode: "keyword"` runs full-text search. `mode: "semantic"` searches by meaning — it needs embeddings on the deployment; without them the route answers `422 semantic-unavailable`. `mode: "both"` runs both and fuses them by rank (reciprocal rank fusion), as `semantic` needing embeddings.',
3213
3763
  type: 'object',
3214
3764
  additionalProperties: false,
3215
3765
  required: ['mode'],
@@ -3237,7 +3787,7 @@ export const RetrievalHitSchema: JsonSchema = {
3237
3787
  score: {
3238
3788
  type: 'number',
3239
3789
  description:
3240
- 'Relevance score. Keyword mode returns an implementation-defined rank (higher = better). Semantic mode returns cosine similarity in [-1, 1] (higher = better). Absent for `list` mode.',
3790
+ 'Relevance score. Keyword mode returns an implementation-defined rank (higher = better). Semantic mode returns cosine similarity in [-1, 1] (higher = better). Both: the fused rank score, `Σ 1/(60 + rank)` (higher = better). Absent for `list` mode.',
3241
3791
  },
3242
3792
  },
3243
3793
  };
@@ -3251,370 +3801,878 @@ export const RetrieveMemoryResultSchema: JsonSchema = {
3251
3801
  },
3252
3802
  };
3253
3803
 
3254
- export const RevokeTokenResultSchema: JsonSchema = {
3804
+ // ---------------- memory erasures ----------------
3805
+
3806
+ const ErasureSelectorKindSchema: JsonSchema = {
3807
+ type: 'string',
3808
+ enum: ['fact', 'participant', 'external', 'conversation'],
3809
+ };
3810
+
3811
+ const ErasureStatusSchema: JsonSchema = {
3812
+ type: 'string',
3813
+ enum: ['pending', 'running', 'waiting-on-run', 'completed', 'failed'],
3814
+ description:
3815
+ "`waiting-on-run`: a turn of the person's sits in a flow that serves other people; the erasure waits for it (`waitingOn`) until its deadline, then cancels it.",
3816
+ };
3817
+
3818
+ /** Erase one fact. */
3819
+ export const MemoryErasureFactSelectorSchema: JsonSchema = {
3255
3820
  type: 'object',
3256
3821
  additionalProperties: false,
3257
- required: ['tokenId', 'revoked'],
3822
+ required: ['factId'],
3823
+ description: 'One fact.',
3824
+ properties: { factId: { type: 'string', minLength: 1, maxLength: 256 } },
3825
+ };
3826
+
3827
+ /** Erase a person's words. */
3828
+ export const MemoryErasureSubjectSelectorSchema: JsonSchema = {
3829
+ type: 'object',
3830
+ additionalProperties: false,
3831
+ required: ['subject'],
3832
+ description:
3833
+ "A person: an app's end user (`participant`), or an `external` subject facts name. Erasing a Kindgi user isn't offered.",
3258
3834
  properties: {
3259
- tokenId: { type: 'string', format: 'uuid' },
3260
- revoked: { type: 'boolean', const: true },
3835
+ subject: {
3836
+ type: 'object',
3837
+ additionalProperties: false,
3838
+ required: ['kind', 'id'],
3839
+ properties: {
3840
+ kind: { type: 'string', enum: ['participant', 'external'] },
3841
+ id: { type: 'string', minLength: 1, maxLength: 256 },
3842
+ },
3843
+ },
3261
3844
  },
3262
3845
  };
3263
3846
 
3264
- // ---------------- signing keys (the deployment trust list) ----------------
3265
-
3266
- export const TrustedSigningKeySchema: JsonSchema = {
3847
+ /** Erase one conversation. */
3848
+ export const MemoryErasureConversationSelectorSchema: JsonSchema = {
3267
3849
  type: 'object',
3268
3850
  additionalProperties: false,
3269
- required: ['keyId', 'tenantId', 'algorithm', 'publicKey', 'createdAt'],
3851
+ required: ['conversationId'],
3852
+ description: 'One conversation.',
3853
+ properties: { conversationId: { type: 'string', minLength: 1, maxLength: 256 } },
3854
+ };
3855
+
3856
+ const MEMORY_ERASURE_SELECTORS = [
3857
+ { $ref: '#/components/schemas/MemoryErasureFactSelector' },
3858
+ { $ref: '#/components/schemas/MemoryErasureSubjectSelector' },
3859
+ { $ref: '#/components/schemas/MemoryErasureConversationSelector' },
3860
+ ];
3861
+
3862
+ /** Whose words to erase: exactly one of a fact, a person or a conversation. */
3863
+ export const MemoryErasureSelectorSchema: JsonSchema = {
3270
3864
  description:
3271
- 'A public key the tenant trusts to sign deployments (`POST /v1/deployments`). A revoked key stays readable, with `revokedAt`, so the deployments it signed can be audited; it verifies no new ones.',
3865
+ "Whose words to erase: one fact (`factId`), a person (`subject`: an app's end user `participant`, or an `external` subject facts name), or one conversation (`conversationId`).",
3866
+ oneOf: MEMORY_ERASURE_SELECTORS,
3867
+ };
3868
+
3869
+ // Its own schema, used only as the request body: `MemoryErasure` names
3870
+ // `MemoryErasureSelector` too, and a union other schemas name gets inlined
3871
+ // away by the Python generator (as `RegisterIdentityProviderBody`).
3872
+ export const CreateMemoryErasureBodySchema: JsonSchema = {
3873
+ description:
3874
+ "Whose words to erase: one fact (`factId`), a person (`subject`: an app's end user `participant`, or an `external` subject facts name), or one conversation (`conversationId`).",
3875
+ oneOf: MEMORY_ERASURE_SELECTORS,
3876
+ };
3877
+
3878
+ export const MemoryErasureSchema: JsonSchema = {
3879
+ type: 'object',
3880
+ additionalProperties: false,
3881
+ required: [
3882
+ 'id',
3883
+ 'selectorKind',
3884
+ 'status',
3885
+ 'phase',
3886
+ 'requestedBy',
3887
+ 'matchable',
3888
+ 'counts',
3889
+ 'attempts',
3890
+ 'createdAt',
3891
+ ],
3272
3892
  properties: {
3273
- keyId: { type: 'string', description: 'The signer key id a deployment envelope names.' },
3274
- tenantId: { type: 'string', format: 'uuid' },
3275
- algorithm: { type: 'string', enum: ['ed25519'] },
3276
- publicKey: {
3893
+ id: { type: 'string', format: 'uuid' },
3894
+ selectorKind: ErasureSelectorKindSchema,
3895
+ selector: {
3896
+ $ref: '#/components/schemas/MemoryErasureSelector',
3897
+ description: 'Only while it runs: a completed or failed erasure keeps no identifier.',
3898
+ },
3899
+ status: ErasureStatusSchema,
3900
+ phase: {
3277
3901
  type: 'string',
3278
- description: 'Base64 of the raw public-key bytes (32 for Ed25519).',
3902
+ enum: ['seed', 'expand', 'settle', 'erase', 'done'],
3903
+ description:
3904
+ "Where a running erasure is: `seed`, `expand`, `settle` (the person's unfinished runs end, or it waits for them, before anything is cleared), `erase`, then `done`.",
3905
+ },
3906
+ requestedBy: { type: 'string', description: '`user:<id>` or `service:<id>`.' },
3907
+ matchable: {
3908
+ type: 'boolean',
3909
+ description:
3910
+ 'A replay after a backup restore can find this person again: a keyed hash was kept.',
3911
+ },
3912
+ counts: {
3913
+ type: 'object',
3914
+ additionalProperties: { type: 'integer', minimum: 0 },
3915
+ description: 'What each store cleared or deleted, by store.',
3916
+ },
3917
+ attempts: { type: 'integer', minimum: 0, description: 'Failed attempts so far.' },
3918
+ lastError: {
3919
+ type: 'string',
3920
+ description: "The last failure's code, or `not-yet:<reason>` while it waits. Never content.",
3921
+ },
3922
+ waitingOn: {
3923
+ type: 'object',
3924
+ additionalProperties: false,
3925
+ required: ['runId'],
3926
+ properties: {
3927
+ runId: { type: 'string', format: 'uuid' },
3928
+ until: { type: 'string', format: 'date-time' },
3929
+ },
3930
+ description:
3931
+ 'The run it waits (or waited) for, and until when; kept as the record of the wait.',
3932
+ },
3933
+ forced: { type: 'boolean', const: true, description: 'A tenant admin said not to wait.' },
3934
+ settleRoundsCapped: {
3935
+ type: 'boolean',
3936
+ const: true,
3937
+ description:
3938
+ "Runs of the person's kept appearing, round after round: the erasure went on to erase after its last round rather than wait any longer. Absent: it didn't.",
3279
3939
  },
3280
- label: { type: 'string' },
3281
3940
  createdAt: { type: 'string', format: 'date-time' },
3282
- revokedAt: { type: 'string', format: 'date-time' },
3283
- revokedReason: { type: 'string' },
3941
+ startedAt: { type: 'string', format: 'date-time' },
3942
+ completedAt: { type: 'string', format: 'date-time' },
3943
+ replayedAt: { type: 'string', format: 'date-time' },
3284
3944
  },
3285
3945
  };
3286
3946
 
3287
- export const TrustSigningKeyBodySchema: JsonSchema = {
3947
+ export const ResumeMemoryErasureBodySchema: JsonSchema = {
3288
3948
  type: 'object',
3289
3949
  additionalProperties: false,
3290
- required: ['keyId', 'publicKey'],
3291
3950
  properties: {
3292
- keyId: {
3293
- type: 'string',
3294
- pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$',
3951
+ force: {
3952
+ type: 'boolean',
3295
3953
  description:
3296
- 'The id deployment envelopes name as `signerKeyId`. Bound to `publicKey` for good: rotate by trusting a new id.',
3297
- },
3298
- algorithm: { type: 'string', enum: ['ed25519'], default: 'ed25519' },
3299
- publicKey: {
3300
- type: 'string',
3301
- description: 'Base64 of the 32 raw bytes of the Ed25519 public key.',
3954
+ "Stop waiting for a run in a flow that serves other people: it's cancelled, and the erasure goes on.",
3302
3955
  },
3303
- label: { type: 'string', maxLength: 200 },
3304
3956
  },
3305
3957
  };
3306
3958
 
3307
- export const TrustedSigningKeyPageSchema: JsonSchema = {
3959
+ export const MemoryErasureCreatedSchema: JsonSchema = {
3960
+ allOf: [
3961
+ { $ref: '#/components/schemas/MemoryErasure' },
3962
+ {
3963
+ type: 'object',
3964
+ properties: {
3965
+ warnings: {
3966
+ type: 'array',
3967
+ items: {
3968
+ type: 'object',
3969
+ additionalProperties: false,
3970
+ required: ['code', 'message'],
3971
+ properties: {
3972
+ code: {
3973
+ type: 'string',
3974
+ enum: ['erasure-unmatchable'],
3975
+ description:
3976
+ "`erasure-unmatchable`: this deployment has no erasure ledger key (`KINDGI_ERASURE_LEDGER_KEY`), so a replay after a restore can't find this person.",
3977
+ },
3978
+ message: { type: 'string' },
3979
+ },
3980
+ },
3981
+ },
3982
+ },
3983
+ },
3984
+ ],
3985
+ };
3986
+
3987
+ export const MemoryErasurePageSchema: JsonSchema = {
3308
3988
  type: 'object',
3309
3989
  additionalProperties: false,
3310
3990
  required: ['data', 'hasMore'],
3311
3991
  properties: {
3312
- data: { type: 'array', items: { $ref: '#/components/schemas/TrustedSigningKey' } },
3313
- nextCursor: { type: 'string' },
3992
+ data: { type: 'array', items: { $ref: '#/components/schemas/MemoryErasure' } },
3314
3993
  hasMore: { type: 'boolean' },
3994
+ nextCursor: { type: 'string' },
3315
3995
  },
3316
3996
  };
3317
3997
 
3318
- export const RevokeSigningKeyBodySchema: JsonSchema = {
3998
+ export const MemoryErasureLedgerEntrySchema: JsonSchema = {
3319
3999
  type: 'object',
3320
4000
  additionalProperties: false,
4001
+ required: ['id', 'selectorKind', 'requestedBy', 'status', 'createdAt'],
3321
4002
  properties: {
3322
- reason: { type: 'string', description: 'Kept with the key as `revokedReason`.' },
4003
+ id: { type: 'string', format: 'uuid' },
4004
+ selectorKind: ErasureSelectorKindSchema,
4005
+ selectorHmac: {
4006
+ type: 'string',
4007
+ pattern: '^[0-9a-f]{64}$',
4008
+ description: "HMAC-SHA256 of the selector under the tenant's ledger key; absent without one.",
4009
+ },
4010
+ keyId: { type: 'string', description: 'Which ledger key made `selectorHmac`.' },
4011
+ requestedBy: { type: 'string' },
4012
+ status: ErasureStatusSchema,
4013
+ createdAt: { type: 'string', format: 'date-time' },
4014
+ completedAt: { type: 'string', format: 'date-time' },
3323
4015
  },
3324
4016
  };
3325
4017
 
3326
- export const RevokeSigningKeyResultSchema: JsonSchema = {
4018
+ export const MemoryErasureLedgerSchema: JsonSchema = {
3327
4019
  type: 'object',
3328
4020
  additionalProperties: false,
3329
- required: ['keyId', 'revoked'],
4021
+ required: ['data'],
3330
4022
  properties: {
3331
- keyId: { type: 'string' },
3332
- revoked: {
3333
- type: 'boolean',
3334
- description: '`false` when the key was unknown or already revoked.',
3335
- },
4023
+ data: { type: 'array', items: { $ref: '#/components/schemas/MemoryErasureLedgerEntry' } },
3336
4024
  },
3337
4025
  };
3338
4026
 
3339
- // ---------------- supervisor (fix proposals) ----------------
3340
-
3341
- export const ProposalTierSchema: JsonSchema = {
3342
- type: 'string',
3343
- enum: ['prompt', 'retrieval', 'tool-config'],
4027
+ export const ReplayMemoryErasuresBodySchema: JsonSchema = {
4028
+ type: 'object',
4029
+ additionalProperties: false,
4030
+ required: ['erasures'],
4031
+ properties: {
4032
+ erasures: {
4033
+ type: 'array',
4034
+ maxItems: 10_000,
4035
+ items: { $ref: '#/components/schemas/MemoryErasureLedgerEntry' },
4036
+ description: 'The ledger as `GET /v1/memory/erasures/export` gave it.',
4037
+ },
4038
+ },
3344
4039
  };
3345
4040
 
3346
- export const FixProposalStatusSchema: JsonSchema = {
3347
- type: 'string',
3348
- enum: [
3349
- 'draft',
3350
- 'dry-running',
3351
- 'dry-run-passed',
3352
- 'dry-run-failed',
3353
- 'proposed-for-review',
3354
- 'approved',
3355
- 'rejected',
3356
- 'applied',
3357
- 'rolled-back',
3358
- 'withdrawn',
3359
- ],
3360
- };
3361
-
3362
- export const PatternRefSchema: JsonSchema = {
4041
+ export const ReplayMemoryErasuresResultSchema: JsonSchema = {
3363
4042
  type: 'object',
3364
4043
  additionalProperties: false,
3365
- required: ['kind', 'key', 'count', 'firstSeenAt', 'lastSeenAt', 'sampleConversations'],
4044
+ required: ['replayed', 'restored', 'unmatched'],
3366
4045
  properties: {
3367
- kind: {
3368
- type: 'string',
3369
- enum: ['guardrail-violation', 'tool-error', 'budget-exceeded', 'model-error', 'aborted'],
4046
+ replayed: {
4047
+ type: 'array',
4048
+ items: { type: 'string', format: 'uuid' },
4049
+ description: 'Found in the tenant again: run again.',
3370
4050
  },
3371
- key: { type: 'string' },
3372
- count: { type: 'integer', minimum: 1 },
3373
- firstSeenAt: { type: 'string', format: 'date-time' },
3374
- lastSeenAt: { type: 'string', format: 'date-time' },
3375
- sampleConversations: {
4051
+ restored: {
3376
4052
  type: 'array',
3377
4053
  items: { type: 'string', format: 'uuid' },
4054
+ description: 'Put back in the ledger; nothing in the tenant matches.',
4055
+ },
4056
+ unmatched: {
4057
+ type: 'array',
4058
+ items: {
4059
+ type: 'object',
4060
+ additionalProperties: false,
4061
+ required: ['id', 'reason'],
4062
+ properties: {
4063
+ id: { type: 'string', format: 'uuid' },
4064
+ reason: { type: 'string', enum: ['no-keyed-hash', 'unknown-key'] },
4065
+ },
4066
+ },
3378
4067
  },
3379
4068
  },
3380
4069
  };
3381
4070
 
3382
- export const ProposedChangeSchema: JsonSchema = {
3383
- description:
3384
- 'Polymorphic change payload. Shape depends on the sibling `tier` on the proposal (prompt / retrieval / tool-config).',
4071
+ export const RevokeTokenResultSchema: JsonSchema = {
3385
4072
  type: 'object',
3386
- additionalProperties: true,
4073
+ additionalProperties: false,
4074
+ required: ['tokenId', 'revoked'],
4075
+ properties: {
4076
+ tokenId: { type: 'string', format: 'uuid' },
4077
+ revoked: { type: 'boolean', const: true },
4078
+ },
3387
4079
  };
3388
4080
 
3389
- export const FixProposalSchema: JsonSchema = {
4081
+ // ---------------- signing keys (the deployment trust list) ----------------
4082
+
4083
+ export const TrustedSigningKeySchema: JsonSchema = {
3390
4084
  type: 'object',
3391
4085
  additionalProperties: false,
3392
- required: [
3393
- 'id',
3394
- 'tenantId',
3395
- 'supervisorId',
3396
- 'agentId',
3397
- 'agentVersion',
3398
- 'tier',
3399
- 'change',
3400
- 'patternRefs',
3401
- 'hypothesis',
3402
- 'proposerRuleId',
3403
- 'status',
3404
- 'fingerprint',
3405
- 'createdAt',
3406
- 'updatedAt',
3407
- ],
4086
+ required: ['keyId', 'tenantId', 'algorithm', 'publicKey', 'createdAt'],
4087
+ description:
4088
+ 'A public key the tenant trusts to sign deployments (`POST /v1/deployments`). A revoked key stays readable, with `revokedAt`, so the deployments it signed can be audited; it verifies no new ones.',
3408
4089
  properties: {
3409
- id: { type: 'string', format: 'uuid', description: 'FixProposalId.' },
4090
+ keyId: { type: 'string', description: 'The signer key id a deployment envelope names.' },
3410
4091
  tenantId: { type: 'string', format: 'uuid' },
3411
- supervisorId: { type: 'string' },
3412
- agentId: { type: 'string' },
3413
- agentVersion: { type: 'string', description: 'Semver of the baseline agent version.' },
3414
- tier: ProposalTierSchema,
3415
- change: ProposedChangeSchema,
3416
- patternRefs: {
3417
- type: 'array',
3418
- items: { $ref: '#/components/schemas/PatternRef' },
3419
- },
3420
- hypothesis: { type: 'string' },
3421
- proposerRuleId: { type: 'string' },
3422
- status: FixProposalStatusSchema,
3423
- fingerprint: {
4092
+ algorithm: { type: 'string', enum: ['ed25519'] },
4093
+ publicKey: {
3424
4094
  type: 'string',
3425
- description: 'sha256(tier + agentId + agentVersion + canonical(change)). Dedup key.',
4095
+ description: 'Base64 of the raw public-key bytes (32 for Ed25519).',
3426
4096
  },
3427
- resolutionReason: { type: 'string' },
3428
- reviewApprovalId: {
4097
+ label: { type: 'string' },
4098
+ createdAt: { type: 'string', format: 'date-time' },
4099
+ revokedAt: { type: 'string', format: 'date-time' },
4100
+ revokedReason: { type: 'string' },
4101
+ },
4102
+ };
4103
+
4104
+ export const TrustSigningKeyBodySchema: JsonSchema = {
4105
+ type: 'object',
4106
+ additionalProperties: false,
4107
+ required: ['keyId', 'publicKey'],
4108
+ properties: {
4109
+ keyId: {
3429
4110
  type: 'string',
3430
- format: 'uuid',
3431
- description: 'HITL approval id created when the proposal was submitted for review.',
4111
+ pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$',
4112
+ description:
4113
+ 'The id deployment envelopes name as `signerKeyId`. Bound to `publicKey` for good: rotate by trusting a new id.',
3432
4114
  },
3433
- appliedVersion: {
4115
+ algorithm: { type: 'string', enum: ['ed25519'], default: 'ed25519' },
4116
+ publicKey: {
3434
4117
  type: 'string',
3435
- description:
3436
- 'Semver of the new agent version the proposal materialized as. Present on `applied` and `rolled-back` proposals.',
4118
+ description: 'Base64 of the 32 raw bytes of the Ed25519 public key.',
3437
4119
  },
3438
- appliedAt: { type: 'string', format: 'date-time' },
3439
- rolledBackAt: { type: 'string', format: 'date-time' },
3440
- createdAt: { type: 'string', format: 'date-time' },
3441
- updatedAt: { type: 'string', format: 'date-time' },
3442
- resolvedAt: { type: 'string', format: 'date-time' },
4120
+ label: { type: 'string', maxLength: 200 },
3443
4121
  },
3444
4122
  };
3445
4123
 
3446
- export const FixProposalCollectionPageSchema: JsonSchema = {
4124
+ export const TrustedSigningKeyPageSchema: JsonSchema = {
3447
4125
  type: 'object',
3448
4126
  additionalProperties: false,
3449
4127
  required: ['data', 'hasMore'],
3450
4128
  properties: {
3451
- data: { type: 'array', items: { $ref: '#/components/schemas/FixProposal' } },
3452
- nextCursor: {
3453
- type: 'string',
3454
- description: 'Opaque cursor for the next page. Absent when `hasMore: false`.',
3455
- },
4129
+ data: { type: 'array', items: { $ref: '#/components/schemas/TrustedSigningKey' } },
4130
+ nextCursor: { type: 'string' },
3456
4131
  hasMore: { type: 'boolean' },
3457
4132
  },
3458
4133
  };
3459
4134
 
3460
- export const DraftProposalBodySchema: JsonSchema = {
3461
- description:
3462
- 'Draft a fix proposal for `(agentId, agentVersion)`. The supervisor context comes from the `X-Supervisor-Id` header; the caller supplies the target agent + change payload + supporting evidence. Duplicate proposals (same `(supervisor, fingerprint)` in a non-terminal state) short-circuit to the pre-existing row and set `X-Proposal-Deduped: true` on the response.',
4135
+ export const RevokeSigningKeyBodySchema: JsonSchema = {
3463
4136
  type: 'object',
3464
4137
  additionalProperties: false,
3465
- required: [
3466
- 'agentId',
3467
- 'agentVersion',
3468
- 'tier',
3469
- 'change',
3470
- 'patternRefs',
3471
- 'hypothesis',
3472
- 'proposerRuleId',
3473
- ],
3474
4138
  properties: {
3475
- agentId: { type: 'string' },
3476
- agentVersion: { type: 'string' },
3477
- tier: ProposalTierSchema,
3478
- change: ProposedChangeSchema,
3479
- patternRefs: {
3480
- type: 'array',
3481
- items: { $ref: '#/components/schemas/PatternRef' },
4139
+ reason: { type: 'string', description: 'Kept with the key as `revokedReason`.' },
4140
+ },
4141
+ };
4142
+
4143
+ export const RevokeSigningKeyResultSchema: JsonSchema = {
4144
+ type: 'object',
4145
+ additionalProperties: false,
4146
+ required: ['keyId', 'revoked'],
4147
+ properties: {
4148
+ keyId: { type: 'string' },
4149
+ revoked: {
4150
+ type: 'boolean',
4151
+ description: '`false` when the key was unknown or already revoked.',
3482
4152
  },
3483
- hypothesis: { type: 'string', minLength: 1 },
3484
- proposerRuleId: { type: 'string', minLength: 1 },
3485
4153
  },
3486
4154
  };
3487
4155
 
3488
- export const PassCriterionSchema: JsonSchema = {
4156
+ // ---------------- improvement proposals ----------------
4157
+
4158
+ export const ProposalTierSchema: JsonSchema = {
4159
+ type: 'string',
4160
+ enum: ['settings-block', 'prompt-block'],
3489
4161
  description:
3490
- 'How the dry-run judges whether the candidate is good enough to submit for review. Two kinds: `min-pass-rate` (candidate pass rate ≥ threshold) or `strict-improvement` (candidate pass rate exceeds baseline by ≥ delta).',
3491
- oneOf: [
3492
- {
3493
- type: 'object',
3494
- additionalProperties: false,
3495
- required: ['kind', 'minPassRate'],
3496
- properties: {
3497
- kind: { type: 'string', const: 'min-pass-rate' },
3498
- minPassRate: { type: 'number', minimum: 0, maximum: 1 },
3499
- },
4162
+ 'What a proposal changes: a settings block (new values) or a prompt block (a new template) the agent version pins.',
4163
+ };
4164
+
4165
+ export const FixProposalStatusSchema: JsonSchema = {
4166
+ type: 'string',
4167
+ enum: [
4168
+ 'draft',
4169
+ 'evaluating',
4170
+ 'evaluated',
4171
+ 'not-better',
4172
+ 'evaluation-failed',
4173
+ 'in-review',
4174
+ 'promoted',
4175
+ 'refused',
4176
+ 'rejected',
4177
+ 'expired',
4178
+ 'superseded',
4179
+ 'rolled-back',
4180
+ 'withdrawn',
4181
+ ],
4182
+ description:
4183
+ "Where a proposal stands, from its comparison and its promotion (never stored). `draft`: not evaluated yet. `evaluating`: its comparison is queued or running. `evaluated`: the candidate beat the recorded outputs on the objective metric by more than the noise (the spread, with more than one repetition). `not-better`: it didn't. `evaluation-failed`: the comparison failed or was cancelled. `in-review`: requested; the gate passed and an approval is open. `promoted`: live for the scope (`promotion.liveNow` says whether it still serves it). `refused`: the gate refused it. `rejected`: the reviewer rejected it. `expired`: the approval expired undecided. `superseded`: approved after the scope's live version or policy changed. `rolled-back`: rolled back through the proposal. `withdrawn`: withdrawn.",
4184
+ };
4185
+
4186
+ export const ProposalChangeSchema: JsonSchema = {
4187
+ type: 'object',
4188
+ additionalProperties: false,
4189
+ required: ['blockId', 'fromVersion', 'content'],
4190
+ properties: {
4191
+ blockId: { type: 'string', description: 'The data block the change is to.' },
4192
+ fromVersion: {
4193
+ type: 'string',
4194
+ description: "The block version the agent version pins: what's being changed.",
3500
4195
  },
3501
- {
4196
+ content: {
3502
4197
  type: 'object',
4198
+ description:
4199
+ 'The new content: `{ values }` for a settings block (its schema carries over), `{ template }` for a prompt block (its parameters carry over).',
3503
4200
  additionalProperties: false,
3504
- required: ['kind', 'baselinePassRate', 'minDelta'],
3505
4201
  properties: {
3506
- kind: { type: 'string', const: 'strict-improvement' },
3507
- baselinePassRate: { type: 'number', minimum: 0, maximum: 1 },
3508
- minDelta: { type: 'number' },
4202
+ values: { type: 'object', additionalProperties: true },
4203
+ template: { type: 'string' },
3509
4204
  },
3510
4205
  },
3511
- ],
4206
+ },
3512
4207
  };
3513
4208
 
3514
- export const DryRunProposalBodySchema: JsonSchema = {
4209
+ export const ProposalDrafterSchema: JsonSchema = {
3515
4210
  type: 'object',
3516
4211
  additionalProperties: false,
3517
- required: ['datasetId', 'datasetVersion', 'criterion'],
4212
+ required: ['kind'],
4213
+ description: "Who wrote the proposal: a person, or one of the runtime's drafters.",
3518
4214
  properties: {
3519
- datasetId: { type: 'string', minLength: 1 },
3520
- datasetVersion: { type: 'string', minLength: 1 },
3521
- criterion: PassCriterionSchema,
4215
+ kind: { type: 'string', enum: ['person', 'settings-optimizer', 'prompt-drafter'] },
4216
+ by: { type: 'string', description: 'For a person: `user:<id>` (or `service:<id>`).' },
4217
+ version: { type: 'string', description: "For a drafter: the drafter's version." },
4218
+ model: {
4219
+ type: 'object',
4220
+ additionalProperties: false,
4221
+ required: ['providerId', 'model'],
4222
+ description: 'For a drafter that used a model: which.',
4223
+ properties: { providerId: { type: 'string' }, model: { type: 'string' } },
4224
+ },
4225
+ passId: {
4226
+ type: 'string',
4227
+ description:
4228
+ 'For a drafter: the improvement pass that drafted it (`GET /v1/improvement-passes/{passId}`).',
4229
+ },
3522
4230
  },
3523
4231
  };
3524
4232
 
3525
- export const DryRunProposalResultSchema: JsonSchema = {
4233
+ export const ProposalCandidateSchema: JsonSchema = {
3526
4234
  type: 'object',
3527
4235
  additionalProperties: false,
3528
- required: ['proposal', 'passed'],
4236
+ required: ['agentVersion', 'blockVersion', 'pinsDigest'],
4237
+ description:
4238
+ 'The versions evaluating the proposal published. They serve no scope until a promotion makes the agent version live.',
3529
4239
  properties: {
3530
- proposal: { $ref: '#/components/schemas/FixProposal' },
3531
- passed: {
3532
- type: 'boolean',
3533
- description:
3534
- 'True when the candidate met the criterion — proposal moves to `dry-run-passed`. False → `dry-run-failed` (still a legitimate response, not an error).',
4240
+ agentVersion: {
4241
+ type: 'string',
4242
+ description: 'The derived agent version (its `derivedFrom.proposalId` names the proposal).',
3535
4243
  },
4244
+ blockVersion: {
4245
+ type: 'string',
4246
+ description: "The block version published from the proposal's content.",
4247
+ },
4248
+ pinsDigest: { type: 'string' },
3536
4249
  },
3537
4250
  };
3538
4251
 
3539
- export const SubmitReviewProposalBodySchema: JsonSchema = {
3540
- description:
3541
- 'Body is optional — omit to accept every default. `requiredRole` overrides the auto-derivation (meta-fixes → senior). `expiresAt` sets the HITL approval deadline.',
4252
+ export const ProposalEvaluationSchema: JsonSchema = {
3542
4253
  type: 'object',
3543
4254
  additionalProperties: false,
4255
+ required: ['evalRunId', 'suiteId', 'objective', 'startedAt'],
4256
+ description:
4257
+ "The comparison the proposal was evaluated with, and what it found on the objective metric (the full summary is the eval run's).",
3544
4258
  properties: {
3545
- requiredRole: { $ref: '#/components/schemas/ReviewerRole' },
3546
- expiresAt: { type: 'string', format: 'date-time' },
4259
+ evalRunId: { type: 'string', format: 'uuid' },
4260
+ suiteId: { type: 'string', description: 'The test set (a judged eval suite).' },
4261
+ objective: { type: 'string', enum: ['weightedYesShare', 'weightedPrecisionAtK'] },
4262
+ startedAt: { type: 'string', format: 'date-time' },
4263
+ runStatus: {
4264
+ type: 'string',
4265
+ enum: ['pending', 'running', 'completed', 'failed', 'cancelled'],
4266
+ description: "The eval run's status. Absent when the run can't be read.",
4267
+ },
4268
+ baseline: {
4269
+ type: ['number', 'null'],
4270
+ description: "The recorded outputs' score; `null` without judged evidence.",
4271
+ },
4272
+ candidate: { type: ['number', 'null'], description: "The candidate's score." },
4273
+ delta: { type: ['number', 'null'] },
4274
+ spread: {
4275
+ type: 'number',
4276
+ description:
4277
+ "With more than one repetition: the candidate's max − min, the noise a delta must beat.",
4278
+ },
4279
+ cases: { type: 'integer' },
4280
+ better: { type: 'boolean', description: 'Set once the comparison finished.' },
3547
4281
  },
3548
4282
  };
3549
4283
 
3550
- export const SubmitReviewProposalResultSchema: JsonSchema = {
4284
+ export const ProposalPromotionSchema: JsonSchema = {
3551
4285
  type: 'object',
3552
4286
  additionalProperties: false,
3553
- required: ['proposal', 'approvalId', 'metaFix'],
4287
+ required: ['id', 'status'],
4288
+ description: "The promotion the proposal's request made.",
3554
4289
  properties: {
3555
- proposal: { $ref: '#/components/schemas/FixProposal' },
3556
- approvalId: { type: 'string', format: 'uuid' },
3557
- metaFix: {
4290
+ id: { type: 'string' },
4291
+ status: {
4292
+ type: 'string',
4293
+ enum: ['promoted', 'pending-approval', 'refused', 'superseded', 'rejected', 'expired'],
4294
+ },
4295
+ approvalId: { type: 'string', description: 'The approval a request in review waits on.' },
4296
+ liveNow: {
3558
4297
  type: 'boolean',
3559
- description:
3560
- "True when the proposal targets one of the supervisor's own agent ids — reviewer role auto-bumps to `senior` unless overridden.",
4298
+ description: 'For a promoted proposal: whether its version still serves the scope.',
3561
4299
  },
3562
4300
  },
3563
4301
  };
3564
4302
 
3565
- export const ApplyProposalBodySchema: JsonSchema = {
3566
- description:
3567
- 'Body is optional. `newVersion` overrides the auto-derived patch bump of the baseline; omit to let the runtime bump `1.0.0 → 1.0.1`.',
4303
+ export const FixProposalSchema: JsonSchema = {
3568
4304
  type: 'object',
3569
4305
  additionalProperties: false,
4306
+ description:
4307
+ 'An improvement proposal: a change to one data block an agent version pins, for one live scope, taken through the same comparison, gate and promotion as any other version.',
4308
+ required: [
4309
+ 'id',
4310
+ 'agentId',
4311
+ 'fromVersion',
4312
+ 'scope',
4313
+ 'tier',
4314
+ 'change',
4315
+ 'hypothesis',
4316
+ 'drafter',
4317
+ 'status',
4318
+ 'createdAt',
4319
+ 'updatedAt',
4320
+ ],
3570
4321
  properties: {
3571
- newVersion: {
3572
- type: 'string',
3573
- description: 'Semver, strictly greater than the baseline.',
4322
+ id: { type: 'string', format: 'uuid' },
4323
+ agentId: { type: 'string' },
4324
+ fromVersion: { type: 'string', description: 'The agent version the change applies to.' },
4325
+ scope: { $ref: '#/components/schemas/LiveScope' },
4326
+ tier: { $ref: '#/components/schemas/ProposalTier' },
4327
+ change: { $ref: '#/components/schemas/ProposalChange' },
4328
+ hypothesis: { type: 'string', description: 'What the change should improve, and why.' },
4329
+ evidence: {
4330
+ type: 'object',
4331
+ additionalProperties: false,
4332
+ properties: { judgmentIds: { type: 'array', items: { type: 'string' } } },
4333
+ },
4334
+ drafter: { $ref: '#/components/schemas/ProposalDrafter' },
4335
+ status: { $ref: '#/components/schemas/FixProposalStatus' },
4336
+ candidate: { $ref: '#/components/schemas/ProposalCandidate' },
4337
+ evaluation: { $ref: '#/components/schemas/ProposalEvaluation' },
4338
+ promotion: { $ref: '#/components/schemas/ProposalPromotion' },
4339
+ rolledBack: {
4340
+ type: 'object',
4341
+ additionalProperties: false,
4342
+ required: ['at', 'promotionId', 'by'],
4343
+ properties: {
4344
+ at: { type: 'string', format: 'date-time' },
4345
+ promotionId: { type: 'string', description: "The rollback's own promotion row." },
4346
+ by: { type: 'string' },
4347
+ reason: { type: 'string' },
4348
+ },
3574
4349
  },
4350
+ withdrawn: {
4351
+ type: 'object',
4352
+ additionalProperties: false,
4353
+ required: ['at', 'by', 'reason'],
4354
+ properties: {
4355
+ at: { type: 'string', format: 'date-time' },
4356
+ by: { type: 'string' },
4357
+ reason: { type: 'string' },
4358
+ },
4359
+ },
4360
+ createdAt: { type: 'string', format: 'date-time' },
4361
+ updatedAt: { type: 'string', format: 'date-time' },
3575
4362
  },
3576
4363
  };
3577
4364
 
3578
- export const ApplyProposalResultSchema: JsonSchema = {
4365
+ export const FixProposalCollectionPageSchema: JsonSchema = {
3579
4366
  type: 'object',
3580
4367
  additionalProperties: false,
3581
- required: ['proposalId', 'appliedVersion', 'appliedAt'],
4368
+ required: ['data', 'hasMore'],
3582
4369
  properties: {
3583
- proposalId: { type: 'string', format: 'uuid' },
3584
- appliedVersion: { type: 'string' },
3585
- appliedAt: { type: 'string', format: 'date-time' },
4370
+ data: { type: 'array', items: { $ref: '#/components/schemas/FixProposal' } },
4371
+ hasMore: { type: 'boolean' },
4372
+ nextCursor: { type: 'string' },
3586
4373
  },
3587
4374
  };
3588
4375
 
3589
- export const RollbackProposalBodySchema: JsonSchema = {
4376
+ export const ImprovementBudgetSchema: JsonSchema = {
3590
4377
  type: 'object',
3591
4378
  additionalProperties: false,
3592
- required: ['reason'],
4379
+ required: ['maxCostUsd', 'maxCandidates'],
3593
4380
  properties: {
3594
- reason: { type: 'string', minLength: 1 },
4381
+ maxCostUsd: {
4382
+ type: 'number',
4383
+ exclusiveMinimum: 0,
4384
+ maximum: 100,
4385
+ description: "The most the pass's comparisons may cost, in US dollars.",
4386
+ },
4387
+ maxCandidates: {
4388
+ type: 'integer',
4389
+ minimum: 1,
4390
+ maximum: 200,
4391
+ description: 'The most candidates it compares.',
4392
+ },
3595
4393
  },
3596
4394
  };
3597
4395
 
3598
- export const RollbackProposalResultSchema: JsonSchema = {
4396
+ export const ImprovementPassOutcomeSchema: JsonSchema = {
3599
4397
  type: 'object',
3600
4398
  additionalProperties: false,
3601
- required: ['proposalId', 'rolledBackAt'],
4399
+ required: ['kind'],
4400
+ description:
4401
+ "What a finished pass found. `proposed`: its best candidate beat the current values on the test set's hold-out part, so it wrote an improvement proposal (`proposalId`) for a reviewer to decide. `nothing-found`: no candidate beat them by more than the noise, or within the budget (`reason`; `holdOut` has the best candidate's numbers when one got that far). `failed`: `message` says why.",
3602
4402
  properties: {
4403
+ kind: { type: 'string', enum: ['proposed', 'nothing-found', 'failed'] },
3603
4404
  proposalId: { type: 'string', format: 'uuid' },
3604
- rolledBackAt: { type: 'string', format: 'date-time' },
4405
+ reason: { type: 'string' },
4406
+ holdOut: {
4407
+ type: 'object',
4408
+ additionalProperties: false,
4409
+ required: ['baseline', 'candidate', 'delta'],
4410
+ properties: {
4411
+ baseline: { type: ['number', 'null'] },
4412
+ candidate: { type: ['number', 'null'] },
4413
+ delta: { type: ['number', 'null'] },
4414
+ spread: { type: 'number' },
4415
+ },
4416
+ },
4417
+ message: { type: 'string' },
3605
4418
  },
3606
4419
  };
3607
4420
 
3608
- export const WithdrawProposalBodySchema: JsonSchema = {
4421
+ export const ImprovementPassSchema: JsonSchema = {
3609
4422
  type: 'object',
3610
4423
  additionalProperties: false,
3611
- required: ['reason'],
4424
+ description:
4425
+ "An improvement pass: the runtime looking for better values for an agent version's tunable settings (`x-kindgi-tunable`) on a test set, within a budget. Its best candidate becomes an improvement proposal.",
4426
+ required: [
4427
+ 'id',
4428
+ 'agentId',
4429
+ 'fromVersion',
4430
+ 'scope',
4431
+ 'suiteId',
4432
+ 'tiers',
4433
+ 'objective',
4434
+ 'budget',
4435
+ 'requestedBy',
4436
+ 'status',
4437
+ 'candidatesEvaluated',
4438
+ 'costUsd',
4439
+ 'createdAt',
4440
+ 'updatedAt',
4441
+ ],
3612
4442
  properties: {
3613
- reason: { type: 'string', minLength: 1 },
3614
- },
3615
- };
3616
-
3617
- // ---------------- provenance ----------------
4443
+ id: { type: 'string', format: 'uuid' },
4444
+ agentId: { type: 'string' },
4445
+ fromVersion: { type: 'string', description: 'The version whose settings it tunes.' },
4446
+ scope: { $ref: '#/components/schemas/LiveScope' },
4447
+ suiteId: { type: 'string', description: 'The test set it searches and proves on.' },
4448
+ tiers: { type: 'array', items: { type: 'string', enum: ['settings', 'prompt'] } },
4449
+ objective: { type: 'string', enum: ['weightedYesShare', 'weightedPrecisionAtK'] },
4450
+ classWeights: {
4451
+ type: 'string',
4452
+ enum: ['as-recorded', 'restricted-only'],
4453
+ description:
4454
+ 'Which judgments its comparisons count. Absent from older servers: `restricted-only`.',
4455
+ },
4456
+ model: {
4457
+ type: 'object',
4458
+ additionalProperties: false,
4459
+ required: ['providerId', 'model'],
4460
+ description: 'For a prompt pass: the provider and model that drafts the templates.',
4461
+ properties: { providerId: { type: 'string' }, model: { type: 'string' } },
4462
+ },
4463
+ candidates: {
4464
+ type: 'integer',
4465
+ minimum: 1,
4466
+ maximum: 5,
4467
+ description: 'For a prompt pass: how many templates it drafts.',
4468
+ },
4469
+ budget: { $ref: '#/components/schemas/ImprovementBudget' },
4470
+ requestedBy: { type: 'string' },
4471
+ status: { type: 'string', enum: ['running', 'completed', 'failed', 'cancelled'] },
4472
+ candidatesEvaluated: { type: 'integer', minimum: 0 },
4473
+ costUsd: { type: 'string', description: 'What its comparisons have cost so far (US dollars).' },
4474
+ outcome: { $ref: '#/components/schemas/ImprovementPassOutcome' },
4475
+ comparisons: {
4476
+ type: 'array',
4477
+ description:
4478
+ 'Its comparisons so far, each an eval run to open: `reference` (the version as it is, on the search part), each `candidate` (the block and the values it changed, on the search part), and the `proof` (the proposal, on the hold-out part). Absent from older servers.',
4479
+ items: {
4480
+ type: 'object',
4481
+ additionalProperties: false,
4482
+ required: ['role', 'part'],
4483
+ properties: {
4484
+ evalRunId: { type: 'string', format: 'uuid' },
4485
+ role: { type: 'string', enum: ['reference', 'candidate', 'proof'] },
4486
+ part: { type: 'string', enum: ['search', 'hold-out'] },
4487
+ blockId: { type: 'string' },
4488
+ changed: { type: 'object', additionalProperties: true },
4489
+ score: { type: ['number', 'null'] },
4490
+ failed: { type: 'string' },
4491
+ refused: {
4492
+ type: 'array',
4493
+ description:
4494
+ "For a drafted template that was never compared: why the check refused it (what it reads or names that the agent doesn't have, or its size).",
4495
+ items: {
4496
+ type: 'object',
4497
+ additionalProperties: false,
4498
+ required: ['path', 'message'],
4499
+ properties: { path: { type: 'string' }, message: { type: 'string' } },
4500
+ },
4501
+ },
4502
+ hypothesis: {
4503
+ type: 'string',
4504
+ description: 'For a drafted template: what the drafter meant it to change.',
4505
+ },
4506
+ },
4507
+ },
4508
+ },
4509
+ trigger: {
4510
+ type: 'object',
4511
+ additionalProperties: false,
4512
+ required: ['triggerId', 'fireId'],
4513
+ description:
4514
+ 'The improve schedule and fire that started it (`GET /v1/schedules/{triggerId}/fires`); absent for a pass a person started.',
4515
+ properties: { triggerId: { type: 'string' }, fireId: { type: 'string' } },
4516
+ },
4517
+ createdAt: { type: 'string', format: 'date-time' },
4518
+ updatedAt: { type: 'string', format: 'date-time' },
4519
+ finishedAt: { type: 'string', format: 'date-time' },
4520
+ },
4521
+ };
4522
+
4523
+ export const ImprovementPassCollectionPageSchema: JsonSchema = {
4524
+ type: 'object',
4525
+ additionalProperties: false,
4526
+ required: ['data', 'hasMore'],
4527
+ properties: {
4528
+ data: { type: 'array', items: { $ref: '#/components/schemas/ImprovementPass' } },
4529
+ hasMore: { type: 'boolean' },
4530
+ nextCursor: { type: 'string' },
4531
+ },
4532
+ };
4533
+
4534
+ export const ImproveBodySchema: JsonSchema = {
4535
+ type: 'object',
4536
+ additionalProperties: false,
4537
+ required: ['agentId', 'scope', 'suiteId'],
4538
+ description: 'Start an improvement pass.',
4539
+ properties: {
4540
+ agentId: { type: 'string' },
4541
+ fromVersion: {
4542
+ type: 'string',
4543
+ description: 'The version whose settings it tunes. Default: the one serving `scope`.',
4544
+ },
4545
+ scope: { $ref: '#/components/schemas/LiveScope' },
4546
+ suiteId: {
4547
+ type: 'string',
4548
+ description:
4549
+ 'The test set (a judged eval suite). The pass splits it into a search part and a hold-out part, and proves its best candidate on the hold-out part.',
4550
+ },
4551
+ tiers: {
4552
+ type: 'array',
4553
+ items: { type: 'string', enum: ['settings', 'prompt'] },
4554
+ minItems: 1,
4555
+ maxItems: 1,
4556
+ default: ['settings'],
4557
+ description:
4558
+ "`['settings']`: values for the tunable settings keys. `['prompt']`: a model drafts templates for the prompt block (needs `model`); a template that reads or names anything the agent doesn't have is refused, and a drafted proposal always waits for a reviewer.",
4559
+ },
4560
+ model: {
4561
+ type: 'object',
4562
+ additionalProperties: false,
4563
+ required: ['providerId', 'model'],
4564
+ description: "For a prompt pass: the tenant's provider and model that drafts the templates.",
4565
+ properties: { providerId: { type: 'string' }, model: { type: 'string' } },
4566
+ },
4567
+ candidates: {
4568
+ type: 'integer',
4569
+ minimum: 1,
4570
+ maximum: 5,
4571
+ default: 3,
4572
+ description: 'For a prompt pass: how many templates it drafts.',
4573
+ },
4574
+ classWeights: {
4575
+ type: 'string',
4576
+ enum: ['as-recorded', 'restricted-only'],
4577
+ default: 'restricted-only',
4578
+ description:
4579
+ 'Which judgments the pass learns from: by default only those recorded under a restricted (trusted) judge class.',
4580
+ },
4581
+ objective: {
4582
+ type: 'string',
4583
+ enum: ['weightedYesShare', 'weightedPrecisionAtK'],
4584
+ default: 'weightedYesShare',
4585
+ },
4586
+ budget: {
4587
+ type: 'object',
4588
+ additionalProperties: false,
4589
+ description: 'Default: $5 and 30 candidates.',
4590
+ properties: {
4591
+ maxCostUsd: { type: 'number', exclusiveMinimum: 0, maximum: 100 },
4592
+ maxCandidates: { type: 'integer', minimum: 1, maximum: 200 },
4593
+ },
4594
+ },
4595
+ },
4596
+ };
4597
+
4598
+ export const CreateProposalBodySchema: JsonSchema = {
4599
+ description:
4600
+ 'A hand-written proposal: new content for a data block that `fromVersion` pins, for a live scope. The same change from the same version for the same scope is one proposal (answered with `X-Proposal-Deduped: true`).',
4601
+ type: 'object',
4602
+ additionalProperties: false,
4603
+ required: ['agentId', 'fromVersion', 'scope', 'tier', 'change', 'hypothesis'],
4604
+ properties: {
4605
+ agentId: { type: 'string' },
4606
+ fromVersion: { type: 'string', description: 'The agent version the change applies to.' },
4607
+ scope: { $ref: '#/components/schemas/LiveScope' },
4608
+ tier: { $ref: '#/components/schemas/ProposalTier' },
4609
+ change: {
4610
+ type: 'object',
4611
+ additionalProperties: false,
4612
+ required: ['blockId', 'content'],
4613
+ properties: {
4614
+ blockId: { type: 'string', description: "A block `fromVersion` pins, of the tier's kind." },
4615
+ content: {
4616
+ type: 'object',
4617
+ description:
4618
+ '`{ values }` for a settings block (they must satisfy its schema), `{ template }` for a prompt block.',
4619
+ additionalProperties: false,
4620
+ properties: {
4621
+ values: { type: 'object', additionalProperties: true },
4622
+ template: { type: 'string' },
4623
+ },
4624
+ },
4625
+ },
4626
+ },
4627
+ hypothesis: { type: 'string', minLength: 1, maxLength: 2000 },
4628
+ evidence: {
4629
+ type: 'object',
4630
+ additionalProperties: false,
4631
+ properties: { judgmentIds: { type: 'array', items: { type: 'string' } } },
4632
+ },
4633
+ },
4634
+ };
4635
+
4636
+ export const EvaluateProposalBodySchema: JsonSchema = {
4637
+ description:
4638
+ "Compare the proposal's candidate on a test set. The first evaluation publishes the block version and derives the agent version (both serve nowhere until promoted).",
4639
+ type: 'object',
4640
+ additionalProperties: false,
4641
+ required: ['suiteId'],
4642
+ properties: {
4643
+ suiteId: { type: 'string', description: 'The test set: a judged eval suite.' },
4644
+ objective: {
4645
+ type: 'string',
4646
+ enum: ['weightedYesShare', 'weightedPrecisionAtK'],
4647
+ default: 'weightedYesShare',
4648
+ description: 'The metric that says whether the candidate is better.',
4649
+ },
4650
+ reads: { type: 'string', enum: ['recorded', 'live'] },
4651
+ repetitions: { type: 'integer', minimum: 1, maximum: 10 },
4652
+ k: { type: 'integer', minimum: 1, maximum: 100 },
4653
+ classWeights: { type: 'string', enum: ['as-recorded', 'restricted-only'] },
4654
+ sample: { $ref: '#/components/schemas/EvalSample' },
4655
+ },
4656
+ };
4657
+
4658
+ export const ProposalReasonBodySchema: JsonSchema = {
4659
+ type: 'object',
4660
+ additionalProperties: false,
4661
+ properties: {
4662
+ reason: { type: 'string', minLength: 1, maxLength: 2000 },
4663
+ },
4664
+ };
4665
+
4666
+ export const WithdrawProposalBodySchema: JsonSchema = {
4667
+ type: 'object',
4668
+ additionalProperties: false,
4669
+ required: ['reason'],
4670
+ properties: {
4671
+ reason: { type: 'string', minLength: 1, maxLength: 2000 },
4672
+ },
4673
+ };
4674
+
4675
+ // ---------------- provenance ----------------
3618
4676
 
3619
4677
  export const ProvenanceNodeKindSchema: JsonSchema = {
3620
4678
  type: 'string',
@@ -3783,16 +4841,11 @@ export const ProvenanceCollectionPageSchema: JsonSchema = {
3783
4841
  };
3784
4842
 
3785
4843
  export const ExportProvenanceBodySchema: JsonSchema = {
4844
+ description: 'Optional: no body signs with the active key.',
3786
4845
  type: 'object',
3787
4846
  additionalProperties: false,
3788
- required: ['signingKeyId'],
3789
4847
  properties: {
3790
- signingKeyId: {
3791
- type: 'string',
3792
- minLength: 1,
3793
- description:
3794
- 'The `SigningKeyId` the deployment plugs into its `signingKey` binding. Server looks up the private key via `signingKey.getPrivateKey(signingKeyId)` — 404 if unknown.',
3795
- },
4848
+ signingKeyId: SIGNING_KEY_ID_PROPERTY,
3796
4849
  includeMessages: {
3797
4850
  type: 'boolean',
3798
4851
  description:
@@ -3802,53 +4855,14 @@ export const ExportProvenanceBodySchema: JsonSchema = {
3802
4855
  },
3803
4856
  };
3804
4857
 
3805
- export const ExportProvenanceResultSchema: JsonSchema = {
4858
+ export const ExportProvenanceResultSchema: JsonSchema = signedExportEnvelope({
3806
4859
  description:
3807
- 'Signed exportable bundle. `bundle` is base64 of the exact bytes that were signed (sorted-key canonical JSON, no whitespace); verifiers can pass those bytes directly to `verifyEd25519`. The bundle body itself includes `bundleSchemaVersion`, `runId`, `tenantId`, `dag: { nodes, edges }`, `messages?` (if requested), `callUsage?` (the usage of the model calls, from the cost ledger), etc. See `canonicalization` for the deterministic serialization algorithm.',
3808
- type: 'object',
3809
- additionalProperties: false,
3810
- required: [
3811
- 'runId',
3812
- 'bundle',
3813
- 'bundleSchemaVersion',
3814
- 'algorithm',
3815
- 'signingKeyId',
3816
- 'signature',
3817
- 'publicKey',
3818
- 'canonicalization',
3819
- 'exportedAt',
3820
- ],
3821
- properties: {
3822
- runId: { type: 'string', format: 'uuid' },
3823
- bundle: {
3824
- type: 'string',
3825
- description: 'Base64-encoded canonical JSON of the bundle body.',
3826
- },
3827
- bundleSchemaVersion: {
3828
- type: 'string',
3829
- description:
3830
- "Semver for the shape of the bundle body. Currently `1.1.0`, which adds `callUsage`: each model call's usage from the cost ledger, by call id, as it stood when signed.",
3831
- },
3832
- algorithm: { type: 'string', const: 'ed25519' },
3833
- signingKeyId: { type: 'string' },
3834
- signature: {
3835
- type: 'string',
3836
- description: 'Base64-encoded Ed25519 signature bytes over `bundle` (after base64-decode).',
3837
- },
3838
- publicKey: {
3839
- type: 'string',
3840
- description:
3841
- 'PEM-encoded Ed25519 public key (DER SPKI envelope). Callers can pass this straight into `parsePublicKeyPem` for verification.',
3842
- },
3843
- canonicalization: {
3844
- type: 'string',
3845
- const: 'sorted-key-json',
3846
- description:
3847
- 'Canonicalization algorithm — sorted-key JSON, no whitespace. Same algorithm as `canonicalize`.',
3848
- },
3849
- exportedAt: { type: 'string', format: 'date-time' },
3850
- },
3851
- };
4860
+ "A run's signed provenance. Body: `{ bundleSchemaVersion, provenanceId, runId, tenantId, version, createdAt, flowRef?, dag: { nodes, edges }, messages?, callUsage?, exportedAt }`; `callUsage` is each model call's usage from the cost ledger, as it stood when signed.",
4861
+ kind: 'provenance',
4862
+ subject: ['runId', { type: 'string', format: 'uuid' }],
4863
+ versionDescription:
4864
+ "The body's version, semver. `1.2.0` adds `exportedAt` to the signed body; `1.1.0` added `callUsage`.",
4865
+ });
3852
4866
 
3853
4867
  // ---------------- registry (exported to the generator) ----------------
3854
4868
 
@@ -3888,6 +4902,15 @@ export const BlobMetaSchema: JsonSchema = {
3888
4902
  format: 'uuid',
3889
4903
  description: 'Optional back-ref to the RunId that produced this blob.',
3890
4904
  },
4905
+ projectId: {
4906
+ type: 'string',
4907
+ description:
4908
+ "The project the artifact belongs to: its owner run's, else the upload's `projectId`, else the tenant's default project. Reading it needs `read` there; deleting it, `write`. Absent on blobs stored before projects were recorded.",
4909
+ },
4910
+ createdBy: {
4911
+ type: 'string',
4912
+ description: 'Who uploaded it: `user:<id>` or `service_account:<id>`.',
4913
+ },
3891
4914
  createdAt: { type: 'string', format: 'date-time' },
3892
4915
  },
3893
4916
  };
@@ -3917,6 +4940,11 @@ export const UploadArtifactBodySchema: JsonSchema = {
3917
4940
  description: 'JSON-encoded `Record<string, string>` — parsed server-side.',
3918
4941
  },
3919
4942
  ownerRunId: { type: 'string', format: 'uuid' },
4943
+ projectId: {
4944
+ type: 'string',
4945
+ description:
4946
+ "The project it belongs to, when there's no `ownerRunId` (with one, the run's project, and this must agree). Default: the tenant's default project.",
4947
+ },
3920
4948
  expectedHash: {
3921
4949
  type: 'string',
3922
4950
  pattern: '^[0-9a-f]{64}$',
@@ -3999,6 +5027,23 @@ export const CapabilityDescriptorSchema: JsonSchema = {
3999
5027
  description:
4000
5028
  'Optional JSON Schema fragment describing the parameters an agent may attach to `{ feature, params }` in a `Requirement`.',
4001
5029
  },
5030
+ providers: {
5031
+ type: 'array',
5032
+ items: { $ref: '#/components/schemas/CapabilityProvider' },
5033
+ description:
5034
+ "The tenant's registered providers with a model that has the feature, and those models. Absent from servers that don't read the provider registry; `[]` when no provider of the tenant has one.",
5035
+ },
5036
+ },
5037
+ };
5038
+
5039
+ export const CapabilityProviderSchema: JsonSchema = {
5040
+ type: 'object',
5041
+ additionalProperties: false,
5042
+ required: ['providerId', 'models'],
5043
+ description: 'A provider of the tenant with a model that has the feature.',
5044
+ properties: {
5045
+ providerId: { type: 'string' },
5046
+ models: { type: 'array', items: { type: 'string' }, description: 'Its models that have it.' },
4002
5047
  },
4003
5048
  };
4004
5049
 
@@ -4220,6 +5265,11 @@ export const RegisterProviderBodySchema: JsonSchema = {
4220
5265
  description:
4221
5266
  "The adapter's connection settings: flat, non-secret values (a cloud project, a base URL). Each adapter documents its keys. Credentials go in `secret_ref`, never here.",
4222
5267
  },
5268
+ send_traceparent: {
5269
+ type: 'boolean',
5270
+ description:
5271
+ "Send each model call's W3C `traceparent` to this provider, as a request header, so its request logs can be matched to the run. Ids only, never content. Default `false`: nothing about a run's trace leaves the deployment unless a registration opts in. The runtime enforces it; an older runtime ignores the field and sends none.",
5272
+ },
4223
5273
  },
4224
5274
  };
4225
5275
 
@@ -4242,6 +5292,47 @@ export const UnregisterProviderResultSchema: JsonSchema = {
4242
5292
  },
4243
5293
  };
4244
5294
 
5295
+ /**
5296
+ * One thing an adapter's check finds wrong with a provider registration,
5297
+ * in the shape of the API's validation issues.
5298
+ */
5299
+ export const AdapterConfigProblemSchema: JsonSchema = {
5300
+ type: 'object',
5301
+ additionalProperties: false,
5302
+ required: ['path', 'message'],
5303
+ properties: {
5304
+ path: {
5305
+ type: 'string',
5306
+ description:
5307
+ 'The setting at fault, as a JSON pointer into the registration: `/adapter_config/<key>`, `/secret_ref`, `/metadata/region`, `/metadata/models/<i>/name`, or `/adapter_id` (an adapter this runtime does not have).',
5308
+ },
5309
+ message: {
5310
+ type: 'string',
5311
+ description:
5312
+ "What's wrong with that setting and what it takes (e.g. `adapter_config.api must be one of responses, chat-completions.`). The error's `message` names the provider and its adapter.",
5313
+ },
5314
+ },
5315
+ };
5316
+
5317
+ export const ProviderCheckResultSchema: JsonSchema = {
5318
+ type: 'object',
5319
+ additionalProperties: false,
5320
+ required: ['providerId', 'adapterId', 'checked', 'issues'],
5321
+ properties: {
5322
+ providerId: { type: 'string' },
5323
+ adapterId: { type: 'string' },
5324
+ checked: {
5325
+ type: 'boolean',
5326
+ description:
5327
+ "False when this runtime has no check for the provider's adapter; `issues` is then empty.",
5328
+ },
5329
+ issues: {
5330
+ type: 'array',
5331
+ items: { $ref: '#/components/schemas/AdapterConfigProblem' },
5332
+ },
5333
+ },
5334
+ };
5335
+
4245
5336
  export const ProviderCapabilitiesResultSchema: JsonSchema = {
4246
5337
  type: 'object',
4247
5338
  additionalProperties: false,
@@ -4353,6 +5444,11 @@ export const MCPEndpointSchema: JsonSchema = {
4353
5444
  additionalProperties: true,
4354
5445
  description: 'Optional caller-defined metadata bag.',
4355
5446
  },
5447
+ sendTraceparent: {
5448
+ type: 'boolean',
5449
+ description:
5450
+ "Send the W3C `traceparent` of the run calling a tool to this endpoint, as a request header, so the server's logs can be matched to the run. Ids only, never content. Default `false`. HTTP transports only: `true` on a `stdio` endpoint is refused (`invalid-mcp-endpoint`, reason `invalid-send-traceparent`). An older runtime ignores it and sends none.",
5451
+ },
4356
5452
  },
4357
5453
  };
4358
5454
 
@@ -5040,6 +6136,8 @@ export const ReinstatePolicyVersionResultSchema: JsonSchema = {
5040
6136
  export const RetentionDomainSchema: JsonSchema = {
5041
6137
  type: 'string',
5042
6138
  enum: [...RETENTION_DOMAINS],
6139
+ description:
6140
+ "The kind of record a retention policy covers. `*` covers every domain without a policy of its own, except `memory` and `conversation`: they hold people's words, so only a policy naming them purges them.",
5043
6141
  };
5044
6142
 
5045
6143
  /**
@@ -5517,6 +6615,43 @@ export const EvalBaselineSchema: JsonSchema = {
5517
6615
  ],
5518
6616
  };
5519
6617
 
6618
+ export const EvalOverridesSchema: JsonSchema = {
6619
+ type: 'object',
6620
+ additionalProperties: false,
6621
+ description:
6622
+ "For an agent candidate: block content its replays run instead of the version's pinned content (an improvement pass's search). `settings`: values by settings block id, each a block the version pins, satisfying its schema. `prompts`: a template for the prompt block the version pins, which reads and names only what the agent has (its parameters, the variables the current template reads, the settings blocks it pins, its tools' and blocks' ids) and is at most twice as long. Anything else is `400 validation-failed`. A comparison with overrides can't gate a promotion.",
6623
+ properties: {
6624
+ settings: {
6625
+ type: 'object',
6626
+ maxProperties: 20,
6627
+ additionalProperties: { type: 'object', additionalProperties: true },
6628
+ },
6629
+ prompts: {
6630
+ type: 'object',
6631
+ maxProperties: 1,
6632
+ additionalProperties: {
6633
+ type: 'object',
6634
+ additionalProperties: false,
6635
+ required: ['template'],
6636
+ properties: { template: { type: 'string' } },
6637
+ },
6638
+ },
6639
+ },
6640
+ };
6641
+
6642
+ export const EvalSampleSchema: JsonSchema = {
6643
+ type: 'object',
6644
+ additionalProperties: false,
6645
+ required: ['part', 'seed', 'holdOutShare'],
6646
+ description:
6647
+ 'Only part of the test set\'s cases: split once into a hold-out part (about `holdOutShare` of them) and a search part (the rest), stratified by judgment (the cases with a "no" and the others are split on their own, a stratum of two or more giving each part at least one), in the order of a hash of each case id and `seed`. The same seed always splits the same test set the same way. A promotion gate refuses a comparison on the search part (`comparison.sample`).',
6648
+ properties: {
6649
+ part: { type: 'string', enum: ['search', 'hold-out'] },
6650
+ seed: { type: 'string', minLength: 1, maxLength: 200 },
6651
+ holdOutShare: { type: 'number', minimum: 0.1, maximum: 0.9 },
6652
+ },
6653
+ };
6654
+
5520
6655
  export const EvalComparisonSchema: JsonSchema = {
5521
6656
  type: 'object',
5522
6657
  additionalProperties: false,
@@ -5539,6 +6674,8 @@ export const EvalComparisonSchema: JsonSchema = {
5539
6674
  description:
5540
6675
  "Which judgments count: each at its class's weight (`as-recorded`, the default), or only those recorded while their class was restricted (`Judgment.restricted`), the others weighing 0 (`restricted-only`).",
5541
6676
  },
6677
+ overrides: { $ref: '#/components/schemas/EvalOverrides' },
6678
+ sample: { $ref: '#/components/schemas/EvalSample' },
5542
6679
  },
5543
6680
  };
5544
6681
 
@@ -5599,6 +6736,16 @@ export const ComparisonCandidateSchema: JsonSchema = {
5599
6736
  description:
5600
6737
  "The version's pinsDigest: what it ran, as a promotion gate checks. Absent for a version published before pins, and from a comparison recorded before it.",
5601
6738
  },
6739
+ overrides: {
6740
+ type: 'object',
6741
+ additionalProperties: false,
6742
+ description:
6743
+ "The blocks whose content the replays replaced (`overrides`): no published version ran, so it can't gate a promotion. Absent otherwise.",
6744
+ properties: {
6745
+ settings: { type: 'array', items: { type: 'string' } },
6746
+ prompts: { type: 'array', items: { type: 'string' } },
6747
+ },
6748
+ },
5602
6749
  },
5603
6750
  },
5604
6751
  {
@@ -5707,6 +6854,12 @@ export const JudgedComparisonSummarySchema: JsonSchema = {
5707
6854
  description: 'Tool calls refused across the cases (what the candidate would have done).',
5708
6855
  },
5709
6856
  errors: { type: 'integer', minimum: 0, description: 'Cases none of whose repetitions ran.' },
6857
+ erased: {
6858
+ type: 'integer',
6859
+ minimum: 1,
6860
+ description:
6861
+ "Cases an erasure cleared (a person's words were erased): left out of the run and the metrics. Absent: none.",
6862
+ },
5710
6863
  stopped: {
5711
6864
  type: 'integer',
5712
6865
  minimum: 0,
@@ -5720,6 +6873,10 @@ export const JudgedComparisonSummarySchema: JsonSchema = {
5720
6873
  description:
5721
6874
  'Which judgments counted. Absent from a comparison recorded before restricted classes: `as-recorded`.',
5722
6875
  },
6876
+ sample: {
6877
+ $ref: '#/components/schemas/EvalSample',
6878
+ description: 'The part of the test set it ran. Absent: every case.',
6879
+ },
5723
6880
  sampling: {
5724
6881
  type: 'object',
5725
6882
  additionalProperties: false,
@@ -5857,7 +7014,12 @@ export const ComparisonCaseResultSchema: JsonSchema = {
5857
7014
  toolVersion: { type: 'string' },
5858
7015
  arguments: {},
5859
7016
  source: { type: 'string', enum: ['live', 'recorded', 'refused'] },
5860
- reason: { type: 'string' },
7017
+ recomputed: {
7018
+ type: 'boolean',
7019
+ description:
7020
+ "With `source: 'live'`: the call ran again from the same arguments because the compared version pins other settings, and the tool reads from nowhere, so it didn't diverge. Absent from older servers, and otherwise.",
7021
+ },
7022
+ reason: { type: 'string' },
5861
7023
  },
5862
7024
  },
5863
7025
  },
@@ -5957,6 +7119,8 @@ export const StartEvalRunBodySchema: JsonSchema = {
5957
7119
  description:
5958
7120
  "Which judgments count: each at its class's weight (`as-recorded`, the default), or only those recorded while their class was restricted (`Judgment.restricted`), the others weighing 0 (`restricted-only`).",
5959
7121
  },
7122
+ overrides: { $ref: '#/components/schemas/EvalOverrides' },
7123
+ sample: { $ref: '#/components/schemas/EvalSample' },
5960
7124
  },
5961
7125
  description:
5962
7126
  "Exactly one of `agentRef` or `flowRef` MUST be supplied. `dryRun: true` returns a plan preview without invoking the subject. For a `judged` suite (a test set), the run is a comparison: `agentRef` or `flowRef` with its `version` is the candidate, replayed on each case without doing anything the past run didn't (a flow stops at a write the replay refuses); `baseline` (default `'recorded'`), `reads` (default `recorded`), `repetitions` (default 1) and `k` (default 10) set how. With `flowRef`, `versions` runs the flow with some of its agents or tools at other versions; an id the flow doesn't use, or a version that isn't published, is refused (`400 validation-failed`, each under `details.issues`).",
@@ -5976,7 +7140,9 @@ export const StartEvalRunResultSchema: JsonSchema = {
5976
7140
 
5977
7141
  export const IdentityProviderKindSchema: JsonSchema = {
5978
7142
  type: 'string',
5979
- enum: ['oauth2', 'oidc'],
7143
+ enum: ['oauth2', 'oidc', 'saml'],
7144
+ description:
7145
+ "`oidc`: an OpenID Connect identity provider people sign in with (Okta, Entra ID, Google, Keycloak…); its endpoints come from its discovery document. `saml`: a SAML 2.0 identity provider people sign in with. `oauth2`: a plain OAuth 2.0 provider that isn't OpenID Connect (e.g. GitHub), with its endpoints given; pick `oidc` for any provider that speaks OpenID Connect.",
5980
7146
  };
5981
7147
 
5982
7148
  export const ClaimMappingScopesSpecSchema: JsonSchema = {
@@ -6005,9 +7171,144 @@ export const ClaimMappingSpecSchema: JsonSchema = {
6005
7171
  },
6006
7172
  };
6007
7173
 
6008
- export const IdentityProviderConfigSchema: JsonSchema = {
7174
+ const IDENTITY_PROVIDER_BASE_PROPERTIES = {
7175
+ providerId: { type: 'string', minLength: 1 },
7176
+ displayName: {
7177
+ type: 'string',
7178
+ minLength: 1,
7179
+ description: 'The name a sign-in page shows ("Sign in with …"). Default: `providerId`.',
7180
+ },
7181
+ domains: {
7182
+ type: 'array',
7183
+ items: { type: 'string', minLength: 1 },
7184
+ description:
7185
+ 'The email domains whose people sign in with this provider (lowercase, e.g. `acme.com`): how an email-first sign-in page finds it.',
7186
+ },
7187
+ join: {
7188
+ type: 'string',
7189
+ enum: ['invite', 'domain'],
7190
+ description:
7191
+ 'Who may sign in the first time: `invite` (default) only people a tenant admin added; `domain` also anyone from one of `domains`, once the deployment has verified them.',
7192
+ },
7193
+ signIn: { $ref: '#/components/schemas/IdentityProviderSignIn' },
7194
+ metadata: { type: 'object', additionalProperties: true },
7195
+ } as const;
7196
+
7197
+ const CLIENT_SECRET_REF = {
7198
+ type: 'string',
7199
+ minLength: 1,
7200
+ description: 'Opaque reference resolved server-side. Never a plaintext secret.',
7201
+ } as const;
7202
+
7203
+ const ALLOWED_REDIRECT_URIS = {
7204
+ type: 'array',
7205
+ items: { type: 'string', minLength: 1 },
7206
+ description:
7207
+ 'OAuth 2.1 BCP redirect-URI allowlist. Exact-string match required at /v1/auth/login. Absent/empty means no redirect-URI allowlist check (pass-through).',
7208
+ } as const;
7209
+
7210
+ export const IdentityProviderSignInSchema: JsonSchema = {
7211
+ description:
7212
+ 'What to give the identity provider so it can send people back: set by the deployment on what it returns, ignored on registration. OIDC / OAuth 2.0: `redirectUri`. SAML: `spEntityId`, `acsUrl`, `spMetadataUrl`.',
7213
+ oneOf: [
7214
+ {
7215
+ type: 'object',
7216
+ additionalProperties: false,
7217
+ required: ['redirectUri'],
7218
+ properties: { redirectUri: { type: 'string', format: 'uri' } },
7219
+ },
7220
+ {
7221
+ type: 'object',
7222
+ additionalProperties: false,
7223
+ required: ['spEntityId', 'acsUrl', 'spMetadataUrl'],
7224
+ properties: {
7225
+ spEntityId: { type: 'string', minLength: 1 },
7226
+ acsUrl: { type: 'string', format: 'uri' },
7227
+ spMetadataUrl: { type: 'string', format: 'uri' },
7228
+ },
7229
+ },
7230
+ ],
7231
+ };
7232
+
7233
+ export const OidcIdentityProviderConfigSchema: JsonSchema = {
7234
+ description:
7235
+ "An OpenID Connect identity provider people sign in with. The endpoints come from the issuer's discovery document when absent, and are returned once the deployment has them.",
7236
+ type: 'object',
7237
+ additionalProperties: false,
7238
+ required: ['providerId', 'kind', 'issuer', 'clientId', 'clientSecretRef'],
7239
+ properties: {
7240
+ ...IDENTITY_PROVIDER_BASE_PROPERTIES,
7241
+ kind: { type: 'string', const: 'oidc' },
7242
+ issuer: { type: 'string', format: 'uri' },
7243
+ clientId: { type: 'string', minLength: 1 },
7244
+ clientSecretRef: CLIENT_SECRET_REF,
7245
+ scopes: {
7246
+ type: 'array',
7247
+ items: { type: 'string' },
7248
+ description: 'Default `openid email profile`.',
7249
+ },
7250
+ authorizationEndpoint: { type: 'string', format: 'uri' },
7251
+ tokenEndpoint: { type: 'string', format: 'uri' },
7252
+ userinfoEndpoint: { type: 'string', format: 'uri' },
7253
+ jwksEndpoint: { type: 'string', format: 'uri' },
7254
+ allowedRedirectUris: ALLOWED_REDIRECT_URIS,
7255
+ claimMapping: { $ref: '#/components/schemas/ClaimMappingSpec' },
7256
+ },
7257
+ };
7258
+
7259
+ export const SamlIdentityProviderConfigSchema: JsonSchema = {
6009
7260
  description:
6010
- 'OAuth 2.0 / OIDC provider configuration registered on a tenant. `clientSecretRef` is a REFERENCE resolved server-side (env-var key, secrets-manager path, KMS handle) — the plaintext client secret never crosses the wire.',
7261
+ 'A SAML 2.0 identity provider people sign in with: its metadata XML, or its entity ID, single sign-on URL and signing certificates. Keys are given as references, never as keys.',
7262
+ type: 'object',
7263
+ additionalProperties: false,
7264
+ required: ['providerId', 'kind'],
7265
+ properties: {
7266
+ ...IDENTITY_PROVIDER_BASE_PROPERTIES,
7267
+ kind: { type: 'string', const: 'saml' },
7268
+ idpMetadataXml: { type: 'string', minLength: 1 },
7269
+ idpEntityId: { type: 'string', minLength: 1 },
7270
+ idpSsoUrl: {
7271
+ type: 'string',
7272
+ format: 'uri',
7273
+ description: "The IdP's single sign-on URL (HTTP-Redirect binding).",
7274
+ },
7275
+ idpCertificates: {
7276
+ type: 'array',
7277
+ items: { type: 'string', minLength: 1 },
7278
+ description: "The IdP's signing certificates (PEM); several during a rollover.",
7279
+ },
7280
+ spSigningKeyRef: {
7281
+ type: 'string',
7282
+ minLength: 1,
7283
+ description:
7284
+ "Opaque reference to the service provider's signing key, for IdPs that require signed AuthnRequests. Never a plaintext key.",
7285
+ },
7286
+ spDecryptionKeyRef: {
7287
+ type: 'string',
7288
+ minLength: 1,
7289
+ description:
7290
+ 'Opaque reference to the key that decrypts encrypted assertions. Never a plaintext key.',
7291
+ },
7292
+ wantAssertionsSigned: {
7293
+ type: 'boolean',
7294
+ description: 'Require signed assertions. Default `true`.',
7295
+ },
7296
+ attributeMapping: {
7297
+ type: 'object',
7298
+ additionalProperties: false,
7299
+ description: 'Assertion attribute names. Defaults: `userId` = the NameID, `email` = `email`.',
7300
+ properties: {
7301
+ userId: { type: 'string', minLength: 1 },
7302
+ email: { type: 'string', minLength: 1 },
7303
+ displayName: { type: 'string', minLength: 1 },
7304
+ },
7305
+ },
7306
+ },
7307
+ };
7308
+
7309
+ export const OAuth2IdentityProviderConfigSchema: JsonSchema = {
7310
+ description:
7311
+ "A plain OAuth 2.0 provider that isn't OpenID Connect (e.g. GitHub), run by this API's own OAuth flow (`/v1/auth/login` + callback). For a provider that speaks OpenID Connect, use `oidc`.",
6011
7312
  type: 'object',
6012
7313
  additionalProperties: false,
6013
7314
  required: [
@@ -6020,26 +7321,75 @@ export const IdentityProviderConfigSchema: JsonSchema = {
6020
7321
  'scopes',
6021
7322
  ],
6022
7323
  properties: {
6023
- providerId: { type: 'string', minLength: 1 },
6024
- kind: IdentityProviderKindSchema,
7324
+ ...IDENTITY_PROVIDER_BASE_PROPERTIES,
7325
+ kind: { type: 'string', const: 'oauth2' },
6025
7326
  clientId: { type: 'string', minLength: 1 },
6026
- clientSecretRef: {
6027
- type: 'string',
6028
- minLength: 1,
6029
- description: 'Opaque reference resolved server-side. Never a plaintext secret.',
6030
- },
7327
+ clientSecretRef: CLIENT_SECRET_REF,
6031
7328
  authorizationEndpoint: { type: 'string', format: 'uri' },
6032
7329
  tokenEndpoint: { type: 'string', format: 'uri' },
6033
7330
  userinfoEndpoint: { type: 'string', format: 'uri' },
6034
7331
  scopes: { type: 'array', items: { type: 'string' } },
6035
- allowedRedirectUris: {
6036
- type: 'array',
6037
- items: { type: 'string', minLength: 1 },
6038
- description:
6039
- 'OAuth 2.1 BCP redirect-URI allowlist. Exact-string match required at /v1/auth/login. Absent/empty means no redirect-URI allowlist check (pass-through).',
6040
- },
7332
+ allowedRedirectUris: ALLOWED_REDIRECT_URIS,
6041
7333
  claimMapping: { $ref: '#/components/schemas/ClaimMappingSpec' },
6042
- metadata: { type: 'object', additionalProperties: true },
7334
+ },
7335
+ };
7336
+
7337
+ export const IdentityProviderConfigSchema: JsonSchema = {
7338
+ description:
7339
+ 'An identity provider registered on a tenant, one shape per `kind` (narrow on `kind` before reading kind-specific fields). Secrets are always REFERENCES resolved server-side (`clientSecretRef`, `spSigningKeyRef`, `spDecryptionKeyRef`); a plaintext secret never crosses the wire, and a `clientSecret` field is refused.',
7340
+ oneOf: [
7341
+ { $ref: '#/components/schemas/OidcIdentityProviderConfig' },
7342
+ { $ref: '#/components/schemas/SamlIdentityProviderConfig' },
7343
+ { $ref: '#/components/schemas/OAuth2IdentityProviderConfig' },
7344
+ ],
7345
+ discriminator: {
7346
+ propertyName: 'kind',
7347
+ mapping: {
7348
+ oidc: '#/components/schemas/OidcIdentityProviderConfig',
7349
+ saml: '#/components/schemas/SamlIdentityProviderConfig',
7350
+ oauth2: '#/components/schemas/OAuth2IdentityProviderConfig',
7351
+ },
7352
+ },
7353
+ };
7354
+
7355
+ // Its own schema, used only as the request body: a union that other
7356
+ // schemas also name gets inlined away by the Python generator, so a body
7357
+ // naming `IdentityProviderConfig` would fail at call time (the same as
7358
+ // `ServiceAccountGrantBody`).
7359
+ export const RegisterIdentityProviderBodySchema: JsonSchema = {
7360
+ description:
7361
+ 'The identity provider to register, one shape per `kind`: `oidc`, `saml` or `oauth2`. Secrets by reference only (`clientSecretRef`, `spSigningKeyRef`, `spDecryptionKeyRef`); a `clientSecret` field is refused.',
7362
+ oneOf: [
7363
+ { $ref: '#/components/schemas/OidcIdentityProviderConfig' },
7364
+ { $ref: '#/components/schemas/SamlIdentityProviderConfig' },
7365
+ { $ref: '#/components/schemas/OAuth2IdentityProviderConfig' },
7366
+ ],
7367
+ discriminator: {
7368
+ propertyName: 'kind',
7369
+ mapping: {
7370
+ oidc: '#/components/schemas/OidcIdentityProviderConfig',
7371
+ saml: '#/components/schemas/SamlIdentityProviderConfig',
7372
+ oauth2: '#/components/schemas/OAuth2IdentityProviderConfig',
7373
+ },
7374
+ },
7375
+ };
7376
+
7377
+ // Its own schema too, used only as the answer (see `RegisterIdentityProviderBody`).
7378
+ export const GetIdentityProviderResultSchema: JsonSchema = {
7379
+ description:
7380
+ 'An identity provider as stored, one shape per `kind`, with `signIn` when the deployment sets it. Secrets appear only as references.',
7381
+ oneOf: [
7382
+ { $ref: '#/components/schemas/OidcIdentityProviderConfig' },
7383
+ { $ref: '#/components/schemas/SamlIdentityProviderConfig' },
7384
+ { $ref: '#/components/schemas/OAuth2IdentityProviderConfig' },
7385
+ ],
7386
+ discriminator: {
7387
+ propertyName: 'kind',
7388
+ mapping: {
7389
+ oidc: '#/components/schemas/OidcIdentityProviderConfig',
7390
+ saml: '#/components/schemas/SamlIdentityProviderConfig',
7391
+ oauth2: '#/components/schemas/OAuth2IdentityProviderConfig',
7392
+ },
6043
7393
  },
6044
7394
  };
6045
7395
 
@@ -6056,12 +7406,88 @@ export const IdentityProviderCollectionPageSchema: JsonSchema = {
6056
7406
  },
6057
7407
  };
6058
7408
 
7409
+ export const SignInOptionSchema: JsonSchema = {
7410
+ description: 'One way to sign in, as a sign-in page shows it.',
7411
+ type: 'object',
7412
+ additionalProperties: false,
7413
+ required: ['providerId', 'displayName', 'signInUrl'],
7414
+ properties: {
7415
+ providerId: { type: 'string', minLength: 1 },
7416
+ displayName: { type: 'string', minLength: 1, description: '"Sign in with …".' },
7417
+ signInUrl: {
7418
+ type: 'string',
7419
+ description: 'Where the browser goes to start signing in with this provider.',
7420
+ },
7421
+ owner: {
7422
+ type: 'string',
7423
+ enum: ['tenant', 'deployment'],
7424
+ description:
7425
+ 'Whose it is: a workspace\'s own identity provider (`tenant`), or one the deployment offers everyone it has added ("Continue with Google", `deployment`). A sign-in page shows a workspace\'s own first. Absent: `tenant`.',
7426
+ },
7427
+ },
7428
+ };
7429
+
7430
+ export const SignInOptionsSchema: JsonSchema = {
7431
+ type: 'object',
7432
+ additionalProperties: false,
7433
+ required: ['data'],
7434
+ properties: {
7435
+ data: { type: 'array', items: { $ref: '#/components/schemas/SignInOption' } },
7436
+ methods: {
7437
+ type: 'object',
7438
+ additionalProperties: false,
7439
+ required: ['identityProviders', 'apiToken'],
7440
+ description:
7441
+ 'The ways in this deployment allows, for a sign-in page to show. Absent from older servers.',
7442
+ properties: {
7443
+ identityProviders: {
7444
+ type: 'boolean',
7445
+ description: "Sign-in with an organization's identity provider (email first).",
7446
+ },
7447
+ apiToken: {
7448
+ type: 'boolean',
7449
+ description: 'Sign-in to the console with an API token (`POST /v1/auth/token-sign-in`).',
7450
+ },
7451
+ emailLink: {
7452
+ type: 'object',
7453
+ additionalProperties: false,
7454
+ description:
7455
+ 'Present when the deployment emails sign-in links: a sign-in page offers "Email me a sign-in link". With `captchaSiteKey`, the request needs a Cloudflare Turnstile token (`x-captcha-response`).',
7456
+ properties: {
7457
+ captchaSiteKey: { type: 'string', minLength: 1 },
7458
+ },
7459
+ },
7460
+ },
7461
+ },
7462
+ },
7463
+ };
7464
+
7465
+ export const TokenSignInResultSchema: JsonSchema = {
7466
+ type: 'object',
7467
+ additionalProperties: false,
7468
+ required: ['userId', 'expiresAt'],
7469
+ properties: {
7470
+ userId: { type: 'string', minLength: 1, description: 'The person now signed in.' },
7471
+ expiresAt: {
7472
+ type: 'string',
7473
+ format: 'date-time',
7474
+ description:
7475
+ "When the session ends at the latest: its lifetime, or the key's expiry if sooner.",
7476
+ },
7477
+ },
7478
+ };
7479
+
6059
7480
  export const RegisterIdentityProviderResultSchema: JsonSchema = {
6060
7481
  type: 'object',
6061
7482
  additionalProperties: false,
6062
7483
  required: ['providerId'],
6063
7484
  properties: {
6064
7485
  providerId: { type: 'string', minLength: 1 },
7486
+ provider: {
7487
+ $ref: '#/components/schemas/IdentityProviderConfig',
7488
+ description:
7489
+ 'The provider as stored: discovered endpoints, and `signIn` (what to give the identity provider). Absent from older servers.',
7490
+ },
6065
7491
  },
6066
7492
  };
6067
7493
 
@@ -6075,6 +7501,91 @@ export const UnregisterIdentityProviderResultSchema: JsonSchema = {
6075
7501
  },
6076
7502
  };
6077
7503
 
7504
+ const NULLABLE_STRING = { type: ['string', 'null'], minLength: 1 } as const;
7505
+ const NULLABLE_URI = { type: ['string', 'null'], format: 'uri' } as const;
7506
+ const NULLABLE_STRINGS = {
7507
+ oneOf: [{ type: 'array', items: { type: 'string', minLength: 1 } }, { type: 'null' }],
7508
+ } as const;
7509
+
7510
+ export const UpdateIdentityProviderBodySchema: JsonSchema = {
7511
+ description:
7512
+ "Changes to a registered identity provider: a field given replaces the stored one, `null` removes an optional one, and anything not given stays. The result must still be a whole provider of its `kind` (the fields `IdentityProviderConfig` requires for it), checked as a registration is. `providerId` and `kind` can't change; `signIn` is the deployment's and is ignored. A new `issuer` drops the endpoints discovered from the old one.",
7513
+ type: 'object',
7514
+ additionalProperties: false,
7515
+ minProperties: 1,
7516
+ properties: {
7517
+ providerId: { type: 'string', minLength: 1, description: 'Must match the path when given.' },
7518
+ kind: { $ref: '#/components/schemas/IdentityProviderKind' },
7519
+ displayName: NULLABLE_STRING,
7520
+ domains: NULLABLE_STRINGS,
7521
+ join: { oneOf: [{ type: 'string', enum: ['invite', 'domain'] }, { type: 'null' }] },
7522
+ metadata: { oneOf: [{ type: 'object', additionalProperties: true }, { type: 'null' }] },
7523
+ issuer: { type: 'string', format: 'uri' },
7524
+ clientId: { type: 'string', minLength: 1 },
7525
+ clientSecretRef: CLIENT_SECRET_REF,
7526
+ scopes: { oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'null' }] },
7527
+ authorizationEndpoint: NULLABLE_URI,
7528
+ tokenEndpoint: NULLABLE_URI,
7529
+ userinfoEndpoint: NULLABLE_URI,
7530
+ jwksEndpoint: NULLABLE_URI,
7531
+ allowedRedirectUris: NULLABLE_STRINGS,
7532
+ claimMapping: {
7533
+ oneOf: [{ $ref: '#/components/schemas/ClaimMappingSpec' }, { type: 'null' }],
7534
+ },
7535
+ idpMetadataXml: NULLABLE_STRING,
7536
+ idpEntityId: NULLABLE_STRING,
7537
+ idpSsoUrl: NULLABLE_URI,
7538
+ idpCertificates: NULLABLE_STRINGS,
7539
+ spSigningKeyRef: NULLABLE_STRING,
7540
+ spDecryptionKeyRef: NULLABLE_STRING,
7541
+ wantAssertionsSigned: { type: ['boolean', 'null'] },
7542
+ attributeMapping: {
7543
+ oneOf: [
7544
+ {
7545
+ type: 'object',
7546
+ additionalProperties: false,
7547
+ properties: {
7548
+ userId: { type: 'string', minLength: 1 },
7549
+ email: { type: 'string', minLength: 1 },
7550
+ displayName: { type: 'string', minLength: 1 },
7551
+ },
7552
+ },
7553
+ { type: 'null' },
7554
+ ],
7555
+ },
7556
+ },
7557
+ };
7558
+
7559
+ export const UpdateIdentityProviderResultSchema: JsonSchema = {
7560
+ type: 'object',
7561
+ additionalProperties: false,
7562
+ required: ['providerId', 'provider'],
7563
+ properties: {
7564
+ providerId: { type: 'string', minLength: 1 },
7565
+ provider: {
7566
+ $ref: '#/components/schemas/IdentityProviderConfig',
7567
+ description: 'The provider as stored now; its `signIn` is unchanged.',
7568
+ },
7569
+ },
7570
+ };
7571
+
7572
+ export const IdentityProviderSignInUrlsSchema: JsonSchema = {
7573
+ description:
7574
+ "What to give the identity provider so it can send people back, for a provider under this `providerId`: the same before it's registered, after, and after an unregister and a new registration, so the identity provider's side can be set up first. Not secrets: they're in every sign-in's browser redirects.",
7575
+ type: 'object',
7576
+ additionalProperties: false,
7577
+ required: ['providerId', 'kind', 'signIn', 'registered'],
7578
+ properties: {
7579
+ providerId: { type: 'string', minLength: 1 },
7580
+ kind: { $ref: '#/components/schemas/IdentityProviderKind' },
7581
+ signIn: { $ref: '#/components/schemas/IdentityProviderSignIn' },
7582
+ registered: {
7583
+ type: 'boolean',
7584
+ description: 'Whether a provider is registered under this `providerId` now.',
7585
+ },
7586
+ },
7587
+ };
7588
+
6078
7589
  export const LoginBodySchema: JsonSchema = {
6079
7590
  description:
6080
7591
  'Optional body for `POST /v1/auth/login/:providerId`. `redirectUri` overrides `metadata.defaultRedirectUri` on the provider config; at least one MUST be supplied.',
@@ -6112,66 +7623,182 @@ export const CallbackBodySchema: JsonSchema = {
6112
7623
  },
6113
7624
  };
6114
7625
 
6115
- export const CallbackResultSchema: JsonSchema = {
7626
+ export const CallbackResultSchema: JsonSchema = {
7627
+ type: 'object',
7628
+ additionalProperties: false,
7629
+ required: ['sessionToken', 'sessionId', 'expiresAt'],
7630
+ properties: {
7631
+ sessionToken: {
7632
+ type: 'string',
7633
+ description:
7634
+ 'Opaque session token (`kgi_sk_…`), shown once: the server keeps only a hash of it. Never parse it. Send as `Authorization: Bearer <sessionToken>` on subsequent requests. The underlying provider access-token never leaves the server.',
7635
+ },
7636
+ sessionId: { type: 'string' },
7637
+ expiresAt: { type: 'string', format: 'date-time' },
7638
+ },
7639
+ };
7640
+
7641
+ export const RefreshResultSchema: JsonSchema = CallbackResultSchema;
7642
+
7643
+ export const LogoutResultSchema: JsonSchema = {
7644
+ type: 'object',
7645
+ additionalProperties: false,
7646
+ required: ['sessionId', 'revoked'],
7647
+ properties: {
7648
+ sessionId: { type: 'string' },
7649
+ revoked: { type: 'boolean' },
7650
+ },
7651
+ };
7652
+
7653
+ export const WhoamiResultSchema: JsonSchema = {
7654
+ description:
7655
+ "Introspection of the caller's current authentication context. Always carries `tenantId` and `scopes` (empty for static bearer tokens), plus `userId` when the token carries one; `principal` says whom the caller acts as, and an API key adds `tokenId`, its `role` and the `projectId` it is limited to; session-token callers additionally see `sessionId`, `providerId`, and `expiresAt`. `user` is the caller's directory record, present when the deployment wires an identity directory and it knows the `userId`. `reviewerRole` is set when the caller is a reviewer — its token carries a reviewer role, or its user is a registered reviewer — so clients can gate reviewer-only UI (the approvals surface) without a second round trip.",
7656
+ type: 'object',
7657
+ additionalProperties: false,
7658
+ required: ['tenantId', 'scopes'],
7659
+ properties: {
7660
+ tenantId: { type: 'string', format: 'uuid' },
7661
+ userId: { type: 'string' },
7662
+ sessionId: { type: 'string' },
7663
+ providerId: { type: 'string' },
7664
+ scopes: { type: 'array', items: { type: 'string' } },
7665
+ expiresAt: { type: 'string', format: 'date-time' },
7666
+ reviewerRole: ReviewerRoleSchema,
7667
+ user: { $ref: '#/components/schemas/UserRecord' },
7668
+ principal: { $ref: '#/components/schemas/ApiKeyPrincipal' },
7669
+ tokenId: { type: 'string', description: "The caller's API key, when it is one." },
7670
+ role: {
7671
+ ...ApiTokenRoleSchema,
7672
+ description: "The caller's API key role, when the key has one.",
7673
+ },
7674
+ projectId: {
7675
+ type: 'string',
7676
+ description: "The project the caller's API key is limited to, when it is.",
7677
+ },
7678
+ tenantAdmin: {
7679
+ type: 'boolean',
7680
+ description:
7681
+ 'Whether the caller is a tenant admin, decided as the admin routes decide it: `admin` on the tenant when the runtime authorizes, otherwise the `tenant-admin` scope of a full key (never a `member` key or one limited to a project). A console shows its admin pages by it. Absent from older servers: read `scopes`.',
7682
+ },
7683
+ },
7684
+ };
7685
+
7686
+ export const UserRecordSchema: JsonSchema = {
7687
+ description:
7688
+ 'Tenant-scoped user record (admin plane). `primaryEmail` may be redacted on the wire based on tenant policy (the routes treat it as opaque). `metadata` is free-form JSON — deployments carry IdP claims / provisioning source / roles here.',
7689
+ type: 'object',
7690
+ additionalProperties: false,
7691
+ required: ['userId', 'tenantId', 'createdAt'],
7692
+ properties: {
7693
+ userId: { type: 'string' },
7694
+ tenantId: { type: 'string', format: 'uuid' },
7695
+ primaryEmail: { type: 'string' },
7696
+ displayName: { type: 'string' },
7697
+ createdAt: { type: 'string', format: 'date-time' },
7698
+ lastActiveAt: { type: 'string', format: 'date-time' },
7699
+ unregisteredAt: {
7700
+ type: 'string',
7701
+ format: 'date-time',
7702
+ description:
7703
+ 'When they were removed from the tenant (`POST /v1/identity/users/{userId}/unregister`); absent while they are here.',
7704
+ },
7705
+ metadata: { type: 'object', additionalProperties: true },
7706
+ },
7707
+ };
7708
+
7709
+ export const UnregisterUserResultSchema: JsonSchema = {
7710
+ description:
7711
+ 'A removed person, and what removing them took away (each 0 when they were already removed).',
7712
+ type: 'object',
7713
+ additionalProperties: false,
7714
+ required: ['user', 'keysRevoked', 'sessionsRevoked', 'grantsRemoved'],
7715
+ properties: {
7716
+ user: { $ref: '#/components/schemas/UserRecord' },
7717
+ keysRevoked: { type: 'integer', minimum: 0 },
7718
+ sessionsRevoked: { type: 'integer', minimum: 0 },
7719
+ grantsRemoved: { type: 'integer', minimum: 0 },
7720
+ },
7721
+ };
7722
+
7723
+ export const CreateUserBodySchema: JsonSchema = {
7724
+ type: 'object',
7725
+ additionalProperties: false,
7726
+ required: ['displayName'],
7727
+ properties: {
7728
+ displayName: { type: 'string', minLength: 1, maxLength: 200 },
7729
+ primaryEmail: { type: 'string', description: "Unique among the tenant's people." },
7730
+ },
7731
+ };
7732
+
7733
+ export const PersonGrantsSchema: JsonSchema = {
6116
7734
  type: 'object',
6117
7735
  additionalProperties: false,
6118
- required: ['sessionToken', 'sessionId', 'expiresAt'],
7736
+ description:
7737
+ "What a person may do, as granted directly: tenant admin, a role on a project (its memberships), a role in a team, and the reviewer roster. What a team's or an org's grants imply is not expanded.",
7738
+ required: ['userId', 'projects', 'teams'],
6119
7739
  properties: {
6120
- sessionToken: {
6121
- type: 'string',
7740
+ userId: { type: 'string' },
7741
+ tenantAdmin: {
7742
+ type: 'boolean',
6122
7743
  description:
6123
- 'Opaque framework-issued session token (`kgi_sk_<sessionId>`). Send as `Authorization: Bearer <sessionToken>` on subsequent requests. The underlying provider access-token never leaves the server.',
7744
+ 'Whether the person is a tenant admin. Absent when the runtime has no authorization store: nothing grants it then.',
6124
7745
  },
6125
- sessionId: { type: 'string' },
6126
- expiresAt: { type: 'string', format: 'date-time' },
7746
+ tenantMember: {
7747
+ type: 'boolean',
7748
+ description:
7749
+ "Whether the person is a tenant member: they read the tenant's settings (providers, policies, adapters, signing keys, deployments), not its projects. A person is one from being added. Absent when the runtime has no authorization store, or doesn't report it.",
7750
+ },
7751
+ projects: {
7752
+ type: 'array',
7753
+ description: 'Direct project memberships.',
7754
+ items: { $ref: '#/components/schemas/PersonProjectRole' },
7755
+ },
7756
+ teams: {
7757
+ type: 'array',
7758
+ description: 'Team memberships.',
7759
+ items: { $ref: '#/components/schemas/PersonTeamRole' },
7760
+ },
7761
+ reviewer: { $ref: '#/components/schemas/PersonReviewerRole' },
6127
7762
  },
6128
7763
  };
6129
7764
 
6130
- export const RefreshResultSchema: JsonSchema = CallbackResultSchema;
6131
-
6132
- export const LogoutResultSchema: JsonSchema = {
7765
+ export const PersonProjectRoleSchema: JsonSchema = {
6133
7766
  type: 'object',
6134
7767
  additionalProperties: false,
6135
- required: ['sessionId', 'revoked'],
7768
+ required: ['projectId', 'role'],
7769
+ description: "A person's direct role on a project.",
6136
7770
  properties: {
6137
- sessionId: { type: 'string' },
6138
- revoked: { type: 'boolean' },
7771
+ projectId: { type: 'string' },
7772
+ role: { $ref: '#/components/schemas/ProjectRole' },
6139
7773
  },
6140
7774
  };
6141
7775
 
6142
- export const WhoamiResultSchema: JsonSchema = {
6143
- description:
6144
- "Introspection of the caller's current authentication context. Always carries `tenantId` and `scopes` (empty for static bearer tokens), plus `userId` when the token carries one; session-token callers additionally see `sessionId`, `providerId`, and `expiresAt`. `user` is the caller's directory record, present when the deployment wires an identity directory and it knows the `userId`. `reviewerRole` is set when the caller is a reviewer — its token carries a reviewer role, or its user is a registered reviewer — so clients can gate reviewer-only UI (the approvals surface) without a second round trip.",
7776
+ export const PersonTeamRoleSchema: JsonSchema = {
6145
7777
  type: 'object',
6146
7778
  additionalProperties: false,
6147
- required: ['tenantId', 'scopes'],
7779
+ required: ['teamId', 'role'],
7780
+ description: "A person's role in a team.",
6148
7781
  properties: {
6149
- tenantId: { type: 'string', format: 'uuid' },
6150
- userId: { type: 'string' },
6151
- sessionId: { type: 'string' },
6152
- providerId: { type: 'string' },
6153
- scopes: { type: 'array', items: { type: 'string' } },
6154
- expiresAt: { type: 'string', format: 'date-time' },
6155
- reviewerRole: ReviewerRoleSchema,
6156
- user: { $ref: '#/components/schemas/UserRecord' },
7782
+ teamId: { type: 'string' },
7783
+ role: { $ref: '#/components/schemas/TeamRole' },
6157
7784
  },
6158
7785
  };
6159
7786
 
6160
- export const UserRecordSchema: JsonSchema = {
6161
- description:
6162
- 'Tenant-scoped user record (admin plane). `primaryEmail` may be redacted on the wire based on tenant policy (the routes treat it as opaque). `metadata` is free-form JSON — deployments carry IdP claims / provisioning source / roles here.',
7787
+ export const PersonReviewerRoleSchema: JsonSchema = {
6163
7788
  type: 'object',
6164
7789
  additionalProperties: false,
6165
- required: ['userId', 'tenantId', 'createdAt'],
6166
- properties: {
6167
- userId: { type: 'string' },
6168
- tenantId: { type: 'string', format: 'uuid' },
6169
- primaryEmail: { type: 'string' },
6170
- displayName: { type: 'string' },
6171
- createdAt: { type: 'string', format: 'date-time' },
6172
- lastActiveAt: { type: 'string', format: 'date-time' },
6173
- metadata: { type: 'object', additionalProperties: true },
6174
- },
7790
+ required: ['role'],
7791
+ description: "A person's active entry on the reviewer roster.",
7792
+ properties: { role: { $ref: '#/components/schemas/ReviewerRole' } },
7793
+ };
7794
+
7795
+ export const PersonGrantBodySchema: JsonSchema = {
7796
+ type: 'object',
7797
+ additionalProperties: false,
7798
+ required: ['kind'],
7799
+ description:
7800
+ "The grant to give or take: tenant admin. A person's project and team roles have their own membership routes.",
7801
+ properties: { kind: { type: 'string', enum: ['tenant-admin'] } },
6175
7802
  };
6176
7803
 
6177
7804
  export const UserCollectionPageSchema: JsonSchema = {
@@ -6678,63 +8305,22 @@ export const ExportComplianceEvidenceFilterSchema: JsonSchema = {
6678
8305
  };
6679
8306
 
6680
8307
  export const ExportComplianceEvidenceBodySchema: JsonSchema = {
8308
+ description: 'Optional: no body exports every exportable kind, signed with the active key.',
6681
8309
  type: 'object',
6682
8310
  additionalProperties: false,
6683
- required: ['signingKeyId'],
6684
8311
  properties: {
6685
- signingKeyId: {
6686
- type: 'string',
6687
- minLength: 1,
6688
- description:
6689
- 'The `SigningKeyId` the deployment plugs into its `signingKey` binding. Server looks up the private key via `signingKey.getPrivateKey(signingKeyId)` — 404 `signing-key-not-found` if unknown.',
6690
- },
8312
+ signingKeyId: SIGNING_KEY_ID_PROPERTY,
6691
8313
  filter: ExportComplianceEvidenceFilterSchema,
6692
8314
  },
6693
8315
  };
6694
8316
 
6695
- export const SignedComplianceEvidenceBundleSchema: JsonSchema = {
8317
+ export const SignedComplianceEvidenceBundleSchema: JsonSchema = signedExportEnvelope({
6696
8318
  description:
6697
- 'Signed exportable bundle. `bundle` is base64 of the exact bytes that were signed (sorted-key canonical JSON, no whitespace); verifiers can pass those bytes directly to `verifyEd25519`. Bundle body: `{ bundleSchemaVersion, tenantId, filter, records, recordCount, exportedAt }`. Envelope shape identical to `ExportProvenanceResult` + audit-bundle — verifiers reuse one `verifyEd25519` wrapper across all three surfaces.',
6698
- type: 'object',
6699
- additionalProperties: false,
6700
- required: [
6701
- 'bundleSchemaVersion',
6702
- 'tenantId',
6703
- 'bundle',
6704
- 'algorithm',
6705
- 'signingKeyId',
6706
- 'signature',
6707
- 'publicKey',
6708
- 'canonicalization',
6709
- 'exportedAt',
6710
- ],
6711
- properties: {
6712
- bundleSchemaVersion: { type: 'string', const: '1.0.0' },
6713
- tenantId: { type: 'string', format: 'uuid' },
6714
- bundle: {
6715
- type: 'string',
6716
- description: 'Base64-encoded canonical JSON of the bundle body.',
6717
- },
6718
- algorithm: { type: 'string', const: 'ed25519' },
6719
- signingKeyId: { type: 'string' },
6720
- signature: {
6721
- type: 'string',
6722
- description: 'Base64-encoded Ed25519 signature bytes over `bundle` (after base64-decode).',
6723
- },
6724
- publicKey: {
6725
- type: 'string',
6726
- description:
6727
- 'PEM-encoded Ed25519 public key (DER SPKI envelope). Callers can pass this straight into `parsePublicKeyPem` for verification.',
6728
- },
6729
- canonicalization: {
6730
- type: 'string',
6731
- const: 'sorted-key-json',
6732
- description:
6733
- 'Canonicalization algorithm — sorted-key JSON, no whitespace. Same algorithm as `canonicalize`.',
6734
- },
6735
- exportedAt: { type: 'string', format: 'date-time' },
6736
- },
6737
- };
8319
+ 'Signed compliance evidence. Body: `{ bundleSchemaVersion, tenantId, filter, records, recordCount, exportedAt }`.',
8320
+ kind: 'compliance',
8321
+ subject: ['tenantId', { type: 'string', format: 'uuid' }],
8322
+ versionDescription: "The body's version, semver: `1.0.0`.",
8323
+ });
6738
8324
 
6739
8325
  // ---------------- platform hierarchy ----------------
6740
8326
 
@@ -7001,11 +8587,17 @@ export const ProjectMembershipCollectionPageSchema: JsonSchema = {
7001
8587
  };
7002
8588
 
7003
8589
  export const AddProjectMembershipBodySchema: JsonSchema = {
8590
+ description: 'Exactly one of `userId` and `email` names the person.',
7004
8591
  type: 'object',
7005
8592
  additionalProperties: false,
7006
- required: ['userId', 'role'],
8593
+ required: ['role'],
7007
8594
  properties: {
7008
8595
  userId: { type: 'string', minLength: 1 },
8596
+ email: {
8597
+ type: 'string',
8598
+ minLength: 1,
8599
+ description: "The person's email, as the tenant has it.",
8600
+ },
7009
8601
  role: { $ref: '#/components/schemas/ProjectRole' },
7010
8602
  },
7011
8603
  };
@@ -7598,11 +9190,11 @@ export const TriggerStatusSchema: JsonSchema = {
7598
9190
  export const ScheduleRecordSchema: JsonSchema = {
7599
9191
  type: 'object',
7600
9192
  additionalProperties: false,
9193
+ description:
9194
+ 'A schedule: what it runs (a flow at a version, or an agent), when (a cron expression in a timezone), as whom (its owner), and what it does after a gap or while a run is still going.',
7601
9195
  required: [
7602
9196
  'scheduleId',
7603
9197
  'triggerId',
7604
- 'flowId',
7605
- 'flowVersion',
7606
9198
  'cronExpression',
7607
9199
  'label',
7608
9200
  'status',
@@ -7618,8 +9210,34 @@ export const ScheduleRecordSchema: JsonSchema = {
7618
9210
  'Domain-friendly alias for `triggerId` — the trigger id (a UUID). Use interchangeably in admin URLs.',
7619
9211
  },
7620
9212
  triggerId: { type: 'string' },
7621
- flowId: { type: 'string', minLength: 1 },
9213
+ flowId: {
9214
+ type: 'string',
9215
+ minLength: 1,
9216
+ description: 'A schedule that runs a flow: the flow, at `flowVersion`.',
9217
+ },
7622
9218
  flowVersion: { type: 'string', minLength: 1 },
9219
+ agentId: {
9220
+ type: 'string',
9221
+ minLength: 1,
9222
+ description:
9223
+ "A schedule that runs an agent: the agent, at `agentVersion`, else its version live for the schedule's project (else the latest), as a run that names none.",
9224
+ },
9225
+ agentVersion: { type: 'string', minLength: 1 },
9226
+ improve: {
9227
+ $ref: '#/components/schemas/ImproveScheduleTarget',
9228
+ description:
9229
+ 'A schedule that starts improvement passes: on this agent, for this scope, when enough new trusted "no" judgments have come in (`input`: the threshold, the monthly cap and the pass options).',
9230
+ },
9231
+ projectId: {
9232
+ type: 'string',
9233
+ format: 'uuid',
9234
+ description: "The schedule's project: its runs are this project's.",
9235
+ },
9236
+ owner: {
9237
+ $ref: '#/components/schemas/TriggerOwner',
9238
+ description:
9239
+ 'Who its runs act as: whoever registered it, until an admin takes it over (`POST …/owner`). Checked again at every fire.',
9240
+ },
7623
9241
  cronExpression: {
7624
9242
  type: 'string',
7625
9243
  minLength: 1,
@@ -7631,22 +9249,174 @@ export const ScheduleRecordSchema: JsonSchema = {
7631
9249
  description: 'IANA timezone (e.g. `UTC`, `America/New_York`). Absent → `UTC`.',
7632
9250
  },
7633
9251
  input: {
7634
- description: 'Static input handed to the flow on every fire. Absent → `{}`.',
9252
+ description: 'Static input handed to the run on every fire. Absent → `{}`.',
9253
+ },
9254
+ catchUp: {
9255
+ type: 'string',
9256
+ enum: ['latest', 'skip'],
9257
+ description:
9258
+ 'After a gap (the runtime was down, or a fire is later than `startingDeadlineSeconds`): `latest` runs once, for the latest missed occurrence, and its fire says how many it missed; `skip` drops the missed occurrences. Never a run per missed occurrence.',
9259
+ },
9260
+ overlap: {
9261
+ type: 'string',
9262
+ enum: ['skip', 'allow'],
9263
+ description:
9264
+ 'When an occurrence comes while the previous run of this schedule is still running: `skip` records the fire as skipped; `allow` starts another run.',
9265
+ },
9266
+ startingDeadlineSeconds: {
9267
+ type: 'integer',
9268
+ minimum: 1,
9269
+ description:
9270
+ 'How late a fire may start and still count as on time; past it, `catchUp` applies.',
7635
9271
  },
7636
9272
  label: { type: ['string', 'null'] },
7637
9273
  status: { $ref: '#/components/schemas/TriggerStatus' },
9274
+ statusReason: {
9275
+ type: 'string',
9276
+ description:
9277
+ 'Why the runtime paused it: repeated fires that were refused (the owner lost access) or failed. Skipped fires (an overlap, an erasure in progress) never count.',
9278
+ },
7638
9279
  nextFireAt: {
7639
9280
  type: ['string', 'null'],
7640
9281
  format: 'date-time',
7641
9282
  description:
7642
9283
  'Wall-clock time of the next scheduled fire. `null` on paused rows if the cron scheduler never re-armed.',
7643
9284
  },
9285
+ upcoming: {
9286
+ type: 'array',
9287
+ items: { type: 'string', format: 'date-time' },
9288
+ description: 'The next occurrences, when the request asked for them (`?upcoming=N`).',
9289
+ },
7644
9290
  lastFiredAt: { type: ['string', 'null'], format: 'date-time' },
7645
9291
  createdAt: { type: 'string', format: 'date-time' },
7646
9292
  updatedAt: { type: 'string', format: 'date-time' },
7647
9293
  },
7648
9294
  };
7649
9295
 
9296
+ export const TriggerOwnerSchema: JsonSchema = {
9297
+ type: 'object',
9298
+ additionalProperties: false,
9299
+ required: ['kind', 'id'],
9300
+ properties: {
9301
+ kind: { type: 'string', enum: ['user', 'service'] },
9302
+ id: { type: 'string' },
9303
+ },
9304
+ };
9305
+
9306
+ export const ImproveScheduleTargetSchema: JsonSchema = {
9307
+ type: 'object',
9308
+ additionalProperties: false,
9309
+ required: ['agentId', 'scope'],
9310
+ description:
9311
+ 'What an improve schedule works on: the agent, and the live scope its passes propose for and count judgments in.',
9312
+ properties: {
9313
+ agentId: { type: 'string', minLength: 1 },
9314
+ scope: { $ref: '#/components/schemas/LiveScope' },
9315
+ },
9316
+ };
9317
+
9318
+ export const ImproveScheduleInputSchema: JsonSchema = {
9319
+ type: 'object',
9320
+ additionalProperties: false,
9321
+ description:
9322
+ 'An improve schedule\'s `config.input`. Each fire counts the trusted "no" judgments (recorded under a restricted judge class) on the agent\'s runs in the scope since its last pass. When there are enough, across enough runs and judges, it starts a pass on a fresh test set of those runs; otherwise the fire is `skipped`, saying which count was short. A pass that proposes asks for the review at once.',
9323
+ properties: {
9324
+ tiers: { type: 'array', items: { type: 'string', enum: ['settings', 'prompt'] } },
9325
+ objective: { type: 'string', enum: ['weightedYesShare', 'weightedPrecisionAtK'] },
9326
+ classWeights: { type: 'string', enum: ['restricted-only', 'as-recorded'] },
9327
+ model: {
9328
+ type: 'object',
9329
+ additionalProperties: false,
9330
+ required: ['providerId', 'model'],
9331
+ properties: { providerId: { type: 'string' }, model: { type: 'string' } },
9332
+ },
9333
+ candidates: { type: 'integer', minimum: 1, maximum: 5 },
9334
+ budget: {
9335
+ type: 'object',
9336
+ additionalProperties: false,
9337
+ description:
9338
+ "Each pass's budget (default $5 and 30 candidates), never more than what's left of the month's cap.",
9339
+ properties: {
9340
+ maxCostUsd: { type: 'number', exclusiveMinimum: 0, maximum: 100 },
9341
+ maxCandidates: { type: 'integer', minimum: 1, maximum: 200 },
9342
+ },
9343
+ },
9344
+ threshold: {
9345
+ type: 'object',
9346
+ additionalProperties: false,
9347
+ description: 'Default 5 judgments, across 3 runs, from 2 judges.',
9348
+ properties: {
9349
+ judgments: { type: 'integer', minimum: 1, maximum: 1000 },
9350
+ runs: { type: 'integer', minimum: 1, maximum: 1000 },
9351
+ judges: { type: 'integer', minimum: 1, maximum: 1000 },
9352
+ },
9353
+ },
9354
+ monthlyCapUsd: {
9355
+ type: 'number',
9356
+ exclusiveMinimum: 0,
9357
+ maximum: 1000,
9358
+ description: 'The most its passes may cost in a calendar month (UTC). Default 20.',
9359
+ },
9360
+ },
9361
+ };
9362
+
9363
+ export const ScheduleFireSchema: JsonSchema = {
9364
+ type: 'object',
9365
+ additionalProperties: false,
9366
+ description:
9367
+ 'One fire of a schedule (an occurrence, or a `run-now`) and what came of it. `pending` while its run is being started.',
9368
+ required: ['fireId', 'scheduleId', 'triggerId', 'firedAt', 'outcome'],
9369
+ properties: {
9370
+ fireId: { type: 'string' },
9371
+ scheduleId: { type: 'string' },
9372
+ triggerId: { type: 'string' },
9373
+ scheduledFor: {
9374
+ type: 'string',
9375
+ format: 'date-time',
9376
+ description: 'The occurrence it is for; absent on a `run-now` fire.',
9377
+ },
9378
+ firedAt: { type: 'string', format: 'date-time' },
9379
+ outcome: {
9380
+ type: 'string',
9381
+ enum: [
9382
+ 'pending',
9383
+ 'started',
9384
+ 'skipped-overlap',
9385
+ 'skipped-erasure',
9386
+ 'skipped',
9387
+ 'refused',
9388
+ 'failed',
9389
+ ],
9390
+ description:
9391
+ "`skipped-overlap`: the previous fire's run was still going (`overlap: skip`). `skipped-erasure`: the person the fire acts for is being erased, so no new run starts for them until the erasure completes. `skipped`: what an improve schedule waits for wasn't there (its threshold, or its monthly cap), as `detail` says. None of the skipped outcomes counts toward the auto-pause; `refused` and `failed` do.",
9392
+ },
9393
+ runId: { type: 'string', format: 'uuid', description: 'The run it started.' },
9394
+ passId: {
9395
+ type: 'string',
9396
+ format: 'uuid',
9397
+ description: 'The improvement pass it started (an improve schedule).',
9398
+ },
9399
+ detail: { type: 'string', description: 'Why it was refused, skipped or failed.' },
9400
+ missedCount: {
9401
+ type: 'integer',
9402
+ minimum: 1,
9403
+ description: 'Occurrences this fire stood in for after a gap (`catchUp: latest`).',
9404
+ },
9405
+ manual: { type: 'boolean', description: 'A `run-now` fire, outside the schedule.' },
9406
+ },
9407
+ };
9408
+
9409
+ export const ScheduleFirePageSchema: JsonSchema = {
9410
+ type: 'object',
9411
+ additionalProperties: false,
9412
+ required: ['data', 'hasMore'],
9413
+ properties: {
9414
+ data: { type: 'array', items: { $ref: '#/components/schemas/ScheduleFire' } },
9415
+ hasMore: { type: 'boolean' },
9416
+ nextCursor: { type: 'string' },
9417
+ },
9418
+ };
9419
+
7650
9420
  export const ScheduleCollectionPageSchema: JsonSchema = {
7651
9421
  type: 'object',
7652
9422
  additionalProperties: false,
@@ -7661,10 +9431,28 @@ export const ScheduleCollectionPageSchema: JsonSchema = {
7661
9431
  export const RegisterScheduleBodySchema: JsonSchema = {
7662
9432
  type: 'object',
7663
9433
  additionalProperties: false,
7664
- required: ['flowId', 'flowVersion', 'config'],
9434
+ description:
9435
+ 'Name what it runs: `flowId` with `flowVersion`, `agentId` (with an optional `agentVersion`), or `improve` (improvement passes). Registering needs `write` on the project and `execute` on what it runs (`publish` on the agent for `improve`); its runs act as the caller.',
9436
+ required: ['config'],
7665
9437
  properties: {
7666
- flowId: { type: 'string', minLength: 1 },
9438
+ flowId: { type: 'string', minLength: 1, description: 'Run a flow (with `flowVersion`).' },
7667
9439
  flowVersion: { type: 'string', minLength: 1 },
9440
+ agentId: {
9441
+ type: 'string',
9442
+ minLength: 1,
9443
+ description: 'Run an agent (instead of a flow): at `agentVersion`, else its live version.',
9444
+ },
9445
+ agentVersion: { type: 'string', minLength: 1 },
9446
+ improve: {
9447
+ $ref: '#/components/schemas/ImproveScheduleTarget',
9448
+ description:
9449
+ 'Start an improvement pass instead of a run (instead of `flowId` or `agentId`). Its `config.input` is the pass options; registering needs `publish` on the agent.',
9450
+ },
9451
+ projectId: {
9452
+ type: 'string',
9453
+ format: 'uuid',
9454
+ description: "The schedule's project. Absent → the tenant's default project.",
9455
+ },
7668
9456
  config: {
7669
9457
  type: 'object',
7670
9458
  additionalProperties: false,
@@ -7672,9 +9460,20 @@ export const RegisterScheduleBodySchema: JsonSchema = {
7672
9460
  properties: {
7673
9461
  cronExpression: { type: 'string', minLength: 1 },
7674
9462
  timezone: { type: 'string' },
7675
- input: {},
9463
+ input: {
9464
+ description:
9465
+ "What each run gets. An agent schedule's runs take the agent payload, `{ userMessage, parameters? }`, so it needs `userMessage`; a flow's take the flow's input. An improve schedule's is `ImproveScheduleInput`, kept with its defaults applied.",
9466
+ },
7676
9467
  },
7677
9468
  },
9469
+ catchUp: { type: 'string', enum: ['latest', 'skip'], description: 'Default `latest`.' },
9470
+ overlap: { type: 'string', enum: ['skip', 'allow'], description: 'Default `skip`.' },
9471
+ startingDeadlineSeconds: {
9472
+ type: 'integer',
9473
+ minimum: 1,
9474
+ maximum: 86400,
9475
+ description: 'Default 600.',
9476
+ },
7678
9477
  label: { type: 'string' },
7679
9478
  },
7680
9479
  };
@@ -7682,21 +9481,46 @@ export const RegisterScheduleBodySchema: JsonSchema = {
7682
9481
  export const PatchScheduleBodySchema: JsonSchema = {
7683
9482
  type: 'object',
7684
9483
  additionalProperties: false,
9484
+ description:
9485
+ 'Change what it runs (the target fields, as at registration, which also needs `execute` on the new target), when, or its policies.',
7685
9486
  properties: {
9487
+ flowId: { type: 'string', minLength: 1, description: 'Run a flow (with `flowVersion`).' },
9488
+ flowVersion: { type: 'string', minLength: 1 },
9489
+ agentId: {
9490
+ type: 'string',
9491
+ minLength: 1,
9492
+ description: 'Run an agent (instead of a flow): at `agentVersion`, else its live version.',
9493
+ },
9494
+ agentVersion: { type: 'string', minLength: 1 },
9495
+ improve: {
9496
+ $ref: '#/components/schemas/ImproveScheduleTarget',
9497
+ description:
9498
+ 'Start an improvement pass instead of a run (instead of `flowId` or `agentId`). Its `config.input` is the pass options; registering needs `publish` on the agent.',
9499
+ },
7686
9500
  config: {
7687
9501
  type: 'object',
7688
9502
  additionalProperties: false,
7689
9503
  properties: {
7690
9504
  cronExpression: { type: 'string' },
7691
9505
  timezone: { type: 'string' },
7692
- input: {},
9506
+ input: {
9507
+ description:
9508
+ "What each run gets. An agent schedule's runs take the agent payload, `{ userMessage, parameters? }`, so it needs `userMessage`; a flow's take the flow's input. An improve schedule's is `ImproveScheduleInput`, kept with its defaults applied.",
9509
+ },
7693
9510
  },
7694
9511
  },
9512
+ catchUp: { type: 'string', enum: ['latest', 'skip'], description: 'Default `latest`.' },
9513
+ overlap: { type: 'string', enum: ['skip', 'allow'], description: 'Default `skip`.' },
9514
+ startingDeadlineSeconds: {
9515
+ type: 'integer',
9516
+ minimum: 1,
9517
+ maximum: 86400,
9518
+ description: 'Default 600.',
9519
+ },
7695
9520
  label: {
7696
9521
  type: ['string', 'null'],
7697
9522
  description: '`null` clears the label; omit to leave unchanged.',
7698
9523
  },
7699
- flowVersion: { type: 'string' },
7700
9524
  },
7701
9525
  };
7702
9526
 
@@ -7923,7 +9747,7 @@ export const WebhookTriggerUnregisterResultSchema: JsonSchema = {
7923
9747
 
7924
9748
  export const WebhookEventTypeSchema: JsonSchema = {
7925
9749
  type: 'string',
7926
- enum: ['run.finished'],
9750
+ enum: ['run.finished', 'improvement-pass.finished'],
7927
9751
  description: 'An event type an endpoint can subscribe to.',
7928
9752
  };
7929
9753
 
@@ -8130,6 +9954,33 @@ export const RunFinishedEventSchema: JsonSchema = {
8130
9954
  },
8131
9955
  };
8132
9956
 
9957
+ export const ImprovementPassFinishedEventSchema: JsonSchema = {
9958
+ type: 'object',
9959
+ additionalProperties: false,
9960
+ required: ['id', 'type', 'createdAt', 'data'],
9961
+ description:
9962
+ 'An improvement pass ended (`completed`, `failed` or `cancelled`): one a person started, or one an `improve` schedule did. Its outcome names the proposal it wrote, if it wrote one.',
9963
+ properties: {
9964
+ id: {
9965
+ type: 'string',
9966
+ description: 'Event id, also sent as the `webhook-id` header; the same on every retry.',
9967
+ },
9968
+ type: { type: 'string', const: 'improvement-pass.finished' },
9969
+ createdAt: { type: 'string', format: 'date-time' },
9970
+ data: {
9971
+ type: 'object',
9972
+ additionalProperties: false,
9973
+ required: ['pass'],
9974
+ properties: {
9975
+ pass: {
9976
+ $ref: '#/components/schemas/ImprovementPass',
9977
+ description: 'The pass, as `GET /v1/improvement-passes/{passId}` shows it.',
9978
+ },
9979
+ },
9980
+ },
9981
+ },
9982
+ };
9983
+
8133
9984
  export const WebhookTestEventSchema: JsonSchema = {
8134
9985
  type: 'object',
8135
9986
  additionalProperties: false,
@@ -8151,12 +10002,14 @@ export const WebhookEventSchema: JsonSchema = {
8151
10002
  description: 'The JSON body of every webhook request.',
8152
10003
  oneOf: [
8153
10004
  { $ref: '#/components/schemas/RunFinishedEvent' },
10005
+ { $ref: '#/components/schemas/ImprovementPassFinishedEvent' },
8154
10006
  { $ref: '#/components/schemas/WebhookTestEvent' },
8155
10007
  ],
8156
10008
  discriminator: {
8157
10009
  propertyName: 'type',
8158
10010
  mapping: {
8159
10011
  'run.finished': '#/components/schemas/RunFinishedEvent',
10012
+ 'improvement-pass.finished': '#/components/schemas/ImprovementPassFinishedEvent',
8160
10013
  'webhook.test': '#/components/schemas/WebhookTestEvent',
8161
10014
  },
8162
10015
  },
@@ -8255,6 +10108,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8255
10108
  ['HealthResult', HealthResultSchema],
8256
10109
  ['RunStatus', RunStatusSchema],
8257
10110
  ['RunAgent', RunAgentSchema],
10111
+ ['RunTrigger', RunTriggerSchema],
8258
10112
  ['ScopeSegment', ScopeSegmentSchema],
8259
10113
  ['LiveScopeTenant', LiveScopeTenantSchema],
8260
10114
  ['LiveScopeOrg', LiveScopeOrgSchema],
@@ -8279,6 +10133,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8279
10133
  ['RollbackBody', RollbackBodySchema],
8280
10134
  ['UnpinBody', UnpinBodySchema],
8281
10135
  ['Run', RunSchema],
10136
+ ['RunFailure', RunFailureSchema],
8282
10137
  ['StartRunOptions', StartRunOptionsSchema],
8283
10138
  ['StartRunBody', StartRunBodySchema],
8284
10139
  ['ResumeRunBody', ResumeRunBodySchema],
@@ -8293,6 +10148,17 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8293
10148
  ['MintTokenResult', MintTokenResultSchema],
8294
10149
  ['ApiToken', ApiTokenSchema],
8295
10150
  ['ApiTokenPage', ApiTokenPageSchema],
10151
+ ['ApiKeyPrincipal', ApiKeyPrincipalSchema],
10152
+ ['ServiceAccountGrantTenantAdmin', ServiceAccountGrantTenantAdminSchema],
10153
+ ['ServiceAccountGrantTenantMember', ServiceAccountGrantTenantMemberSchema],
10154
+ ['ServiceAccountGrantProject', ServiceAccountGrantProjectSchema],
10155
+ ['ServiceAccountGrant', ServiceAccountGrantSchema],
10156
+ ['ServiceAccountGrantBody', ServiceAccountGrantBodySchema],
10157
+ ['ServiceAccountUngrantProject', ServiceAccountUngrantProjectSchema],
10158
+ ['ServiceAccountUngrantBody', ServiceAccountUngrantBodySchema],
10159
+ ['ServiceAccount', ServiceAccountSchema],
10160
+ ['ServiceAccountPage', ServiceAccountPageSchema],
10161
+ ['CreateServiceAccountBody', CreateServiceAccountBodySchema],
8296
10162
  ['RevokeTokenResult', RevokeTokenResultSchema],
8297
10163
  ['TrustedSigningKey', TrustedSigningKeySchema],
8298
10164
  ['TrustSigningKeyBody', TrustSigningKeyBodySchema],
@@ -8314,6 +10180,8 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8314
10180
  ['ReviewerCollectionPage', ReviewerCollectionPageSchema],
8315
10181
  ['RegisterReviewerBody', RegisterReviewerBodySchema],
8316
10182
  ['UnregisterReviewerResult', UnregisterReviewerResultSchema],
10183
+ ['ExportSigningKey', ExportSigningKeySchema],
10184
+ ['ExportSigningKeyList', ExportSigningKeyListSchema],
8317
10185
  ['ExportAuditBundleBody', ExportAuditBundleBodySchema],
8318
10186
  ['ExportAuditBundleResult', ExportAuditBundleResultSchema],
8319
10187
  ['ObservationStatus', ObservationStatusSchema],
@@ -8343,6 +10211,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8343
10211
  ['BuildJudgedSuiteResult', BuildJudgedSuiteResultSchema],
8344
10212
  ['PromptParameter', PromptParameterSchema],
8345
10213
  ['RetrievalIntent', RetrievalIntentSchema],
10214
+ ['AgentMemoryPolicy', AgentMemoryPolicySchema],
8346
10215
  ['ConversationPolicy', ConversationPolicySchema],
8347
10216
  ['TurnBudget', TurnBudgetSchema],
8348
10217
  ['Capability', CapabilitySchema],
@@ -8411,30 +10280,49 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8411
10280
  ['SourceFreshness', SourceFreshnessSchema],
8412
10281
  ['SourceRefresh', SourceRefreshSchema],
8413
10282
  ['FactSource', FactSourceSchema],
10283
+ ['FactSubject', FactSubjectSchema],
10284
+ ['FactAttribution', FactAttributionSchema],
10285
+ ['FactGeneratedBy', FactGeneratedBySchema],
8414
10286
  ['Fact', FactSchema],
8415
10287
  ['FactCollectionPage', FactCollectionPageSchema],
8416
10288
  ['WriteFactBody', WriteFactBodySchema],
8417
- ['SupersedeFactResult', SupersedeFactResultSchema],
10289
+ ['SupersedeFactBody', SupersedeFactBodySchema],
10290
+ ['VerifyFactBody', VerifyFactBodySchema],
10291
+ ['FactRevisionList', FactRevisionListSchema],
8418
10292
  ['RetrieveIntent', RetrieveIntentSchema],
8419
10293
  ['RetrieveMemoryBody', RetrieveMemoryBodySchema],
8420
10294
  ['RetrievalHit', RetrievalHitSchema],
8421
10295
  ['RetrieveMemoryResult', RetrieveMemoryResultSchema],
10296
+ ['MemoryErasureFactSelector', MemoryErasureFactSelectorSchema],
10297
+ ['MemoryErasureSubjectSelector', MemoryErasureSubjectSelectorSchema],
10298
+ ['MemoryErasureConversationSelector', MemoryErasureConversationSelectorSchema],
10299
+ ['MemoryErasureSelector', MemoryErasureSelectorSchema],
10300
+ ['CreateMemoryErasureBody', CreateMemoryErasureBodySchema],
10301
+ ['MemoryErasure', MemoryErasureSchema],
10302
+ ['MemoryErasureCreated', MemoryErasureCreatedSchema],
10303
+ ['MemoryErasurePage', MemoryErasurePageSchema],
10304
+ ['MemoryErasureLedgerEntry', MemoryErasureLedgerEntrySchema],
10305
+ ['MemoryErasureLedger', MemoryErasureLedgerSchema],
10306
+ ['ReplayMemoryErasuresBody', ReplayMemoryErasuresBodySchema],
10307
+ ['ResumeMemoryErasureBody', ResumeMemoryErasureBodySchema],
10308
+ ['ReplayMemoryErasuresResult', ReplayMemoryErasuresResultSchema],
8422
10309
  ['ProposalTier', ProposalTierSchema],
8423
10310
  ['FixProposalStatus', FixProposalStatusSchema],
8424
- ['PatternRef', PatternRefSchema],
8425
- ['ProposedChange', ProposedChangeSchema],
10311
+ ['ProposalChange', ProposalChangeSchema],
10312
+ ['ProposalDrafter', ProposalDrafterSchema],
10313
+ ['ProposalCandidate', ProposalCandidateSchema],
10314
+ ['ProposalEvaluation', ProposalEvaluationSchema],
10315
+ ['ProposalPromotion', ProposalPromotionSchema],
8426
10316
  ['FixProposal', FixProposalSchema],
8427
10317
  ['FixProposalCollectionPage', FixProposalCollectionPageSchema],
8428
- ['PassCriterion', PassCriterionSchema],
8429
- ['DraftProposalBody', DraftProposalBodySchema],
8430
- ['DryRunProposalBody', DryRunProposalBodySchema],
8431
- ['DryRunProposalResult', DryRunProposalResultSchema],
8432
- ['SubmitReviewProposalBody', SubmitReviewProposalBodySchema],
8433
- ['SubmitReviewProposalResult', SubmitReviewProposalResultSchema],
8434
- ['ApplyProposalBody', ApplyProposalBodySchema],
8435
- ['ApplyProposalResult', ApplyProposalResultSchema],
8436
- ['RollbackProposalBody', RollbackProposalBodySchema],
8437
- ['RollbackProposalResult', RollbackProposalResultSchema],
10318
+ ['ImprovementBudget', ImprovementBudgetSchema],
10319
+ ['ImprovementPassOutcome', ImprovementPassOutcomeSchema],
10320
+ ['ImprovementPass', ImprovementPassSchema],
10321
+ ['ImprovementPassCollectionPage', ImprovementPassCollectionPageSchema],
10322
+ ['ImproveBody', ImproveBodySchema],
10323
+ ['CreateProposalBody', CreateProposalBodySchema],
10324
+ ['EvaluateProposalBody', EvaluateProposalBodySchema],
10325
+ ['ProposalReasonBody', ProposalReasonBodySchema],
8438
10326
  ['WithdrawProposalBody', WithdrawProposalBodySchema],
8439
10327
  ['ProvenanceNodeKind', ProvenanceNodeKindSchema],
8440
10328
  ['ProvenanceEdgeKind', ProvenanceEdgeKindSchema],
@@ -8453,6 +10341,7 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8453
10341
  ['DeleteArtifactResult', DeleteArtifactResultSchema],
8454
10342
  ['Feature', FeatureSchema],
8455
10343
  ['CapabilityDescriptor', CapabilityDescriptorSchema],
10344
+ ['CapabilityProvider', CapabilityProviderSchema],
8456
10345
  ['CapabilityCollectionPage', CapabilityCollectionPageSchema],
8457
10346
  ['ModelThinking', ModelThinkingSchema],
8458
10347
  ['ProviderCost', ProviderCostSchema],
@@ -8463,6 +10352,8 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8463
10352
  ['RegisterProviderResult', RegisterProviderResultSchema],
8464
10353
  ['UnregisterProviderResult', UnregisterProviderResultSchema],
8465
10354
  ['ProviderCapabilitiesResult', ProviderCapabilitiesResultSchema],
10355
+ ['AdapterConfigProblem', AdapterConfigProblemSchema],
10356
+ ['ProviderCheckResult', ProviderCheckResultSchema],
8466
10357
  ['MCPTransport', MCPTransportSchema],
8467
10358
  ['MCPEndpoint', MCPEndpointSchema],
8468
10359
  ['MCPEndpointSecretRef', MCPEndpointSecretRefSchema],
@@ -8529,6 +10420,8 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8529
10420
  ['EvalRunAgentRef', EvalRunAgentRefSchema],
8530
10421
  ['EvalRunFlowRef', EvalRunFlowRefSchema],
8531
10422
  ['EvalBaseline', EvalBaselineSchema],
10423
+ ['EvalOverrides', EvalOverridesSchema],
10424
+ ['EvalSample', EvalSampleSchema],
8532
10425
  ['EvalComparison', EvalComparisonSchema],
8533
10426
  ['ComparisonMetric', ComparisonMetricSchema],
8534
10427
  ['ComparisonCandidate', ComparisonCandidateSchema],
@@ -8542,10 +10435,22 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8542
10435
  ['IdentityProviderKind', IdentityProviderKindSchema],
8543
10436
  ['ClaimMappingScopesSpec', ClaimMappingScopesSpecSchema],
8544
10437
  ['ClaimMappingSpec', ClaimMappingSpecSchema],
10438
+ ['IdentityProviderSignIn', IdentityProviderSignInSchema],
10439
+ ['OidcIdentityProviderConfig', OidcIdentityProviderConfigSchema],
10440
+ ['SamlIdentityProviderConfig', SamlIdentityProviderConfigSchema],
10441
+ ['OAuth2IdentityProviderConfig', OAuth2IdentityProviderConfigSchema],
8545
10442
  ['IdentityProviderConfig', IdentityProviderConfigSchema],
10443
+ ['RegisterIdentityProviderBody', RegisterIdentityProviderBodySchema],
10444
+ ['GetIdentityProviderResult', GetIdentityProviderResultSchema],
8546
10445
  ['IdentityProviderCollectionPage', IdentityProviderCollectionPageSchema],
10446
+ ['SignInOption', SignInOptionSchema],
10447
+ ['SignInOptions', SignInOptionsSchema],
10448
+ ['TokenSignInResult', TokenSignInResultSchema],
8547
10449
  ['RegisterIdentityProviderResult', RegisterIdentityProviderResultSchema],
8548
10450
  ['UnregisterIdentityProviderResult', UnregisterIdentityProviderResultSchema],
10451
+ ['UpdateIdentityProviderBody', UpdateIdentityProviderBodySchema],
10452
+ ['UpdateIdentityProviderResult', UpdateIdentityProviderResultSchema],
10453
+ ['IdentityProviderSignInUrls', IdentityProviderSignInUrlsSchema],
8549
10454
  ['LoginBody', LoginBodySchema],
8550
10455
  ['AuthorizationResponse', AuthorizationResponseSchema],
8551
10456
  ['CallbackBody', CallbackBodySchema],
@@ -8554,6 +10459,13 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8554
10459
  ['LogoutResult', LogoutResultSchema],
8555
10460
  ['WhoamiResult', WhoamiResultSchema],
8556
10461
  ['UserRecord', UserRecordSchema],
10462
+ ['UnregisterUserResult', UnregisterUserResultSchema],
10463
+ ['CreateUserBody', CreateUserBodySchema],
10464
+ ['PersonGrants', PersonGrantsSchema],
10465
+ ['PersonProjectRole', PersonProjectRoleSchema],
10466
+ ['PersonTeamRole', PersonTeamRoleSchema],
10467
+ ['PersonReviewerRole', PersonReviewerRoleSchema],
10468
+ ['PersonGrantBody', PersonGrantBodySchema],
8557
10469
  ['UserCollectionPage', UserCollectionPageSchema],
8558
10470
  ['IdentitySessionSummary', IdentitySessionSummarySchema],
8559
10471
  ['IdentitySessionCollectionPage', IdentitySessionCollectionPageSchema],
@@ -8641,6 +10553,9 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8641
10553
  // Trigger surface.
8642
10554
  ['TriggerStatus', TriggerStatusSchema],
8643
10555
  ['ScheduleRecord', ScheduleRecordSchema],
10556
+ ['TriggerOwner', TriggerOwnerSchema],
10557
+ ['ScheduleFire', ScheduleFireSchema],
10558
+ ['ScheduleFirePage', ScheduleFirePageSchema],
8644
10559
  ['ScheduleCollectionPage', ScheduleCollectionPageSchema],
8645
10560
  ['RegisterScheduleBody', RegisterScheduleBodySchema],
8646
10561
  ['PatchScheduleBody', PatchScheduleBodySchema],
@@ -8668,6 +10583,9 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
8668
10583
  ['RunTreeUsage', RunTreeUsageSchema],
8669
10584
  ['FinishedRun', FinishedRunSchema],
8670
10585
  ['RunFinishedEvent', RunFinishedEventSchema],
10586
+ ['ImprovementPassFinishedEvent', ImprovementPassFinishedEventSchema],
10587
+ ['ImproveScheduleTarget', ImproveScheduleTargetSchema],
10588
+ ['ImproveScheduleInput', ImproveScheduleInputSchema],
8671
10589
  ['WebhookTestEvent', WebhookTestEventSchema],
8672
10590
  ['WebhookEvent', WebhookEventSchema],
8673
10591
  ['WebhookDeliveryStatus', WebhookDeliveryStatusSchema],