@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
@@ -1,8 +1,23 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
- import { denyPayload, } from '@kindgi/authz';
3
+ import { OBJECT_ACTIONS, denyPayload, } from '@kindgi/authz';
4
4
  import { toWireError } from '../errors.js';
5
5
  export function createAuthorizer(binding) {
6
+ /**
7
+ * Whether a resource is inside the project the caller's API key is
8
+ * limited to (always, for a caller with no such key). The tenant, orgs,
9
+ * teams and projects are held by `keyCeilingDeny`; anything else must
10
+ * belong to the key's project, as the store says (`inProject`). Without
11
+ * that answer, the key reaches no other resource.
12
+ */
13
+ async function inKeyProject(c, principal, resource) {
14
+ const keyProject = c.get('tokenProjectId');
15
+ if (keyProject === undefined || STRUCTURAL.has(resource.type))
16
+ return true;
17
+ if (binding.inProject === undefined)
18
+ return false;
19
+ return binding.inProject(principal, resource, keyProject);
20
+ }
6
21
  async function checkInternal(c, action, resource) {
7
22
  const principal = c.get('principal');
8
23
  if (principal === undefined) {
@@ -18,6 +33,15 @@ export function createAuthorizer(binding) {
18
33
  },
19
34
  };
20
35
  }
36
+ const undefinedPair = undefinedRelation(action, resource);
37
+ if (undefinedPair !== undefined)
38
+ return undefinedPair;
39
+ const ceiling = keyCeilingDeny(c, action, resource);
40
+ if (ceiling !== undefined)
41
+ return ceiling;
42
+ if (!(await inKeyProject(c, principal, resource))) {
43
+ return keyDecision(action, resource, `the API key is limited to project ${c.get('tokenProjectId')}`);
44
+ }
21
45
  const requestId = c.get('requestId');
22
46
  const ctx = typeof requestId === 'string' && requestId.length > 0
23
47
  ? { correlationId: requestId }
@@ -58,19 +82,104 @@ export function createAuthorizer(binding) {
58
82
  const principal = c.get('principal');
59
83
  if (principal === undefined)
60
84
  return [];
61
- const refs = items.map(refFn);
85
+ // What the model can't answer, or the key itself rules out, never
86
+ // reaches the store.
87
+ const allowedByKey = await Promise.all(items.map(async (item) => undefinedRelation(action, refFn(item)) === undefined &&
88
+ keyCeilingDeny(c, action, refFn(item)) === undefined &&
89
+ (await inKeyProject(c, principal, refFn(item)))));
90
+ const open = items.filter((_, i) => allowedByKey[i]);
91
+ if (open.length === 0)
92
+ return [];
93
+ const refs = open.map(refFn);
62
94
  const requestId = c.get('requestId');
63
95
  const ctx = typeof requestId === 'string' && requestId.length > 0
64
96
  ? { correlationId: requestId }
65
97
  : undefined;
66
98
  const decisions = await binding.checkBatch(principal, action, refs, ctx);
67
99
  const out = [];
68
- for (let i = 0; i < items.length; i++) {
100
+ for (let i = 0; i < open.length; i++) {
69
101
  if (decisions[i]?.allowed)
70
- out.push(items[i]);
102
+ out.push(open[i]);
71
103
  }
72
104
  return out;
73
105
  },
106
+ async listObjects(c, action, type) {
107
+ if (binding.listObjects === undefined)
108
+ return undefined;
109
+ const principal = c.get('principal');
110
+ if (principal === undefined)
111
+ return [];
112
+ const requestId = c.get('requestId');
113
+ const ctx = typeof requestId === 'string' && requestId.length > 0
114
+ ? { correlationId: requestId }
115
+ : undefined;
116
+ return binding.listObjects(principal, action, type, ctx);
117
+ },
74
118
  };
75
119
  }
120
+ /**
121
+ * A check must name a relation the authorization model defines for the
122
+ * resource's type (`OBJECT_ACTIONS`, kept equal to the runtime's model by
123
+ * its tests). Any other pair is a bug in the route: the PDP rejects it
124
+ * for everyone, the seed admin included, and only with authorization on,
125
+ * so it's refused here, naming the pair, and logged.
126
+ */
127
+ function undefinedRelation(action, resource) {
128
+ const defined = OBJECT_ACTIONS[resource.type];
129
+ if (defined?.includes(action) === true)
130
+ return undefined;
131
+ const reason = `the authorization model has no \`${action}\` on \`${resource.type}\` (a check that can never pass: a bug in the route)`;
132
+ console.error(`[authz] ${reason}`);
133
+ return {
134
+ allowed: false,
135
+ failing: 'invalid-action',
136
+ reason,
137
+ evidence: {
138
+ action,
139
+ relation: '',
140
+ resource: `${resource.type}:${resource.id}`,
141
+ actorSubject: '',
142
+ },
143
+ };
144
+ }
145
+ /** Types a key's project limit is checked on directly, not through `inProject`. */
146
+ const STRUCTURAL = new Set(['tenant', 'org', 'team', 'project']);
147
+ function keyDecision(action, resource, reason) {
148
+ return {
149
+ allowed: false,
150
+ failing: 'scope',
151
+ reason,
152
+ evidence: {
153
+ action,
154
+ relation: '',
155
+ resource: `${resource.type}:${resource.id}`,
156
+ actorSubject: '',
157
+ },
158
+ };
159
+ }
160
+ /**
161
+ * What an API key itself rules out, before the principal's grants are
162
+ * asked: a key can do less than its principal, never more.
163
+ *
164
+ * - A `member` key takes no `admin` action on the tenant, even for a
165
+ * principal who is a tenant admin: a day-to-day key can't change keys,
166
+ * grants or policies. Below the tenant, its principal's roles hold: a
167
+ * project admin's member key administers that project.
168
+ * - A key limited to a project acts on no other project, and takes no
169
+ * `admin` action on the tenant, an org or a team. Other resources must
170
+ * be in its project (`inKeyProject`).
171
+ */
172
+ function keyCeilingDeny(c, action, resource) {
173
+ if (action === 'admin' && resource.type === 'tenant' && c.get('tokenRole') === 'member') {
174
+ return keyDecision(action, resource, 'a member API key takes no admin action on the tenant');
175
+ }
176
+ const keyProject = c.get('tokenProjectId');
177
+ if (keyProject === undefined)
178
+ return undefined;
179
+ const otherProject = resource.type === 'project' && resource.id !== keyProject;
180
+ const aboveIt = resource.type !== 'project' && STRUCTURAL.has(resource.type) && action === 'admin';
181
+ return otherProject || aboveIt
182
+ ? keyDecision(action, resource, `the API key is limited to project ${keyProject}`)
183
+ : undefined;
184
+ }
76
185
  //# sourceMappingURL=authorize.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/middleware/authorize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/middleware/authorize.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,11 @@ import type { Context } from 'hono';
15
15
  *
16
16
  * The requestId embedded in the response body matches
17
17
  * `middleware/request-id.ts`, so a caller can correlate.
18
+ *
19
+ * A failed database query's message carries its SQL and its parameters
20
+ * (Drizzle's `Failed query: … params: …`), which can be a person's email or
21
+ * address: the body says only that a query failed, and the log keeps the
22
+ * whole error.
18
23
  */
19
24
  export declare function mapThrownError(cause: Error, c: Context): Response;
20
25
  //# sourceMappingURL=error-mapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-mapper.d.ts","sourceRoot":"","sources":["../../src/middleware/error-mapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAIpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAG,QAAQ,CAiBjE"}
1
+ {"version":3,"file":"error-mapper.d.ts","sourceRoot":"","sources":["../../src/middleware/error-mapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAIpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAG,QAAQ,CAqBjE"}
@@ -17,6 +17,11 @@ import { statusFor, toWireError } from '../errors.js';
17
17
  *
18
18
  * The requestId embedded in the response body matches
19
19
  * `middleware/request-id.ts`, so a caller can correlate.
20
+ *
21
+ * A failed database query's message carries its SQL and its parameters
22
+ * (Drizzle's `Failed query: … params: …`), which can be a person's email or
23
+ * address: the body says only that a query failed, and the log keeps the
24
+ * whole error.
20
25
  */
21
26
  export function mapThrownError(cause, c) {
22
27
  if ('getResponse' in cause && typeof cause.getResponse === 'function') {
@@ -28,9 +33,17 @@ export function mapThrownError(cause, c) {
28
33
  c.get('log')?.error('unhandled error', { err: cause });
29
34
  const body = toWireError({
30
35
  code: 'internal-server-error',
31
- message: cause.message.length > 0 ? cause.message : 'Unhandled server error',
36
+ message: isQueryError(cause)
37
+ ? 'A database query failed.'
38
+ : cause.message.length > 0
39
+ ? cause.message
40
+ : 'Unhandled server error',
32
41
  }, requestId);
33
42
  c.status(statusFor('internal-server-error'));
34
43
  return c.json(body);
35
44
  }
45
+ /** Drizzle's wrapper around a failed query, whose message is the SQL and its values. */
46
+ function isQueryError(cause) {
47
+ return cause.name === 'DrizzleQueryError' || cause.message.startsWith('Failed query: ');
48
+ }
36
49
  //# sourceMappingURL=error-mapper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-mapper.js","sourceRoot":"","sources":["../../src/middleware/error-mapper.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,CAAU;IACrD,IAAI,aAAa,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,GAAG,GAAI,KAAqC,CAAC,WAAW,EAAE,CAAC;QACjE,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,SAAS,GAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAwB,IAAI,aAAa,CAAC;IAC9E,yEAAyE;IACxE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAwB,EAAE,KAAK,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,WAAW,CACtB;QACE,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;KAC7E,EACD,SAAS,CACV,CAAC;IACF,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAU,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"error-mapper.js","sourceRoot":"","sources":["../../src/middleware/error-mapper.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,CAAU;IACrD,IAAI,aAAa,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,GAAG,GAAI,KAAqC,CAAC,WAAW,EAAE,CAAC;QACjE,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,SAAS,GAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAwB,IAAI,aAAa,CAAC;IAC9E,yEAAyE;IACxE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAwB,EAAE,KAAK,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,WAAW,CACtB;QACE,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC;YAC1B,CAAC,CAAC,0BAA0B;YAC5B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACxB,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,wBAAwB;KAC/B,EACD,SAAS,CACV,CAAC;IACF,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAU,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,wFAAwF;AACxF,SAAS,YAAY,CAAC,KAAY;IAChC,OAAO,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAC1F,CAAC"}
@@ -1,6 +1,7 @@
1
- import type { MiddlewareHandler } from 'hono';
1
+ import type { Context, MiddlewareHandler } from 'hono';
2
+ import type { AppEnv } from '../types.js';
2
3
  /**
3
- * Idempotency-key store: `(tenantId, route, key) → cached response`,
4
+ * Idempotency-key store: `(tenantId, caller, route, key) → cached response`,
4
5
  * cached for `ttlMs` (default 24h per API-ROUTE-CONVENTIONS.md §3.1).
5
6
  *
6
7
  * Injected into the middleware so deployments can plug in a durable
@@ -10,15 +11,65 @@ import type { MiddlewareHandler } from 'hono';
10
11
  */
11
12
  export interface IdempotencyStore {
12
13
  get(key: string): Promise<StoredIdempotencyEntry | null>;
14
+ /** Store an answer. It replaces a hold on the key, never a stored answer: the first stays. */
13
15
  set(key: string, entry: StoredIdempotencyEntry): Promise<void>;
16
+ /**
17
+ * Hold a key while its request runs (T349), so a repeat sent meanwhile
18
+ * is answered 409 `idempotency-key-in-flight` instead of running the
19
+ * operation again. Optional: a store without holds holds nothing, and
20
+ * such a repeat runs again (the behaviour before 0.1.5).
21
+ */
22
+ readonly holds?: IdempotencyHolds;
14
23
  }
24
+ /** A store's holds: all three or none. */
25
+ export interface IdempotencyHolds {
26
+ /** Take the key for `hold.holder`, unless an unexpired hold or a stored answer has it. */
27
+ hold(key: string, hold: IdempotencyHold): Promise<IdempotencyHoldOutcome>;
28
+ /** Extend the holder's hold: its request still runs. */
29
+ renew(key: string, holder: string, expiresAt: number): Promise<void>;
30
+ /** Drop the holder's hold: its request ended with nothing to replay. */
31
+ release(key: string, holder: string): Promise<void>;
32
+ }
33
+ export interface IdempotencyHold {
34
+ /** Who holds it: one id per request. */
35
+ readonly holder: string;
36
+ readonly bodyHash: string;
37
+ readonly expiresAt: number;
38
+ }
39
+ export type IdempotencyHoldOutcome = {
40
+ readonly kind: 'held';
41
+ } | {
42
+ readonly kind: 'in-flight';
43
+ readonly bodyHash: string;
44
+ } | {
45
+ readonly kind: 'stored';
46
+ readonly entry: StoredIdempotencyEntry;
47
+ };
15
48
  export interface StoredIdempotencyEntry {
16
49
  readonly bodyHash: string;
17
50
  readonly status: number;
18
51
  readonly contentType: string;
52
+ /** The answer's body; empty when it's `withheld`. */
19
53
  readonly bodyText: string;
20
54
  readonly expiresAt: number;
55
+ /**
56
+ * The answer carried a secret (`withholdFromReplay`), so only that the
57
+ * request succeeded is kept: a repeat is answered 409
58
+ * `idempotency-key-replay-withheld`, never the secret. Optional: a store
59
+ * that doesn't keep it stores the empty body, and a repeat replays that.
60
+ */
61
+ readonly withheld?: boolean;
62
+ /** When the answer was stored (ms since the epoch), for the withheld 409. */
63
+ readonly storedAt?: number;
21
64
  }
65
+ /**
66
+ * For a route whose answer carries a secret (an API key, a session token,
67
+ * a signing secret): the Idempotency-Key middleware keeps that the request
68
+ * succeeded and when, never the answer. A repeat with the same key gets 409
69
+ * `idempotency-key-replay-withheld` instead of the secret, and instead of
70
+ * running again (which would make a second one). Call it before answering.
71
+ */
72
+ export declare function withholdFromReplay(c: Context<AppEnv>): void;
22
73
  /** Simple in-memory store with lazy expiry — swap for a DB store in prod. */
23
74
  export declare function createInMemoryIdempotencyStore(): IdempotencyStore;
24
75
  /**
@@ -36,12 +87,26 @@ export declare function createInMemoryIdempotencyStore(): IdempotencyStore;
36
87
  * nothing, and a failure (5xx) may be transient: neither is stored, so
37
88
  * a retry with the same key after fixing the cause runs again instead
38
89
  * of replaying the old error.
90
+ * - With a store that holds keys (`store.holds`, T349): the key is held
91
+ * while the handler runs (for `holdMs`, renewed every third of it), so
92
+ * a repeat sent meanwhile gets 409 `idempotency-key-in-flight` with
93
+ * `Retry-After`, or `idempotency-key-body-mismatch` for another body,
94
+ * instead of running the operation again. The hold becomes the stored
95
+ * answer, or is released when nothing is stored. A crashed request's
96
+ * hold lapses within `holdMs`.
97
+ *
98
+ * The middleware sits AFTER auth so `tenantId` is available. The cache
99
+ * key is the tenant, the caller (`user:…`, `service_account:…`, else the
100
+ * key or session it came with), the route and the key: someone else in
101
+ * the tenant who sends the same key and body runs the request themselves,
102
+ * and never gets another caller's answer (T392).
39
103
  *
40
- * The middleware sits AFTER auth so `tenantId` is available; the
41
- * cache key is namespaced by tenant so callers can't collide across
42
- * tenants.
104
+ * A route whose answer carries a secret calls `withholdFromReplay`: its
105
+ * answer isn't kept, only that it succeeded (status, when). A repeat with
106
+ * the same key and body gets 409 `idempotency-key-replay-withheld`.
43
107
  */
44
108
  export declare function idempotencyMiddleware(store: IdempotencyStore, opts?: {
45
109
  ttlMs?: number;
110
+ holdMs?: number;
46
111
  }): MiddlewareHandler;
47
112
  //# sourceMappingURL=idempotency.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAM9C;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACzD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,IAAI,gBAAgB,CAgBjE;AAKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5B,iBAAiB,CA+DnB"}
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAMvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACzD,8FAA8F;IAC9F,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;CACnC;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,0FAA0F;IAC1F,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC1E,wDAAwD;IACxD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,wEAAwE;IACxE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAE3D;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,IAAI,gBAAgB,CAwCjE;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7C,iBAAiB,CA8FnB"}
@@ -1,28 +1,71 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
- import { createHash } from 'node:crypto';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ import { callerRef } from '../caller.js';
4
5
  import { statusFor, toWireError } from '../errors.js';
6
+ /**
7
+ * For a route whose answer carries a secret (an API key, a session token,
8
+ * a signing secret): the Idempotency-Key middleware keeps that the request
9
+ * succeeded and when, never the answer. A repeat with the same key gets 409
10
+ * `idempotency-key-replay-withheld` instead of the secret, and instead of
11
+ * running again (which would make a second one). Call it before answering.
12
+ */
13
+ export function withholdFromReplay(c) {
14
+ c.set('idempotencyWithhold', true);
15
+ }
5
16
  /** Simple in-memory store with lazy expiry — swap for a DB store in prod. */
6
17
  export function createInMemoryIdempotencyStore() {
7
18
  const table = new Map();
19
+ const held = new Map();
20
+ const stored = (key) => {
21
+ const hit = table.get(key);
22
+ if (hit === undefined)
23
+ return null;
24
+ if (hit.expiresAt <= Date.now()) {
25
+ table.delete(key);
26
+ return null;
27
+ }
28
+ return hit;
29
+ };
8
30
  return {
9
31
  async get(key) {
10
- const hit = table.get(key);
11
- if (hit === undefined)
12
- return null;
13
- if (hit.expiresAt <= Date.now()) {
14
- table.delete(key);
15
- return null;
16
- }
17
- return hit;
32
+ return stored(key);
18
33
  },
19
34
  async set(key, entry) {
20
- table.set(key, entry);
35
+ held.delete(key);
36
+ if (stored(key) === null)
37
+ table.set(key, entry);
38
+ },
39
+ holds: {
40
+ async hold(key, hold) {
41
+ const entry = stored(key);
42
+ if (entry !== null)
43
+ return { kind: 'stored', entry };
44
+ const current = held.get(key);
45
+ if (current !== undefined && current.expiresAt > Date.now()) {
46
+ return { kind: 'in-flight', bodyHash: current.bodyHash };
47
+ }
48
+ held.set(key, hold);
49
+ return { kind: 'held' };
50
+ },
51
+ async renew(key, holder, expiresAt) {
52
+ const current = held.get(key);
53
+ if (current?.holder === holder)
54
+ held.set(key, { ...current, expiresAt });
55
+ },
56
+ async release(key, holder) {
57
+ if (held.get(key)?.holder === holder)
58
+ held.delete(key);
59
+ },
21
60
  },
22
61
  };
23
62
  }
24
63
  const MUTATING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
25
64
  const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
65
+ /** How long a hold lasts unless renewed; renewed every third of it while the request runs. */
66
+ const DEFAULT_HOLD_MS = 30 * 1000;
67
+ /** What a repeat in flight is told to wait, in seconds. */
68
+ const IN_FLIGHT_RETRY_AFTER_S = 5;
26
69
  /**
27
70
  * Idempotency-Key middleware per API-ROUTE-CONVENTIONS.md §3.1.
28
71
  *
@@ -38,13 +81,27 @@ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
38
81
  * nothing, and a failure (5xx) may be transient: neither is stored, so
39
82
  * a retry with the same key after fixing the cause runs again instead
40
83
  * of replaying the old error.
84
+ * - With a store that holds keys (`store.holds`, T349): the key is held
85
+ * while the handler runs (for `holdMs`, renewed every third of it), so
86
+ * a repeat sent meanwhile gets 409 `idempotency-key-in-flight` with
87
+ * `Retry-After`, or `idempotency-key-body-mismatch` for another body,
88
+ * instead of running the operation again. The hold becomes the stored
89
+ * answer, or is released when nothing is stored. A crashed request's
90
+ * hold lapses within `holdMs`.
91
+ *
92
+ * The middleware sits AFTER auth so `tenantId` is available. The cache
93
+ * key is the tenant, the caller (`user:…`, `service_account:…`, else the
94
+ * key or session it came with), the route and the key: someone else in
95
+ * the tenant who sends the same key and body runs the request themselves,
96
+ * and never gets another caller's answer (T392).
41
97
  *
42
- * The middleware sits AFTER auth so `tenantId` is available; the
43
- * cache key is namespaced by tenant so callers can't collide across
44
- * tenants.
98
+ * A route whose answer carries a secret calls `withholdFromReplay`: its
99
+ * answer isn't kept, only that it succeeded (status, when). A repeat with
100
+ * the same key and body gets 409 `idempotency-key-replay-withheld`.
45
101
  */
46
102
  export function idempotencyMiddleware(store, opts = {}) {
47
103
  const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
104
+ const holdMs = opts.holdMs ?? DEFAULT_HOLD_MS;
48
105
  return async (c, next) => {
49
106
  if (!MUTATING_METHODS.has(c.req.method.toUpperCase())) {
50
107
  return next();
@@ -62,43 +119,119 @@ export function idempotencyMiddleware(store, opts = {}) {
62
119
  return next();
63
120
  }
64
121
  const bodyText = await readRawBody(c.req.raw);
65
- const bodyHash = hashBody(bodyText);
66
- const cacheKey = `${tenantId}|${c.req.method.toUpperCase()}:${c.req.path}|${rawKey}`;
122
+ const bodyHash = sha256Hex(bodyText);
123
+ const cacheKey = `${tenantId}|${callerKey(c)}|${c.req.method.toUpperCase()}:${c.req.path}|${rawKey}`;
67
124
  const hit = await store.get(cacheKey);
68
- if (hit !== null) {
69
- if (hit.bodyHash !== bodyHash) {
70
- c.status(statusFor('idempotency-key-body-mismatch'));
125
+ if (hit !== null)
126
+ return replay(c, hit, bodyHash, requestId, ttlMs);
127
+ const { holds } = store;
128
+ const holder = randomUUID();
129
+ if (holds !== undefined) {
130
+ const held = await holds.hold(cacheKey, {
131
+ holder,
132
+ bodyHash,
133
+ expiresAt: Date.now() + holdMs,
134
+ });
135
+ if (held.kind === 'stored')
136
+ return replay(c, held.entry, bodyHash, requestId, ttlMs);
137
+ if (held.kind === 'in-flight') {
138
+ if (held.bodyHash !== bodyHash)
139
+ return bodyMismatch(c, requestId);
140
+ c.header('Retry-After', String(IN_FLIGHT_RETRY_AFTER_S));
141
+ c.status(statusFor('idempotency-key-in-flight'));
71
142
  return c.json(toWireError({
72
- code: 'idempotency-key-body-mismatch',
73
- message: 'Idempotency-Key was reused with a different request body. Use a fresh key or the original body.',
143
+ code: 'idempotency-key-in-flight',
144
+ message: "A request with this Idempotency-Key is still running. Retry after it answers (Retry-After), and you'll get its answer.",
74
145
  }, requestId));
75
146
  }
76
- return c.body(hit.bodyText, hit.status, {
77
- 'Content-Type': hit.contentType,
78
- 'X-Idempotent-Replay': 'true',
79
- });
80
147
  }
81
148
  // Re-attach the buffered body so downstream handlers reading
82
149
  // `c.req.json()` see the same bytes.
83
150
  if (bodyText.length > 0)
84
151
  rebindBody(c, bodyText);
85
- await next();
86
- const res = c.res;
87
- // Only what took effect is replayed; see the doc above.
88
- if (res.status >= 400)
89
- return;
90
- const savedBody = await res.clone().text();
91
- const contentType = res.headers.get('Content-Type') ?? 'application/octet-stream';
92
- await store.set(cacheKey, {
93
- bodyHash,
94
- status: res.status,
95
- contentType,
96
- bodyText: savedBody,
97
- expiresAt: Date.now() + ttlMs,
98
- });
99
- return;
152
+ const renewal = holds === undefined
153
+ ? undefined
154
+ : setInterval(() => {
155
+ holds.renew(cacheKey, holder, Date.now() + holdMs).catch(() => undefined);
156
+ }, Math.max(1, Math.floor(holdMs / 3)));
157
+ renewal?.unref?.();
158
+ let answered = false;
159
+ try {
160
+ await next();
161
+ const res = c.res;
162
+ // Only what took effect is replayed; see the doc above.
163
+ if (res.status >= 400)
164
+ return;
165
+ const withheld = c.get('idempotencyWithhold') === true;
166
+ const savedBody = withheld ? '' : await res.clone().text();
167
+ const contentType = res.headers.get('Content-Type') ?? 'application/octet-stream';
168
+ const now = Date.now();
169
+ await store.set(cacheKey, {
170
+ bodyHash,
171
+ status: res.status,
172
+ contentType,
173
+ bodyText: savedBody,
174
+ expiresAt: now + ttlMs,
175
+ ...(withheld && { withheld: true }),
176
+ storedAt: now,
177
+ });
178
+ answered = true;
179
+ }
180
+ finally {
181
+ if (renewal !== undefined)
182
+ clearInterval(renewal);
183
+ // Nothing stored (a refusal, a failure, a throw): let a retry run.
184
+ if (!answered && holds !== undefined) {
185
+ await holds.release(cacheKey, holder).catch(() => undefined);
186
+ }
187
+ }
100
188
  };
101
189
  }
190
+ /**
191
+ * Who the request comes from, for the cache key: the caller's principal
192
+ * (`user:…`, `service_account:…`; an API key with neither is its own
193
+ * service account), else the session it came with, else the credential
194
+ * itself (`token:` and the first 16 hex of its sha256: one bucket per
195
+ * credential, never a shared one, and nothing a reader could use).
196
+ */
197
+ function callerKey(c) {
198
+ const ref = callerRef(c);
199
+ if (ref !== undefined)
200
+ return ref;
201
+ const sessionId = c.get('sessionId');
202
+ if (sessionId !== undefined)
203
+ return `session:${sessionId}`;
204
+ return `token:${sha256Hex(c.req.header('authorization') ?? '').slice(0, 16)}`;
205
+ }
206
+ /**
207
+ * A stored answer, replayed; or the refusal for the same key with another
208
+ * body; or, for an answer that carried a secret, what succeeded and when.
209
+ */
210
+ function replay(c, hit, bodyHash, requestId, ttlMs) {
211
+ if (hit.bodyHash !== bodyHash)
212
+ return bodyMismatch(c, requestId);
213
+ if (hit.withheld === true) {
214
+ const at = new Date(hit.storedAt ?? hit.expiresAt - ttlMs).toISOString();
215
+ c.status(statusFor('idempotency-key-replay-withheld'));
216
+ return c.json(toWireError({
217
+ code: 'idempotency-key-replay-withheld',
218
+ message: `The request with this Idempotency-Key succeeded (${hit.status}, at ${at}). Its answer carried a secret, which isn't kept, so it can't be sent again: read what it made (for an API key, \`GET /v1/tokens\`), or make a new one with a fresh key.`,
219
+ status: hit.status,
220
+ at,
221
+ }, requestId));
222
+ }
223
+ return c.body(hit.bodyText, hit.status, {
224
+ 'Content-Type': hit.contentType,
225
+ 'X-Idempotent-Replay': 'true',
226
+ });
227
+ }
228
+ function bodyMismatch(c, requestId) {
229
+ c.status(statusFor('idempotency-key-body-mismatch'));
230
+ return c.json(toWireError({
231
+ code: 'idempotency-key-body-mismatch',
232
+ message: 'Idempotency-Key was reused with a different request body. Use a fresh key or the original body.',
233
+ }, requestId));
234
+ }
102
235
  async function readRawBody(req) {
103
236
  const method = req.method.toUpperCase();
104
237
  if (method === 'GET' || method === 'HEAD')
@@ -110,8 +243,8 @@ async function readRawBody(req) {
110
243
  return '';
111
244
  }
112
245
  }
113
- function hashBody(body) {
114
- return createHash('sha256').update(body).digest('hex');
246
+ function sha256Hex(text) {
247
+ return createHash('sha256').update(text).digest('hex');
115
248
  }
116
249
  function rebindBody(c, body) {
117
250
  const original = c.req.raw;
@@ -1 +1 @@
1
- {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"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"}