@homeflare/alchemy 0.43.0 → 0.45.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 (612) hide show
  1. package/README.md +10 -1
  2. package/dist/caddy/index.js +35 -1
  3. package/dist/caddy/index.js.map +3 -3
  4. package/dist/launchd/index.js +35 -1
  5. package/dist/launchd/index.js.map +3 -3
  6. package/dist/linux/index.js +35 -1
  7. package/dist/linux/index.js.map +3 -3
  8. package/dist/litellm/access-group-form.d.ts +26 -0
  9. package/dist/litellm/access-group-form.d.ts.map +1 -0
  10. package/dist/litellm/access-group-operations.d.ts +37 -0
  11. package/dist/litellm/access-group-operations.d.ts.map +1 -0
  12. package/dist/litellm/access-group-types.d.ts +49 -0
  13. package/dist/litellm/access-group-types.d.ts.map +1 -0
  14. package/dist/litellm/access-group.d.ts +55 -0
  15. package/dist/litellm/access-group.d.ts.map +1 -0
  16. package/dist/litellm/credential-errors.d.ts +131 -0
  17. package/dist/litellm/credential-errors.d.ts.map +1 -0
  18. package/dist/litellm/credential-form.d.ts +79 -0
  19. package/dist/litellm/credential-form.d.ts.map +1 -0
  20. package/dist/litellm/credential-operations.d.ts +84 -0
  21. package/dist/litellm/credential-operations.d.ts.map +1 -0
  22. package/dist/litellm/credential-rewrite.d.ts +6 -0
  23. package/dist/litellm/credential-rewrite.d.ts.map +1 -0
  24. package/dist/litellm/credential-types.d.ts +87 -0
  25. package/dist/litellm/credential-types.d.ts.map +1 -0
  26. package/dist/litellm/credential-values.d.ts +53 -0
  27. package/dist/litellm/credential-values.d.ts.map +1 -0
  28. package/dist/litellm/credential.d.ts +83 -0
  29. package/dist/litellm/credential.d.ts.map +1 -0
  30. package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
  31. package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
  32. package/dist/litellm/fake-credential-litellm.d.ts +54 -0
  33. package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
  34. package/dist/litellm/fake-keys.d.ts +53 -0
  35. package/dist/litellm/fake-keys.d.ts.map +1 -0
  36. package/dist/litellm/fake-litellm.d.ts +4 -1
  37. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  38. package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
  39. package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
  40. package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
  41. package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
  42. package/dist/litellm/fake-model-litellm.d.ts +48 -0
  43. package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
  44. package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
  45. package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
  46. package/dist/litellm/fake-policy-litellm.d.ts +32 -0
  47. package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
  48. package/dist/litellm/fake-registry-base.d.ts +42 -0
  49. package/dist/litellm/fake-registry-base.d.ts.map +1 -0
  50. package/dist/litellm/fake-stack.d.ts +8 -1
  51. package/dist/litellm/fake-stack.d.ts.map +1 -1
  52. package/dist/litellm/fake-team-litellm.d.ts +47 -0
  53. package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
  54. package/dist/litellm/fake-tool-litellm.d.ts +28 -0
  55. package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
  56. package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
  57. package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
  58. package/dist/litellm/index.d.ts +18 -0
  59. package/dist/litellm/index.d.ts.map +1 -1
  60. package/dist/litellm/index.js +3078 -2
  61. package/dist/litellm/index.js.map +65 -4
  62. package/dist/litellm/key-errors.d.ts +169 -0
  63. package/dist/litellm/key-errors.d.ts.map +1 -0
  64. package/dist/litellm/key-form.d.ts +119 -0
  65. package/dist/litellm/key-form.d.ts.map +1 -0
  66. package/dist/litellm/key-harness.d.ts +41 -0
  67. package/dist/litellm/key-harness.d.ts.map +1 -0
  68. package/dist/litellm/key-metadata-errors.d.ts +30 -0
  69. package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
  70. package/dist/litellm/key-metadata.d.ts +22 -0
  71. package/dist/litellm/key-metadata.d.ts.map +1 -0
  72. package/dist/litellm/key-operations.d.ts +63 -0
  73. package/dist/litellm/key-operations.d.ts.map +1 -0
  74. package/dist/litellm/key-secret.d.ts +33 -0
  75. package/dist/litellm/key-secret.d.ts.map +1 -0
  76. package/dist/litellm/key.d.ts +78 -0
  77. package/dist/litellm/key.d.ts.map +1 -0
  78. package/dist/litellm/mcp-server-credential.d.ts +50 -0
  79. package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
  80. package/dist/litellm/mcp-server-errors.d.ts +101 -0
  81. package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
  82. package/dist/litellm/mcp-server-form.d.ts +56 -0
  83. package/dist/litellm/mcp-server-form.d.ts.map +1 -0
  84. package/dist/litellm/mcp-server-locate.d.ts +26 -0
  85. package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
  86. package/dist/litellm/mcp-server-operations.d.ts +63 -0
  87. package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
  88. package/dist/litellm/mcp-server-shadow.d.ts +24 -0
  89. package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
  90. package/dist/litellm/mcp-server-types.d.ts +118 -0
  91. package/dist/litellm/mcp-server-types.d.ts.map +1 -0
  92. package/dist/litellm/mcp-server-url.d.ts +11 -0
  93. package/dist/litellm/mcp-server-url.d.ts.map +1 -0
  94. package/dist/litellm/mcp-server.d.ts +95 -0
  95. package/dist/litellm/mcp-server.d.ts.map +1 -0
  96. package/dist/litellm/model-claim.d.ts +24 -0
  97. package/dist/litellm/model-claim.d.ts.map +1 -0
  98. package/dist/litellm/model-credential.d.ts +12 -0
  99. package/dist/litellm/model-credential.d.ts.map +1 -0
  100. package/dist/litellm/model-errors.d.ts +119 -0
  101. package/dist/litellm/model-errors.d.ts.map +1 -0
  102. package/dist/litellm/model-form.d.ts +78 -0
  103. package/dist/litellm/model-form.d.ts.map +1 -0
  104. package/dist/litellm/model-locate.d.ts +13 -0
  105. package/dist/litellm/model-locate.d.ts.map +1 -0
  106. package/dist/litellm/model-operations.d.ts +59 -0
  107. package/dist/litellm/model-operations.d.ts.map +1 -0
  108. package/dist/litellm/model-types.d.ts +91 -0
  109. package/dist/litellm/model-types.d.ts.map +1 -0
  110. package/dist/litellm/model.d.ts +88 -0
  111. package/dist/litellm/model.d.ts.map +1 -0
  112. package/dist/litellm/policy-attachment-form.d.ts +19 -0
  113. package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
  114. package/dist/litellm/policy-attachment-operations.d.ts +31 -0
  115. package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
  116. package/dist/litellm/policy-attachment-types.d.ts +48 -0
  117. package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
  118. package/dist/litellm/policy-attachment.d.ts +61 -0
  119. package/dist/litellm/policy-attachment.d.ts.map +1 -0
  120. package/dist/litellm/policy-form.d.ts +22 -0
  121. package/dist/litellm/policy-form.d.ts.map +1 -0
  122. package/dist/litellm/policy-operations.d.ts +42 -0
  123. package/dist/litellm/policy-operations.d.ts.map +1 -0
  124. package/dist/litellm/policy-types.d.ts +57 -0
  125. package/dist/litellm/policy-types.d.ts.map +1 -0
  126. package/dist/litellm/policy.d.ts +65 -0
  127. package/dist/litellm/policy.d.ts.map +1 -0
  128. package/dist/litellm/providers.d.ts +1 -1
  129. package/dist/litellm/providers.d.ts.map +1 -1
  130. package/dist/litellm/registry-errors.d.ts +62 -0
  131. package/dist/litellm/registry-errors.d.ts.map +1 -0
  132. package/dist/litellm/registry-support.d.ts +42 -0
  133. package/dist/litellm/registry-support.d.ts.map +1 -0
  134. package/dist/litellm/team-form.d.ts +26 -0
  135. package/dist/litellm/team-form.d.ts.map +1 -0
  136. package/dist/litellm/team-members.d.ts +10 -0
  137. package/dist/litellm/team-members.d.ts.map +1 -0
  138. package/dist/litellm/team-operations.d.ts +38 -0
  139. package/dist/litellm/team-operations.d.ts.map +1 -0
  140. package/dist/litellm/team-permission.d.ts +35 -0
  141. package/dist/litellm/team-permission.d.ts.map +1 -0
  142. package/dist/litellm/team-types.d.ts +101 -0
  143. package/dist/litellm/team-types.d.ts.map +1 -0
  144. package/dist/litellm/team.d.ts +67 -0
  145. package/dist/litellm/team.d.ts.map +1 -0
  146. package/dist/litellm/tool-policy-form.d.ts +21 -0
  147. package/dist/litellm/tool-policy-form.d.ts.map +1 -0
  148. package/dist/litellm/tool-policy-operations.d.ts +30 -0
  149. package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
  150. package/dist/litellm/tool-policy-types.d.ts +46 -0
  151. package/dist/litellm/tool-policy-types.d.ts.map +1 -0
  152. package/dist/litellm/tool-policy.d.ts +62 -0
  153. package/dist/litellm/tool-policy.d.ts.map +1 -0
  154. package/dist/litellm/toolset-form.d.ts +20 -0
  155. package/dist/litellm/toolset-form.d.ts.map +1 -0
  156. package/dist/litellm/toolset-operations.d.ts +39 -0
  157. package/dist/litellm/toolset-operations.d.ts.map +1 -0
  158. package/dist/litellm/toolset-types.d.ts +46 -0
  159. package/dist/litellm/toolset-types.d.ts.map +1 -0
  160. package/dist/litellm/toolset.d.ts +55 -0
  161. package/dist/litellm/toolset.d.ts.map +1 -0
  162. package/dist/openbao/index.js +35 -1
  163. package/dist/openbao/index.js.map +3 -3
  164. package/dist/ownership/rows.d.ts +11 -0
  165. package/dist/ownership/rows.d.ts.map +1 -1
  166. package/dist/postgres/connection.d.ts +14 -2
  167. package/dist/postgres/connection.d.ts.map +1 -1
  168. package/dist/postgres/database-sql.d.ts +27 -8
  169. package/dist/postgres/database-sql.d.ts.map +1 -1
  170. package/dist/postgres/fake-grants-parse.d.ts +37 -0
  171. package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
  172. package/dist/postgres/fake-grants-read.d.ts +61 -0
  173. package/dist/postgres/fake-grants-read.d.ts.map +1 -0
  174. package/dist/postgres/fake-grants-sql.d.ts +46 -0
  175. package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
  176. package/dist/postgres/fake-grants-write.d.ts +29 -0
  177. package/dist/postgres/fake-grants-write.d.ts.map +1 -0
  178. package/dist/postgres/fake-role-sql.d.ts +41 -0
  179. package/dist/postgres/fake-role-sql.d.ts.map +1 -0
  180. package/dist/postgres/fake-schema-sql.d.ts +42 -0
  181. package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
  182. package/dist/postgres/fake-sql-parse.d.ts +23 -0
  183. package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
  184. package/dist/postgres/fake-sql-quote.d.ts +12 -0
  185. package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
  186. package/dist/postgres/fake-sql.d.ts +42 -0
  187. package/dist/postgres/fake-sql.d.ts.map +1 -1
  188. package/dist/postgres/grants-attrs.d.ts +115 -0
  189. package/dist/postgres/grants-attrs.d.ts.map +1 -0
  190. package/dist/postgres/grants-declare.d.ts +88 -0
  191. package/dist/postgres/grants-declare.d.ts.map +1 -0
  192. package/dist/postgres/grants-diff.d.ts +25 -0
  193. package/dist/postgres/grants-diff.d.ts.map +1 -0
  194. package/dist/postgres/grants-errors.d.ts +137 -0
  195. package/dist/postgres/grants-errors.d.ts.map +1 -0
  196. package/dist/postgres/grants-existence.d.ts +14 -0
  197. package/dist/postgres/grants-existence.d.ts.map +1 -0
  198. package/dist/postgres/grants-ops.d.ts +65 -0
  199. package/dist/postgres/grants-ops.d.ts.map +1 -0
  200. package/dist/postgres/grants-ownership.d.ts +18 -0
  201. package/dist/postgres/grants-ownership.d.ts.map +1 -0
  202. package/dist/postgres/grants-plan-restore.d.ts +22 -0
  203. package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
  204. package/dist/postgres/grants-plan.d.ts +65 -0
  205. package/dist/postgres/grants-plan.d.ts.map +1 -0
  206. package/dist/postgres/grants-read-defaults.d.ts +17 -0
  207. package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
  208. package/dist/postgres/grants-read.d.ts +77 -0
  209. package/dist/postgres/grants-read.d.ts.map +1 -0
  210. package/dist/postgres/grants-refuse.d.ts +25 -0
  211. package/dist/postgres/grants-refuse.d.ts.map +1 -0
  212. package/dist/postgres/grants-sql.d.ts +42 -0
  213. package/dist/postgres/grants-sql.d.ts.map +1 -0
  214. package/dist/postgres/grants-words.d.ts +29 -0
  215. package/dist/postgres/grants-words.d.ts.map +1 -0
  216. package/dist/postgres/grants.d.ts +37 -0
  217. package/dist/postgres/grants.d.ts.map +1 -0
  218. package/dist/postgres/index.d.ts +31 -6
  219. package/dist/postgres/index.d.ts.map +1 -1
  220. package/dist/postgres/index.js +1998 -37
  221. package/dist/postgres/index.js.map +46 -7
  222. package/dist/postgres/installed-classifier.d.ts +13 -0
  223. package/dist/postgres/installed-classifier.d.ts.map +1 -0
  224. package/dist/postgres/providers.d.ts +16 -8
  225. package/dist/postgres/providers.d.ts.map +1 -1
  226. package/dist/postgres/psql-executor.d.ts +4 -0
  227. package/dist/postgres/psql-executor.d.ts.map +1 -1
  228. package/dist/postgres/role-attrs.d.ts +112 -0
  229. package/dist/postgres/role-attrs.d.ts.map +1 -0
  230. package/dist/postgres/role-diff.d.ts +22 -0
  231. package/dist/postgres/role-diff.d.ts.map +1 -0
  232. package/dist/postgres/role-errors.d.ts +132 -0
  233. package/dist/postgres/role-errors.d.ts.map +1 -0
  234. package/dist/postgres/role-membership-sql.d.ts +78 -0
  235. package/dist/postgres/role-membership-sql.d.ts.map +1 -0
  236. package/dist/postgres/role-provider.d.ts +11 -0
  237. package/dist/postgres/role-provider.d.ts.map +1 -0
  238. package/dist/postgres/role-scram.d.ts +8 -0
  239. package/dist/postgres/role-scram.d.ts.map +1 -0
  240. package/dist/postgres/role-secrets.d.ts +38 -0
  241. package/dist/postgres/role-secrets.d.ts.map +1 -0
  242. package/dist/postgres/role-sql.d.ts +68 -0
  243. package/dist/postgres/role-sql.d.ts.map +1 -0
  244. package/dist/postgres/role.d.ts +57 -0
  245. package/dist/postgres/role.d.ts.map +1 -0
  246. package/dist/postgres/schema-assert.d.ts +50 -0
  247. package/dist/postgres/schema-assert.d.ts.map +1 -0
  248. package/dist/postgres/schema-attrs.d.ts +51 -0
  249. package/dist/postgres/schema-attrs.d.ts.map +1 -0
  250. package/dist/postgres/schema-delete.d.ts +28 -0
  251. package/dist/postgres/schema-delete.d.ts.map +1 -0
  252. package/dist/postgres/schema-diff.d.ts +14 -0
  253. package/dist/postgres/schema-diff.d.ts.map +1 -0
  254. package/dist/postgres/schema-errors.d.ts +139 -0
  255. package/dist/postgres/schema-errors.d.ts.map +1 -0
  256. package/dist/postgres/schema-identity.d.ts +8 -0
  257. package/dist/postgres/schema-identity.d.ts.map +1 -0
  258. package/dist/postgres/schema-reconcile.d.ts +12 -0
  259. package/dist/postgres/schema-reconcile.d.ts.map +1 -0
  260. package/dist/postgres/schema-sql.d.ts +45 -0
  261. package/dist/postgres/schema-sql.d.ts.map +1 -0
  262. package/dist/postgres/schema-test-kit.d.ts +67 -0
  263. package/dist/postgres/schema-test-kit.d.ts.map +1 -0
  264. package/dist/postgres/schema.d.ts +54 -0
  265. package/dist/postgres/schema.d.ts.map +1 -0
  266. package/dist/proxmox/index.js +35 -1
  267. package/dist/proxmox/index.js.map +3 -3
  268. package/dist/release/fake-engine.d.ts +10 -0
  269. package/dist/release/fake-engine.d.ts.map +1 -1
  270. package/dist/release/index.js +35 -1
  271. package/dist/release/index.js.map +3 -3
  272. package/dist/valkey/acl-attrs.d.ts +94 -0
  273. package/dist/valkey/acl-attrs.d.ts.map +1 -0
  274. package/dist/valkey/acl-compare.d.ts +28 -0
  275. package/dist/valkey/acl-compare.d.ts.map +1 -0
  276. package/dist/valkey/acl-connection.d.ts +6 -0
  277. package/dist/valkey/acl-connection.d.ts.map +1 -0
  278. package/dist/valkey/acl-form.d.ts +62 -0
  279. package/dist/valkey/acl-form.d.ts.map +1 -0
  280. package/dist/valkey/acl-managed.d.ts +4 -0
  281. package/dist/valkey/acl-managed.d.ts.map +1 -0
  282. package/dist/valkey/acl-ops.d.ts +37 -0
  283. package/dist/valkey/acl-ops.d.ts.map +1 -0
  284. package/dist/valkey/acl-profiles.d.ts +53 -0
  285. package/dist/valkey/acl-profiles.d.ts.map +1 -0
  286. package/dist/valkey/acl-reconcile.d.ts +26 -0
  287. package/dist/valkey/acl-reconcile.d.ts.map +1 -0
  288. package/dist/valkey/acl.d.ts +24 -0
  289. package/dist/valkey/acl.d.ts.map +1 -0
  290. package/dist/valkey/connection-service.d.ts +22 -0
  291. package/dist/valkey/connection-service.d.ts.map +1 -0
  292. package/dist/valkey/connection.d.ts +59 -0
  293. package/dist/valkey/connection.d.ts.map +1 -0
  294. package/dist/valkey/errors.d.ts +165 -0
  295. package/dist/valkey/errors.d.ts.map +1 -0
  296. package/dist/valkey/fake-acl.d.ts +29 -0
  297. package/dist/valkey/fake-acl.d.ts.map +1 -0
  298. package/dist/valkey/fake-valkey.d.ts +35 -0
  299. package/dist/valkey/fake-valkey.d.ts.map +1 -0
  300. package/dist/valkey/handler-test-fixture.d.ts +20 -0
  301. package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
  302. package/dist/valkey/index.d.ts +18 -0
  303. package/dist/valkey/index.d.ts.map +1 -0
  304. package/dist/valkey/index.js +964 -0
  305. package/dist/valkey/index.js.map +27 -0
  306. package/dist/valkey/instance-attrs.d.ts +46 -0
  307. package/dist/valkey/instance-attrs.d.ts.map +1 -0
  308. package/dist/valkey/instance-form.d.ts +22 -0
  309. package/dist/valkey/instance-form.d.ts.map +1 -0
  310. package/dist/valkey/instance.d.ts +48 -0
  311. package/dist/valkey/instance.d.ts.map +1 -0
  312. package/dist/valkey/provider-socket-fixture.d.ts +8 -0
  313. package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
  314. package/dist/valkey/providers.d.ts +16 -0
  315. package/dist/valkey/providers.d.ts.map +1 -0
  316. package/dist/valkey/resp.d.ts +38 -0
  317. package/dist/valkey/resp.d.ts.map +1 -0
  318. package/dist/valkey/transport-error.d.ts +36 -0
  319. package/dist/valkey/transport-error.d.ts.map +1 -0
  320. package/dist/valkey/transport.d.ts +50 -0
  321. package/dist/valkey/transport.d.ts.map +1 -0
  322. package/docs/litellm-access-group.md +105 -0
  323. package/docs/litellm-credential.md +60 -0
  324. package/docs/litellm-key-metadata.md +56 -0
  325. package/docs/litellm-key.md +194 -0
  326. package/docs/litellm-mcp.md +187 -0
  327. package/docs/litellm-model.md +111 -0
  328. package/docs/litellm-policy-attachment.md +86 -0
  329. package/docs/litellm-policy.md +103 -0
  330. package/docs/litellm-team.md +117 -0
  331. package/docs/litellm-tool-policy.md +90 -0
  332. package/docs/litellm-toolset.md +92 -0
  333. package/docs/litellm.md +16 -9
  334. package/docs/peers.md +15 -6
  335. package/docs/postgres-grants-example.md +55 -0
  336. package/docs/postgres-grants.md +157 -0
  337. package/docs/postgres-role.md +126 -0
  338. package/docs/postgres-schema.md +139 -0
  339. package/docs/postgres.md +20 -3
  340. package/docs/valkey-transport.md +29 -0
  341. package/docs/valkey.md +187 -0
  342. package/package.json +6 -2
  343. package/src/ceph/ceph-argv.test.ts +1 -1
  344. package/src/launchd/sudo-allowlist.test.ts +2 -2
  345. package/src/linux/sudo-allowlist.test.ts +3 -3
  346. package/src/linux/sudo-runner.test.ts +2 -2
  347. package/src/litellm/access-group-form.ts +105 -0
  348. package/src/litellm/access-group-operations.ts +92 -0
  349. package/src/litellm/access-group-types.ts +49 -0
  350. package/src/litellm/access-group.test.ts +197 -0
  351. package/src/litellm/access-group.ts +151 -0
  352. package/src/litellm/credential-errors.ts +183 -0
  353. package/src/litellm/credential-form.test.ts +151 -0
  354. package/src/litellm/credential-form.ts +211 -0
  355. package/src/litellm/credential-guards.test.ts +241 -0
  356. package/src/litellm/credential-operations.ts +208 -0
  357. package/src/litellm/credential-recovery.test.ts +93 -0
  358. package/src/litellm/credential-rewrite.test.ts +164 -0
  359. package/src/litellm/credential-rewrite.ts +50 -0
  360. package/src/litellm/credential-types.ts +117 -0
  361. package/src/litellm/credential-values.ts +94 -0
  362. package/src/litellm/credential.test.ts +218 -0
  363. package/src/litellm/credential.ts +227 -0
  364. package/src/litellm/fake-access-group-litellm.ts +127 -0
  365. package/src/litellm/fake-credential-litellm.ts +216 -0
  366. package/src/litellm/fake-keys.ts +190 -0
  367. package/src/litellm/fake-litellm.ts +19 -9
  368. package/src/litellm/fake-mcp-litellm.ts +214 -0
  369. package/src/litellm/fake-model-litellm-post-update.ts +103 -0
  370. package/src/litellm/fake-model-litellm.ts +233 -0
  371. package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
  372. package/src/litellm/fake-policy-litellm.ts +186 -0
  373. package/src/litellm/fake-registry-base.ts +69 -0
  374. package/src/litellm/fake-stack.ts +17 -1
  375. package/src/litellm/fake-team-litellm.ts +229 -0
  376. package/src/litellm/fake-tool-litellm.ts +88 -0
  377. package/src/litellm/fake-toolset-litellm.ts +110 -0
  378. package/src/litellm/index.ts +140 -0
  379. package/src/litellm/key-delete.test.ts +212 -0
  380. package/src/litellm/key-errors.ts +241 -0
  381. package/src/litellm/key-form.ts +200 -0
  382. package/src/litellm/key-harness.ts +121 -0
  383. package/src/litellm/key-metadata-errors.ts +49 -0
  384. package/src/litellm/key-metadata.test.ts +156 -0
  385. package/src/litellm/key-metadata.ts +74 -0
  386. package/src/litellm/key-operations.ts +184 -0
  387. package/src/litellm/key-rotation.test.ts +110 -0
  388. package/src/litellm/key-scope.test.ts +135 -0
  389. package/src/litellm/key-secret.test.ts +248 -0
  390. package/src/litellm/key-secret.ts +137 -0
  391. package/src/litellm/key-transport.test.ts +166 -0
  392. package/src/litellm/key.test.ts +231 -0
  393. package/src/litellm/key.ts +213 -0
  394. package/src/litellm/mcp-server-adopt.test.ts +86 -0
  395. package/src/litellm/mcp-server-alias.test.ts +184 -0
  396. package/src/litellm/mcp-server-credential.ts +85 -0
  397. package/src/litellm/mcp-server-errors.ts +141 -0
  398. package/src/litellm/mcp-server-exports.test.ts +15 -0
  399. package/src/litellm/mcp-server-form.test.ts +241 -0
  400. package/src/litellm/mcp-server-form.ts +233 -0
  401. package/src/litellm/mcp-server-handlers.test.ts +150 -0
  402. package/src/litellm/mcp-server-locate.ts +66 -0
  403. package/src/litellm/mcp-server-operations.ts +111 -0
  404. package/src/litellm/mcp-server-registry.test.ts +146 -0
  405. package/src/litellm/mcp-server-retype.test.ts +114 -0
  406. package/src/litellm/mcp-server-shadow.test.ts +91 -0
  407. package/src/litellm/mcp-server-shadow.ts +45 -0
  408. package/src/litellm/mcp-server-tools.test.ts +85 -0
  409. package/src/litellm/mcp-server-types.ts +143 -0
  410. package/src/litellm/mcp-server-url.ts +66 -0
  411. package/src/litellm/mcp-server.test.ts +213 -0
  412. package/src/litellm/mcp-server.ts +225 -0
  413. package/src/litellm/model-claim.ts +69 -0
  414. package/src/litellm/model-credential.ts +45 -0
  415. package/src/litellm/model-errors.ts +168 -0
  416. package/src/litellm/model-foreign-row.test.ts +173 -0
  417. package/src/litellm/model-form.test.ts +228 -0
  418. package/src/litellm/model-form.ts +223 -0
  419. package/src/litellm/model-locate.test.ts +128 -0
  420. package/src/litellm/model-locate.ts +67 -0
  421. package/src/litellm/model-operations.test.ts +93 -0
  422. package/src/litellm/model-operations.ts +146 -0
  423. package/src/litellm/model-params-preserve.test.ts +119 -0
  424. package/src/litellm/model-recovery.test.ts +57 -0
  425. package/src/litellm/model-types.ts +112 -0
  426. package/src/litellm/model.test.ts +222 -0
  427. package/src/litellm/model.ts +237 -0
  428. package/src/litellm/policy-attachment-form.ts +103 -0
  429. package/src/litellm/policy-attachment-operations.ts +74 -0
  430. package/src/litellm/policy-attachment-types.ts +48 -0
  431. package/src/litellm/policy-attachment.test.ts +198 -0
  432. package/src/litellm/policy-attachment.ts +178 -0
  433. package/src/litellm/policy-form.ts +122 -0
  434. package/src/litellm/policy-operations.ts +112 -0
  435. package/src/litellm/policy-types.ts +58 -0
  436. package/src/litellm/policy.test.ts +214 -0
  437. package/src/litellm/policy.ts +146 -0
  438. package/src/litellm/providers.ts +24 -3
  439. package/src/litellm/registry-errors.ts +88 -0
  440. package/src/litellm/registry-exports.test.ts +66 -0
  441. package/src/litellm/registry-support.ts +109 -0
  442. package/src/litellm/team-form.ts +140 -0
  443. package/src/litellm/team-members.test.ts +150 -0
  444. package/src/litellm/team-members.ts +58 -0
  445. package/src/litellm/team-operations.ts +90 -0
  446. package/src/litellm/team-permission.ts +159 -0
  447. package/src/litellm/team-read.test.ts +89 -0
  448. package/src/litellm/team-types.ts +106 -0
  449. package/src/litellm/team.test.ts +206 -0
  450. package/src/litellm/team.ts +159 -0
  451. package/src/litellm/tool-policy-form.ts +94 -0
  452. package/src/litellm/tool-policy-operations.ts +58 -0
  453. package/src/litellm/tool-policy-types.ts +48 -0
  454. package/src/litellm/tool-policy.test.ts +172 -0
  455. package/src/litellm/tool-policy.ts +125 -0
  456. package/src/litellm/toolset-form.ts +104 -0
  457. package/src/litellm/toolset-operations.ts +90 -0
  458. package/src/litellm/toolset-types.ts +47 -0
  459. package/src/litellm/toolset.test.ts +198 -0
  460. package/src/litellm/toolset.ts +151 -0
  461. package/src/ownership/ownership.test.ts +33 -1
  462. package/src/ownership/rows.ts +53 -0
  463. package/src/postgres/connection.ts +42 -7
  464. package/src/postgres/database-bigint-serialization.test.ts +1 -0
  465. package/src/postgres/database-refusals.test.ts +2 -2
  466. package/src/postgres/database-sql.ts +36 -9
  467. package/src/postgres/fake-grants-parse.ts +189 -0
  468. package/src/postgres/fake-grants-read.ts +250 -0
  469. package/src/postgres/fake-grants-sql.ts +207 -0
  470. package/src/postgres/fake-grants-write.ts +90 -0
  471. package/src/postgres/fake-role-sql.ts +240 -0
  472. package/src/postgres/fake-schema-semantics.test.ts +36 -0
  473. package/src/postgres/fake-schema-sql.ts +146 -0
  474. package/src/postgres/fake-sql-parse.ts +86 -0
  475. package/src/postgres/fake-sql-quote.ts +36 -0
  476. package/src/postgres/fake-sql.ts +166 -46
  477. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
  478. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
  479. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
  480. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
  481. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
  482. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
  483. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
  484. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
  485. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
  486. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
  487. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
  488. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
  489. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
  490. package/src/postgres/grants-acl.test.ts +61 -0
  491. package/src/postgres/grants-attrs.ts +185 -0
  492. package/src/postgres/grants-database.test.ts +158 -0
  493. package/src/postgres/grants-declare.ts +172 -0
  494. package/src/postgres/grants-delete-proof.test.ts +154 -0
  495. package/src/postgres/grants-diff.ts +101 -0
  496. package/src/postgres/grants-errors.ts +215 -0
  497. package/src/postgres/grants-existence-guards.test.ts +113 -0
  498. package/src/postgres/grants-existence.ts +101 -0
  499. package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
  500. package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
  501. package/src/postgres/grants-lifecycle.test.ts +181 -0
  502. package/src/postgres/grants-ops.ts +229 -0
  503. package/src/postgres/grants-owner-revoke.test.ts +121 -0
  504. package/src/postgres/grants-ownership.ts +49 -0
  505. package/src/postgres/grants-plan-collateral.test.ts +202 -0
  506. package/src/postgres/grants-plan-diff.test.ts +204 -0
  507. package/src/postgres/grants-plan-restore.ts +43 -0
  508. package/src/postgres/grants-plan-revocations.test.ts +69 -0
  509. package/src/postgres/grants-plan.test.ts +148 -0
  510. package/src/postgres/grants-plan.ts +245 -0
  511. package/src/postgres/grants-provenance.test.ts +134 -0
  512. package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
  513. package/src/postgres/grants-read-absent.test.ts +91 -0
  514. package/src/postgres/grants-read-defaults.ts +51 -0
  515. package/src/postgres/grants-read.ts +250 -0
  516. package/src/postgres/grants-refusals.test.ts +136 -0
  517. package/src/postgres/grants-refuse.ts +119 -0
  518. package/src/postgres/grants-relkind-wire.test.ts +111 -0
  519. package/src/postgres/grants-repair-plan.test.ts +201 -0
  520. package/src/postgres/grants-sql.test.ts +128 -0
  521. package/src/postgres/grants-sql.ts +144 -0
  522. package/src/postgres/grants-words.ts +34 -0
  523. package/src/postgres/grants.ts +110 -0
  524. package/src/postgres/index.ts +129 -5
  525. package/src/postgres/installed-classifier.ts +36 -0
  526. package/src/postgres/providers.ts +33 -9
  527. package/src/postgres/psql-executor-escaping.test.ts +67 -0
  528. package/src/postgres/psql-executor.test.ts +63 -2
  529. package/src/postgres/psql-executor.ts +74 -34
  530. package/src/postgres/role-adopt.test.ts +98 -0
  531. package/src/postgres/role-attrs.ts +137 -0
  532. package/src/postgres/role-diff.ts +93 -0
  533. package/src/postgres/role-errors.ts +206 -0
  534. package/src/postgres/role-guard.test.ts +60 -0
  535. package/src/postgres/role-identity.test.ts +197 -0
  536. package/src/postgres/role-lifecycle.test.ts +228 -0
  537. package/src/postgres/role-membership-options.test.ts +73 -0
  538. package/src/postgres/role-membership-repair.test.ts +153 -0
  539. package/src/postgres/role-membership-sql.ts +223 -0
  540. package/src/postgres/role-password-ascii.test.ts +53 -0
  541. package/src/postgres/role-password-transports.test.ts +123 -0
  542. package/src/postgres/role-password.test.ts +158 -0
  543. package/src/postgres/role-privilege.test.ts +107 -0
  544. package/src/postgres/role-provenance.test.ts +200 -0
  545. package/src/postgres/role-provider.ts +105 -0
  546. package/src/postgres/role-refusals.test.ts +225 -0
  547. package/src/postgres/role-scram.test.ts +38 -0
  548. package/src/postgres/role-scram.ts +40 -0
  549. package/src/postgres/role-secrets.ts +61 -0
  550. package/src/postgres/role-sql.ts +213 -0
  551. package/src/postgres/role-valid-until.test.ts +68 -0
  552. package/src/postgres/role.ts +226 -0
  553. package/src/postgres/schema-assert.ts +139 -0
  554. package/src/postgres/schema-attrs.ts +71 -0
  555. package/src/postgres/schema-delete-proofs.test.ts +192 -0
  556. package/src/postgres/schema-delete.ts +96 -0
  557. package/src/postgres/schema-diff.ts +44 -0
  558. package/src/postgres/schema-drop-2bp01.test.ts +146 -0
  559. package/src/postgres/schema-errors.ts +209 -0
  560. package/src/postgres/schema-handlers.test.ts +193 -0
  561. package/src/postgres/schema-identity.ts +39 -0
  562. package/src/postgres/schema-lifecycle.test.ts +246 -0
  563. package/src/postgres/schema-race.test.ts +70 -0
  564. package/src/postgres/schema-reconcile.ts +100 -0
  565. package/src/postgres/schema-refusals.test.ts +144 -0
  566. package/src/postgres/schema-socket.test.ts +162 -0
  567. package/src/postgres/schema-sql.ts +130 -0
  568. package/src/postgres/schema-takeover.test.ts +149 -0
  569. package/src/postgres/schema-test-kit.ts +85 -0
  570. package/src/postgres/schema.ts +130 -0
  571. package/src/release/binary-alias.test.ts +3 -3
  572. package/src/release/binary-claims.test.ts +3 -3
  573. package/src/release/binary-directory-umask.test.ts +65 -0
  574. package/src/release/fake-engine.ts +15 -0
  575. package/src/valkey/acl-attrs.ts +98 -0
  576. package/src/valkey/acl-compare.ts +57 -0
  577. package/src/valkey/acl-connection.ts +13 -0
  578. package/src/valkey/acl-delete.test.ts +127 -0
  579. package/src/valkey/acl-form.ts +239 -0
  580. package/src/valkey/acl-managed.ts +13 -0
  581. package/src/valkey/acl-ops.ts +122 -0
  582. package/src/valkey/acl-ownership.test.ts +118 -0
  583. package/src/valkey/acl-prefix.test.ts +38 -0
  584. package/src/valkey/acl-profiles.ts +81 -0
  585. package/src/valkey/acl-reconcile.ts +180 -0
  586. package/src/valkey/acl-reserved.test.ts +69 -0
  587. package/src/valkey/acl-revocation.test.ts +94 -0
  588. package/src/valkey/acl-seat-prefix.test.ts +111 -0
  589. package/src/valkey/acl-validation.test.ts +54 -0
  590. package/src/valkey/acl.test.ts +215 -0
  591. package/src/valkey/acl.ts +169 -0
  592. package/src/valkey/connection-service.ts +46 -0
  593. package/src/valkey/connection.ts +180 -0
  594. package/src/valkey/errors.ts +239 -0
  595. package/src/valkey/fake-acl.ts +128 -0
  596. package/src/valkey/fake-valkey.ts +224 -0
  597. package/src/valkey/handler-test-fixture.ts +43 -0
  598. package/src/valkey/handlers.test.ts +205 -0
  599. package/src/valkey/index.ts +54 -0
  600. package/src/valkey/instance-attrs.ts +48 -0
  601. package/src/valkey/instance-form.ts +104 -0
  602. package/src/valkey/instance.test.ts +108 -0
  603. package/src/valkey/instance.ts +160 -0
  604. package/src/valkey/provider-socket-fixture.ts +71 -0
  605. package/src/valkey/providers.test.ts +129 -0
  606. package/src/valkey/providers.ts +21 -0
  607. package/src/valkey/resp.ts +212 -0
  608. package/src/valkey/transport-bounds.test.ts +150 -0
  609. package/src/valkey/transport-error.ts +37 -0
  610. package/src/valkey/transport.test.ts +158 -0
  611. package/src/valkey/transport.ts +109 -0
  612. package/src/valkey/upstream-bounds.test.ts +14 -0
@@ -0,0 +1,241 @@
1
+ /**
2
+ * The typed refusals `LiteLLM.Key` raises on top of `@distilled.cloud/litellm`'s own SDK errors.
3
+ *
4
+ * ⛔ NOT ONE OF THESE CARRIES A KEY VALUE. They name the alias, the environment VARIABLE and the
5
+ * rule broken, never what the variable held: an error is logged, retried and pasted into a PR.
6
+ * The SDK's own errors are the other half: `generateKey` (key-operations.ts) turns the one that
7
+ * holds the request, and so the value, into `LitellmKeyTransportError` below.
8
+ */
9
+ import type * as keys from '@distilled.cloud/litellm/key_management';
10
+ import * as Data from 'effect/Data';
11
+ import type { HttpClientErrorReason } from 'effect/unstable/http/HttpClientError';
12
+ import type {
13
+ LitellmKeyCallbackMetadataDeclaredError,
14
+ LitellmKeyCallbackMetadataLiveError,
15
+ } from './key-metadata-errors.ts';
16
+
17
+ /** A create is needed and the declaration names no `key` — LiteLLM would mint a value nobody holds. */
18
+ export class LitellmKeyValueRequiredError extends Data.TaggedError('LitellmKeyValueRequiredError')<{
19
+ readonly keyAlias: string;
20
+ }> {
21
+ override get message(): string {
22
+ return (
23
+ `LiteLLM.Key '${this.keyAlias}' does not exist and declares no \`key\`. Creating it would ` +
24
+ 'mint a value nobody holds. Declare `key: { fromEnv: "NAME" }`, or adopt an existing key.'
25
+ );
26
+ }
27
+ }
28
+
29
+ /**
30
+ * distilled prints request and response BODIES to stderr while `DISTILLED_DEBUG_HTTP` is set, and
31
+ * `/key/generate` carries the key in both. Refused before any request, as `fetchMeshNodeToken` does.
32
+ */
33
+ export class LitellmKeyDebugLoggingError extends Data.TaggedError('LitellmKeyDebugLoggingError')<{
34
+ readonly keyAlias: string;
35
+ }> {
36
+ override get message(): string {
37
+ return (
38
+ `LiteLLM.Key '${this.keyAlias}': DISTILLED_DEBUG_HTTP is set, so the SDK would print the ` +
39
+ "key to stderr in /key/generate's request and response. Unset it and run again. Nothing was written."
40
+ );
41
+ }
42
+ }
43
+
44
+ /**
45
+ * `/key/generate` failed on the wire (or its answer could not be read), so nobody knows whether the
46
+ * key exists.
47
+ *
48
+ * ⛔ THIS IS WHAT STANDS IN FOR AN `HttpClientError`, WHICH CARRIES ITS REQUEST, AND THE REQUEST BODY
49
+ * OF `/key/generate` IS `{"key":"sk-…"}`. Measured 2026-09-29 with a synthetic value: on a dropped
50
+ * connection `JSON.stringify(error)`, `Bun.inspect(error, { depth: 10 })` and Effect's JSON logger
51
+ * all printed the key, and so did the failure of a deploy over it. A defect from reading a broken
52
+ * answer (`protocol-rest.ts` reads it with `Effect.orDie`) carries the same request. So `reason` is
53
+ * the `HttpClientError` reason's TAG (a string) and nothing else is kept: no request, no cause, no
54
+ * description (a cause is free text from `fetch`).
55
+ */
56
+ export class LitellmKeyTransportError extends Data.TaggedError('LitellmKeyTransportError')<{
57
+ readonly keyAlias: string;
58
+ readonly reason: HttpClientErrorReason['_tag'] | 'Defect';
59
+ }> {
60
+ override get message(): string {
61
+ return (
62
+ `LiteLLM.Key '${this.keyAlias}': the /key/generate request failed (${this.reason}) before an ` +
63
+ 'answer could be read, so the key MAY have been created. This error keeps neither the request ' +
64
+ "nor its cause: the request body holds the key's value. Look for the alias in LiteLLM. A key " +
65
+ 'that landed is taken over by the next deploy with --adopt; one that did not is created by it.'
66
+ );
67
+ }
68
+ }
69
+
70
+ /** An empty alias: `/key/list` would read `key_alias=` as no filter, and nothing could find the key again. */
71
+ export class LitellmKeyAliasEmptyError extends Data.TaggedError('LitellmKeyAliasEmptyError')<{}> {
72
+ override get message(): string {
73
+ return "LiteLLM.Key: keyAlias is empty. The alias is the key's identity. Nothing was written.";
74
+ }
75
+ }
76
+
77
+ /** `key: { fromEnv }` names a variable the deploying process does not have (or has empty). */
78
+ export class LitellmKeyValueMissingError extends Data.TaggedError('LitellmKeyValueMissingError')<{
79
+ readonly keyAlias: string;
80
+ readonly variable: string;
81
+ }> {
82
+ override get message(): string {
83
+ return (
84
+ `LiteLLM.Key '${this.keyAlias}': the environment variable ${this.variable} is unset or empty ` +
85
+ 'in the deploying process. Nothing was written.'
86
+ );
87
+ }
88
+ }
89
+
90
+ /** The variable's value breaks the rule `/key/generate` states for a user-defined key. */
91
+ export class LitellmKeyValueMalformedError extends Data.TaggedError(
92
+ 'LitellmKeyValueMalformedError',
93
+ )<{
94
+ readonly keyAlias: string;
95
+ readonly variable: string;
96
+ readonly rule: string;
97
+ }> {
98
+ override get message(): string {
99
+ return (
100
+ `LiteLLM.Key '${this.keyAlias}': the value of ${this.variable} is not usable — ${this.rule}. ` +
101
+ 'Nothing was written.'
102
+ );
103
+ }
104
+ }
105
+
106
+ /**
107
+ * `/key/generate` answered with a different value than the one sent, so the row exists under a
108
+ * key nobody holds. `removed` says whether the row was deleted again on the way out.
109
+ */
110
+ export class LitellmKeyValueNotHonouredError extends Data.TaggedError(
111
+ 'LitellmKeyValueNotHonouredError',
112
+ )<{
113
+ readonly keyAlias: string;
114
+ readonly removed: boolean;
115
+ }> {
116
+ override get message(): string {
117
+ const outcome = this.removed
118
+ ? 'The row was deleted again.'
119
+ : 'The row could NOT be deleted again: remove it by hand.';
120
+ return (
121
+ `LiteLLM.Key '${this.keyAlias}': /key/generate answered with a different value than the one ` +
122
+ `sent, so the key would authenticate nobody. ${outcome}`
123
+ );
124
+ }
125
+ }
126
+
127
+ /**
128
+ * An ADOPTED key was declared with a `key` whose value is not the key the live row holds. The
129
+ * value is compared only as a sha256 in memory against the row's `token` (`hash_token`, the
130
+ * vendor's own store) — never in state, never in an error — and a mismatch is refused, because a
131
+ * seat that reads the same variable would hold a key that authenticates nothing while the plan
132
+ * reported success. `/key/update` cannot change a key's value (`prepare_key_update_data` pops
133
+ * `key`), so there is nothing to write: the operator must fix the variable or drop the `key`.
134
+ */
135
+ export class LitellmKeyValueMismatchError extends Data.TaggedError('LitellmKeyValueMismatchError')<{
136
+ readonly keyAlias: string;
137
+ readonly variable: string;
138
+ }> {
139
+ override get message(): string {
140
+ return (
141
+ `LiteLLM.Key '${this.keyAlias}': the value of ${this.variable} is not the key this alias ` +
142
+ 'holds. Nothing was written. /key/update cannot change a key value, so fix the variable or ' +
143
+ 'drop the `key` and manage the existing key without one.'
144
+ );
145
+ }
146
+ }
147
+
148
+ /**
149
+ * The alias is the identity: `/key/update` and `/key/delete` find a key by it, and this resource
150
+ * never holds the value that could find it any other way. A different alias is a different key.
151
+ */
152
+ export class LitellmKeyAliasChangedError extends Data.TaggedError('LitellmKeyAliasChangedError')<{
153
+ readonly from: string;
154
+ readonly to: string;
155
+ }> {
156
+ override get message(): string {
157
+ return (
158
+ `LiteLLM.Key alias changed from '${this.from}' to '${this.to}'. The alias is the key's ` +
159
+ 'identity and a rename would need the same value under a new row: declare the new alias as ' +
160
+ 'a new resource and remove the old one with RemovalPolicy.destroy(). Nothing was written.'
161
+ );
162
+ }
163
+ }
164
+
165
+ /** More than one live key carries the alias, so nothing can say which one is declared. */
166
+ export class LitellmKeyAmbiguousAliasError extends Data.TaggedError(
167
+ 'LitellmKeyAmbiguousAliasError',
168
+ )<{
169
+ readonly keyAlias: string;
170
+ readonly count: number;
171
+ }> {
172
+ override get message(): string {
173
+ return (
174
+ `LiteLLM.Key '${this.keyAlias}': ${this.count} live keys carry this alias, so none can be ` +
175
+ 'called the declared one. Resolve the duplicates in LiteLLM first. Nothing was written.'
176
+ );
177
+ }
178
+ }
179
+
180
+ /** `/key/list` answered something that is not a list of key rows. */
181
+ export class LitellmKeyUnreadableError extends Data.TaggedError('LitellmKeyUnreadableError')<{
182
+ readonly keyAlias: string;
183
+ }> {
184
+ override get message(): string {
185
+ return (
186
+ `LiteLLM.Key '${this.keyAlias}': /key/list did not answer full key rows (a hash list means ` +
187
+ 'return_full_object was ignored). Nothing was written.'
188
+ );
189
+ }
190
+ }
191
+
192
+ /** A write returned no error but the alias is not listed afterwards. */
193
+ export class LitellmKeyAbsentAfterWriteError extends Data.TaggedError(
194
+ 'LitellmKeyAbsentAfterWriteError',
195
+ )<{
196
+ readonly keyAlias: string;
197
+ }> {
198
+ override get message(): string {
199
+ return `LiteLLM.Key '${this.keyAlias}': the write returned no error but the alias is not listed.`;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * The write returned no error but the row still differs from the declaration. `/key/update` is a
205
+ * merge patch (its docstring), so this is a proxy that did not apply a field — refused, never
206
+ * reported as done.
207
+ */
208
+ export class LitellmKeyFieldNotAppliedError extends Data.TaggedError(
209
+ 'LitellmKeyFieldNotAppliedError',
210
+ )<{
211
+ readonly keyAlias: string;
212
+ readonly fields: readonly string[];
213
+ }> {
214
+ override get message(): string {
215
+ return (
216
+ `LiteLLM.Key '${this.keyAlias}': the write returned no error but ${this.fields.join(', ')} ` +
217
+ 'still differ from the declaration.'
218
+ );
219
+ }
220
+ }
221
+
222
+ export type KeyError =
223
+ | keys.ListKeysKeyListGetError
224
+ | keys.GenerateKeyFnKeyGeneratePostError
225
+ | keys.UpdateKeyFnKeyUpdatePostError
226
+ | keys.DeleteKeyFnKeyDeletePostError
227
+ | LitellmKeyDebugLoggingError
228
+ | LitellmKeyTransportError
229
+ | LitellmKeyAliasEmptyError
230
+ | LitellmKeyValueRequiredError
231
+ | LitellmKeyValueMissingError
232
+ | LitellmKeyValueMalformedError
233
+ | LitellmKeyValueNotHonouredError
234
+ | LitellmKeyValueMismatchError
235
+ | LitellmKeyAliasChangedError
236
+ | LitellmKeyAmbiguousAliasError
237
+ | LitellmKeyCallbackMetadataDeclaredError
238
+ | LitellmKeyCallbackMetadataLiveError
239
+ | LitellmKeyUnreadableError
240
+ | LitellmKeyAbsentAfterWriteError
241
+ | LitellmKeyFieldNotAppliedError;
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Props, attributes, wire bodies and comparison for `LiteLLM.Key`, testable without a server.
3
+ *
4
+ * ⛔ THERE IS NO SECRET IN THIS FILE'S OUTPUT. `KeyAttributes` has no `key`, no `token` and no hash:
5
+ * `/key/list` rows carry `token` (LiteLLM's hash of the key) and `toAttributes` drops it, because
6
+ * attributes are persisted unencrypted (key-secret.ts). The value is unwrapped in `createBody`, at
7
+ * the last moment before the wire, and compared with a live row only as a sha256 in memory
8
+ * (`verifyKeyValue`, key-secret.ts) against the raw row's `token` — the hash itself never reaches
9
+ * state. The callback slots of `metadata` are dropped too (key-metadata.ts).
10
+ * ★ THE ROW IS READ THROUGH `/key/list?key_alias=…&return_full_object=true`. Measured 2026-09-28
11
+ * (litellm-key-access): a bare list and `get_key` come back with `models: []` for keys whose real
12
+ * allowlist lives in the full object. The generated `UserAPIKeyAuth` row declares every column
13
+ * compared here (`budget_id`, `models`, `allowed_routes`, `team_id`, `metadata`, `expires`).
14
+ * ⛔ A DECLARATION MANAGES ONLY WHAT IT NAMES. An omitted `budgetId`, `models`, `allowedRoutes`,
15
+ * `teamId` or `duration` is neither compared nor sent, so a live value stays. Reading omission as
16
+ * "clear it" FAILS OPEN on a credential: `[]` is "all models" and "no route restriction" to
17
+ * LiteLLM, and no budget drops the tier's limits. On an adopted key (whose plan says `adopted`, never
18
+ * what the apply will write, and which `--adopt` given for another resource takes over too) that
19
+ * would widen a live key without the plan ever showing an `update`. Clearing is an explicit
20
+ * declaration: `models: []`, `allowedRoutes: []`, `budgetId: null`, `teamId: null`, `duration: null`.
21
+ * `/key/update` is a merge patch for the COLUMNS (its docstring), so an unsent one is left as it is.
22
+ * ⛔ `metadata` IS A MERGE, NOT A COLUMN OF THE DECLARER'S: LiteLLM keeps guardrails, per-model limits
23
+ * and more inside it, and `/key/update` replaces it wholesale. See key-metadata.ts.
24
+ * ⚠️ NOT MODELLED, so a declaration of them could never be diffed: `max_budget`, `soft_budget`,
25
+ * `object_permission`, `blocked`, `spend`, and the top-level rate limits. Bind a `LiteLLM.Budget`
26
+ * for limits. The ones that live in `metadata` (guardrails, tags, `model_rpm_limit`, …) are left
27
+ * alone by the merge, and can be declared as `metadata` keys.
28
+ */
29
+ import type * as keys from '@distilled.cloud/litellm/key_management';
30
+ import * as Redacted from 'effect/Redacted';
31
+ import type { FromEnv } from '../secrets/write-only.ts';
32
+ import { type Metadata, mergedMetadata, metadataDiffers, splitMetadata } from './key-metadata.ts';
33
+
34
+ export interface KeyProps {
35
+ /** The alias LiteLLM knows the key by: its identity, unique per proxy. Declare an existing key's alias to adopt it. */
36
+ readonly keyAlias: string;
37
+ /**
38
+ * The key's VALUE, by the NAME of the environment variable holding it (`{ fromEnv: 'SEAT_KEY' }`).
39
+ * Write-only and create-only: required to create the key, never stored. On an EXISTING key a
40
+ * declared value is compared with the row in memory only (sha256 against the row's `token`), and a
41
+ * mismatch is refused — `/key/update` cannot change a key's value. Omit it to manage an existing
42
+ * key's settings without ever holding its value.
43
+ */
44
+ readonly key?: FromEnv;
45
+ /**
46
+ * The `LiteLLM.Budget` tier the key binds to (`budget.budgetId`, so the tier is created first).
47
+ * Omitted = not managed, a live binding stays. `null` = unbind, which drops the tier's limits.
48
+ */
49
+ readonly budgetId?: string | null;
50
+ /**
51
+ * Model names the key may call. Omitted = not managed, a live scope stays (a NEW key then starts
52
+ * with LiteLLM's default). `[]` = ALL models, LiteLLM's reading: declared on a scoped key it WIDENS it.
53
+ */
54
+ readonly models?: readonly string[];
55
+ /**
56
+ * Routes the key may call, exact or wildcard (`/chat/completions`, `/v1/*`). Omitted = not
57
+ * managed. `[]` = no route restriction: declared on a restricted key it WIDENS it.
58
+ */
59
+ readonly allowedRoutes?: readonly string[];
60
+ /** The team the key belongs to. Omitted = not managed. `null` = detach. */
61
+ readonly teamId?: string | null;
62
+ /**
63
+ * The `metadata` keys this declaration manages, a MERGE (key-metadata.ts): other live keys are
64
+ * carried, never removed, and a key is cleared by declaring it `null`. Stored in state, so no
65
+ * secrets. `logging`, `callback_settings` and `secret_manager_settings` are refused.
66
+ */
67
+ readonly metadata?: Metadata;
68
+ /**
69
+ * Validity from creation: `'30s'`, `'30m'`, `'30h'`, `'30d'`. Omitted = not managed (a live expiry
70
+ * stays; a new key never expires). `null` = never expires, which clears a live expiry.
71
+ */
72
+ readonly duration?: string | null;
73
+ }
74
+
75
+ export interface KeyAttributes {
76
+ readonly keyAlias: string;
77
+ readonly budgetId: string | null;
78
+ readonly models: readonly string[];
79
+ readonly allowedRoutes: readonly string[];
80
+ readonly teamId: string | null;
81
+ /** The row's `metadata` WITHOUT the callback slots (`withheld`): those carry secret keys and state is unencrypted. */
82
+ readonly metadata: Metadata;
83
+ /**
84
+ * The `duration` this provider last WROTE. The row carries only `expires`, an absolute time, so
85
+ * the declared duration cannot be read back; state remembers it. `null` for an adopted row.
86
+ */
87
+ readonly duration: string | null;
88
+ /** When the key stops authenticating, as the row says. Observed, never declared. */
89
+ readonly expires: string | null;
90
+ /**
91
+ * The NAMES of the `metadata` callback slots the row has and this resource never reads. A metadata
92
+ * write is refused while any is present: `/key/update` replaces the column and could not carry them.
93
+ */
94
+ readonly withheld: readonly string[];
95
+ }
96
+
97
+ /** Order-insensitive: LiteLLM does not promise the order a list comes back in. */
98
+ const sameSet = (a: readonly string[], b: readonly string[]): boolean => {
99
+ const left = [...a].sort();
100
+ const right = [...b].sort();
101
+ return left.length === right.length && left.every((value, i) => value === right[i]);
102
+ };
103
+
104
+ /**
105
+ * Whether the expiry differs from the DECLARED `duration` (`null` = never expires): the remembered
106
+ * duration is not the declared one, or the row has (no) expiry where the declaration wants (none) —
107
+ * someone cleared or set it by hand.
108
+ * ⚠️ AN ADOPTED ROW REMEMBERS NOTHING, so declaring a `duration` on one re-arms its expiry once,
109
+ * from that deploy; after it the duration is remembered and a plan is quiet.
110
+ */
111
+ const expiryDiffers = (live: KeyAttributes, wanted: string | null): boolean =>
112
+ live.duration !== wanted || (wanted === null) !== (live.expires === null);
113
+
114
+ /**
115
+ * Wire names of the fields the declaration NAMES where the live row disagrees. An omitted prop is
116
+ * never here (the header's "manages only what it names"), so nothing omitted is ever written.
117
+ */
118
+ export const differing = (live: KeyAttributes, props: KeyProps): readonly string[] => {
119
+ const out: string[] = [];
120
+ if (props.budgetId !== undefined && live.budgetId !== props.budgetId) out.push('budget_id');
121
+ if (props.models !== undefined && !sameSet(live.models, props.models)) out.push('models');
122
+ if (props.allowedRoutes !== undefined && !sameSet(live.allowedRoutes, props.allowedRoutes)) {
123
+ out.push('allowed_routes');
124
+ }
125
+ if (props.teamId !== undefined && live.teamId !== props.teamId) out.push('team_id');
126
+ if (metadataDiffers(live.metadata, props.metadata)) out.push('metadata');
127
+ if (props.duration !== undefined && expiryDiffers(live, props.duration)) out.push('duration');
128
+ return out;
129
+ };
130
+
131
+ /**
132
+ * Create body: only what is declared, plus the value.
133
+ * ⛔ `Redacted.value` IS CALLED HERE, TO SEND, AND IN key-secret.ts's `echoes`, TO COMPARE — nowhere else.
134
+ */
135
+ export const createBody = (
136
+ props: KeyProps,
137
+ secret: Redacted.Redacted<string>,
138
+ ): keys.GenerateKeyFnKeyGeneratePostRequest => {
139
+ const body: keys.GenerateKeyFnKeyGeneratePostRequest = {
140
+ key: Redacted.value(secret),
141
+ key_alias: props.keyAlias,
142
+ };
143
+ // ★ A DECLARED `null` (unbind, detach, never expires) IS NOT SENT: a new key has nothing to clear.
144
+ if (typeof props.budgetId === 'string') body.budget_id = props.budgetId;
145
+ if (props.models !== undefined) body.models = [...props.models];
146
+ if (props.allowedRoutes !== undefined) body.allowed_routes = [...props.allowedRoutes];
147
+ if (typeof props.teamId === 'string') body.team_id = props.teamId;
148
+ if (props.metadata !== undefined) body.metadata = { ...props.metadata };
149
+ if (typeof props.duration === 'string') body.duration = props.duration;
150
+ return body;
151
+ };
152
+
153
+ /**
154
+ * Update body: the alias (which finds the key, `key` omitted) and ONLY the declared fields that
155
+ * differ, each as the declaration wants it — a declared `null` on `budget_id`/`team_id`/`duration`
156
+ * as an explicit `null` (a key column, which "an explicit null clears"), a declared `[]` as `[]`.
157
+ * ★ `metadata` CARRIES EVERY LIVE KEY with the declared ones on top, because `/key/update` replaces
158
+ * the column (key-metadata.ts). The caller has refused a key with `withheld` slots by now.
159
+ * ⛔ NEVER CARRIES `key`: an update must not be able to change which value authenticates.
160
+ */
161
+ export const updateBody = (
162
+ props: KeyProps,
163
+ live: KeyAttributes,
164
+ ): keys.UpdateKeyFnKeyUpdatePostRequest => {
165
+ const body: keys.UpdateKeyFnKeyUpdatePostRequest = { key_alias: live.keyAlias };
166
+ for (const field of differing(live, props)) {
167
+ if (field === 'budget_id') body.budget_id = props.budgetId ?? null;
168
+ if (field === 'models') body.models = [...(props.models ?? [])];
169
+ if (field === 'allowed_routes') body.allowed_routes = [...(props.allowedRoutes ?? [])];
170
+ if (field === 'team_id') body.team_id = props.teamId ?? null;
171
+ if (field === 'metadata') body.metadata = { ...mergedMetadata(live.metadata, props.metadata) };
172
+ if (field === 'duration') body.duration = props.duration ?? null;
173
+ }
174
+ return body;
175
+ };
176
+
177
+ const strings = (value: unknown): readonly string[] =>
178
+ Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [];
179
+
180
+ const stringOrNull = (value: unknown): string | null => (typeof value === 'string' ? value : null);
181
+
182
+ /**
183
+ * One row of `/key/list?return_full_object=true`. The row's `token` (LiteLLM's hash of the key), the
184
+ * `metadata` callback slots (only their names stay, as `withheld`), and every other column not named
185
+ * in `KeyAttributes`, are dropped here on purpose.
186
+ */
187
+ export const toAttributes = (row: Record<string, unknown>): KeyAttributes => {
188
+ const { metadata, withheld } = splitMetadata(row['metadata']);
189
+ return {
190
+ allowedRoutes: strings(row['allowed_routes']),
191
+ budgetId: stringOrNull(row['budget_id']),
192
+ duration: null,
193
+ expires: stringOrNull(row['expires']),
194
+ keyAlias: String(row['key_alias']),
195
+ metadata,
196
+ models: strings(row['models']),
197
+ teamId: stringOrNull(row['team_id']),
198
+ withheld,
199
+ };
200
+ };
@@ -0,0 +1,121 @@
1
+ /**
2
+ * What every `LiteLLM.Key` test needs, in one place — TEST ONLY, never imported by `index.ts` (the
3
+ * `mesh-node-harness.ts` convention).
4
+ *
5
+ * ⛔ EVERY KEY VALUE IN THE TESTS IS SYNTHETIC: `sk-FAKE-…`, never a value that ever authenticated
6
+ * anything. A test that asserts a value is absent from a place needs a value it can search for.
7
+ */
8
+ import { credentials } from '@distilled.cloud/litellm/Credentials';
9
+ import { Retry } from '@distilled.cloud/litellm/Retry';
10
+ import * as Effect from 'effect/Effect';
11
+ import * as Layer from 'effect/Layer';
12
+ import * as FetchHttpClient from 'effect/unstable/http/FetchHttpClient';
13
+ import { FAKE_BASE, startFakeLitellm } from './fake-litellm.ts';
14
+ import { type FakeStack, fakeStack } from './fake-stack.ts';
15
+ import { LiteLLMKey } from './key.ts';
16
+ import type { KeyProps } from './key-form.ts';
17
+ import type { LitellmOpContext } from './operations.ts';
18
+
19
+ export const MASTER_KEY = 'sk-test-master';
20
+ /** A valid user-defined key (`sk-` and 16+ characters) that is obviously not a real one. */
21
+ export const FAKE_KEY = 'sk-FAKE-seat-key-000000000001';
22
+ export const OTHER_FAKE_KEY = 'sk-FAKE-seat-key-000000000002';
23
+ export const VAR = 'FAKE_LITELLM_SEAT_KEY';
24
+
25
+ /** The row's `token` for a value, the same sha256 the fake and the vendor store (`hash_token`). */
26
+ export const tokenFor = (value: string): string =>
27
+ new Bun.CryptoHasher('sha256').update(value).digest('hex');
28
+
29
+ export type Fake = ReturnType<typeof startFakeLitellm>;
30
+
31
+ export const newFake = (options?: Parameters<typeof startFakeLitellm>[0]): Fake =>
32
+ startFakeLitellm({ masterKey: MASTER_KEY, ...options });
33
+
34
+ export const keyStack = (fake: Fake, settings?: { readonly noRetry?: boolean }): FakeStack =>
35
+ fakeStack({ apiKey: MASTER_KEY, baseUrl: FAKE_BASE }, fake.fetch, 'KeyStack', settings);
36
+
37
+ /** One declaration as a stack body. `name` is the resource's logical id. */
38
+ export const declare = (props: KeyProps, name = 'Seat') =>
39
+ Effect.gen(function* () {
40
+ yield* LiteLLMKey(name, props);
41
+ });
42
+
43
+ /**
44
+ * Runs `body` with `values` in `process.env`, then puts the environment back exactly as it was.
45
+ * ⚠️ THE PROVIDER READS `process.env` AT CALL TIME (write-only.ts `resolveAll`), so the variable
46
+ * has to be there for the whole deploy and gone after it.
47
+ */
48
+ export const withEnv = async <A>(
49
+ values: Readonly<Record<string, string | undefined>>,
50
+ body: () => Promise<A>,
51
+ ): Promise<A> => {
52
+ const saved = Object.fromEntries(Object.keys(values).map((name) => [name, process.env[name]]));
53
+ for (const [name, value] of Object.entries(values)) {
54
+ if (value === undefined) delete process.env[name];
55
+ else process.env[name] = value;
56
+ }
57
+ try {
58
+ return await body();
59
+ } finally {
60
+ for (const [name, value] of Object.entries(saved)) {
61
+ if (value === undefined) delete process.env[name];
62
+ else process.env[name] = value;
63
+ }
64
+ }
65
+ };
66
+
67
+ /** The message a rejected deploy carries, or `''` when it did not reject. */
68
+ export const failureOf = async (attempt: Promise<unknown>): Promise<string> =>
69
+ attempt.then(
70
+ () => '',
71
+ (error: unknown) => (error instanceof Error ? error.message : String(error)),
72
+ );
73
+
74
+ /**
75
+ * Runs one handler effect against the fake outside any stack (a handler-level test), with the SDK's
76
+ * retry OFF: a test of a failing call wants the failure, not the backoff before it.
77
+ */
78
+ export const runAgainst = <A, E>(
79
+ fake: Fake,
80
+ effect: Effect.Effect<A, E, LitellmOpContext>,
81
+ ): Promise<A> =>
82
+ Effect.runPromise(
83
+ effect.pipe(
84
+ Effect.provideService(Retry, { while: () => false }),
85
+ Effect.provide(FetchHttpClient.layer),
86
+ Effect.provide(Layer.succeed(FetchHttpClient.Fetch, fake.fetch)),
87
+ Effect.provide(credentials({ apiKey: MASTER_KEY, baseUrl: FAKE_BASE })),
88
+ ) as Effect.Effect<A, E, never>,
89
+ );
90
+
91
+ /** A seeded live row shaped like `UserAPIKeyAuth`, with a hash `token` a resource must never surface. */
92
+ export const liveRow = (fields: Record<string, unknown> = {}): Record<string, unknown> => ({
93
+ allowed_routes: [],
94
+ blocked: null,
95
+ budget_id: null,
96
+ expires: null,
97
+ key_alias: 'seat-a',
98
+ metadata: {},
99
+ models: [],
100
+ spend: 0,
101
+ team_id: null,
102
+ token: 'FAKE-TOKEN-HASH-do-not-surface',
103
+ ...fields,
104
+ });
105
+
106
+ /**
107
+ * Someone changing a live key outside the stack — the dashboard's `/key/update` — through the fake's
108
+ * own route, so it replaces `metadata` the way LiteLLM does. It shows in `fake.keys.writes()`.
109
+ */
110
+ export const dashboardEdit = async (
111
+ fake: Fake,
112
+ keyAlias: string,
113
+ patch: Record<string, unknown>,
114
+ ): Promise<void> => {
115
+ const response = await fake.fetch(`${FAKE_BASE}/key/update`, {
116
+ body: JSON.stringify({ key_alias: keyAlias, ...patch }),
117
+ headers: { authorization: `Bearer ${MASTER_KEY}`, 'content-type': 'application/json' },
118
+ method: 'POST',
119
+ });
120
+ if (!response.ok) throw new Error(`dashboard edit failed: ${response.status}`);
121
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The typed refusals for `LiteLLM.Key`'s `metadata` slots that carry callback credentials
3
+ * (`logging`, `callback_settings`, `secret_manager_settings`; key-metadata.ts has the reasons).
4
+ * Split from key-errors.ts, which is at its size cap.
5
+ *
6
+ * ⛔ NEITHER CARRIES A VALUE. They name the alias and the slot, never what the slot held.
7
+ */
8
+ import * as Data from 'effect/Data';
9
+
10
+ /**
11
+ * The declaration names a callback slot. LiteLLM stores its `callback_vars` ENCRYPTED, so the row
12
+ * would never read back equal (every deploy would fail with `LitellmKeyFieldNotAppliedError`), and
13
+ * Alchemy state is unencrypted.
14
+ */
15
+ export class LitellmKeyCallbackMetadataDeclaredError extends Data.TaggedError(
16
+ 'LitellmKeyCallbackMetadataDeclaredError',
17
+ )<{
18
+ readonly keyAlias: string;
19
+ readonly slots: readonly string[];
20
+ }> {
21
+ override get message(): string {
22
+ return (
23
+ `LiteLLM.Key '${this.keyAlias}': metadata declares ${this.slots.join(', ')}, which carry ` +
24
+ 'callback credentials. LiteLLM stores them encrypted, so they would never read back equal, ' +
25
+ "and Alchemy state is unencrypted. Configure the key's logging in LiteLLM itself. Nothing was written."
26
+ );
27
+ }
28
+ }
29
+
30
+ /**
31
+ * The live key holds callback credentials in its `metadata` and the declaration wants a metadata
32
+ * key changed. `/key/update` REPLACES the column, and this resource never read those slots, so it
33
+ * could not send them back: writing would strip the key's logging. Refused before the write.
34
+ */
35
+ export class LitellmKeyCallbackMetadataLiveError extends Data.TaggedError(
36
+ 'LitellmKeyCallbackMetadataLiveError',
37
+ )<{
38
+ readonly keyAlias: string;
39
+ readonly slots: readonly string[];
40
+ }> {
41
+ override get message(): string {
42
+ return (
43
+ `LiteLLM.Key '${this.keyAlias}': the live key holds ${this.slots.join(', ')} in its metadata ` +
44
+ '(callback credentials this resource never reads), and /key/update replaces the whole ' +
45
+ 'metadata, so writing the declared metadata would strip them. Change that metadata in LiteLLM, ' +
46
+ 'or stop declaring metadata for this key. Nothing was written.'
47
+ );
48
+ }
49
+ }