@homeflare/alchemy 0.42.0 → 0.44.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 (648) 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/budget-errors.d.ts +36 -0
  17. package/dist/litellm/budget-errors.d.ts.map +1 -0
  18. package/dist/litellm/budget-form.d.ts +50 -0
  19. package/dist/litellm/budget-form.d.ts.map +1 -0
  20. package/dist/litellm/budget-operations.d.ts +20 -0
  21. package/dist/litellm/budget-operations.d.ts.map +1 -0
  22. package/dist/litellm/budget.d.ts +61 -0
  23. package/dist/litellm/budget.d.ts.map +1 -0
  24. package/dist/litellm/credential-errors.d.ts +131 -0
  25. package/dist/litellm/credential-errors.d.ts.map +1 -0
  26. package/dist/litellm/credential-form.d.ts +79 -0
  27. package/dist/litellm/credential-form.d.ts.map +1 -0
  28. package/dist/litellm/credential-operations.d.ts +84 -0
  29. package/dist/litellm/credential-operations.d.ts.map +1 -0
  30. package/dist/litellm/credential-rewrite.d.ts +6 -0
  31. package/dist/litellm/credential-rewrite.d.ts.map +1 -0
  32. package/dist/litellm/credential-types.d.ts +87 -0
  33. package/dist/litellm/credential-types.d.ts.map +1 -0
  34. package/dist/litellm/credential-values.d.ts +53 -0
  35. package/dist/litellm/credential-values.d.ts.map +1 -0
  36. package/dist/litellm/credential.d.ts +83 -0
  37. package/dist/litellm/credential.d.ts.map +1 -0
  38. package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
  39. package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
  40. package/dist/litellm/fake-credential-litellm.d.ts +54 -0
  41. package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
  42. package/dist/litellm/fake-keys.d.ts +53 -0
  43. package/dist/litellm/fake-keys.d.ts.map +1 -0
  44. package/dist/litellm/fake-litellm.d.ts +9 -1
  45. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  46. package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
  47. package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
  48. package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
  49. package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
  50. package/dist/litellm/fake-model-litellm.d.ts +48 -0
  51. package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
  52. package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
  53. package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
  54. package/dist/litellm/fake-policy-litellm.d.ts +32 -0
  55. package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
  56. package/dist/litellm/fake-registry-base.d.ts +42 -0
  57. package/dist/litellm/fake-registry-base.d.ts.map +1 -0
  58. package/dist/litellm/fake-stack.d.ts +8 -1
  59. package/dist/litellm/fake-stack.d.ts.map +1 -1
  60. package/dist/litellm/fake-team-litellm.d.ts +47 -0
  61. package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
  62. package/dist/litellm/fake-tool-litellm.d.ts +28 -0
  63. package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
  64. package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
  65. package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
  66. package/dist/litellm/index.d.ts +20 -0
  67. package/dist/litellm/index.d.ts.map +1 -1
  68. package/dist/litellm/index.js +3201 -2
  69. package/dist/litellm/index.js.map +70 -5
  70. package/dist/litellm/key-errors.d.ts +169 -0
  71. package/dist/litellm/key-errors.d.ts.map +1 -0
  72. package/dist/litellm/key-form.d.ts +119 -0
  73. package/dist/litellm/key-form.d.ts.map +1 -0
  74. package/dist/litellm/key-harness.d.ts +41 -0
  75. package/dist/litellm/key-harness.d.ts.map +1 -0
  76. package/dist/litellm/key-metadata-errors.d.ts +30 -0
  77. package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
  78. package/dist/litellm/key-metadata.d.ts +22 -0
  79. package/dist/litellm/key-metadata.d.ts.map +1 -0
  80. package/dist/litellm/key-operations.d.ts +63 -0
  81. package/dist/litellm/key-operations.d.ts.map +1 -0
  82. package/dist/litellm/key-secret.d.ts +33 -0
  83. package/dist/litellm/key-secret.d.ts.map +1 -0
  84. package/dist/litellm/key.d.ts +78 -0
  85. package/dist/litellm/key.d.ts.map +1 -0
  86. package/dist/litellm/mcp-server-credential.d.ts +50 -0
  87. package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
  88. package/dist/litellm/mcp-server-errors.d.ts +101 -0
  89. package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
  90. package/dist/litellm/mcp-server-form.d.ts +56 -0
  91. package/dist/litellm/mcp-server-form.d.ts.map +1 -0
  92. package/dist/litellm/mcp-server-locate.d.ts +26 -0
  93. package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
  94. package/dist/litellm/mcp-server-operations.d.ts +63 -0
  95. package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
  96. package/dist/litellm/mcp-server-shadow.d.ts +24 -0
  97. package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
  98. package/dist/litellm/mcp-server-types.d.ts +118 -0
  99. package/dist/litellm/mcp-server-types.d.ts.map +1 -0
  100. package/dist/litellm/mcp-server-url.d.ts +11 -0
  101. package/dist/litellm/mcp-server-url.d.ts.map +1 -0
  102. package/dist/litellm/mcp-server.d.ts +95 -0
  103. package/dist/litellm/mcp-server.d.ts.map +1 -0
  104. package/dist/litellm/model-claim.d.ts +24 -0
  105. package/dist/litellm/model-claim.d.ts.map +1 -0
  106. package/dist/litellm/model-credential.d.ts +12 -0
  107. package/dist/litellm/model-credential.d.ts.map +1 -0
  108. package/dist/litellm/model-errors.d.ts +119 -0
  109. package/dist/litellm/model-errors.d.ts.map +1 -0
  110. package/dist/litellm/model-form.d.ts +78 -0
  111. package/dist/litellm/model-form.d.ts.map +1 -0
  112. package/dist/litellm/model-locate.d.ts +13 -0
  113. package/dist/litellm/model-locate.d.ts.map +1 -0
  114. package/dist/litellm/model-operations.d.ts +59 -0
  115. package/dist/litellm/model-operations.d.ts.map +1 -0
  116. package/dist/litellm/model-types.d.ts +91 -0
  117. package/dist/litellm/model-types.d.ts.map +1 -0
  118. package/dist/litellm/model.d.ts +88 -0
  119. package/dist/litellm/model.d.ts.map +1 -0
  120. package/dist/litellm/operations.d.ts +22 -0
  121. package/dist/litellm/operations.d.ts.map +1 -1
  122. package/dist/litellm/policy-attachment-form.d.ts +19 -0
  123. package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
  124. package/dist/litellm/policy-attachment-operations.d.ts +31 -0
  125. package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
  126. package/dist/litellm/policy-attachment-types.d.ts +48 -0
  127. package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
  128. package/dist/litellm/policy-attachment.d.ts +61 -0
  129. package/dist/litellm/policy-attachment.d.ts.map +1 -0
  130. package/dist/litellm/policy-form.d.ts +22 -0
  131. package/dist/litellm/policy-form.d.ts.map +1 -0
  132. package/dist/litellm/policy-operations.d.ts +42 -0
  133. package/dist/litellm/policy-operations.d.ts.map +1 -0
  134. package/dist/litellm/policy-types.d.ts +57 -0
  135. package/dist/litellm/policy-types.d.ts.map +1 -0
  136. package/dist/litellm/policy.d.ts +65 -0
  137. package/dist/litellm/policy.d.ts.map +1 -0
  138. package/dist/litellm/providers.d.ts +1 -1
  139. package/dist/litellm/providers.d.ts.map +1 -1
  140. package/dist/litellm/registry-errors.d.ts +62 -0
  141. package/dist/litellm/registry-errors.d.ts.map +1 -0
  142. package/dist/litellm/registry-support.d.ts +42 -0
  143. package/dist/litellm/registry-support.d.ts.map +1 -0
  144. package/dist/litellm/team-form.d.ts +26 -0
  145. package/dist/litellm/team-form.d.ts.map +1 -0
  146. package/dist/litellm/team-members.d.ts +10 -0
  147. package/dist/litellm/team-members.d.ts.map +1 -0
  148. package/dist/litellm/team-operations.d.ts +38 -0
  149. package/dist/litellm/team-operations.d.ts.map +1 -0
  150. package/dist/litellm/team-permission.d.ts +35 -0
  151. package/dist/litellm/team-permission.d.ts.map +1 -0
  152. package/dist/litellm/team-types.d.ts +101 -0
  153. package/dist/litellm/team-types.d.ts.map +1 -0
  154. package/dist/litellm/team.d.ts +67 -0
  155. package/dist/litellm/team.d.ts.map +1 -0
  156. package/dist/litellm/tool-policy-form.d.ts +21 -0
  157. package/dist/litellm/tool-policy-form.d.ts.map +1 -0
  158. package/dist/litellm/tool-policy-operations.d.ts +30 -0
  159. package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
  160. package/dist/litellm/tool-policy-types.d.ts +46 -0
  161. package/dist/litellm/tool-policy-types.d.ts.map +1 -0
  162. package/dist/litellm/tool-policy.d.ts +62 -0
  163. package/dist/litellm/tool-policy.d.ts.map +1 -0
  164. package/dist/litellm/toolset-form.d.ts +20 -0
  165. package/dist/litellm/toolset-form.d.ts.map +1 -0
  166. package/dist/litellm/toolset-operations.d.ts +39 -0
  167. package/dist/litellm/toolset-operations.d.ts.map +1 -0
  168. package/dist/litellm/toolset-types.d.ts +46 -0
  169. package/dist/litellm/toolset-types.d.ts.map +1 -0
  170. package/dist/litellm/toolset.d.ts +55 -0
  171. package/dist/litellm/toolset.d.ts.map +1 -0
  172. package/dist/openbao/auth-role-form.d.ts +9 -0
  173. package/dist/openbao/auth-role-form.d.ts.map +1 -1
  174. package/dist/openbao/auth-role-wire.d.ts.map +1 -1
  175. package/dist/openbao/fake-engines-roles.d.ts.map +1 -1
  176. package/dist/openbao/index.js +43 -6
  177. package/dist/openbao/index.js.map +5 -5
  178. package/dist/ownership/rows.d.ts +11 -0
  179. package/dist/ownership/rows.d.ts.map +1 -1
  180. package/dist/postgres/connection.d.ts +32 -2
  181. package/dist/postgres/connection.d.ts.map +1 -1
  182. package/dist/postgres/database-sql.d.ts +28 -9
  183. package/dist/postgres/database-sql.d.ts.map +1 -1
  184. package/dist/postgres/database.d.ts +1 -1
  185. package/dist/postgres/database.d.ts.map +1 -1
  186. package/dist/postgres/fake-grants-parse.d.ts +37 -0
  187. package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
  188. package/dist/postgres/fake-grants-read.d.ts +61 -0
  189. package/dist/postgres/fake-grants-read.d.ts.map +1 -0
  190. package/dist/postgres/fake-grants-sql.d.ts +46 -0
  191. package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
  192. package/dist/postgres/fake-grants-write.d.ts +29 -0
  193. package/dist/postgres/fake-grants-write.d.ts.map +1 -0
  194. package/dist/postgres/fake-role-sql.d.ts +40 -0
  195. package/dist/postgres/fake-role-sql.d.ts.map +1 -0
  196. package/dist/postgres/fake-schema-sql.d.ts +42 -0
  197. package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
  198. package/dist/postgres/fake-sql-parse.d.ts +23 -0
  199. package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
  200. package/dist/postgres/fake-sql-quote.d.ts +12 -0
  201. package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
  202. package/dist/postgres/fake-sql.d.ts +42 -0
  203. package/dist/postgres/fake-sql.d.ts.map +1 -1
  204. package/dist/postgres/grants-attrs.d.ts +115 -0
  205. package/dist/postgres/grants-attrs.d.ts.map +1 -0
  206. package/dist/postgres/grants-declare.d.ts +88 -0
  207. package/dist/postgres/grants-declare.d.ts.map +1 -0
  208. package/dist/postgres/grants-diff.d.ts +25 -0
  209. package/dist/postgres/grants-diff.d.ts.map +1 -0
  210. package/dist/postgres/grants-errors.d.ts +137 -0
  211. package/dist/postgres/grants-errors.d.ts.map +1 -0
  212. package/dist/postgres/grants-existence.d.ts +14 -0
  213. package/dist/postgres/grants-existence.d.ts.map +1 -0
  214. package/dist/postgres/grants-ops.d.ts +65 -0
  215. package/dist/postgres/grants-ops.d.ts.map +1 -0
  216. package/dist/postgres/grants-ownership.d.ts +18 -0
  217. package/dist/postgres/grants-ownership.d.ts.map +1 -0
  218. package/dist/postgres/grants-plan-restore.d.ts +22 -0
  219. package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
  220. package/dist/postgres/grants-plan.d.ts +65 -0
  221. package/dist/postgres/grants-plan.d.ts.map +1 -0
  222. package/dist/postgres/grants-read-defaults.d.ts +17 -0
  223. package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
  224. package/dist/postgres/grants-read.d.ts +77 -0
  225. package/dist/postgres/grants-read.d.ts.map +1 -0
  226. package/dist/postgres/grants-refuse.d.ts +25 -0
  227. package/dist/postgres/grants-refuse.d.ts.map +1 -0
  228. package/dist/postgres/grants-sql.d.ts +42 -0
  229. package/dist/postgres/grants-sql.d.ts.map +1 -0
  230. package/dist/postgres/grants-words.d.ts +29 -0
  231. package/dist/postgres/grants-words.d.ts.map +1 -0
  232. package/dist/postgres/grants.d.ts +37 -0
  233. package/dist/postgres/grants.d.ts.map +1 -0
  234. package/dist/postgres/index.d.ts +35 -8
  235. package/dist/postgres/index.d.ts.map +1 -1
  236. package/dist/postgres/index.js +2063 -39
  237. package/dist/postgres/index.js.map +47 -7
  238. package/dist/postgres/installed-classifier.d.ts +13 -0
  239. package/dist/postgres/installed-classifier.d.ts.map +1 -0
  240. package/dist/postgres/providers.d.ts +17 -7
  241. package/dist/postgres/providers.d.ts.map +1 -1
  242. package/dist/postgres/psql-executor.d.ts +25 -0
  243. package/dist/postgres/psql-executor.d.ts.map +1 -0
  244. package/dist/postgres/role-attrs.d.ts +109 -0
  245. package/dist/postgres/role-attrs.d.ts.map +1 -0
  246. package/dist/postgres/role-diff.d.ts +22 -0
  247. package/dist/postgres/role-diff.d.ts.map +1 -0
  248. package/dist/postgres/role-errors.d.ts +126 -0
  249. package/dist/postgres/role-errors.d.ts.map +1 -0
  250. package/dist/postgres/role-membership-sql.d.ts +75 -0
  251. package/dist/postgres/role-membership-sql.d.ts.map +1 -0
  252. package/dist/postgres/role-provider.d.ts +11 -0
  253. package/dist/postgres/role-provider.d.ts.map +1 -0
  254. package/dist/postgres/role-scram.d.ts +6 -0
  255. package/dist/postgres/role-scram.d.ts.map +1 -0
  256. package/dist/postgres/role-secrets.d.ts +30 -0
  257. package/dist/postgres/role-secrets.d.ts.map +1 -0
  258. package/dist/postgres/role-sql.d.ts +68 -0
  259. package/dist/postgres/role-sql.d.ts.map +1 -0
  260. package/dist/postgres/role.d.ts +57 -0
  261. package/dist/postgres/role.d.ts.map +1 -0
  262. package/dist/postgres/schema-assert.d.ts +50 -0
  263. package/dist/postgres/schema-assert.d.ts.map +1 -0
  264. package/dist/postgres/schema-attrs.d.ts +51 -0
  265. package/dist/postgres/schema-attrs.d.ts.map +1 -0
  266. package/dist/postgres/schema-delete.d.ts +28 -0
  267. package/dist/postgres/schema-delete.d.ts.map +1 -0
  268. package/dist/postgres/schema-diff.d.ts +14 -0
  269. package/dist/postgres/schema-diff.d.ts.map +1 -0
  270. package/dist/postgres/schema-errors.d.ts +139 -0
  271. package/dist/postgres/schema-errors.d.ts.map +1 -0
  272. package/dist/postgres/schema-identity.d.ts +8 -0
  273. package/dist/postgres/schema-identity.d.ts.map +1 -0
  274. package/dist/postgres/schema-reconcile.d.ts +12 -0
  275. package/dist/postgres/schema-reconcile.d.ts.map +1 -0
  276. package/dist/postgres/schema-sql.d.ts +45 -0
  277. package/dist/postgres/schema-sql.d.ts.map +1 -0
  278. package/dist/postgres/schema-test-kit.d.ts +67 -0
  279. package/dist/postgres/schema-test-kit.d.ts.map +1 -0
  280. package/dist/postgres/schema.d.ts +54 -0
  281. package/dist/postgres/schema.d.ts.map +1 -0
  282. package/dist/proxmox/ceph-flag-types.d.ts +57 -0
  283. package/dist/proxmox/ceph-flag-types.d.ts.map +1 -0
  284. package/dist/proxmox/ceph-flag-wire.d.ts +77 -0
  285. package/dist/proxmox/ceph-flag-wire.d.ts.map +1 -0
  286. package/dist/proxmox/ceph-flag.d.ts +15 -50
  287. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  288. package/dist/proxmox/ceph-osd-write.d.ts +10 -13
  289. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  290. package/dist/proxmox/index.js +806 -740
  291. package/dist/proxmox/index.js.map +9 -8
  292. package/dist/release/fake-engine.d.ts +10 -0
  293. package/dist/release/fake-engine.d.ts.map +1 -1
  294. package/dist/release/index.js +35 -1
  295. package/dist/release/index.js.map +3 -3
  296. package/dist/valkey/acl-attrs.d.ts +94 -0
  297. package/dist/valkey/acl-attrs.d.ts.map +1 -0
  298. package/dist/valkey/acl-compare.d.ts +28 -0
  299. package/dist/valkey/acl-compare.d.ts.map +1 -0
  300. package/dist/valkey/acl-connection.d.ts +6 -0
  301. package/dist/valkey/acl-connection.d.ts.map +1 -0
  302. package/dist/valkey/acl-form.d.ts +62 -0
  303. package/dist/valkey/acl-form.d.ts.map +1 -0
  304. package/dist/valkey/acl-managed.d.ts +4 -0
  305. package/dist/valkey/acl-managed.d.ts.map +1 -0
  306. package/dist/valkey/acl-ops.d.ts +37 -0
  307. package/dist/valkey/acl-ops.d.ts.map +1 -0
  308. package/dist/valkey/acl-profiles.d.ts +53 -0
  309. package/dist/valkey/acl-profiles.d.ts.map +1 -0
  310. package/dist/valkey/acl-reconcile.d.ts +26 -0
  311. package/dist/valkey/acl-reconcile.d.ts.map +1 -0
  312. package/dist/valkey/acl.d.ts +24 -0
  313. package/dist/valkey/acl.d.ts.map +1 -0
  314. package/dist/valkey/connection-service.d.ts +22 -0
  315. package/dist/valkey/connection-service.d.ts.map +1 -0
  316. package/dist/valkey/connection.d.ts +59 -0
  317. package/dist/valkey/connection.d.ts.map +1 -0
  318. package/dist/valkey/errors.d.ts +165 -0
  319. package/dist/valkey/errors.d.ts.map +1 -0
  320. package/dist/valkey/fake-acl.d.ts +29 -0
  321. package/dist/valkey/fake-acl.d.ts.map +1 -0
  322. package/dist/valkey/fake-valkey.d.ts +35 -0
  323. package/dist/valkey/fake-valkey.d.ts.map +1 -0
  324. package/dist/valkey/handler-test-fixture.d.ts +20 -0
  325. package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
  326. package/dist/valkey/index.d.ts +18 -0
  327. package/dist/valkey/index.d.ts.map +1 -0
  328. package/dist/valkey/index.js +964 -0
  329. package/dist/valkey/index.js.map +27 -0
  330. package/dist/valkey/instance-attrs.d.ts +46 -0
  331. package/dist/valkey/instance-attrs.d.ts.map +1 -0
  332. package/dist/valkey/instance-form.d.ts +22 -0
  333. package/dist/valkey/instance-form.d.ts.map +1 -0
  334. package/dist/valkey/instance.d.ts +48 -0
  335. package/dist/valkey/instance.d.ts.map +1 -0
  336. package/dist/valkey/provider-socket-fixture.d.ts +8 -0
  337. package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
  338. package/dist/valkey/providers.d.ts +16 -0
  339. package/dist/valkey/providers.d.ts.map +1 -0
  340. package/dist/valkey/resp.d.ts +38 -0
  341. package/dist/valkey/resp.d.ts.map +1 -0
  342. package/dist/valkey/transport-error.d.ts +36 -0
  343. package/dist/valkey/transport-error.d.ts.map +1 -0
  344. package/dist/valkey/transport.d.ts +50 -0
  345. package/dist/valkey/transport.d.ts.map +1 -0
  346. package/docs/litellm-access-group.md +105 -0
  347. package/docs/litellm-budget.md +55 -0
  348. package/docs/litellm-credential.md +60 -0
  349. package/docs/litellm-key-metadata.md +56 -0
  350. package/docs/litellm-key.md +194 -0
  351. package/docs/litellm-mcp.md +187 -0
  352. package/docs/litellm-model.md +111 -0
  353. package/docs/litellm-policy-attachment.md +86 -0
  354. package/docs/litellm-policy.md +103 -0
  355. package/docs/litellm-team.md +117 -0
  356. package/docs/litellm-tool-policy.md +90 -0
  357. package/docs/litellm-toolset.md +92 -0
  358. package/docs/litellm.md +16 -8
  359. package/docs/peers.md +15 -6
  360. package/docs/postgres-grants-example.md +55 -0
  361. package/docs/postgres-grants.md +157 -0
  362. package/docs/postgres-role.md +114 -0
  363. package/docs/postgres-schema.md +139 -0
  364. package/docs/postgres.md +39 -0
  365. package/docs/proxmox-sdk-migration.md +45 -0
  366. package/docs/valkey-transport.md +29 -0
  367. package/docs/valkey.md +187 -0
  368. package/package.json +7 -3
  369. package/src/litellm/access-group-form.ts +105 -0
  370. package/src/litellm/access-group-operations.ts +92 -0
  371. package/src/litellm/access-group-types.ts +49 -0
  372. package/src/litellm/access-group.test.ts +197 -0
  373. package/src/litellm/access-group.ts +151 -0
  374. package/src/litellm/budget-errors.ts +38 -0
  375. package/src/litellm/budget-form.ts +94 -0
  376. package/src/litellm/budget-operations.ts +51 -0
  377. package/src/litellm/budget.test.ts +105 -0
  378. package/src/litellm/budget.ts +127 -0
  379. package/src/litellm/credential-errors.ts +183 -0
  380. package/src/litellm/credential-form.test.ts +151 -0
  381. package/src/litellm/credential-form.ts +211 -0
  382. package/src/litellm/credential-guards.test.ts +241 -0
  383. package/src/litellm/credential-operations.ts +208 -0
  384. package/src/litellm/credential-recovery.test.ts +93 -0
  385. package/src/litellm/credential-rewrite.test.ts +164 -0
  386. package/src/litellm/credential-rewrite.ts +50 -0
  387. package/src/litellm/credential-types.ts +117 -0
  388. package/src/litellm/credential-values.ts +94 -0
  389. package/src/litellm/credential.test.ts +218 -0
  390. package/src/litellm/credential.ts +227 -0
  391. package/src/litellm/fake-access-group-litellm.ts +127 -0
  392. package/src/litellm/fake-credential-litellm.ts +216 -0
  393. package/src/litellm/fake-keys.ts +190 -0
  394. package/src/litellm/fake-litellm.ts +66 -7
  395. package/src/litellm/fake-mcp-litellm.ts +214 -0
  396. package/src/litellm/fake-model-litellm-post-update.ts +103 -0
  397. package/src/litellm/fake-model-litellm.ts +233 -0
  398. package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
  399. package/src/litellm/fake-policy-litellm.ts +186 -0
  400. package/src/litellm/fake-registry-base.ts +69 -0
  401. package/src/litellm/fake-stack.ts +17 -1
  402. package/src/litellm/fake-team-litellm.ts +229 -0
  403. package/src/litellm/fake-tool-litellm.ts +88 -0
  404. package/src/litellm/fake-toolset-litellm.ts +110 -0
  405. package/src/litellm/index.ts +153 -0
  406. package/src/litellm/key-delete.test.ts +212 -0
  407. package/src/litellm/key-errors.ts +241 -0
  408. package/src/litellm/key-form.ts +200 -0
  409. package/src/litellm/key-harness.ts +121 -0
  410. package/src/litellm/key-metadata-errors.ts +49 -0
  411. package/src/litellm/key-metadata.test.ts +156 -0
  412. package/src/litellm/key-metadata.ts +74 -0
  413. package/src/litellm/key-operations.ts +184 -0
  414. package/src/litellm/key-rotation.test.ts +110 -0
  415. package/src/litellm/key-scope.test.ts +135 -0
  416. package/src/litellm/key-secret.test.ts +248 -0
  417. package/src/litellm/key-secret.ts +137 -0
  418. package/src/litellm/key-transport.test.ts +166 -0
  419. package/src/litellm/key.test.ts +231 -0
  420. package/src/litellm/key.ts +213 -0
  421. package/src/litellm/mcp-server-adopt.test.ts +86 -0
  422. package/src/litellm/mcp-server-alias.test.ts +184 -0
  423. package/src/litellm/mcp-server-credential.ts +85 -0
  424. package/src/litellm/mcp-server-errors.ts +141 -0
  425. package/src/litellm/mcp-server-exports.test.ts +15 -0
  426. package/src/litellm/mcp-server-form.test.ts +241 -0
  427. package/src/litellm/mcp-server-form.ts +233 -0
  428. package/src/litellm/mcp-server-handlers.test.ts +150 -0
  429. package/src/litellm/mcp-server-locate.ts +66 -0
  430. package/src/litellm/mcp-server-operations.ts +111 -0
  431. package/src/litellm/mcp-server-registry.test.ts +146 -0
  432. package/src/litellm/mcp-server-retype.test.ts +114 -0
  433. package/src/litellm/mcp-server-shadow.test.ts +91 -0
  434. package/src/litellm/mcp-server-shadow.ts +45 -0
  435. package/src/litellm/mcp-server-tools.test.ts +85 -0
  436. package/src/litellm/mcp-server-types.ts +143 -0
  437. package/src/litellm/mcp-server-url.ts +66 -0
  438. package/src/litellm/mcp-server.test.ts +213 -0
  439. package/src/litellm/mcp-server.ts +225 -0
  440. package/src/litellm/model-claim.ts +69 -0
  441. package/src/litellm/model-credential.ts +45 -0
  442. package/src/litellm/model-errors.ts +168 -0
  443. package/src/litellm/model-foreign-row.test.ts +173 -0
  444. package/src/litellm/model-form.test.ts +228 -0
  445. package/src/litellm/model-form.ts +223 -0
  446. package/src/litellm/model-locate.test.ts +128 -0
  447. package/src/litellm/model-locate.ts +67 -0
  448. package/src/litellm/model-operations.test.ts +93 -0
  449. package/src/litellm/model-operations.ts +146 -0
  450. package/src/litellm/model-params-preserve.test.ts +119 -0
  451. package/src/litellm/model-recovery.test.ts +57 -0
  452. package/src/litellm/model-types.ts +112 -0
  453. package/src/litellm/model.test.ts +222 -0
  454. package/src/litellm/model.ts +237 -0
  455. package/src/litellm/operations.ts +1 -1
  456. package/src/litellm/policy-attachment-form.ts +103 -0
  457. package/src/litellm/policy-attachment-operations.ts +74 -0
  458. package/src/litellm/policy-attachment-types.ts +48 -0
  459. package/src/litellm/policy-attachment.test.ts +198 -0
  460. package/src/litellm/policy-attachment.ts +178 -0
  461. package/src/litellm/policy-form.ts +122 -0
  462. package/src/litellm/policy-operations.ts +112 -0
  463. package/src/litellm/policy-types.ts +58 -0
  464. package/src/litellm/policy.test.ts +214 -0
  465. package/src/litellm/policy.ts +146 -0
  466. package/src/litellm/providers.ts +25 -1
  467. package/src/litellm/registry-errors.ts +88 -0
  468. package/src/litellm/registry-exports.test.ts +66 -0
  469. package/src/litellm/registry-support.ts +109 -0
  470. package/src/litellm/team-form.ts +140 -0
  471. package/src/litellm/team-members.test.ts +150 -0
  472. package/src/litellm/team-members.ts +58 -0
  473. package/src/litellm/team-operations.ts +90 -0
  474. package/src/litellm/team-permission.ts +159 -0
  475. package/src/litellm/team-read.test.ts +89 -0
  476. package/src/litellm/team-types.ts +106 -0
  477. package/src/litellm/team.test.ts +206 -0
  478. package/src/litellm/team.ts +159 -0
  479. package/src/litellm/tool-policy-form.ts +94 -0
  480. package/src/litellm/tool-policy-operations.ts +58 -0
  481. package/src/litellm/tool-policy-types.ts +48 -0
  482. package/src/litellm/tool-policy.test.ts +172 -0
  483. package/src/litellm/tool-policy.ts +125 -0
  484. package/src/litellm/toolset-form.ts +104 -0
  485. package/src/litellm/toolset-operations.ts +90 -0
  486. package/src/litellm/toolset-types.ts +47 -0
  487. package/src/litellm/toolset.test.ts +198 -0
  488. package/src/litellm/toolset.ts +151 -0
  489. package/src/openbao/auth-role-form.test.ts +37 -0
  490. package/src/openbao/auth-role-form.ts +12 -1
  491. package/src/openbao/auth-role-wire.test.ts +1 -0
  492. package/src/openbao/auth-role-wire.ts +13 -1
  493. package/src/openbao/distilled-retry.test.ts +1 -0
  494. package/src/openbao/fake-engines-roles.ts +7 -1
  495. package/src/ownership/ownership.test.ts +33 -1
  496. package/src/ownership/rows.ts +53 -0
  497. package/src/postgres/connection.ts +72 -3
  498. package/src/postgres/database-bigint-serialization.test.ts +1 -0
  499. package/src/postgres/database-refusals.test.ts +2 -2
  500. package/src/postgres/database-sql.ts +40 -12
  501. package/src/postgres/database.ts +3 -2
  502. package/src/postgres/fake-grants-parse.ts +189 -0
  503. package/src/postgres/fake-grants-read.ts +250 -0
  504. package/src/postgres/fake-grants-sql.ts +207 -0
  505. package/src/postgres/fake-grants-write.ts +90 -0
  506. package/src/postgres/fake-role-sql.ts +220 -0
  507. package/src/postgres/fake-schema-semantics.test.ts +36 -0
  508. package/src/postgres/fake-schema-sql.ts +146 -0
  509. package/src/postgres/fake-sql-parse.ts +86 -0
  510. package/src/postgres/fake-sql-quote.ts +36 -0
  511. package/src/postgres/fake-sql.ts +161 -46
  512. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
  513. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
  514. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
  515. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
  516. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
  517. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
  518. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
  519. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
  520. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
  521. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
  522. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
  523. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
  524. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
  525. package/src/postgres/grants-acl.test.ts +61 -0
  526. package/src/postgres/grants-attrs.ts +185 -0
  527. package/src/postgres/grants-database.test.ts +158 -0
  528. package/src/postgres/grants-declare.ts +172 -0
  529. package/src/postgres/grants-delete-proof.test.ts +154 -0
  530. package/src/postgres/grants-diff.ts +101 -0
  531. package/src/postgres/grants-errors.ts +215 -0
  532. package/src/postgres/grants-existence-guards.test.ts +113 -0
  533. package/src/postgres/grants-existence.ts +101 -0
  534. package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
  535. package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
  536. package/src/postgres/grants-lifecycle.test.ts +181 -0
  537. package/src/postgres/grants-ops.ts +229 -0
  538. package/src/postgres/grants-owner-revoke.test.ts +121 -0
  539. package/src/postgres/grants-ownership.ts +49 -0
  540. package/src/postgres/grants-plan-collateral.test.ts +202 -0
  541. package/src/postgres/grants-plan-diff.test.ts +204 -0
  542. package/src/postgres/grants-plan-restore.ts +43 -0
  543. package/src/postgres/grants-plan-revocations.test.ts +69 -0
  544. package/src/postgres/grants-plan.test.ts +148 -0
  545. package/src/postgres/grants-plan.ts +245 -0
  546. package/src/postgres/grants-provenance.test.ts +134 -0
  547. package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
  548. package/src/postgres/grants-read-absent.test.ts +91 -0
  549. package/src/postgres/grants-read-defaults.ts +51 -0
  550. package/src/postgres/grants-read.ts +250 -0
  551. package/src/postgres/grants-refusals.test.ts +136 -0
  552. package/src/postgres/grants-refuse.ts +119 -0
  553. package/src/postgres/grants-relkind-wire.test.ts +111 -0
  554. package/src/postgres/grants-repair-plan.test.ts +201 -0
  555. package/src/postgres/grants-sql.test.ts +128 -0
  556. package/src/postgres/grants-sql.ts +144 -0
  557. package/src/postgres/grants-words.ts +34 -0
  558. package/src/postgres/grants.ts +110 -0
  559. package/src/postgres/index.ts +137 -7
  560. package/src/postgres/installed-classifier.ts +36 -0
  561. package/src/postgres/providers.ts +44 -7
  562. package/src/postgres/psql-executor-escaping.test.ts +67 -0
  563. package/src/postgres/psql-executor.test.ts +167 -0
  564. package/src/postgres/psql-executor.ts +170 -0
  565. package/src/postgres/role-adopt.test.ts +98 -0
  566. package/src/postgres/role-attrs.ts +134 -0
  567. package/src/postgres/role-diff.ts +89 -0
  568. package/src/postgres/role-errors.ts +198 -0
  569. package/src/postgres/role-guard.test.ts +60 -0
  570. package/src/postgres/role-identity.test.ts +185 -0
  571. package/src/postgres/role-lifecycle.test.ts +228 -0
  572. package/src/postgres/role-membership-sql.ts +198 -0
  573. package/src/postgres/role-password.test.ts +158 -0
  574. package/src/postgres/role-privilege.test.ts +80 -0
  575. package/src/postgres/role-provenance.test.ts +200 -0
  576. package/src/postgres/role-provider.ts +104 -0
  577. package/src/postgres/role-refusals.test.ts +250 -0
  578. package/src/postgres/role-scram.test.ts +38 -0
  579. package/src/postgres/role-scram.ts +38 -0
  580. package/src/postgres/role-secrets.ts +46 -0
  581. package/src/postgres/role-sql.ts +211 -0
  582. package/src/postgres/role-valid-until.test.ts +68 -0
  583. package/src/postgres/role.ts +218 -0
  584. package/src/postgres/schema-assert.ts +139 -0
  585. package/src/postgres/schema-attrs.ts +71 -0
  586. package/src/postgres/schema-delete-proofs.test.ts +192 -0
  587. package/src/postgres/schema-delete.ts +96 -0
  588. package/src/postgres/schema-diff.ts +44 -0
  589. package/src/postgres/schema-drop-2bp01.test.ts +146 -0
  590. package/src/postgres/schema-errors.ts +209 -0
  591. package/src/postgres/schema-handlers.test.ts +193 -0
  592. package/src/postgres/schema-identity.ts +39 -0
  593. package/src/postgres/schema-lifecycle.test.ts +246 -0
  594. package/src/postgres/schema-race.test.ts +70 -0
  595. package/src/postgres/schema-reconcile.ts +100 -0
  596. package/src/postgres/schema-refusals.test.ts +144 -0
  597. package/src/postgres/schema-socket.test.ts +161 -0
  598. package/src/postgres/schema-sql.ts +130 -0
  599. package/src/postgres/schema-takeover.test.ts +149 -0
  600. package/src/postgres/schema-test-kit.ts +85 -0
  601. package/src/postgres/schema.ts +130 -0
  602. package/src/proxmox/ceph-flag-types.ts +70 -0
  603. package/src/proxmox/ceph-flag-wire.test.ts +72 -0
  604. package/src/proxmox/ceph-flag-wire.ts +123 -0
  605. package/src/proxmox/ceph-flag.ts +77 -130
  606. package/src/proxmox/ceph-osd-write.ts +10 -13
  607. package/src/release/binary-alias.test.ts +3 -3
  608. package/src/release/binary-claims.test.ts +3 -3
  609. package/src/release/binary-directory-umask.test.ts +65 -0
  610. package/src/release/fake-engine.ts +15 -0
  611. package/src/valkey/acl-attrs.ts +98 -0
  612. package/src/valkey/acl-compare.ts +57 -0
  613. package/src/valkey/acl-connection.ts +13 -0
  614. package/src/valkey/acl-delete.test.ts +127 -0
  615. package/src/valkey/acl-form.ts +239 -0
  616. package/src/valkey/acl-managed.ts +13 -0
  617. package/src/valkey/acl-ops.ts +122 -0
  618. package/src/valkey/acl-ownership.test.ts +118 -0
  619. package/src/valkey/acl-prefix.test.ts +38 -0
  620. package/src/valkey/acl-profiles.ts +81 -0
  621. package/src/valkey/acl-reconcile.ts +180 -0
  622. package/src/valkey/acl-reserved.test.ts +69 -0
  623. package/src/valkey/acl-revocation.test.ts +94 -0
  624. package/src/valkey/acl-seat-prefix.test.ts +111 -0
  625. package/src/valkey/acl-validation.test.ts +54 -0
  626. package/src/valkey/acl.test.ts +215 -0
  627. package/src/valkey/acl.ts +169 -0
  628. package/src/valkey/connection-service.ts +46 -0
  629. package/src/valkey/connection.ts +180 -0
  630. package/src/valkey/errors.ts +239 -0
  631. package/src/valkey/fake-acl.ts +128 -0
  632. package/src/valkey/fake-valkey.ts +224 -0
  633. package/src/valkey/handler-test-fixture.ts +43 -0
  634. package/src/valkey/handlers.test.ts +205 -0
  635. package/src/valkey/index.ts +54 -0
  636. package/src/valkey/instance-attrs.ts +48 -0
  637. package/src/valkey/instance-form.ts +104 -0
  638. package/src/valkey/instance.test.ts +108 -0
  639. package/src/valkey/instance.ts +160 -0
  640. package/src/valkey/provider-socket-fixture.ts +71 -0
  641. package/src/valkey/providers.test.ts +129 -0
  642. package/src/valkey/providers.ts +21 -0
  643. package/src/valkey/resp.ts +212 -0
  644. package/src/valkey/transport-bounds.test.ts +150 -0
  645. package/src/valkey/transport-error.ts +37 -0
  646. package/src/valkey/transport.test.ts +158 -0
  647. package/src/valkey/transport.ts +109 -0
  648. package/src/valkey/upstream-bounds.test.ts +14 -0
@@ -0,0 +1,93 @@
1
+ /** A failed rewrite must describe the completed DELETE and recover on the next real deploy. */
2
+ import { expect, test } from 'bun:test';
3
+ import * as Effect from 'effect/Effect';
4
+ import { type CredentialProps, LiteLLMCredential, credentialHandlers } from './credential.ts';
5
+ import { startFakeCredentialLitellm } from './fake-credential-litellm.ts';
6
+ import { fakeStack, writesOf } from './fake-stack.ts';
7
+ import { FAKE_BASE } from './fake-litellm.ts';
8
+ import { FAKE_KEY, MASTER_KEY, failureOf, newFake, runAgainst, withEnv } from './key-harness.ts';
9
+
10
+ const variable = 'FAKE_RECOVERY_KEY';
11
+ const props: CredentialProps = {
12
+ credentialName: 'recovery',
13
+ credentialInfo: { note: 'search' },
14
+ credentialValues: { api_key: { fromEnv: variable } },
15
+ };
16
+ const original = { ...props, credentialInfo: { ...props.credentialInfo, extra: 'remove' } };
17
+ const declare = (news: CredentialProps) =>
18
+ Effect.gen(function* () {
19
+ yield* LiteLLMCredential('Cred', news);
20
+ });
21
+
22
+ for (const mode of ['transport', 'forbidden', 'validation'] as const) {
23
+ test(`a rewrite POST ${mode} failure reports DELETE and the next deploy recreates`, async () => {
24
+ const fake = startFakeCredentialLitellm({ masterKey: MASTER_KEY });
25
+ let failPost = false;
26
+ let postsFailed = 0;
27
+ const fetch = (async (input, init) => {
28
+ const request =
29
+ input instanceof Request ? new Request(input, init) : new Request(String(input), init);
30
+ if (
31
+ failPost &&
32
+ request.method === 'POST' &&
33
+ new URL(request.url).pathname === '/credentials'
34
+ ) {
35
+ postsFailed += 1;
36
+ if (mode === 'transport') throw new TypeError('connection dropped');
37
+ return new Response(JSON.stringify({ detail: 'replacement rejected' }), {
38
+ status: mode === 'forbidden' ? 403 : 422,
39
+ headers: { 'content-type': 'application/json' },
40
+ });
41
+ }
42
+ return fake.fetch(request);
43
+ }) as typeof globalThis.fetch;
44
+ const engine = fakeStack({ apiKey: MASTER_KEY, baseUrl: FAKE_BASE }, fetch, 'Recovery', {
45
+ noRetry: true,
46
+ });
47
+ await withEnv({ [variable]: FAKE_KEY }, async () => {
48
+ await engine.deploy(declare(original));
49
+ failPost = true;
50
+ const message = await failureOf(engine.deploy(declare(props)));
51
+ expect(message).toContain('DELETE already ran');
52
+ expect(message).toContain('next deploy recreates');
53
+ expect(message.includes(FAKE_KEY)).toBe(false);
54
+ expect(postsFailed).toBe(1);
55
+ expect(fake.rows()).toHaveLength(0);
56
+ expect(writesOf(fake.requests())).toEqual([
57
+ 'POST /credentials',
58
+ 'DELETE /credentials/recovery',
59
+ ]);
60
+ failPost = false;
61
+ await engine.deploy(declare(props));
62
+ expect(fake.rows()).toHaveLength(1);
63
+ expect(fake.rows()[0]?.credential_info).toEqual(props.credentialInfo);
64
+ expect(await engine.deploy(declare(props))).toEqual({ Cred: 'noop' });
65
+ expect(engine.snapshot().includes(FAKE_KEY)).toBe(false);
66
+
67
+ // The same failure is catchable in the error channel, with no request or cause retained.
68
+ await engine.deploy(declare(original));
69
+ failPost = true;
70
+ const error = await runAgainst(
71
+ { ...newFake(), fetch },
72
+ credentialHandlers
73
+ .reconcile({
74
+ fqn: 'Cred',
75
+ instanceId: 'i-1',
76
+ news: props,
77
+ output: {
78
+ credentialName: props.credentialName,
79
+ credentialInfo: original.credentialInfo,
80
+ valuesSeal: '',
81
+ },
82
+ })
83
+ .pipe(
84
+ Effect.catchTag('LitellmCredentialRewriteError', (failure) => Effect.succeed(failure)),
85
+ ),
86
+ );
87
+ expect('_tag' in error && error._tag).toBe('LitellmCredentialRewriteError');
88
+ expect(JSON.stringify(error).includes(FAKE_KEY)).toBe(false);
89
+ expect('cause' in error).toBe(false);
90
+ expect('request' in error).toBe(false);
91
+ });
92
+ });
93
+ }
@@ -0,0 +1,164 @@
1
+ /** Removal needs both LiteLLM stores to converge; preflight must finish before DELETE. */
2
+ import { afterEach, beforeEach, expect, test } from 'bun:test';
3
+ import { credentials } from '@distilled.cloud/litellm/Credentials';
4
+ import * as Effect from 'effect/Effect';
5
+ import * as FetchHttpClient from 'effect/unstable/http/FetchHttpClient';
6
+ import { type CredentialProps, LiteLLMCredential, credentialHandlers } from './credential.ts';
7
+ import { credentialRow, startFakeCredentialLitellm } from './fake-credential-litellm.ts';
8
+ import { FAKE_BASE } from './fake-litellm.ts';
9
+ import { fakeStack, writesOf } from './fake-stack.ts';
10
+
11
+ const variable = 'FAKE_REWRITE_KEY';
12
+ const creds = { apiKey: 'FAKE-master', baseUrl: FAKE_BASE };
13
+ const props: CredentialProps = {
14
+ credentialName: 'FAKE_api',
15
+ credentialInfo: { note: 'search' },
16
+ credentialValues: { api_key: { fromEnv: variable } },
17
+ };
18
+ const declare = (news: CredentialProps) =>
19
+ Effect.gen(function* () {
20
+ yield* LiteLLMCredential('Cred', news);
21
+ });
22
+ const extraValues = {
23
+ ...props,
24
+ credentialValues: {
25
+ ...props.credentialValues,
26
+ api_base: { fromEnv: variable },
27
+ },
28
+ };
29
+ const extraInfo = { ...props, credentialInfo: { ...props.credentialInfo, team: 'a' } };
30
+ const setup = () => {
31
+ const fake = startFakeCredentialLitellm({ masterKey: creds.apiKey });
32
+ return { fake, engine: fakeStack(creds, fake.fetch) };
33
+ };
34
+ beforeEach(() => {
35
+ process.env[variable] = 'FAKE-rewrite-value';
36
+ });
37
+ afterEach(() => {
38
+ delete process.env[variable];
39
+ delete process.env.DISTILLED_DEBUG_HTTP;
40
+ });
41
+
42
+ test('dropping a value key rewrites the row, removes it from DB and memory, then noops', async () => {
43
+ const { fake, engine } = setup();
44
+ await engine.deploy(declare(extraValues));
45
+ const before = fake.requests().length;
46
+ expect(await engine.deploy(declare(props))).toEqual({ Cred: 'update' });
47
+ expect(writesOf(fake.requests().slice(before))).toEqual([
48
+ 'DELETE /credentials/FAKE_api',
49
+ 'POST /credentials',
50
+ ]);
51
+ expect(Object.keys(fake.rows()[0]?.credential_values as object)).toEqual(['api_key']);
52
+ expect(await engine.deploy(declare(props))).toEqual({ Cred: 'noop' });
53
+ expect(engine.snapshot().includes('FAKE-rewrite-value')).toBe(false);
54
+ });
55
+
56
+ for (const [kind, original] of [
57
+ ['value', extraValues],
58
+ ['info', extraInfo],
59
+ ] as const) {
60
+ test(`dropping a ${kind} key with a missing value refuses before DELETE`, async () => {
61
+ const { fake, engine } = setup();
62
+ await engine.deploy(declare(original));
63
+ const before = fake.requests().length;
64
+ delete process.env[variable];
65
+ await expect(engine.deploy(declare(props))).rejects.toThrow(variable);
66
+ expect(writesOf(fake.requests().slice(before))).toEqual([]);
67
+ expect(fake.rows()).toHaveLength(1);
68
+ });
69
+
70
+ test(`dropping a ${kind} key under debug logging refuses before any reconcile request`, async () => {
71
+ const { fake, engine } = setup();
72
+ await engine.deploy(declare(original));
73
+ // The refusal is before any observation or write, so even stale state cannot bypass it.
74
+ const before = fake.requests().length;
75
+ process.env.DISTILLED_DEBUG_HTTP = '1';
76
+ const error = await Effect.runPromise(
77
+ credentialHandlers
78
+ .reconcile({
79
+ fqn: 'Cred',
80
+ instanceId: 'i-1',
81
+ news: props,
82
+ output: {
83
+ credentialName: props.credentialName,
84
+ credentialInfo: original.credentialInfo ?? {},
85
+ valuesSeal: '',
86
+ },
87
+ })
88
+ .pipe(
89
+ Effect.catchTag('LitellmCredentialDebugLoggingError', (failure) =>
90
+ Effect.succeed(failure._tag),
91
+ ),
92
+ Effect.provide(FetchHttpClient.layer),
93
+ Effect.provideService(FetchHttpClient.Fetch, fake.fetch),
94
+ Effect.provide(credentials(creds)),
95
+ ),
96
+ );
97
+ expect(error).toBe('LitellmCredentialDebugLoggingError');
98
+ expect(fake.requests()).toHaveLength(before);
99
+ expect(fake.rows()).toHaveLength(1);
100
+ });
101
+ }
102
+
103
+ test('adoption deliberately removes undeclared info keys, including withheld sensitive names', async () => {
104
+ const fake = startFakeCredentialLitellm({
105
+ masterKey: creds.apiKey,
106
+ seed: [
107
+ credentialRow({
108
+ credential_name: props.credentialName,
109
+ credential_info: { note: 'search', foreign: 'a', secret: 'FAKE-withheld' },
110
+ credential_values: { api_key: 'FAKE-existing' },
111
+ }),
112
+ ],
113
+ });
114
+ const engine = fakeStack(creds, fake.fetch);
115
+ await engine.deploy(declare(props), { adopt: true });
116
+ expect(writesOf(fake.requests())).toEqual(['DELETE /credentials/FAKE_api', 'POST /credentials']);
117
+ expect(Object.keys(fake.rows()[0]?.credential_info as object)).toEqual(['note']);
118
+ expect(engine.snapshot().includes('FAKE-withheld')).toBe(false);
119
+ expect(await engine.deploy(declare(props))).toEqual({ Cred: 'noop' });
120
+ });
121
+
122
+ test('PATCH records a complete intended info map and the required body name', async () => {
123
+ const { fake, engine } = setup();
124
+ await engine.deploy(declare(extraInfo));
125
+ const news = { ...extraInfo, credentialInfo: { note: 'changed', team: 'a' } };
126
+ await engine.deploy(declare(news));
127
+ expect(fake.bodies()[1]?.credential_name).toBe(props.credentialName);
128
+ expect(fake.bodies()[1]?.credential_info).toEqual(news.credentialInfo);
129
+ expect(fake.rows()[0]?.credential_info).toEqual(news.credentialInfo);
130
+ expect(await engine.deploy(declare(news))).toEqual({ Cred: 'noop' });
131
+ });
132
+
133
+ test('the fake rejects a PATCH with no body credential_name, matching UpdateCredentialItem', async () => {
134
+ const { fake, engine } = setup();
135
+ await engine.deploy(declare(props));
136
+ const response = await fake.fetch(`${FAKE_BASE}/credentials/FAKE_api`, {
137
+ method: 'PATCH',
138
+ headers: { authorization: `Bearer ${creds.apiKey}`, 'content-type': 'application/json' },
139
+ body: JSON.stringify({ credential_info: { note: 'changed' } }),
140
+ });
141
+ expect(response.status).toBe(422);
142
+ expect(fake.bodies()).toHaveLength(2);
143
+ expect(fake.rows()[0]?.credential_info).toEqual(props.credentialInfo);
144
+ });
145
+
146
+ test('a debug-enabled plan refuses before the read response can print unmasked values', async () => {
147
+ const { fake, engine } = setup();
148
+ await engine.deploy(declare(extraValues));
149
+ const before = fake.requests().length;
150
+ const printed: string[] = [];
151
+ const original = console.error;
152
+ console.error = (...args: unknown[]) => {
153
+ printed.push(args.join(' '));
154
+ };
155
+ try {
156
+ process.env.DISTILLED_DEBUG_HTTP = '1';
157
+ await expect(engine.deploy(declare(props))).rejects.toThrow('DISTILLED_DEBUG_HTTP');
158
+ } finally {
159
+ console.error = original;
160
+ }
161
+ expect(printed.join('\n').includes('FAKE-rewrite-value')).toBe(false);
162
+ expect(fake.requests()).toHaveLength(before);
163
+ expect(fake.rows()).toHaveLength(1);
164
+ });
@@ -0,0 +1,50 @@
1
+ /** Whole-row removal needs a diagnostic that remembers DELETE succeeded before POST failed. */
2
+ import type { API_ERRORS } from '@distilled.cloud/litellm/Errors';
3
+ import type * as credentials from '@distilled.cloud/litellm/credential_management';
4
+ import * as Effect from 'effect/Effect';
5
+ import {
6
+ LitellmCredentialRewriteError,
7
+ type LitellmCredentialTransportError,
8
+ } from './credential-errors.ts';
9
+ import { createCredential, deleteCredential } from './credential-operations.ts';
10
+ import type { LitellmOpContext } from './operations.ts';
11
+
12
+ export const rewriteCredential = (body: credentials.CreateCredentialCredentialsPostRequest) =>
13
+ Effect.gen(function* () {
14
+ const credentialName = body.credential_name;
15
+ yield* deleteCredential(credentialName);
16
+ // The SDK's status fallback can emit every API_ERRORS member, including statuses absent
17
+ // from this operation's generated union. Keep only its tag, never a body/message/cause.
18
+ const post: Effect.Effect<
19
+ void,
20
+ | credentials.CreateCredentialCredentialsPostError
21
+ | LitellmCredentialTransportError
22
+ | InstanceType<(typeof API_ERRORS)[number]>,
23
+ LitellmOpContext
24
+ > = createCredential(body);
25
+ yield* post.pipe(
26
+ Effect.catchTag(
27
+ [
28
+ 'BadGateway',
29
+ 'BadRequest',
30
+ 'ConfigError',
31
+ 'Conflict',
32
+ 'Forbidden',
33
+ 'GatewayTimeout',
34
+ 'HttpClientError',
35
+ 'InternalServerError',
36
+ 'LitellmCredentialTransportError',
37
+ 'LitellmParseError',
38
+ 'Locked',
39
+ 'NotFound',
40
+ 'ServiceUnavailable',
41
+ 'TooManyRequests',
42
+ 'Unauthorized',
43
+ 'UnknownLitellmError',
44
+ 'UnprocessableEntity',
45
+ ],
46
+ (error) =>
47
+ Effect.fail(new LitellmCredentialRewriteError({ credentialName, reason: error._tag })),
48
+ ),
49
+ );
50
+ });
@@ -0,0 +1,117 @@
1
+ /**
2
+ * What `LiteLLM.Credential` declares (props) and what is remembered about it (attributes).
3
+ *
4
+ * ⛔ NO CREDENTIAL VALUE IS EVER A PROP OR AN ATTRIBUTE (S25). Alchemy persists props AND
5
+ * attributes unencrypted (`StateEncoding.ts` writes a `Redacted` value's inner string beside
6
+ * the tag — `secrets/write-only.ts`, measured on alchemy 2.0.0-beta.79), and LiteLLM stores a
7
+ * credential's values ENCRYPTED in its database while the reads answer them MASKED, so a value
8
+ * the declaration holds is `{ fromEnv: 'NAME' }` — NAME lands in state, and the value is read
9
+ * from the DEPLOYING process's environment only when a write is being made
10
+ * (`credential-values.ts`, the same shape `McpServerProps.authValue` uses). Unlike a model
11
+ * deployment's `os.environ/NAME` reference (the PROXY resolves that in its own environment),
12
+ * the credential table stores LITERAL values — measured in the live 1.103.0 container
13
+ * (`credential_endpoints/endpoints.py`: `create_credential` encrypts the body's
14
+ * `credential_values` before the insert, `CredentialsRepository.create`) — so the proxy could
15
+ * not resolve a reference here even if one were sent.
16
+ * ⛔ THE LIVE ROW'S MASKED VALUES ARE NEVER MIRRORED INTO ATTRIBUTES. Both reads answer
17
+ * `credential_values` with every SENSITIVE-keyed value masked (the vendor's own rule,
18
+ * `_get_masked_values` in `litellm_logging.py`: a key matching `authorization`, `token`, `key`,
19
+ * `secret`, `vertex_credentials`, `credentials`, `password` or `passwd` — substring,
20
+ * case-insensitive — answers `v[:2] + "****" + v[-2:]` for a string longer than four
21
+ * characters, `*****` otherwise; non-string values and non-sensitive keys answer in full).
22
+ * A masked fragment (`sk****45`) is a PARTIAL SECRET, so `toAttributes` copies no
23
+ * `credential_values` entry at all (`credential-form.ts`); what was last written is remembered
24
+ * as the digest of the values this process RESOLVED, `valuesSeal` — never the values.
25
+ * ⚠️ `credential_info` IS THE COMPLETE INTENDED MAP, INCLUDING ON ADOPTION. Measured in
26
+ * LiteLLM 1.103.0 `credential_endpoints/endpoints.py:314-319`: a nonempty PATCH normally resets
27
+ * the DB info map (except when it contains a literal `credential_info` key); an empty patch
28
+ * leaves it alone. Memory only merges (:385-387), retaining removed keys until restart.
29
+ * Therefore removing any live info key requires a rewrite; every PATCH sends the full map.
30
+ * Sensitive info keys are refused at plan time because the vendor returns info UNMASKED.
31
+ * Reads retain their NAMES only, so removal can converge without persisting their values.
32
+ */
33
+ import type { FromEnv } from '../secrets/write-only.ts';
34
+
35
+ /**
36
+ * The credential's name — its identity in the vendor's table (a unique column, enforced by the
37
+ * database, `schema.prisma`'s `Credentials` model). ADOPTED: the live row whose `credential_name`
38
+ * equals it. ⛔ A RENAMED ROW IS A DIFFERENT CREDENTIAL: the name is the only address the vendor's
39
+ * routes have, so a changed `credentialName` plans a REPLACE — the old row survives under the
40
+ * resource's default `retain` policy, never renamed in place.
41
+ */
42
+ export interface CredentialProps {
43
+ readonly credentialName: string;
44
+
45
+ /**
46
+ * Free-form metadata stored beside the values (`credential_info` in the vendor's row), compared
47
+ * as the complete intended map with canonical-JSON deep equality (omitted means empty). ⛔ Refused for a key matching the vendor's
48
+ * own sensitive-key list: those belong in `credentialValues`, where LiteLLM stores them
49
+ * encrypted and answers them masked — in `credential_info` they would be stored in clear.
50
+ */
51
+ readonly credentialInfo?: Readonly<Record<string, unknown>>;
52
+
53
+ /**
54
+ * The credential's values, each declared as `{ fromEnv: 'NAME' }` naming the environment
55
+ * variable the DEPLOYING process reads at call time. AT LEAST ONE is required: LiteLLM's create
56
+ * model refuses a body whose `credential_values` and `model_id` are both empty
57
+ * (`models/credentials.py`'s `CreateCredentialItem` validator → 422), and `model_id` — which
58
+ * would copy a deployment's values — is not modelled here, so a value-less declaration has
59
+ * nothing to write. A value that never resolves in a plan-only environment never drifts
60
+ * (credential-values.ts); one that resolves is SENT as the literal the proxy stores encrypted.
61
+ */
62
+ readonly credentialValues: Readonly<Record<string, FromEnv>>;
63
+ }
64
+
65
+ export interface CredentialAttributes {
66
+ readonly credentialName: string;
67
+
68
+ /**
69
+ * The row's `credential_info` as the read answers it, minus any SENSITIVE-KEYED entry — those
70
+ * would mirror a clear secret into Alchemy's state and are skipped (`toAttributes`). The digest
71
+ * comparison removes undeclared live keys, including on adoption (credential-form.ts).
72
+ */
73
+ readonly credentialInfo: Readonly<Record<string, unknown>>;
74
+
75
+ /**
76
+ * `scrypt:<salt>:<digest>` of the values the LAST WRITE resolved — the only way a plan notices
77
+ * a rotated credential, because the live row answers masked fragments that can never be
78
+ * compared (`secrets/write-only.ts`). An ADOPTED row starts `''`, which reads as `stale`.
79
+ */
80
+ readonly valuesSeal: string;
81
+
82
+ /** Names only, never masked fragments. Optional for states written by older providers. */
83
+ readonly valueKeys?: readonly string[];
84
+
85
+ /** All info key names, including withheld sensitive entries; optional for older states. */
86
+ readonly infoKeys?: readonly string[];
87
+ }
88
+
89
+ /**
90
+ * Whether a value is not a string with something in it. Takes `unknown`: a declaration can say
91
+ * anything. (Same rule as model-types.ts and registry-support.ts.)
92
+ */
93
+ export const isBlank = (value: unknown): boolean =>
94
+ typeof value !== 'string' || value.trim() === '';
95
+
96
+ /**
97
+ * The vendor's OWN sensitive-key list, read from the live 1.103.0 container
98
+ * (`litellm_logging.py::_get_masked_values`): a key containing any of these substrings
99
+ * (case-insensitive) is masked in every `credential_values` read. Credential-form.ts refuses
100
+ * them in `credentialInfo` for the same reason the vendor masks them in values.
101
+ */
102
+ const SENSITIVE_KEY_FRAGMENTS: readonly string[] = [
103
+ 'authorization',
104
+ 'token',
105
+ 'key',
106
+ 'secret',
107
+ 'vertex_credentials',
108
+ 'credentials',
109
+ 'password',
110
+ 'passwd',
111
+ ];
112
+
113
+ /** Whether a key is one the vendor itself treats as sensitive. */
114
+ export const isSensitiveKey = (key: string): boolean => {
115
+ const lower = key.toLowerCase();
116
+ return SENSITIVE_KEY_FRAGMENTS.some((fragment) => lower.includes(fragment));
117
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * The values of a `LiteLLM.Credential` — resolved from the deploying process's environment at
3
+ * call time, held as `Redacted`, and compared by seal.
4
+ *
5
+ * ★ THIS IS THE CREDENTIAL LITELLM STORES, so the deploying process holds the value: the wire
6
+ * body carries the LITERAL (the proxy encrypts it into its database, measured in the live
7
+ * 1.103.0 container — `credential_endpoints/endpoints.py`'s `encrypt_credential_values`), which
8
+ * is exactly why the prop is only a NAME (`credential-types.ts`). Inside this process the value
9
+ * is a `Redacted<string>`, so a stray log or error dump prints `<redacted>`; it is unwrapped in
10
+ * exactly one place, the wire body (credential-form.ts). Never a prop or an attribute.
11
+ * ⚠️ LITELLM DOES NOT HAND THE VALUES BACK TO COMPARE WITH: both reads answer them MASKED
12
+ * (2 + `****` + 2, `*****` for a short string — `litellm_logging.py::_get_masked_values`), and a
13
+ * masked fragment is a partial secret that must never be compared or stored. So what was last
14
+ * written is remembered as a SEAL, and a plan asks "are the values in my environment the ones I
15
+ * wrote". Four answers, mcp-server-credential.ts's own list:
16
+ * - `none` — no values are declared, nothing to compare.
17
+ * - `unknown` — one or more declared variables is unset here, so a plan cannot tell. Never
18
+ * drift: a plan-only environment must not report every credentialed row as
19
+ * changed. A WRITE still demands them (`requireValues`).
20
+ * - `stale` — every variable is set and there is no seal (an adopted row, or one written
21
+ * outside this stack) or the seal disagrees. The declaration is authoritative,
22
+ * so it is written.
23
+ * - `match` — the seal was made from exactly these resolved values.
24
+ * ⚠️ ALL-OR-NOTHING RESOLUTION: a write sends `credential_values` only when EVERY declared
25
+ * variable resolves — the values-stale PATCH and the whole-row create both demand every value
26
+ * (`requireValues`, credential.ts), because sending the resolved half would store a row whose
27
+ * unset half was silently blanked. When any variable is missing the state is `unknown`: an
28
+ * info-only PATCH can proceed, but a required rewrite refuses before DELETE.
29
+ * ⚠️ A SEAL OF A GUESSABLE SECRET IS STILL GUESSABLE (secrets/write-only.ts). Use a random token.
30
+ */
31
+ import * as Effect from 'effect/Effect';
32
+ import * as Redacted from 'effect/Redacted';
33
+ import { type Environment, resolveAll, seal, sealMatches } from '../secrets/write-only.ts';
34
+ import { LitellmCredentialEnvUnsetError } from './credential-errors.ts';
35
+ import type { CredentialProps } from './credential-types.ts';
36
+
37
+ /** What the environment holds for the declared values. `missing` names the unset variables. */
38
+ export interface ResolvedValues {
39
+ readonly values: Readonly<Record<string, Redacted.Redacted<string>>>;
40
+ readonly missing: readonly string[];
41
+ }
42
+
43
+ export type CredentialValuesState = 'none' | 'unknown' | 'stale' | 'match';
44
+
45
+ /** ⛔ Reads the environment at CALL time, never at module load (docs/credentials.md). */
46
+ export const resolveValues = (
47
+ props: CredentialProps,
48
+ env: Environment = process.env,
49
+ ): ResolvedValues => {
50
+ const { values, missing } = resolveAll(props.credentialValues, env);
51
+ return {
52
+ missing,
53
+ values: Object.fromEntries(
54
+ Object.entries(values).map(([key, value]) => [key, Redacted.make(value)]),
55
+ ),
56
+ };
57
+ };
58
+
59
+ const sealable = (values: Readonly<Record<string, Redacted.Redacted<string>>>) =>
60
+ Object.fromEntries(Object.entries(values).map(([key, value]) => [key, Redacted.value(value)]));
61
+
62
+ /** `scrypt:<salt>:<digest>` of the resolved values, for `valuesSeal`. ⛔ Never a value. */
63
+ export const sealValues = (values: Readonly<Record<string, Redacted.Redacted<string>>>): string =>
64
+ seal(sealable(values));
65
+
66
+ export const valuesState = (
67
+ props: CredentialProps,
68
+ sealed: string,
69
+ resolved: ResolvedValues = resolveValues(props),
70
+ ): CredentialValuesState => {
71
+ const declared = Object.keys(props.credentialValues);
72
+ if (declared.length === 0) return 'none';
73
+ if (resolved.missing.length > 0) return 'unknown';
74
+ if (sealed === '') return 'stale';
75
+ return sealMatches(sealed, sealable(resolved.values)) ? 'match' : 'stale';
76
+ };
77
+
78
+ /**
79
+ * Fails naming the missing variables when this write has to send the values and the deploying
80
+ * process does not hold them all. Creates, rewrites and value-stale PATCHes need every value;
81
+ * an info-only PATCH leaves values alone and does not need this guard (credential.ts).
82
+ */
83
+ export const requireValues = (
84
+ props: CredentialProps,
85
+ resolved: ResolvedValues,
86
+ ): Effect.Effect<void, LitellmCredentialEnvUnsetError> =>
87
+ resolved.missing.length === 0
88
+ ? Effect.void
89
+ : Effect.fail(
90
+ new LitellmCredentialEnvUnsetError({
91
+ credentialName: props.credentialName,
92
+ variables: resolved.missing,
93
+ }),
94
+ );