@homeflare/alchemy 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/README.md +10 -1
  2. package/dist/caddy/index.js +35 -1
  3. package/dist/caddy/index.js.map +3 -3
  4. package/dist/launchd/index.js +35 -1
  5. package/dist/launchd/index.js.map +3 -3
  6. package/dist/linux/index.js +35 -1
  7. package/dist/linux/index.js.map +3 -3
  8. package/dist/litellm/access-group-form.d.ts +26 -0
  9. package/dist/litellm/access-group-form.d.ts.map +1 -0
  10. package/dist/litellm/access-group-operations.d.ts +37 -0
  11. package/dist/litellm/access-group-operations.d.ts.map +1 -0
  12. package/dist/litellm/access-group-types.d.ts +49 -0
  13. package/dist/litellm/access-group-types.d.ts.map +1 -0
  14. package/dist/litellm/access-group.d.ts +55 -0
  15. package/dist/litellm/access-group.d.ts.map +1 -0
  16. package/dist/litellm/credential-errors.d.ts +131 -0
  17. package/dist/litellm/credential-errors.d.ts.map +1 -0
  18. package/dist/litellm/credential-form.d.ts +79 -0
  19. package/dist/litellm/credential-form.d.ts.map +1 -0
  20. package/dist/litellm/credential-operations.d.ts +84 -0
  21. package/dist/litellm/credential-operations.d.ts.map +1 -0
  22. package/dist/litellm/credential-rewrite.d.ts +6 -0
  23. package/dist/litellm/credential-rewrite.d.ts.map +1 -0
  24. package/dist/litellm/credential-types.d.ts +87 -0
  25. package/dist/litellm/credential-types.d.ts.map +1 -0
  26. package/dist/litellm/credential-values.d.ts +53 -0
  27. package/dist/litellm/credential-values.d.ts.map +1 -0
  28. package/dist/litellm/credential.d.ts +83 -0
  29. package/dist/litellm/credential.d.ts.map +1 -0
  30. package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
  31. package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
  32. package/dist/litellm/fake-credential-litellm.d.ts +54 -0
  33. package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
  34. package/dist/litellm/fake-keys.d.ts +53 -0
  35. package/dist/litellm/fake-keys.d.ts.map +1 -0
  36. package/dist/litellm/fake-litellm.d.ts +4 -1
  37. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  38. package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
  39. package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
  40. package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
  41. package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
  42. package/dist/litellm/fake-model-litellm.d.ts +48 -0
  43. package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
  44. package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
  45. package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
  46. package/dist/litellm/fake-policy-litellm.d.ts +32 -0
  47. package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
  48. package/dist/litellm/fake-registry-base.d.ts +42 -0
  49. package/dist/litellm/fake-registry-base.d.ts.map +1 -0
  50. package/dist/litellm/fake-stack.d.ts +8 -1
  51. package/dist/litellm/fake-stack.d.ts.map +1 -1
  52. package/dist/litellm/fake-team-litellm.d.ts +47 -0
  53. package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
  54. package/dist/litellm/fake-tool-litellm.d.ts +28 -0
  55. package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
  56. package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
  57. package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
  58. package/dist/litellm/index.d.ts +18 -0
  59. package/dist/litellm/index.d.ts.map +1 -1
  60. package/dist/litellm/index.js +3078 -2
  61. package/dist/litellm/index.js.map +65 -4
  62. package/dist/litellm/key-errors.d.ts +169 -0
  63. package/dist/litellm/key-errors.d.ts.map +1 -0
  64. package/dist/litellm/key-form.d.ts +119 -0
  65. package/dist/litellm/key-form.d.ts.map +1 -0
  66. package/dist/litellm/key-harness.d.ts +41 -0
  67. package/dist/litellm/key-harness.d.ts.map +1 -0
  68. package/dist/litellm/key-metadata-errors.d.ts +30 -0
  69. package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
  70. package/dist/litellm/key-metadata.d.ts +22 -0
  71. package/dist/litellm/key-metadata.d.ts.map +1 -0
  72. package/dist/litellm/key-operations.d.ts +63 -0
  73. package/dist/litellm/key-operations.d.ts.map +1 -0
  74. package/dist/litellm/key-secret.d.ts +33 -0
  75. package/dist/litellm/key-secret.d.ts.map +1 -0
  76. package/dist/litellm/key.d.ts +78 -0
  77. package/dist/litellm/key.d.ts.map +1 -0
  78. package/dist/litellm/mcp-server-credential.d.ts +50 -0
  79. package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
  80. package/dist/litellm/mcp-server-errors.d.ts +101 -0
  81. package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
  82. package/dist/litellm/mcp-server-form.d.ts +56 -0
  83. package/dist/litellm/mcp-server-form.d.ts.map +1 -0
  84. package/dist/litellm/mcp-server-locate.d.ts +26 -0
  85. package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
  86. package/dist/litellm/mcp-server-operations.d.ts +63 -0
  87. package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
  88. package/dist/litellm/mcp-server-shadow.d.ts +24 -0
  89. package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
  90. package/dist/litellm/mcp-server-types.d.ts +118 -0
  91. package/dist/litellm/mcp-server-types.d.ts.map +1 -0
  92. package/dist/litellm/mcp-server-url.d.ts +11 -0
  93. package/dist/litellm/mcp-server-url.d.ts.map +1 -0
  94. package/dist/litellm/mcp-server.d.ts +95 -0
  95. package/dist/litellm/mcp-server.d.ts.map +1 -0
  96. package/dist/litellm/model-claim.d.ts +24 -0
  97. package/dist/litellm/model-claim.d.ts.map +1 -0
  98. package/dist/litellm/model-credential.d.ts +12 -0
  99. package/dist/litellm/model-credential.d.ts.map +1 -0
  100. package/dist/litellm/model-errors.d.ts +119 -0
  101. package/dist/litellm/model-errors.d.ts.map +1 -0
  102. package/dist/litellm/model-form.d.ts +78 -0
  103. package/dist/litellm/model-form.d.ts.map +1 -0
  104. package/dist/litellm/model-locate.d.ts +13 -0
  105. package/dist/litellm/model-locate.d.ts.map +1 -0
  106. package/dist/litellm/model-operations.d.ts +59 -0
  107. package/dist/litellm/model-operations.d.ts.map +1 -0
  108. package/dist/litellm/model-types.d.ts +91 -0
  109. package/dist/litellm/model-types.d.ts.map +1 -0
  110. package/dist/litellm/model.d.ts +88 -0
  111. package/dist/litellm/model.d.ts.map +1 -0
  112. package/dist/litellm/policy-attachment-form.d.ts +19 -0
  113. package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
  114. package/dist/litellm/policy-attachment-operations.d.ts +31 -0
  115. package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
  116. package/dist/litellm/policy-attachment-types.d.ts +48 -0
  117. package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
  118. package/dist/litellm/policy-attachment.d.ts +61 -0
  119. package/dist/litellm/policy-attachment.d.ts.map +1 -0
  120. package/dist/litellm/policy-form.d.ts +22 -0
  121. package/dist/litellm/policy-form.d.ts.map +1 -0
  122. package/dist/litellm/policy-operations.d.ts +42 -0
  123. package/dist/litellm/policy-operations.d.ts.map +1 -0
  124. package/dist/litellm/policy-types.d.ts +57 -0
  125. package/dist/litellm/policy-types.d.ts.map +1 -0
  126. package/dist/litellm/policy.d.ts +65 -0
  127. package/dist/litellm/policy.d.ts.map +1 -0
  128. package/dist/litellm/providers.d.ts +1 -1
  129. package/dist/litellm/providers.d.ts.map +1 -1
  130. package/dist/litellm/registry-errors.d.ts +62 -0
  131. package/dist/litellm/registry-errors.d.ts.map +1 -0
  132. package/dist/litellm/registry-support.d.ts +42 -0
  133. package/dist/litellm/registry-support.d.ts.map +1 -0
  134. package/dist/litellm/team-form.d.ts +26 -0
  135. package/dist/litellm/team-form.d.ts.map +1 -0
  136. package/dist/litellm/team-members.d.ts +10 -0
  137. package/dist/litellm/team-members.d.ts.map +1 -0
  138. package/dist/litellm/team-operations.d.ts +38 -0
  139. package/dist/litellm/team-operations.d.ts.map +1 -0
  140. package/dist/litellm/team-permission.d.ts +35 -0
  141. package/dist/litellm/team-permission.d.ts.map +1 -0
  142. package/dist/litellm/team-types.d.ts +101 -0
  143. package/dist/litellm/team-types.d.ts.map +1 -0
  144. package/dist/litellm/team.d.ts +67 -0
  145. package/dist/litellm/team.d.ts.map +1 -0
  146. package/dist/litellm/tool-policy-form.d.ts +21 -0
  147. package/dist/litellm/tool-policy-form.d.ts.map +1 -0
  148. package/dist/litellm/tool-policy-operations.d.ts +30 -0
  149. package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
  150. package/dist/litellm/tool-policy-types.d.ts +46 -0
  151. package/dist/litellm/tool-policy-types.d.ts.map +1 -0
  152. package/dist/litellm/tool-policy.d.ts +62 -0
  153. package/dist/litellm/tool-policy.d.ts.map +1 -0
  154. package/dist/litellm/toolset-form.d.ts +20 -0
  155. package/dist/litellm/toolset-form.d.ts.map +1 -0
  156. package/dist/litellm/toolset-operations.d.ts +39 -0
  157. package/dist/litellm/toolset-operations.d.ts.map +1 -0
  158. package/dist/litellm/toolset-types.d.ts +46 -0
  159. package/dist/litellm/toolset-types.d.ts.map +1 -0
  160. package/dist/litellm/toolset.d.ts +55 -0
  161. package/dist/litellm/toolset.d.ts.map +1 -0
  162. package/dist/openbao/index.js +35 -1
  163. package/dist/openbao/index.js.map +3 -3
  164. package/dist/ownership/rows.d.ts +11 -0
  165. package/dist/ownership/rows.d.ts.map +1 -1
  166. package/dist/postgres/connection.d.ts +14 -2
  167. package/dist/postgres/connection.d.ts.map +1 -1
  168. package/dist/postgres/database-sql.d.ts +27 -8
  169. package/dist/postgres/database-sql.d.ts.map +1 -1
  170. package/dist/postgres/fake-grants-parse.d.ts +37 -0
  171. package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
  172. package/dist/postgres/fake-grants-read.d.ts +61 -0
  173. package/dist/postgres/fake-grants-read.d.ts.map +1 -0
  174. package/dist/postgres/fake-grants-sql.d.ts +46 -0
  175. package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
  176. package/dist/postgres/fake-grants-write.d.ts +29 -0
  177. package/dist/postgres/fake-grants-write.d.ts.map +1 -0
  178. package/dist/postgres/fake-role-sql.d.ts +41 -0
  179. package/dist/postgres/fake-role-sql.d.ts.map +1 -0
  180. package/dist/postgres/fake-schema-sql.d.ts +42 -0
  181. package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
  182. package/dist/postgres/fake-sql-parse.d.ts +23 -0
  183. package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
  184. package/dist/postgres/fake-sql-quote.d.ts +12 -0
  185. package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
  186. package/dist/postgres/fake-sql.d.ts +42 -0
  187. package/dist/postgres/fake-sql.d.ts.map +1 -1
  188. package/dist/postgres/grants-attrs.d.ts +115 -0
  189. package/dist/postgres/grants-attrs.d.ts.map +1 -0
  190. package/dist/postgres/grants-declare.d.ts +88 -0
  191. package/dist/postgres/grants-declare.d.ts.map +1 -0
  192. package/dist/postgres/grants-diff.d.ts +25 -0
  193. package/dist/postgres/grants-diff.d.ts.map +1 -0
  194. package/dist/postgres/grants-errors.d.ts +137 -0
  195. package/dist/postgres/grants-errors.d.ts.map +1 -0
  196. package/dist/postgres/grants-existence.d.ts +14 -0
  197. package/dist/postgres/grants-existence.d.ts.map +1 -0
  198. package/dist/postgres/grants-ops.d.ts +65 -0
  199. package/dist/postgres/grants-ops.d.ts.map +1 -0
  200. package/dist/postgres/grants-ownership.d.ts +18 -0
  201. package/dist/postgres/grants-ownership.d.ts.map +1 -0
  202. package/dist/postgres/grants-plan-restore.d.ts +22 -0
  203. package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
  204. package/dist/postgres/grants-plan.d.ts +65 -0
  205. package/dist/postgres/grants-plan.d.ts.map +1 -0
  206. package/dist/postgres/grants-read-defaults.d.ts +17 -0
  207. package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
  208. package/dist/postgres/grants-read.d.ts +77 -0
  209. package/dist/postgres/grants-read.d.ts.map +1 -0
  210. package/dist/postgres/grants-refuse.d.ts +25 -0
  211. package/dist/postgres/grants-refuse.d.ts.map +1 -0
  212. package/dist/postgres/grants-sql.d.ts +42 -0
  213. package/dist/postgres/grants-sql.d.ts.map +1 -0
  214. package/dist/postgres/grants-words.d.ts +29 -0
  215. package/dist/postgres/grants-words.d.ts.map +1 -0
  216. package/dist/postgres/grants.d.ts +37 -0
  217. package/dist/postgres/grants.d.ts.map +1 -0
  218. package/dist/postgres/index.d.ts +31 -6
  219. package/dist/postgres/index.d.ts.map +1 -1
  220. package/dist/postgres/index.js +1998 -37
  221. package/dist/postgres/index.js.map +46 -7
  222. package/dist/postgres/installed-classifier.d.ts +13 -0
  223. package/dist/postgres/installed-classifier.d.ts.map +1 -0
  224. package/dist/postgres/providers.d.ts +16 -8
  225. package/dist/postgres/providers.d.ts.map +1 -1
  226. package/dist/postgres/psql-executor.d.ts +4 -0
  227. package/dist/postgres/psql-executor.d.ts.map +1 -1
  228. package/dist/postgres/role-attrs.d.ts +112 -0
  229. package/dist/postgres/role-attrs.d.ts.map +1 -0
  230. package/dist/postgres/role-diff.d.ts +22 -0
  231. package/dist/postgres/role-diff.d.ts.map +1 -0
  232. package/dist/postgres/role-errors.d.ts +132 -0
  233. package/dist/postgres/role-errors.d.ts.map +1 -0
  234. package/dist/postgres/role-membership-sql.d.ts +78 -0
  235. package/dist/postgres/role-membership-sql.d.ts.map +1 -0
  236. package/dist/postgres/role-provider.d.ts +11 -0
  237. package/dist/postgres/role-provider.d.ts.map +1 -0
  238. package/dist/postgres/role-scram.d.ts +8 -0
  239. package/dist/postgres/role-scram.d.ts.map +1 -0
  240. package/dist/postgres/role-secrets.d.ts +38 -0
  241. package/dist/postgres/role-secrets.d.ts.map +1 -0
  242. package/dist/postgres/role-sql.d.ts +68 -0
  243. package/dist/postgres/role-sql.d.ts.map +1 -0
  244. package/dist/postgres/role.d.ts +57 -0
  245. package/dist/postgres/role.d.ts.map +1 -0
  246. package/dist/postgres/schema-assert.d.ts +50 -0
  247. package/dist/postgres/schema-assert.d.ts.map +1 -0
  248. package/dist/postgres/schema-attrs.d.ts +51 -0
  249. package/dist/postgres/schema-attrs.d.ts.map +1 -0
  250. package/dist/postgres/schema-delete.d.ts +28 -0
  251. package/dist/postgres/schema-delete.d.ts.map +1 -0
  252. package/dist/postgres/schema-diff.d.ts +14 -0
  253. package/dist/postgres/schema-diff.d.ts.map +1 -0
  254. package/dist/postgres/schema-errors.d.ts +139 -0
  255. package/dist/postgres/schema-errors.d.ts.map +1 -0
  256. package/dist/postgres/schema-identity.d.ts +8 -0
  257. package/dist/postgres/schema-identity.d.ts.map +1 -0
  258. package/dist/postgres/schema-reconcile.d.ts +12 -0
  259. package/dist/postgres/schema-reconcile.d.ts.map +1 -0
  260. package/dist/postgres/schema-sql.d.ts +45 -0
  261. package/dist/postgres/schema-sql.d.ts.map +1 -0
  262. package/dist/postgres/schema-test-kit.d.ts +67 -0
  263. package/dist/postgres/schema-test-kit.d.ts.map +1 -0
  264. package/dist/postgres/schema.d.ts +54 -0
  265. package/dist/postgres/schema.d.ts.map +1 -0
  266. package/dist/proxmox/index.js +35 -1
  267. package/dist/proxmox/index.js.map +3 -3
  268. package/dist/release/fake-engine.d.ts +10 -0
  269. package/dist/release/fake-engine.d.ts.map +1 -1
  270. package/dist/release/index.js +35 -1
  271. package/dist/release/index.js.map +3 -3
  272. package/dist/valkey/acl-attrs.d.ts +94 -0
  273. package/dist/valkey/acl-attrs.d.ts.map +1 -0
  274. package/dist/valkey/acl-compare.d.ts +28 -0
  275. package/dist/valkey/acl-compare.d.ts.map +1 -0
  276. package/dist/valkey/acl-connection.d.ts +6 -0
  277. package/dist/valkey/acl-connection.d.ts.map +1 -0
  278. package/dist/valkey/acl-form.d.ts +62 -0
  279. package/dist/valkey/acl-form.d.ts.map +1 -0
  280. package/dist/valkey/acl-managed.d.ts +4 -0
  281. package/dist/valkey/acl-managed.d.ts.map +1 -0
  282. package/dist/valkey/acl-ops.d.ts +37 -0
  283. package/dist/valkey/acl-ops.d.ts.map +1 -0
  284. package/dist/valkey/acl-profiles.d.ts +53 -0
  285. package/dist/valkey/acl-profiles.d.ts.map +1 -0
  286. package/dist/valkey/acl-reconcile.d.ts +26 -0
  287. package/dist/valkey/acl-reconcile.d.ts.map +1 -0
  288. package/dist/valkey/acl.d.ts +24 -0
  289. package/dist/valkey/acl.d.ts.map +1 -0
  290. package/dist/valkey/connection-service.d.ts +22 -0
  291. package/dist/valkey/connection-service.d.ts.map +1 -0
  292. package/dist/valkey/connection.d.ts +59 -0
  293. package/dist/valkey/connection.d.ts.map +1 -0
  294. package/dist/valkey/errors.d.ts +165 -0
  295. package/dist/valkey/errors.d.ts.map +1 -0
  296. package/dist/valkey/fake-acl.d.ts +29 -0
  297. package/dist/valkey/fake-acl.d.ts.map +1 -0
  298. package/dist/valkey/fake-valkey.d.ts +35 -0
  299. package/dist/valkey/fake-valkey.d.ts.map +1 -0
  300. package/dist/valkey/handler-test-fixture.d.ts +20 -0
  301. package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
  302. package/dist/valkey/index.d.ts +18 -0
  303. package/dist/valkey/index.d.ts.map +1 -0
  304. package/dist/valkey/index.js +964 -0
  305. package/dist/valkey/index.js.map +27 -0
  306. package/dist/valkey/instance-attrs.d.ts +46 -0
  307. package/dist/valkey/instance-attrs.d.ts.map +1 -0
  308. package/dist/valkey/instance-form.d.ts +22 -0
  309. package/dist/valkey/instance-form.d.ts.map +1 -0
  310. package/dist/valkey/instance.d.ts +48 -0
  311. package/dist/valkey/instance.d.ts.map +1 -0
  312. package/dist/valkey/provider-socket-fixture.d.ts +8 -0
  313. package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
  314. package/dist/valkey/providers.d.ts +16 -0
  315. package/dist/valkey/providers.d.ts.map +1 -0
  316. package/dist/valkey/resp.d.ts +38 -0
  317. package/dist/valkey/resp.d.ts.map +1 -0
  318. package/dist/valkey/transport-error.d.ts +36 -0
  319. package/dist/valkey/transport-error.d.ts.map +1 -0
  320. package/dist/valkey/transport.d.ts +50 -0
  321. package/dist/valkey/transport.d.ts.map +1 -0
  322. package/docs/litellm-access-group.md +105 -0
  323. package/docs/litellm-credential.md +60 -0
  324. package/docs/litellm-key-metadata.md +56 -0
  325. package/docs/litellm-key.md +194 -0
  326. package/docs/litellm-mcp.md +187 -0
  327. package/docs/litellm-model.md +111 -0
  328. package/docs/litellm-policy-attachment.md +86 -0
  329. package/docs/litellm-policy.md +103 -0
  330. package/docs/litellm-team.md +117 -0
  331. package/docs/litellm-tool-policy.md +90 -0
  332. package/docs/litellm-toolset.md +92 -0
  333. package/docs/litellm.md +16 -9
  334. package/docs/peers.md +15 -6
  335. package/docs/postgres-grants-example.md +55 -0
  336. package/docs/postgres-grants.md +157 -0
  337. package/docs/postgres-role.md +126 -0
  338. package/docs/postgres-schema.md +139 -0
  339. package/docs/postgres.md +20 -3
  340. package/docs/valkey-transport.md +29 -0
  341. package/docs/valkey.md +187 -0
  342. package/package.json +6 -2
  343. package/src/ceph/ceph-argv.test.ts +1 -1
  344. package/src/launchd/sudo-allowlist.test.ts +2 -2
  345. package/src/linux/sudo-allowlist.test.ts +3 -3
  346. package/src/linux/sudo-runner.test.ts +2 -2
  347. package/src/litellm/access-group-form.ts +105 -0
  348. package/src/litellm/access-group-operations.ts +92 -0
  349. package/src/litellm/access-group-types.ts +49 -0
  350. package/src/litellm/access-group.test.ts +197 -0
  351. package/src/litellm/access-group.ts +151 -0
  352. package/src/litellm/credential-errors.ts +183 -0
  353. package/src/litellm/credential-form.test.ts +151 -0
  354. package/src/litellm/credential-form.ts +211 -0
  355. package/src/litellm/credential-guards.test.ts +241 -0
  356. package/src/litellm/credential-operations.ts +208 -0
  357. package/src/litellm/credential-recovery.test.ts +93 -0
  358. package/src/litellm/credential-rewrite.test.ts +164 -0
  359. package/src/litellm/credential-rewrite.ts +50 -0
  360. package/src/litellm/credential-types.ts +117 -0
  361. package/src/litellm/credential-values.ts +94 -0
  362. package/src/litellm/credential.test.ts +218 -0
  363. package/src/litellm/credential.ts +227 -0
  364. package/src/litellm/fake-access-group-litellm.ts +127 -0
  365. package/src/litellm/fake-credential-litellm.ts +216 -0
  366. package/src/litellm/fake-keys.ts +190 -0
  367. package/src/litellm/fake-litellm.ts +19 -9
  368. package/src/litellm/fake-mcp-litellm.ts +214 -0
  369. package/src/litellm/fake-model-litellm-post-update.ts +103 -0
  370. package/src/litellm/fake-model-litellm.ts +233 -0
  371. package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
  372. package/src/litellm/fake-policy-litellm.ts +186 -0
  373. package/src/litellm/fake-registry-base.ts +69 -0
  374. package/src/litellm/fake-stack.ts +17 -1
  375. package/src/litellm/fake-team-litellm.ts +229 -0
  376. package/src/litellm/fake-tool-litellm.ts +88 -0
  377. package/src/litellm/fake-toolset-litellm.ts +110 -0
  378. package/src/litellm/index.ts +140 -0
  379. package/src/litellm/key-delete.test.ts +212 -0
  380. package/src/litellm/key-errors.ts +241 -0
  381. package/src/litellm/key-form.ts +200 -0
  382. package/src/litellm/key-harness.ts +121 -0
  383. package/src/litellm/key-metadata-errors.ts +49 -0
  384. package/src/litellm/key-metadata.test.ts +156 -0
  385. package/src/litellm/key-metadata.ts +74 -0
  386. package/src/litellm/key-operations.ts +184 -0
  387. package/src/litellm/key-rotation.test.ts +110 -0
  388. package/src/litellm/key-scope.test.ts +135 -0
  389. package/src/litellm/key-secret.test.ts +248 -0
  390. package/src/litellm/key-secret.ts +137 -0
  391. package/src/litellm/key-transport.test.ts +166 -0
  392. package/src/litellm/key.test.ts +231 -0
  393. package/src/litellm/key.ts +213 -0
  394. package/src/litellm/mcp-server-adopt.test.ts +86 -0
  395. package/src/litellm/mcp-server-alias.test.ts +184 -0
  396. package/src/litellm/mcp-server-credential.ts +85 -0
  397. package/src/litellm/mcp-server-errors.ts +141 -0
  398. package/src/litellm/mcp-server-exports.test.ts +15 -0
  399. package/src/litellm/mcp-server-form.test.ts +241 -0
  400. package/src/litellm/mcp-server-form.ts +233 -0
  401. package/src/litellm/mcp-server-handlers.test.ts +150 -0
  402. package/src/litellm/mcp-server-locate.ts +66 -0
  403. package/src/litellm/mcp-server-operations.ts +111 -0
  404. package/src/litellm/mcp-server-registry.test.ts +146 -0
  405. package/src/litellm/mcp-server-retype.test.ts +114 -0
  406. package/src/litellm/mcp-server-shadow.test.ts +91 -0
  407. package/src/litellm/mcp-server-shadow.ts +45 -0
  408. package/src/litellm/mcp-server-tools.test.ts +85 -0
  409. package/src/litellm/mcp-server-types.ts +143 -0
  410. package/src/litellm/mcp-server-url.ts +66 -0
  411. package/src/litellm/mcp-server.test.ts +213 -0
  412. package/src/litellm/mcp-server.ts +225 -0
  413. package/src/litellm/model-claim.ts +69 -0
  414. package/src/litellm/model-credential.ts +45 -0
  415. package/src/litellm/model-errors.ts +168 -0
  416. package/src/litellm/model-foreign-row.test.ts +173 -0
  417. package/src/litellm/model-form.test.ts +228 -0
  418. package/src/litellm/model-form.ts +223 -0
  419. package/src/litellm/model-locate.test.ts +128 -0
  420. package/src/litellm/model-locate.ts +67 -0
  421. package/src/litellm/model-operations.test.ts +93 -0
  422. package/src/litellm/model-operations.ts +146 -0
  423. package/src/litellm/model-params-preserve.test.ts +119 -0
  424. package/src/litellm/model-recovery.test.ts +57 -0
  425. package/src/litellm/model-types.ts +112 -0
  426. package/src/litellm/model.test.ts +222 -0
  427. package/src/litellm/model.ts +237 -0
  428. package/src/litellm/policy-attachment-form.ts +103 -0
  429. package/src/litellm/policy-attachment-operations.ts +74 -0
  430. package/src/litellm/policy-attachment-types.ts +48 -0
  431. package/src/litellm/policy-attachment.test.ts +198 -0
  432. package/src/litellm/policy-attachment.ts +178 -0
  433. package/src/litellm/policy-form.ts +122 -0
  434. package/src/litellm/policy-operations.ts +112 -0
  435. package/src/litellm/policy-types.ts +58 -0
  436. package/src/litellm/policy.test.ts +214 -0
  437. package/src/litellm/policy.ts +146 -0
  438. package/src/litellm/providers.ts +24 -3
  439. package/src/litellm/registry-errors.ts +88 -0
  440. package/src/litellm/registry-exports.test.ts +66 -0
  441. package/src/litellm/registry-support.ts +109 -0
  442. package/src/litellm/team-form.ts +140 -0
  443. package/src/litellm/team-members.test.ts +150 -0
  444. package/src/litellm/team-members.ts +58 -0
  445. package/src/litellm/team-operations.ts +90 -0
  446. package/src/litellm/team-permission.ts +159 -0
  447. package/src/litellm/team-read.test.ts +89 -0
  448. package/src/litellm/team-types.ts +106 -0
  449. package/src/litellm/team.test.ts +206 -0
  450. package/src/litellm/team.ts +159 -0
  451. package/src/litellm/tool-policy-form.ts +94 -0
  452. package/src/litellm/tool-policy-operations.ts +58 -0
  453. package/src/litellm/tool-policy-types.ts +48 -0
  454. package/src/litellm/tool-policy.test.ts +172 -0
  455. package/src/litellm/tool-policy.ts +125 -0
  456. package/src/litellm/toolset-form.ts +104 -0
  457. package/src/litellm/toolset-operations.ts +90 -0
  458. package/src/litellm/toolset-types.ts +47 -0
  459. package/src/litellm/toolset.test.ts +198 -0
  460. package/src/litellm/toolset.ts +151 -0
  461. package/src/ownership/ownership.test.ts +33 -1
  462. package/src/ownership/rows.ts +53 -0
  463. package/src/postgres/connection.ts +42 -7
  464. package/src/postgres/database-bigint-serialization.test.ts +1 -0
  465. package/src/postgres/database-refusals.test.ts +2 -2
  466. package/src/postgres/database-sql.ts +36 -9
  467. package/src/postgres/fake-grants-parse.ts +189 -0
  468. package/src/postgres/fake-grants-read.ts +250 -0
  469. package/src/postgres/fake-grants-sql.ts +207 -0
  470. package/src/postgres/fake-grants-write.ts +90 -0
  471. package/src/postgres/fake-role-sql.ts +240 -0
  472. package/src/postgres/fake-schema-semantics.test.ts +36 -0
  473. package/src/postgres/fake-schema-sql.ts +146 -0
  474. package/src/postgres/fake-sql-parse.ts +86 -0
  475. package/src/postgres/fake-sql-quote.ts +36 -0
  476. package/src/postgres/fake-sql.ts +166 -46
  477. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
  478. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
  479. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
  480. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
  481. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
  482. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
  483. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
  484. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
  485. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
  486. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
  487. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
  488. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
  489. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
  490. package/src/postgres/grants-acl.test.ts +61 -0
  491. package/src/postgres/grants-attrs.ts +185 -0
  492. package/src/postgres/grants-database.test.ts +158 -0
  493. package/src/postgres/grants-declare.ts +172 -0
  494. package/src/postgres/grants-delete-proof.test.ts +154 -0
  495. package/src/postgres/grants-diff.ts +101 -0
  496. package/src/postgres/grants-errors.ts +215 -0
  497. package/src/postgres/grants-existence-guards.test.ts +113 -0
  498. package/src/postgres/grants-existence.ts +101 -0
  499. package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
  500. package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
  501. package/src/postgres/grants-lifecycle.test.ts +181 -0
  502. package/src/postgres/grants-ops.ts +229 -0
  503. package/src/postgres/grants-owner-revoke.test.ts +121 -0
  504. package/src/postgres/grants-ownership.ts +49 -0
  505. package/src/postgres/grants-plan-collateral.test.ts +202 -0
  506. package/src/postgres/grants-plan-diff.test.ts +204 -0
  507. package/src/postgres/grants-plan-restore.ts +43 -0
  508. package/src/postgres/grants-plan-revocations.test.ts +69 -0
  509. package/src/postgres/grants-plan.test.ts +148 -0
  510. package/src/postgres/grants-plan.ts +245 -0
  511. package/src/postgres/grants-provenance.test.ts +134 -0
  512. package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
  513. package/src/postgres/grants-read-absent.test.ts +91 -0
  514. package/src/postgres/grants-read-defaults.ts +51 -0
  515. package/src/postgres/grants-read.ts +250 -0
  516. package/src/postgres/grants-refusals.test.ts +136 -0
  517. package/src/postgres/grants-refuse.ts +119 -0
  518. package/src/postgres/grants-relkind-wire.test.ts +111 -0
  519. package/src/postgres/grants-repair-plan.test.ts +201 -0
  520. package/src/postgres/grants-sql.test.ts +128 -0
  521. package/src/postgres/grants-sql.ts +144 -0
  522. package/src/postgres/grants-words.ts +34 -0
  523. package/src/postgres/grants.ts +110 -0
  524. package/src/postgres/index.ts +129 -5
  525. package/src/postgres/installed-classifier.ts +36 -0
  526. package/src/postgres/providers.ts +33 -9
  527. package/src/postgres/psql-executor-escaping.test.ts +67 -0
  528. package/src/postgres/psql-executor.test.ts +63 -2
  529. package/src/postgres/psql-executor.ts +74 -34
  530. package/src/postgres/role-adopt.test.ts +98 -0
  531. package/src/postgres/role-attrs.ts +137 -0
  532. package/src/postgres/role-diff.ts +93 -0
  533. package/src/postgres/role-errors.ts +206 -0
  534. package/src/postgres/role-guard.test.ts +60 -0
  535. package/src/postgres/role-identity.test.ts +197 -0
  536. package/src/postgres/role-lifecycle.test.ts +228 -0
  537. package/src/postgres/role-membership-options.test.ts +73 -0
  538. package/src/postgres/role-membership-repair.test.ts +153 -0
  539. package/src/postgres/role-membership-sql.ts +223 -0
  540. package/src/postgres/role-password-ascii.test.ts +53 -0
  541. package/src/postgres/role-password-transports.test.ts +123 -0
  542. package/src/postgres/role-password.test.ts +158 -0
  543. package/src/postgres/role-privilege.test.ts +107 -0
  544. package/src/postgres/role-provenance.test.ts +200 -0
  545. package/src/postgres/role-provider.ts +105 -0
  546. package/src/postgres/role-refusals.test.ts +225 -0
  547. package/src/postgres/role-scram.test.ts +38 -0
  548. package/src/postgres/role-scram.ts +40 -0
  549. package/src/postgres/role-secrets.ts +61 -0
  550. package/src/postgres/role-sql.ts +213 -0
  551. package/src/postgres/role-valid-until.test.ts +68 -0
  552. package/src/postgres/role.ts +226 -0
  553. package/src/postgres/schema-assert.ts +139 -0
  554. package/src/postgres/schema-attrs.ts +71 -0
  555. package/src/postgres/schema-delete-proofs.test.ts +192 -0
  556. package/src/postgres/schema-delete.ts +96 -0
  557. package/src/postgres/schema-diff.ts +44 -0
  558. package/src/postgres/schema-drop-2bp01.test.ts +146 -0
  559. package/src/postgres/schema-errors.ts +209 -0
  560. package/src/postgres/schema-handlers.test.ts +193 -0
  561. package/src/postgres/schema-identity.ts +39 -0
  562. package/src/postgres/schema-lifecycle.test.ts +246 -0
  563. package/src/postgres/schema-race.test.ts +70 -0
  564. package/src/postgres/schema-reconcile.ts +100 -0
  565. package/src/postgres/schema-refusals.test.ts +144 -0
  566. package/src/postgres/schema-socket.test.ts +162 -0
  567. package/src/postgres/schema-sql.ts +130 -0
  568. package/src/postgres/schema-takeover.test.ts +149 -0
  569. package/src/postgres/schema-test-kit.ts +85 -0
  570. package/src/postgres/schema.ts +130 -0
  571. package/src/release/binary-alias.test.ts +3 -3
  572. package/src/release/binary-claims.test.ts +3 -3
  573. package/src/release/binary-directory-umask.test.ts +65 -0
  574. package/src/release/fake-engine.ts +15 -0
  575. package/src/valkey/acl-attrs.ts +98 -0
  576. package/src/valkey/acl-compare.ts +57 -0
  577. package/src/valkey/acl-connection.ts +13 -0
  578. package/src/valkey/acl-delete.test.ts +127 -0
  579. package/src/valkey/acl-form.ts +239 -0
  580. package/src/valkey/acl-managed.ts +13 -0
  581. package/src/valkey/acl-ops.ts +122 -0
  582. package/src/valkey/acl-ownership.test.ts +118 -0
  583. package/src/valkey/acl-prefix.test.ts +38 -0
  584. package/src/valkey/acl-profiles.ts +81 -0
  585. package/src/valkey/acl-reconcile.ts +180 -0
  586. package/src/valkey/acl-reserved.test.ts +69 -0
  587. package/src/valkey/acl-revocation.test.ts +94 -0
  588. package/src/valkey/acl-seat-prefix.test.ts +111 -0
  589. package/src/valkey/acl-validation.test.ts +54 -0
  590. package/src/valkey/acl.test.ts +215 -0
  591. package/src/valkey/acl.ts +169 -0
  592. package/src/valkey/connection-service.ts +46 -0
  593. package/src/valkey/connection.ts +180 -0
  594. package/src/valkey/errors.ts +239 -0
  595. package/src/valkey/fake-acl.ts +128 -0
  596. package/src/valkey/fake-valkey.ts +224 -0
  597. package/src/valkey/handler-test-fixture.ts +43 -0
  598. package/src/valkey/handlers.test.ts +205 -0
  599. package/src/valkey/index.ts +54 -0
  600. package/src/valkey/instance-attrs.ts +48 -0
  601. package/src/valkey/instance-form.ts +104 -0
  602. package/src/valkey/instance.test.ts +108 -0
  603. package/src/valkey/instance.ts +160 -0
  604. package/src/valkey/provider-socket-fixture.ts +71 -0
  605. package/src/valkey/providers.test.ts +129 -0
  606. package/src/valkey/providers.ts +21 -0
  607. package/src/valkey/resp.ts +212 -0
  608. package/src/valkey/transport-bounds.test.ts +150 -0
  609. package/src/valkey/transport-error.ts +37 -0
  610. package/src/valkey/transport.test.ts +158 -0
  611. package/src/valkey/transport.ts +109 -0
  612. package/src/valkey/upstream-bounds.test.ts +14 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * `Postgres.Role` props and attributes, and the plan-time checks that run before any statement.
3
+ *
4
+ * ⛔ EVERY ASSERTED PROP TRACES TO A REAL `CREATE ROLE` / `ALTER ROLE` OPTION AND A REAL CATALOG
5
+ * COLUMN. `role-provenance.test.ts` parses the committed fixtures (`create_role.sgml`,
6
+ * `alter_role.sgml`, `pg_authid.h`, `pg_auth_members.h`) and fails if that mapping breaks.
7
+ * ⛔ NO PASSWORD VALUE AS A PROP (S25). `password` is declared as
8
+ * `{ fromEnv: 'PG_SEAT_WIDGET_PASSWORD' }`, never a string. The name lives in state; the value
9
+ * is resolved from the deploying process's environment at reconcile time, wrapped in
10
+ * `Redacted`, and quoted into the one statement that needs it.
11
+ * ★ UNLIKE `Postgres.Database`, THIS FAMILY IS ALTER-CAPABLE: `LOGIN`/`NOLOGIN`,
12
+ * `INHERIT`/`NOINHERIT`, `CONNECTION LIMIT` and `VALID UNTIL` all have a safe atomic
13
+ * `ALTER ROLE` form (`alter_role.sgml`'s first synopsis variant), so a drifted live row is
14
+ * brought back to the declaration instead of refused.
15
+ */
16
+ import type { FromEnv } from '../secrets/write-only.ts';
17
+
18
+ /** Re-exported for tests that operate on identifier byte length. */
19
+ export { POSTGRES_NAME_MAX_BYTES, nameByteRefusal, utf8ByteLength } from './database-attrs.ts';
20
+
21
+ /**
22
+ * A declared `validUntil` must carry its own UTC designator (`Z`) or numeric offset (`+02:00`).
23
+ *
24
+ * ⛔ WHY A ZONE-FREE TIMESTAMP IS REFUSED AT PLAN. PostgreSQL reads `VALID UNTIL '2027-01-01'`
25
+ * as midnight in the SESSION's time zone; the deploying process parses the same string as UTC
26
+ * (ECMAScript's rule for date-only forms). The instants differ, so the value read back would
27
+ * never equal the declaration, and every plan would issue the same `ALTER ROLE … VALID UNTIL`
28
+ * forever — the exact silent loop this family refuses elsewhere. A string ECMAScript cannot
29
+ * parse at all reaches the same refusal; PostgreSQL would reject it too, only later and as an
30
+ * unclassified statement error.
31
+ */
32
+ const VALID_UNTIL_OFFSET = /(?:Z|[+-]\d{2}:\d{2})$/;
33
+
34
+ export const validUntilRefusal = (
35
+ value: string,
36
+ ): { readonly reason: 'unparseable' | 'zone-free' } | undefined => {
37
+ // A zone suffix is not a timestamp. `2027-13-01T00:00:00Z` and `not-a-dateZ` match the
38
+ // offset and `Date.parse` to NaN; accepting them sends a VALID UNTIL PostgreSQL rejects, or
39
+ // one that never compares equal on read-back, so every later reconcile re-issues the ALTER.
40
+ if (Number.isNaN(Date.parse(value))) return { reason: 'unparseable' };
41
+ if (VALID_UNTIL_OFFSET.test(value)) return undefined;
42
+ return { reason: 'zone-free' };
43
+ };
44
+
45
+ /** Whether a declared `validUntil` and the live serialised value name the same instant. Both
46
+ * sides are plan-checked parseable, so `NaN` cannot reach here. */
47
+ export const sameValidUntil = (declared: string, live: string | null): boolean =>
48
+ live !== null && Date.parse(declared) === Date.parse(live);
49
+
50
+ /**
51
+ * Declared properties of one role.
52
+ *
53
+ * `login` and `inherit` are required: the resource configures a LOGIN or NOLOGIN role with
54
+ * INHERIT explicit, per the seat-wiring spec's group-role-per-seat shape (`NOLOGIN`, member of
55
+ * `hf_agent`, owning its own schema). An undeclared boolean would silently adopt whatever the
56
+ * live row already says — the opposite of idempotent.
57
+ */
58
+ export interface PostgresRoleProps {
59
+ /** At most 63 UTF-8 bytes — refused at plan/reconcile if larger (`PostgresRoleNameRefused`). */
60
+ readonly name: string;
61
+ /** `LOGIN` or `NOLOGIN` — maps to `pg_roles.rolcanlogin`. */
62
+ readonly login: boolean;
63
+ /** `CONNECTION LIMIT n`, `-1` for unlimited — maps to `pg_roles.rolconnlimit`. */
64
+ readonly connectionLimit: number;
65
+ /** `INHERIT` or `NOINHERIT` — maps to `pg_roles.rolinherit`; false also clears per-grant
66
+ * INHERIT on declared memberships (PG 16+ uses the role flag only to default new grants). */
67
+ readonly inherit: boolean;
68
+ /**
69
+ * `VALID UNTIL 'timestamp'` — maps to `pg_roles.rolvaliduntil`. ISO 8601 without a timezone is
70
+ * accepted by PostgreSQL's `timestamptz` input (it is interpreted in the client's time zone);
71
+ * an ISO 8601 string carrying `Z` is unambiguous, so the docs recommend declaring it. Omitted
72
+ * means "leave the live value alone" — the resource never clears an expiry it did not declare.
73
+ */
74
+ readonly validUntil?: string;
75
+ /**
76
+ * The roles this role is a member of (`GRANT parent TO this`). Backed by `pg_auth_members`.
77
+ * Compared when declared; omitted leaves live memberships untouched. Empty array means
78
+ * "ensure none".
79
+ */
80
+ readonly memberOf?: readonly string[];
81
+ /**
82
+ * `PASSWORD '...'` by the NAME of the environment variable holding it. Omitted means "leave
83
+ * the live password alone" (and `NOLOGIN` group roles need none). Required once, before the
84
+ * first create that declares it, and on every later write while the variable is set — a value
85
+ * the environment stopped providing is never guessed.
86
+ */
87
+ readonly password?: FromEnv;
88
+ }
89
+
90
+ /** Live attributes, read back after every reconcile. `passwordValue` is NEVER stored (S25). */
91
+ export interface PostgresRoleAttributes {
92
+ readonly name: string;
93
+ readonly oid: number;
94
+ readonly login: boolean;
95
+ readonly connectionLimit: number;
96
+ readonly inherit: boolean;
97
+ /** ISO 8601 (`...Z`), server-side serialised; `null` when the live row has no expiry. */
98
+ readonly validUntil: string | null;
99
+ /**
100
+ * Catalog flags this family never declares. A create lands on the server default (all false).
101
+ * An adopt or alter that finds any of them true is refused — they are not inherited, so a
102
+ * member who `SET ROLE`s to this role would exercise them. Absent on a seeded test row means
103
+ * false, the default a `CREATE ROLE` without the option lands on.
104
+ */
105
+ readonly superuser?: boolean;
106
+ readonly createrole?: boolean;
107
+ readonly createdb?: boolean;
108
+ readonly replication?: boolean;
109
+ readonly bypassrls?: boolean;
110
+ /**
111
+ * Parent role names, sorted. Empty array when the role is a member of nothing. Null means
112
+ * "memberships were not declared on this resource", so the field is not asserted.
113
+ */
114
+ readonly memberOf: readonly string[] | null;
115
+ /**
116
+ * The membership rows behind `memberOf`, including `admin_option`, `set_option` and
117
+ * `inherit_option`. Present
118
+ * on a catalog read; stripped before attributes are stored (`storedAttributes`), because the
119
+ * engine's diff receives stored attributes and would never see them there. The provider's
120
+ * diff reads these rows live. `grantor` is the role that made the grant
121
+ * (`pg_auth_members.grantor`). Null is a defensive inconsistent-catalog case, not an ordinary
122
+ * DROP ROLE outcome; such a row cannot be named in `REVOKE … GRANTED BY`.
123
+ */
124
+ readonly memberships?: readonly {
125
+ readonly parent: string;
126
+ readonly grantor: string | null;
127
+ readonly admin: boolean;
128
+ readonly set: boolean;
129
+ readonly inherit: boolean;
130
+ }[];
131
+ /**
132
+ * A seal of the last password value written, or `''` if none was ever written (`seal()` from
133
+ * `secrets/write-only.ts`). Lets a later reconcile notice a rotated environment variable
134
+ * without the state store holding anything a reader could replay.
135
+ */
136
+ readonly passwordSeal: string;
137
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Plan diff for `Postgres.Role`.
3
+ *
4
+ * ⛔ THE ENGINE PASSES STORED ATTRIBUTES, NOT A CATALOG READ. `Plan.ts` (alchemy beta.79,
5
+ * the `provider.diff` call that sets `output: oldState.attr`) hands `diff` whatever reconcile
6
+ * last stored. `storedAttributes` strips `memberships`, so a name-matched `memberOf` looks
7
+ * idle even when the live row is `WITH ADMIN` or still at the `SET TRUE` default. The provider
8
+ * reads the role and passes it as `observation`. Offline tests omit `observation` and compare
9
+ * the stored parent names only.
10
+ */
11
+ import { isResolved } from 'alchemy/Diff';
12
+ import type { Input } from 'alchemy/Input';
13
+ import * as Effect from 'effect/Effect';
14
+ import type { Environment } from '../secrets/write-only.ts';
15
+ import type { PostgresRoleAttributes, PostgresRoleProps } from './role-attrs.ts';
16
+ import {
17
+ PostgresRoleIdentityRefused,
18
+ type PostgresRoleNameRefused,
19
+ type PostgresRolePasswordNonAsciiRefused,
20
+ PostgresRoleRenameRefused,
21
+ type PostgresRoleValidUntilRefused,
22
+ } from './role-errors.ts';
23
+ import { membershipDrift, unsafeMemberships } from './role-membership-sql.ts';
24
+ import { assertPasswordAscii, passwordMatchesSeal, resolvePassword } from './role-secrets.ts';
25
+ import { privilegedFlags, scalarDrift } from './role-sql.ts';
26
+ import { refuseAtPlan } from './role.ts';
27
+
28
+ /** A catalog read the provider performed for this diff. `found: undefined` means the name is
29
+ * absent. Omitting the argument means no catalog read (the offline comparison). */
30
+ export interface RoleObservation {
31
+ readonly found: Omit<PostgresRoleAttributes, 'passwordSeal'> | undefined;
32
+ }
33
+
34
+ /**
35
+ * `news` against stored `output`, plus a live row when the provider has one. A rename is a
36
+ * plan-time refusal; so are an over-long name and an unusable `validUntil`. An oid that is not
37
+ * the stored one is refused — the name was recreated out of band. Every other change answers
38
+ * `update`. `delete` is a real drop here, so `diff` never answers `replace`.
39
+ */
40
+ export const diffPostgresRole = (
41
+ news: Input<PostgresRoleProps>,
42
+ output: PostgresRoleAttributes | undefined,
43
+ env: Environment = process.env,
44
+ observation?: RoleObservation,
45
+ ): Effect.Effect<
46
+ { readonly action: 'update' } | { readonly action: 'noop' } | undefined,
47
+ | PostgresRoleRenameRefused
48
+ | PostgresRoleNameRefused
49
+ | PostgresRoleValidUntilRefused
50
+ | PostgresRoleIdentityRefused
51
+ | PostgresRolePasswordNonAsciiRefused
52
+ > =>
53
+ Effect.gen(function* () {
54
+ if (output === undefined || !isResolved(news)) return undefined;
55
+ if (news.name !== output.name) {
56
+ return yield* Effect.fail(
57
+ new PostgresRoleRenameRefused({ from: output.name, to: news.name }),
58
+ );
59
+ }
60
+ yield* refuseAtPlan(news);
61
+ const live = observation?.found;
62
+ if (live !== undefined && live.oid !== output.oid) {
63
+ return yield* Effect.fail(
64
+ new PostgresRoleIdentityRefused({
65
+ role: output.name,
66
+ storedOid: output.oid,
67
+ liveOid: live.oid,
68
+ }),
69
+ );
70
+ }
71
+ const compared = live ?? output;
72
+ const scalars = scalarDrift(news, compared);
73
+ // Option rows live only on the catalog read. Stored `memberships` is stripped before it
74
+ // reaches the engine, so it is not consulted here.
75
+ const membership = membershipDrift(
76
+ news.memberOf,
77
+ compared.memberOf ?? [],
78
+ live === undefined ? new Set() : unsafeMemberships(live, news.inherit),
79
+ );
80
+ const resolved = resolvePassword(news, env);
81
+ yield* assertPasswordAscii(news.name, resolved);
82
+ const passwordStale =
83
+ resolved.value !== undefined && !passwordMatchesSeal(resolved.value, output.passwordSeal);
84
+ const absent = observation !== undefined && live === undefined;
85
+ const changed =
86
+ absent ||
87
+ privilegedFlags(compared).length > 0 ||
88
+ scalars.length > 0 ||
89
+ membership.grants.length > 0 ||
90
+ membership.revokes.length > 0 ||
91
+ passwordStale;
92
+ return changed ? ({ action: 'update' } as const) : ({ action: 'noop' } as const);
93
+ });
@@ -0,0 +1,206 @@
1
+ /**
2
+ * `Postgres.Role` failures as typed tags (S21).
3
+ *
4
+ * ⛔ NEVER MATCH DRIVER MESSAGE TEXT. Most errors are raised from a fact the
5
+ * provider already checked (a byte count, a live catalog row, a missing environment variable,
6
+ * a vanished create). Membership repair also maps raw SQLSTATE 2BP01/42501 to a typed
7
+ * refusal naming the observed parent and grantor. A `DROP ROLE` that the
8
+ * server refuses (the role still owns objects, `2BP01 dependent_objects_still_exist`) surfaces
9
+ * as the `SqlError` the client raised, unclassified by this family.
10
+ */
11
+ import * as Data from 'effect/Data';
12
+
13
+ /**
14
+ * A role name would be silently truncated by the server (`NAMEDATALEN` 64, so 63 UTF-8 bytes is
15
+ * the last one that survives whole) — refused at plan, before any statement runs.
16
+ *
17
+ * ⚠️ Same hazard as `PostgresDatabaseNameRefused`: `truncate_identifier` clips at 63 bytes and
18
+ * emits only a NOTICE. A create would succeed against the truncated name; the next plan would
19
+ * look for the original name and find nothing, looping forever.
20
+ */
21
+ export class PostgresRoleNameRefused extends Data.TaggedError('PostgresRoleNameRefused')<{
22
+ readonly name: string;
23
+ readonly byteLength: number;
24
+ readonly limit: number;
25
+ }> {
26
+ override get message(): string {
27
+ return (
28
+ `Postgres.Role "${this.name}": ${String(this.byteLength)} UTF-8 bytes, over the ` +
29
+ `${String(this.limit)}-byte limit (NAMEDATALEN 64, minus the terminator). PostgreSQL would ` +
30
+ 'accept the CREATE and silently truncate the name with only a NOTICE, so this plan refuses ' +
31
+ 'it instead of creating a role no later read will ever find again.'
32
+ );
33
+ }
34
+ }
35
+
36
+ /** A logical id's `name` changed. A role's name is its identity; this resource never replaces via
37
+ * `DROP` then `CREATE` — role memberships, grants and owned objects would be lost, and the
38
+ * seat-wiring shape depends on the group-role name staying stable. `ALTER ROLE … RENAME TO`
39
+ * exists in PostgreSQL; this family does not drive it, so a rename is refused at plan and the
40
+ * new name is declared as its own logical id. */
41
+ export class PostgresRoleRenameRefused extends Data.TaggedError('PostgresRoleRenameRefused')<{
42
+ readonly from: string;
43
+ readonly to: string;
44
+ }> {
45
+ override get message(): string {
46
+ return (
47
+ `Postgres.Role: the declared name changed from "${this.from}" to "${this.to}". A ` +
48
+ 'rename is refused at plan — this provider never replaces a role (that is DROP then ' +
49
+ 'CREATE, which loses memberships, grants and ownerships). Declare a new logical id for ' +
50
+ 'the new name, and remove the old one once its objects have moved.'
51
+ );
52
+ }
53
+ }
54
+
55
+ /** The password prop names an environment variable that is unset or empty at reconcile time, on a
56
+ * write that must send one (a create that declares it, or any reconcile while the variable is
57
+ * set). Never a guess: a group role left with a stale or empty password is exactly the
58
+ * unauthenticated path the refusal exists to prevent. */
59
+ export class PostgresRolePasswordEnvUnsetError extends Data.TaggedError(
60
+ 'PostgresRolePasswordEnvUnsetError',
61
+ )<{
62
+ readonly role: string;
63
+ readonly variable: string;
64
+ }> {
65
+ override get message(): string {
66
+ return (
67
+ `Postgres.Role "${this.role}": password.fromEnv "${this.variable}" is unset or empty ` +
68
+ 'in the deploying process, but this write requires a password this stack has not sealed.'
69
+ );
70
+ }
71
+ }
72
+
73
+ /** A live role carries a catalog flag this family never declares (`rolsuper`, `rolcreaterole`,
74
+ * `rolcreatedb`, `rolreplication`, `rolbypassrls`). Those are not inherited: a member who
75
+ * `SET ROLE`s to the parent exercises them. Refused before any write, adopt included. */
76
+ export class PostgresRolePrivilegedRefused extends Data.TaggedError(
77
+ 'PostgresRolePrivilegedRefused',
78
+ )<{
79
+ readonly role: string;
80
+ readonly flags: readonly string[];
81
+ }> {
82
+ override get message(): string {
83
+ return (
84
+ `Postgres.Role "${this.role}": the live role has ${this.flags.join(', ')} set. This ` +
85
+ 'family never declares those attributes (a create lands on the server default, all off), ' +
86
+ 'and they are not inherited — a member who SET ROLEs to this role would exercise them. ' +
87
+ 'Clear the flag on the cluster before this stack adopts the role.'
88
+ );
89
+ }
90
+ }
91
+
92
+ /** The declared `validUntil` is not a timestamp this family can compare: ECMAScript cannot parse
93
+ * it at all, or it names no time zone. Refused at plan, before any statement — see
94
+ * `role-attrs.ts#validUntilRefusal` for the churn loop this prevents. */
95
+ export class PostgresRoleValidUntilRefused extends Data.TaggedError(
96
+ 'PostgresRoleValidUntilRefused',
97
+ )<{
98
+ readonly role: string;
99
+ readonly value: string;
100
+ readonly reason: 'unparseable' | 'zone-free';
101
+ }> {
102
+ override get message(): string {
103
+ return (
104
+ `Postgres.Role "${this.role}": validUntil "${this.value}" is ${this.reason === 'unparseable' ? 'not a timestamp this kit can parse' : 'missing its UTC designator or numeric offset'}. ` +
105
+ 'Declare an explicit-zone ISO 8601 value such as "2027-01-01T00:00:00Z" — PostgreSQL would ' +
106
+ 'read a zone-free value in the session time zone while the plan compares UTC, and the two ' +
107
+ 'would never agree.'
108
+ );
109
+ }
110
+ }
111
+
112
+ /** `CREATE ROLE` raised no error, but the immediate re-read still finds nothing (S10/S20).
113
+ * Measured to have no real trigger in a correctly speaking client; still a typed failure the
114
+ * caller can see and retry, never a defect that crashes the engine. */
115
+ export class PostgresRoleCreateVanished extends Data.TaggedError('PostgresRoleCreateVanished')<{
116
+ readonly role: string;
117
+ }> {
118
+ override get message(): string {
119
+ return (
120
+ `Postgres.Role "${this.role}": CREATE ROLE raised no error, but the role is still ` +
121
+ 'absent on the immediate re-read. Re-plan — this is not a state this provider expects to reach.'
122
+ );
123
+ }
124
+ }
125
+
126
+ /** An option repair was refused, or a catalog row survived outside the declaration. A null grantor is a
127
+ * defensive corruption/test case: PostgreSQL tracks grantor dependencies, so ordinary
128
+ * DROP ROLE does not leave a dangling grantor. Refuse instead of claiming convergence. */
129
+ export class PostgresRoleMembershipUnrepaired extends Data.TaggedError(
130
+ 'PostgresRoleMembershipUnrepaired',
131
+ )<{
132
+ readonly role: string;
133
+ readonly parent: string;
134
+ readonly grantor: string | null;
135
+ readonly declared: boolean;
136
+ }> {
137
+ override get message(): string {
138
+ const who =
139
+ this.grantor === null
140
+ ? 'an unresolvable grantor (inconsistent catalog)'
141
+ : `grantor "${this.grantor}"`;
142
+ return (
143
+ `Postgres.Role "${this.role}": membership of "${this.parent}" ` +
144
+ `(${this.declared ? 'declared, options unsafe' : 'not declared'}) could not be repaired ` +
145
+ `under ${who}. The server refused the repair or the catalog re-read still found the row ` +
146
+ 'outside the declaration. pg_auth_members keys a membership on (parent, member, grantor). ' +
147
+ 'Check dependent grants, executor permissions and grantor identity before re-planning.'
148
+ );
149
+ }
150
+ }
151
+
152
+ /** A declared `memberOf` parent is not in `pg_roles`. Checked before any statement of a create,
153
+ * so a missing parent never leaves a committed LOGIN role behind a `42704` (`undefined_object`,
154
+ * `user.c@REL_18_6`) from `GRANT`. */
155
+ export class PostgresRoleParentMissing extends Data.TaggedError('PostgresRoleParentMissing')<{
156
+ readonly role: string;
157
+ readonly parent: string;
158
+ }> {
159
+ override get message(): string {
160
+ return (
161
+ `Postgres.Role "${this.role}": memberOf parent "${this.parent}" does not exist. ` +
162
+ 'Nothing was written — declare that role first (or drop it from memberOf). A GRANT of a ' +
163
+ 'missing role fails only after CREATE ROLE has committed, and the next plan then needs ' +
164
+ '--adopt to finish the orphan.'
165
+ );
166
+ }
167
+ }
168
+
169
+ /** The live role's oid is not the one this stack stored. A drop and recreate out of band reuses
170
+ * the name and would otherwise plan as ours: noop while the seal still matches, and a destroy
171
+ * would `DROP` a role this stack never created. */
172
+ export class PostgresRoleIdentityRefused extends Data.TaggedError('PostgresRoleIdentityRefused')<{
173
+ readonly role: string;
174
+ readonly storedOid: number;
175
+ readonly liveOid: number;
176
+ }> {
177
+ override get message(): string {
178
+ return (
179
+ `Postgres.Role "${this.role}": the live oid is ${String(this.liveOid)}, but state recorded ` +
180
+ `${String(this.storedOid)}. The name was dropped and recreated outside this stack. Nothing ` +
181
+ 'was altered and the live role was not dropped — remove the stale state, or adopt the new ' +
182
+ 'role under a new logical id once you mean to own it.'
183
+ );
184
+ }
185
+ }
186
+
187
+ /** Never carry the rejected password in this error: errors reach logs and traces. */
188
+ export class PostgresRolePasswordNonAsciiRefused extends Data.TaggedError(
189
+ 'PostgresRolePasswordNonAsciiRefused',
190
+ )<{ readonly role: string }> {
191
+ override get message(): string {
192
+ return `Postgres.Role "${this.role}": password must be ASCII; this provider does not implement PostgreSQL SASLprep normalization. Nothing was written.`;
193
+ }
194
+ }
195
+
196
+ export type PostgresRoleError =
197
+ | PostgresRolePasswordNonAsciiRefused
198
+ | PostgresRoleNameRefused
199
+ | PostgresRoleRenameRefused
200
+ | PostgresRoleValidUntilRefused
201
+ | PostgresRolePasswordEnvUnsetError
202
+ | PostgresRolePrivilegedRefused
203
+ | PostgresRoleCreateVanished
204
+ | PostgresRoleMembershipUnrepaired
205
+ | PostgresRoleParentMissing
206
+ | PostgresRoleIdentityRefused;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The create must not survive a missing parent, and a synthetic inconsistent-catalog membership with no grantor
3
+ * must fail typed rather than look repaired.
4
+ */
5
+ import { describe, expect, test } from 'bun:test';
6
+ import * as Effect from 'effect/Effect';
7
+ import { makeFakeSql } from './fake-sql.ts';
8
+ import { PostgresRoleMembershipUnrepaired, PostgresRoleParentMissing } from './role-errors.ts';
9
+ import type { PostgresRoleAttributes, PostgresRoleProps } from './role-attrs.ts';
10
+ import { reconcileWithClient } from './role.ts';
11
+
12
+ const fails = <A, E>(eff: Effect.Effect<A, E>): Promise<E> => Effect.runPromise(Effect.flip(eff));
13
+
14
+ const props: PostgresRoleProps = {
15
+ name: 'seat-observability',
16
+ login: true,
17
+ connectionLimit: 10,
18
+ inherit: true,
19
+ memberOf: ['hf_agent'],
20
+ };
21
+
22
+ const live = (): PostgresRoleAttributes => ({
23
+ name: 'seat-observability',
24
+ oid: 20000,
25
+ login: true,
26
+ connectionLimit: 10,
27
+ inherit: true,
28
+ validUntil: null,
29
+ memberOf: ['hf_agent'],
30
+ passwordSeal: '',
31
+ });
32
+
33
+ describe('missing parent and inconsistent grantor', () => {
34
+ test('a missing parent fails typed and issues no CREATE', async () => {
35
+ const fake = makeFakeSql();
36
+ const error = await fails(reconcileWithClient(fake, props));
37
+ expect(error).toBeInstanceOf(PostgresRoleParentMissing);
38
+ expect((error as PostgresRoleParentMissing).parent).toBe('hf_agent');
39
+ expect(fake.statements.some((s) => s.text.startsWith('CREATE'))).toBe(false);
40
+ expect(fake.roleRows.has('seat-observability')).toBe(false);
41
+ });
42
+
43
+ test('a GRANT failure inside the create transaction rolls the CREATE back', async () => {
44
+ const fake = makeFakeSql({ roles: ['hf_agent'], failNext: 'GRANT' });
45
+ const error = await fails(reconcileWithClient(fake, props));
46
+ expect(error).not.toBeInstanceOf(PostgresRoleParentMissing);
47
+ expect(fake.roleRows.has('seat-observability')).toBe(false);
48
+ expect(fake.statements.some((s) => s.text.startsWith('CREATE ROLE'))).toBe(true);
49
+ });
50
+
51
+ test('a synthetic unresolvable grantor fails typed (not an ordinary DROP ROLE outcome)', async () => {
52
+ const fake = makeFakeSql({ roleRows: [live()], roles: ['hf_agent'] });
53
+ fake.memberships.add('seat-observability\0hf_agent\0');
54
+ fake.membershipOptions.set('seat-observability\0hf_agent\0', { admin: true, set: true });
55
+ const error = await fails(reconcileWithClient(fake, props));
56
+ expect(error).toBeInstanceOf(PostgresRoleMembershipUnrepaired);
57
+ expect((error as PostgresRoleMembershipUnrepaired).grantor).toBeNull();
58
+ expect(fake.memberships.has('seat-observability\0hf_agent\0')).toBe(true);
59
+ });
60
+ });