@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
@@ -18,6 +18,8 @@ import * as Context from 'effect/Context';
18
18
  import * as Effect from 'effect/Effect';
19
19
  import * as Layer from 'effect/Layer';
20
20
  import type { SqlError } from 'effect/unstable/sql/SqlError';
21
+ import type { PgExecutor } from './database-sql.ts';
22
+ import { type PsqlRunner, makePsqlExecutor } from './psql-executor.ts';
21
23
 
22
24
  /** What a stack passes to reach one cluster. `host` may be a socket directory (one beginning
23
25
  * with `/` expands to `${host}/.s.PGSQL.${port}` — measured in
@@ -31,11 +33,30 @@ export interface PostgresConnectionConfig {
31
33
  readonly ssl?: boolean;
32
34
  }
33
35
 
36
+ /** The runner transport (`psql-executor.ts`): SQL goes through `run` instead of a socket, for a
37
+ * host whose Postgres is reachable only by a command (CT100: ssh + `podman exec`). `template`
38
+ * is the `CREATE DATABASE` template — `template0` by default, because CT100's `template1` is
39
+ * ParadeDB's and would copy postgis/pg_ivm/paradedb objects into every new database. */
40
+ export interface PostgresRunnerConfig {
41
+ readonly run: PsqlRunner;
42
+ readonly database: string;
43
+ readonly username: string;
44
+ readonly template?: string;
45
+ }
46
+
47
+ /** What `withPg`'s callback learns about the transport beyond the client. `database` is the
48
+ * database the statements run IN: the family connection's, or the override `Postgres.Schema`
49
+ * and `Postgres.Grants` pass so they open their declared database and then prove it. */
50
+ export interface PgContext {
51
+ readonly template?: string;
52
+ readonly database: string;
53
+ }
54
+
34
55
  /** The lazy connection service. Its value is an `Effect` of the config, per S24 — see the file
35
56
  * header for why. */
36
57
  export class PostgresConnection extends Context.Service<
37
58
  PostgresConnection,
38
- Effect.Effect<PostgresConnectionConfig>
59
+ Effect.Effect<PostgresConnectionConfig | PostgresRunnerConfig>
39
60
  >()('Postgres.Connection') {}
40
61
 
41
62
  /** A stack's one-line way to provide a cluster: `Layer.provide(postgresConnection({ … }))` on
@@ -44,6 +65,19 @@ export const postgresConnection = (
44
65
  config: PostgresConnectionConfig,
45
66
  ): Layer.Layer<PostgresConnection> => Layer.succeed(PostgresConnection, Effect.succeed(config));
46
67
 
68
+ /** A stack's one-line way to provide a cluster reached through a command runner. */
69
+ export const postgresRunnerConnection = (
70
+ config: PostgresRunnerConfig,
71
+ ): Layer.Layer<PostgresConnection> => Layer.succeed(PostgresConnection, Effect.succeed(config));
72
+
73
+ /** Effect-scoped pool factory, like BaoGate: tests override it without process-wide module mocks. */
74
+ export const PostgresPool = Context.Reference<typeof PgClient.layer>('homeflare/postgres/Pool', {
75
+ defaultValue: () => PgClient.layer,
76
+ });
77
+
78
+ const isRunner = (c: PostgresConnectionConfig | PostgresRunnerConfig): c is PostgresRunnerConfig =>
79
+ 'run' in c;
80
+
47
81
  /**
48
82
  * Run one operation against a freshly built, freshly closed connection pool.
49
83
  *
@@ -51,12 +85,47 @@ export const postgresConnection = (
51
85
  * operation — never once per statement — so a reconcile that runs a `SELECT`, then a `CREATE`,
52
86
  * then a re-read shares one pool and closes it once, while a plan-only `read` still opens and
53
87
  * closes its own.
88
+ *
89
+ * `database` overrides which database of the SAME cluster the pool opens — the declared
90
+ * database of `Postgres.Schema` and `Postgres.Grants`. The family connection is pointed at a
91
+ * maintenance database (a brand-new database cannot be connected to on a cold plan), so those
92
+ * resources pass their declared database here: the runner transport swaps the `psql -d` target,
93
+ * the socket path swaps the pool's `database`. The swap is proven, not trusted: schema rows
94
+ * carry `current_database()` (`schema-sql.ts`) and grants calls the same function before writing.
54
95
  */
55
96
  export const withPg = <A, E>(
56
- build: (pg: PgClient.PgClient) => Effect.Effect<A, E>,
97
+ build: (pg: PgExecutor, context: PgContext) => Effect.Effect<A, E>,
98
+ database?: string,
57
99
  ): Effect.Effect<A, E | SqlError, PostgresConnection> =>
58
100
  Effect.gen(function* () {
59
101
  const resolveConfig = yield* PostgresConnection;
60
102
  const config = yield* resolveConfig;
61
- return yield* Effect.provide(Effect.flatMap(PgClient.PgClient, build), PgClient.layer(config));
103
+ const target: PostgresConnectionConfig | PostgresRunnerConfig =
104
+ database === undefined ? config : { ...config, database };
105
+ if (isRunner(target)) {
106
+ return yield* build(makePsqlExecutor(target.run, target), {
107
+ template: target.template ?? 'template0',
108
+ database: target.database,
109
+ });
110
+ }
111
+ const pool = yield* PostgresPool;
112
+ return yield* Effect.provide(
113
+ Effect.flatMap(PgClient.PgClient, (pg) =>
114
+ build(
115
+ {
116
+ unsafe: (sql, params) => pg.unsafe(sql, params),
117
+ // One reserved connection (`SqlClient.withTransaction`). A pool checkout per
118
+ // statement would autocommit CREATE before GRANT.
119
+ transaction: (statements) =>
120
+ pg.withTransaction(
121
+ Effect.gen(function* () {
122
+ for (const sql of statements) yield* pg.unsafe(sql).pipe(Effect.asVoid);
123
+ }),
124
+ ),
125
+ },
126
+ { database: target.database },
127
+ ),
128
+ ),
129
+ pool(target),
130
+ );
62
131
  });
@@ -90,6 +90,7 @@ const wireAccuratePg = (seed?: {
90
90
  }
91
91
  throw new Error(`wireAccuratePg: unrecognised statement: ${text}`);
92
92
  }) as Effect.Effect<ReadonlyArray<A>, SqlError>,
93
+ transaction: () => Effect.void,
93
94
  };
94
95
  };
95
96
 
@@ -50,12 +50,12 @@ describe('quoting', () => {
50
50
  });
51
51
 
52
52
  test('quoteStringLiteral doubles an embedded single quote', () => {
53
- expect(quoteStringLiteral("en_US.UTF-8'; DROP")).toBe("'en_US.UTF-8''; DROP'");
53
+ expect(quoteStringLiteral("en_US.UTF-8'; DROP")).toBe("E'en_US.UTF-8''; DROP'");
54
54
  });
55
55
 
56
56
  test('buildCreateDatabaseSql never string-concatenates an unescaped value', () => {
57
57
  const sql = buildCreateDatabaseSql({ name: 'db"1', owner: 'ro"le', encoding: "UT'F8" });
58
- expect(sql).toBe('CREATE DATABASE "db""1" WITH OWNER "ro""le" ENCODING \'UT\'\'F8\'');
58
+ expect(sql).toBe('CREATE DATABASE "db""1" WITH OWNER "ro""le" ENCODING E\'UT\'\'F8\'');
59
59
  });
60
60
  });
61
61
 
@@ -19,23 +19,33 @@
19
19
  * `createdb_opt_item`'s string branch is `opt_boolean_or_string → NonReservedWord_or_Sconst →
20
20
  * NonReservedWord | Sconst`. A locale like `en_US.UTF-8` would hit the same dot-splitting
21
21
  * `quoteIdent` avoids if it were identifier-quoted; a plain `Sconst` (`quoteStringLiteral`) has
22
- * no such rule. This rests on `standard_conforming_strings = on` (the PG18 default, and
23
- * measured live 2026-09-23 — `docs/postgres.md#measured`); the escaper only ever doubles `'`
24
- * and never emits a backslash, so it never depends on which way that setting points.
22
+ * no such rule. Use E'…' with doubled backslashes and quotes: PostgreSQL 18 lexical
23
+ * section 4.1.2.2 makes escape strings independent of standard_conforming_strings.
24
+ * Measured 2026-10-01: the former quote-only escaper allowed comment SQL injection when
25
+ * that setting was off; an input backslash escaped the first quote of a doubled pair.
25
26
  */
26
27
  import type { SqlError } from 'effect/unstable/sql/SqlError';
27
28
  import * as Effect from 'effect/Effect';
28
29
  import type { PostgresDatabaseAttributes, PostgresDatabaseProps } from './database-attrs.ts';
29
30
 
30
31
  /** What every function in this file needs from a client — real (`PgClient.PgClient`) or fake
31
- * (`fake-sql.ts`). Deliberately smaller than `SqlClient`: nothing here ever needs the tagged
32
- * template, transactions or streaming, because every statement is either bound params through
33
- * `.unsafe(text, params)` or a hand-escaped literal through `.unsafe(text)`. */
32
+ * (`fake-sql.ts`). Deliberately smaller than `SqlClient`: nothing here needs the tagged template
33
+ * or streaming. `transaction` is the exception `Postgres.Role`'s create and `Postgres.Grants`'
34
+ * repair share: role DDL commits per statement unless the statements share a transaction, and
35
+ * a grants repair's `REVOKE` must not autocommit apart from the `GRANT`s that restore it. */
34
36
  export interface PgExecutor {
35
37
  readonly unsafe: <A extends object>(
36
38
  sql: string,
37
39
  params?: ReadonlyArray<unknown>,
38
40
  ) => Effect.Effect<ReadonlyArray<A>, SqlError>;
41
+ /**
42
+ * Run `statements` in one transaction. `CREATE ROLE`, `ALTER ROLE` and `GRANT`/`REVOKE` of
43
+ * membership are transactional (`utility.c@REL_18_6`: those cases do not call
44
+ * `PreventInTransactionBlock`; `CREATE DATABASE` does). The socket client reserves one
45
+ * connection (`SqlClient.withTransaction`); the runner sends one `psql` script, because each
46
+ * `unsafe` call is its own session and would autocommit.
47
+ */
48
+ readonly transaction: (statements: readonly string[]) => Effect.Effect<void, SqlError>;
39
49
  }
40
50
 
41
51
  /** Single-token identifier quoting: wrap in `"`, double any embedded `"`. No dot-splitting —
@@ -43,12 +53,14 @@ export interface PgExecutor {
43
53
  * `NonReservedWord` too, for `OWNER` and `TABLESPACE`. */
44
54
  export const quoteIdent = (value: string): string => `"${value.replace(/"/g, '""')}"`;
45
55
 
46
- /** SQL string-literal quoting: wrap in `'`, double any embedded `'`. Used for every `WITH`
47
- * value that is locale or encoding text, never for an identifier (see the file header). */
48
- export const quoteStringLiteral = (value: string): string => `'${value.replace(/'/g, "''")}'`;
56
+ /** Escape-string quoting is safe with standard_conforming_strings either on or off.
57
+ * Double backslashes BEFORE quotes, so caller text cannot escape a closing delimiter. */
58
+ export const quoteStringLiteral = (value: string): string =>
59
+ `E'${value.replace(/\\/g, '\\\\').replace(/'/g, "''")}'`;
49
60
 
50
- const withOptions = (props: PostgresDatabaseProps): string => {
61
+ const withOptions = (props: PostgresDatabaseProps, template?: string): string => {
51
62
  const parts: string[] = [`OWNER ${quoteIdent(props.owner)}`];
63
+ if (template !== undefined) parts.push(`TEMPLATE ${quoteIdent(template)}`);
52
64
  if (props.encoding !== undefined) parts.push(`ENCODING ${quoteStringLiteral(props.encoding)}`);
53
65
  if (props.localeProvider !== undefined) {
54
66
  parts.push(`LOCALE_PROVIDER ${quoteStringLiteral(props.localeProvider)}`);
@@ -74,8 +86,8 @@ const withOptions = (props: PostgresDatabaseProps): string => {
74
86
  * `Math.trunc`ed and stringified, and a boolean is one of exactly two literal words this file
75
87
  * writes, so no declared value reaches the statement through string interpolation unescaped.
76
88
  */
77
- export const buildCreateDatabaseSql = (props: PostgresDatabaseProps): string =>
78
- `CREATE DATABASE ${quoteIdent(props.name)} WITH ${withOptions(props)}`;
89
+ export const buildCreateDatabaseSql = (props: PostgresDatabaseProps, template?: string): string =>
90
+ `CREATE DATABASE ${quoteIdent(props.name)} WITH ${withOptions(props, template)}`;
79
91
 
80
92
  /** `42P04` (`duplicate_database`) is a race: something else created the name between our read
81
93
  * and our create. Measured at `internal/sqlError.ts@effect/sql-pg 4.0.0-rc.115`: every SQLSTATE
@@ -102,6 +114,22 @@ export const roleExists = (pg: PgExecutor, role: string): Effect.Effect<boolean,
102
114
  (rows) => rows.length > 0,
103
115
  );
104
116
 
117
+ const DATABASE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_database WHERE datname = $1';
118
+
119
+ /**
120
+ * Does one database of the cluster exist? `Postgres.Schema` runs this over the FAMILY
121
+ * connection (no `withPg` database override) before `read` and `delete`, so a declared
122
+ * database that does not exist yet answers "schema absent" instead of the transports' untyped
123
+ * connect failures (`ConnectionError` over psql, `UnknownError` 3D000 over the socket). The
124
+ * probe targets the maintenance database the family connection already points at, which a
125
+ * cold plan can always reach.
126
+ */
127
+ export const databaseExists = (pg: PgExecutor, name: string): Effect.Effect<boolean, SqlError> =>
128
+ Effect.map(
129
+ pg.unsafe<{ readonly present: number }>(DATABASE_EXISTS_SQL, [name]),
130
+ (rows) => rows.length > 0,
131
+ );
132
+
105
133
  /** `datlocprovider` is Postgres's internal 1-byte `"char"` type, which this client decodes as
106
134
  * raw bytes rather than text (measured 2026-09-23 against the live socket — `docs/postgres.md`);
107
135
  * the `CASE` maps it to the same three words `pg_collation.h@REL_18_6#collprovider_name` returns
@@ -80,6 +80,7 @@ const liveDrift = (props: PostgresDatabaseProps, live: PostgresDatabaseAttribute
80
80
  export const reconcileWithClient = (
81
81
  pg: PgExecutor,
82
82
  props: PostgresDatabaseProps,
83
+ template?: string,
83
84
  ): Effect.Effect<
84
85
  PostgresDatabaseAttributes,
85
86
  PostgresDatabaseOwnerMissing | PostgresDatabaseDrift | PostgresDatabaseCreateVanished | SqlError
@@ -93,7 +94,7 @@ export const reconcileWithClient = (
93
94
  new PostgresDatabaseOwnerMissing({ database: props.name, owner: props.owner }),
94
95
  );
95
96
  }
96
- yield* pg.unsafe(buildCreateDatabaseSql(props)).pipe(
97
+ yield* pg.unsafe(buildCreateDatabaseSql(props, template)).pipe(
97
98
  Effect.asVoid,
98
99
  Effect.catchTag('SqlError', (error) =>
99
100
  isDuplicateDatabaseRace(error) ? Effect.succeed(undefined) : Effect.fail(error),
@@ -183,7 +184,7 @@ export const postgresDatabaseHandlers = PostgresDatabase.Provider.of({
183
184
  new PostgresDatabaseNameRefused({ name: news.name, ...nameRefusal }),
184
185
  );
185
186
  }
186
- return yield* withPg((pg) => reconcileWithClient(pg, news));
187
+ return yield* withPg((pg, ctx) => reconcileWithClient(pg, news, ctx.template));
187
188
  }),
188
189
 
189
190
  delete: ({ olds }) => Effect.fail(new PostgresDatabaseDropRefused({ database: olds.name })),
@@ -0,0 +1,189 @@
1
+ /**
2
+ * The statement parser half of the `Postgres.Grants` test fake: it understands EXACTLY the
3
+ * ten statement shapes `grants-sql.ts` generates — `quoteIdent`'s quoting, one clause
4
+ * order — and nothing else, so a quoting or clause-order bug in a builder trips the parser
5
+ * instead of hiding behind lenient matching. The server-model half (entries, grant/revoke
6
+ * semantics, the aclexplode-shaped reads) lives in `fake-grants-sql.ts`.
7
+ *
8
+ * ⛔ IT PARSES ITS OWN OUTPUT, NOT SQL IN GENERAL (`fake-sql.ts`'s own rule): every value
9
+ * the builders `quoteIdent` is read back through the same `"…""…"` unquoting, and every
10
+ * statement ends in exactly one of the accepted shapes or the parse refuses.
11
+ * ⛔ A COLUMN GRANT CARRIES ONE COLUMN LIST PER WORD — `GRANT select ("id"), update ("id")`:
12
+ * a single trailing list binds only to the privilege it follows (gram.y@REL_18_6), so
13
+ * `GRANT select, update ("id")` is a table-level SELECT on a real server. The parser
14
+ * refuses that shape instead of filing it as a column-only grant.
15
+ */
16
+ export interface AclObject {
17
+ readonly schema: string;
18
+ readonly table?: string;
19
+ readonly column?: string;
20
+ readonly defaultFor?: string;
21
+ }
22
+
23
+ /** One parsed write statement, already reduced to what the model applies. */
24
+ export interface ParsedWrite {
25
+ readonly kind: 'grant' | 'revoke';
26
+ /** `REVOKE ALL ON ALL TABLES IN SCHEMA … FROM PUBLIC` — applied per known relation. */
27
+ readonly allTables?: boolean;
28
+ readonly object: AclObject;
29
+ /** `'PUBLIC'` or a role name. */
30
+ readonly grantee: string;
31
+ /** Declared privilege words, lowercase, no `*` marks (the option clause carries the flag). */
32
+ readonly words: ReadonlyArray<string>;
33
+ readonly option: boolean;
34
+ }
35
+
36
+ const unquote = (raw: string): string => raw.replace(/""/g, '"');
37
+
38
+ const IDENT = String.raw`"((?:[^"]|"")*)"`;
39
+ const WORDS = String.raw`([a-z]+(?:, [a-z]+)*)`;
40
+ /** One column-grant atom, `word ("col")` — the shape every builder column statement is made of. */
41
+ const SYNOPSIS = String.raw`[a-z]+ \("(?:[^"]|"")*"\)`;
42
+ const GRANTEE = String.raw`(?:"((?:[^"]|"")*)"|PUBLIC)`;
43
+ const OPTION = String.raw`(?:( WITH GRANT OPTION))?`;
44
+
45
+ interface Pattern {
46
+ readonly re: RegExp;
47
+ /** `undefined` when the regex matched but the shape is one no builder emits — the loop
48
+ * falls through and the parse refuses (a builder regression, not a tolerated statement). */
49
+ readonly parse: (m: RegExpExecArray) => Omit<ParsedWrite, 'kind'> | undefined;
50
+ }
51
+
52
+ const role = (raw: string | undefined): string => (raw === undefined ? 'PUBLIC' : unquote(raw));
53
+
54
+ /** Ordered: a column grant/revoke must be tried before the table form its text starts like,
55
+ * and the two default-privileges forms before the plain ones they begin as. */
56
+ const PATTERNS: ReadonlyArray<Pattern & { readonly kind: 'grant' | 'revoke' }> = [
57
+ {
58
+ kind: 'grant',
59
+ re: new RegExp(
60
+ `^ALTER DEFAULT PRIVILEGES FOR ROLE ${IDENT} IN SCHEMA ${IDENT} GRANT ${WORDS} ON TABLES TO ${GRANTEE}${OPTION}$`,
61
+ ),
62
+ parse: (m) => ({
63
+ object: { schema: unquote(m[2] as string), defaultFor: unquote(m[1] as string) },
64
+ grantee: role(m[4] as string | undefined),
65
+ words: (m[3] as string).split(', '),
66
+ option: m[5] !== undefined,
67
+ }),
68
+ },
69
+ {
70
+ kind: 'revoke',
71
+ re: new RegExp(
72
+ `^ALTER DEFAULT PRIVILEGES FOR ROLE ${IDENT} IN SCHEMA ${IDENT} REVOKE ALL ON TABLES FROM ${GRANTEE}$`,
73
+ ),
74
+ parse: (m) => ({
75
+ object: { schema: unquote(m[2] as string), defaultFor: unquote(m[1] as string) },
76
+ grantee: role(m[3] as string | undefined),
77
+ words: [],
78
+ option: false,
79
+ }),
80
+ },
81
+ {
82
+ kind: 'grant',
83
+ // ⛔ Every word carries its OWN column list — `GRANT select ("id"), update ("id") …`.
84
+ // A single trailing list binds only to the privilege it follows (gram.y@REL_18_6), so
85
+ // `GRANT select, update ("id")` is a table-level SELECT on a real server; the parser
86
+ // refuses that shape instead of filing it as a column-only grant (a builder that
87
+ // emits it would over-grant at the table level while the suite stays green).
88
+ re: new RegExp(
89
+ `^GRANT (${SYNOPSIS}(?:, ${SYNOPSIS})*) ON ${IDENT}\\.${IDENT} TO ${GRANTEE}${OPTION}$`,
90
+ ),
91
+ parse: (m) => {
92
+ const pairs = [...(m[1] as string).matchAll(/([a-z]+) \("((?:[^"]|"")*)"\)/g)];
93
+ const first = pairs[0];
94
+ if (first === undefined) return undefined;
95
+ const column = unquote(first[2] as string);
96
+ // One statement grants ONE column: every synopsis pair must name the same one (the
97
+ // builders emit one column per statement) — mixed columns are a foreign shape.
98
+ if (pairs.some(([, , raw]) => unquote(raw as string) !== column)) return undefined;
99
+ return {
100
+ object: {
101
+ schema: unquote(m[2] as string),
102
+ table: unquote(m[3] as string),
103
+ column,
104
+ },
105
+ grantee: role(m[4] as string | undefined),
106
+ words: pairs.map(([, word]) => word as string),
107
+ option: m[5] !== undefined,
108
+ };
109
+ },
110
+ },
111
+ {
112
+ kind: 'revoke',
113
+ re: new RegExp(`^REVOKE ALL \\(${IDENT}\\) ON ${IDENT}\\.${IDENT} FROM ${GRANTEE}$`),
114
+ parse: (m) => ({
115
+ object: {
116
+ schema: unquote(m[2] as string),
117
+ table: unquote(m[3] as string),
118
+ column: unquote(m[1] as string),
119
+ },
120
+ grantee: role(m[4] as string | undefined),
121
+ words: [],
122
+ option: false,
123
+ }),
124
+ },
125
+ {
126
+ kind: 'grant',
127
+ re: new RegExp(`^GRANT ${WORDS} ON SCHEMA ${IDENT} TO ${GRANTEE}${OPTION}$`),
128
+ parse: (m) => ({
129
+ object: { schema: unquote(m[2] as string) },
130
+ grantee: role(m[3] as string | undefined),
131
+ words: (m[1] as string).split(', '),
132
+ option: m[4] !== undefined,
133
+ }),
134
+ },
135
+ {
136
+ kind: 'grant',
137
+ re: new RegExp(`^GRANT ${WORDS} ON ${IDENT}\\.${IDENT} TO ${GRANTEE}${OPTION}$`),
138
+ parse: (m) => ({
139
+ object: { schema: unquote(m[2] as string), table: unquote(m[3] as string) },
140
+ grantee: role(m[4] as string | undefined),
141
+ words: (m[1] as string).split(', '),
142
+ option: m[5] !== undefined,
143
+ }),
144
+ },
145
+ {
146
+ kind: 'revoke',
147
+ re: new RegExp(`^REVOKE ALL ON ${IDENT}\\.${IDENT} FROM ${GRANTEE}$`),
148
+ parse: (m) => ({
149
+ object: { schema: unquote(m[1] as string), table: unquote(m[2] as string) },
150
+ grantee: role(m[3] as string | undefined),
151
+ words: [],
152
+ option: false,
153
+ }),
154
+ },
155
+ {
156
+ kind: 'revoke',
157
+ re: new RegExp(`^REVOKE ALL ON SCHEMA ${IDENT} FROM ${GRANTEE}$`),
158
+ parse: (m) => ({
159
+ object: { schema: unquote(m[1] as string) },
160
+ grantee: role(m[2] as string | undefined),
161
+ words: [],
162
+ option: false,
163
+ }),
164
+ },
165
+ {
166
+ kind: 'revoke',
167
+ re: new RegExp(`^REVOKE ALL ON ALL TABLES IN SCHEMA ${IDENT} FROM ${GRANTEE}$`),
168
+ parse: (m) => ({
169
+ allTables: true,
170
+ object: { schema: unquote(m[1] as string) },
171
+ grantee: role(m[2] as string | undefined),
172
+ words: [],
173
+ option: false,
174
+ }),
175
+ },
176
+ ];
177
+
178
+ /** `undefined` when the text is no statement this family generates — the model refuses it
179
+ * rather than guessing (a parse miss on a GRANT-shaped text means a builder regressed). */
180
+ export const parseGrantStatement = (text: string): ParsedWrite | undefined => {
181
+ for (const pattern of PATTERNS) {
182
+ const m = pattern.re.exec(text);
183
+ if (m === null) continue;
184
+ const parsed = pattern.parse(m);
185
+ if (parsed === undefined) continue;
186
+ return { kind: pattern.kind, ...parsed };
187
+ }
188
+ return undefined;
189
+ };