@kindgi/api 0.0.0-bootstrap.0 → 0.1.1

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 (505) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +216 -1
  3. package/dist/adapter-binding.d.ts +177 -0
  4. package/dist/adapter-binding.d.ts.map +1 -0
  5. package/dist/adapter-binding.js +12 -0
  6. package/dist/adapter-binding.js.map +1 -0
  7. package/dist/agent-binding.d.ts +207 -0
  8. package/dist/agent-binding.d.ts.map +1 -0
  9. package/dist/agent-binding.js +4 -0
  10. package/dist/agent-binding.js.map +1 -0
  11. package/dist/app.d.ts +770 -0
  12. package/dist/app.d.ts.map +1 -0
  13. package/dist/app.js +397 -0
  14. package/dist/app.js.map +1 -0
  15. package/dist/capability-binding.d.ts +76 -0
  16. package/dist/capability-binding.d.ts.map +1 -0
  17. package/dist/capability-binding.js +4 -0
  18. package/dist/capability-binding.js.map +1 -0
  19. package/dist/cost-binding.d.ts +175 -0
  20. package/dist/cost-binding.d.ts.map +1 -0
  21. package/dist/cost-binding.js +13 -0
  22. package/dist/cost-binding.js.map +1 -0
  23. package/dist/deployment-binding.d.ts +201 -0
  24. package/dist/deployment-binding.d.ts.map +1 -0
  25. package/dist/deployment-binding.js +4 -0
  26. package/dist/deployment-binding.js.map +1 -0
  27. package/dist/env-binding.d.ts +132 -0
  28. package/dist/env-binding.d.ts.map +1 -0
  29. package/dist/env-binding.js +4 -0
  30. package/dist/env-binding.js.map +1 -0
  31. package/dist/errors.d.ts +37 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +268 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/eval-run-binding.d.ts +196 -0
  36. package/dist/eval-run-binding.d.ts.map +1 -0
  37. package/dist/eval-run-binding.js +16 -0
  38. package/dist/eval-run-binding.js.map +1 -0
  39. package/dist/eval-run-dispatcher.d.ts +131 -0
  40. package/dist/eval-run-dispatcher.d.ts.map +1 -0
  41. package/dist/eval-run-dispatcher.js +368 -0
  42. package/dist/eval-run-dispatcher.js.map +1 -0
  43. package/dist/eval-suite-binding.d.ts +227 -0
  44. package/dist/eval-suite-binding.d.ts.map +1 -0
  45. package/dist/eval-suite-binding.js +24 -0
  46. package/dist/eval-suite-binding.js.map +1 -0
  47. package/dist/event-bus-binding.d.ts +107 -0
  48. package/dist/event-bus-binding.d.ts.map +1 -0
  49. package/dist/event-bus-binding.js +5 -0
  50. package/dist/event-bus-binding.js.map +1 -0
  51. package/dist/flow-binding.d.ts +194 -0
  52. package/dist/flow-binding.d.ts.map +1 -0
  53. package/dist/flow-binding.js +4 -0
  54. package/dist/flow-binding.js.map +1 -0
  55. package/dist/guardrail-binding.d.ts +138 -0
  56. package/dist/guardrail-binding.d.ts.map +1 -0
  57. package/dist/guardrail-binding.js +4 -0
  58. package/dist/guardrail-binding.js.map +1 -0
  59. package/dist/handler-binding.d.ts +126 -0
  60. package/dist/handler-binding.d.ts.map +1 -0
  61. package/dist/handler-binding.js +4 -0
  62. package/dist/handler-binding.js.map +1 -0
  63. package/dist/hitl-binding.d.ts +115 -0
  64. package/dist/hitl-binding.d.ts.map +1 -0
  65. package/dist/hitl-binding.js +4 -0
  66. package/dist/hitl-binding.js.map +1 -0
  67. package/dist/identity-directory-binding.d.ts +116 -0
  68. package/dist/identity-directory-binding.d.ts.map +1 -0
  69. package/dist/identity-directory-binding.js +4 -0
  70. package/dist/identity-directory-binding.js.map +1 -0
  71. package/dist/identity-provider-binding.d.ts +184 -0
  72. package/dist/identity-provider-binding.d.ts.map +1 -0
  73. package/dist/identity-provider-binding.js +4 -0
  74. package/dist/identity-provider-binding.js.map +1 -0
  75. package/dist/image-registry-binding.d.ts +165 -0
  76. package/dist/image-registry-binding.d.ts.map +1 -0
  77. package/dist/image-registry-binding.js +4 -0
  78. package/dist/image-registry-binding.js.map +1 -0
  79. package/dist/index.d.ts +72 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +26 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/key-management-binding.d.ts +101 -0
  84. package/dist/key-management-binding.d.ts.map +1 -0
  85. package/dist/key-management-binding.js +4 -0
  86. package/dist/key-management-binding.js.map +1 -0
  87. package/dist/mcp-endpoint-binding.d.ts +312 -0
  88. package/dist/mcp-endpoint-binding.d.ts.map +1 -0
  89. package/dist/mcp-endpoint-binding.js +12 -0
  90. package/dist/mcp-endpoint-binding.js.map +1 -0
  91. package/dist/memory-binding.d.ts +209 -0
  92. package/dist/memory-binding.d.ts.map +1 -0
  93. package/dist/memory-binding.js +4 -0
  94. package/dist/memory-binding.js.map +1 -0
  95. package/dist/middleware/auth.d.ts +168 -0
  96. package/dist/middleware/auth.d.ts.map +1 -0
  97. package/dist/middleware/auth.js +247 -0
  98. package/dist/middleware/auth.js.map +1 -0
  99. package/dist/middleware/authorize.d.ts +26 -0
  100. package/dist/middleware/authorize.d.ts.map +1 -0
  101. package/dist/middleware/authorize.js +65 -0
  102. package/dist/middleware/authorize.js.map +1 -0
  103. package/dist/middleware/error-mapper.d.ts +20 -0
  104. package/dist/middleware/error-mapper.d.ts.map +1 -0
  105. package/dist/middleware/error-mapper.js +34 -0
  106. package/dist/middleware/error-mapper.js.map +1 -0
  107. package/dist/middleware/idempotency.d.ts +43 -0
  108. package/dist/middleware/idempotency.d.ts.map +1 -0
  109. package/dist/middleware/idempotency.js +118 -0
  110. package/dist/middleware/idempotency.js.map +1 -0
  111. package/dist/middleware/principal.d.ts +4 -0
  112. package/dist/middleware/principal.d.ts.map +1 -0
  113. package/dist/middleware/principal.js +42 -0
  114. package/dist/middleware/principal.js.map +1 -0
  115. package/dist/middleware/public-run-routes.d.ts +16 -0
  116. package/dist/middleware/public-run-routes.d.ts.map +1 -0
  117. package/dist/middleware/public-run-routes.js +43 -0
  118. package/dist/middleware/public-run-routes.js.map +1 -0
  119. package/dist/middleware/request-id.d.ts +14 -0
  120. package/dist/middleware/request-id.d.ts.map +1 -0
  121. package/dist/middleware/request-id.js +24 -0
  122. package/dist/middleware/request-id.js.map +1 -0
  123. package/dist/middleware/sigv4-verify.d.ts +64 -0
  124. package/dist/middleware/sigv4-verify.d.ts.map +1 -0
  125. package/dist/middleware/sigv4-verify.js +286 -0
  126. package/dist/middleware/sigv4-verify.js.map +1 -0
  127. package/dist/middleware/sigv4.d.ts +25 -0
  128. package/dist/middleware/sigv4.d.ts.map +1 -0
  129. package/dist/middleware/sigv4.js +120 -0
  130. package/dist/middleware/sigv4.js.map +1 -0
  131. package/dist/openapi/generate.d.ts +15 -0
  132. package/dist/openapi/generate.d.ts.map +1 -0
  133. package/dist/openapi/generate.js +241 -0
  134. package/dist/openapi/generate.js.map +1 -0
  135. package/dist/openapi/operations.d.ts +70 -0
  136. package/dist/openapi/operations.d.ts.map +1 -0
  137. package/dist/openapi/operations.js +5050 -0
  138. package/dist/openapi/operations.js.map +1 -0
  139. package/dist/openapi/schemas.d.ts +590 -0
  140. package/dist/openapi/schemas.d.ts.map +1 -0
  141. package/dist/openapi/schemas.js +5820 -0
  142. package/dist/openapi/schemas.js.map +1 -0
  143. package/dist/provenance-binding.d.ts +116 -0
  144. package/dist/provenance-binding.d.ts.map +1 -0
  145. package/dist/provenance-binding.js +31 -0
  146. package/dist/provenance-binding.js.map +1 -0
  147. package/dist/provider-binding.d.ts +174 -0
  148. package/dist/provider-binding.d.ts.map +1 -0
  149. package/dist/provider-binding.js +4 -0
  150. package/dist/provider-binding.js.map +1 -0
  151. package/dist/public-run-token.d.ts +97 -0
  152. package/dist/public-run-token.d.ts.map +1 -0
  153. package/dist/public-run-token.js +167 -0
  154. package/dist/public-run-token.js.map +1 -0
  155. package/dist/retention-binding.d.ts +69 -0
  156. package/dist/retention-binding.d.ts.map +1 -0
  157. package/dist/retention-binding.js +4 -0
  158. package/dist/retention-binding.js.map +1 -0
  159. package/dist/reviewer-binding.d.ts +84 -0
  160. package/dist/reviewer-binding.d.ts.map +1 -0
  161. package/dist/reviewer-binding.js +4 -0
  162. package/dist/reviewer-binding.js.map +1 -0
  163. package/dist/rotation-status-store.d.ts +96 -0
  164. package/dist/rotation-status-store.d.ts.map +1 -0
  165. package/dist/rotation-status-store.js +106 -0
  166. package/dist/rotation-status-store.js.map +1 -0
  167. package/dist/routes/adapters.d.ts +29 -0
  168. package/dist/routes/adapters.d.ts.map +1 -0
  169. package/dist/routes/adapters.js +230 -0
  170. package/dist/routes/adapters.js.map +1 -0
  171. package/dist/routes/agents.d.ts +17 -0
  172. package/dist/routes/agents.d.ts.map +1 -0
  173. package/dist/routes/agents.js +342 -0
  174. package/dist/routes/agents.js.map +1 -0
  175. package/dist/routes/approvals.d.ts +37 -0
  176. package/dist/routes/approvals.d.ts.map +1 -0
  177. package/dist/routes/approvals.js +551 -0
  178. package/dist/routes/approvals.js.map +1 -0
  179. package/dist/routes/artifacts.d.ts +25 -0
  180. package/dist/routes/artifacts.d.ts.map +1 -0
  181. package/dist/routes/artifacts.js +265 -0
  182. package/dist/routes/artifacts.js.map +1 -0
  183. package/dist/routes/audit.d.ts +6 -0
  184. package/dist/routes/audit.d.ts.map +1 -0
  185. package/dist/routes/audit.js +162 -0
  186. package/dist/routes/audit.js.map +1 -0
  187. package/dist/routes/auth.d.ts +47 -0
  188. package/dist/routes/auth.d.ts.map +1 -0
  189. package/dist/routes/auth.js +630 -0
  190. package/dist/routes/auth.js.map +1 -0
  191. package/dist/routes/capabilities.d.ts +14 -0
  192. package/dist/routes/capabilities.d.ts.map +1 -0
  193. package/dist/routes/capabilities.js +62 -0
  194. package/dist/routes/capabilities.js.map +1 -0
  195. package/dist/routes/compliance.d.ts +37 -0
  196. package/dist/routes/compliance.d.ts.map +1 -0
  197. package/dist/routes/compliance.js +321 -0
  198. package/dist/routes/compliance.js.map +1 -0
  199. package/dist/routes/conversations.d.ts +13 -0
  200. package/dist/routes/conversations.d.ts.map +1 -0
  201. package/dist/routes/conversations.js +295 -0
  202. package/dist/routes/conversations.js.map +1 -0
  203. package/dist/routes/cost.d.ts +24 -0
  204. package/dist/routes/cost.d.ts.map +1 -0
  205. package/dist/routes/cost.js +243 -0
  206. package/dist/routes/cost.js.map +1 -0
  207. package/dist/routes/deployments.d.ts +122 -0
  208. package/dist/routes/deployments.d.ts.map +1 -0
  209. package/dist/routes/deployments.js +1036 -0
  210. package/dist/routes/deployments.js.map +1 -0
  211. package/dist/routes/env.d.ts +62 -0
  212. package/dist/routes/env.d.ts.map +1 -0
  213. package/dist/routes/env.js +311 -0
  214. package/dist/routes/env.js.map +1 -0
  215. package/dist/routes/eval-runs.d.ts +28 -0
  216. package/dist/routes/eval-runs.d.ts.map +1 -0
  217. package/dist/routes/eval-runs.js +479 -0
  218. package/dist/routes/eval-runs.js.map +1 -0
  219. package/dist/routes/eval-suites.d.ts +24 -0
  220. package/dist/routes/eval-suites.d.ts.map +1 -0
  221. package/dist/routes/eval-suites.js +381 -0
  222. package/dist/routes/eval-suites.js.map +1 -0
  223. package/dist/routes/event-triggers.d.ts +12 -0
  224. package/dist/routes/event-triggers.d.ts.map +1 -0
  225. package/dist/routes/event-triggers.js +218 -0
  226. package/dist/routes/event-triggers.js.map +1 -0
  227. package/dist/routes/flows.d.ts +23 -0
  228. package/dist/routes/flows.d.ts.map +1 -0
  229. package/dist/routes/flows.js +344 -0
  230. package/dist/routes/flows.js.map +1 -0
  231. package/dist/routes/guardrails.d.ts +33 -0
  232. package/dist/routes/guardrails.d.ts.map +1 -0
  233. package/dist/routes/guardrails.js +236 -0
  234. package/dist/routes/guardrails.js.map +1 -0
  235. package/dist/routes/identity.d.ts +39 -0
  236. package/dist/routes/identity.d.ts.map +1 -0
  237. package/dist/routes/identity.js +138 -0
  238. package/dist/routes/identity.js.map +1 -0
  239. package/dist/routes/mcp.d.ts +23 -0
  240. package/dist/routes/mcp.d.ts.map +1 -0
  241. package/dist/routes/mcp.js +727 -0
  242. package/dist/routes/mcp.js.map +1 -0
  243. package/dist/routes/memory.d.ts +16 -0
  244. package/dist/routes/memory.d.ts.map +1 -0
  245. package/dist/routes/memory.js +353 -0
  246. package/dist/routes/memory.js.map +1 -0
  247. package/dist/routes/observations.d.ts +19 -0
  248. package/dist/routes/observations.d.ts.map +1 -0
  249. package/dist/routes/observations.js +135 -0
  250. package/dist/routes/observations.js.map +1 -0
  251. package/dist/routes/orgs.d.ts +24 -0
  252. package/dist/routes/orgs.d.ts.map +1 -0
  253. package/dist/routes/orgs.js +208 -0
  254. package/dist/routes/orgs.js.map +1 -0
  255. package/dist/routes/pagination.d.ts +18 -0
  256. package/dist/routes/pagination.d.ts.map +1 -0
  257. package/dist/routes/pagination.js +35 -0
  258. package/dist/routes/pagination.js.map +1 -0
  259. package/dist/routes/policies.d.ts +23 -0
  260. package/dist/routes/policies.d.ts.map +1 -0
  261. package/dist/routes/policies.js +314 -0
  262. package/dist/routes/policies.js.map +1 -0
  263. package/dist/routes/projects.d.ts +45 -0
  264. package/dist/routes/projects.d.ts.map +1 -0
  265. package/dist/routes/projects.js +485 -0
  266. package/dist/routes/projects.js.map +1 -0
  267. package/dist/routes/proposals.d.ts +24 -0
  268. package/dist/routes/proposals.d.ts.map +1 -0
  269. package/dist/routes/proposals.js +581 -0
  270. package/dist/routes/proposals.js.map +1 -0
  271. package/dist/routes/provenance.d.ts +34 -0
  272. package/dist/routes/provenance.d.ts.map +1 -0
  273. package/dist/routes/provenance.js +274 -0
  274. package/dist/routes/provenance.js.map +1 -0
  275. package/dist/routes/providers.d.ts +32 -0
  276. package/dist/routes/providers.d.ts.map +1 -0
  277. package/dist/routes/providers.js +490 -0
  278. package/dist/routes/providers.js.map +1 -0
  279. package/dist/routes/public-run-tokens.d.ts +17 -0
  280. package/dist/routes/public-run-tokens.d.ts.map +1 -0
  281. package/dist/routes/public-run-tokens.js +69 -0
  282. package/dist/routes/public-run-tokens.js.map +1 -0
  283. package/dist/routes/retention.d.ts +19 -0
  284. package/dist/routes/retention.d.ts.map +1 -0
  285. package/dist/routes/retention.js +152 -0
  286. package/dist/routes/retention.js.map +1 -0
  287. package/dist/routes/reviewers.d.ts +5 -0
  288. package/dist/routes/reviewers.d.ts.map +1 -0
  289. package/dist/routes/reviewers.js +161 -0
  290. package/dist/routes/reviewers.js.map +1 -0
  291. package/dist/routes/runs.d.ts +34 -0
  292. package/dist/routes/runs.d.ts.map +1 -0
  293. package/dist/routes/runs.js +705 -0
  294. package/dist/routes/runs.js.map +1 -0
  295. package/dist/routes/s3.d.ts +31 -0
  296. package/dist/routes/s3.d.ts.map +1 -0
  297. package/dist/routes/s3.js +433 -0
  298. package/dist/routes/s3.js.map +1 -0
  299. package/dist/routes/schedules.d.ts +20 -0
  300. package/dist/routes/schedules.d.ts.map +1 -0
  301. package/dist/routes/schedules.js +234 -0
  302. package/dist/routes/schedules.js.map +1 -0
  303. package/dist/routes/scope-params.d.ts +57 -0
  304. package/dist/routes/scope-params.d.ts.map +1 -0
  305. package/dist/routes/scope-params.js +105 -0
  306. package/dist/routes/scope-params.js.map +1 -0
  307. package/dist/routes/secret-ref.d.ts +20 -0
  308. package/dist/routes/secret-ref.d.ts.map +1 -0
  309. package/dist/routes/secret-ref.js +42 -0
  310. package/dist/routes/secret-ref.js.map +1 -0
  311. package/dist/routes/secrets.d.ts +53 -0
  312. package/dist/routes/secrets.d.ts.map +1 -0
  313. package/dist/routes/secrets.js +715 -0
  314. package/dist/routes/secrets.js.map +1 -0
  315. package/dist/routes/signing-keys.d.ts +23 -0
  316. package/dist/routes/signing-keys.d.ts.map +1 -0
  317. package/dist/routes/signing-keys.js +212 -0
  318. package/dist/routes/signing-keys.js.map +1 -0
  319. package/dist/routes/sse.d.ts +58 -0
  320. package/dist/routes/sse.d.ts.map +1 -0
  321. package/dist/routes/sse.js +92 -0
  322. package/dist/routes/sse.js.map +1 -0
  323. package/dist/routes/teams.d.ts +30 -0
  324. package/dist/routes/teams.d.ts.map +1 -0
  325. package/dist/routes/teams.js +443 -0
  326. package/dist/routes/teams.js.map +1 -0
  327. package/dist/routes/tenant.d.ts +57 -0
  328. package/dist/routes/tenant.d.ts.map +1 -0
  329. package/dist/routes/tenant.js +352 -0
  330. package/dist/routes/tenant.js.map +1 -0
  331. package/dist/routes/tokens.d.ts +14 -0
  332. package/dist/routes/tokens.d.ts.map +1 -0
  333. package/dist/routes/tokens.js +231 -0
  334. package/dist/routes/tokens.js.map +1 -0
  335. package/dist/routes/tools.d.ts +33 -0
  336. package/dist/routes/tools.d.ts.map +1 -0
  337. package/dist/routes/tools.js +380 -0
  338. package/dist/routes/tools.js.map +1 -0
  339. package/dist/routes/webhook-endpoints.d.ts +10 -0
  340. package/dist/routes/webhook-endpoints.d.ts.map +1 -0
  341. package/dist/routes/webhook-endpoints.js +407 -0
  342. package/dist/routes/webhook-endpoints.js.map +1 -0
  343. package/dist/routes/webhooks.d.ts +21 -0
  344. package/dist/routes/webhooks.d.ts.map +1 -0
  345. package/dist/routes/webhooks.js +228 -0
  346. package/dist/routes/webhooks.js.map +1 -0
  347. package/dist/s3-credential-binding.d.ts +54 -0
  348. package/dist/s3-credential-binding.d.ts.map +1 -0
  349. package/dist/s3-credential-binding.js +4 -0
  350. package/dist/s3-credential-binding.js.map +1 -0
  351. package/dist/secrets-binding.d.ts +281 -0
  352. package/dist/secrets-binding.d.ts.map +1 -0
  353. package/dist/secrets-binding.js +10 -0
  354. package/dist/secrets-binding.js.map +1 -0
  355. package/dist/secrets-provider-binding.d.ts +164 -0
  356. package/dist/secrets-provider-binding.d.ts.map +1 -0
  357. package/dist/secrets-provider-binding.js +4 -0
  358. package/dist/secrets-provider-binding.js.map +1 -0
  359. package/dist/session-store-binding.d.ts +148 -0
  360. package/dist/session-store-binding.d.ts.map +1 -0
  361. package/dist/session-store-binding.js +4 -0
  362. package/dist/session-store-binding.js.map +1 -0
  363. package/dist/signing-key-binding.d.ts +210 -0
  364. package/dist/signing-key-binding.d.ts.map +1 -0
  365. package/dist/signing-key-binding.js +4 -0
  366. package/dist/signing-key-binding.js.map +1 -0
  367. package/dist/state-store-binding.d.ts +53 -0
  368. package/dist/state-store-binding.d.ts.map +1 -0
  369. package/dist/state-store-binding.js +38 -0
  370. package/dist/state-store-binding.js.map +1 -0
  371. package/dist/supervisor-binding.d.ts +526 -0
  372. package/dist/supervisor-binding.d.ts.map +1 -0
  373. package/dist/supervisor-binding.js +4 -0
  374. package/dist/supervisor-binding.js.map +1 -0
  375. package/dist/tenant-host-access.d.ts +41 -0
  376. package/dist/tenant-host-access.d.ts.map +1 -0
  377. package/dist/tenant-host-access.js +42 -0
  378. package/dist/tenant-host-access.js.map +1 -0
  379. package/dist/token-admin.d.ts +99 -0
  380. package/dist/token-admin.d.ts.map +1 -0
  381. package/dist/token-admin.js +4 -0
  382. package/dist/token-admin.js.map +1 -0
  383. package/dist/tool-binding.d.ts +247 -0
  384. package/dist/tool-binding.d.ts.map +1 -0
  385. package/dist/tool-binding.js +4 -0
  386. package/dist/tool-binding.js.map +1 -0
  387. package/dist/trigger-binding.d.ts +13 -0
  388. package/dist/trigger-binding.d.ts.map +1 -0
  389. package/dist/trigger-binding.js +4 -0
  390. package/dist/trigger-binding.js.map +1 -0
  391. package/dist/types.d.ts +71 -0
  392. package/dist/types.d.ts.map +1 -0
  393. package/dist/types.js +4 -0
  394. package/dist/types.js.map +1 -0
  395. package/dist/webhook-endpoint-binding.d.ts +230 -0
  396. package/dist/webhook-endpoint-binding.d.ts.map +1 -0
  397. package/dist/webhook-endpoint-binding.js +12 -0
  398. package/dist/webhook-endpoint-binding.js.map +1 -0
  399. package/dist/xml.d.ts +79 -0
  400. package/dist/xml.d.ts.map +1 -0
  401. package/dist/xml.js +115 -0
  402. package/dist/xml.js.map +1 -0
  403. package/openapi.json +29649 -0
  404. package/package.json +76 -4
  405. package/scripts/emit-openapi.mjs +44 -0
  406. package/src/adapter-binding.ts +204 -0
  407. package/src/agent-binding.ts +231 -0
  408. package/src/app.ts +1286 -0
  409. package/src/capability-binding.ts +83 -0
  410. package/src/cost-binding.ts +213 -0
  411. package/src/deployment-binding.ts +225 -0
  412. package/src/env-binding.ts +140 -0
  413. package/src/errors.ts +295 -0
  414. package/src/eval-run-binding.ts +209 -0
  415. package/src/eval-run-dispatcher.ts +497 -0
  416. package/src/eval-suite-binding.ts +257 -0
  417. package/src/event-bus-binding.ts +127 -0
  418. package/src/flow-binding.ts +213 -0
  419. package/src/guardrail-binding.ts +151 -0
  420. package/src/handler-binding.ts +132 -0
  421. package/src/hitl-binding.ts +172 -0
  422. package/src/identity-directory-binding.ts +128 -0
  423. package/src/identity-provider-binding.ts +203 -0
  424. package/src/image-registry-binding.ts +193 -0
  425. package/src/index.ts +606 -0
  426. package/src/key-management-binding.ts +91 -0
  427. package/src/mcp-endpoint-binding.ts +311 -0
  428. package/src/memory-binding.ts +239 -0
  429. package/src/middleware/auth.ts +437 -0
  430. package/src/middleware/authorize.ts +125 -0
  431. package/src/middleware/error-mapper.ts +40 -0
  432. package/src/middleware/idempotency.ts +160 -0
  433. package/src/middleware/principal.ts +64 -0
  434. package/src/middleware/public-run-routes.ts +50 -0
  435. package/src/middleware/request-id.ts +28 -0
  436. package/src/middleware/sigv4-verify.ts +374 -0
  437. package/src/middleware/sigv4.ts +165 -0
  438. package/src/openapi/generate.ts +307 -0
  439. package/src/openapi/operations.ts +5444 -0
  440. package/src/openapi/schemas.ts +6363 -0
  441. package/src/provenance-binding.ts +169 -0
  442. package/src/provider-binding.ts +196 -0
  443. package/src/public-run-token.ts +263 -0
  444. package/src/retention-binding.ts +78 -0
  445. package/src/reviewer-binding.ts +99 -0
  446. package/src/rotation-status-store.ts +209 -0
  447. package/src/routes/adapters.ts +319 -0
  448. package/src/routes/agents.ts +424 -0
  449. package/src/routes/approvals.ts +759 -0
  450. package/src/routes/artifacts.ts +317 -0
  451. package/src/routes/audit.ts +219 -0
  452. package/src/routes/auth.ts +806 -0
  453. package/src/routes/capabilities.ts +79 -0
  454. package/src/routes/compliance.ts +482 -0
  455. package/src/routes/conversations.ts +369 -0
  456. package/src/routes/cost.ts +327 -0
  457. package/src/routes/deployments.ts +1493 -0
  458. package/src/routes/env.ts +429 -0
  459. package/src/routes/eval-runs.ts +631 -0
  460. package/src/routes/eval-suites.ts +490 -0
  461. package/src/routes/event-triggers.ts +283 -0
  462. package/src/routes/flows.ts +423 -0
  463. package/src/routes/guardrails.ts +320 -0
  464. package/src/routes/identity.ts +203 -0
  465. package/src/routes/mcp.ts +940 -0
  466. package/src/routes/memory.ts +430 -0
  467. package/src/routes/observations.ts +175 -0
  468. package/src/routes/orgs.ts +273 -0
  469. package/src/routes/pagination.ts +51 -0
  470. package/src/routes/policies.ts +413 -0
  471. package/src/routes/projects.ts +634 -0
  472. package/src/routes/proposals.ts +719 -0
  473. package/src/routes/provenance.ts +406 -0
  474. package/src/routes/providers.ts +624 -0
  475. package/src/routes/public-run-tokens.ts +104 -0
  476. package/src/routes/retention.ts +193 -0
  477. package/src/routes/reviewers.ts +209 -0
  478. package/src/routes/runs.ts +892 -0
  479. package/src/routes/s3.ts +519 -0
  480. package/src/routes/schedules.ts +300 -0
  481. package/src/routes/scope-params.ts +133 -0
  482. package/src/routes/secret-ref.ts +52 -0
  483. package/src/routes/secrets.ts +975 -0
  484. package/src/routes/signing-keys.ts +259 -0
  485. package/src/routes/sse.ts +148 -0
  486. package/src/routes/teams.ts +584 -0
  487. package/src/routes/tenant.ts +530 -0
  488. package/src/routes/tokens.ts +285 -0
  489. package/src/routes/tools.ts +491 -0
  490. package/src/routes/webhook-endpoints.ts +534 -0
  491. package/src/routes/webhooks.ts +296 -0
  492. package/src/s3-credential-binding.ts +58 -0
  493. package/src/secrets-binding.ts +308 -0
  494. package/src/secrets-provider-binding.ts +167 -0
  495. package/src/session-store-binding.ts +163 -0
  496. package/src/signing-key-binding.ts +235 -0
  497. package/src/state-store-binding.ts +84 -0
  498. package/src/supervisor-binding.ts +554 -0
  499. package/src/tenant-host-access.ts +62 -0
  500. package/src/token-admin.ts +104 -0
  501. package/src/tool-binding.ts +274 -0
  502. package/src/trigger-binding.ts +38 -0
  503. package/src/types.ts +74 -0
  504. package/src/webhook-endpoint-binding.ts +246 -0
  505. package/src/xml.ts +196 -0
@@ -0,0 +1,530 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import { Hono } from 'hono';
5
+
6
+ import { ref, tuplesForCreate } from '@kindgi/authz';
7
+ import type { Scope, TenantHierarchyBinding } from '@kindgi/platform';
8
+ import type { Cursor, EnvName, TenantId } from '@kindgi/types';
9
+ import { makeEnvName } from '@kindgi/types';
10
+
11
+ import type { EnvBinding, EnvRecord } from '../env-binding.js';
12
+ import { statusFor, toWireError } from '../errors.js';
13
+ import type { Authorizer } from '../middleware/authorize.js';
14
+ import type { SecretBinding, SecretRecord } from '../secrets-binding.js';
15
+ import type { AppEnv } from '../types.js';
16
+ import { clampLimit } from './pagination.js';
17
+
18
+ /**
19
+ * Tenant resource routes — part of the multi-tenant hierarchy. Config
20
+ * reads and writes route through the two symmetric bindings
21
+ * `EnvBinding` + `SecretBinding` at tenant scope.
22
+ *
23
+ * Three endpoints on `/v1/tenant` — the caller's tenant is always
24
+ * implicit from the bearer token; there is no `/v1/tenants` collection
25
+ * (tenants are the sovereignty boundary, not a listable resource under
26
+ * a tenant).
27
+ *
28
+ * - `GET /` — returns `{ id, name, slug, createdAt,
29
+ * updatedAt }` for the caller's tenant.
30
+ * Reads the tenant via the tenant-hierarchy
31
+ * binding.
32
+ * - `GET /config` — cursor-paginated list of the tenant's config
33
+ * entries: the env entries, then the secret
34
+ * entries. Merged view over `EnvBinding.list` +
35
+ * `SecretBinding.list` at `scope: tenant` with
36
+ * `inherit: false` (tenant is the top of the
37
+ * resolution walk — no upward inheritance is
38
+ * possible). Optional `?kind=` filters to one
39
+ * binding; `env` and `config` both surface the
40
+ * env binding. Secret
41
+ * `value` is ALWAYS redacted here (the admin
42
+ * surface never returns raw plaintext).
43
+ * - `PATCH /config` — upsert one config entry. Body: `{ kind, key,
44
+ * value, sensitive?, ifRevision? }`. Routes to
45
+ * `SecretBinding.set` when `kind === 'secret'`
46
+ * OR `sensitive === true`; else to
47
+ * `EnvBinding.set`. Returns 200 with `{ entry }`
48
+ * on ok, 409 `tenant-config-revision-conflict`
49
+ * when `ifRevision` mismatches.
50
+ *
51
+ * Env dimension. The wire shape doesn't carry `envName`, but both
52
+ * bindings require it. The router
53
+ * derives it from `KINDGI_ENV_NAME` at request time, falling back to
54
+ * `'default'` if unset. Deployments that want per-env writes should use
55
+ * the dedicated `/v1/env/*` + `/v1/secrets/*` routes.
56
+ *
57
+ * Mount policy. `/config` mounts when either `envBinding` OR
58
+ * `secretsBinding` is present. If only one is wired, the other class of
59
+ * writes returns 400 with a clear message.
60
+ */
61
+ export interface TenantRouterOptions {
62
+ readonly tenantHierarchyBinding: TenantHierarchyBinding;
63
+ readonly envBinding?: EnvBinding;
64
+ readonly secretsBinding?: SecretBinding;
65
+ readonly authorizer?: Authorizer;
66
+ }
67
+
68
+ /**
69
+ * Wire shape of one tenant config entry. Callers speak
70
+ * `{ kind, key, value, sensitive?, revision, updatedAt }` and see the
71
+ * same response envelope regardless of which binding actually stored
72
+ * the write. `kind` collapses — `env` and `config` both
73
+ * name the env binding; only `secret` names the secrets binding.
74
+ */
75
+ type CompatConfigKind = 'env' | 'config' | 'secret';
76
+
77
+ interface CompatConfigEntry {
78
+ readonly tenantId: TenantId;
79
+ readonly kind: CompatConfigKind;
80
+ readonly key: string;
81
+ readonly value: string;
82
+ readonly sensitive: boolean;
83
+ readonly revision: number;
84
+ readonly updatedAt: string;
85
+ }
86
+
87
+ /** The binding a `GET /config` page reads from: env entries first, then secrets. */
88
+ type ConfigSource = 'env' | 'secret';
89
+
90
+ /** Position in the merged list: a binding, and that binding's own cursor. */
91
+ interface ConfigCursor {
92
+ readonly source: ConfigSource;
93
+ readonly cursor?: string;
94
+ }
95
+
96
+ /**
97
+ * Upper bound on binding `list` calls per `GET /config` request, so a
98
+ * binding that keeps returning empty pages with a `nextCursor` can't
99
+ * hold the request open; the response then carries the cursor on.
100
+ */
101
+ const MAX_CONFIG_LIST_CALLS = 10;
102
+
103
+ /** Opaque url-safe base64 of the JSON position (as in `./pagination.ts`). */
104
+ function encodeConfigCursor(position: ConfigCursor): string {
105
+ return Buffer.from(JSON.stringify(position), 'utf8').toString('base64url');
106
+ }
107
+
108
+ /** Returns `null` on any decode failure — caller responds with 400 bad-input. */
109
+ function decodeConfigCursor(raw: string): ConfigCursor | null {
110
+ try {
111
+ const parsed = JSON.parse(Buffer.from(raw, 'base64url').toString('utf8')) as unknown;
112
+ if (parsed === null || typeof parsed !== 'object') return null;
113
+ const { source, cursor } = parsed as { source?: unknown; cursor?: unknown };
114
+ if (source !== 'env' && source !== 'secret') return null;
115
+ if (cursor !== undefined && (typeof cursor !== 'string' || cursor.length === 0)) return null;
116
+ return cursor === undefined ? { source } : { source, cursor };
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ const DEFAULT_ENV_NAME: EnvName = ((): EnvName => {
123
+ const raw = 'default';
124
+ const validated = makeEnvName(raw);
125
+ // Defensive: the constant grammar accepts 'default'; the null branch
126
+ // is unreachable, but the cast is unavoidable without factory
127
+ // widening.
128
+ return validated ?? (raw as EnvName);
129
+ })();
130
+
131
+ function resolveTenantConfigEnvName(): EnvName {
132
+ const raw = process.env.KINDGI_ENV_NAME;
133
+ if (raw === undefined || raw.length === 0) return DEFAULT_ENV_NAME;
134
+ const validated = makeEnvName(raw);
135
+ return validated ?? DEFAULT_ENV_NAME;
136
+ }
137
+
138
+ export function tenantRouter(options: TenantRouterOptions): Hono<AppEnv> {
139
+ const { tenantHierarchyBinding, envBinding, secretsBinding, authorizer } = options;
140
+ const r = new Hono<AppEnv>();
141
+
142
+ // Authorization — gate every /v1/tenant route with `read` on the
143
+ // caller's tenant. Anyone with tenant admin/member cascades through
144
+ // via can_read. Non-members (rare — usually implies a mis-issued
145
+ // token) get 403 rather than the tenant metadata.
146
+ if (authorizer !== undefined) {
147
+ r.use(
148
+ '*',
149
+ authorizer.authorize('read', (c) => ref('tenant', c.get('tenantId') as unknown as string)),
150
+ );
151
+ }
152
+
153
+ // ---------- GET / ----------
154
+ r.get('/', async (c) => {
155
+ const requestId = c.get('requestId');
156
+ const tenantId = c.get('tenantId') as TenantId;
157
+
158
+ const row = await tenantHierarchyBinding.getTenant(tenantId);
159
+ if (row === null) {
160
+ c.status(statusFor('tenant-not-found') as never);
161
+ return c.json(
162
+ toWireError(
163
+ {
164
+ code: 'tenant-not-found',
165
+ message: `No tenant with id "${tenantId as unknown as string}"`,
166
+ tenantId: tenantId as unknown as string,
167
+ },
168
+ requestId,
169
+ ),
170
+ );
171
+ }
172
+ return c.json({
173
+ id: row.id,
174
+ name: row.name,
175
+ slug: row.slug,
176
+ createdAt: row.createdAt,
177
+ updatedAt: row.updatedAt,
178
+ });
179
+ });
180
+
181
+ if (envBinding === undefined && secretsBinding === undefined) {
182
+ return r;
183
+ }
184
+
185
+ // ---------- GET /config ----------
186
+ r.get('/config', async (c) => {
187
+ const requestId = c.get('requestId');
188
+ const tenantId = c.get('tenantId') as TenantId;
189
+ const limit = clampLimit(c.req.query('limit'));
190
+
191
+ const kindRaw = c.req.query('kind');
192
+ let kindFilter: CompatConfigKind | undefined;
193
+ if (kindRaw !== undefined && kindRaw.length > 0) {
194
+ if (!isCompatConfigKind(kindRaw)) {
195
+ c.status(statusFor('bad-input') as never);
196
+ return c.json(
197
+ toWireError(
198
+ { code: 'bad-input', message: '`kind` must be one of: env, config, secret' },
199
+ requestId,
200
+ ),
201
+ );
202
+ }
203
+ kindFilter = kindRaw;
204
+ }
205
+ const keyPrefix = c.req.query('keyPrefix');
206
+ const cursorRaw = c.req.query('cursor');
207
+ const envName = resolveTenantConfigEnvName();
208
+ const scope: Scope = { kind: 'tenant', tenantId };
209
+
210
+ // Paging across two bindings with opaque cursors: the list is the
211
+ // env entries (in the env binding's order) followed by the secret
212
+ // entries (in the secrets binding's order). `env` and `config` both
213
+ // draw from `envBinding`; `secret` from `secretsBinding`. The wire
214
+ // cursor records which binding the next page starts in and that
215
+ // binding's own cursor. Each binding page is requested with the
216
+ // slots still free and taken whole, so a page never exceeds `limit`
217
+ // and the binding's `nextCursor` is always an exact resume point.
218
+ const wantsEnv = kindFilter === undefined || kindFilter === 'env' || kindFilter === 'config';
219
+ const wantsSecret = kindFilter === undefined || kindFilter === 'secret';
220
+ const sources: readonly ConfigSource[] = [
221
+ ...(wantsEnv && envBinding !== undefined ? (['env'] as const) : []),
222
+ ...(wantsSecret && secretsBinding !== undefined ? (['secret'] as const) : []),
223
+ ];
224
+
225
+ let position: ConfigCursor | null = sources[0] !== undefined ? { source: sources[0] } : null;
226
+ if (cursorRaw !== undefined && cursorRaw.length > 0) {
227
+ const decoded = decodeConfigCursor(cursorRaw);
228
+ if (decoded === null || !sources.includes(decoded.source)) {
229
+ c.status(statusFor('bad-input') as never);
230
+ return c.json(
231
+ toWireError({ code: 'bad-input', message: '`cursor` is malformed' }, requestId),
232
+ );
233
+ }
234
+ position = decoded;
235
+ }
236
+
237
+ const listFrom = async (
238
+ at: ConfigCursor,
239
+ pageLimit: number,
240
+ ): Promise<{
241
+ readonly entries: readonly CompatConfigEntry[];
242
+ readonly nextCursor?: Cursor;
243
+ }> => {
244
+ const input = {
245
+ scope,
246
+ envName,
247
+ limit: pageLimit,
248
+ ...(keyPrefix !== undefined && keyPrefix.length > 0 && { namePrefix: keyPrefix }),
249
+ ...(at.cursor !== undefined && { cursor: at.cursor as Cursor }),
250
+ };
251
+ if (at.source === 'env') {
252
+ const page = await (envBinding as EnvBinding).list(input);
253
+ return {
254
+ entries: page.data.map((rec) => envRecordToCompat(rec, tenantId)),
255
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor }),
256
+ };
257
+ }
258
+ const page = await (secretsBinding as SecretBinding).list(input);
259
+ return {
260
+ entries: page.data.map((rec) => secretRecordToCompat(rec, tenantId)),
261
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor }),
262
+ };
263
+ };
264
+ const nextSource = (source: ConfigSource): ConfigCursor | null => {
265
+ const following = sources[sources.indexOf(source) + 1];
266
+ return following !== undefined ? { source: following } : null;
267
+ };
268
+
269
+ const entries: CompatConfigEntry[] = [];
270
+ let calls = 0;
271
+ while (position !== null && entries.length < limit && calls < MAX_CONFIG_LIST_CALLS) {
272
+ calls += 1;
273
+ const page = await listFrom(position, limit - entries.length);
274
+ entries.push(...page.entries);
275
+ position =
276
+ page.nextCursor !== undefined
277
+ ? { source: position.source, cursor: page.nextCursor }
278
+ : nextSource(position.source);
279
+ }
280
+ // The page filled up exactly where a binding not yet read begins:
281
+ // look ahead one entry so `hasMore` doesn't promise an empty page.
282
+ while (position !== null && position.cursor === undefined && calls < MAX_CONFIG_LIST_CALLS) {
283
+ calls += 1;
284
+ const probe = await listFrom(position, 1);
285
+ if (probe.entries.length > 0 || probe.nextCursor !== undefined) break;
286
+ position = nextSource(position.source);
287
+ }
288
+
289
+ return c.json({
290
+ data: entries,
291
+ hasMore: position !== null,
292
+ ...(position !== null && { nextCursor: encodeConfigCursor(position) }),
293
+ });
294
+ });
295
+
296
+ // ---------- PATCH /config ----------
297
+ r.patch('/config', async (c) => {
298
+ const requestId = c.get('requestId');
299
+ const tenantId = c.get('tenantId') as TenantId;
300
+
301
+ let body: unknown;
302
+ try {
303
+ body = await c.req.json();
304
+ } catch {
305
+ c.status(statusFor('bad-input') as never);
306
+ return c.json(
307
+ toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
308
+ );
309
+ }
310
+ if (body === null || typeof body !== 'object') {
311
+ c.status(statusFor('bad-input') as never);
312
+ return c.json(
313
+ toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
314
+ );
315
+ }
316
+ const b = body as Record<string, unknown>;
317
+ if (!isCompatConfigKind(b.kind)) {
318
+ c.status(statusFor('bad-input') as never);
319
+ return c.json(
320
+ toWireError(
321
+ { code: 'bad-input', message: '`kind` must be one of: env, config, secret' },
322
+ requestId,
323
+ ),
324
+ );
325
+ }
326
+ if (typeof b.key !== 'string' || b.key.length === 0) {
327
+ c.status(statusFor('bad-input') as never);
328
+ return c.json(
329
+ toWireError(
330
+ { code: 'bad-input', message: '`key` is required and must be a non-empty string' },
331
+ requestId,
332
+ ),
333
+ );
334
+ }
335
+ if (typeof b.value !== 'string') {
336
+ c.status(statusFor('bad-input') as never);
337
+ return c.json(
338
+ toWireError(
339
+ { code: 'bad-input', message: '`value` is required and must be a string' },
340
+ requestId,
341
+ ),
342
+ );
343
+ }
344
+ if (b.sensitive !== undefined && typeof b.sensitive !== 'boolean') {
345
+ c.status(statusFor('bad-input') as never);
346
+ return c.json(
347
+ toWireError(
348
+ { code: 'bad-input', message: '`sensitive` must be a boolean when present' },
349
+ requestId,
350
+ ),
351
+ );
352
+ }
353
+ if (b.ifRevision !== undefined && typeof b.ifRevision !== 'number') {
354
+ c.status(statusFor('bad-input') as never);
355
+ return c.json(
356
+ toWireError(
357
+ { code: 'bad-input', message: '`ifRevision` must be a number when present' },
358
+ requestId,
359
+ ),
360
+ );
361
+ }
362
+
363
+ const key = b.key;
364
+ const value = b.value;
365
+ const kind = b.kind;
366
+ const explicitSensitive = b.sensitive as boolean | undefined;
367
+ const ifRevision = b.ifRevision as number | undefined;
368
+ const envName = resolveTenantConfigEnvName();
369
+ const scope: Scope = { kind: 'tenant', tenantId };
370
+
371
+ // `kind` collapse: `env` and `config` both name the env binding; a
372
+ // caller flag of `sensitive: true` promotes the write to the
373
+ // secrets binding regardless of `kind`. `kind: 'secret'` always
374
+ // routes to secrets.
375
+ const wantsSecrets = kind === 'secret' || explicitSensitive === true;
376
+
377
+ if (wantsSecrets) {
378
+ if (secretsBinding === undefined) {
379
+ c.status(statusFor('bad-input') as never);
380
+ return c.json(
381
+ toWireError(
382
+ {
383
+ code: 'bad-input',
384
+ message:
385
+ 'A secret write was attempted but no `secretsBinding` is wired on this deployment.',
386
+ },
387
+ requestId,
388
+ ),
389
+ );
390
+ }
391
+ const currentRecord = await secretsBinding.get({ scope, envName, name: key });
392
+ const writeMode = currentRecord === null ? 'create-new' : 'add-version';
393
+ const outcome = await secretsBinding.set({
394
+ scope,
395
+ envName,
396
+ name: key,
397
+ value,
398
+ writeMode,
399
+ ...(ifRevision !== undefined && { ifVersion: ifRevision }),
400
+ enqueueTuples: (secretRowId) =>
401
+ tuplesForCreate({ kind: 'secret', id: secretRowId, tenantId, scope }),
402
+ });
403
+ if (outcome.kind === 'ok') {
404
+ return c.json({
405
+ entry: {
406
+ tenantId: tenantId as unknown as string,
407
+ kind: 'secret',
408
+ key,
409
+ value: '[redacted]',
410
+ sensitive: true,
411
+ revision: outcome.versionId,
412
+ updatedAt: outcome.record.updatedAt,
413
+ },
414
+ });
415
+ }
416
+ if (outcome.kind === 'version-conflict') {
417
+ c.status(statusFor('tenant-config-revision-conflict') as never);
418
+ return c.json(
419
+ toWireError(
420
+ {
421
+ code: 'tenant-config-revision-conflict',
422
+ message: `Stored revision is ${outcome.currentVersion}; retry with the current value.`,
423
+ currentRevision: outcome.currentVersion,
424
+ },
425
+ requestId,
426
+ ),
427
+ );
428
+ }
429
+ if (outcome.kind === 'already-exists') {
430
+ return c.json({
431
+ entry: {
432
+ tenantId: tenantId as unknown as string,
433
+ kind: 'secret',
434
+ key,
435
+ value: '[redacted]',
436
+ sensitive: true,
437
+ revision: outcome.record.currentVersion,
438
+ updatedAt: outcome.record.updatedAt,
439
+ },
440
+ });
441
+ }
442
+ c.status(500);
443
+ return c.json(toWireError({ code: outcome.code, message: outcome.message }, requestId));
444
+ }
445
+
446
+ if (envBinding === undefined) {
447
+ c.status(statusFor('bad-input') as never);
448
+ return c.json(
449
+ toWireError(
450
+ {
451
+ code: 'bad-input',
452
+ message: 'An env write was attempted but no `envBinding` is wired on this deployment.',
453
+ },
454
+ requestId,
455
+ ),
456
+ );
457
+ }
458
+ const outcome = await envBinding.set({
459
+ scope,
460
+ envName,
461
+ name: key,
462
+ value,
463
+ ...(ifRevision !== undefined && { ifRevision }),
464
+ enqueueTuples: (envRowId) => tuplesForCreate({ kind: 'env', id: envRowId, tenantId, scope }),
465
+ });
466
+ if (outcome.kind === 'ok') {
467
+ // At this point `kind` is `env` or `config` (secrets branch
468
+ // early-returned above); PATCH echoes the input verbatim so
469
+ // callers see the same slot they wrote.
470
+ return c.json({
471
+ entry: {
472
+ tenantId: tenantId as unknown as string,
473
+ kind,
474
+ key,
475
+ value: outcome.record.value,
476
+ sensitive: false,
477
+ revision: outcome.record.revision,
478
+ updatedAt: outcome.record.updatedAt,
479
+ },
480
+ });
481
+ }
482
+ if (outcome.kind === 'revision-conflict') {
483
+ c.status(statusFor('tenant-config-revision-conflict') as never);
484
+ return c.json(
485
+ toWireError(
486
+ {
487
+ code: 'tenant-config-revision-conflict',
488
+ message: `Stored revision is ${outcome.currentRevision}; retry with the current value.`,
489
+ currentRevision: outcome.currentRevision,
490
+ },
491
+ requestId,
492
+ ),
493
+ );
494
+ }
495
+ c.status(500);
496
+ return c.json(toWireError({ code: outcome.code, message: outcome.message }, requestId));
497
+ });
498
+
499
+ return r;
500
+ }
501
+
502
+ function isCompatConfigKind(x: unknown): x is CompatConfigKind {
503
+ return x === 'env' || x === 'config' || x === 'secret';
504
+ }
505
+
506
+ function envRecordToCompat(rec: EnvRecord, tenantId: TenantId): CompatConfigEntry {
507
+ return {
508
+ tenantId,
509
+ kind: 'env',
510
+ key: rec.name,
511
+ value: rec.value,
512
+ sensitive: false,
513
+ revision: rec.revision,
514
+ updatedAt: rec.updatedAt,
515
+ };
516
+ }
517
+
518
+ function secretRecordToCompat(rec: SecretRecord, tenantId: TenantId): CompatConfigEntry {
519
+ return {
520
+ tenantId,
521
+ kind: 'secret',
522
+ key: rec.name,
523
+ // Admin surface never reveals the value. It is only accessible via
524
+ // `SecretBinding.resolve` (dispatch path, capability-gated).
525
+ value: '[redacted]',
526
+ sensitive: true,
527
+ revision: rec.currentVersion,
528
+ updatedAt: rec.updatedAt,
529
+ };
530
+ }