@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,158 @@
1
+ /**
2
+ * The write-only password lifecycle (S25) against `fake-sql.ts`'s recording fake: the
3
+ * declaration is the NAME of an environment variable, the value exists only in memory and on
4
+ * the wire of the one dedicated `ALTER ROLE … PASSWORD` statement, and what state remembers is
5
+ * a scrypt seal. Create, adopt, rotate and the never-guessed refusals.
6
+ */
7
+ import { describe, expect, test } from 'bun:test';
8
+ import * as Effect from 'effect/Effect';
9
+ import type { PgExecutor } from './database-sql.ts';
10
+ import { seal, sealMatches } from '../secrets/write-only.ts';
11
+ import { makeFakeSql } from './fake-sql.ts';
12
+ import { PostgresRoleCreateVanished, PostgresRolePasswordEnvUnsetError } from './role-errors.ts';
13
+ import type { PostgresRoleAttributes, PostgresRoleProps } from './role-attrs.ts';
14
+ import { reconcileWithClient } from './role.ts';
15
+
16
+ const run = <A, E>(eff: Effect.Effect<A, E>): Promise<A> => Effect.runPromise(eff);
17
+ const fails = <A, E>(eff: Effect.Effect<A, E>): Promise<E> => Effect.runPromise(Effect.flip(eff));
18
+
19
+ const baseProps: PostgresRoleProps = {
20
+ name: 'seat-observability',
21
+ login: false,
22
+ connectionLimit: 10,
23
+ inherit: true,
24
+ };
25
+
26
+ const liveRole = (over: Partial<PostgresRoleAttributes> = {}): PostgresRoleAttributes => ({
27
+ name: 'seat-observability',
28
+ oid: 20000,
29
+ login: false,
30
+ connectionLimit: 10,
31
+ inherit: true,
32
+ validUntil: null,
33
+ memberOf: [],
34
+ passwordSeal: '',
35
+ ...over,
36
+ });
37
+
38
+ const startingWith = (fake: ReturnType<typeof makeFakeSql>, prefix: string) =>
39
+ fake.statements.filter((s) => s.text.startsWith(prefix));
40
+
41
+ const withPassword = {
42
+ ...baseProps,
43
+ password: { fromEnv: 'PG_SEAT_ROLE_PASSWORD' },
44
+ };
45
+
46
+ describe('password: create', () => {
47
+ test('travels in a dedicated ALTER, never in the CREATE, and only its seal lands in state', async () => {
48
+ const fake = makeFakeSql();
49
+ const attrs = await run(
50
+ reconcileWithClient(fake, withPassword, { PG_SEAT_ROLE_PASSWORD: 's3cret-value' }),
51
+ );
52
+ expect(startingWith(fake, 'CREATE ROLE')[0]?.text.includes('PASSWORD')).toBe(false);
53
+ // The statement carries the SCRAM-SHA-256 verifier, never the plain value: this is the text
54
+ // that reaches the span attribute `db.query.text` on the socket transport and the inlined
55
+ // stdin on the runner transport, so both are covered by one assertion over the shared text.
56
+ const sent = startingWith(fake, 'ALTER ROLE').map((s) => s.text);
57
+ expect(sent).toHaveLength(1);
58
+ expect(sent[0]).toMatch(/^ALTER ROLE "seat-observability" WITH PASSWORD E'SCRAM-SHA-256\$/);
59
+ expect(JSON.stringify(fake.statements)).not.toContain('s3cret-value');
60
+ expect(JSON.stringify(attrs)).not.toContain('s3cret-value');
61
+ // The seal stays a seal of the plain value — only the wire form changed.
62
+ expect(sealMatches(attrs.passwordSeal, { password: 's3cret-value' })).toBe(true);
63
+ });
64
+
65
+ test('a missing environment value refuses before any statement — never a guess', async () => {
66
+ const fake = makeFakeSql();
67
+ const error = await fails(reconcileWithClient(fake, withPassword, {}));
68
+ expect(error).toBeInstanceOf(PostgresRolePasswordEnvUnsetError);
69
+ expect((error as PostgresRolePasswordEnvUnsetError).variable).toBe('PG_SEAT_ROLE_PASSWORD');
70
+ // The reconcile reads first (one SELECT); the refusal lands before any write statement.
71
+ expect(startingWith(fake, 'CREATE').length).toBe(0);
72
+ expect(startingWith(fake, 'ALTER').length).toBe(0);
73
+ });
74
+ });
75
+
76
+ describe('password: live role', () => {
77
+ test('a rotated environment value rewrites the password under a fresh seal', async () => {
78
+ const oldSeal = seal({ password: 'old' }, 'fixed-salt');
79
+ const fake = makeFakeSql({ roleRows: [liveRole()] });
80
+ const attrs = await run(
81
+ reconcileWithClient(fake, withPassword, { PG_SEAT_ROLE_PASSWORD: 'new' }, oldSeal),
82
+ );
83
+ const sent = startingWith(fake, 'ALTER ROLE').map((s) => s.text);
84
+ expect(sent).toHaveLength(1);
85
+ expect(sent[0]).toMatch(/^ALTER ROLE "seat-observability" WITH PASSWORD E'SCRAM-SHA-256\$/);
86
+ expect(JSON.stringify(fake.statements)).not.toContain('new');
87
+ expect(sealMatches(attrs.passwordSeal, { password: 'new' })).toBe(true);
88
+ expect(sealMatches(attrs.passwordSeal, { password: 'old' })).toBe(false);
89
+ });
90
+
91
+ test('an unchanged environment value sends no password statement and keeps the seal bit-identical', async () => {
92
+ const oldSeal = seal({ password: 'old' }, 'fixed-salt');
93
+ const fake = makeFakeSql({ roleRows: [liveRole()] });
94
+ const attrs = await run(
95
+ reconcileWithClient(fake, withPassword, { PG_SEAT_ROLE_PASSWORD: 'old' }, oldSeal),
96
+ );
97
+ expect(fake.statements.some((s) => s.text.startsWith('ALTER'))).toBe(false);
98
+ expect(attrs.passwordSeal).toBe(oldSeal);
99
+ });
100
+
101
+ test('an adopted role (empty seal) gets the password written on the first reconcile that holds it', async () => {
102
+ const fake = makeFakeSql({ roleRows: [liveRole()] });
103
+ const attrs = await run(
104
+ reconcileWithClient(fake, withPassword, { PG_SEAT_ROLE_PASSWORD: 'first' }),
105
+ );
106
+ expect(startingWith(fake, 'ALTER ROLE').length).toBe(1);
107
+ expect(sealMatches(attrs.passwordSeal, { password: 'first' })).toBe(true);
108
+ });
109
+
110
+ test('an environment that went empty on a live role never churns the stored password', async () => {
111
+ const oldSeal = seal({ password: 'old' }, 'fixed-salt');
112
+ const fake = makeFakeSql({ roleRows: [liveRole()] });
113
+ const attrs = await run(
114
+ reconcileWithClient(fake, withPassword, { PG_SEAT_ROLE_PASSWORD: '' }, oldSeal),
115
+ );
116
+ expect(fake.statements.some((s) => s.text.startsWith('ALTER'))).toBe(false);
117
+ expect(attrs.passwordSeal).toBe(oldSeal);
118
+ });
119
+
120
+ test('a declared password whose seal is still empty refuses an unset variable on the update path', async () => {
121
+ // CREATE ROLE committed, then ALTER ROLE … PASSWORD failed or the process died before state
122
+ // was saved. The next run sees the role and an empty seal. Reporting success would leave a
123
+ // LOGIN role this stack has never sealed.
124
+ const fake = makeFakeSql({ roleRows: [liveRole({ login: true })] });
125
+ const error = await fails(
126
+ reconcileWithClient(fake, { ...withPassword, login: true }, { PG_SEAT_ROLE_PASSWORD: '' }),
127
+ );
128
+ expect(error).toBeInstanceOf(PostgresRolePasswordEnvUnsetError);
129
+ expect(fake.statements.some((s) => s.text.startsWith('ALTER'))).toBe(false);
130
+ });
131
+ });
132
+
133
+ describe('password: no new write statements on the no-op path', () => {
134
+ test('a create with no password declared never mentions PASSWORD at all', async () => {
135
+ const fake = makeFakeSql();
136
+ await run(reconcileWithClient(fake, baseProps));
137
+ expect(fake.statements.some((s) => s.text.includes('PASSWORD'))).toBe(false);
138
+ });
139
+
140
+ test('a vanished create on a password-carrying reconcile fails typed, with the password statement issued first', async () => {
141
+ // The blank executor answers every read with `[]` (absent), so the reconcile takes the
142
+ // create path: CREATE, then the dedicated password ALTER, then a re-read that finds nothing.
143
+ // The typed `PostgresRoleCreateVanished` surfaces that — the value stayed on the wire, and
144
+ // the failure is never a secret leak.
145
+ const unsafe = <A extends object>(_sql?: string) => Effect.succeed([] as ReadonlyArray<A>);
146
+ const blankPg: PgExecutor = {
147
+ unsafe,
148
+ transaction: (statements) =>
149
+ Effect.gen(function* () {
150
+ for (const sql of statements) yield* unsafe(sql).pipe(Effect.asVoid);
151
+ }),
152
+ };
153
+ const error = await fails(
154
+ reconcileWithClient(blankPg, withPassword, { PG_SEAT_ROLE_PASSWORD: 'v' }),
155
+ );
156
+ expect(error).toBeInstanceOf(PostgresRoleCreateVanished);
157
+ });
158
+ });
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Adopt and alter of a role that already carries privileges this family never declares.
3
+ *
4
+ * The review of PR 336: `--adopt` of a SUPERUSER (or CREATEROLE / CREATEDB / REPLICATION /
5
+ * BYPASSRLS) role planned green and left the flag set, and a membership already granted
6
+ * `WITH ADMIN` matched by name so it was never revoked. `GRANT` also omitted `SET`, which
7
+ * upstream defaults to TRUE — a member can `SET ROLE` to the parent.
8
+ */
9
+ import { describe, expect, test } from 'bun:test';
10
+ import * as Effect from 'effect/Effect';
11
+ import { makeFakeSql } from './fake-sql.ts';
12
+ import { PostgresRolePrivilegedRefused } from './role-errors.ts';
13
+ import type { PostgresRoleAttributes, PostgresRoleProps } from './role-attrs.ts';
14
+ import { reconcileWithClient } from './role.ts';
15
+
16
+ const run = <A, E>(eff: Effect.Effect<A, E>): Promise<A> => Effect.runPromise(eff);
17
+ const fails = <A, E>(eff: Effect.Effect<A, E>): Promise<E> => Effect.runPromise(Effect.flip(eff));
18
+
19
+ const baseProps: PostgresRoleProps = {
20
+ name: 'seat-widget',
21
+ login: false,
22
+ connectionLimit: -1,
23
+ inherit: true,
24
+ memberOf: ['hf_agent'],
25
+ };
26
+
27
+ const liveRole = (over: Partial<PostgresRoleAttributes> = {}): PostgresRoleAttributes => ({
28
+ name: 'seat-widget',
29
+ oid: 20000,
30
+ login: false,
31
+ connectionLimit: -1,
32
+ inherit: true,
33
+ validUntil: null,
34
+ memberOf: ['hf_agent'],
35
+ passwordSeal: '',
36
+ superuser: false,
37
+ createrole: false,
38
+ createdb: false,
39
+ replication: false,
40
+ bypassrls: false,
41
+ ...over,
42
+ });
43
+
44
+ describe('adopted privilege flags', () => {
45
+ test('a live SUPERUSER is refused before any write', async () => {
46
+ const fake = makeFakeSql({ roleRows: [liveRole({ superuser: true })] });
47
+ const error = await fails(reconcileWithClient(fake, baseProps));
48
+ expect(error).toBeInstanceOf(PostgresRolePrivilegedRefused);
49
+ expect(
50
+ fake.statements.some((s) => s.text.startsWith('ALTER') || s.text.startsWith('GRANT')),
51
+ ).toBe(false);
52
+ });
53
+
54
+ test('a membership granted WITH ADMIN by this session is repaired in place', async () => {
55
+ const fake = makeFakeSql({ roleRows: [liveRole()], roles: ['hf_agent'] });
56
+ fake.memberships.add('seat-widget\0hf_agent\0postgres');
57
+ fake.membershipOptions.set('seat-widget\0hf_agent\0postgres', { admin: true, set: true });
58
+ await run(reconcileWithClient(fake, baseProps));
59
+ const texts = fake.statements.map((s) => s.text);
60
+ // `AddRoleMems` updates the session grantor's row. One full-options GRANT clears ADMIN
61
+ // and SET without a REVOKE that would drop the membership the declaration still wants.
62
+ expect(texts).toContain('GRANT "hf_agent" TO "seat-widget" WITH ADMIN FALSE, SET FALSE');
63
+ expect(texts.some((text) => text.startsWith('REVOKE'))).toBe(false);
64
+ expect(fake.memberships.has('seat-widget\0hf_agent\0postgres')).toBe(true);
65
+ expect(fake.membershipOptions.has('seat-widget\0hf_agent\0postgres')).toBe(false);
66
+ });
67
+
68
+ test("another grantor's ADMIN row is revoked by that grantor and the seat grant remains", async () => {
69
+ const fake = makeFakeSql({ roleRows: [liveRole()], roles: ['hf_agent'] });
70
+ fake.memberships.add('seat-widget\0hf_agent\0other');
71
+ fake.membershipOptions.set('seat-widget\0hf_agent\0other', { admin: true, set: true });
72
+ await run(reconcileWithClient(fake, baseProps));
73
+ const texts = fake.statements.map((s) => s.text);
74
+ expect(texts).toContain('GRANT "hf_agent" TO "seat-widget" WITH ADMIN FALSE, SET FALSE');
75
+ expect(texts).toContain('REVOKE "hf_agent" FROM "seat-widget" GRANTED BY "other"');
76
+ expect(fake.memberships.has('seat-widget\0hf_agent\0other')).toBe(false);
77
+ expect(fake.memberships.has('seat-widget\0hf_agent\0postgres')).toBe(true);
78
+ expect(fake.membershipOptions.has('seat-widget\0hf_agent\0postgres')).toBe(false);
79
+ });
80
+ });
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Provenance: every `PostgresRoleProps` field traces to a real `CREATE ROLE` synopsis option AND
3
+ * a real `pg_authid`/`pg_auth_members` column, every synopsis option this family does NOT expose
4
+ * is named with a reason, and the `ALTER ROLE` synopsis backs every field the family alters (plus
5
+ * the "memberships move via GRANT and REVOKE" note the membership statements lean on). All four
6
+ * fixtures are parsed, not eyeballed — deleting a fixture line, or adding a prop with no mapping,
7
+ * fails this file (S38, the house's provenance rule).
8
+ */
9
+ import { describe, expect, test } from 'bun:test';
10
+ import { readFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+
13
+ const FIXTURES = join(import.meta.dir, 'fixtures');
14
+ const createRole = readFileSync(join(FIXTURES, 'pg-REL_18_6-create_role.sgml.txt'), 'utf8');
15
+ const alterRole = readFileSync(join(FIXTURES, 'pg-REL_18_6-alter_role.sgml.txt'), 'utf8');
16
+ const authid = readFileSync(join(FIXTURES, 'pg-REL_18_6-pg_authid.h.txt'), 'utf8');
17
+ const authMembers = readFileSync(join(FIXTURES, 'pg-REL_18_6-pg_auth_members.h.txt'), 'utf8');
18
+
19
+ const CREATE_ROLE_BLOB = 'cee23b1ea6b4dcf2d9d356d07a582e64808c2912';
20
+ const ALTER_ROLE_BLOB = '7b0a04bc4637c7c08246e597a9acf4466b467fa2';
21
+ const AUTHID_BLOB = 'b2f3e9d01eec972a3392e7037c9679ac644ddc7b';
22
+ const AUTH_MEMBERS_BLOB = '387316e44f07982264482f01f2298f4f85ffbafb';
23
+
24
+ /** Each alternative of a "where <option> can be:" list, normalised to its leading keyword
25
+ * sequence, keeping the optional `[ ENCRYPTED ]` prefix and multi-word forms such as
26
+ * `CONNECTION LIMIT` / `VALID UNTIL` intact. */
27
+ const optionTokens = (region: string): readonly string[] => {
28
+ const found: string[] = [];
29
+ for (const line of region.split('\n')) {
30
+ for (const raw of line.split('|')) {
31
+ const m = /^(\[ ENCRYPTED \] )?([A-Z]+(?: [A-Z]+)*)/.exec(raw.trim());
32
+ if (m !== null) found.push(`${m[1] ?? ''}${m[2] as string}`.trim());
33
+ }
34
+ }
35
+ return [...new Set(found)];
36
+ };
37
+
38
+ /** A `CATALOG` struct's column names, from the tab-indicated `type name;` lines. */
39
+ const structColumns = (fixture: string): readonly string[] => {
40
+ const re = /^\t[A-Za-z_][A-Za-z0-9_]*\s+(\w+)(?:\[\d+\])?\b/;
41
+ return fixture
42
+ .split('\n')
43
+ .map((line) => re.exec(line)?.[1])
44
+ .filter((name): name is string => name !== undefined);
45
+ };
46
+
47
+ /** The create synopsis's option list: from the first `can be:</phrase>` to `</synopsis>`. */
48
+ const createOptionsRegion = (): string => {
49
+ const start = createRole.indexOf('can be:</phrase>');
50
+ return createRole.slice(start, createRole.indexOf('</synopsis>', start));
51
+ };
52
+
53
+ /** The first ALTER variant's option list: from the first `can be:</phrase>` to `RENAME TO`. */
54
+ const alterOptionsRegion = (): string => {
55
+ const start = alterRole.indexOf('can be:</phrase>');
56
+ return alterRole.slice(start, alterRole.indexOf('RENAME TO', start));
57
+ };
58
+
59
+ /** Every asserted prop except `name`, which is the mandatory `CREATE ROLE <name>` token, checked
60
+ * separately below. A boolean prop claims both its affirmative and its negative option. */
61
+ const PROP_MAPPING: Readonly<
62
+ Record<string, { readonly option: string; readonly also?: string; readonly column: string }>
63
+ > = {
64
+ login: { option: 'LOGIN', also: 'NOLOGIN', column: 'rolcanlogin' },
65
+ inherit: { option: 'INHERIT', also: 'NOINHERIT', column: 'rolinherit' },
66
+ connectionLimit: { option: 'CONNECTION LIMIT', column: 'rolconnlimit' },
67
+ validUntil: { option: 'VALID UNTIL', column: 'rolvaliduntil' },
68
+ // The value is never a prop (S25): the prop names the environment variable, and the value
69
+ // travels only in the dedicated `ALTER ROLE … WITH PASSWORD` statement.
70
+ password: { option: '[ ENCRYPTED ] PASSWORD', column: 'rolpassword' },
71
+ };
72
+
73
+ /** Every synopsis option this family does NOT declare as a prop, and why. */
74
+ const EXCLUDED: Readonly<Record<string, string>> = {
75
+ SUPERUSER:
76
+ 'left at the server default (NOSUPERUSER) on CREATE; an adopt or alter that finds rolsuper true is PostgresRolePrivilegedRefused — the flag is not inherited, SET ROLE exercises it',
77
+ NOSUPERUSER:
78
+ 'the server default for CREATE ROLE; never declared, so the default is what a create lands on',
79
+ CREATEDB:
80
+ "left at the server default (NOCREATEDB); database creation is Postgres.Database's job, not a role prop",
81
+ NOCREATEDB: 'the server default for CREATE ROLE; never declared',
82
+ CREATEROLE:
83
+ 'left at the server default (NOCREATEROLE) on CREATE; an adopt or alter that finds rolcreaterole true is refused — a CREATEROLE role can manage other roles',
84
+ NOCREATEROLE: 'the server default for CREATE ROLE; never declared',
85
+ REPLICATION:
86
+ 'left at the server default (NOREPLICATION); replication is a cluster-operator concern, never a seat role',
87
+ NOREPLICATION: 'the server default for CREATE ROLE; never declared',
88
+ BYPASSRLS:
89
+ 'left at the server default (NOBYPASSRLS) on CREATE; an adopt or alter that finds rolbypassrls true is refused',
90
+ NOBYPASSRLS: 'the server default for CREATE ROLE; never declared',
91
+ 'PASSWORD NULL':
92
+ 'clears the password; this family never clears one — a password is either declared by reference or left alone',
93
+ 'IN ROLE':
94
+ 'the create-time membership shorthand; this family writes memberships with one explicit GRANT per parent instead, so the re-read stays authoritative',
95
+ ROLE: 'grants the listed roles membership in the NEW role — the inverse of memberOf; membership is declared in one direction only',
96
+ ADMIN:
97
+ 'grants membership with ADMIN OPTION; a live membership that already has admin_option is revoked and re-granted without it, and the seat GRANT says SET FALSE',
98
+ SYSID:
99
+ 'ignored by the server since PostgreSQL 8.1 (the docs keep it only for compatibility); this family never assigns oids',
100
+ };
101
+
102
+ describe('postgres role provenance', () => {
103
+ test('fixture headers name the measured blob shas', () => {
104
+ expect(createRole).toContain(CREATE_ROLE_BLOB);
105
+ expect(createRole).toContain('doc/src/sgml/ref/create_role.sgml');
106
+ expect(alterRole).toContain(ALTER_ROLE_BLOB);
107
+ expect(alterRole).toContain('doc/src/sgml/ref/alter_role.sgml');
108
+ expect(authid).toContain(AUTHID_BLOB);
109
+ expect(authid).toContain('src/include/catalog/pg_authid.h');
110
+ expect(authMembers).toContain(AUTH_MEMBERS_BLOB);
111
+ expect(authMembers).toContain('src/include/catalog/pg_auth_members.h');
112
+ });
113
+
114
+ test('the name token is documented and backed by rolname', () => {
115
+ expect(createRole).toContain('CREATE ROLE <replaceable class="parameter">name</replaceable>');
116
+ expect(structColumns(authid)).toContain('rolname');
117
+ });
118
+
119
+ test('every declared prop maps to a real synopsis option (affirmative and negative)', () => {
120
+ const options = optionTokens(createOptionsRegion());
121
+ for (const [prop, { option, also }] of Object.entries(PROP_MAPPING)) {
122
+ expect(options, `prop "${prop}" claims synopsis option "${option}"`).toContain(option);
123
+ if (also !== undefined) {
124
+ expect(options, `prop "${prop}" claims negative option "${also}"`).toContain(also);
125
+ }
126
+ }
127
+ });
128
+
129
+ test('every declared prop maps to a real pg_authid column', () => {
130
+ const columns = structColumns(authid);
131
+ for (const [prop, { column }] of Object.entries(PROP_MAPPING)) {
132
+ expect(columns, `prop "${prop}" claims column "${column}"`).toContain(column);
133
+ }
134
+ });
135
+
136
+ test('memberOf is backed by the pg_auth_members catalog columns the membership read joins on', () => {
137
+ const columns = structColumns(authMembers);
138
+ expect(columns).toContain('roleid');
139
+ expect(columns).toContain('member');
140
+ });
141
+
142
+ test('every synopsis option is either a declared prop or a documented exclusion', () => {
143
+ const declared = new Set(
144
+ Object.values(PROP_MAPPING).flatMap((m) => [
145
+ m.option,
146
+ ...(m.also !== undefined ? [m.also] : []),
147
+ ]),
148
+ );
149
+ for (const option of optionTokens(createOptionsRegion())) {
150
+ const accounted = declared.has(option) || option in EXCLUDED;
151
+ expect(accounted, `synopsis option "${option}" is neither a prop nor in EXCLUDED`).toBe(true);
152
+ }
153
+ });
154
+
155
+ test('no excluded option is silently also a declared prop', () => {
156
+ const declared = new Set(
157
+ Object.values(PROP_MAPPING).flatMap((m) => [
158
+ m.option,
159
+ ...(m.also !== undefined ? [m.also] : []),
160
+ ]),
161
+ );
162
+ for (const option of Object.keys(EXCLUDED)) {
163
+ expect(declared.has(option), `"${option}" is both excluded and declared`).toBe(false);
164
+ }
165
+ });
166
+
167
+ test('every excluded option actually exists in the synopsis (no stale entries)', () => {
168
+ const options = new Set(optionTokens(createOptionsRegion()));
169
+ for (const option of Object.keys(EXCLUDED)) {
170
+ expect(
171
+ options.has(option),
172
+ `EXCLUDED names "${option}", which the synopsis no longer has`,
173
+ ).toBe(true);
174
+ }
175
+ });
176
+
177
+ test('ALTER ROLE backs every field this family alters', () => {
178
+ const alterOptions = optionTokens(alterOptionsRegion());
179
+ for (const option of Object.values(PROP_MAPPING).map((m) => m.option)) {
180
+ expect(alterOptions, `ALTER ROLE cannot set "${option}"`).toContain(option);
181
+ }
182
+ });
183
+
184
+ test('ALTER ROLE offers no membership or oid options, which is why memberships move via GRANT/REVOKE', () => {
185
+ const alterOptions = new Set(optionTokens(alterOptionsRegion()));
186
+ for (const option of ['IN ROLE', 'ROLE', 'ADMIN', 'SYSID']) {
187
+ expect(alterOptions.has(option), `ALTER ROLE unexpectedly offers "${option}"`).toBe(false);
188
+ }
189
+ });
190
+
191
+ test('the fixture carries the memberships sentence the one-parent GRANT/REVOKE design leans on', () => {
192
+ const stripped = alterRole.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ');
193
+ expect(stripped).toMatch(/no options[^;]*memberships/);
194
+ expect(stripped).toMatch(/use GRANT.{0,20}REVOKE/);
195
+ });
196
+
197
+ test('RENAME TO exists in the synopsis — the rename refusal is a choice, not an unknowing gap', () => {
198
+ expect(alterRole).toContain('RENAME TO');
199
+ });
200
+ });
@@ -0,0 +1,104 @@
1
+ /**
2
+ * `Postgres.Role`'s five lifecycle handlers, wired to `withPg` for anything that touches a
3
+ * client, and the one Layer a consuming stack provides. Split from `role.ts` so the file stays
4
+ * under the house cap: `role.ts` holds reconcile, `role-diff.ts` the plan diff; this file holds
5
+ * only the engine wiring.
6
+ */
7
+ import * as Provider from 'alchemy/Provider';
8
+ import { isResolved } from 'alchemy/Diff';
9
+ import * as Effect from 'effect/Effect';
10
+ import { ownedRead } from '../ownership/probe.ts';
11
+ import { noteUnfinished } from '../ownership/resume.ts';
12
+ import { refuseTakeover } from '../ownership/adopt.ts';
13
+ import { PostgresRole } from './role.ts';
14
+ import { readRole, reconcileWithClient, refuseAtPlan } from './role.ts';
15
+ import { diffPostgresRole } from './role-diff.ts';
16
+ import { PostgresRoleIdentityRefused } from './role-errors.ts';
17
+ import { buildDropRoleSql, declarationMatches } from './role-sql.ts';
18
+ import { withPg } from './connection.ts';
19
+
20
+ export const postgresRoleHandlers = PostgresRole.Provider.of({
21
+ // ⚠️ EMPTY, NOT A LIVE SWEEP: `pg_roles` lists every role on the cluster, most of which nothing
22
+ // declared — the same reasoning `Postgres.Database`'s `list` documents.
23
+ list: () => Effect.succeed([]),
24
+ nuke: { skip: true },
25
+
26
+ read: ({ fqn, instanceId, olds, output }) =>
27
+ Effect.gen(function* () {
28
+ const name = output?.name ?? olds.name;
29
+ const live = yield* withPg((pg) => readRole(pg, name));
30
+ if (live === undefined) return undefined;
31
+ // A recycled name is not the role state recorded. Failing (rather than `Unowned`) matters
32
+ // because drift strips `Unowned` and would then reconcile the foreign role.
33
+ if (output !== undefined && live.oid !== output.oid) {
34
+ return yield* Effect.fail(
35
+ new PostgresRoleIdentityRefused({
36
+ role: name,
37
+ storedOid: output.oid,
38
+ liveOid: live.oid,
39
+ }),
40
+ );
41
+ }
42
+ const passwordSeal = output?.passwordSeal ?? '';
43
+ const found = { ...live, passwordSeal };
44
+ return yield* ownedRead(
45
+ { fqn, instanceId, output },
46
+ found,
47
+ Effect.succeed(declarationMatches(olds, live)),
48
+ );
49
+ }),
50
+
51
+ diff: ({ news, output, instanceId }) =>
52
+ Effect.gen(function* () {
53
+ // A `creating` row has no attributes. Mark it unfinished so `--adopt` can resume it
54
+ // (ownership/resume.ts); the engine treats `undefined` as "defer".
55
+ if (output === undefined) return yield* noteUnfinished(instanceId);
56
+ if (!isResolved(news)) return undefined;
57
+ const found = yield* withPg((pg) => readRole(pg, output.name));
58
+ return yield* diffPostgresRole(news, output, process.env, { found });
59
+ }),
60
+
61
+ reconcile: ({ fqn, instanceId, news, output }) =>
62
+ Effect.gen(function* () {
63
+ yield* refuseAtPlan(news);
64
+ return yield* withPg((pg) =>
65
+ Effect.gen(function* () {
66
+ // Alchemy skips the plan probe while a prop is still an Output, and a role can
67
+ // appear between plan and apply. A live role with no state is a takeover: refuse
68
+ // before any ALTER, PASSWORD or REVOKE, unless `--adopt` speaks for this apply.
69
+ const observed = yield* readRole(pg, news.name);
70
+ if (observed !== undefined && output === undefined) {
71
+ yield* refuseTakeover({ fqn, instanceId, output }, 'Postgres.Role');
72
+ }
73
+ return yield* reconcileWithClient(
74
+ pg,
75
+ news,
76
+ process.env,
77
+ output?.passwordSeal,
78
+ output?.oid,
79
+ );
80
+ }),
81
+ );
82
+ }),
83
+
84
+ delete: ({ output }) =>
85
+ withPg((pg) =>
86
+ Effect.gen(function* () {
87
+ if (output === undefined) return;
88
+ const live = yield* readRole(pg, output.name);
89
+ if (live === undefined) return;
90
+ if (live.oid !== output.oid) {
91
+ return yield* Effect.fail(
92
+ new PostgresRoleIdentityRefused({
93
+ role: output.name,
94
+ storedOid: output.oid,
95
+ liveOid: live.oid,
96
+ }),
97
+ );
98
+ }
99
+ yield* pg.unsafe(buildDropRoleSql(output.name)).pipe(Effect.asVoid);
100
+ }),
101
+ ),
102
+ });
103
+
104
+ export const PostgresRoleProvider = () => Provider.succeed(PostgresRole, postgresRoleHandlers);