@kindgi/api 0.1.4 → 0.1.5-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/dist/agent-binding.d.ts +13 -0
  2. package/dist/agent-binding.d.ts.map +1 -1
  3. package/dist/agent-pins.d.ts.map +1 -1
  4. package/dist/agent-pins.js +18 -2
  5. package/dist/agent-pins.js.map +1 -1
  6. package/dist/app.d.ts +110 -17
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +163 -35
  9. package/dist/app.js.map +1 -1
  10. package/dist/block-publish.d.ts +56 -0
  11. package/dist/block-publish.d.ts.map +1 -0
  12. package/dist/block-publish.js +132 -0
  13. package/dist/block-publish.js.map +1 -0
  14. package/dist/caller.d.ts +24 -0
  15. package/dist/caller.d.ts.map +1 -0
  16. package/dist/caller.js +47 -0
  17. package/dist/caller.js.map +1 -0
  18. package/dist/capability-binding.d.ts +11 -0
  19. package/dist/capability-binding.d.ts.map +1 -1
  20. package/dist/derive-agent-version.d.ts +7 -0
  21. package/dist/derive-agent-version.d.ts.map +1 -1
  22. package/dist/derive-agent-version.js +4 -0
  23. package/dist/derive-agent-version.js.map +1 -1
  24. package/dist/errors.d.ts.map +1 -1
  25. package/dist/errors.js +73 -7
  26. package/dist/errors.js.map +1 -1
  27. package/dist/eval-case-binding.d.ts +16 -4
  28. package/dist/eval-case-binding.d.ts.map +1 -1
  29. package/dist/eval-run-binding.d.ts +31 -0
  30. package/dist/eval-run-binding.d.ts.map +1 -1
  31. package/dist/eval-run-dispatcher.d.ts +7 -0
  32. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  33. package/dist/eval-run-dispatcher.js.map +1 -1
  34. package/dist/eval-sample.d.ts +11 -0
  35. package/dist/eval-sample.d.ts.map +1 -0
  36. package/dist/eval-sample.js +34 -0
  37. package/dist/eval-sample.js.map +1 -0
  38. package/dist/eval-suite-binding.d.ts +13 -0
  39. package/dist/eval-suite-binding.d.ts.map +1 -1
  40. package/dist/eval-suite-binding.js.map +1 -1
  41. package/dist/flow-binding.d.ts +18 -0
  42. package/dist/flow-binding.d.ts.map +1 -1
  43. package/dist/flow-pins.d.ts.map +1 -1
  44. package/dist/flow-pins.js +18 -2
  45. package/dist/flow-pins.js.map +1 -1
  46. package/dist/gate.d.ts.map +1 -1
  47. package/dist/gate.js +25 -0
  48. package/dist/gate.js.map +1 -1
  49. package/dist/handler-binding.d.ts +32 -0
  50. package/dist/handler-binding.d.ts.map +1 -1
  51. package/dist/hitl-binding.d.ts +23 -0
  52. package/dist/hitl-binding.d.ts.map +1 -1
  53. package/dist/identity-directory-binding.d.ts +82 -4
  54. package/dist/identity-directory-binding.d.ts.map +1 -1
  55. package/dist/identity-provider-binding.d.ts +197 -17
  56. package/dist/identity-provider-binding.d.ts.map +1 -1
  57. package/dist/improvement-pass-binding.d.ts +196 -0
  58. package/dist/improvement-pass-binding.d.ts.map +1 -0
  59. package/dist/improvement-pass-binding.js +9 -0
  60. package/dist/improvement-pass-binding.js.map +1 -0
  61. package/dist/index.d.ts +35 -17
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +11 -3
  64. package/dist/index.js.map +1 -1
  65. package/dist/judged-dispatcher.d.ts +25 -4
  66. package/dist/judged-dispatcher.d.ts.map +1 -1
  67. package/dist/judged-dispatcher.js +43 -6
  68. package/dist/judged-dispatcher.js.map +1 -1
  69. package/dist/judgment-binding.d.ts +25 -1
  70. package/dist/judgment-binding.d.ts.map +1 -1
  71. package/dist/mcp-endpoint-binding.d.ts +7 -0
  72. package/dist/mcp-endpoint-binding.d.ts.map +1 -1
  73. package/dist/memory-binding.d.ts +124 -17
  74. package/dist/memory-binding.d.ts.map +1 -1
  75. package/dist/memory-erasure-binding.d.ts +145 -0
  76. package/dist/memory-erasure-binding.d.ts.map +1 -0
  77. package/dist/memory-erasure-binding.js +4 -0
  78. package/dist/memory-erasure-binding.js.map +1 -0
  79. package/dist/middleware/auth.d.ts +66 -13
  80. package/dist/middleware/auth.d.ts.map +1 -1
  81. package/dist/middleware/auth.js +150 -50
  82. package/dist/middleware/auth.js.map +1 -1
  83. package/dist/middleware/authorize.d.ts +6 -0
  84. package/dist/middleware/authorize.d.ts.map +1 -1
  85. package/dist/middleware/authorize.js +113 -4
  86. package/dist/middleware/authorize.js.map +1 -1
  87. package/dist/middleware/error-mapper.d.ts +5 -0
  88. package/dist/middleware/error-mapper.d.ts.map +1 -1
  89. package/dist/middleware/error-mapper.js +14 -1
  90. package/dist/middleware/error-mapper.js.map +1 -1
  91. package/dist/middleware/idempotency.d.ts +70 -5
  92. package/dist/middleware/idempotency.d.ts.map +1 -1
  93. package/dist/middleware/idempotency.js +174 -41
  94. package/dist/middleware/idempotency.js.map +1 -1
  95. package/dist/middleware/key-project.d.ts +17 -0
  96. package/dist/middleware/key-project.d.ts.map +1 -0
  97. package/dist/middleware/key-project.js +75 -0
  98. package/dist/middleware/key-project.js.map +1 -0
  99. package/dist/middleware/principal.d.ts.map +1 -1
  100. package/dist/middleware/principal.js +9 -5
  101. package/dist/middleware/principal.js.map +1 -1
  102. package/dist/middleware/project-ref.d.ts.map +1 -1
  103. package/dist/middleware/project-ref.js +3 -0
  104. package/dist/middleware/project-ref.js.map +1 -1
  105. package/dist/openapi/generate.d.ts.map +1 -1
  106. package/dist/openapi/generate.js +5 -2
  107. package/dist/openapi/generate.js.map +1 -1
  108. package/dist/openapi/operations.d.ts.map +1 -1
  109. package/dist/openapi/operations.js +918 -139
  110. package/dist/openapi/operations.js.map +1 -1
  111. package/dist/openapi/schemas.d.ts +90 -13
  112. package/dist/openapi/schemas.d.ts.map +1 -1
  113. package/dist/openapi/schemas.js +2081 -359
  114. package/dist/openapi/schemas.js.map +1 -1
  115. package/dist/person-grants-binding.d.ts +77 -0
  116. package/dist/person-grants-binding.d.ts.map +1 -0
  117. package/dist/person-grants-binding.js +4 -0
  118. package/dist/person-grants-binding.js.map +1 -0
  119. package/dist/proposal-service.d.ts +121 -0
  120. package/dist/proposal-service.d.ts.map +1 -0
  121. package/dist/proposal-service.js +447 -0
  122. package/dist/proposal-service.js.map +1 -0
  123. package/dist/proposal-status.d.ts +60 -0
  124. package/dist/proposal-status.d.ts.map +1 -0
  125. package/dist/proposal-status.js +109 -0
  126. package/dist/proposal-status.js.map +1 -0
  127. package/dist/provider-binding.d.ts +10 -0
  128. package/dist/provider-binding.d.ts.map +1 -1
  129. package/dist/publish-refused.d.ts +18 -3
  130. package/dist/publish-refused.d.ts.map +1 -1
  131. package/dist/publish-refused.js +18 -3
  132. package/dist/publish-refused.js.map +1 -1
  133. package/dist/routes/adapters.d.ts +2 -1
  134. package/dist/routes/adapters.d.ts.map +1 -1
  135. package/dist/routes/adapters.js +3 -1
  136. package/dist/routes/adapters.js.map +1 -1
  137. package/dist/routes/agent-releases.d.ts +55 -3
  138. package/dist/routes/agent-releases.d.ts.map +1 -1
  139. package/dist/routes/agent-releases.js +85 -55
  140. package/dist/routes/agent-releases.js.map +1 -1
  141. package/dist/routes/agents.d.ts +12 -1
  142. package/dist/routes/agents.d.ts.map +1 -1
  143. package/dist/routes/agents.js +100 -2
  144. package/dist/routes/agents.js.map +1 -1
  145. package/dist/routes/approvals.d.ts +15 -3
  146. package/dist/routes/approvals.d.ts.map +1 -1
  147. package/dist/routes/approvals.js +133 -122
  148. package/dist/routes/approvals.js.map +1 -1
  149. package/dist/routes/artifacts.d.ts +25 -3
  150. package/dist/routes/artifacts.d.ts.map +1 -1
  151. package/dist/routes/artifacts.js +116 -7
  152. package/dist/routes/artifacts.js.map +1 -1
  153. package/dist/routes/auth.d.ts +25 -1
  154. package/dist/routes/auth.d.ts.map +1 -1
  155. package/dist/routes/auth.js +655 -281
  156. package/dist/routes/auth.js.map +1 -1
  157. package/dist/routes/blocks.d.ts.map +1 -1
  158. package/dist/routes/blocks.js +2 -42
  159. package/dist/routes/blocks.js.map +1 -1
  160. package/dist/routes/capabilities.d.ts +2 -1
  161. package/dist/routes/capabilities.d.ts.map +1 -1
  162. package/dist/routes/capabilities.js +6 -1
  163. package/dist/routes/capabilities.js.map +1 -1
  164. package/dist/routes/compliance.d.ts +9 -10
  165. package/dist/routes/compliance.d.ts.map +1 -1
  166. package/dist/routes/compliance.js +42 -61
  167. package/dist/routes/compliance.js.map +1 -1
  168. package/dist/routes/conversations.d.ts +8 -1
  169. package/dist/routes/conversations.d.ts.map +1 -1
  170. package/dist/routes/conversations.js +87 -8
  171. package/dist/routes/conversations.js.map +1 -1
  172. package/dist/routes/cost.d.ts +7 -1
  173. package/dist/routes/cost.d.ts.map +1 -1
  174. package/dist/routes/cost.js +22 -3
  175. package/dist/routes/cost.js.map +1 -1
  176. package/dist/routes/denied.d.ts +11 -0
  177. package/dist/routes/denied.d.ts.map +1 -0
  178. package/dist/routes/denied.js +17 -0
  179. package/dist/routes/denied.js.map +1 -0
  180. package/dist/routes/deployments.d.ts +2 -1
  181. package/dist/routes/deployments.d.ts.map +1 -1
  182. package/dist/routes/deployments.js +44 -12
  183. package/dist/routes/deployments.js.map +1 -1
  184. package/dist/routes/eval-comparison.d.ts.map +1 -1
  185. package/dist/routes/eval-comparison.js +69 -1
  186. package/dist/routes/eval-comparison.js.map +1 -1
  187. package/dist/routes/eval-overrides.d.ts +18 -0
  188. package/dist/routes/eval-overrides.d.ts.map +1 -0
  189. package/dist/routes/eval-overrides.js +81 -0
  190. package/dist/routes/eval-overrides.js.map +1 -0
  191. package/dist/routes/eval-runs.d.ts +10 -1
  192. package/dist/routes/eval-runs.d.ts.map +1 -1
  193. package/dist/routes/eval-runs.js +63 -7
  194. package/dist/routes/eval-runs.js.map +1 -1
  195. package/dist/routes/eval-suites.d.ts.map +1 -1
  196. package/dist/routes/eval-suites.js +20 -1
  197. package/dist/routes/eval-suites.js.map +1 -1
  198. package/dist/routes/event-triggers.d.ts +5 -1
  199. package/dist/routes/event-triggers.d.ts.map +1 -1
  200. package/dist/routes/event-triggers.js +26 -3
  201. package/dist/routes/event-triggers.js.map +1 -1
  202. package/dist/routes/export-signing-keys.d.ts +12 -0
  203. package/dist/routes/export-signing-keys.d.ts.map +1 -0
  204. package/dist/routes/export-signing-keys.js +24 -0
  205. package/dist/routes/export-signing-keys.js.map +1 -0
  206. package/dist/routes/flows.d.ts.map +1 -1
  207. package/dist/routes/flows.js +9 -1
  208. package/dist/routes/flows.js.map +1 -1
  209. package/dist/routes/gate-policies.d.ts +4 -1
  210. package/dist/routes/gate-policies.d.ts.map +1 -1
  211. package/dist/routes/gate-policies.js +29 -5
  212. package/dist/routes/gate-policies.js.map +1 -1
  213. package/dist/routes/guardrails.d.ts +16 -14
  214. package/dist/routes/guardrails.d.ts.map +1 -1
  215. package/dist/routes/guardrails.js +39 -3
  216. package/dist/routes/guardrails.js.map +1 -1
  217. package/dist/routes/identity.d.ts +20 -4
  218. package/dist/routes/identity.d.ts.map +1 -1
  219. package/dist/routes/identity.js +246 -6
  220. package/dist/routes/identity.js.map +1 -1
  221. package/dist/routes/improvement-passes.d.ts +52 -0
  222. package/dist/routes/improvement-passes.d.ts.map +1 -0
  223. package/dist/routes/improvement-passes.js +449 -0
  224. package/dist/routes/improvement-passes.js.map +1 -0
  225. package/dist/routes/judged-suites.d.ts +50 -0
  226. package/dist/routes/judged-suites.d.ts.map +1 -1
  227. package/dist/routes/judged-suites.js +66 -27
  228. package/dist/routes/judged-suites.js.map +1 -1
  229. package/dist/routes/judgment-context.d.ts +18 -2
  230. package/dist/routes/judgment-context.d.ts.map +1 -1
  231. package/dist/routes/judgment-context.js +63 -5
  232. package/dist/routes/judgment-context.js.map +1 -1
  233. package/dist/routes/judgment-flow-context.d.ts.map +1 -1
  234. package/dist/routes/judgment-flow-context.js +14 -2
  235. package/dist/routes/judgment-flow-context.js.map +1 -1
  236. package/dist/routes/judgments.d.ts.map +1 -1
  237. package/dist/routes/judgments.js +8 -1
  238. package/dist/routes/judgments.js.map +1 -1
  239. package/dist/routes/mcp.d.ts.map +1 -1
  240. package/dist/routes/mcp.js +26 -1
  241. package/dist/routes/mcp.js.map +1 -1
  242. package/dist/routes/memory-access.d.ts +43 -0
  243. package/dist/routes/memory-access.d.ts.map +1 -0
  244. package/dist/routes/memory-access.js +129 -0
  245. package/dist/routes/memory-access.js.map +1 -0
  246. package/dist/routes/memory-erasures.d.ts +25 -0
  247. package/dist/routes/memory-erasures.d.ts.map +1 -0
  248. package/dist/routes/memory-erasures.js +214 -0
  249. package/dist/routes/memory-erasures.js.map +1 -0
  250. package/dist/routes/memory-parse.d.ts +38 -0
  251. package/dist/routes/memory-parse.d.ts.map +1 -0
  252. package/dist/routes/memory-parse.js +199 -0
  253. package/dist/routes/memory-parse.js.map +1 -0
  254. package/dist/routes/memory.d.ts +9 -4
  255. package/dist/routes/memory.d.ts.map +1 -1
  256. package/dist/routes/memory.js +226 -234
  257. package/dist/routes/memory.js.map +1 -1
  258. package/dist/routes/observations.d.ts +4 -1
  259. package/dist/routes/observations.d.ts.map +1 -1
  260. package/dist/routes/observations.js +8 -2
  261. package/dist/routes/observations.js.map +1 -1
  262. package/dist/routes/pagination.d.ts +7 -0
  263. package/dist/routes/pagination.d.ts.map +1 -1
  264. package/dist/routes/pagination.js +10 -0
  265. package/dist/routes/pagination.js.map +1 -1
  266. package/dist/routes/policies.d.ts +2 -1
  267. package/dist/routes/policies.d.ts.map +1 -1
  268. package/dist/routes/policies.js +3 -1
  269. package/dist/routes/policies.js.map +1 -1
  270. package/dist/routes/project-mismatch.d.ts +22 -0
  271. package/dist/routes/project-mismatch.d.ts.map +1 -0
  272. package/dist/routes/project-mismatch.js +34 -0
  273. package/dist/routes/project-mismatch.js.map +1 -0
  274. package/dist/routes/projects.d.ts +15 -4
  275. package/dist/routes/projects.d.ts.map +1 -1
  276. package/dist/routes/projects.js +100 -9
  277. package/dist/routes/projects.js.map +1 -1
  278. package/dist/routes/proposals.d.ts +25 -17
  279. package/dist/routes/proposals.d.ts.map +1 -1
  280. package/dist/routes/proposals.js +340 -507
  281. package/dist/routes/proposals.js.map +1 -1
  282. package/dist/routes/provenance.d.ts +17 -3
  283. package/dist/routes/provenance.d.ts.map +1 -1
  284. package/dist/routes/provenance.js +79 -103
  285. package/dist/routes/provenance.js.map +1 -1
  286. package/dist/routes/providers.d.ts +17 -1
  287. package/dist/routes/providers.d.ts.map +1 -1
  288. package/dist/routes/providers.js +110 -3
  289. package/dist/routes/providers.js.map +1 -1
  290. package/dist/routes/public-run-tokens.d.ts.map +1 -1
  291. package/dist/routes/public-run-tokens.js +3 -0
  292. package/dist/routes/public-run-tokens.js.map +1 -1
  293. package/dist/routes/runs.d.ts +10 -0
  294. package/dist/routes/runs.d.ts.map +1 -1
  295. package/dist/routes/runs.js +92 -42
  296. package/dist/routes/runs.js.map +1 -1
  297. package/dist/routes/schedules.d.ts +21 -13
  298. package/dist/routes/schedules.d.ts.map +1 -1
  299. package/dist/routes/schedules.js +416 -55
  300. package/dist/routes/schedules.js.map +1 -1
  301. package/dist/routes/segments.d.ts +2 -0
  302. package/dist/routes/segments.d.ts.map +1 -1
  303. package/dist/routes/segments.js +5 -0
  304. package/dist/routes/segments.js.map +1 -1
  305. package/dist/routes/service-accounts.d.ts +17 -0
  306. package/dist/routes/service-accounts.d.ts.map +1 -0
  307. package/dist/routes/service-accounts.js +212 -0
  308. package/dist/routes/service-accounts.js.map +1 -0
  309. package/dist/routes/sign-in-options.d.ts +50 -0
  310. package/dist/routes/sign-in-options.d.ts.map +1 -0
  311. package/dist/routes/sign-in-options.js +98 -0
  312. package/dist/routes/sign-in-options.js.map +1 -0
  313. package/dist/routes/signing-keys.d.ts +2 -1
  314. package/dist/routes/signing-keys.d.ts.map +1 -1
  315. package/dist/routes/signing-keys.js +3 -1
  316. package/dist/routes/signing-keys.js.map +1 -1
  317. package/dist/routes/tenant-access.d.ts +13 -0
  318. package/dist/routes/tenant-access.d.ts.map +1 -0
  319. package/dist/routes/tenant-access.js +26 -0
  320. package/dist/routes/tenant-access.js.map +1 -0
  321. package/dist/routes/tenant.d.ts.map +1 -1
  322. package/dist/routes/tenant.js +4 -0
  323. package/dist/routes/tenant.js.map +1 -1
  324. package/dist/routes/token-sign-in.d.ts +36 -0
  325. package/dist/routes/token-sign-in.d.ts.map +1 -0
  326. package/dist/routes/token-sign-in.js +101 -0
  327. package/dist/routes/token-sign-in.js.map +1 -0
  328. package/dist/routes/tokens.d.ts +15 -5
  329. package/dist/routes/tokens.d.ts.map +1 -1
  330. package/dist/routes/tokens.js +162 -43
  331. package/dist/routes/tokens.js.map +1 -1
  332. package/dist/routes/tools.d.ts.map +1 -1
  333. package/dist/routes/tools.js +9 -1
  334. package/dist/routes/tools.js.map +1 -1
  335. package/dist/routes/trigger-access.d.ts +29 -0
  336. package/dist/routes/trigger-access.d.ts.map +1 -0
  337. package/dist/routes/trigger-access.js +33 -0
  338. package/dist/routes/trigger-access.js.map +1 -0
  339. package/dist/routes/webhook-endpoints.d.ts +2 -1
  340. package/dist/routes/webhook-endpoints.d.ts.map +1 -1
  341. package/dist/routes/webhook-endpoints.js +11 -3
  342. package/dist/routes/webhook-endpoints.js.map +1 -1
  343. package/dist/routes/webhooks.d.ts +5 -1
  344. package/dist/routes/webhooks.d.ts.map +1 -1
  345. package/dist/routes/webhooks.js +25 -2
  346. package/dist/routes/webhooks.js.map +1 -1
  347. package/dist/run-failure.d.ts +21 -0
  348. package/dist/run-failure.d.ts.map +1 -0
  349. package/dist/run-failure.js +29 -0
  350. package/dist/run-failure.js.map +1 -0
  351. package/dist/service-account-binding.d.ts +108 -0
  352. package/dist/service-account-binding.d.ts.map +1 -0
  353. package/dist/service-account-binding.js +4 -0
  354. package/dist/service-account-binding.js.map +1 -0
  355. package/dist/session-store-binding.d.ts +61 -13
  356. package/dist/session-store-binding.d.ts.map +1 -1
  357. package/dist/signed-export.d.ts +89 -0
  358. package/dist/signed-export.d.ts.map +1 -0
  359. package/dist/signed-export.js +149 -0
  360. package/dist/signed-export.js.map +1 -0
  361. package/dist/supervisor-binding.d.ts +186 -413
  362. package/dist/supervisor-binding.d.ts.map +1 -1
  363. package/dist/testing/app-bindings.d.ts +33 -0
  364. package/dist/testing/app-bindings.d.ts.map +1 -0
  365. package/dist/testing/app-bindings.js +112 -0
  366. package/dist/testing/app-bindings.js.map +1 -0
  367. package/dist/testing/index.d.ts +11 -0
  368. package/dist/testing/index.d.ts.map +1 -0
  369. package/dist/testing/index.js +13 -0
  370. package/dist/testing/index.js.map +1 -0
  371. package/dist/testing/stub-binding.d.ts +34 -0
  372. package/dist/testing/stub-binding.d.ts.map +1 -0
  373. package/dist/testing/stub-binding.js +42 -0
  374. package/dist/testing/stub-binding.js.map +1 -0
  375. package/dist/testing/trigger-registry.d.ts +21 -0
  376. package/dist/testing/trigger-registry.d.ts.map +1 -0
  377. package/dist/testing/trigger-registry.js +206 -0
  378. package/dist/testing/trigger-registry.js.map +1 -0
  379. package/dist/token-admin.d.ts +46 -8
  380. package/dist/token-admin.d.ts.map +1 -1
  381. package/dist/token-admin.js.map +1 -1
  382. package/dist/tool-binding.d.ts +13 -0
  383. package/dist/tool-binding.d.ts.map +1 -1
  384. package/dist/trigger-binding.d.ts +2 -2
  385. package/dist/trigger-binding.d.ts.map +1 -1
  386. package/dist/trigger-binding.js +1 -1
  387. package/dist/trigger-binding.js.map +1 -1
  388. package/dist/types.d.ts +16 -0
  389. package/dist/types.d.ts.map +1 -1
  390. package/dist/webhook-endpoint-binding.d.ts +19 -3
  391. package/dist/webhook-endpoint-binding.d.ts.map +1 -1
  392. package/dist/webhook-endpoint-binding.js +1 -1
  393. package/dist/webhook-endpoint-binding.js.map +1 -1
  394. package/openapi.json +15385 -8788
  395. package/package.json +26 -22
  396. package/src/agent-binding.ts +14 -0
  397. package/src/agent-pins.ts +18 -2
  398. package/src/app.ts +366 -80
  399. package/src/block-publish.ts +181 -0
  400. package/src/caller.ts +62 -0
  401. package/src/capability-binding.ts +12 -0
  402. package/src/derive-agent-version.ts +9 -1
  403. package/src/errors.ts +73 -7
  404. package/src/eval-case-binding.ts +17 -1
  405. package/src/eval-run-binding.ts +31 -0
  406. package/src/eval-run-dispatcher.ts +7 -0
  407. package/src/eval-sample.ts +42 -0
  408. package/src/eval-suite-binding.ts +14 -0
  409. package/src/flow-binding.ts +19 -0
  410. package/src/flow-pins.ts +18 -2
  411. package/src/gate.ts +26 -0
  412. package/src/handler-binding.ts +36 -1
  413. package/src/hitl-binding.ts +24 -0
  414. package/src/identity-directory-binding.ts +85 -4
  415. package/src/identity-provider-binding.ts +216 -21
  416. package/src/improvement-pass-binding.ts +193 -0
  417. package/src/index.ts +153 -31
  418. package/src/judged-dispatcher.ts +78 -11
  419. package/src/judgment-binding.ts +25 -1
  420. package/src/mcp-endpoint-binding.ts +7 -0
  421. package/src/memory-binding.ts +121 -17
  422. package/src/memory-erasure-binding.ts +156 -0
  423. package/src/middleware/auth.ts +228 -62
  424. package/src/middleware/authorize.ts +139 -3
  425. package/src/middleware/error-mapper.ts +15 -1
  426. package/src/middleware/idempotency.ts +230 -43
  427. package/src/middleware/key-project.ts +86 -0
  428. package/src/middleware/principal.ts +9 -5
  429. package/src/middleware/project-ref.ts +3 -0
  430. package/src/openapi/generate.ts +11 -2
  431. package/src/openapi/operations.ts +1059 -142
  432. package/src/openapi/schemas.ts +2387 -469
  433. package/src/person-grants-binding.ts +76 -0
  434. package/src/proposal-service.ts +640 -0
  435. package/src/proposal-status.ts +176 -0
  436. package/src/provider-binding.ts +10 -0
  437. package/src/publish-refused.ts +38 -9
  438. package/src/routes/adapters.ts +4 -0
  439. package/src/routes/agent-releases.ts +121 -69
  440. package/src/routes/agents.ts +128 -1
  441. package/src/routes/approvals.ts +164 -154
  442. package/src/routes/artifacts.ts +181 -11
  443. package/src/routes/auth.ts +804 -336
  444. package/src/routes/blocks.ts +2 -53
  445. package/src/routes/capabilities.ts +10 -1
  446. package/src/routes/compliance.ts +60 -99
  447. package/src/routes/conversations.ts +101 -7
  448. package/src/routes/cost.ts +32 -3
  449. package/src/routes/denied.ts +28 -0
  450. package/src/routes/deployments.ts +62 -16
  451. package/src/routes/eval-comparison.ts +81 -2
  452. package/src/routes/eval-overrides.ts +108 -0
  453. package/src/routes/eval-runs.ts +86 -6
  454. package/src/routes/eval-suites.ts +25 -1
  455. package/src/routes/event-triggers.ts +27 -3
  456. package/src/routes/export-signing-keys.ts +31 -0
  457. package/src/routes/flows.ts +12 -1
  458. package/src/routes/gate-policies.ts +37 -6
  459. package/src/routes/guardrails.ts +61 -2
  460. package/src/routes/identity.ts +328 -10
  461. package/src/routes/improvement-passes.ts +541 -0
  462. package/src/routes/judged-suites.ts +113 -43
  463. package/src/routes/judgment-context.ts +76 -5
  464. package/src/routes/judgment-flow-context.ts +16 -2
  465. package/src/routes/judgments.ts +17 -3
  466. package/src/routes/mcp.ts +29 -1
  467. package/src/routes/memory-access.ts +179 -0
  468. package/src/routes/memory-erasures.ts +240 -0
  469. package/src/routes/memory-parse.ts +250 -0
  470. package/src/routes/memory.ts +244 -286
  471. package/src/routes/observations.ts +15 -2
  472. package/src/routes/pagination.ts +12 -0
  473. package/src/routes/policies.ts +7 -1
  474. package/src/routes/project-mismatch.ts +56 -0
  475. package/src/routes/projects.ts +107 -13
  476. package/src/routes/proposals.ts +370 -611
  477. package/src/routes/provenance.ts +99 -133
  478. package/src/routes/providers.ts +142 -3
  479. package/src/routes/public-run-tokens.ts +3 -0
  480. package/src/routes/runs.ts +119 -39
  481. package/src/routes/schedules.ts +472 -60
  482. package/src/routes/segments.ts +11 -0
  483. package/src/routes/service-accounts.ts +262 -0
  484. package/src/routes/sign-in-options.ts +168 -0
  485. package/src/routes/signing-keys.ts +7 -1
  486. package/src/routes/tenant-access.ts +37 -0
  487. package/src/routes/tenant.ts +6 -0
  488. package/src/routes/token-sign-in.ts +161 -0
  489. package/src/routes/tokens.ts +172 -46
  490. package/src/routes/tools.ts +12 -1
  491. package/src/routes/trigger-access.ts +72 -0
  492. package/src/routes/webhook-endpoints.ts +15 -3
  493. package/src/routes/webhooks.ts +26 -2
  494. package/src/run-failure.ts +42 -0
  495. package/src/service-account-binding.ts +113 -0
  496. package/src/session-store-binding.ts +65 -13
  497. package/src/signed-export.ts +250 -0
  498. package/src/supervisor-binding.ts +169 -409
  499. package/src/testing/app-bindings.ts +142 -0
  500. package/src/testing/index.ts +21 -0
  501. package/src/testing/stub-binding.ts +53 -0
  502. package/src/testing/trigger-registry.ts +259 -0
  503. package/src/token-admin.ts +40 -8
  504. package/src/tool-binding.ts +14 -0
  505. package/src/trigger-binding.ts +8 -1
  506. package/src/types.ts +16 -0
  507. package/src/webhook-endpoint-binding.ts +18 -3
@@ -0,0 +1,113 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import type { ProjectRole } from '@kindgi/platform';
5
+ import type { Cursor, Result, TenantId, Timestamp } from '@kindgi/types';
6
+
7
+ /**
8
+ * Service accounts: named, non-human principals (`service_account:<id>`)
9
+ * for an app, a pipeline or a schedule's runs. A service account holds
10
+ * its own grants, set when it's created and changed by a tenant admin,
11
+ * and acts through API keys minted for it (`POST /v1/tokens` with `for`),
12
+ * several at once for rotation. Every route needs a tenant admin.
13
+ *
14
+ * Grants are written before a call answers, so a key minted for a new
15
+ * account works on its first request. Unregistering an account is a
16
+ * tombstone: its grants go, its keys stop working, and it stays readable.
17
+ */
18
+
19
+ /**
20
+ * What a service account may do: tenant admin, tenant member (read the
21
+ * tenant's settings), or a role on one project. Unlike a person, an
22
+ * account isn't a tenant member unless it's granted that.
23
+ */
24
+ export type ServiceAccountGrant =
25
+ | { readonly kind: 'tenant-admin' }
26
+ | { readonly kind: 'tenant-member' }
27
+ | { readonly kind: 'project'; readonly projectId: string; readonly role: ProjectRole };
28
+
29
+ /** A grant to remove: tenant admin, tenant member, or whatever role the account has on a project. */
30
+ export type ServiceAccountGrantTarget =
31
+ | { readonly kind: 'tenant-admin' }
32
+ | { readonly kind: 'tenant-member' }
33
+ | { readonly kind: 'project'; readonly projectId: string };
34
+
35
+ export interface ServiceAccount {
36
+ readonly serviceAccountId: string;
37
+ readonly tenantId: TenantId;
38
+ /** Unique among the tenant's active accounts, e.g. `acme-ci`. */
39
+ readonly name: string;
40
+ readonly description?: string;
41
+ /** Its grants, at the time of the read. */
42
+ readonly grants: readonly ServiceAccountGrant[];
43
+ /** Who created it: `user:<id>` or `service_account:<id>`. */
44
+ readonly createdBy?: string;
45
+ readonly createdAt: Timestamp;
46
+ /** Set once unregistered: no grants, and its keys no longer work. */
47
+ readonly unregisteredAt?: Timestamp;
48
+ }
49
+
50
+ export interface ServiceAccountCreateInput {
51
+ readonly tenantId: TenantId;
52
+ readonly name: string;
53
+ readonly description?: string;
54
+ /** Written with the account, before `create` returns. */
55
+ readonly grants: readonly ServiceAccountGrant[];
56
+ readonly createdBy?: string;
57
+ }
58
+
59
+ export interface ServiceAccountRef {
60
+ readonly tenantId: TenantId;
61
+ readonly serviceAccountId: string;
62
+ }
63
+
64
+ /** A change to an account, and who made it: `user:<id>` or `service_account:<id>`. */
65
+ export interface ServiceAccountChange extends ServiceAccountRef {
66
+ readonly by?: string;
67
+ }
68
+
69
+ export interface ServiceAccountListInput {
70
+ readonly tenantId: TenantId;
71
+ readonly limit: number;
72
+ readonly cursor?: Cursor;
73
+ /** Unregistered accounts too (default: active only). */
74
+ readonly includeUnregistered?: boolean;
75
+ }
76
+
77
+ export type ServiceAccountErrorCode =
78
+ /** An active account of the tenant already has this name. */
79
+ | 'service-account-name-taken'
80
+ | 'service-account-not-found'
81
+ /** A grant for an unregistered account. */
82
+ | 'service-account-unregistered'
83
+ /** A grant names a project the tenant doesn't have. */
84
+ | 'project-not-found';
85
+
86
+ export interface ServiceAccountError {
87
+ readonly code: ServiceAccountErrorCode;
88
+ readonly message: string;
89
+ }
90
+
91
+ export interface ServiceAccountBinding {
92
+ create(input: ServiceAccountCreateInput): Promise<Result<ServiceAccount, ServiceAccountError>>;
93
+ /** Unregistered accounts too, or `null`. */
94
+ get(input: ServiceAccountRef): Promise<ServiceAccount | null>;
95
+ /** Oldest first. */
96
+ list(input: ServiceAccountListInput): Promise<{
97
+ readonly data: readonly ServiceAccount[];
98
+ readonly nextCursor?: Cursor;
99
+ }>;
100
+ /**
101
+ * Add a grant (a no-op when held). A project role replaces the
102
+ * account's role on that project. Not for an unregistered account.
103
+ */
104
+ grant(
105
+ input: ServiceAccountChange & { readonly grant: ServiceAccountGrant },
106
+ ): Promise<Result<ServiceAccount, ServiceAccountError>>;
107
+ /** Remove a grant (a no-op when not held). */
108
+ ungrant(
109
+ input: ServiceAccountChange & { readonly grant: ServiceAccountGrantTarget },
110
+ ): Promise<Result<ServiceAccount, ServiceAccountError>>;
111
+ /** Tombstone the account: its grants go and its keys stop working. Idempotent. */
112
+ unregister(input: ServiceAccountChange): Promise<Result<ServiceAccount, ServiceAccountError>>;
113
+ }
@@ -13,15 +13,19 @@ import type { Cursor, SessionId, TenantId, Timestamp, UserId } from '@kindgi/typ
13
13
  * `POST /v1/auth/callback/:providerId` exchanges the authorization code
14
14
  * for provider tokens, fetches the userinfo, and calls
15
15
  * `SessionStoreBinding.create` to persist the resulting session; the
16
- * route then hands the caller an opaque framework-issued token
17
- * (`kgi_sk_<sessionId>`) that never leaks the provider access-token or
18
- * refresh-token to the client.
16
+ * route then hands the caller an opaque session token (`kgi_sk_…`) that
17
+ * never leaks the provider access-token or refresh-token to the client.
19
18
  *
20
- * The bearer-auth middleware routes session-token requests through
21
- * `get(tenantId, sessionId)`; the resolver hot path runs on every
22
- * authenticated request that carries a session token, so implementations
23
- * SHOULD keep `get` cheap (e.g. a single indexed lookup by id and
24
- * expiry, or a cache).
19
+ * A store that implements `resolveToken` owns the token: `create` mints it
20
+ * (returned once, as `token`), the store keeps only a hash, and the
21
+ * bearer-auth middleware hands every `kgi_sk_` token to `resolveToken`.
22
+ * A store without it gets the older token, `kgi_sk_<sessionId>`, which
23
+ * the middleware resolves through `get` with `MULTI_TENANT_LOOKUP`;
24
+ * anyone who can read such a store's session ids can use the sessions.
25
+ *
26
+ * The resolver hot path runs on every authenticated request that carries
27
+ * a session token, so implementations SHOULD keep it cheap (a single
28
+ * indexed lookup, or a cache).
25
29
  */
26
30
  export interface SessionStoreBinding {
27
31
  create(input: SessionCreateInput): Promise<SessionCreateOutput>;
@@ -29,6 +33,21 @@ export interface SessionStoreBinding {
29
33
  list(input: SessionListInput): Promise<SessionPage>;
30
34
  revoke(input: SessionRevokeInput): Promise<SessionRevokeOutcome>;
31
35
  revokeAllForUser(input: SessionRevokeAllForUserInput): Promise<SessionRevokeAllForUserOutcome>;
36
+ /**
37
+ * The session a token names, or `null` when it names none: an unknown,
38
+ * malformed or tampered token, or one in a format this store didn't
39
+ * mint. The store reads the token's tenant from the token itself and
40
+ * looks only in that tenant, comparing a hash of the token with what it
41
+ * stored (in constant time); nothing is read across tenants before the
42
+ * token is authenticated.
43
+ *
44
+ * A revoked, rotated or expired session is still returned (with
45
+ * `revokedAt`, `rotatedAt`, `expiresAt`): the middleware says which.
46
+ *
47
+ * When present, the middleware never calls `get` with
48
+ * `MULTI_TENANT_LOOKUP`, and `create` must return `token`.
49
+ */
50
+ readonly resolveToken?: (input: SessionResolveTokenInput) => Promise<Session | null>;
32
51
  /**
33
52
  * Update the session's `lastActiveAt` marker. Called by the auth
34
53
  * middleware on each successful authenticated request (throttled, by
@@ -36,10 +55,31 @@ export interface SessionStoreBinding {
36
55
  * doesn't hot-spot under load). Absent = the middleware only enforces absolute
37
56
  * TTL; inactivity timeout is disabled.
38
57
  *
39
- * The tenant sentinel `MULTI_TENANT_LOOKUP` is honored the same way
40
- * as `get` — the middleware doesn't know the tenant ahead of time.
58
+ * The middleware passes the session's own tenant. A store without
59
+ * `resolveToken` must also honor the sentinel `MULTI_TENANT_LOOKUP`,
60
+ * as `get` does.
41
61
  */
42
62
  readonly touch?: (input: SessionTouchInput) => Promise<SessionTouchOutcome>;
63
+ /**
64
+ * End every live session one provider opened, in one tenant: the console
65
+ * sessions an API key opened (`api-token:<tokenId>`, from token sign-in)
66
+ * when it's revoked; an identity provider's sign-ins when it's removed.
67
+ * Absent → those sessions run until they expire.
68
+ */
69
+ readonly revokeByProvider?: (
70
+ input: SessionRevokeByProviderInput,
71
+ ) => Promise<SessionRevokeAllForUserOutcome>;
72
+ }
73
+
74
+ export interface SessionRevokeByProviderInput {
75
+ readonly tenantId: TenantId;
76
+ /** The `providerId` the sessions were created with. */
77
+ readonly providerId: string;
78
+ }
79
+
80
+ export interface SessionResolveTokenInput {
81
+ /** The whole token, as the caller sent it (`kgi_sk_…`). */
82
+ readonly token: string;
43
83
  }
44
84
 
45
85
  export interface SessionCreateInput {
@@ -47,8 +87,12 @@ export interface SessionCreateInput {
47
87
  readonly userId: UserId;
48
88
  /** ProviderId of the `IdentityProviderBinding` that authenticated the user. */
49
89
  readonly providerId: string;
50
- /** Opaque provider access-token — server-side only. */
51
- readonly accessToken: string;
90
+ /**
91
+ * Opaque provider access-token, server-side only. Absent when the
92
+ * deployment keeps no identity-provider tokens (a sign-in that only
93
+ * establishes who the person is).
94
+ */
95
+ readonly accessToken?: string;
52
96
  /** Opaque provider refresh-token — server-side only, may be absent. */
53
97
  readonly refreshToken?: string;
54
98
  readonly expiresAt: Timestamp;
@@ -60,6 +104,13 @@ export interface SessionCreateInput {
60
104
  export interface SessionCreateOutput {
61
105
  readonly sessionId: SessionId;
62
106
  readonly expiresAt: Timestamp;
107
+ /**
108
+ * The session token the store minted, returned this once (the store
109
+ * keeps only its hash). Required from a store that implements
110
+ * `resolveToken`; absent from an older store, whose token is
111
+ * `kgi_sk_<sessionId>`.
112
+ */
113
+ readonly token?: string;
63
114
  }
64
115
 
65
116
  export interface SessionGetInput {
@@ -99,7 +150,8 @@ export interface Session {
99
150
  readonly tenantId: TenantId;
100
151
  readonly userId: UserId;
101
152
  readonly providerId: string;
102
- readonly accessToken: string;
153
+ /** Absent when the deployment keeps no identity-provider tokens. */
154
+ readonly accessToken?: string;
103
155
  readonly refreshToken?: string;
104
156
  readonly expiresAt: Timestamp;
105
157
  readonly scopes: readonly string[];
@@ -0,0 +1,250 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ /**
5
+ * Signed exports: one envelope and one signing path for the three
6
+ * exports a deployment signs (an approval's audit bundle, a run's
7
+ * provenance, compliance evidence).
8
+ *
9
+ * The envelope carries the exact bytes that were signed (`bundle`,
10
+ * base64 of the sorted-key JSON body), so a verifier checks those bytes
11
+ * and never re-serializes anything. `exportedAt` is inside the signed
12
+ * body, and the envelope's copy is the same value.
13
+ *
14
+ * Each export is recorded as an `export-signed` audit event (who, what,
15
+ * which key, the bundle's SHA-256) when the app has an audit-event
16
+ * binding. Recording comes before the bundle is returned: a bundle the
17
+ * record couldn't be written for isn't handed out.
18
+ */
19
+
20
+ import { createHash, randomUUID } from 'node:crypto';
21
+
22
+ import type { AuditEvent, AuditEventBinding } from '@kindgi/audit-events';
23
+ import type {
24
+ ExportSigningAlgorithm,
25
+ ExportSigningBinding,
26
+ ExportSigningError,
27
+ } from '@kindgi/crypto';
28
+ import { canonicalize } from '@kindgi/schema';
29
+ import type { ProjectId, TenantId, Timestamp } from '@kindgi/types';
30
+ import type { Context } from 'hono';
31
+
32
+ import { statusFor, toWireError } from './errors.js';
33
+ import type { AppEnv } from './types.js';
34
+
35
+ export type SignedExportKind = 'audit-bundle' | 'provenance' | 'compliance';
36
+
37
+ /** The audit-event kind each signed export is recorded under. */
38
+ export const EXPORT_SIGNED_EVENT_KIND = 'export-signed';
39
+
40
+ /** What every signed export answers, before its subject field (`approvalId`, `runId`, `tenantId`). */
41
+ export interface SignedExportEnvelope {
42
+ readonly kind: SignedExportKind;
43
+ /** Base64 of the signed bytes: the body, as sorted-key JSON. */
44
+ readonly bundle: string;
45
+ readonly bundleSchemaVersion: string;
46
+ /** The signing key's algorithm: `ed25519`, or `ecdsa-p256-sha256` for a KMS without Ed25519. */
47
+ readonly algorithm: ExportSigningAlgorithm;
48
+ readonly signingKeyId: string;
49
+ /**
50
+ * Base64 of the signature over the `bundle` bytes: 64 bytes either way,
51
+ * Ed25519's, or ECDSA P-256's as IEEE P1363 `r‖s`.
52
+ */
53
+ readonly signature: string;
54
+ /** The signing key's public half, PEM SPKI. Check it against `GET /v1/export-signing-keys`. */
55
+ readonly publicKey: string;
56
+ readonly canonicalization: 'sorted-key-json';
57
+ /** The same instant as the signed body's `exportedAt`. */
58
+ readonly exportedAt: string;
59
+ }
60
+
61
+ export interface SignExportInput {
62
+ readonly signer: ExportSigningBinding;
63
+ readonly kind: SignedExportKind;
64
+ readonly bundleSchemaVersion: string;
65
+ /** The body without `bundleSchemaVersion` and `exportedAt`: both are added, and signed. */
66
+ readonly body: Readonly<Record<string, unknown>>;
67
+ readonly signingKeyId?: string;
68
+ readonly now?: () => Date;
69
+ /** Record the export (an `export-signed` audit event) before answering. */
70
+ readonly record?: {
71
+ readonly auditEvents: AuditEventBinding;
72
+ readonly tenantId: TenantId;
73
+ readonly projectId?: ProjectId;
74
+ readonly runId?: string;
75
+ readonly actor: string;
76
+ /** The exported thing: `{ approvalId }`, `{ runId }`, or the compliance filter. */
77
+ readonly subject: Readonly<Record<string, unknown>>;
78
+ };
79
+ }
80
+
81
+ export type SignExportError =
82
+ | ExportSigningError
83
+ | { readonly code: 'persistence-error'; readonly message: string };
84
+
85
+ /** Sign an export's body and, when asked, record it. */
86
+ export async function signExport(
87
+ input: SignExportInput,
88
+ ): Promise<
89
+ | { readonly kind: 'ok'; readonly value: SignedExportEnvelope }
90
+ | { readonly kind: 'err'; readonly error: SignExportError }
91
+ > {
92
+ const exportedAt = (input.now?.() ?? new Date()).toISOString();
93
+ const body = { ...input.body, bundleSchemaVersion: input.bundleSchemaVersion, exportedAt };
94
+ const bytes = new TextEncoder().encode(canonicalize(body));
95
+ const signed = await input.signer.sign(
96
+ bytes,
97
+ input.signingKeyId !== undefined ? { keyId: input.signingKeyId } : undefined,
98
+ );
99
+ if (signed.kind === 'err') return signed;
100
+ const envelope: SignedExportEnvelope = {
101
+ kind: input.kind,
102
+ bundle: Buffer.from(bytes).toString('base64'),
103
+ bundleSchemaVersion: input.bundleSchemaVersion,
104
+ algorithm: signed.value.key.algorithm,
105
+ signingKeyId: signed.value.key.keyId,
106
+ signature: Buffer.from(signed.value.signature).toString('base64'),
107
+ publicKey: signed.value.key.publicKeyPem,
108
+ canonicalization: 'sorted-key-json',
109
+ exportedAt,
110
+ };
111
+ if (input.record !== undefined) {
112
+ const recorded = await recordExport(input.record, envelope, bytes);
113
+ if (recorded !== undefined) return { kind: 'err', error: recorded };
114
+ }
115
+ return { kind: 'ok', value: envelope };
116
+ }
117
+
118
+ async function recordExport(
119
+ record: NonNullable<SignExportInput['record']>,
120
+ envelope: SignedExportEnvelope,
121
+ bytes: Uint8Array,
122
+ ): Promise<SignExportError | undefined> {
123
+ const event: AuditEvent = {
124
+ id: randomUUID(),
125
+ tenantId: record.tenantId,
126
+ ...(record.projectId !== undefined && { projectId: record.projectId }),
127
+ kind: EXPORT_SIGNED_EVENT_KIND,
128
+ timestamp: envelope.exportedAt as unknown as Timestamp,
129
+ actor: record.actor,
130
+ ...(record.runId !== undefined && { runId: record.runId }),
131
+ outcome: 'succeeded',
132
+ payload: {
133
+ v: 1,
134
+ doc: {
135
+ exportKind: envelope.kind,
136
+ subject: record.subject,
137
+ signingKeyId: envelope.signingKeyId,
138
+ bundleSha256: createHash('sha256').update(bytes).digest('hex'),
139
+ bundleSchemaVersion: envelope.bundleSchemaVersion,
140
+ exportedAt: envelope.exportedAt,
141
+ },
142
+ },
143
+ };
144
+ const appended = await record.auditEvents.append([event]);
145
+ if (appended.kind === 'ok') return undefined;
146
+ return {
147
+ code: 'persistence-error',
148
+ message: `The export was signed, but recording it failed, so it isn't returned: ${appended.error.message}. Try again.`,
149
+ };
150
+ }
151
+
152
+ /**
153
+ * An export request's body: JSON, an object, or nothing at all (read as
154
+ * `{}`, so `curl -X POST` and a bodiless POST work).
155
+ */
156
+ export async function readExportBody(
157
+ c: Context<AppEnv>,
158
+ ): Promise<
159
+ | { readonly kind: 'ok'; readonly value: Record<string, unknown> }
160
+ | { readonly kind: 'err'; readonly message: string }
161
+ > {
162
+ const text = await c.req.text();
163
+ if (text.trim() === '') return { kind: 'ok', value: {} };
164
+ let body: unknown;
165
+ try {
166
+ body = JSON.parse(text);
167
+ } catch {
168
+ return { kind: 'err', message: 'Request body must be valid JSON' };
169
+ }
170
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) {
171
+ return { kind: 'err', message: 'Request body must be an object' };
172
+ }
173
+ return { kind: 'ok', value: body as Record<string, unknown> };
174
+ }
175
+
176
+ /** `signingKeyId`, when the body names one: a non-empty string. */
177
+ export function parseSigningKeyId(
178
+ body: Readonly<Record<string, unknown>>,
179
+ ):
180
+ | { readonly kind: 'ok'; readonly value: string | undefined }
181
+ | { readonly kind: 'err'; readonly message: string } {
182
+ if (!('signingKeyId' in body) || body.signingKeyId === undefined) {
183
+ return { kind: 'ok', value: undefined };
184
+ }
185
+ const raw = body.signingKeyId;
186
+ if (typeof raw !== 'string' || raw.length === 0) {
187
+ return {
188
+ kind: 'err',
189
+ message:
190
+ 'Field `signingKeyId` must be a non-empty string when present; leave it out to sign with the active key.',
191
+ };
192
+ }
193
+ return { kind: 'ok', value: raw };
194
+ }
195
+
196
+ /** `404 signing-not-configured`: this deployment has no export signing key. */
197
+ export function signingNotConfigured(c: Context<AppEnv>, what: string): Response {
198
+ c.status(statusFor('signing-not-configured') as never);
199
+ return c.json(
200
+ toWireError(
201
+ {
202
+ code: 'signing-not-configured',
203
+ message: `This deployment doesn't sign exports, so ${what} are unavailable: it has no export signing key. On the Kindgi runtime, set KINDGI_EXPORT_SIGNING_KEY_PATH, KINDGI_EXPORT_SIGNING_KEY or KINDGI_EXPORT_SIGNING_KMS_KEY.`,
204
+ },
205
+ c.get('requestId'),
206
+ ),
207
+ );
208
+ }
209
+
210
+ /**
211
+ * A `signExport` failure as the route answers it: `404
212
+ * signing-key-not-found`, `500 persistence-error`, or `500` with
213
+ * `failureCode` (each route keeps the code it answered before).
214
+ */
215
+ export function signExportFailure(
216
+ c: Context<AppEnv>,
217
+ error: SignExportError,
218
+ failureCode: 'export-key-error' | 'compliance-export-failed',
219
+ ): Response {
220
+ const requestId = c.get('requestId');
221
+ if (error.code === 'signing-key-not-found') {
222
+ c.status(statusFor('signing-key-not-found') as never);
223
+ return c.json(
224
+ toWireError(
225
+ { code: 'signing-key-not-found', message: error.message, signingKeyId: error.keyId },
226
+ requestId,
227
+ ),
228
+ );
229
+ }
230
+ if (error.code === 'persistence-error') {
231
+ c.status(statusFor('persistence-error') as never);
232
+ return c.json(toWireError({ code: 'persistence-error', message: error.message }, requestId));
233
+ }
234
+ c.status(statusFor(failureCode) as never);
235
+ return c.json(
236
+ toWireError(
237
+ { code: failureCode, message: `Signing the export failed: ${error.message}` },
238
+ requestId,
239
+ ),
240
+ );
241
+ }
242
+
243
+ /** The caller as an audit actor: `user:<id>`, `service_account:<tokenId>`, or `service_account:unknown`. */
244
+ export function exportActor(c: Context<AppEnv>): string {
245
+ const userId = c.get('userId');
246
+ if (userId !== undefined) return `user:${userId as unknown as string}`;
247
+ const tokenId = c.get('tokenId');
248
+ if (tokenId !== undefined) return `service_account:${tokenId as unknown as string}`;
249
+ return 'service_account:unknown';
250
+ }