@kindgi/api 0.0.0-bootstrap.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +396 -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 +264 -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 +13 -0
  104. package/dist/middleware/error-mapper.d.ts.map +1 -0
  105. package/dist/middleware/error-mapper.js +32 -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 +5051 -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 +773 -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 +29659 -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 +1285 -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 +291 -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 +37 -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 +5445 -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 +981 -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,1036 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { createHash } from 'node:crypto';
4
+ import { Hono } from 'hono';
5
+ import { tuplesForCreate } from '@kindgi/authz';
6
+ import { parsePublicKeyPem, verifyEd25519 } from '@kindgi/crypto';
7
+ import { validateGuardrailSpec } from '@kindgi/guardrails';
8
+ import { validateToolManifest } from '@kindgi/tools';
9
+ import { statusFor, toWireError } from '../errors.js';
10
+ import { hasCapability, requireEnvName } from './env.js';
11
+ import { clampLimit } from './pagination.js';
12
+ export function deploymentsRouter(bindings) {
13
+ const r = new Hono();
14
+ // ---------- GET / (list, cursor-paginated) ----------
15
+ r.get('/', async (c) => {
16
+ const requestId = c.get('requestId');
17
+ const tenantId = c.get('tenantId');
18
+ const limit = clampLimit(c.req.query('limit'));
19
+ const cursorRaw = c.req.query('cursor');
20
+ const imageRefPrefixRaw = c.req.query('imageRefPrefix');
21
+ const signerKeyIdRaw = c.req.query('signerKeyId');
22
+ try {
23
+ const page = await bindings.deploymentRegistry.list({
24
+ tenantId,
25
+ limit,
26
+ ...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw }),
27
+ ...(imageRefPrefixRaw !== undefined &&
28
+ imageRefPrefixRaw.length > 0 && {
29
+ imageRefPrefix: imageRefPrefixRaw,
30
+ }),
31
+ ...(signerKeyIdRaw !== undefined &&
32
+ signerKeyIdRaw.length > 0 && {
33
+ signerKeyId: signerKeyIdRaw,
34
+ }),
35
+ });
36
+ return c.json({
37
+ data: page.data.map(serializeDeployment),
38
+ hasMore: page.nextCursor !== undefined,
39
+ ...(page.nextCursor !== undefined && {
40
+ nextCursor: page.nextCursor,
41
+ }),
42
+ });
43
+ }
44
+ catch (cause) {
45
+ c.status(statusFor('internal-server-error'));
46
+ return c.json(toWireError({
47
+ code: 'internal-server-error',
48
+ message: `Deployment list failed: ${errMessage(cause)}`,
49
+ }, requestId));
50
+ }
51
+ });
52
+ // ---------- GET /:deploymentId ----------
53
+ r.get('/:deploymentId', async (c) => {
54
+ const requestId = c.get('requestId');
55
+ const tenantId = c.get('tenantId');
56
+ const deploymentId = c.req.param('deploymentId');
57
+ const record = await bindings.deploymentRegistry.get({ tenantId, deploymentId });
58
+ if (record === null) {
59
+ c.status(statusFor('deployment-not-found'));
60
+ return c.json(toWireError({
61
+ code: 'deployment-not-found',
62
+ message: `No deployment with id "${deploymentId}" under this tenant`,
63
+ deploymentId,
64
+ }, requestId));
65
+ }
66
+ return c.json(serializeDeployment(record));
67
+ });
68
+ // ---------- POST / (register a signed deployment) ----------
69
+ r.post('/', async (c) => {
70
+ const requestId = c.get('requestId');
71
+ const tenantId = c.get('tenantId');
72
+ let body;
73
+ try {
74
+ body = await c.req.json();
75
+ }
76
+ catch {
77
+ c.status(statusFor('bad-input'));
78
+ return c.json(toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId));
79
+ }
80
+ const parsed = parseWireBody(body);
81
+ if (parsed.kind === 'err') {
82
+ c.status(statusFor('bad-input'));
83
+ return c.json(toWireError({
84
+ code: 'bad-input',
85
+ message: parsed.error.message,
86
+ issues: parsed.error.issues,
87
+ }, requestId));
88
+ }
89
+ const wire = parsed.value;
90
+ // Extract image digest from imageRef. Must be `<host>/<repo>@sha256:<hex>`.
91
+ const digestFromRef = extractImageDigest(wire.imageRef);
92
+ if (digestFromRef === null) {
93
+ c.status(statusFor('bad-input'));
94
+ return c.json(toWireError({
95
+ code: 'bad-input',
96
+ message: 'imageRef must be digest-pinned: "<host>/<repo>@sha256:<64-hex>"',
97
+ }, requestId));
98
+ }
99
+ const imageDigest = digestFromRef;
100
+ // ---- Signature verification ----
101
+ const publicKeyBytes = parsePublicKeyPem(wire.signerPublicKey);
102
+ if (publicKeyBytes.kind === 'err') {
103
+ c.status(statusFor('bad-input'));
104
+ return c.json(toWireError({
105
+ code: 'bad-input',
106
+ message: `signerPublicKey PEM invalid: ${publicKeyBytes.error.message}`,
107
+ }, requestId));
108
+ }
109
+ const publicKeyBase64 = Buffer.from(publicKeyBytes.value).toString('base64');
110
+ const trusted = await bindings.signingKeyRegistry.isTrusted({
111
+ tenantId,
112
+ keyId: wire.signerKeyId,
113
+ publicKey: publicKeyBase64,
114
+ });
115
+ if (trusted.kind === 'err') {
116
+ c.status(statusFor('internal-server-error'));
117
+ return c.json(toWireError({
118
+ code: 'internal-server-error',
119
+ message: `Trust check failed: ${trusted.error.message}`,
120
+ }, requestId));
121
+ }
122
+ if (!trusted.value) {
123
+ c.status(statusFor('signer-not-trusted'));
124
+ return c.json(toWireError({
125
+ code: 'signer-not-trusted',
126
+ message: `Signer key "${wire.signerKeyId}" is not on this tenant's trust list`,
127
+ signerKeyId: wire.signerKeyId,
128
+ }, requestId));
129
+ }
130
+ const canonicalEnvelope = canonicalizeEnvelope({
131
+ imageDigest,
132
+ artifactVersion: wire.artifactVersion,
133
+ indexHash: wire.indexHash,
134
+ tenantId: tenantId,
135
+ publishedAt: wire.publishedAt,
136
+ });
137
+ let signatureBytes;
138
+ try {
139
+ signatureBytes = Buffer.from(wire.signature, 'base64');
140
+ }
141
+ catch {
142
+ c.status(statusFor('signature-invalid'));
143
+ return c.json(toWireError({ code: 'signature-invalid', message: 'signature is not valid base64' }, requestId));
144
+ }
145
+ const verification = verifyEd25519(publicKeyBytes.value, canonicalEnvelope, new Uint8Array(signatureBytes));
146
+ if (verification.kind === 'err') {
147
+ c.status(statusFor('signature-invalid'));
148
+ return c.json(toWireError({
149
+ code: 'signature-invalid',
150
+ message: `Signature verification rejected: ${verification.error.message}`,
151
+ }, requestId));
152
+ }
153
+ if (!verification.value) {
154
+ c.status(statusFor('signature-invalid'));
155
+ return c.json(toWireError({
156
+ code: 'signature-invalid',
157
+ message: 'Ed25519 signature does not match canonical envelope { imageDigest, artifactVersion, indexHash, tenantId, publishedAt }',
158
+ }, requestId));
159
+ }
160
+ // ---- Image pullability + index integrity ----
161
+ const head = await bindings.imageRegistry.head({ tenantId, imageRef: wire.imageRef });
162
+ if (head.kind === 'err') {
163
+ c.status(statusFor('image-unverifiable'));
164
+ return c.json(toWireError({
165
+ code: 'image-unverifiable',
166
+ message: `Image head probe failed: ${head.error.message}`,
167
+ imageRef: wire.imageRef,
168
+ cause: head.error.code,
169
+ }, requestId));
170
+ }
171
+ if (head.value.digest !== imageDigest) {
172
+ c.status(statusFor('image-unverifiable'));
173
+ return c.json(toWireError({
174
+ code: 'image-unverifiable',
175
+ message: `Registry digest ${head.value.digest} does not match imageRef digest ${imageDigest}`,
176
+ imageRef: wire.imageRef,
177
+ }, requestId));
178
+ }
179
+ const indexFile = await bindings.imageRegistry.extractFile({
180
+ tenantId,
181
+ imageRef: wire.imageRef,
182
+ path: '/app/index.json',
183
+ });
184
+ if (indexFile.kind === 'err') {
185
+ c.status(statusFor('image-unverifiable'));
186
+ return c.json(toWireError({
187
+ code: 'image-unverifiable',
188
+ message: `Extract /app/index.json failed: ${indexFile.error.message}`,
189
+ imageRef: wire.imageRef,
190
+ cause: indexFile.error.code,
191
+ }, requestId));
192
+ }
193
+ const normalisedIndexHash = normaliseSha256Hex(indexFile.value.sha256);
194
+ const normalisedWireIndexHash = normaliseSha256Hex(wire.indexHash);
195
+ if (normalisedIndexHash !== normalisedWireIndexHash) {
196
+ c.status(statusFor('image-unverifiable'));
197
+ return c.json(toWireError({
198
+ code: 'image-unverifiable',
199
+ message: `Image /app/index.json sha256 (${normalisedIndexHash}) does not match signed indexHash (${normalisedWireIndexHash})`,
200
+ imageRef: wire.imageRef,
201
+ }, requestId));
202
+ }
203
+ // What registers is the image's own index, the bytes the signature
204
+ // covers (through indexHash), never a copy from the request.
205
+ const imageIndex = parseImageIndex(indexFile.value.bytes);
206
+ if (imageIndex === undefined) {
207
+ c.status(statusFor('image-unverifiable'));
208
+ return c.json(toWireError({
209
+ code: 'image-unverifiable',
210
+ message: 'Image /app/index.json is not a JSON object',
211
+ imageRef: wire.imageRef,
212
+ }, requestId));
213
+ }
214
+ if (imageIndex.artifactVersion !== wire.artifactVersion) {
215
+ c.status(statusFor('image-unverifiable'));
216
+ return c.json(toWireError({
217
+ code: 'image-unverifiable',
218
+ message: `Image /app/index.json is artifact ${JSON.stringify(imageIndex.artifactVersion)}, not the signed ${wire.artifactVersion}`,
219
+ imageRef: wire.imageRef,
220
+ }, requestId));
221
+ }
222
+ // ---- Manifest validation ----
223
+ const validation = validatePrimitives(imageIndex, {
224
+ imageRef: wire.imageRef,
225
+ artifactVersion: wire.artifactVersion,
226
+ });
227
+ if (validation.kind === 'err') {
228
+ c.status(statusFor('deployment-validation-failed'));
229
+ return c.json(toWireError({
230
+ code: 'deployment-validation-failed',
231
+ message: `Deployment manifest validation failed (${validation.error.details.length} issue${validation.error.details.length === 1 ? '' : 's'})`,
232
+ issues: validation.error.details,
233
+ }, requestId));
234
+ }
235
+ const validated = validation.value;
236
+ // ---- Registry upserts (with rollback tracking) ----
237
+ //
238
+ // Agent-registry, flow-registry, tool-registry, and
239
+ // guardrail-registry writes are all project-scoped. All four loops resolve
240
+ // the tenant's Default project via `projectBinding.getDefault(
241
+ // tenantId)` once per request and thread the resolved id into
242
+ // `AgentRegistryBinding.publish(...)` /
243
+ // `FlowRegistryBinding.publish(...)` /
244
+ // `ToolRegistryBinding.register(...)` /
245
+ // `GuardrailRegistryBinding.register(...)`.
246
+ //
247
+ // Fail-fast: if a deployment brings any of those primitives but
248
+ // no `projectBinding` was wired, we surface `500 internal-server-
249
+ // error` with an operator-actionable message BEFORE any registry
250
+ // writes so rollback stays empty.
251
+ const needsProjectBinding = validated.agents.length > 0 ||
252
+ validated.flows.length > 0 ||
253
+ validated.tools.length > 0 ||
254
+ validated.guardrails.length > 0;
255
+ if (needsProjectBinding && bindings.projectBinding === undefined) {
256
+ c.status(statusFor('internal-server-error'));
257
+ return c.json(toWireError({
258
+ code: 'internal-server-error',
259
+ message: 'agent/flow/tool/guardrail publish requires projectBinding; deployment blocked. Wire projectBinding into DeploymentsRouterBindings at app-creation time.',
260
+ }, requestId));
261
+ }
262
+ let defaultProjectId;
263
+ if (needsProjectBinding && bindings.projectBinding !== undefined) {
264
+ const defaultProject = await bindings.projectBinding.getDefault(tenantId);
265
+ if (defaultProject === undefined) {
266
+ c.status(statusFor('internal-server-error'));
267
+ return c.json(toWireError({
268
+ code: 'internal-server-error',
269
+ message: 'no Default project exists for this tenant; deployment blocked. Every tenant should auto-seed a Default project at creation.',
270
+ }, requestId));
271
+ }
272
+ defaultProjectId = defaultProject.id;
273
+ }
274
+ const rolled = [];
275
+ try {
276
+ if (bindings.toolRegistry !== undefined && defaultProjectId !== undefined) {
277
+ for (const tool of validated.tools) {
278
+ const projectIdForTool = defaultProjectId;
279
+ const outcome = await bindings.toolRegistry.publish({
280
+ tenantId,
281
+ projectId: projectIdForTool,
282
+ tool,
283
+ enqueueTuples: (toolId) => tuplesForCreate({
284
+ kind: 'tool',
285
+ id: toolId,
286
+ tenantId,
287
+ projectId: projectIdForTool,
288
+ }),
289
+ });
290
+ if (outcome.kind === 'ok') {
291
+ const toolId = outcome.toolId;
292
+ const version = outcome.version;
293
+ rolled.push(async () => {
294
+ await bindings.toolRegistry?.unregister({ tenantId, toolId, version });
295
+ });
296
+ }
297
+ }
298
+ }
299
+ if (bindings.guardrailRegistry !== undefined && defaultProjectId !== undefined) {
300
+ for (const guardrail of validated.guardrails) {
301
+ const projectIdForGuardrail = defaultProjectId;
302
+ const outcome = await bindings.guardrailRegistry.register({
303
+ tenantId,
304
+ projectId: projectIdForGuardrail,
305
+ guardrail,
306
+ enqueueTuples: (guardrailId) => tuplesForCreate({
307
+ kind: 'guardrail',
308
+ id: guardrailId,
309
+ tenantId,
310
+ projectId: projectIdForGuardrail,
311
+ }),
312
+ });
313
+ if (outcome.kind === 'ok') {
314
+ const guardrailId = outcome.guardrailId;
315
+ rolled.push(async () => {
316
+ await bindings.guardrailRegistry?.unregister({ tenantId, guardrailId });
317
+ });
318
+ }
319
+ }
320
+ }
321
+ if (bindings.agentRegistry !== undefined && defaultProjectId !== undefined) {
322
+ for (const agent of validated.agents) {
323
+ const projectIdForAgent = defaultProjectId;
324
+ const outcome = await bindings.agentRegistry.publish({
325
+ tenantId,
326
+ projectId: projectIdForAgent,
327
+ agent,
328
+ // Signed deploys have no per-request principal — pass parent-
329
+ // only tuples (no owner grant). Tenant admins keep access via
330
+ // `admin from parent` cascade.
331
+ enqueueTuples: (agentId) => tuplesForCreate({
332
+ kind: 'agent',
333
+ id: agentId,
334
+ tenantId,
335
+ projectId: projectIdForAgent,
336
+ }),
337
+ });
338
+ if (outcome.kind === 'ok') {
339
+ const agentId = outcome.agentId;
340
+ const version = outcome.version;
341
+ rolled.push(async () => {
342
+ await bindings.agentRegistry?.unregister({ tenantId, agentId, version });
343
+ });
344
+ }
345
+ }
346
+ }
347
+ if (bindings.flowRegistry !== undefined && defaultProjectId !== undefined) {
348
+ for (const flow of validated.flows) {
349
+ const projectIdForGraph = defaultProjectId;
350
+ const outcome = await bindings.flowRegistry.publish({
351
+ tenantId,
352
+ projectId: projectIdForGraph,
353
+ flow,
354
+ enqueueTuples: (flowId) => tuplesForCreate({
355
+ kind: 'flow',
356
+ id: flowId,
357
+ tenantId,
358
+ projectId: projectIdForGraph,
359
+ }),
360
+ });
361
+ if (outcome.kind === 'ok') {
362
+ const flowId = outcome.flowId;
363
+ const version = outcome.version;
364
+ rolled.push(async () => {
365
+ await bindings.flowRegistry?.unregister({ tenantId, flowId, version });
366
+ });
367
+ }
368
+ }
369
+ }
370
+ }
371
+ catch (cause) {
372
+ await rollback(rolled);
373
+ c.status(statusFor('internal-server-error'));
374
+ return c.json(toWireError({
375
+ code: 'internal-server-error',
376
+ message: `Registry upsert failed: ${errMessage(cause)}`,
377
+ }, requestId));
378
+ }
379
+ // ---- Deployment record ----
380
+ const primitives = {
381
+ tools: validated.tools.length,
382
+ guardrails: validated.guardrails.length,
383
+ agents: validated.agents.length,
384
+ flows: validated.flows.length,
385
+ };
386
+ let outcome;
387
+ try {
388
+ outcome = await bindings.deploymentRegistry.register({
389
+ tenantId,
390
+ imageRef: wire.imageRef,
391
+ imageDigest,
392
+ artifactVersion: wire.artifactVersion,
393
+ indexHash: normalisedWireIndexHash,
394
+ signerKeyId: wire.signerKeyId,
395
+ signerPublicKey: publicKeyBase64,
396
+ signature: wire.signature,
397
+ publishedAt: wire.publishedAt,
398
+ primitives,
399
+ contents: {
400
+ tools: validated.tools.map((t) => ({
401
+ id: t.id,
402
+ version: t.version,
403
+ })),
404
+ guardrails: validated.guardrails.map((g) => ({ id: g.id })),
405
+ agents: validated.agents.map((a) => ({
406
+ id: a.id,
407
+ version: a.version,
408
+ })),
409
+ flows: validated.flows.map((f) => ({
410
+ id: f.id,
411
+ version: f.version,
412
+ })),
413
+ },
414
+ });
415
+ }
416
+ catch (cause) {
417
+ await rollback(rolled);
418
+ c.status(statusFor('internal-server-error'));
419
+ return c.json(toWireError({
420
+ code: 'internal-server-error',
421
+ message: `Deployment record failed: ${errMessage(cause)}`,
422
+ }, requestId));
423
+ }
424
+ if (outcome.kind === 'error') {
425
+ await rollback(rolled);
426
+ c.status(statusFor('internal-server-error'));
427
+ return c.json(toWireError({
428
+ code: 'internal-server-error',
429
+ message: `Deployment record failed: ${outcome.message}`,
430
+ cause: outcome.code,
431
+ }, requestId));
432
+ }
433
+ if (outcome.kind === 'already-registered') {
434
+ // Digest-based idempotency: same digest already recorded. Roll back
435
+ // any freshly-inserted primitives (the primitive itself is fine —
436
+ // the previous deploy landed it — but re-inserting is idempotent
437
+ // at the primitive layer too, so `ok` outcomes only happen when
438
+ // the primitive was DIFFERENT this run, which is an inconsistent
439
+ // wire body).
440
+ await rollback(rolled);
441
+ c.status(200);
442
+ return c.json(serializeDeployment(outcome.deployment));
443
+ }
444
+ await notifyWrites(tenantId, validated, bindings);
445
+ c.status(201);
446
+ return c.json(serializeDeployment(outcome.deployment));
447
+ });
448
+ // ---------- POST /:deploymentId/secrets ----------
449
+ //
450
+ // Deployment-scoped bulk secret sync.
451
+ //
452
+ // Body shape:
453
+ // {
454
+ // envName: EnvName;
455
+ // secrets: Array<{ name, ref } | { name, value }>;
456
+ // }
457
+ //
458
+ // - `{ name, ref }` entries → validated via `SecretBinding.get`. No
459
+ // bytes cross the wire. Missing → 404 `secret-not-found` (matches
460
+ // the framework-wide `secret-not-found` → 404 mapping in
461
+ // `errors.ts`). The `ref` value is echoed
462
+ // verbatim in the response (opaque reference the deployment
463
+ // runtime resolves at dispatch).
464
+ // - `{ name, value }` entries → written via `SecretBinding.set` with
465
+ // `writeMode: 'add-version'` + `tags.deployment = deploymentId`. The
466
+ // response returns the just-minted reference (framework-generated
467
+ // `secret:` scheme so the developer can round-trip).
468
+ //
469
+ // Scope is derived from the target deployment record, NOT accepted from
470
+ // the wire (CRITICAL). The `Deployment` shape carries no `projectId`, so
471
+ // the scope is `{ kind: 'tenant', tenantId }`; `deriveScopeFromDeployment`
472
+ // switches to a project scope if a record does carry one.
473
+ //
474
+ // Capability: `secrets:write` (fail-closed).
475
+ // Idempotency-Key: honoured by the middleware layer.
476
+ r.post('/:deploymentId/secrets', async (c) => {
477
+ const requestId = c.get('requestId');
478
+ const tenantId = c.get('tenantId');
479
+ const deploymentId = c.req.param('deploymentId');
480
+ if (bindings.secretsBinding === undefined) {
481
+ c.status(statusFor('internal-server-error'));
482
+ return c.json(toWireError({
483
+ code: 'internal-server-error',
484
+ message: 'secretsBinding is not wired; POST /v1/deployments/:deploymentId/secrets is unavailable. ' +
485
+ 'Wire secretsBinding into DeploymentsRouterBindings.',
486
+ }, requestId));
487
+ }
488
+ if (!hasCapability(c, 'secrets:write')) {
489
+ c.status(statusFor('permission-denied'));
490
+ return c.json(toWireError({
491
+ code: 'permission-denied',
492
+ message: 'Bearer token is missing the `secrets:write` capability required for deployment secret sync.',
493
+ }, requestId));
494
+ }
495
+ // Resolve the target deployment first — its `(tenantId, projectId?)`
496
+ // is what determines the write scope.
497
+ const deployment = await bindings.deploymentRegistry.get({ tenantId, deploymentId });
498
+ if (deployment === null) {
499
+ c.status(statusFor('deployment-not-found'));
500
+ return c.json(toWireError({
501
+ code: 'deployment-not-found',
502
+ message: `No deployment with id "${deploymentId}" under this tenant`,
503
+ deploymentId,
504
+ }, requestId));
505
+ }
506
+ const scope = deriveScopeFromDeployment(deployment);
507
+ let body;
508
+ try {
509
+ body = await c.req.json();
510
+ }
511
+ catch {
512
+ c.status(statusFor('bad-input'));
513
+ return c.json(toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId));
514
+ }
515
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) {
516
+ c.status(statusFor('bad-input'));
517
+ return c.json(toWireError({ code: 'bad-input', message: 'Request body must be a JSON object' }, requestId));
518
+ }
519
+ const b = body;
520
+ const envNameResult = requireEnvName(typeof b.envName === 'string' ? b.envName : undefined);
521
+ if (envNameResult.kind === 'err') {
522
+ c.status(statusFor(envNameResult.code));
523
+ return c.json(toWireError({ code: envNameResult.code, message: envNameResult.message }, requestId));
524
+ }
525
+ const envName = envNameResult.envName;
526
+ if (!Array.isArray(b.secrets)) {
527
+ c.status(statusFor('bad-input'));
528
+ return c.json(toWireError({
529
+ code: 'bad-input',
530
+ message: '`secrets` must be an array of `{ name, ref }` or `{ name, value }` entries',
531
+ }, requestId));
532
+ }
533
+ // Empty array is legal (a no-op sync). Every real entry must be an
534
+ // object with a non-empty `name` and exactly one of `ref` / `value`.
535
+ const parsed = [];
536
+ for (let i = 0; i < b.secrets.length; i++) {
537
+ const raw = b.secrets[i];
538
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
539
+ c.status(statusFor('bad-input'));
540
+ return c.json(toWireError({
541
+ code: 'bad-input',
542
+ message: `secrets[${i}] must be an object`,
543
+ }, requestId));
544
+ }
545
+ const e = raw;
546
+ if (typeof e.name !== 'string' || e.name.length === 0) {
547
+ c.status(statusFor('bad-input'));
548
+ return c.json(toWireError({
549
+ code: 'bad-input',
550
+ message: `secrets[${i}].name is required and must be a non-empty string`,
551
+ }, requestId));
552
+ }
553
+ const hasRef = typeof e.ref === 'string';
554
+ const hasValue = typeof e.value === 'string';
555
+ if (hasRef === hasValue) {
556
+ c.status(statusFor('bad-input'));
557
+ return c.json(toWireError({
558
+ code: 'bad-input',
559
+ message: `secrets[${i}] must set exactly one of \`ref\` or \`value\``,
560
+ }, requestId));
561
+ }
562
+ if (hasRef) {
563
+ parsed.push({ kind: 'ref', name: e.name, ref: e.ref });
564
+ }
565
+ else {
566
+ parsed.push({ kind: 'value', name: e.name, value: e.value });
567
+ }
568
+ }
569
+ let resolvedCount = 0;
570
+ let addedCount = 0;
571
+ const references = [];
572
+ for (const entry of parsed) {
573
+ if (entry.kind === 'ref') {
574
+ const rec = await bindings.secretsBinding.get({ scope, envName, name: entry.name });
575
+ if (rec === null || rec.revokedAt !== undefined) {
576
+ c.status(statusFor('secret-not-found'));
577
+ return c.json(toWireError({
578
+ code: 'secret-not-found',
579
+ message: `secrets[${entry.name}]: no secret at (${scope.kind}, ${envName}, ${entry.name}) — write with { name, value } first or fix the ref.`,
580
+ name: entry.name,
581
+ }, requestId));
582
+ }
583
+ resolvedCount += 1;
584
+ references.push({ name: entry.name, ref: entry.ref, version: rec.currentVersion });
585
+ }
586
+ else {
587
+ const outcome = await bindings.secretsBinding.set({
588
+ scope,
589
+ envName,
590
+ name: entry.name,
591
+ value: entry.value,
592
+ writeMode: 'add-version',
593
+ tags: { deployment: deploymentId },
594
+ // Only fires on create-new; here we're adding a version → no-op.
595
+ enqueueTuples: () => [],
596
+ });
597
+ if (outcome.kind !== 'ok') {
598
+ // add-version should never trigger `already-exists`; treat any
599
+ // non-ok as a hard failure (binding-side conflict, encryption
600
+ // failure, etc.). Fail the whole request (atomic model).
601
+ const code = outcome.kind === 'version-conflict'
602
+ ? 'secret-write-conflict'
603
+ : outcome.kind === 'already-exists'
604
+ ? 'secret-write-conflict'
605
+ : outcome.code;
606
+ const message = outcome.kind === 'version-conflict'
607
+ ? `secrets[${entry.name}]: version conflict (stored=${outcome.currentVersion}); retry.`
608
+ : outcome.kind === 'already-exists'
609
+ ? `secrets[${entry.name}]: already-exists surface on add-version (adapter bug); investigate.`
610
+ : `secrets[${entry.name}]: ${outcome.message}`;
611
+ c.status(statusFor(code));
612
+ return c.json(toWireError({ code, message }, requestId));
613
+ }
614
+ addedCount += 1;
615
+ // Reference format: `secret:<envName>/<name>#<version>`. Opaque
616
+ // to the wire — the deployment runtime resolves via SecretBinding
617
+ // at dispatch time.
618
+ const ref = `secret:${envName}/${entry.name}#${outcome.versionId}`;
619
+ references.push({ name: entry.name, ref, version: outcome.versionId });
620
+ }
621
+ }
622
+ return c.json({
623
+ resolved: resolvedCount,
624
+ added: addedCount,
625
+ references,
626
+ });
627
+ });
628
+ return r;
629
+ }
630
+ // ------------------------------------------------------------
631
+ // Scope derivation for deployment secret sync
632
+ // ------------------------------------------------------------
633
+ /**
634
+ * Derive the write scope for a deployment secret-sync request from
635
+ * the deployment record itself. Never accepts a caller-supplied scope
636
+ * override on the wire (CRITICAL — scope MUST be inferred
637
+ * server-side to prevent tenant/project confusion attacks).
638
+ *
639
+ * The `Deployment` type carries no `projectId`, so this normally returns
640
+ * `{ kind: 'tenant', tenantId }`. If a binding's record does carry a
641
+ * non-empty `projectId`, the helper returns a project scope instead. The
642
+ * field is read dynamically because the type does not declare it.
643
+ */
644
+ function deriveScopeFromDeployment(d) {
645
+ const maybeProjectId = d.projectId;
646
+ if (typeof maybeProjectId === 'string' && maybeProjectId.length > 0) {
647
+ return {
648
+ kind: 'project',
649
+ tenantId: d.tenantId,
650
+ projectId: maybeProjectId,
651
+ };
652
+ }
653
+ return { kind: 'tenant', tenantId: d.tenantId };
654
+ }
655
+ const ARTIFACT_VERSION_RE = /^\d{8}\.\d+$/;
656
+ const SHA256_HEX_RE = /^[0-9a-f]{64}$/i;
657
+ const SHA256_PREFIX_RE = /^sha256:[0-9a-f]{64}$/i;
658
+ function parseWireBody(body) {
659
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) {
660
+ return {
661
+ kind: 'err',
662
+ error: {
663
+ message: 'Request body must be a JSON object',
664
+ issues: [{ path: '', message: 'must be an object' }],
665
+ },
666
+ };
667
+ }
668
+ const b = body;
669
+ const issues = [];
670
+ const requireString = (field) => {
671
+ const raw = b[field];
672
+ if (typeof raw !== 'string' || raw.length === 0) {
673
+ issues.push({ path: field, message: `${field} must be a non-empty string` });
674
+ return undefined;
675
+ }
676
+ return raw;
677
+ };
678
+ const imageRef = requireString('imageRef');
679
+ const artifactVersion = requireString('artifactVersion');
680
+ const indexHash = requireString('indexHash');
681
+ const signerKeyId = requireString('signerKeyId');
682
+ const signerPublicKey = requireString('signerPublicKey');
683
+ const signature = requireString('signature');
684
+ const publishedAt = requireString('publishedAt');
685
+ if (artifactVersion !== undefined && !ARTIFACT_VERSION_RE.test(artifactVersion)) {
686
+ issues.push({
687
+ path: 'artifactVersion',
688
+ message: 'artifactVersion must match YYYYMMDD.N',
689
+ });
690
+ }
691
+ if (indexHash !== undefined &&
692
+ !SHA256_PREFIX_RE.test(indexHash) &&
693
+ !SHA256_HEX_RE.test(indexHash)) {
694
+ issues.push({
695
+ path: 'indexHash',
696
+ message: 'indexHash must be sha256:<64-hex> (or bare 64-hex)',
697
+ });
698
+ }
699
+ if (publishedAt !== undefined && Number.isNaN(Date.parse(publishedAt))) {
700
+ issues.push({ path: 'publishedAt', message: 'publishedAt must be ISO-8601' });
701
+ }
702
+ if (issues.length > 0) {
703
+ return {
704
+ kind: 'err',
705
+ error: { message: issues[0]?.message ?? 'body validation failed', issues },
706
+ };
707
+ }
708
+ return {
709
+ kind: 'ok',
710
+ value: {
711
+ imageRef: imageRef,
712
+ artifactVersion: artifactVersion,
713
+ indexHash: indexHash,
714
+ signerKeyId: signerKeyId,
715
+ signerPublicKey: signerPublicKey,
716
+ signature: signature,
717
+ publishedAt: publishedAt,
718
+ },
719
+ };
720
+ }
721
+ /** The image's `/app/index.json` as an object, or `undefined` when it isn't one. */
722
+ function parseImageIndex(bytes) {
723
+ let parsed;
724
+ try {
725
+ parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
726
+ }
727
+ catch {
728
+ return undefined;
729
+ }
730
+ return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
731
+ ? parsed
732
+ : undefined;
733
+ }
734
+ function extractImageDigest(imageRef) {
735
+ const at = imageRef.lastIndexOf('@');
736
+ if (at < 0)
737
+ return null;
738
+ const digest = imageRef.slice(at + 1);
739
+ if (!SHA256_PREFIX_RE.test(digest))
740
+ return null;
741
+ return digest.toLowerCase();
742
+ }
743
+ function normaliseSha256Hex(raw) {
744
+ const lower = raw.toLowerCase();
745
+ return lower.startsWith('sha256:') ? lower : `sha256:${lower}`;
746
+ }
747
+ /**
748
+ * Canonical form of the signed envelope: JSON object with sorted keys,
749
+ * no whitespace, UTF-8. Deterministic by construction — the same field
750
+ * values always produce byte-identical output.
751
+ */
752
+ function canonicalizeEnvelope(fields) {
753
+ const ordered = {
754
+ artifactVersion: fields.artifactVersion,
755
+ imageDigest: normaliseSha256Hex(fields.imageDigest),
756
+ indexHash: normaliseSha256Hex(fields.indexHash),
757
+ publishedAt: fields.publishedAt,
758
+ tenantId: fields.tenantId,
759
+ };
760
+ const json = JSON.stringify(ordered);
761
+ return new TextEncoder().encode(json);
762
+ }
763
+ /** The pointer to a tool's or guardrail's module inside the deployed image. */
764
+ function ociCodeArtifactRef(image, modulePath) {
765
+ return typeof modulePath === 'string' && modulePath.length > 0
766
+ ? {
767
+ codeArtifactRef: {
768
+ kind: 'oci',
769
+ imageRef: image.imageRef,
770
+ modulePath,
771
+ artifactVersion: image.artifactVersion,
772
+ },
773
+ }
774
+ : {};
775
+ }
776
+ /**
777
+ * Validate the index's primitives as the registries store them. Tools
778
+ * and guardrails keep where their code is (`codeArtifactRef`, an `oci`
779
+ * pointer into the deployed image) in place of the index's module path;
780
+ * a guardrail's `checkId` becomes its `check`, as `kindgi dev`'s disk
781
+ * registry maps it.
782
+ */
783
+ function validatePrimitives(index, image) {
784
+ const details = [];
785
+ const tools = readArray(index.tools);
786
+ const guardrails = readArray(index.guardrails);
787
+ const agents = readArray(index.agents);
788
+ const flows = readArray(index.flows);
789
+ const validatedTools = [];
790
+ tools.forEach((raw, i) => {
791
+ if (raw === null || typeof raw !== 'object') {
792
+ details.push({ primitive: 'tool', index: i, path: '', message: 'must be an object' });
793
+ return;
794
+ }
795
+ const { modulePath, ...manifest } = raw;
796
+ const r = validateToolManifest({ ...manifest, ...ociCodeArtifactRef(image, modulePath) });
797
+ if (r.kind === 'err') {
798
+ const err = r.error;
799
+ const rawId = raw.id;
800
+ const idBase = typeof rawId === 'string' ? { id: rawId } : {};
801
+ if (err.issues && err.issues.length > 0) {
802
+ for (const issue of err.issues) {
803
+ details.push({
804
+ primitive: 'tool',
805
+ index: i,
806
+ ...idBase,
807
+ path: issue.path,
808
+ message: issue.message,
809
+ });
810
+ }
811
+ }
812
+ else {
813
+ details.push({ primitive: 'tool', index: i, ...idBase, path: '', message: err.message });
814
+ }
815
+ return;
816
+ }
817
+ validatedTools.push(r.value);
818
+ });
819
+ const validatedGuardrails = [];
820
+ guardrails.forEach((raw, i) => {
821
+ if (raw === null || typeof raw !== 'object') {
822
+ details.push({ primitive: 'guardrail', index: i, path: '', message: 'must be an object' });
823
+ return;
824
+ }
825
+ const { checkModulePath, checkId, configSchema: _configSchema, ...rest } = raw;
826
+ const r = validateGuardrailSpec({
827
+ ...rest,
828
+ check: checkId ?? rest.check ?? rest.id,
829
+ ...ociCodeArtifactRef(image, checkModulePath),
830
+ });
831
+ if (r.kind === 'err') {
832
+ const err = r.error;
833
+ const rawId = raw.id;
834
+ const idBase = typeof rawId === 'string' ? { id: rawId } : {};
835
+ if (err.issues && err.issues.length > 0) {
836
+ for (const issue of err.issues) {
837
+ details.push({
838
+ primitive: 'guardrail',
839
+ index: i,
840
+ ...idBase,
841
+ path: issue.path,
842
+ message: issue.message,
843
+ });
844
+ }
845
+ }
846
+ else {
847
+ details.push({
848
+ primitive: 'guardrail',
849
+ index: i,
850
+ ...idBase,
851
+ path: '',
852
+ message: err.message,
853
+ });
854
+ }
855
+ return;
856
+ }
857
+ validatedGuardrails.push(r.value);
858
+ });
859
+ const validatedAgents = [];
860
+ agents.forEach((raw, i) => {
861
+ if (raw === null || typeof raw !== 'object') {
862
+ details.push({ primitive: 'agent', index: i, path: '', message: 'must be an object' });
863
+ return;
864
+ }
865
+ const { modulePath: _mp, ...spec } = raw;
866
+ const shapeIssues = validateAgentIndexShape(spec);
867
+ if (shapeIssues.length > 0) {
868
+ const rawId = spec.id;
869
+ const idBase = typeof rawId === 'string' ? { id: rawId } : {};
870
+ for (const issue of shapeIssues) {
871
+ details.push({ primitive: 'agent', index: i, ...idBase, ...issue });
872
+ }
873
+ return;
874
+ }
875
+ validatedAgents.push(spec);
876
+ });
877
+ const validatedGraphs = [];
878
+ flows.forEach((raw, i) => {
879
+ if (raw === null || typeof raw !== 'object') {
880
+ details.push({ primitive: 'flow', index: i, path: '', message: 'must be an object' });
881
+ return;
882
+ }
883
+ const { modulePath: _mp, kernelPayloadVersion: _kpv, ...spec } = raw;
884
+ const shapeIssues = validateFlowIndexShape(spec);
885
+ if (shapeIssues.length > 0) {
886
+ const rawId = spec.id;
887
+ const idBase = typeof rawId === 'string' ? { id: rawId } : {};
888
+ for (const issue of shapeIssues) {
889
+ details.push({ primitive: 'flow', index: i, ...idBase, ...issue });
890
+ }
891
+ return;
892
+ }
893
+ validatedGraphs.push(spec);
894
+ });
895
+ if (details.length > 0) {
896
+ return { kind: 'err', error: { details } };
897
+ }
898
+ return {
899
+ kind: 'ok',
900
+ value: {
901
+ tools: validatedTools,
902
+ guardrails: validatedGuardrails,
903
+ agents: validatedAgents,
904
+ flows: validatedGraphs,
905
+ },
906
+ };
907
+ }
908
+ function readArray(value) {
909
+ return Array.isArray(value) ? value : [];
910
+ }
911
+ const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
912
+ /**
913
+ * Minimal shape check on an `IndexedAgent` after `modulePath` is
914
+ * stripped. Deeper validation (RetrievalIntent shape, budget arithmetic,
915
+ * conversation policy tri-state) is left to the runtime at dispatch —
916
+ * the deploy route only validates that the wire is well-shaped enough to
917
+ * persist. The alternative is running `defineAgent`, but that requires
918
+ * promoting `capabilities`/`tools` to their branded shapes; the pattern
919
+ * across the API package is to keep transport shape checks lightweight
920
+ * and leave semantic checks to the runtime.
921
+ */
922
+ function validateAgentIndexShape(spec) {
923
+ const out = [];
924
+ if (typeof spec.id !== 'string' || spec.id.length === 0) {
925
+ out.push({ path: '/id', message: 'agent.id must be a non-empty string' });
926
+ }
927
+ if (typeof spec.version !== 'string' || !SEMVER_RE.test(spec.version)) {
928
+ out.push({ path: '/version', message: 'agent.version must be semver' });
929
+ }
930
+ if (typeof spec.name !== 'string' || spec.name.length === 0) {
931
+ out.push({ path: '/name', message: 'agent.name must be a non-empty string' });
932
+ }
933
+ if (typeof spec.instructions !== 'string' || spec.instructions.length === 0) {
934
+ out.push({ path: '/instructions', message: 'agent.instructions must be a non-empty string' });
935
+ }
936
+ if (!Array.isArray(spec.capabilities)) {
937
+ out.push({ path: '/capabilities', message: 'agent.capabilities must be an array' });
938
+ }
939
+ if (!Array.isArray(spec.tools)) {
940
+ out.push({ path: '/tools', message: 'agent.tools must be an array of tool ids' });
941
+ }
942
+ return out;
943
+ }
944
+ function validateFlowIndexShape(spec) {
945
+ const out = [];
946
+ if (typeof spec.id !== 'string' || spec.id.length === 0) {
947
+ out.push({ path: '/id', message: 'flow.id must be a non-empty string' });
948
+ }
949
+ if (typeof spec.version !== 'string' || !SEMVER_RE.test(spec.version)) {
950
+ out.push({ path: '/version', message: 'flow.version must be semver' });
951
+ }
952
+ if (!Array.isArray(spec.nodes)) {
953
+ out.push({ path: '/nodes', message: 'flow.nodes must be an array' });
954
+ }
955
+ if (!Array.isArray(spec.edges)) {
956
+ out.push({ path: '/edges', message: 'flow.edges must be an array' });
957
+ }
958
+ return out;
959
+ }
960
+ async function rollback(actions) {
961
+ // Reverse order — last-in, first-out — so registrations are undone in
962
+ // the mirror sequence of their creation.
963
+ for (let i = actions.length - 1; i >= 0; i--) {
964
+ const action = actions[i];
965
+ if (action === undefined)
966
+ continue;
967
+ try {
968
+ await action();
969
+ }
970
+ catch {
971
+ // Swallow: rollback is best-effort. Real production adapters
972
+ // record a rollback-failure event so operators can reconcile.
973
+ }
974
+ }
975
+ }
976
+ function serializeDeployment(d) {
977
+ return {
978
+ deploymentId: d.deploymentId,
979
+ tenantId: d.tenantId,
980
+ imageRef: d.imageRef,
981
+ imageDigest: d.imageDigest,
982
+ artifactVersion: d.artifactVersion,
983
+ indexHash: d.indexHash,
984
+ signerKeyId: d.signerKeyId,
985
+ signerPublicKey: d.signerPublicKey,
986
+ signature: d.signature,
987
+ publishedAt: d.publishedAt,
988
+ activatedAt: d.activatedAt,
989
+ primitives: {
990
+ tools: d.primitives.tools,
991
+ guardrails: d.primitives.guardrails,
992
+ agents: d.primitives.agents,
993
+ flows: d.primitives.flows,
994
+ },
995
+ contents: d.contents,
996
+ };
997
+ }
998
+ /** Tell the catalog caches about what a new deployment registered (advisory). */
999
+ async function notifyWrites(tenantId, validated, bindings) {
1000
+ for (const tool of validated.tools) {
1001
+ try {
1002
+ await bindings.onToolWrite?.({
1003
+ tenantId,
1004
+ toolId: tool.id,
1005
+ version: tool.version,
1006
+ kind: 'publish',
1007
+ });
1008
+ }
1009
+ catch {
1010
+ // Advisory, as on `POST /v1/tools`.
1011
+ }
1012
+ }
1013
+ for (const guardrail of validated.guardrails) {
1014
+ try {
1015
+ await bindings.onGuardrailWrite?.({
1016
+ tenantId,
1017
+ guardrailId: guardrail.id,
1018
+ kind: 'register',
1019
+ });
1020
+ }
1021
+ catch {
1022
+ // Advisory, as on `POST /v1/guardrails`.
1023
+ }
1024
+ }
1025
+ }
1026
+ function errMessage(cause) {
1027
+ return cause instanceof Error ? cause.message : String(cause);
1028
+ }
1029
+ // Formats a sha256 digest in the canonical `sha256:<hex>` shape. Not used
1030
+ // by the router or elsewhere in this package; exported from this module
1031
+ // only.
1032
+ export function sha256HexPrefixed(bytes) {
1033
+ const hex = createHash('sha256').update(bytes).digest('hex');
1034
+ return `sha256:${hex}`;
1035
+ }
1036
+ //# sourceMappingURL=deployments.js.map