@kindgi/api 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/dist/agent-binding.d.ts +13 -0
  2. package/dist/agent-binding.d.ts.map +1 -1
  3. package/dist/agent-pins.d.ts.map +1 -1
  4. package/dist/agent-pins.js +18 -2
  5. package/dist/agent-pins.js.map +1 -1
  6. package/dist/app.d.ts +110 -17
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +163 -35
  9. package/dist/app.js.map +1 -1
  10. package/dist/block-publish.d.ts +56 -0
  11. package/dist/block-publish.d.ts.map +1 -0
  12. package/dist/block-publish.js +132 -0
  13. package/dist/block-publish.js.map +1 -0
  14. package/dist/caller.d.ts +24 -0
  15. package/dist/caller.d.ts.map +1 -0
  16. package/dist/caller.js +47 -0
  17. package/dist/caller.js.map +1 -0
  18. package/dist/capability-binding.d.ts +11 -0
  19. package/dist/capability-binding.d.ts.map +1 -1
  20. package/dist/cost-binding.d.ts +19 -0
  21. package/dist/cost-binding.d.ts.map +1 -1
  22. package/dist/cost-binding.js.map +1 -1
  23. package/dist/derive-agent-version.d.ts +7 -0
  24. package/dist/derive-agent-version.d.ts.map +1 -1
  25. package/dist/derive-agent-version.js +4 -0
  26. package/dist/derive-agent-version.js.map +1 -1
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +75 -7
  29. package/dist/errors.js.map +1 -1
  30. package/dist/eval-case-binding.d.ts +16 -4
  31. package/dist/eval-case-binding.d.ts.map +1 -1
  32. package/dist/eval-run-binding.d.ts +31 -0
  33. package/dist/eval-run-binding.d.ts.map +1 -1
  34. package/dist/eval-run-dispatcher.d.ts +7 -0
  35. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  36. package/dist/eval-run-dispatcher.js.map +1 -1
  37. package/dist/eval-sample.d.ts +11 -0
  38. package/dist/eval-sample.d.ts.map +1 -0
  39. package/dist/eval-sample.js +34 -0
  40. package/dist/eval-sample.js.map +1 -0
  41. package/dist/eval-suite-binding.d.ts +13 -0
  42. package/dist/eval-suite-binding.d.ts.map +1 -1
  43. package/dist/eval-suite-binding.js.map +1 -1
  44. package/dist/flow-binding.d.ts +18 -0
  45. package/dist/flow-binding.d.ts.map +1 -1
  46. package/dist/flow-pins.d.ts.map +1 -1
  47. package/dist/flow-pins.js +18 -2
  48. package/dist/flow-pins.js.map +1 -1
  49. package/dist/gate.d.ts.map +1 -1
  50. package/dist/gate.js +25 -0
  51. package/dist/gate.js.map +1 -1
  52. package/dist/handler-binding.d.ts +32 -0
  53. package/dist/handler-binding.d.ts.map +1 -1
  54. package/dist/hitl-binding.d.ts +23 -0
  55. package/dist/hitl-binding.d.ts.map +1 -1
  56. package/dist/identity-directory-binding.d.ts +82 -4
  57. package/dist/identity-directory-binding.d.ts.map +1 -1
  58. package/dist/identity-provider-binding.d.ts +197 -17
  59. package/dist/identity-provider-binding.d.ts.map +1 -1
  60. package/dist/improvement-pass-binding.d.ts +196 -0
  61. package/dist/improvement-pass-binding.d.ts.map +1 -0
  62. package/dist/improvement-pass-binding.js +9 -0
  63. package/dist/improvement-pass-binding.js.map +1 -0
  64. package/dist/index.d.ts +35 -17
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +11 -3
  67. package/dist/index.js.map +1 -1
  68. package/dist/judged-dispatcher.d.ts +25 -4
  69. package/dist/judged-dispatcher.d.ts.map +1 -1
  70. package/dist/judged-dispatcher.js +43 -6
  71. package/dist/judged-dispatcher.js.map +1 -1
  72. package/dist/judgment-binding.d.ts +25 -1
  73. package/dist/judgment-binding.d.ts.map +1 -1
  74. package/dist/mcp-endpoint-binding.d.ts +7 -0
  75. package/dist/mcp-endpoint-binding.d.ts.map +1 -1
  76. package/dist/memory-binding.d.ts +124 -17
  77. package/dist/memory-binding.d.ts.map +1 -1
  78. package/dist/memory-erasure-binding.d.ts +145 -0
  79. package/dist/memory-erasure-binding.d.ts.map +1 -0
  80. package/dist/memory-erasure-binding.js +4 -0
  81. package/dist/memory-erasure-binding.js.map +1 -0
  82. package/dist/middleware/auth.d.ts +66 -13
  83. package/dist/middleware/auth.d.ts.map +1 -1
  84. package/dist/middleware/auth.js +150 -50
  85. package/dist/middleware/auth.js.map +1 -1
  86. package/dist/middleware/authorize.d.ts +9 -0
  87. package/dist/middleware/authorize.d.ts.map +1 -1
  88. package/dist/middleware/authorize.js +122 -4
  89. package/dist/middleware/authorize.js.map +1 -1
  90. package/dist/middleware/error-mapper.d.ts +5 -0
  91. package/dist/middleware/error-mapper.d.ts.map +1 -1
  92. package/dist/middleware/error-mapper.js +14 -1
  93. package/dist/middleware/error-mapper.js.map +1 -1
  94. package/dist/middleware/idempotency.d.ts +70 -5
  95. package/dist/middleware/idempotency.d.ts.map +1 -1
  96. package/dist/middleware/idempotency.js +174 -41
  97. package/dist/middleware/idempotency.js.map +1 -1
  98. package/dist/middleware/key-project.d.ts +17 -0
  99. package/dist/middleware/key-project.d.ts.map +1 -0
  100. package/dist/middleware/key-project.js +75 -0
  101. package/dist/middleware/key-project.js.map +1 -0
  102. package/dist/middleware/principal.d.ts.map +1 -1
  103. package/dist/middleware/principal.js +9 -5
  104. package/dist/middleware/principal.js.map +1 -1
  105. package/dist/middleware/project-ref.d.ts.map +1 -1
  106. package/dist/middleware/project-ref.js +3 -0
  107. package/dist/middleware/project-ref.js.map +1 -1
  108. package/dist/openapi/generate.d.ts.map +1 -1
  109. package/dist/openapi/generate.js +5 -2
  110. package/dist/openapi/generate.js.map +1 -1
  111. package/dist/openapi/operations.d.ts.map +1 -1
  112. package/dist/openapi/operations.js +919 -140
  113. package/dist/openapi/operations.js.map +1 -1
  114. package/dist/openapi/schemas.d.ts +90 -13
  115. package/dist/openapi/schemas.d.ts.map +1 -1
  116. package/dist/openapi/schemas.js +2081 -359
  117. package/dist/openapi/schemas.js.map +1 -1
  118. package/dist/person-grants-binding.d.ts +77 -0
  119. package/dist/person-grants-binding.d.ts.map +1 -0
  120. package/dist/person-grants-binding.js +4 -0
  121. package/dist/person-grants-binding.js.map +1 -0
  122. package/dist/proposal-service.d.ts +121 -0
  123. package/dist/proposal-service.d.ts.map +1 -0
  124. package/dist/proposal-service.js +447 -0
  125. package/dist/proposal-service.js.map +1 -0
  126. package/dist/proposal-status.d.ts +60 -0
  127. package/dist/proposal-status.d.ts.map +1 -0
  128. package/dist/proposal-status.js +109 -0
  129. package/dist/proposal-status.js.map +1 -0
  130. package/dist/provider-binding.d.ts +10 -0
  131. package/dist/provider-binding.d.ts.map +1 -1
  132. package/dist/publish-refused.d.ts +28 -3
  133. package/dist/publish-refused.d.ts.map +1 -1
  134. package/dist/publish-refused.js +24 -3
  135. package/dist/publish-refused.js.map +1 -1
  136. package/dist/routes/adapters.d.ts +2 -1
  137. package/dist/routes/adapters.d.ts.map +1 -1
  138. package/dist/routes/adapters.js +3 -1
  139. package/dist/routes/adapters.js.map +1 -1
  140. package/dist/routes/agent-releases.d.ts +55 -3
  141. package/dist/routes/agent-releases.d.ts.map +1 -1
  142. package/dist/routes/agent-releases.js +85 -55
  143. package/dist/routes/agent-releases.js.map +1 -1
  144. package/dist/routes/agents.d.ts +12 -1
  145. package/dist/routes/agents.d.ts.map +1 -1
  146. package/dist/routes/agents.js +100 -2
  147. package/dist/routes/agents.js.map +1 -1
  148. package/dist/routes/approvals.d.ts +15 -3
  149. package/dist/routes/approvals.d.ts.map +1 -1
  150. package/dist/routes/approvals.js +133 -122
  151. package/dist/routes/approvals.js.map +1 -1
  152. package/dist/routes/artifacts.d.ts +25 -3
  153. package/dist/routes/artifacts.d.ts.map +1 -1
  154. package/dist/routes/artifacts.js +116 -7
  155. package/dist/routes/artifacts.js.map +1 -1
  156. package/dist/routes/auth.d.ts +25 -1
  157. package/dist/routes/auth.d.ts.map +1 -1
  158. package/dist/routes/auth.js +655 -281
  159. package/dist/routes/auth.js.map +1 -1
  160. package/dist/routes/blocks.d.ts.map +1 -1
  161. package/dist/routes/blocks.js +2 -42
  162. package/dist/routes/blocks.js.map +1 -1
  163. package/dist/routes/capabilities.d.ts +2 -1
  164. package/dist/routes/capabilities.d.ts.map +1 -1
  165. package/dist/routes/capabilities.js +6 -1
  166. package/dist/routes/capabilities.js.map +1 -1
  167. package/dist/routes/compliance.d.ts +9 -10
  168. package/dist/routes/compliance.d.ts.map +1 -1
  169. package/dist/routes/compliance.js +42 -61
  170. package/dist/routes/compliance.js.map +1 -1
  171. package/dist/routes/conversations.d.ts +8 -1
  172. package/dist/routes/conversations.d.ts.map +1 -1
  173. package/dist/routes/conversations.js +87 -8
  174. package/dist/routes/conversations.js.map +1 -1
  175. package/dist/routes/cost.d.ts +12 -1
  176. package/dist/routes/cost.d.ts.map +1 -1
  177. package/dist/routes/cost.js +74 -3
  178. package/dist/routes/cost.js.map +1 -1
  179. package/dist/routes/denied.d.ts +11 -0
  180. package/dist/routes/denied.d.ts.map +1 -0
  181. package/dist/routes/denied.js +17 -0
  182. package/dist/routes/denied.js.map +1 -0
  183. package/dist/routes/deployments.d.ts +10 -1
  184. package/dist/routes/deployments.d.ts.map +1 -1
  185. package/dist/routes/deployments.js +171 -13
  186. package/dist/routes/deployments.js.map +1 -1
  187. package/dist/routes/eval-comparison.d.ts.map +1 -1
  188. package/dist/routes/eval-comparison.js +69 -1
  189. package/dist/routes/eval-comparison.js.map +1 -1
  190. package/dist/routes/eval-overrides.d.ts +18 -0
  191. package/dist/routes/eval-overrides.d.ts.map +1 -0
  192. package/dist/routes/eval-overrides.js +81 -0
  193. package/dist/routes/eval-overrides.js.map +1 -0
  194. package/dist/routes/eval-runs.d.ts +10 -1
  195. package/dist/routes/eval-runs.d.ts.map +1 -1
  196. package/dist/routes/eval-runs.js +66 -7
  197. package/dist/routes/eval-runs.js.map +1 -1
  198. package/dist/routes/eval-suites.d.ts.map +1 -1
  199. package/dist/routes/eval-suites.js +28 -2
  200. package/dist/routes/eval-suites.js.map +1 -1
  201. package/dist/routes/event-triggers.d.ts +5 -1
  202. package/dist/routes/event-triggers.d.ts.map +1 -1
  203. package/dist/routes/event-triggers.js +26 -3
  204. package/dist/routes/event-triggers.js.map +1 -1
  205. package/dist/routes/export-signing-keys.d.ts +12 -0
  206. package/dist/routes/export-signing-keys.d.ts.map +1 -0
  207. package/dist/routes/export-signing-keys.js +24 -0
  208. package/dist/routes/export-signing-keys.js.map +1 -0
  209. package/dist/routes/flows.d.ts.map +1 -1
  210. package/dist/routes/flows.js +9 -1
  211. package/dist/routes/flows.js.map +1 -1
  212. package/dist/routes/gate-policies.d.ts +4 -1
  213. package/dist/routes/gate-policies.d.ts.map +1 -1
  214. package/dist/routes/gate-policies.js +29 -5
  215. package/dist/routes/gate-policies.js.map +1 -1
  216. package/dist/routes/guardrails.d.ts +16 -14
  217. package/dist/routes/guardrails.d.ts.map +1 -1
  218. package/dist/routes/guardrails.js +39 -3
  219. package/dist/routes/guardrails.js.map +1 -1
  220. package/dist/routes/identity.d.ts +20 -4
  221. package/dist/routes/identity.d.ts.map +1 -1
  222. package/dist/routes/identity.js +246 -6
  223. package/dist/routes/identity.js.map +1 -1
  224. package/dist/routes/improvement-passes.d.ts +52 -0
  225. package/dist/routes/improvement-passes.d.ts.map +1 -0
  226. package/dist/routes/improvement-passes.js +449 -0
  227. package/dist/routes/improvement-passes.js.map +1 -0
  228. package/dist/routes/judged-suites.d.ts +50 -0
  229. package/dist/routes/judged-suites.d.ts.map +1 -1
  230. package/dist/routes/judged-suites.js +66 -27
  231. package/dist/routes/judged-suites.js.map +1 -1
  232. package/dist/routes/judgment-context.d.ts +18 -2
  233. package/dist/routes/judgment-context.d.ts.map +1 -1
  234. package/dist/routes/judgment-context.js +63 -5
  235. package/dist/routes/judgment-context.js.map +1 -1
  236. package/dist/routes/judgment-flow-context.d.ts.map +1 -1
  237. package/dist/routes/judgment-flow-context.js +14 -2
  238. package/dist/routes/judgment-flow-context.js.map +1 -1
  239. package/dist/routes/judgments.d.ts.map +1 -1
  240. package/dist/routes/judgments.js +8 -1
  241. package/dist/routes/judgments.js.map +1 -1
  242. package/dist/routes/mcp.d.ts.map +1 -1
  243. package/dist/routes/mcp.js +26 -1
  244. package/dist/routes/mcp.js.map +1 -1
  245. package/dist/routes/memory-access.d.ts +43 -0
  246. package/dist/routes/memory-access.d.ts.map +1 -0
  247. package/dist/routes/memory-access.js +114 -0
  248. package/dist/routes/memory-access.js.map +1 -0
  249. package/dist/routes/memory-erasures.d.ts +25 -0
  250. package/dist/routes/memory-erasures.d.ts.map +1 -0
  251. package/dist/routes/memory-erasures.js +214 -0
  252. package/dist/routes/memory-erasures.js.map +1 -0
  253. package/dist/routes/memory-parse.d.ts +38 -0
  254. package/dist/routes/memory-parse.d.ts.map +1 -0
  255. package/dist/routes/memory-parse.js +199 -0
  256. package/dist/routes/memory-parse.js.map +1 -0
  257. package/dist/routes/memory.d.ts +9 -4
  258. package/dist/routes/memory.d.ts.map +1 -1
  259. package/dist/routes/memory.js +226 -234
  260. package/dist/routes/memory.js.map +1 -1
  261. package/dist/routes/observations.d.ts +4 -1
  262. package/dist/routes/observations.d.ts.map +1 -1
  263. package/dist/routes/observations.js +8 -2
  264. package/dist/routes/observations.js.map +1 -1
  265. package/dist/routes/pagination.d.ts +7 -0
  266. package/dist/routes/pagination.d.ts.map +1 -1
  267. package/dist/routes/pagination.js +10 -0
  268. package/dist/routes/pagination.js.map +1 -1
  269. package/dist/routes/policies.d.ts +2 -1
  270. package/dist/routes/policies.d.ts.map +1 -1
  271. package/dist/routes/policies.js +3 -1
  272. package/dist/routes/policies.js.map +1 -1
  273. package/dist/routes/project-mismatch.d.ts +22 -0
  274. package/dist/routes/project-mismatch.d.ts.map +1 -0
  275. package/dist/routes/project-mismatch.js +34 -0
  276. package/dist/routes/project-mismatch.js.map +1 -0
  277. package/dist/routes/projects.d.ts +15 -4
  278. package/dist/routes/projects.d.ts.map +1 -1
  279. package/dist/routes/projects.js +100 -9
  280. package/dist/routes/projects.js.map +1 -1
  281. package/dist/routes/proposals.d.ts +25 -17
  282. package/dist/routes/proposals.d.ts.map +1 -1
  283. package/dist/routes/proposals.js +340 -507
  284. package/dist/routes/proposals.js.map +1 -1
  285. package/dist/routes/provenance.d.ts +17 -3
  286. package/dist/routes/provenance.d.ts.map +1 -1
  287. package/dist/routes/provenance.js +79 -103
  288. package/dist/routes/provenance.js.map +1 -1
  289. package/dist/routes/providers.d.ts +17 -1
  290. package/dist/routes/providers.d.ts.map +1 -1
  291. package/dist/routes/providers.js +110 -3
  292. package/dist/routes/providers.js.map +1 -1
  293. package/dist/routes/public-run-tokens.d.ts.map +1 -1
  294. package/dist/routes/public-run-tokens.js +3 -0
  295. package/dist/routes/public-run-tokens.js.map +1 -1
  296. package/dist/routes/readable-projects.d.ts +26 -0
  297. package/dist/routes/readable-projects.d.ts.map +1 -0
  298. package/dist/routes/readable-projects.js +39 -0
  299. package/dist/routes/readable-projects.js.map +1 -0
  300. package/dist/routes/runs.d.ts +10 -0
  301. package/dist/routes/runs.d.ts.map +1 -1
  302. package/dist/routes/runs.js +92 -42
  303. package/dist/routes/runs.js.map +1 -1
  304. package/dist/routes/schedules.d.ts +21 -13
  305. package/dist/routes/schedules.d.ts.map +1 -1
  306. package/dist/routes/schedules.js +416 -55
  307. package/dist/routes/schedules.js.map +1 -1
  308. package/dist/routes/segments.d.ts +2 -0
  309. package/dist/routes/segments.d.ts.map +1 -1
  310. package/dist/routes/segments.js +5 -0
  311. package/dist/routes/segments.js.map +1 -1
  312. package/dist/routes/service-accounts.d.ts +17 -0
  313. package/dist/routes/service-accounts.d.ts.map +1 -0
  314. package/dist/routes/service-accounts.js +212 -0
  315. package/dist/routes/service-accounts.js.map +1 -0
  316. package/dist/routes/sign-in-options.d.ts +50 -0
  317. package/dist/routes/sign-in-options.d.ts.map +1 -0
  318. package/dist/routes/sign-in-options.js +98 -0
  319. package/dist/routes/sign-in-options.js.map +1 -0
  320. package/dist/routes/signing-keys.d.ts +2 -1
  321. package/dist/routes/signing-keys.d.ts.map +1 -1
  322. package/dist/routes/signing-keys.js +3 -1
  323. package/dist/routes/signing-keys.js.map +1 -1
  324. package/dist/routes/tenant-access.d.ts +13 -0
  325. package/dist/routes/tenant-access.d.ts.map +1 -0
  326. package/dist/routes/tenant-access.js +26 -0
  327. package/dist/routes/tenant-access.js.map +1 -0
  328. package/dist/routes/tenant.d.ts.map +1 -1
  329. package/dist/routes/tenant.js +4 -0
  330. package/dist/routes/tenant.js.map +1 -1
  331. package/dist/routes/token-sign-in.d.ts +36 -0
  332. package/dist/routes/token-sign-in.d.ts.map +1 -0
  333. package/dist/routes/token-sign-in.js +101 -0
  334. package/dist/routes/token-sign-in.js.map +1 -0
  335. package/dist/routes/tokens.d.ts +15 -5
  336. package/dist/routes/tokens.d.ts.map +1 -1
  337. package/dist/routes/tokens.js +162 -43
  338. package/dist/routes/tokens.js.map +1 -1
  339. package/dist/routes/tools.d.ts.map +1 -1
  340. package/dist/routes/tools.js +9 -1
  341. package/dist/routes/tools.js.map +1 -1
  342. package/dist/routes/trigger-access.d.ts +29 -0
  343. package/dist/routes/trigger-access.d.ts.map +1 -0
  344. package/dist/routes/trigger-access.js +33 -0
  345. package/dist/routes/trigger-access.js.map +1 -0
  346. package/dist/routes/webhook-endpoints.d.ts +2 -1
  347. package/dist/routes/webhook-endpoints.d.ts.map +1 -1
  348. package/dist/routes/webhook-endpoints.js +11 -3
  349. package/dist/routes/webhook-endpoints.js.map +1 -1
  350. package/dist/routes/webhooks.d.ts +5 -1
  351. package/dist/routes/webhooks.d.ts.map +1 -1
  352. package/dist/routes/webhooks.js +25 -2
  353. package/dist/routes/webhooks.js.map +1 -1
  354. package/dist/run-failure.d.ts +21 -0
  355. package/dist/run-failure.d.ts.map +1 -0
  356. package/dist/run-failure.js +29 -0
  357. package/dist/run-failure.js.map +1 -0
  358. package/dist/service-account-binding.d.ts +108 -0
  359. package/dist/service-account-binding.d.ts.map +1 -0
  360. package/dist/service-account-binding.js +4 -0
  361. package/dist/service-account-binding.js.map +1 -0
  362. package/dist/session-store-binding.d.ts +61 -13
  363. package/dist/session-store-binding.d.ts.map +1 -1
  364. package/dist/signed-export.d.ts +89 -0
  365. package/dist/signed-export.d.ts.map +1 -0
  366. package/dist/signed-export.js +149 -0
  367. package/dist/signed-export.js.map +1 -0
  368. package/dist/supervisor-binding.d.ts +186 -413
  369. package/dist/supervisor-binding.d.ts.map +1 -1
  370. package/dist/testing/app-bindings.d.ts +33 -0
  371. package/dist/testing/app-bindings.d.ts.map +1 -0
  372. package/dist/testing/app-bindings.js +112 -0
  373. package/dist/testing/app-bindings.js.map +1 -0
  374. package/dist/testing/index.d.ts +11 -0
  375. package/dist/testing/index.d.ts.map +1 -0
  376. package/dist/testing/index.js +13 -0
  377. package/dist/testing/index.js.map +1 -0
  378. package/dist/testing/stub-binding.d.ts +34 -0
  379. package/dist/testing/stub-binding.d.ts.map +1 -0
  380. package/dist/testing/stub-binding.js +42 -0
  381. package/dist/testing/stub-binding.js.map +1 -0
  382. package/dist/testing/trigger-registry.d.ts +21 -0
  383. package/dist/testing/trigger-registry.d.ts.map +1 -0
  384. package/dist/testing/trigger-registry.js +206 -0
  385. package/dist/testing/trigger-registry.js.map +1 -0
  386. package/dist/token-admin.d.ts +46 -8
  387. package/dist/token-admin.d.ts.map +1 -1
  388. package/dist/token-admin.js.map +1 -1
  389. package/dist/tool-binding.d.ts +13 -0
  390. package/dist/tool-binding.d.ts.map +1 -1
  391. package/dist/trigger-binding.d.ts +2 -2
  392. package/dist/trigger-binding.d.ts.map +1 -1
  393. package/dist/trigger-binding.js +1 -1
  394. package/dist/trigger-binding.js.map +1 -1
  395. package/dist/types.d.ts +16 -0
  396. package/dist/types.d.ts.map +1 -1
  397. package/dist/webhook-endpoint-binding.d.ts +19 -3
  398. package/dist/webhook-endpoint-binding.d.ts.map +1 -1
  399. package/dist/webhook-endpoint-binding.js +1 -1
  400. package/dist/webhook-endpoint-binding.js.map +1 -1
  401. package/openapi.json +15387 -8789
  402. package/package.json +26 -22
  403. package/src/agent-binding.ts +14 -0
  404. package/src/agent-pins.ts +18 -2
  405. package/src/app.ts +366 -80
  406. package/src/block-publish.ts +181 -0
  407. package/src/caller.ts +62 -0
  408. package/src/capability-binding.ts +12 -0
  409. package/src/cost-binding.ts +19 -0
  410. package/src/derive-agent-version.ts +9 -1
  411. package/src/errors.ts +75 -7
  412. package/src/eval-case-binding.ts +17 -1
  413. package/src/eval-run-binding.ts +31 -0
  414. package/src/eval-run-dispatcher.ts +7 -0
  415. package/src/eval-sample.ts +42 -0
  416. package/src/eval-suite-binding.ts +14 -0
  417. package/src/flow-binding.ts +19 -0
  418. package/src/flow-pins.ts +18 -2
  419. package/src/gate.ts +26 -0
  420. package/src/handler-binding.ts +36 -1
  421. package/src/hitl-binding.ts +24 -0
  422. package/src/identity-directory-binding.ts +85 -4
  423. package/src/identity-provider-binding.ts +216 -21
  424. package/src/improvement-pass-binding.ts +193 -0
  425. package/src/index.ts +153 -31
  426. package/src/judged-dispatcher.ts +78 -11
  427. package/src/judgment-binding.ts +25 -1
  428. package/src/mcp-endpoint-binding.ts +7 -0
  429. package/src/memory-binding.ts +121 -17
  430. package/src/memory-erasure-binding.ts +156 -0
  431. package/src/middleware/auth.ts +228 -62
  432. package/src/middleware/authorize.ts +155 -3
  433. package/src/middleware/error-mapper.ts +15 -1
  434. package/src/middleware/idempotency.ts +230 -43
  435. package/src/middleware/key-project.ts +86 -0
  436. package/src/middleware/principal.ts +9 -5
  437. package/src/middleware/project-ref.ts +3 -0
  438. package/src/openapi/generate.ts +11 -2
  439. package/src/openapi/operations.ts +1060 -143
  440. package/src/openapi/schemas.ts +2387 -469
  441. package/src/person-grants-binding.ts +76 -0
  442. package/src/proposal-service.ts +640 -0
  443. package/src/proposal-status.ts +176 -0
  444. package/src/provider-binding.ts +10 -0
  445. package/src/publish-refused.ts +56 -9
  446. package/src/routes/adapters.ts +4 -0
  447. package/src/routes/agent-releases.ts +121 -69
  448. package/src/routes/agents.ts +128 -1
  449. package/src/routes/approvals.ts +164 -154
  450. package/src/routes/artifacts.ts +181 -11
  451. package/src/routes/auth.ts +804 -336
  452. package/src/routes/blocks.ts +2 -53
  453. package/src/routes/capabilities.ts +10 -1
  454. package/src/routes/compliance.ts +60 -99
  455. package/src/routes/conversations.ts +101 -7
  456. package/src/routes/cost.ts +110 -4
  457. package/src/routes/denied.ts +28 -0
  458. package/src/routes/deployments.ts +210 -17
  459. package/src/routes/eval-comparison.ts +81 -2
  460. package/src/routes/eval-overrides.ts +108 -0
  461. package/src/routes/eval-runs.ts +89 -6
  462. package/src/routes/eval-suites.ts +32 -2
  463. package/src/routes/event-triggers.ts +27 -3
  464. package/src/routes/export-signing-keys.ts +31 -0
  465. package/src/routes/flows.ts +12 -1
  466. package/src/routes/gate-policies.ts +37 -6
  467. package/src/routes/guardrails.ts +61 -2
  468. package/src/routes/identity.ts +328 -10
  469. package/src/routes/improvement-passes.ts +541 -0
  470. package/src/routes/judged-suites.ts +113 -43
  471. package/src/routes/judgment-context.ts +76 -5
  472. package/src/routes/judgment-flow-context.ts +16 -2
  473. package/src/routes/judgments.ts +17 -3
  474. package/src/routes/mcp.ts +29 -1
  475. package/src/routes/memory-access.ts +160 -0
  476. package/src/routes/memory-erasures.ts +240 -0
  477. package/src/routes/memory-parse.ts +250 -0
  478. package/src/routes/memory.ts +244 -286
  479. package/src/routes/observations.ts +15 -2
  480. package/src/routes/pagination.ts +12 -0
  481. package/src/routes/policies.ts +7 -1
  482. package/src/routes/project-mismatch.ts +56 -0
  483. package/src/routes/projects.ts +107 -13
  484. package/src/routes/proposals.ts +370 -611
  485. package/src/routes/provenance.ts +99 -133
  486. package/src/routes/providers.ts +142 -3
  487. package/src/routes/public-run-tokens.ts +3 -0
  488. package/src/routes/readable-projects.ts +66 -0
  489. package/src/routes/runs.ts +119 -39
  490. package/src/routes/schedules.ts +472 -60
  491. package/src/routes/segments.ts +11 -0
  492. package/src/routes/service-accounts.ts +262 -0
  493. package/src/routes/sign-in-options.ts +168 -0
  494. package/src/routes/signing-keys.ts +7 -1
  495. package/src/routes/tenant-access.ts +37 -0
  496. package/src/routes/tenant.ts +6 -0
  497. package/src/routes/token-sign-in.ts +161 -0
  498. package/src/routes/tokens.ts +172 -46
  499. package/src/routes/tools.ts +12 -1
  500. package/src/routes/trigger-access.ts +72 -0
  501. package/src/routes/webhook-endpoints.ts +15 -3
  502. package/src/routes/webhooks.ts +26 -2
  503. package/src/run-failure.ts +42 -0
  504. package/src/service-account-binding.ts +113 -0
  505. package/src/session-store-binding.ts +65 -13
  506. package/src/signed-export.ts +250 -0
  507. package/src/supervisor-binding.ts +169 -409
  508. package/src/testing/app-bindings.ts +142 -0
  509. package/src/testing/index.ts +21 -0
  510. package/src/testing/stub-binding.ts +53 -0
  511. package/src/testing/trigger-registry.ts +259 -0
  512. package/src/token-admin.ts +40 -8
  513. package/src/tool-binding.ts +14 -0
  514. package/src/trigger-binding.ts +8 -1
  515. package/src/types.ts +16 -0
  516. package/src/webhook-endpoint-binding.ts +18 -3
@@ -72,6 +72,8 @@ export interface FlowRegistryBinding {
72
72
  * well-formed `Flow`. Bindings MAY reject with `already-registered`
73
73
  * when the same `(flowId, version)` is re-published; the route maps
74
74
  * that to `409`.
75
+ * A version of a flow whose versions live in another project is
76
+ * `project-mismatch` (flows never move between projects; `409 flow-project-mismatch`).
75
77
  */
76
78
  publish(input: FlowPublishInput): Promise<FlowPublishOutcome>;
77
79
  /**
@@ -93,6 +95,11 @@ export interface FlowRegistryBinding {
93
95
  export type FlowVersionRecord = Flow & {
94
96
  /** ISO-8601; present only on an unregistered version. */
95
97
  readonly unregisteredAt?: string;
98
+ /**
99
+ * The project the version belongs to, when the store records it: a
100
+ * deploy into another project is refused even when it writes nothing.
101
+ */
102
+ readonly projectId?: ProjectId;
96
103
  };
97
104
 
98
105
  export interface FlowListInput {
@@ -209,6 +216,18 @@ export type FlowPublishOutcome =
209
216
  readonly flowId: FlowId;
210
217
  readonly version: string;
211
218
  readonly projectId: ProjectId;
219
+ }
220
+ | {
221
+ /**
222
+ * The flow's versions live in another project: a flow belongs to
223
+ * the project its first version was published into, and never
224
+ * moves. Nothing is written (the route answers `409 flow-project-mismatch`).
225
+ */
226
+ readonly kind: 'project-mismatch';
227
+ readonly flowId: FlowId;
228
+ readonly version: string;
229
+ /** The project the flow belongs to. */
230
+ readonly projectId: ProjectId;
212
231
  };
213
232
 
214
233
  export type FlowUnregisterOutcome = {
package/src/flow-pins.ts CHANGED
@@ -113,17 +113,33 @@ export async function publishDeployedFlow(
113
113
  input: PublishDeployedFlowInput,
114
114
  ): Promise<DeployedVersionOutcome> {
115
115
  const { flows, tenantId, projectId, flow, pins, enqueueTuples } = input;
116
+ const existing = await allFlowVersions(flows, tenantId, flow.id);
117
+ // A flow never moves, even by a deploy that writes nothing (an unchanged
118
+ // or reused version): one of another project is refused. A registry
119
+ // that doesn't record the project refuses only a write.
120
+ const held = existing[0];
121
+ if (held !== undefined) {
122
+ const record = await flows.getVersion({ tenantId, flowId: flow.id, version: held.version });
123
+ if (record?.projectId !== undefined && record.projectId !== projectId) {
124
+ throw new PublishRefused('flow', `${flow.id}@${flow.version}`, {
125
+ kind: 'project-mismatch',
126
+ flowId: flow.id,
127
+ version: flow.version,
128
+ projectId: record.projectId,
129
+ });
130
+ }
131
+ }
116
132
  return deployVersion<Flow>({
117
133
  label: `flow "${flow.id as unknown as string}"`,
118
134
  definition: flow,
119
135
  pins,
120
136
  pinsDigest: flowPinsDigest(pins),
121
- existing: await allFlowVersions(flows, tenantId, flow.id),
137
+ existing,
122
138
  publish: async (version) => {
123
139
  const outcome = await flows.publish({ tenantId, projectId, flow: version, enqueueTuples });
124
140
  if (outcome.kind === 'ok') return 'ok';
125
141
  if (outcome.kind === 'already-registered') return 'taken';
126
- throw new PublishRefused('flow', `${flow.id}@${version.version}`, outcome.kind);
142
+ throw new PublishRefused('flow', `${flow.id}@${version.version}`, outcome);
127
143
  },
128
144
  });
129
145
  }
package/src/gate.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import type { ReviewerRole } from '@kindgi/authz';
5
5
  import type { LiveScope } from '@kindgi/types';
6
6
 
7
+ import type { EvalSample } from './eval-run-binding.js';
7
8
  import type { GateMetricName, GateMetricSpec, GatePolicySpec } from './gate-policy-binding.js';
8
9
  import type { ComparisonMetric, JudgedComparisonSummary } from './judged-dispatcher.js';
9
10
 
@@ -114,6 +115,7 @@ export function evaluateGate(input: GateInput): GateResult {
114
115
  checks.push(freshnessCheck(spec.comparison.maxAgeHours, summary, input.now));
115
116
  }
116
117
  if (spec.comparison?.suite !== undefined) checks.push(suiteCheck(spec.comparison.suite, summary));
118
+ if (summary.sample !== undefined) checks.push(sampleCheck(summary.sample));
117
119
  checks.push(sameContentsCheck(input));
118
120
  checks.push(baselineCheck(summary, input));
119
121
  checks.push(scopeCheck(summary, input));
@@ -204,6 +206,23 @@ function suiteCheck(
204
206
  };
205
207
  }
206
208
 
209
+ /**
210
+ * A comparison on part of the test set: the hold-out part proves a
211
+ * candidate; the search part chose it, so its numbers flatter it.
212
+ */
213
+ function sampleCheck(sample: EvalSample): GateCheck {
214
+ const passed = sample.part === 'hold-out';
215
+ return {
216
+ name: 'comparison.sample',
217
+ passed,
218
+ message: passed
219
+ ? `The comparison ran the hold-out part of the test set (seed ${sample.seed}).`
220
+ : 'The comparison ran the search part of the test set, which chose this candidate: compare on the hold-out part, or the whole test set.',
221
+ value: sample.part,
222
+ threshold: 'hold-out',
223
+ };
224
+ }
225
+
207
226
  function sameContentsCheck(input: GateInput): GateCheck {
208
227
  const { promotion, summary } = input;
209
228
  const candidate = summary?.candidate;
@@ -217,6 +236,13 @@ function sameContentsCheck(input: GateInput): GateCheck {
217
236
  };
218
237
  }
219
238
  const compared = `${candidate.agentId} ${candidate.version}`;
239
+ if (candidate.overrides !== undefined) {
240
+ return {
241
+ name,
242
+ passed: false,
243
+ message: `The comparison ran ${compared} with other content for ${[...(candidate.overrides.settings ?? []), ...(candidate.overrides.prompts ?? [])].join(', ')} than it pins (an improvement pass's search): compare the published version.`,
244
+ };
245
+ }
220
246
  if (candidate.agentId !== promotion.agentId || candidate.version !== promotion.version) {
221
247
  return {
222
248
  name,
@@ -2,7 +2,9 @@
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
 
4
4
  import type { AgentId } from '@kindgi/agents';
5
+ import type { Principal } from '@kindgi/authz';
5
6
  import type { FlowVersionOverrides } from '@kindgi/flow';
7
+ import type { RunIdempotencyKey, RunTriggerRef } from '@kindgi/runtime';
6
8
  import type { FlowId, ProjectId, RunId, ScopeSegment, Semver, TenantId } from '@kindgi/types';
7
9
 
8
10
  /**
@@ -67,6 +69,12 @@ export interface RunTrace {
67
69
  export interface ResumeRunBindingInput {
68
70
  readonly tenantId: TenantId;
69
71
  readonly runId: RunId;
72
+ /**
73
+ * The trace context of the request resuming the run (a reviewer's
74
+ * decision): the resumed work runs under it, and the run keeps its own
75
+ * trace id from the request that started it. Absent: as before.
76
+ */
77
+ readonly trace?: RunTrace;
70
78
  }
71
79
 
72
80
  export interface InvokeAgentBindingInput {
@@ -107,6 +115,19 @@ export interface InvokeAgentBindingInput {
107
115
  * can't run in the background may treat `false` like `true`.
108
116
  */
109
117
  readonly wait?: boolean;
118
+ /**
119
+ * Start the run at most once per key (`RunIdempotencyKey`): a key a run
120
+ * already has starts nothing and answers that run, with `existing`.
121
+ */
122
+ readonly idempotencyKey?: RunIdempotencyKey;
123
+ /** Set when a trigger starts the run; the run records it (`RunTriggerRef`). */
124
+ readonly trigger?: RunTriggerRef;
125
+ /**
126
+ * Who started the run (the authenticated caller), when known: whom the
127
+ * turn acts for, e.g. whose own memory its retrievals may read. Set by
128
+ * the route, never from the body. On its own it enforces nothing.
129
+ */
130
+ readonly principal?: Principal;
110
131
  /** The trace context of the request starting the run: the binding records its `traceId` on the run. */
111
132
  readonly trace?: RunTrace;
112
133
  }
@@ -128,14 +149,28 @@ export interface InvokeFlowBindingInput {
128
149
  * can't run in the background may treat `false` like `true`.
129
150
  */
130
151
  readonly wait?: boolean;
152
+ /**
153
+ * Start the run at most once per key (`RunIdempotencyKey`): a key a run
154
+ * already has starts nothing and answers that run, with `existing`.
155
+ */
156
+ readonly idempotencyKey?: RunIdempotencyKey;
157
+ /** Set when a trigger starts the run; the run records it (`RunTriggerRef`). */
158
+ readonly trigger?: RunTriggerRef;
131
159
  /** Agents and tools to run at other exact versions than the flow version's pins (`RunFlowInput.versions`). */
132
160
  readonly versions?: FlowVersionOverrides;
161
+ /** Who started the run, as for `InvokeAgentBindingInput.principal`: its agent steps act for them. */
162
+ readonly principal?: Principal;
133
163
  /** The trace context of the request starting the run, as for an agent run. */
134
164
  readonly trace?: RunTrace;
135
165
  }
136
166
 
137
167
  export type RunHandlerOutcome =
138
- | { readonly kind: 'ok'; readonly runId: RunId }
168
+ | {
169
+ readonly kind: 'ok';
170
+ readonly runId: RunId;
171
+ /** The `idempotencyKey` named a run that already existed: nothing new started. */
172
+ readonly existing?: true;
173
+ }
139
174
  | { readonly kind: 'err'; readonly error: RunHandlerFailure };
140
175
 
141
176
  /**
@@ -88,17 +88,41 @@ export interface ListApprovalsBindingInput {
88
88
  readonly status?: ApprovalStatus;
89
89
  readonly requiredRole?: ReviewerRole;
90
90
  readonly since?: Timestamp;
91
+ /** A bare time: approvals created before it. Milliseconds, no tie-breaker; `after` replaces it. */
91
92
  readonly cursor?: Cursor;
92
93
  /**
93
94
  * Only approvals whose `waitTokenId` is one of these: the approvals a
94
95
  * run's open waits belong to (T272). Absent: no filter.
95
96
  */
96
97
  readonly waitTokenIds?: readonly string[];
98
+ /**
99
+ * Only approvals after this one in the list's order (`createdAt` desc,
100
+ * then `id` desc): where a page that ended on it continues. Its
101
+ * `createdAt` is the binding's `exactCreatedAt` for it.
102
+ */
103
+ readonly after?: ApprovalPosition;
104
+ }
105
+
106
+ /**
107
+ * Where a page of approvals ends: an approval's `createdAt` as stored
108
+ * (Postgres keeps microseconds), and its id. A JS `Date` keeps
109
+ * milliseconds: a position built from one skips the approvals created
110
+ * earlier in the same millisecond.
111
+ */
112
+ export interface ApprovalPosition {
113
+ readonly createdAt: string;
114
+ readonly id: ApprovalId;
97
115
  }
98
116
 
99
117
  export interface ListApprovalsBindingResult {
100
118
  readonly approvals: readonly Approval[];
101
119
  readonly nextCursor?: Cursor;
120
+ /**
121
+ * Each listed approval's `createdAt` as stored (microseconds), by id:
122
+ * with the id, the `after` that continues past it. Absent from a binding
123
+ * that doesn't give it; a caller then continues by `cursor`.
124
+ */
125
+ readonly exactCreatedAt?: Readonly<Record<string, string>>;
102
126
  }
103
127
 
104
128
  export interface SubmitReviewBindingInput {
@@ -13,16 +13,16 @@ import type { Cursor, TenantId, Timestamp, UserId } from '@kindgi/types';
13
13
  * tenant" / "show me a user's profile" / "revoke all a user's active
14
14
  * sessions" question this binding covers.
15
15
  *
16
- * Registry-only over HTTP — the framework does NOT own user
17
- * persistence. Deployments plug in an LDAP / SCIM / IdP-mirror /
18
- * bespoke store behind this binding.
16
+ * The framework does NOT own user persistence. Deployments plug in an
17
+ * LDAP / SCIM / IdP-mirror / bespoke store behind this binding.
19
18
  *
20
19
  * Same caller-plugged pattern as every other admin-plane binding
21
20
  * (`PolicyRegistryBinding`, `ProviderRegistryBinding`, ...).
22
21
  *
23
22
  * The directory is flat. Groups / roles / RBAC / invitations /
24
23
  * audit history / LDAP+SCIM sync / impersonation are not part of this
25
- * binding.
24
+ * binding. Adding a person (`createUser`) is optional: a directory that
25
+ * mirrors an identity provider leaves it out.
26
26
  */
27
27
  export interface IdentityDirectoryBinding {
28
28
  /**
@@ -30,6 +30,14 @@ export interface IdentityDirectoryBinding {
30
30
  * the route surfaces `null` as `404 identity-user-not-found`.
31
31
  */
32
32
  getUser(input: IdentityGetUserInput): Promise<UserRecord | null>;
33
+ /**
34
+ * Optional. The person still in the tenant whose `primaryEmail` is
35
+ * `email`, compared as the directory compares emails when it adds a
36
+ * person (case-insensitively, for the runtime's); `null` when none.
37
+ * When present, `POST /v1/projects/{projectId}/memberships` takes an
38
+ * `email` as well as a `userId`.
39
+ */
40
+ findUserByEmail?(input: IdentityFindUserByEmailInput): Promise<UserRecord | null>;
33
41
  /**
34
42
  * Cursor-paginated list of users in the tenant. Optional `query`
35
43
  * is a prefix match on `displayName` — the natural filter shape
@@ -55,19 +63,88 @@ export interface IdentityDirectoryBinding {
55
63
  * delegate to `SessionStoreBinding.revokeAllForUser`.
56
64
  */
57
65
  revokeAllSessions(input: IdentityRevokeSessionsInput): Promise<RevokeSessionsResult>;
66
+ /**
67
+ * Optional. Add a person to the tenant as a tenant member, written to
68
+ * the authorization store before it returns: they can read the
69
+ * tenant's settings, not its projects. A tenant admin then gives them a
70
+ * role and mints their first API key. When present,
71
+ * `POST /v1/identity/users` mounts (tenant admins only). An email
72
+ * another person of the tenant has is refused.
73
+ */
74
+ createUser?(input: IdentityCreateUserInput): Promise<IdentityCreateUserResult>;
75
+ /**
76
+ * Optional. Unregister a person (remove them from the tenant), in one
77
+ * step: they're marked unregistered (their record stays, with
78
+ * `unregisteredAt`, so their history still says who they were), every
79
+ * API key and session of theirs is revoked, and every grant and
80
+ * membership they hold is taken from the authorization store, all before
81
+ * it returns. Their email is then free: adding it again makes a new
82
+ * person. Unregistering someone already unregistered changes nothing.
83
+ * Refused for yourself, the deployment's seed user, and the tenant's
84
+ * only tenant admin. When present,
85
+ * `POST /v1/identity/users/{userId}/unregister` mounts (tenant admins
86
+ * only).
87
+ */
88
+ unregisterUser?(input: IdentityUnregisterUserInput): Promise<IdentityUnregisterUserResult>;
89
+ }
90
+
91
+ export interface IdentityUnregisterUserInput {
92
+ readonly tenantId: TenantId;
93
+ readonly userId: UserId;
94
+ /** Who unregisters them: `user:<id>` or `service_account:<id>`. */
95
+ readonly unregisteredBy?: string;
58
96
  }
59
97
 
98
+ /** Why a person can't be unregistered. */
99
+ export type IdentityUnregisterUserRefusal = 'yourself' | 'seed-user' | 'last-tenant-admin';
100
+
101
+ export type IdentityUnregisterUserResult =
102
+ | {
103
+ readonly kind: 'unregistered';
104
+ /** The person, with `unregisteredAt`. */
105
+ readonly user: UserRecord;
106
+ /** What unregistering took away (each 0 when they were already unregistered). */
107
+ readonly keysRevoked: number;
108
+ readonly sessionsRevoked: number;
109
+ readonly grantsRemoved: number;
110
+ }
111
+ | { readonly kind: 'not-found' }
112
+ | {
113
+ readonly kind: 'refused';
114
+ readonly reason: IdentityUnregisterUserRefusal;
115
+ readonly message: string;
116
+ };
117
+
118
+ export interface IdentityCreateUserInput {
119
+ readonly tenantId: TenantId;
120
+ readonly displayName: string;
121
+ readonly primaryEmail?: string;
122
+ /** Who added them: `user:<id>` or `service_account:<id>`. */
123
+ readonly createdBy?: string;
124
+ }
125
+
126
+ export type IdentityCreateUserResult =
127
+ | { readonly kind: 'created'; readonly user: UserRecord }
128
+ | { readonly kind: 'email-taken'; readonly userId: UserId };
129
+
60
130
  export interface IdentityGetUserInput {
61
131
  readonly tenantId: TenantId;
62
132
  readonly userId: UserId;
63
133
  }
64
134
 
135
+ export interface IdentityFindUserByEmailInput {
136
+ readonly tenantId: TenantId;
137
+ readonly email: string;
138
+ }
139
+
65
140
  export interface IdentityListUsersInput {
66
141
  readonly tenantId: TenantId;
67
142
  readonly limit: number;
68
143
  readonly cursor?: Cursor;
69
144
  /** Prefix match on `UserRecord.displayName`. Undefined = no filter. */
70
145
  readonly query?: string;
146
+ /** Unregistered people too (`unregisteredAt` set). Default: only the people still here. */
147
+ readonly includeUnregistered?: boolean;
71
148
  }
72
149
 
73
150
  export interface IdentityListSessionsInput {
@@ -78,6 +155,8 @@ export interface IdentityListSessionsInput {
78
155
  export interface IdentityRevokeSessionsInput {
79
156
  readonly tenantId: TenantId;
80
157
  readonly userId: UserId;
158
+ /** Who asked (`user:<id>`, `service_account:<id>`), for the audit trail. */
159
+ readonly revokedBy?: string;
81
160
  }
82
161
 
83
162
  /**
@@ -94,6 +173,8 @@ export interface UserRecord {
94
173
  readonly displayName?: string;
95
174
  readonly createdAt: Timestamp;
96
175
  readonly lastActiveAt?: Timestamp;
176
+ /** When they were removed from the tenant (`unregisterUser`); absent while they're here. */
177
+ readonly unregisteredAt?: Timestamp;
97
178
  readonly metadata?: Readonly<Record<string, unknown>>;
98
179
  }
99
180
 
@@ -4,35 +4,216 @@
4
4
  import type { TenantId } from '@kindgi/types';
5
5
 
6
6
  /**
7
- * Caller-plugged catalog of OAuth 2.0 / OIDC identity providers the
8
- * deployment offers to its tenants. Same pattern as
9
- * `ProviderRegistryBinding` (model providers) — the API package does
10
- * NOT own provider persistence, and secrets never cross the wire.
7
+ * Caller-plugged catalog of the identity providers a tenant signs in
8
+ * with: OIDC and SAML identity providers (sign-in), and plain OAuth 2.0
9
+ * providers. Same pattern as `ProviderRegistryBinding` (model providers):
10
+ * the API package does NOT own provider persistence, and secrets never
11
+ * cross the wire.
11
12
  *
12
- * A `ProviderConfig` carries ONLY a `clientSecretRef` — an opaque
13
- * pointer that the deployment resolves server-side (env-var lookup,
14
- * secrets-manager path, KMS handle, etc.). The plaintext client secret
15
- * is exchanged with the identity provider inside the deployment's
16
- * boundary during the code→token exchange in `/v1/auth/callback` and
17
- * never surfaces on any HTTP response.
13
+ * A provider carries only REFERENCES to its secrets (`clientSecretRef`,
14
+ * `spSigningKeyRef`, `spDecryptionKeyRef`): opaque pointers the deployment
15
+ * resolves server-side (env-var lookup, secrets-manager path, KMS handle,
16
+ * etc.). The secrets themselves are used inside the deployment's boundary
17
+ * and never surface on any HTTP response.
18
18
  *
19
- * PKCE is mandatory (S256). Providers that don't support PKCE are
20
- * rejected at boot; the framework does NOT emit `code_challenge_method`
21
- * negotiation.
19
+ * PKCE is mandatory (S256) for the OAuth flows.
22
20
  */
23
21
  export interface IdentityProviderBinding {
24
22
  list(input: IdentityProviderListInput): Promise<IdentityProviderPage>;
25
23
  get(input: IdentityProviderGetInput): Promise<ProviderConfig | null>;
26
24
  register(input: IdentityProviderRegisterInput): Promise<IdentityProviderRegisterOutcome>;
27
25
  unregister(input: IdentityProviderUnregisterInput): Promise<IdentityProviderUnregisterOutcome>;
26
+ /**
27
+ * The ways a person can sign in, before anyone is signed in
28
+ * (`GET /v1/auth/sign-in-options`, unauthenticated). Answer by the email
29
+ * DOMAIN only, never by whether a person exists:
30
+ * - with `emailDomain`: the providers whose `domains` include it, from
31
+ * the one tenant the domain is verified for (the deployment decides
32
+ * how: e.g. the only tenant it serves, or one its operator named);
33
+ * none when the domain isn't verified for any tenant;
34
+ * - without: the route doesn't ask. Sign-in is email first, so nothing
35
+ * is offered before an email.
36
+ * Absent → the route answers an empty list.
37
+ */
38
+ readonly signInOptions?: (input: SignInOptionsInput) => Promise<readonly SignInOption[]>;
39
+ /**
40
+ * What to give the identity provider so it can send people back
41
+ * (`signIn`), for a provider registered now or later under this
42
+ * `providerId`: the same before registration, after it, and after an
43
+ * unregister and a new registration, so an admin can set up the
44
+ * identity provider's side first. `undefined` when this deployment
45
+ * doesn't sign in with that `kind`.
46
+ * Absent → `GET /v1/auth/providers/:providerId/sign-in` isn't mounted.
47
+ */
48
+ readonly signInUrls?: (
49
+ input: IdentityProviderSignInUrlsInput,
50
+ ) => Promise<ProviderSignIn | undefined>;
51
+ /**
52
+ * Replace a registered provider's configuration, keeping its `signIn`
53
+ * (the identity provider's side doesn't change). Validated as a new
54
+ * registration is.
55
+ * Absent → `PATCH /v1/auth/providers/:providerId` isn't mounted.
56
+ */
57
+ readonly update?: (input: IdentityProviderUpdateInput) => Promise<IdentityProviderUpdateOutcome>;
58
+ }
59
+
60
+ export interface IdentityProviderSignInUrlsInput {
61
+ readonly tenantId: TenantId;
62
+ readonly providerId: string;
63
+ readonly kind: IdentityProviderKind;
64
+ }
65
+
66
+ export interface IdentityProviderUpdateInput {
67
+ readonly tenantId: TenantId;
68
+ /** The whole new configuration (the route merges the changes in). */
69
+ readonly config: ProviderConfig;
28
70
  }
29
71
 
30
- export type IdentityProviderKind = 'oauth2' | 'oidc';
72
+ export type IdentityProviderUpdateOutcome =
73
+ | { readonly kind: 'ok'; readonly provider: ProviderConfig }
74
+ | {
75
+ /** As on registration: 422 `identity-provider-invalid`, with `message`. */
76
+ readonly kind: 'invalid';
77
+ readonly message: string;
78
+ }
79
+ | { readonly kind: 'not-found' };
31
80
 
32
- export interface ProviderConfig {
33
- /** Stable string chosen by the deployment (e.g. `acme-sso`, `globex-oidc`). */
81
+ export interface SignInOptionsInput {
82
+ /** Lowercase, from the email the person typed. */
83
+ readonly emailDomain?: string;
84
+ }
85
+
86
+ /** One way to sign in, as a sign-in page shows it. */
87
+ export interface SignInOption {
88
+ readonly providerId: string;
89
+ /** "Sign in with …". */
90
+ readonly displayName: string;
91
+ /** Where the browser goes to start signing in with this provider. */
92
+ readonly signInUrl: string;
93
+ /**
94
+ * Whose it is: a workspace's own identity provider (`tenant`), or one
95
+ * the deployment offers everyone it has added ("Continue with Google",
96
+ * `deployment`). A sign-in page shows a workspace's own first. Absent:
97
+ * `tenant`.
98
+ */
99
+ readonly owner?: 'tenant' | 'deployment';
100
+ }
101
+
102
+ /**
103
+ * - `oidc`: an OpenID Connect identity provider people sign in with
104
+ * (Okta, Entra ID, Google, Keycloak…): an `issuer`, the endpoints come
105
+ * from its discovery document.
106
+ * - `saml`: a SAML 2.0 identity provider people sign in with.
107
+ * - `oauth2`: a plain OAuth 2.0 provider that isn't OpenID Connect (e.g.
108
+ * GitHub), with its endpoints given. Pick `oidc` for any provider that
109
+ * speaks OpenID Connect.
110
+ */
111
+ export type IdentityProviderKind = 'oauth2' | 'oidc' | 'saml';
112
+
113
+ /**
114
+ * An identity provider's configuration: one shape per `kind`. Narrow on
115
+ * `kind` before reading kind-specific fields (`clientId`,
116
+ * `tokenEndpoint`, `idpMetadataXml`…).
117
+ */
118
+ export type ProviderConfig = OAuth2ProviderConfig | OidcProviderConfig | SamlProviderConfig;
119
+
120
+ /** What every kind of identity provider has. */
121
+ export interface ProviderConfigBase {
122
+ /** Stable string chosen by the tenant (e.g. `acme-sso`, `globex-oidc`). */
34
123
  readonly providerId: string;
35
124
  readonly kind: IdentityProviderKind;
125
+ /** The name a sign-in page shows ("Sign in with …"). Default: `providerId`. */
126
+ readonly displayName?: string;
127
+ /**
128
+ * The email domains whose people sign in with this provider (lowercase,
129
+ * e.g. `acme.com`): how an email-first sign-in page finds it.
130
+ */
131
+ readonly domains?: readonly string[];
132
+ /**
133
+ * Who may sign in the first time: `invite` (default) only people a
134
+ * tenant admin added; `domain` also anyone from one of `domains`, once
135
+ * the deployment has verified them.
136
+ */
137
+ readonly join?: 'invite' | 'domain';
138
+ /**
139
+ * What to give the identity provider so it can send people back: set
140
+ * by the deployment on what it returns; ignored on registration.
141
+ */
142
+ readonly signIn?: ProviderSignIn;
143
+ readonly metadata?: Record<string, unknown>;
144
+ }
145
+
146
+ /** Where the identity provider sends people back to. */
147
+ export type ProviderSignIn =
148
+ | {
149
+ /** OIDC / OAuth 2.0: the redirect URI to allow on the provider's client. */
150
+ readonly redirectUri: string;
151
+ }
152
+ | {
153
+ /** SAML: the service provider's entity ID, as the IdP knows it. */
154
+ readonly spEntityId: string;
155
+ /** SAML: the assertion consumer service URL (HTTP-POST binding). */
156
+ readonly acsUrl: string;
157
+ /** SAML: the service provider's metadata, for IdPs that import it. */
158
+ readonly spMetadataUrl: string;
159
+ };
160
+
161
+ /** An OpenID Connect identity provider (sign-in). */
162
+ export interface OidcProviderConfig extends ProviderConfigBase {
163
+ readonly kind: 'oidc';
164
+ /** The issuer; its `/.well-known/openid-configuration` gives the endpoints. */
165
+ readonly issuer: string;
166
+ readonly clientId: string;
167
+ /** Opaque pointer resolved server-side. Never a plaintext secret. */
168
+ readonly clientSecretRef: string;
169
+ /** Default `openid email profile`. */
170
+ readonly scopes?: readonly string[];
171
+ /** From discovery when absent; returned once the deployment has them. */
172
+ readonly authorizationEndpoint?: string;
173
+ readonly tokenEndpoint?: string;
174
+ readonly userinfoEndpoint?: string;
175
+ readonly jwksEndpoint?: string;
176
+ readonly allowedRedirectUris?: readonly string[];
177
+ readonly claimMapping?: ClaimMappingSpec;
178
+ }
179
+
180
+ /** A SAML 2.0 identity provider (sign-in). */
181
+ export interface SamlProviderConfig extends ProviderConfigBase {
182
+ readonly kind: 'saml';
183
+ /** The IdP's metadata XML. Or give `idpEntityId` + `idpSsoUrl` + `idpCertificates`. */
184
+ readonly idpMetadataXml?: string;
185
+ readonly idpEntityId?: string;
186
+ /** The IdP's single sign-on URL (HTTP-Redirect binding). */
187
+ readonly idpSsoUrl?: string;
188
+ /** The IdP's signing certificates (PEM); several during a rollover. */
189
+ readonly idpCertificates?: readonly string[];
190
+ /**
191
+ * Opaque pointer to the service provider's signing key (PEM), for IdPs
192
+ * that require signed AuthnRequests. Never a plaintext key.
193
+ */
194
+ readonly spSigningKeyRef?: string;
195
+ /** Opaque pointer to the key that decrypts encrypted assertions. Never a plaintext key. */
196
+ readonly spDecryptionKeyRef?: string;
197
+ /** Require signed assertions. Default `true`. */
198
+ readonly wantAssertionsSigned?: boolean;
199
+ /** Assertion attribute names. Defaults: `userId` = the NameID, `email` = `email`. */
200
+ readonly attributeMapping?: SamlAttributeMapping;
201
+ }
202
+
203
+ export interface SamlAttributeMapping {
204
+ readonly userId?: string;
205
+ readonly email?: string;
206
+ readonly displayName?: string;
207
+ }
208
+
209
+ /**
210
+ * A plain OAuth 2.0 provider that isn't OpenID Connect (e.g. GitHub), run
211
+ * by this package's own OAuth flow (`/v1/auth/login` + callback, with the
212
+ * deployment's `exchangeCode`). For a provider that speaks OpenID Connect,
213
+ * use `oidc`.
214
+ */
215
+ export interface OAuth2ProviderConfig extends ProviderConfigBase {
216
+ readonly kind: 'oauth2';
36
217
  readonly clientId: string;
37
218
  /**
38
219
  * Opaque pointer resolved server-side. Never a plaintext secret. The
@@ -69,7 +250,6 @@ export interface ProviderConfig {
69
250
  * own `ExchangeCodeFn` MAY honor this field the same way.
70
251
  */
71
252
  readonly claimMapping?: ClaimMappingSpec;
72
- readonly metadata?: Record<string, unknown>;
73
253
  }
74
254
 
75
255
  /**
@@ -140,10 +320,25 @@ export interface IdentityProviderRegisterInput {
140
320
  readonly config: ProviderConfig;
141
321
  }
142
322
 
143
- export type IdentityProviderRegisterOutcome = {
144
- readonly kind: 'ok';
145
- readonly providerId: string;
146
- };
323
+ export type IdentityProviderRegisterOutcome =
324
+ | {
325
+ readonly kind: 'ok';
326
+ readonly providerId: string;
327
+ /**
328
+ * The provider as stored: discovered endpoints, `signIn`. Absent from
329
+ * older bindings; the route then answers with `providerId` alone.
330
+ */
331
+ readonly provider?: ProviderConfig;
332
+ }
333
+ | {
334
+ /**
335
+ * The deployment couldn't use the configuration: the issuer's
336
+ * discovery failed, the SAML metadata didn't parse, a host it may
337
+ * not reach. 422 `identity-provider-invalid`, with `message`.
338
+ */
339
+ readonly kind: 'invalid';
340
+ readonly message: string;
341
+ };
147
342
 
148
343
  export interface IdentityProviderUnregisterInput {
149
344
  readonly tenantId: TenantId;