@homeflare/alchemy 0.46.0 → 0.47.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 (773) hide show
  1. package/README.md +10 -10
  2. package/dist/argocd/cluster.d.ts +5 -5
  3. package/dist/argocd/cluster.d.ts.map +1 -1
  4. package/dist/argocd/fake-argocd.d.ts +1 -1
  5. package/dist/argocd/fake-argocd.d.ts.map +1 -1
  6. package/dist/argocd/index.js.map +1 -1
  7. package/dist/argocd/providers.d.ts +1 -1
  8. package/dist/argocd/providers.d.ts.map +1 -1
  9. package/dist/argocd/repo-creds.d.ts +5 -5
  10. package/dist/argocd/repo-creds.d.ts.map +1 -1
  11. package/dist/argocd/repository.d.ts +5 -5
  12. package/dist/argocd/repository.d.ts.map +1 -1
  13. package/dist/argocd/resource.d.ts +1 -1
  14. package/dist/argocd/resource.d.ts.map +1 -1
  15. package/dist/caddy/admin.d.ts +1 -1
  16. package/dist/caddy/admin.d.ts.map +1 -1
  17. package/dist/caddy/caddy-http-client.d.ts +2 -2
  18. package/dist/caddy/caddy-http-client.d.ts.map +1 -1
  19. package/dist/caddy/format.d.ts +1 -1
  20. package/dist/caddy/format.d.ts.map +1 -1
  21. package/dist/caddy/index.js +6 -6
  22. package/dist/caddy/index.js.map +4 -4
  23. package/dist/ceph/auth-entity.d.ts +1 -1
  24. package/dist/ceph/auth-entity.d.ts.map +1 -1
  25. package/dist/ceph/ceph-auth-reconcile.d.ts +1 -1
  26. package/dist/ceph/ceph-auth-reconcile.d.ts.map +1 -1
  27. package/dist/ceph/index.js +5 -5
  28. package/dist/ceph/index.js.map +4 -4
  29. package/dist/cloudflare/fake-mesh.d.ts +2 -2
  30. package/dist/cloudflare/fake-mesh.d.ts.map +1 -1
  31. package/dist/cloudflare/fake-r2-lock.d.ts +1 -1
  32. package/dist/cloudflare/fake-r2-lock.d.ts.map +1 -1
  33. package/dist/cloudflare/index.js +3 -3
  34. package/dist/cloudflare/index.js.map +3 -3
  35. package/dist/cloudflare/mesh-node-token.d.ts +1 -1
  36. package/dist/cloudflare/mesh-node-token.d.ts.map +1 -1
  37. package/dist/cloudflare/mesh-node.d.ts +1 -1
  38. package/dist/cloudflare/mesh-node.d.ts.map +1 -1
  39. package/dist/cloudflare/providers.d.ts +1 -1
  40. package/dist/cloudflare/providers.d.ts.map +1 -1
  41. package/dist/cloudflare/r2-bucket-lock.d.ts +1 -1
  42. package/dist/cloudflare/r2-bucket-lock.d.ts.map +1 -1
  43. package/dist/discord/application-command.d.ts +6 -6
  44. package/dist/discord/application-command.d.ts.map +1 -1
  45. package/dist/discord/fake-discord.d.ts +1 -1
  46. package/dist/discord/fake-discord.d.ts.map +1 -1
  47. package/dist/discord/guild-application-command.d.ts +6 -6
  48. package/dist/discord/guild-application-command.d.ts.map +1 -1
  49. package/dist/discord/index.js.map +1 -1
  50. package/dist/discord/providers.d.ts +1 -1
  51. package/dist/discord/providers.d.ts.map +1 -1
  52. package/dist/discord/resource.d.ts +1 -1
  53. package/dist/discord/resource.d.ts.map +1 -1
  54. package/dist/forgejo/branch-protection.d.ts +5 -5
  55. package/dist/forgejo/branch-protection.d.ts.map +1 -1
  56. package/dist/forgejo/fake-forgejo.d.ts +1 -1
  57. package/dist/forgejo/fake-forgejo.d.ts.map +1 -1
  58. package/dist/forgejo/index.js.map +1 -1
  59. package/dist/forgejo/org-actions-secrets.d.ts +5 -5
  60. package/dist/forgejo/org-actions-secrets.d.ts.map +1 -1
  61. package/dist/forgejo/org-label.d.ts +5 -5
  62. package/dist/forgejo/org-label.d.ts.map +1 -1
  63. package/dist/forgejo/org-team.d.ts +5 -5
  64. package/dist/forgejo/org-team.d.ts.map +1 -1
  65. package/dist/forgejo/repo-webhook.d.ts +5 -5
  66. package/dist/forgejo/repo-webhook.d.ts.map +1 -1
  67. package/dist/forgejo/repository.d.ts +5 -5
  68. package/dist/forgejo/repository.d.ts.map +1 -1
  69. package/dist/forgejo/resource.d.ts +1 -1
  70. package/dist/forgejo/resource.d.ts.map +1 -1
  71. package/dist/forgejo/team-member.d.ts +5 -5
  72. package/dist/forgejo/team-member.d.ts.map +1 -1
  73. package/dist/github/repository-ruleset-providers.d.ts +1 -1
  74. package/dist/github/repository-ruleset-providers.d.ts.map +1 -1
  75. package/dist/google-workspace/domain-alias.d.ts +5 -5
  76. package/dist/google-workspace/domain-alias.d.ts.map +1 -1
  77. package/dist/google-workspace/fake-google-workspace.d.ts +1 -1
  78. package/dist/google-workspace/fake-google-workspace.d.ts.map +1 -1
  79. package/dist/google-workspace/group-member.d.ts +5 -5
  80. package/dist/google-workspace/group-member.d.ts.map +1 -1
  81. package/dist/google-workspace/group.d.ts +5 -5
  82. package/dist/google-workspace/group.d.ts.map +1 -1
  83. package/dist/google-workspace/index.js.map +1 -1
  84. package/dist/google-workspace/org-unit.d.ts +5 -5
  85. package/dist/google-workspace/org-unit.d.ts.map +1 -1
  86. package/dist/google-workspace/providers.d.ts +1 -1
  87. package/dist/google-workspace/providers.d.ts.map +1 -1
  88. package/dist/google-workspace/resource.d.ts +1 -1
  89. package/dist/google-workspace/resource.d.ts.map +1 -1
  90. package/dist/grafana/alert-rule-group.d.ts +4 -4
  91. package/dist/grafana/alert-rule-group.d.ts.map +1 -1
  92. package/dist/grafana/contact-point.d.ts +4 -4
  93. package/dist/grafana/dashboard.d.ts +4 -4
  94. package/dist/grafana/datasource.d.ts +4 -4
  95. package/dist/grafana/fake-grafana.d.ts +1 -1
  96. package/dist/grafana/fake-grafana.d.ts.map +1 -1
  97. package/dist/grafana/folder.d.ts +4 -4
  98. package/dist/grafana/message-template.d.ts +4 -4
  99. package/dist/grafana/mute-timing.d.ts +4 -4
  100. package/dist/grafana/notification-policy.d.ts +4 -4
  101. package/dist/grafana/notification-policy.d.ts.map +1 -1
  102. package/dist/grafana/providers.d.ts +1 -1
  103. package/dist/grafana/providers.d.ts.map +1 -1
  104. package/dist/litellm/access-group.d.ts +1 -1
  105. package/dist/litellm/budget-operations.d.ts +1 -1
  106. package/dist/litellm/budget-operations.d.ts.map +1 -1
  107. package/dist/litellm/budget.d.ts +2 -2
  108. package/dist/litellm/credential-errors.d.ts +1 -1
  109. package/dist/litellm/credential-errors.d.ts.map +1 -1
  110. package/dist/litellm/credential.d.ts +1 -1
  111. package/dist/litellm/index.js +26 -5
  112. package/dist/litellm/index.js.map +8 -8
  113. package/dist/litellm/key-errors.d.ts +1 -1
  114. package/dist/litellm/key-errors.d.ts.map +1 -1
  115. package/dist/litellm/key.d.ts +2 -2
  116. package/dist/litellm/mcp-server-locate.d.ts +1 -1
  117. package/dist/litellm/mcp-server-locate.d.ts.map +1 -1
  118. package/dist/litellm/mcp-server.d.ts +2 -2
  119. package/dist/litellm/model-operations.d.ts +1 -1
  120. package/dist/litellm/model-operations.d.ts.map +1 -1
  121. package/dist/litellm/model.d.ts +2 -2
  122. package/dist/litellm/operations.d.ts +1 -1
  123. package/dist/litellm/operations.d.ts.map +1 -1
  124. package/dist/litellm/policy-attachment.d.ts +1 -1
  125. package/dist/litellm/policy.d.ts +1 -1
  126. package/dist/litellm/providers.d.ts +1 -1
  127. package/dist/litellm/providers.d.ts.map +1 -1
  128. package/dist/litellm/team-operations.d.ts +1 -1
  129. package/dist/litellm/team-operations.d.ts.map +1 -1
  130. package/dist/litellm/team.d.ts +1 -1
  131. package/dist/litellm/tool-policy-operations.d.ts +1 -1
  132. package/dist/litellm/tool-policy-operations.d.ts.map +1 -1
  133. package/dist/litellm/tool-policy.d.ts +1 -1
  134. package/dist/litellm/toolset.d.ts +1 -1
  135. package/dist/netbox/fake-netbox.d.ts +1 -1
  136. package/dist/netbox/fake-netbox.d.ts.map +1 -1
  137. package/dist/netbox/index.js.map +1 -1
  138. package/dist/netbox/prefix.d.ts +5 -5
  139. package/dist/netbox/prefix.d.ts.map +1 -1
  140. package/dist/netbox/resource.d.ts +1 -1
  141. package/dist/netbox/resource.d.ts.map +1 -1
  142. package/dist/openbao/approle-login.d.ts +1 -1
  143. package/dist/openbao/approle-login.d.ts.map +1 -1
  144. package/dist/openbao/auth-method-reconcile.d.ts +1 -1
  145. package/dist/openbao/auth-method-reconcile.d.ts.map +1 -1
  146. package/dist/openbao/auth-method-wire.d.ts +4 -4
  147. package/dist/openbao/auth-method-wire.d.ts.map +1 -1
  148. package/dist/openbao/auth-method.d.ts +1 -1
  149. package/dist/openbao/auth-method.d.ts.map +1 -1
  150. package/dist/openbao/auth-role-identity.d.ts +1 -1
  151. package/dist/openbao/auth-role-identity.d.ts.map +1 -1
  152. package/dist/openbao/auth-role-wire.d.ts +4 -4
  153. package/dist/openbao/auth-role-wire.d.ts.map +1 -1
  154. package/dist/openbao/auth-role.d.ts +1 -1
  155. package/dist/openbao/auth-role.d.ts.map +1 -1
  156. package/dist/openbao/bao-http.d.ts +1 -1
  157. package/dist/openbao/bao-http.d.ts.map +1 -1
  158. package/dist/openbao/bao-identity.d.ts +1 -1
  159. package/dist/openbao/bao-identity.d.ts.map +1 -1
  160. package/dist/openbao/cloudflare-permission-groups.d.ts +1 -1
  161. package/dist/openbao/cloudflare-permission-groups.d.ts.map +1 -1
  162. package/dist/openbao/cloudflare-role-wire.d.ts +1 -1
  163. package/dist/openbao/cloudflare-role-wire.d.ts.map +1 -1
  164. package/dist/openbao/cloudflare-role.d.ts +1 -1
  165. package/dist/openbao/cloudflare-role.d.ts.map +1 -1
  166. package/dist/openbao/distilled.d.ts +1 -1
  167. package/dist/openbao/distilled.d.ts.map +1 -1
  168. package/dist/openbao/fake-bao.d.ts +1 -1
  169. package/dist/openbao/fake-bao.d.ts.map +1 -1
  170. package/dist/openbao/fake-core.d.ts +1 -1
  171. package/dist/openbao/fake-core.d.ts.map +1 -1
  172. package/dist/openbao/fake-engines.d.ts +1 -1
  173. package/dist/openbao/fake-engines.d.ts.map +1 -1
  174. package/dist/openbao/fake-families.d.ts +2 -2
  175. package/dist/openbao/fake-families.d.ts.map +1 -1
  176. package/dist/openbao/fake-stack.d.ts +5 -0
  177. package/dist/openbao/fake-stack.d.ts.map +1 -1
  178. package/dist/openbao/forgejo-bootstrap.d.ts +1 -1
  179. package/dist/openbao/forgejo-bootstrap.d.ts.map +1 -1
  180. package/dist/openbao/index.js +31 -10
  181. package/dist/openbao/index.js.map +31 -31
  182. package/dist/openbao/jwt-config.d.ts +1 -1
  183. package/dist/openbao/jwt-config.d.ts.map +1 -1
  184. package/dist/openbao/jwt-role.d.ts +1 -1
  185. package/dist/openbao/jwt-role.d.ts.map +1 -1
  186. package/dist/openbao/kubernetes-role.d.ts +1 -1
  187. package/dist/openbao/kubernetes-role.d.ts.map +1 -1
  188. package/dist/openbao/mfa-enforcement.d.ts +1 -1
  189. package/dist/openbao/mfa-enforcement.d.ts.map +1 -1
  190. package/dist/openbao/mfa-totp.d.ts +1 -1
  191. package/dist/openbao/mfa-totp.d.ts.map +1 -1
  192. package/dist/openbao/mfa-wire.d.ts +1 -1
  193. package/dist/openbao/mfa-wire.d.ts.map +1 -1
  194. package/dist/openbao/mount-move.d.ts +1 -1
  195. package/dist/openbao/mount-move.d.ts.map +1 -1
  196. package/dist/openbao/mount-reconcile.d.ts +1 -1
  197. package/dist/openbao/mount-reconcile.d.ts.map +1 -1
  198. package/dist/openbao/mount-wire.d.ts +4 -4
  199. package/dist/openbao/mount-wire.d.ts.map +1 -1
  200. package/dist/openbao/mount.d.ts +1 -1
  201. package/dist/openbao/mount.d.ts.map +1 -1
  202. package/dist/openbao/pki-role.d.ts +1 -1
  203. package/dist/openbao/pki-role.d.ts.map +1 -1
  204. package/dist/openbao/plugin-reconcile.d.ts +1 -1
  205. package/dist/openbao/plugin-reconcile.d.ts.map +1 -1
  206. package/dist/openbao/plugin-wire.d.ts +1 -1
  207. package/dist/openbao/plugin-wire.d.ts.map +1 -1
  208. package/dist/openbao/plugin.d.ts +1 -1
  209. package/dist/openbao/plugin.d.ts.map +1 -1
  210. package/dist/openbao/policy-identity.d.ts +1 -1
  211. package/dist/openbao/policy-identity.d.ts.map +1 -1
  212. package/dist/openbao/policy-wire.d.ts +4 -4
  213. package/dist/openbao/policy-wire.d.ts.map +1 -1
  214. package/dist/openbao/policy.d.ts +1 -1
  215. package/dist/openbao/policy.d.ts.map +1 -1
  216. package/dist/openbao/proxmox-role-wire.d.ts +1 -1
  217. package/dist/openbao/proxmox-role-wire.d.ts.map +1 -1
  218. package/dist/openbao/proxmox-role.d.ts +1 -1
  219. package/dist/openbao/proxmox-role.d.ts.map +1 -1
  220. package/dist/openbao/remount-wire.d.ts +1 -1
  221. package/dist/openbao/remount-wire.d.ts.map +1 -1
  222. package/dist/openbao/rename-identity.d.ts +1 -1
  223. package/dist/openbao/rename-identity.d.ts.map +1 -1
  224. package/dist/openbao/rename.d.ts +1 -1
  225. package/dist/openbao/rename.d.ts.map +1 -1
  226. package/dist/openbao/role-reconcile.d.ts +1 -1
  227. package/dist/openbao/role-reconcile.d.ts.map +1 -1
  228. package/dist/openbao/ssh-role.d.ts +1 -1
  229. package/dist/openbao/ssh-role.d.ts.map +1 -1
  230. package/dist/opnsense/alias.d.ts +5 -5
  231. package/dist/opnsense/alias.d.ts.map +1 -1
  232. package/dist/opnsense/category.d.ts +5 -5
  233. package/dist/opnsense/category.d.ts.map +1 -1
  234. package/dist/opnsense/fake-opnsense.d.ts +1 -1
  235. package/dist/opnsense/fake-opnsense.d.ts.map +1 -1
  236. package/dist/opnsense/group.d.ts +5 -5
  237. package/dist/opnsense/group.d.ts.map +1 -1
  238. package/dist/opnsense/index.js.map +1 -1
  239. package/dist/opnsense/providers.d.ts +1 -1
  240. package/dist/opnsense/providers.d.ts.map +1 -1
  241. package/dist/opnsense/resource.d.ts +1 -1
  242. package/dist/opnsense/resource.d.ts.map +1 -1
  243. package/dist/ownership/probe.d.ts.map +1 -1
  244. package/dist/paperless/custom-field.d.ts +5 -5
  245. package/dist/paperless/custom-field.d.ts.map +1 -1
  246. package/dist/paperless/document-type.d.ts +5 -5
  247. package/dist/paperless/document-type.d.ts.map +1 -1
  248. package/dist/paperless/fake-paperless.d.ts +1 -1
  249. package/dist/paperless/fake-paperless.d.ts.map +1 -1
  250. package/dist/paperless/matching-types.d.ts +1 -1
  251. package/dist/paperless/matching-types.d.ts.map +1 -1
  252. package/dist/paperless/matching.d.ts +4 -4
  253. package/dist/paperless/providers.d.ts +1 -1
  254. package/dist/paperless/providers.d.ts.map +1 -1
  255. package/dist/paperless/storage-path.d.ts +5 -5
  256. package/dist/paperless/storage-path.d.ts.map +1 -1
  257. package/dist/paperless/tag.d.ts +5 -5
  258. package/dist/paperless/tag.d.ts.map +1 -1
  259. package/dist/postgres/connection.d.ts +2 -2
  260. package/dist/postgres/connection.d.ts.map +1 -1
  261. package/dist/postgres/database-sql.d.ts +1 -1
  262. package/dist/postgres/database-sql.d.ts.map +1 -1
  263. package/dist/postgres/database.d.ts +1 -1
  264. package/dist/postgres/database.d.ts.map +1 -1
  265. package/dist/postgres/fake-grants-read.d.ts +1 -1
  266. package/dist/postgres/fake-grants-read.d.ts.map +1 -1
  267. package/dist/postgres/fake-grants-write.d.ts +1 -1
  268. package/dist/postgres/fake-grants-write.d.ts.map +1 -1
  269. package/dist/postgres/fake-role-sql.d.ts +1 -1
  270. package/dist/postgres/fake-role-sql.d.ts.map +1 -1
  271. package/dist/postgres/fake-schema-drop.d.ts +13 -0
  272. package/dist/postgres/fake-schema-drop.d.ts.map +1 -0
  273. package/dist/postgres/fake-schema-sql.d.ts +6 -1
  274. package/dist/postgres/fake-schema-sql.d.ts.map +1 -1
  275. package/dist/postgres/fake-sql.d.ts +4 -0
  276. package/dist/postgres/fake-sql.d.ts.map +1 -1
  277. package/dist/postgres/grants-existence.d.ts +1 -1
  278. package/dist/postgres/grants-existence.d.ts.map +1 -1
  279. package/dist/postgres/grants-ops.d.ts +1 -1
  280. package/dist/postgres/grants-ops.d.ts.map +1 -1
  281. package/dist/postgres/grants-ownership.d.ts +1 -1
  282. package/dist/postgres/grants-ownership.d.ts.map +1 -1
  283. package/dist/postgres/grants-read-defaults.d.ts +1 -1
  284. package/dist/postgres/grants-read-defaults.d.ts.map +1 -1
  285. package/dist/postgres/grants-read.d.ts +1 -1
  286. package/dist/postgres/grants-read.d.ts.map +1 -1
  287. package/dist/postgres/index.d.ts +2 -1
  288. package/dist/postgres/index.d.ts.map +1 -1
  289. package/dist/postgres/index.js +523 -324
  290. package/dist/postgres/index.js.map +26 -22
  291. package/dist/postgres/installed-classifier.d.ts +1 -1
  292. package/dist/postgres/installed-classifier.d.ts.map +1 -1
  293. package/dist/postgres/psql-executor.d.ts.map +1 -1
  294. package/dist/postgres/role-membership-sql.d.ts +1 -1
  295. package/dist/postgres/role-membership-sql.d.ts.map +1 -1
  296. package/dist/postgres/role-sql.d.ts +1 -1
  297. package/dist/postgres/role-sql.d.ts.map +1 -1
  298. package/dist/postgres/role.d.ts +1 -1
  299. package/dist/postgres/role.d.ts.map +1 -1
  300. package/dist/postgres/schema-assert.d.ts +1 -1
  301. package/dist/postgres/schema-assert.d.ts.map +1 -1
  302. package/dist/postgres/schema-closure-sql.d.ts +45 -0
  303. package/dist/postgres/schema-closure-sql.d.ts.map +1 -0
  304. package/dist/postgres/schema-delete.d.ts +18 -9
  305. package/dist/postgres/schema-delete.d.ts.map +1 -1
  306. package/dist/postgres/schema-drop-sql.d.ts +66 -0
  307. package/dist/postgres/schema-drop-sql.d.ts.map +1 -0
  308. package/dist/postgres/schema-errors.d.ts +19 -1
  309. package/dist/postgres/schema-errors.d.ts.map +1 -1
  310. package/dist/postgres/schema-reconcile.d.ts +1 -1
  311. package/dist/postgres/schema-reconcile.d.ts.map +1 -1
  312. package/dist/postgres/schema-sequence-error.d.ts +29 -0
  313. package/dist/postgres/schema-sequence-error.d.ts.map +1 -0
  314. package/dist/postgres/schema-sql.d.ts +17 -1
  315. package/dist/postgres/schema-sql.d.ts.map +1 -1
  316. package/dist/postgres/schema-test-kit.d.ts +3 -1
  317. package/dist/postgres/schema-test-kit.d.ts.map +1 -1
  318. package/dist/postgres/schema.d.ts +1 -1
  319. package/dist/postgres/schema.d.ts.map +1 -1
  320. package/dist/postgres/search-path.d.ts +38 -0
  321. package/dist/postgres/search-path.d.ts.map +1 -0
  322. package/dist/proxmox/acl.d.ts +1 -1
  323. package/dist/proxmox/acl.d.ts.map +1 -1
  324. package/dist/proxmox/api-token.d.ts +1 -1
  325. package/dist/proxmox/api-token.d.ts.map +1 -1
  326. package/dist/proxmox/backup-job-distilled.d.ts +2 -2
  327. package/dist/proxmox/backup-job-distilled.d.ts.map +1 -1
  328. package/dist/proxmox/backup-job.d.ts +1 -1
  329. package/dist/proxmox/backup-job.d.ts.map +1 -1
  330. package/dist/proxmox/ceph-daemon-wire.d.ts +3 -3
  331. package/dist/proxmox/ceph-daemon-wire.d.ts.map +1 -1
  332. package/dist/proxmox/ceph-daemon.d.ts +2 -2
  333. package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
  334. package/dist/proxmox/ceph-flag-wire.d.ts +3 -3
  335. package/dist/proxmox/ceph-flag-wire.d.ts.map +1 -1
  336. package/dist/proxmox/ceph-flag.d.ts +1 -1
  337. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  338. package/dist/proxmox/ceph-fs-distilled.d.ts +3 -3
  339. package/dist/proxmox/ceph-fs-distilled.d.ts.map +1 -1
  340. package/dist/proxmox/ceph-fs.d.ts +1 -1
  341. package/dist/proxmox/ceph-fs.d.ts.map +1 -1
  342. package/dist/proxmox/ceph-osd-tree.d.ts +1 -1
  343. package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -1
  344. package/dist/proxmox/ceph-osd-write.d.ts +2 -2
  345. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  346. package/dist/proxmox/ceph-osd.d.ts +1 -1
  347. package/dist/proxmox/ceph-osd.d.ts.map +1 -1
  348. package/dist/proxmox/ceph-pool-settle.d.ts +2 -2
  349. package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -1
  350. package/dist/proxmox/ceph-pool-wire.d.ts +1 -1
  351. package/dist/proxmox/ceph-pool-wire.d.ts.map +1 -1
  352. package/dist/proxmox/ceph-pool.d.ts +1 -1
  353. package/dist/proxmox/ceph-pool.d.ts.map +1 -1
  354. package/dist/proxmox/client.d.ts +1 -1
  355. package/dist/proxmox/client.d.ts.map +1 -1
  356. package/dist/proxmox/distilled-pbs.d.ts +1 -1
  357. package/dist/proxmox/distilled-pbs.d.ts.map +1 -1
  358. package/dist/proxmox/distilled-pve.d.ts +1 -1
  359. package/dist/proxmox/distilled-pve.d.ts.map +1 -1
  360. package/dist/proxmox/fake-pbs-jobs.d.ts +1 -1
  361. package/dist/proxmox/fake-pve.d.ts +1 -1
  362. package/dist/proxmox/fake-pve.d.ts.map +1 -1
  363. package/dist/proxmox/firewall-alias-lifecycle.d.ts +6 -6
  364. package/dist/proxmox/firewall-alias-lifecycle.d.ts.map +1 -1
  365. package/dist/proxmox/firewall-alias.d.ts +1 -1
  366. package/dist/proxmox/firewall-alias.d.ts.map +1 -1
  367. package/dist/proxmox/group-wire.d.ts +2 -2
  368. package/dist/proxmox/group-wire.d.ts.map +1 -1
  369. package/dist/proxmox/group.d.ts +1 -1
  370. package/dist/proxmox/group.d.ts.map +1 -1
  371. package/dist/proxmox/ha-resource.d.ts +1 -1
  372. package/dist/proxmox/ha-resource.d.ts.map +1 -1
  373. package/dist/proxmox/ha-rule.d.ts +1 -1
  374. package/dist/proxmox/ha-rule.d.ts.map +1 -1
  375. package/dist/proxmox/index.js +38 -17
  376. package/dist/proxmox/index.js.map +9 -9
  377. package/dist/proxmox/lease-cache.d.ts +2 -2
  378. package/dist/proxmox/lease-cache.d.ts.map +1 -1
  379. package/dist/proxmox/live-core-fixtures.d.ts +1 -1
  380. package/dist/proxmox/live-core-fixtures.d.ts.map +1 -1
  381. package/dist/proxmox/lxc-lifecycle.d.ts +3 -3
  382. package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
  383. package/dist/proxmox/lxc-read.d.ts +1 -1
  384. package/dist/proxmox/lxc-read.d.ts.map +1 -1
  385. package/dist/proxmox/lxc-task.d.ts +1 -1
  386. package/dist/proxmox/lxc-task.d.ts.map +1 -1
  387. package/dist/proxmox/lxc.d.ts +1 -1
  388. package/dist/proxmox/lxc.d.ts.map +1 -1
  389. package/dist/proxmox/members.d.ts +3 -3
  390. package/dist/proxmox/members.d.ts.map +1 -1
  391. package/dist/proxmox/metric-server-distilled.d.ts +3 -3
  392. package/dist/proxmox/metric-server-distilled.d.ts.map +1 -1
  393. package/dist/proxmox/metric-server.d.ts +1 -1
  394. package/dist/proxmox/metric-server.d.ts.map +1 -1
  395. package/dist/proxmox/mint.d.ts +1 -1
  396. package/dist/proxmox/mint.d.ts.map +1 -1
  397. package/dist/proxmox/network-apply-read.d.ts +3 -3
  398. package/dist/proxmox/network-apply-read.d.ts.map +1 -1
  399. package/dist/proxmox/network-apply-run.d.ts +1 -1
  400. package/dist/proxmox/network-apply-run.d.ts.map +1 -1
  401. package/dist/proxmox/network-apply.d.ts +1 -1
  402. package/dist/proxmox/network-apply.d.ts.map +1 -1
  403. package/dist/proxmox/node-network-wire.d.ts +2 -2
  404. package/dist/proxmox/node-network-wire.d.ts.map +1 -1
  405. package/dist/proxmox/node-network.d.ts +1 -1
  406. package/dist/proxmox/node-network.d.ts.map +1 -1
  407. package/dist/proxmox/notification-matcher-distilled.d.ts +4 -4
  408. package/dist/proxmox/notification-matcher-distilled.d.ts.map +1 -1
  409. package/dist/proxmox/notification-matcher-lifecycle.d.ts +4 -4
  410. package/dist/proxmox/notification-matcher.d.ts +1 -1
  411. package/dist/proxmox/notification-matcher.d.ts.map +1 -1
  412. package/dist/proxmox/notification-target-distilled.d.ts +4 -4
  413. package/dist/proxmox/notification-target-distilled.d.ts.map +1 -1
  414. package/dist/proxmox/notification-target-lifecycle.d.ts +4 -4
  415. package/dist/proxmox/notification-target.d.ts +1 -1
  416. package/dist/proxmox/notification-target.d.ts.map +1 -1
  417. package/dist/proxmox/pbs-datastore-lifecycle.d.ts +4 -4
  418. package/dist/proxmox/pbs-datastore-wire.d.ts +4 -4
  419. package/dist/proxmox/pbs-datastore-wire.d.ts.map +1 -1
  420. package/dist/proxmox/pbs-datastore.d.ts +1 -1
  421. package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
  422. package/dist/proxmox/pbs-notification-matcher-distilled.d.ts +4 -4
  423. package/dist/proxmox/pbs-notification-matcher-distilled.d.ts.map +1 -1
  424. package/dist/proxmox/pbs-notification-matcher.d.ts +1 -1
  425. package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -1
  426. package/dist/proxmox/pbs-notification-target-distilled.d.ts +4 -4
  427. package/dist/proxmox/pbs-notification-target-distilled.d.ts.map +1 -1
  428. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +4 -4
  429. package/dist/proxmox/pbs-notification-target.d.ts +1 -1
  430. package/dist/proxmox/pbs-notification-target.d.ts.map +1 -1
  431. package/dist/proxmox/pbs-prune-job-lifecycle.d.ts +4 -4
  432. package/dist/proxmox/pbs-prune-job-wire.d.ts +4 -4
  433. package/dist/proxmox/pbs-prune-job-wire.d.ts.map +1 -1
  434. package/dist/proxmox/pbs-prune-job.d.ts +1 -1
  435. package/dist/proxmox/pbs-prune-job.d.ts.map +1 -1
  436. package/dist/proxmox/pbs-sync-job-lifecycle.d.ts +4 -4
  437. package/dist/proxmox/pbs-sync-job-wire.d.ts +4 -4
  438. package/dist/proxmox/pbs-sync-job-wire.d.ts.map +1 -1
  439. package/dist/proxmox/pbs-sync-job.d.ts +1 -1
  440. package/dist/proxmox/pbs-sync-job.d.ts.map +1 -1
  441. package/dist/proxmox/pbs-verify-job-lifecycle.d.ts +4 -4
  442. package/dist/proxmox/pbs-verify-job-wire.d.ts +4 -4
  443. package/dist/proxmox/pbs-verify-job-wire.d.ts.map +1 -1
  444. package/dist/proxmox/pbs-verify-job.d.ts +1 -1
  445. package/dist/proxmox/pbs-verify-job.d.ts.map +1 -1
  446. package/dist/proxmox/pool.d.ts +3 -3
  447. package/dist/proxmox/pool.d.ts.map +1 -1
  448. package/dist/proxmox/provision-declare.d.ts +1 -1
  449. package/dist/proxmox/provision-declare.d.ts.map +1 -1
  450. package/dist/proxmox/qemu-lifecycle.d.ts +3 -3
  451. package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
  452. package/dist/proxmox/qemu-read.d.ts +1 -1
  453. package/dist/proxmox/qemu-read.d.ts.map +1 -1
  454. package/dist/proxmox/qemu-resize.d.ts +1 -1
  455. package/dist/proxmox/qemu-resize.d.ts.map +1 -1
  456. package/dist/proxmox/qemu-task.d.ts +1 -1
  457. package/dist/proxmox/qemu-task.d.ts.map +1 -1
  458. package/dist/proxmox/qemu.d.ts +1 -1
  459. package/dist/proxmox/qemu.d.ts.map +1 -1
  460. package/dist/proxmox/replication-job-lifecycle.d.ts +6 -6
  461. package/dist/proxmox/replication-job-lifecycle.d.ts.map +1 -1
  462. package/dist/proxmox/replication-job.d.ts +1 -1
  463. package/dist/proxmox/replication-job.d.ts.map +1 -1
  464. package/dist/proxmox/resource-spec.d.ts +1 -1
  465. package/dist/proxmox/resource-spec.d.ts.map +1 -1
  466. package/dist/proxmox/resource.d.ts +8 -8
  467. package/dist/proxmox/role.d.ts +1 -1
  468. package/dist/proxmox/role.d.ts.map +1 -1
  469. package/dist/proxmox/sdn-apply-read.d.ts +1 -1
  470. package/dist/proxmox/sdn-apply-read.d.ts.map +1 -1
  471. package/dist/proxmox/sdn-apply.d.ts +1 -1
  472. package/dist/proxmox/sdn-apply.d.ts.map +1 -1
  473. package/dist/proxmox/sdn-subnet.d.ts +1 -1
  474. package/dist/proxmox/sdn-subnet.d.ts.map +1 -1
  475. package/dist/proxmox/sdn-vnet.d.ts +1 -1
  476. package/dist/proxmox/sdn-vnet.d.ts.map +1 -1
  477. package/dist/proxmox/sdn-zone.d.ts +1 -1
  478. package/dist/proxmox/sdn-zone.d.ts.map +1 -1
  479. package/dist/proxmox/storage-download-lifecycle.d.ts +6 -6
  480. package/dist/proxmox/storage-download-lifecycle.d.ts.map +1 -1
  481. package/dist/proxmox/storage-download-task.d.ts +1 -1
  482. package/dist/proxmox/storage-download-task.d.ts.map +1 -1
  483. package/dist/proxmox/storage-download.d.ts +1 -1
  484. package/dist/proxmox/storage-download.d.ts.map +1 -1
  485. package/dist/proxmox/storage-wire.d.ts +2 -2
  486. package/dist/proxmox/storage-wire.d.ts.map +1 -1
  487. package/dist/proxmox/storage.d.ts +1 -1
  488. package/dist/proxmox/storage.d.ts.map +1 -1
  489. package/dist/proxmox/user-wire.d.ts +2 -2
  490. package/dist/proxmox/user-wire.d.ts.map +1 -1
  491. package/dist/proxmox/user.d.ts +1 -1
  492. package/dist/proxmox/user.d.ts.map +1 -1
  493. package/dist/proxmox/zfs-pool-form.d.ts +2 -2
  494. package/dist/proxmox/zfs-pool-form.d.ts.map +1 -1
  495. package/dist/proxmox/zfs-pool-wire.d.ts +2 -2
  496. package/dist/proxmox/zfs-pool-wire.d.ts.map +1 -1
  497. package/dist/proxmox/zfs-pool.d.ts +1 -1
  498. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  499. package/dist/release/binary.d.ts +1 -1
  500. package/dist/release/binary.d.ts.map +1 -1
  501. package/dist/release/download.d.ts +1 -1
  502. package/dist/release/download.d.ts.map +1 -1
  503. package/dist/release/index.js +6 -5
  504. package/dist/release/index.js.map +5 -5
  505. package/dist/talos/credentials-write.d.ts +1 -1
  506. package/dist/talos/credentials-write.d.ts.map +1 -1
  507. package/dist/talos/credentials.d.ts +1 -1
  508. package/dist/talos/credentials.d.ts.map +1 -1
  509. package/dist/talos/fake-process.d.ts +2 -2
  510. package/dist/talos/fake-process.d.ts.map +1 -1
  511. package/dist/talos/index.js +7 -7
  512. package/dist/talos/index.js.map +4 -4
  513. package/dist/talos/kubeconfig.d.ts +4 -4
  514. package/dist/talos/kubeconfig.d.ts.map +1 -1
  515. package/dist/talos/machine-config-fixtures.d.ts +1 -1
  516. package/dist/talos/machine-config-fixtures.d.ts.map +1 -1
  517. package/dist/talos/machine-config-read.d.ts +3 -3
  518. package/dist/talos/machine-config-read.d.ts.map +1 -1
  519. package/dist/talos/resource.d.ts +1 -1
  520. package/dist/talos/resource.d.ts.map +1 -1
  521. package/dist/talos/talos-bootstrap-etcd.d.ts +2 -2
  522. package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -1
  523. package/dist/talos/talos-bootstrap.d.ts +4 -4
  524. package/dist/talos/talos-bootstrap.d.ts.map +1 -1
  525. package/dist/talos/talos-cluster-health.d.ts +4 -4
  526. package/dist/talos/talos-cluster-health.d.ts.map +1 -1
  527. package/dist/talos/talos-machine-config.d.ts +2 -2
  528. package/dist/talos/talos-machine-config.d.ts.map +1 -1
  529. package/dist/talos/talosctl.d.ts +1 -1
  530. package/dist/talos/talosctl.d.ts.map +1 -1
  531. package/dist/telemetry/index.js +4 -4
  532. package/dist/telemetry/index.js.map +3 -3
  533. package/dist/telemetry/redact-serialization.d.ts +2 -2
  534. package/dist/telemetry/redact-serialization.d.ts.map +1 -1
  535. package/dist/unifi/acl-rule-ordering.d.ts +6 -6
  536. package/dist/unifi/acl-rule-ordering.d.ts.map +1 -1
  537. package/dist/unifi/acl-rule.d.ts +6 -6
  538. package/dist/unifi/acl-rule.d.ts.map +1 -1
  539. package/dist/unifi/dns-policy.d.ts +6 -6
  540. package/dist/unifi/dns-policy.d.ts.map +1 -1
  541. package/dist/unifi/fake-unifi.d.ts +1 -1
  542. package/dist/unifi/fake-unifi.d.ts.map +1 -1
  543. package/dist/unifi/firewall-policy-ordering.d.ts +6 -6
  544. package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -1
  545. package/dist/unifi/firewall-policy.d.ts +6 -6
  546. package/dist/unifi/firewall-policy.d.ts.map +1 -1
  547. package/dist/unifi/firewall-zone.d.ts +6 -6
  548. package/dist/unifi/firewall-zone.d.ts.map +1 -1
  549. package/dist/unifi/index.js +2 -2
  550. package/dist/unifi/index.js.map +2 -2
  551. package/dist/unifi/network.d.ts +6 -6
  552. package/dist/unifi/network.d.ts.map +1 -1
  553. package/dist/unifi/providers.d.ts +1 -1
  554. package/dist/unifi/providers.d.ts.map +1 -1
  555. package/dist/unifi/resource.d.ts +1 -1
  556. package/dist/unifi/resource.d.ts.map +1 -1
  557. package/dist/unifi/traffic-matching-list.d.ts +6 -6
  558. package/dist/unifi/traffic-matching-list.d.ts.map +1 -1
  559. package/dist/unifi/wifi-broadcast.d.ts +6 -6
  560. package/dist/unifi/wifi-broadcast.d.ts.map +1 -1
  561. package/dist/verify/cli.js.map +1 -1
  562. package/dist/verify/index.js.map +1 -1
  563. package/docs/distilled-interim.md +1 -1
  564. package/docs/mesh-node.md +1 -1
  565. package/docs/paperless.md +1 -1
  566. package/docs/peers.md +8 -8
  567. package/docs/postgres-schema.md +22 -1
  568. package/docs/telemetry.md +1 -1
  569. package/package.json +20 -20
  570. package/src/argocd/fake-argocd.ts +1 -1
  571. package/src/argocd/resource.ts +1 -1
  572. package/src/caddy/admin-transport-scope.test.ts +2 -2
  573. package/src/caddy/admin.ts +1 -1
  574. package/src/caddy/caddy-http-client.ts +5 -5
  575. package/src/caddy/config-adopt.test.ts +2 -2
  576. package/src/caddy/format.ts +2 -2
  577. package/src/caddy/local-admin.test.ts +1 -1
  578. package/src/ceph/auth-entity.ts +1 -1
  579. package/src/ceph/ceph-auth-reconcile.ts +1 -1
  580. package/src/cloudflare/fake-mesh.ts +1 -1
  581. package/src/cloudflare/fake-r2-lock.ts +1 -1
  582. package/src/cloudflare/mesh-node-harness.ts +1 -1
  583. package/src/cloudflare/mesh-node.ts +1 -1
  584. package/src/cloudflare/r2-bucket-lock.ts +1 -1
  585. package/src/discord/fake-discord.ts +1 -1
  586. package/src/discord/resource.ts +1 -1
  587. package/src/forgejo/fake-forgejo.ts +1 -1
  588. package/src/forgejo/resource.ts +1 -1
  589. package/src/google-workspace/fake-google-workspace.ts +1 -1
  590. package/src/google-workspace/resource.ts +1 -1
  591. package/src/grafana/fake-grafana.ts +1 -1
  592. package/src/litellm/access-group.test.ts +1 -1
  593. package/src/litellm/credential-errors.ts +1 -1
  594. package/src/litellm/credential-guards.test.ts +1 -1
  595. package/src/litellm/credential-operations.ts +1 -1
  596. package/src/litellm/credential-rewrite.test.ts +1 -1
  597. package/src/litellm/fake-stack.ts +1 -1
  598. package/src/litellm/key-errors.ts +1 -1
  599. package/src/litellm/key-harness.ts +1 -1
  600. package/src/litellm/key-operations.ts +1 -1
  601. package/src/litellm/key.test.ts +2 -1
  602. package/src/litellm/mcp-server-handlers.test.ts +1 -1
  603. package/src/litellm/mcp-server-registry.test.ts +1 -1
  604. package/src/litellm/model-operations.test.ts +1 -1
  605. package/src/litellm/operations.ts +1 -1
  606. package/src/litellm/pass-through-endpoint-delete-swallow.test.ts +1 -1
  607. package/src/litellm/pass-through-endpoint.test.ts +1 -1
  608. package/src/litellm/pass-through-fetch-client.test.ts +2 -2
  609. package/src/litellm/policy-attachment.test.ts +1 -1
  610. package/src/litellm/policy.test.ts +1 -1
  611. package/src/litellm/team-members.test.ts +1 -1
  612. package/src/litellm/team-read.test.ts +1 -1
  613. package/src/litellm/tool-policy.test.ts +1 -1
  614. package/src/litellm/toolset.test.ts +1 -1
  615. package/src/netbox/fake-netbox.ts +1 -1
  616. package/src/netbox/resource.ts +1 -1
  617. package/src/openbao/adopt-core.test.ts +4 -1
  618. package/src/openbao/adopt-families.test.ts +4 -1
  619. package/src/openbao/adopt-holes.test.ts +1 -1
  620. package/src/openbao/adopt-recovery.test.ts +24 -0
  621. package/src/openbao/approle-login.ts +2 -2
  622. package/src/openbao/auth-method-reconcile.ts +1 -1
  623. package/src/openbao/auth-method.ts +1 -1
  624. package/src/openbao/auth-role-sdk.test.ts +1 -1
  625. package/src/openbao/auth-role.ts +1 -1
  626. package/src/openbao/bao-http.test.ts +3 -3
  627. package/src/openbao/bao-http.ts +4 -4
  628. package/src/openbao/bao-identity.ts +2 -2
  629. package/src/openbao/cloudflare-permission-groups.ts +1 -1
  630. package/src/openbao/cloudflare-role-wire.ts +1 -1
  631. package/src/openbao/cloudflare-role.ts +1 -1
  632. package/src/openbao/distilled-retry.test.ts +3 -3
  633. package/src/openbao/distilled.test.ts +3 -3
  634. package/src/openbao/distilled.ts +2 -2
  635. package/src/openbao/fake-bao.ts +2 -2
  636. package/src/openbao/fake-core.ts +1 -1
  637. package/src/openbao/fake-engines.ts +1 -1
  638. package/src/openbao/fake-families.ts +1 -1
  639. package/src/openbao/fake-stack.ts +13 -3
  640. package/src/openbao/jwt-config.ts +1 -1
  641. package/src/openbao/jwt-role.ts +1 -1
  642. package/src/openbao/kubernetes-role.ts +1 -1
  643. package/src/openbao/mfa-enforcement.ts +1 -1
  644. package/src/openbao/mfa-totp.ts +1 -1
  645. package/src/openbao/mfa-wire.ts +1 -1
  646. package/src/openbao/mount-move.ts +1 -1
  647. package/src/openbao/mount-reconcile.ts +1 -1
  648. package/src/openbao/mount.ts +1 -1
  649. package/src/openbao/pki-role.ts +1 -1
  650. package/src/openbao/plugin-reconcile.ts +1 -1
  651. package/src/openbao/plugin-wire.ts +1 -1
  652. package/src/openbao/plugin.ts +1 -1
  653. package/src/openbao/policy.ts +1 -1
  654. package/src/openbao/proxmox-role.ts +1 -1
  655. package/src/openbao/remount-wire.ts +1 -1
  656. package/src/openbao/rename-occupied.test.ts +1 -1
  657. package/src/openbao/role-reconcile.ts +1 -1
  658. package/src/openbao/role-rename.test.ts +1 -1
  659. package/src/openbao/ssh-role.ts +1 -1
  660. package/src/opnsense/fake-opnsense.ts +1 -1
  661. package/src/opnsense/resource.ts +1 -1
  662. package/src/ownership/probe.ts +51 -2
  663. package/src/paperless/fake-paperless.ts +1 -1
  664. package/src/paperless/matching-types.ts +1 -1
  665. package/src/postgres/connection.ts +11 -15
  666. package/src/postgres/database-bigint-serialization.test.ts +3 -3
  667. package/src/postgres/database-sql.ts +7 -7
  668. package/src/postgres/database.ts +1 -1
  669. package/src/postgres/fake-grants-read.ts +4 -4
  670. package/src/postgres/fake-grants-sql.ts +1 -1
  671. package/src/postgres/fake-grants-write.ts +1 -1
  672. package/src/postgres/fake-role-sql.ts +3 -3
  673. package/src/postgres/fake-schema-drop.ts +75 -0
  674. package/src/postgres/fake-schema-sql.ts +11 -2
  675. package/src/postgres/fake-sql.ts +11 -4
  676. package/src/postgres/grants-database.test.ts +5 -5
  677. package/src/postgres/grants-existence.ts +8 -8
  678. package/src/postgres/grants-ops.ts +1 -1
  679. package/src/postgres/grants-ownership.ts +6 -6
  680. package/src/postgres/grants-psql-lifecycle.test.ts +7 -3
  681. package/src/postgres/grants-read-defaults.ts +6 -6
  682. package/src/postgres/grants-read.ts +17 -17
  683. package/src/postgres/grants-relkind-wire.test.ts +6 -4
  684. package/src/postgres/index.ts +2 -0
  685. package/src/postgres/installed-classifier.ts +1 -1
  686. package/src/postgres/psql-executor-escaping.test.ts +3 -1
  687. package/src/postgres/psql-executor.test.ts +11 -5
  688. package/src/postgres/psql-executor.ts +5 -7
  689. package/src/postgres/role-adopt.test.ts +3 -1
  690. package/src/postgres/role-membership-options.test.ts +3 -1
  691. package/src/postgres/role-membership-repair.test.ts +3 -3
  692. package/src/postgres/role-membership-sql.ts +5 -5
  693. package/src/postgres/role-password-transports.test.ts +6 -4
  694. package/src/postgres/role-sql.ts +2 -2
  695. package/src/postgres/role.ts +1 -1
  696. package/src/postgres/schema-assert.ts +1 -1
  697. package/src/postgres/schema-closure-sql.ts +108 -0
  698. package/src/postgres/schema-delete-proofs.test.ts +7 -7
  699. package/src/postgres/schema-delete.ts +89 -47
  700. package/src/postgres/schema-drop-2bp01.test.ts +30 -18
  701. package/src/postgres/schema-drop-real.test.ts +190 -0
  702. package/src/postgres/schema-drop-sql.ts +135 -0
  703. package/src/postgres/schema-drop.test.ts +241 -0
  704. package/src/postgres/schema-errors.ts +26 -0
  705. package/src/postgres/schema-handlers.test.ts +21 -14
  706. package/src/postgres/schema-lifecycle.test.ts +6 -60
  707. package/src/postgres/schema-reconcile.ts +1 -1
  708. package/src/postgres/schema-sequence-error.ts +38 -0
  709. package/src/postgres/schema-socket.test.ts +20 -6
  710. package/src/postgres/schema-sql.ts +17 -12
  711. package/src/postgres/schema-takeover.test.ts +7 -4
  712. package/src/postgres/schema-test-kit.ts +18 -4
  713. package/src/postgres/search-path.test.ts +100 -0
  714. package/src/postgres/search-path.ts +62 -0
  715. package/src/proxmox/ceph-flag-wire.test.ts +1 -1
  716. package/src/proxmox/ceph-fs-destroy-sdk.test.ts +1 -1
  717. package/src/proxmox/ceph-pool-write.test.ts +1 -1
  718. package/src/proxmox/client.test.ts +2 -2
  719. package/src/proxmox/client.ts +2 -2
  720. package/src/proxmox/credentials.test.ts +1 -1
  721. package/src/proxmox/distilled-pbs.test.ts +1 -1
  722. package/src/proxmox/distilled-pbs.ts +1 -1
  723. package/src/proxmox/distilled-pve.test.ts +2 -2
  724. package/src/proxmox/distilled-pve.ts +1 -1
  725. package/src/proxmox/fake-pbs-jobs.ts +1 -1
  726. package/src/proxmox/fake-pve.ts +1 -1
  727. package/src/proxmox/lease-cache-mint.test.ts +1 -1
  728. package/src/proxmox/live-core-fixtures.ts +1 -1
  729. package/src/proxmox/lxc-distilled.test.ts +1 -1
  730. package/src/proxmox/lxc-harness.ts +1 -1
  731. package/src/proxmox/members-timeout.test.ts +3 -3
  732. package/src/proxmox/members.test.ts +1 -1
  733. package/src/proxmox/members.ts +4 -4
  734. package/src/proxmox/mint.ts +4 -4
  735. package/src/proxmox/node-network-read-failure.test.ts +1 -1
  736. package/src/proxmox/qemu-lifecycle.ts +1 -1
  737. package/src/proxmox/read-failure-propagation.test.ts +1 -1
  738. package/src/proxmox/resource-spec.ts +1 -1
  739. package/src/proxmox/storage-read-failure.test.ts +1 -1
  740. package/src/proxmox/typed-absence.test.ts +2 -2
  741. package/src/proxmox/unreadable-read.test.ts +1 -1
  742. package/src/proxmox/user.test.ts +1 -1
  743. package/src/proxmox/zfs-pool-read-failure.test.ts +1 -1
  744. package/src/release/adopt-parity.test.ts +3 -1
  745. package/src/release/apply-pins.test.ts +2 -2
  746. package/src/release/binary-root.test.ts +2 -2
  747. package/src/release/binary.ts +9 -2
  748. package/src/release/download.test.ts +3 -3
  749. package/src/release/download.ts +1 -1
  750. package/src/release/fake-deploy.ts +2 -2
  751. package/src/release/fake-engine.ts +2 -2
  752. package/src/release/fake-provider.ts +2 -2
  753. package/src/release/plan.test.ts +2 -2
  754. package/src/release/providers.ts +1 -1
  755. package/src/talos/credentials-write.test.ts +1 -1
  756. package/src/talos/credentials-write.ts +2 -2
  757. package/src/talos/credentials.test.ts +1 -1
  758. package/src/talos/credentials.ts +2 -2
  759. package/src/talos/fake-process.ts +2 -2
  760. package/src/talos/kubeconfig.test.ts +1 -1
  761. package/src/talos/machine-config-fixtures.ts +1 -1
  762. package/src/talos/resource.ts +1 -1
  763. package/src/talos/talos-bootstrap.test.ts +1 -1
  764. package/src/talos/talos-cluster-health.test.ts +1 -1
  765. package/src/talos/talosctl.ts +2 -2
  766. package/src/telemetry/http-client-sealing.test.ts +2 -2
  767. package/src/telemetry/layer.test.ts +3 -3
  768. package/src/telemetry/layer.ts +2 -2
  769. package/src/telemetry/redact-serialization.ts +2 -2
  770. package/src/unifi/fake-unifi.ts +1 -1
  771. package/src/unifi/get-only-guard.test.ts +3 -3
  772. package/src/unifi/resource.ts +1 -1
  773. package/src/verify/args.ts +1 -1
@@ -4,6 +4,7 @@
4
4
  * Refusals use checked catalog facts or raw SQLSTATE (42P06 / 2BP01), never driver message text.
5
5
  */
6
6
  import * as Data from 'effect/Data';
7
+ import type { PostgresSchemaCascadeSequencesRefused } from './schema-sequence-error.ts';
7
8
 
8
9
  /** A declared name would be silently truncated (same as `PostgresDatabaseNameRefused`). */
9
10
  export class PostgresSchemaNameRefused extends Data.TaggedError('PostgresSchemaNameRefused')<{
@@ -94,6 +95,29 @@ export class PostgresSchemaDropNotEmptyError extends Data.TaggedError(
94
95
  }
95
96
  }
96
97
 
98
+ /**
99
+ * `cascade: true` refused: `DROP SCHEMA … CASCADE` would also drop objects that live in OTHER
100
+ * schemas because they depend on something in this one (a view, a foreign key or a trigger
101
+ * another stack owns). The refusal carries the COUNT only — never an object name, so the error
102
+ * cannot disclose another owner's catalog. Nothing was dropped: move or drop those dependents
103
+ * deliberately, or empty this schema by hand and declare `cascade: false`.
104
+ */
105
+ export class PostgresSchemaCascadeCrossSchemaRefused extends Data.TaggedError(
106
+ 'PostgresSchemaCascadeCrossSchemaRefused',
107
+ )<{
108
+ readonly schema: string;
109
+ /** How many dependent objects live outside this schema (at least one when raised). */
110
+ readonly dependents: number;
111
+ }> {
112
+ override get message(): string {
113
+ return (
114
+ `Postgres.Schema "${this.schema}": cascade: true refused — ${String(this.dependents)} ` +
115
+ 'dependent object(s) outside this schema would be dropped with it. No DROP was issued. ' +
116
+ 'Remove or move those dependents first.'
117
+ );
118
+ }
119
+ }
120
+
97
121
  /** Every statement this resource issues must run against the DECLARED database. The family
98
122
  * connection points at a maintenance database, so the schema handlers open `props.database`
99
123
  * themselves (`withPg`'s database override); this failure means the server answered
@@ -204,6 +228,8 @@ export type PostgresSchemaError =
204
228
  | PostgresSchemaDrift
205
229
  | PostgresSchemaCreateVanished
206
230
  | PostgresSchemaDropNotEmptyError
231
+ | PostgresSchemaCascadeCrossSchemaRefused
232
+ | PostgresSchemaCascadeSequencesRefused
207
233
  | PostgresSchemaDeleteForeignRefused
208
234
  | PostgresSchemaWrongDatabase
209
235
  | PostgresSchemaDatabaseRefused;
@@ -14,6 +14,7 @@ import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-att
14
14
  import { Unowned } from 'alchemy/AdoptPolicy';
15
15
  import { postgresSchemaHandlers } from './schema.ts';
16
16
  import { PostgresSchemaDropNotEmptyError, PostgresSchemaWrongDatabase } from './schema-errors.ts';
17
+ import { buildAtomicDropSql } from './schema-drop-sql.ts';
17
18
  import { deleteArgs, ok, readArgs, route, router, runnerWith } from './schema-test-kit.ts';
18
19
 
19
20
  const sampleOutput: PostgresSchemaAttributes = {
@@ -51,10 +52,12 @@ describe('delete handler (runner transport)', () => {
51
52
  ),
52
53
  ),
53
54
  );
54
- expect(stdins.find((s) => s.startsWith('DROP SCHEMA'))).toBe(
55
- 'DROP SCHEMA IF EXISTS "ledger" CASCADE;',
55
+ // The drop is ONE `DO` statement carrying the proven oid + owner (`schema-drop-sql.ts`),
56
+ // not a re-read followed by a separate `DROP`.
57
+ expect(stdins.find((s) => s.startsWith('DO '))).toBe(
58
+ `${buildAtomicDropSql({ name: 'ledger', oid: 1, owner: 'tim', cascade: true })};`,
56
59
  );
57
- // One `psql` argv per STATEMENT: probe, proof, ownership re-read, drop. The probe's argv
60
+ // One `psql` argv per STATEMENT: probe, proof, ownership re-read, atomic drop. The probe's argv
58
61
  // targets the family database; the delete's argvs target the declared one — the `-d` value
59
62
  // is the argv's last element.
60
63
  expect(argvs.length).toBe(4);
@@ -80,17 +83,19 @@ describe('delete handler (runner transport)', () => {
80
83
  ),
81
84
  ),
82
85
  );
83
- expect(stdins.find((s) => s.startsWith('DROP SCHEMA'))).toBe('DROP SCHEMA IF EXISTS "ledger";');
86
+ expect(stdins.find((s) => s.startsWith('DO '))).toBe(
87
+ `${buildAtomicDropSql({ name: 'ledger', oid: 1, owner: 'tim', cascade: false })};`,
88
+ );
84
89
  });
85
90
 
86
- test('the real handler refuses a non-empty schema over the runner transport, no DROP issued', async () => {
87
- const { run, stdins } = runnerWith(
88
- router({
89
- probe: '[{"present":1}]',
90
- schema: '[{"name":"ledger","oid":1,"owner":"tim"}]',
91
- empty: '[{"empty":false}]',
92
- proof,
93
- }),
91
+ test('a non-empty schema is the typed refusal the atomic drop raises (HF002), over one psql', async () => {
92
+ const answers = router({
93
+ probe: '[{"present":1}]',
94
+ schema: '[{"name":"ledger","oid":1,"owner":"tim"}]',
95
+ proof,
96
+ });
97
+ const { run, stdins } = runnerWith(answers, (stdin) =>
98
+ stdin.startsWith('DO ') ? 'ERROR: HF002: schema not empty' : undefined,
94
99
  );
95
100
  const error = await Effect.runPromise(
96
101
  Effect.flip(
@@ -104,7 +109,9 @@ describe('delete handler (runner transport)', () => {
104
109
  ),
105
110
  );
106
111
  expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
107
- expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
112
+ // Proof and drop were ONE statement: exactly one `DO`, and no separate emptiness probe.
113
+ expect(stdins.filter((s) => s.startsWith('DO ')).length).toBe(1);
114
+ expect(stdins.some((s) => s.includes('AS empty'))).toBe(false);
108
115
  });
109
116
 
110
117
  test('the real handler refuses a wrong connected database before any DROP', async () => {
@@ -128,7 +135,7 @@ describe('delete handler (runner transport)', () => {
128
135
  ),
129
136
  );
130
137
  expect(error).toBeInstanceOf(PostgresSchemaWrongDatabase);
131
- expect(stdins.some((s) => s.startsWith('DROP SCHEMA'))).toBe(false);
138
+ expect(stdins.some((s) => s.startsWith('DO '))).toBe(false);
132
139
  });
133
140
 
134
141
  test('defaultRemovalPolicy is retain — declared on the Resource for Postgres.Schema itself', () => {
@@ -1,18 +1,16 @@
1
1
  /**
2
2
  * `reconcile`, `read`, and `drop` for `Postgres.Schema` against `fake-sql.ts`'s recording fake.
3
3
  * Tests the greenfield create, comment creation, already-present/drift, owner-missing guard,
4
- * quoting, the safe-drop rules, and the `current_database()` proof every write path runs first.
4
+ * quoting, and the `current_database()` proof every write path runs first. The drop rules live
5
+ * in `schema-drop.test.ts`.
5
6
  */
6
7
  import { describe, expect, test } from 'bun:test';
7
8
  import * as Effect from 'effect/Effect';
8
- import { SqlError, UnknownError } from 'effect/unstable/sql/SqlError';
9
9
  import { makeFakeSql } from './fake-sql.ts';
10
10
  import { type PostgresSchemaAttributes, type PostgresSchemaProps } from './schema-attrs.ts';
11
- import type { PgExecutor } from './database-sql.ts';
12
11
  import {
13
12
  PostgresSchemaCreateVanished,
14
13
  PostgresSchemaDrift,
15
- PostgresSchemaDropNotEmptyError,
16
14
  PostgresSchemaExistsRefused,
17
15
  PostgresSchemaOwnerMissing,
18
16
  PostgresSchemaWrongDatabase,
@@ -42,7 +40,9 @@ describe('the current_database() proof', () => {
42
40
  expect(refusal.declared).toBe('agents');
43
41
  expect(refusal.connected).toBe('postgres');
44
42
  // The refusal fires before the first pg_namespace read, so nothing but the proof ran.
45
- expect(fake.statements.some((s) => s.text.includes('FROM pg_namespace'))).toBe(false);
43
+ expect(fake.statements.some((s) => s.text.includes('FROM pg_catalog.pg_namespace'))).toBe(
44
+ false,
45
+ );
46
46
  expect(fake.statements.some((s) => s.text.startsWith('CREATE SCHEMA'))).toBe(false);
47
47
  });
48
48
 
@@ -50,7 +50,7 @@ describe('the current_database() proof', () => {
50
50
  const fake = makeFakeSql({ schemas: [liveRow()] });
51
51
  const error = await fails(dropWithClient(fake, { ...baseProps, database: 'agents' }));
52
52
  expect(error).toBeInstanceOf(PostgresSchemaWrongDatabase);
53
- expect(fake.statements.some((s) => s.text.startsWith('DROP SCHEMA'))).toBe(false);
53
+ expect(fake.statements.some((s) => s.text.startsWith('DO '))).toBe(false);
54
54
  expect(fake.schemas.get('ledger')).not.toBeUndefined();
55
55
  });
56
56
 
@@ -190,57 +190,3 @@ describe('read', () => {
190
190
  expect(await run(readWithClient(fake, 'ledger'))).toEqual(liveRow());
191
191
  });
192
192
  });
193
-
194
- describe('drop', () => {
195
- test('drops an empty schema with cascade false', async () => {
196
- const fake = makeFakeSql({ schemas: [liveRow()] });
197
- await run(dropWithClient(fake, baseProps));
198
- const drops = fake.statements.filter((s) => s.text.startsWith('DROP SCHEMA'));
199
- expect(drops.length).toBe(1);
200
- expect(drops[0]?.text).toBe('DROP SCHEMA IF EXISTS "ledger"');
201
- expect(fake.schemas.get('ledger')).toBeUndefined();
202
- });
203
-
204
- test('refuses to drop a non-empty schema with cascade false', async () => {
205
- const fake = makeFakeSql({ schemas: [liveRow()], schemasWithRelations: ['ledger'] });
206
- const error = await fails(dropWithClient(fake, baseProps));
207
- expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
208
- expect(fake.schemas.get('ledger')).not.toBeUndefined();
209
- });
210
-
211
- test('drops a non-empty schema with cascade true', async () => {
212
- const fake = makeFakeSql({ schemas: [liveRow()], schemasWithRelations: ['ledger'] });
213
- await run(dropWithClient(fake, { ...baseProps, cascade: true }));
214
- const drop = fake.statements.find((s) => s.text.startsWith('DROP SCHEMA'));
215
- expect(drop?.text).toBe('DROP SCHEMA IF EXISTS "ledger" CASCADE');
216
- expect(fake.schemas.get('ledger')).toBeUndefined();
217
- });
218
-
219
- test('classifies the server 2BP01 refusal as the typed not-empty tag', async () => {
220
- // The emptiness check said empty, but the server refuses with SQLSTATE 2BP01 — an object
221
- // kind the check's four catalogs do not cover. Class `2B` is not `42`, so both drivers
222
- // wrap it as UnknownError with the raw code on the cause; this executor replays that shape.
223
- const refusing: PgExecutor = {
224
- unsafe: <A extends object>(text: string) =>
225
- text.startsWith('SELECT current_database()')
226
- ? Effect.succeed([{ database: 'postgres' }] as unknown as ReadonlyArray<A>)
227
- : text.includes('AS empty')
228
- ? Effect.succeed([{ empty: true }] as unknown as ReadonlyArray<A>)
229
- : Effect.fail(
230
- new SqlError({
231
- reason: new UnknownError({
232
- cause: Object.assign(
233
- new Error('ERROR: 2BP01: dependent objects still exist'),
234
- { code: '2BP01' },
235
- ),
236
- message: 'dependent_objects_still_exist',
237
- operation: 'DROP SCHEMA',
238
- }),
239
- }),
240
- ),
241
- transaction: () => Effect.void,
242
- };
243
- const error = await fails(dropWithClient(refusing, baseProps));
244
- expect(error).toBeInstanceOf(PostgresSchemaDropNotEmptyError);
245
- });
246
- });
@@ -1,6 +1,6 @@
1
1
  /** Schema reconcile: prove the stored target and identity before asserting a live row. */
2
2
  import * as Effect from 'effect/Effect';
3
- import type { SqlError } from 'effect/unstable/sql/SqlError';
3
+ import type { SqlError } from 'effect/sql/SqlError';
4
4
  import { type PgExecutor, roleExists } from './database-sql.ts';
5
5
  import {
6
6
  type PostgresSchemaAttributes,
@@ -0,0 +1,38 @@
1
+ import * as Data from 'effect/Data';
2
+
3
+ /**
4
+ * `cascade: true` on a schema that holds a SEQUENCE is refused (`HF004`, `schema-drop-sql.ts`).
5
+ *
6
+ * ⛔ A sequence cannot be locked by `LOCK TABLE`, so the drop's closure proof has a hole there: a
7
+ * concurrent, uncommitted `CREATE VIEW other.v AS SELECT last_value FROM ours.seq` is invisible
8
+ * to the scan, and when it commits while the drop waits on the sequence, PostgreSQL's deletion
9
+ * cascades into `other.v` (Codex read of PR 357, 2026-10-06). Serial and identity columns each
10
+ * own a sequence, so such a schema cannot be cascade-dropped by this provider.
11
+ * The message carries a COUNT only. Nothing was dropped: drop the schema's contents deliberately
12
+ * (the sequences included), then declare `cascade: false`.
13
+ */
14
+ export class PostgresSchemaCascadeSequencesRefused extends Data.TaggedError(
15
+ 'PostgresSchemaCascadeSequencesRefused',
16
+ )<{
17
+ readonly schema: string;
18
+ /** How many sequences the schema holds (at least one when raised). */
19
+ readonly sequences: number;
20
+ }> {
21
+ override get message(): string {
22
+ return (
23
+ `Postgres.Schema "${this.schema}": cascade: true refused — the schema holds ` +
24
+ `${String(this.sequences)} sequence(s) (serial/identity columns own one), which cannot be ` +
25
+ 'locked, so a concurrent dependent could escape the cascade proof. No DROP was issued. ' +
26
+ 'Drop the schema contents first, then declare cascade: false.'
27
+ );
28
+ }
29
+ }
30
+
31
+ /** The sequence COUNT out of an `HF004` error; unreadable still refuses (1, never 0). */
32
+ export const sequencesCount = (error: {
33
+ readonly reason: { readonly cause?: unknown };
34
+ }): number => {
35
+ const cause = error.reason.cause;
36
+ const message = typeof cause === 'object' && cause !== null ? (cause as Error).message : '';
37
+ return Math.max(1, Number(/sequences:\s*(\d+)/.exec(message ?? '')?.[1] ?? 1));
38
+ };
@@ -11,7 +11,8 @@ import * as PgClientModule from '@effect/sql-pg/PgClient';
11
11
  import type { PgClient as PgClientService } from '@effect/sql-pg/PgClient';
12
12
  import * as Effect from 'effect/Effect';
13
13
  import * as Layer from 'effect/Layer';
14
- import { SqlClient } from 'effect/unstable/sql/SqlClient';
14
+ import { SqlClient, TransactionConnection } from 'effect/sql/SqlClient';
15
+ import { PIN_SEARCH_PATH_SQL } from './search-path.ts';
15
16
  import { isDependentObjectsError } from './schema-sql.ts';
16
17
  import { classifyInstalled } from './installed-classifier.ts';
17
18
  import { PostgresPool, postgresConnection } from './connection.ts';
@@ -31,6 +32,8 @@ const schemaRead = postgresSchemaHandlers.read;
31
32
  const pools: Array<{ database?: string | undefined }> = [];
32
33
  /** Every SQL text the fake client ran, in order. */
33
34
  const queries: string[] = [];
35
+ /** The pool count at each `SET search_path`: one pin per pool, before that pool's statements. */
36
+ const pins: number[] = [];
34
37
  /** The router answers for the current test (`schema-test-kit.ts` markers, JSON strings). */
35
38
  let answers: RouteAnswers = {};
36
39
 
@@ -38,7 +41,15 @@ let answers: RouteAnswers = {};
38
41
  // callbacks), and `Statement<A>` is an `Effect<ReadonlyArray<A>, SqlError>` — a plain succeed
39
42
  // satisfies the same call shape.
40
43
  const fakeClient = {
44
+ // `pinnedSocketExecutor` reserves one connection and routes every statement through the
45
+ // client's own `transactionService` — the fake only has to answer both.
46
+ reserve: Effect.succeed({}),
47
+ transactionService: TransactionConnection(0),
41
48
  unsafe: (text: string) => {
49
+ if (text === PIN_SEARCH_PATH_SQL) {
50
+ pins.push(pools.length);
51
+ return Effect.succeed([] as never);
52
+ }
42
53
  queries.push(text);
43
54
  const answer = route(text, answers);
44
55
  return Effect.succeed(
@@ -72,6 +83,7 @@ describe('socket transport: a missing declared database is schema absent', () =>
72
83
  beforeEach(() => {
73
84
  pools.length = 0;
74
85
  queries.length = 0;
86
+ pins.length = 0;
75
87
  answers = {};
76
88
  });
77
89
 
@@ -85,8 +97,8 @@ describe('socket transport: a missing declared database is schema absent', () =>
85
97
  expect(pools.length).toBe(1);
86
98
  expect(pools[0]?.database).toBe('postgres');
87
99
  expect(queries.length).toBe(1);
88
- expect(queries[0]).toContain('FROM pg_database');
89
- expect(queries.some((q) => q.startsWith('DROP SCHEMA'))).toBe(false);
100
+ expect(queries[0]).toContain('FROM pg_catalog.pg_database');
101
+ expect(queries.some((q) => q.startsWith('DO '))).toBe(false);
90
102
  });
91
103
 
92
104
  test('read answers absent: the untyped 3D000 connect never happens', async () => {
@@ -98,7 +110,7 @@ describe('socket transport: a missing declared database is schema absent', () =>
98
110
  expect(pools.length).toBe(1);
99
111
  expect(pools[0]?.database).toBe('postgres');
100
112
  expect(queries.length).toBe(1);
101
- expect(queries[0]).toContain('FROM pg_database');
113
+ expect(queries[0]).toContain('FROM pg_catalog.pg_database');
102
114
  });
103
115
 
104
116
  test('the `database` override reaches the pool: probe over the family pool, statements over the declared one', async () => {
@@ -113,7 +125,9 @@ describe('socket transport: a missing declared database is schema absent', () =>
113
125
  );
114
126
  // The probe opened the family database; every statement after it opened `agents`.
115
127
  expect(pools.map((pool) => pool.database)).toEqual(['postgres', 'agents']);
116
- expect(queries.some((q) => q.startsWith('DROP SCHEMA'))).toBe(true);
128
+ // Each pool's reserved connection is pinned before its first statement: pool 1, then pool 2.
129
+ expect(pins).toEqual([1, 2]);
130
+ expect(queries.some((q) => q.startsWith('DO '))).toBe(true);
117
131
  });
118
132
 
119
133
  test('read over an existing declared database answers the row from the overridden pool', async () => {
@@ -147,7 +161,7 @@ describe('socket transport: a missing declared database is schema absent', () =>
147
161
  );
148
162
  expect(error).toBeInstanceOf(PostgresSchemaDeleteForeignRefused);
149
163
  expect(error).toMatchObject({ liveOid: 16443, liveOwner: 'other_role', lastOid: 16442 });
150
- expect(queries.some((q) => q.startsWith('DROP SCHEMA'))).toBe(false);
164
+ expect(queries.some((q) => q.startsWith('DO '))).toBe(false);
151
165
  });
152
166
 
153
167
  test('the installed classifier keeps 3D000 as UnknownError with the raw code — the untyped failure the probe prevents', async () => {
@@ -9,7 +9,7 @@
9
9
  * ★ The schema name is a single `ColId` token, so `quoteIdent` (single-token quoting) is
10
10
  * correct — same rule as `Postgres.Database`'s name.
11
11
  */
12
- import type { SqlError } from 'effect/unstable/sql/SqlError';
12
+ import type { SqlError } from 'effect/sql/SqlError';
13
13
  import * as Effect from 'effect/Effect';
14
14
  import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
15
15
  import { quoteIdent, quoteStringLiteral } from './database-sql.ts';
@@ -32,10 +32,10 @@ export const buildDropSchemaSql = (name: string, cascade: boolean): string =>
32
32
  const SELECT_SCHEMA_SQL = `SELECT
33
33
  n.oid AS oid,
34
34
  n.nspname AS name,
35
- pg_get_userbyid(n.nspowner) AS owner,
36
- obj_description(n.oid, 'pg_namespace') AS comment,
35
+ pg_catalog.pg_get_userbyid(n.nspowner) AS owner,
36
+ pg_catalog.obj_description(n.oid, 'pg_namespace') AS comment,
37
37
  current_database() AS database
38
- FROM pg_namespace n
38
+ FROM pg_catalog.pg_namespace n
39
39
  WHERE n.nspname = $1`;
40
40
 
41
41
  /** The read: one bound `SELECT` on `pg_namespace`. `undefined` when absent. The row carries
@@ -84,18 +84,23 @@ export const currentUser = (pg: PgExecutor): Effect.Effect<string, SqlError> =>
84
84
  *
85
85
  * ⚠️ THE FAKE (`fake-schema-sql.ts`) ROUTES THIS STATEMENT BY `AS empty` + `pg_class` — keep both
86
86
  * markers in any rewrite, and keep this check matched BEFORE the plain `pg_namespace` branch
87
- * (this SQL contains `FROM pg_namespace` too, inside its `WITH`).
87
+ * (this SQL contains `FROM pg_catalog.pg_namespace` too, inside its `WITH`).
88
88
  */
89
- const SCHEMA_EMPTY_SQL = `WITH ns AS (SELECT oid FROM pg_namespace WHERE nspname = $1)
90
- SELECT NOT EXISTS (
91
- SELECT 1 FROM pg_class c WHERE c.relnamespace = (SELECT oid FROM ns)
89
+ /** The four-catalog emptiness predicate over a namespace oid expression — shared by this read
90
+ * and by the atomic drop's in-transaction check (`schema-drop-sql.ts`), so the two cannot
91
+ * disagree about what "empty" means. */
92
+ export const emptyPredicate = (ns: string): string => `NOT EXISTS (
93
+ SELECT 1 FROM pg_catalog.pg_class c WHERE c.relnamespace = ${ns}
92
94
  ) AND NOT EXISTS (
93
- SELECT 1 FROM pg_proc p WHERE p.pronamespace = (SELECT oid FROM ns)
95
+ SELECT 1 FROM pg_catalog.pg_proc p WHERE p.pronamespace = ${ns}
94
96
  ) AND NOT EXISTS (
95
- SELECT 1 FROM pg_type t WHERE t.typnamespace = (SELECT oid FROM ns)
97
+ SELECT 1 FROM pg_catalog.pg_type t WHERE t.typnamespace = ${ns}
96
98
  ) AND NOT EXISTS (
97
- SELECT 1 FROM pg_operator o WHERE o.oprnamespace = (SELECT oid FROM ns)
98
- ) AS empty`;
99
+ SELECT 1 FROM pg_catalog.pg_operator o WHERE o.oprnamespace = ${ns}
100
+ )`;
101
+
102
+ const SCHEMA_EMPTY_SQL = `WITH ns AS (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
103
+ SELECT ${emptyPredicate('(SELECT oid FROM ns)')} AS empty`;
99
104
 
100
105
  /** `true` when the schema holds none of the four object catalogs above (used before a
101
106
  * non-cascade `DROP SCHEMA`). */
@@ -5,6 +5,7 @@ import { postgresSchemaHandlers, reconcileWithClient } from './schema.ts';
5
5
  import { postgresRunnerConnection } from './connection.ts';
6
6
  import { makeFakeSql } from './fake-sql.ts';
7
7
  import { readArgs, router, runnerWith } from './schema-test-kit.ts';
8
+ import { stripPin } from './search-path.ts';
8
9
  import type { PostgresSchemaAttributes } from './schema-attrs.ts';
9
10
 
10
11
  const props = { name: 'ledger', database: 'postgres', owner: 'postgres', cascade: true };
@@ -101,21 +102,23 @@ test('same-owner create race is a typed exists refusal, never a comment or adopt
101
102
 
102
103
  test('runner 42P06 becomes an adoption refusal; other SQLSTATEs remain SqlError', async () => {
103
104
  for (const code of ['42P06', '42501']) {
104
- const run = ({ stdin }: { stdin: string }) =>
105
- Promise.resolve(
105
+ const run = ({ stdin: raw }: { stdin: string }) => {
106
+ const stdin = stripPin(raw);
107
+ return Promise.resolve(
106
108
  stdin.startsWith('CREATE')
107
109
  ? { code: 3, stdout: '', stderr: `ERROR: ${code}: refused` }
108
110
  : {
109
111
  code: 0,
110
112
  stdout:
111
- stdin.includes('current_database()') && !stdin.includes('pg_namespace')
113
+ stdin.includes('current_database()') && !stdin.includes('pg_catalog.pg_namespace')
112
114
  ? '[{"database":"postgres"}]'
113
- : stdin.includes('pg_roles')
115
+ : stdin.includes('pg_catalog.pg_roles')
114
116
  ? '[{"present":1}]'
115
117
  : '[]',
116
118
  stderr: '',
117
119
  },
118
120
  );
121
+ };
119
122
  const error = await Effect.runPromise(
120
123
  postgresSchemaHandlers
121
124
  .reconcile(args())
@@ -11,6 +11,7 @@
11
11
  * branch's marker and matches its own.
12
12
  */
13
13
  import type { PsqlRunner } from './psql-executor.ts';
14
+ import { stripPin } from './search-path.ts';
14
15
  import type { PostgresSchemaAttributes, PostgresSchemaProps } from './schema-attrs.ts';
15
16
 
16
17
  export const ok = (stdout: string) => Promise.resolve({ code: 0, stdout, stderr: '' });
@@ -29,9 +30,12 @@ export interface RouteAnswers {
29
30
 
30
31
  /** Route one stdin to its answer by the markers above, `undefined` when no branch matches. */
31
32
  export const route = (stdin: string, answers: RouteAnswers): string | undefined => {
33
+ // The atomic drop (`schema-drop-sql.ts`) quotes every marker below inside its body: it answers
34
+ // nothing, and a refusal is injected by `runnerWith`'s `failOn`, never routed.
35
+ if (stdin.startsWith('DO ')) return undefined;
32
36
  if (stdin.includes('AS empty')) return answers.empty;
33
- if (stdin.includes('FROM pg_namespace')) return answers.schema;
34
- if (stdin.includes('FROM pg_database')) return answers.probe;
37
+ if (stdin.includes('FROM pg_catalog.pg_namespace')) return answers.schema;
38
+ if (stdin.includes('FROM pg_catalog.pg_database')) return answers.probe;
35
39
  if (stdin.includes('current_database()')) return answers.proof;
36
40
  return undefined;
37
41
  };
@@ -46,14 +50,24 @@ export const router = (answers: RouteAnswers) => (stdin: string) => route(stdin,
46
50
  */
47
51
  export const runnerWith = (
48
52
  answers: (stdin: string) => string,
53
+ /** The `psql` stderr a statement fails with (exit 3), or `undefined` to answer normally. */
54
+ failOn: (stdin: string) => string | undefined = () => undefined,
49
55
  ): { run: PsqlRunner; stdins: string[]; argvs: Array<readonly string[]> } => {
50
56
  const stdins: string[] = [];
51
57
  const argvs: Array<readonly string[]> = [];
52
58
  return {
53
- run: ({ stdin, argv }) => {
59
+ // The pin prefix (`search-path.ts`) is stripped: these tests assert the STATEMENT. The pin
60
+ // itself is asserted once, on the raw stdin, in `search-path.test.ts`.
61
+ run: ({ stdin: raw, argv }) => {
62
+ const stdin = stripPin(raw);
54
63
  stdins.push(stdin);
55
64
  argvs.push(argv);
56
- return Promise.resolve({ code: 0, stdout: answers(stdin), stderr: '' });
65
+ const stderr = failOn(stdin);
66
+ return Promise.resolve(
67
+ stderr === undefined
68
+ ? { code: 0, stdout: answers(stdin), stderr: '' }
69
+ : { code: 3, stdout: '', stderr },
70
+ );
57
71
  },
58
72
  stdins,
59
73
  argvs,
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The `search_path` pin (`search-path.ts`): every session this family opens starts with
3
+ * `SET search_path = pg_catalog, pg_temp`, on both transports, and the SQL builders only name
4
+ * catalogs as `pg_catalog.*`. The Opus read of PR 334 (2026-10-02) found that a role allowed to
5
+ * create objects in a schema on the path could forge `pg_namespace` and fake the delete proof.
6
+ */
7
+ import { readFileSync, readdirSync } from 'node:fs';
8
+ import { describe, expect, test } from 'bun:test';
9
+ import * as Effect from 'effect/Effect';
10
+ import { currentDatabase } from './schema-sql.ts';
11
+ import { makePsqlExecutor } from './psql-executor.ts';
12
+ import { PIN_SCRIPT_PREFIX, PIN_SEARCH_PATH_SQL } from './search-path.ts';
13
+
14
+ describe('runner transport', () => {
15
+ const target = { database: 'postgres', username: 'postgres' };
16
+ const record = () => {
17
+ const stdins: string[] = [];
18
+ const run = ({ stdin }: { stdin: string }) => {
19
+ stdins.push(stdin);
20
+ return Promise.resolve({ code: 0, stdout: '[]', stderr: '' });
21
+ };
22
+ return { stdins, run };
23
+ };
24
+
25
+ test('a read starts with the pin, in the same psql session as the statement', async () => {
26
+ const { stdins, run } = record();
27
+ await Effect.runPromise(currentDatabase(makePsqlExecutor(run, target)));
28
+ expect(stdins).toHaveLength(1);
29
+ expect(stdins[0]?.startsWith('SET search_path = pg_catalog, pg_temp;\n')).toBe(true);
30
+ expect(stdins[0]?.startsWith(PIN_SCRIPT_PREFIX)).toBe(true);
31
+ });
32
+
33
+ test('a write and a transaction start with the pin too', async () => {
34
+ const { stdins, run } = record();
35
+ const pg = makePsqlExecutor(run, target);
36
+ await Effect.runPromise(pg.unsafe('COMMENT ON SCHEMA "a" IS E\'b\''));
37
+ await Effect.runPromise(pg.transaction(['CREATE ROLE "r"']));
38
+ expect(stdins).toHaveLength(2);
39
+ for (const stdin of stdins) expect(stdin.startsWith(PIN_SCRIPT_PREFIX)).toBe(true);
40
+ // The pin comes BEFORE `BEGIN`: it is a session setting, not part of the transaction.
41
+ expect(stdins[1]).toBe(`${PIN_SCRIPT_PREFIX}BEGIN;\nCREATE ROLE "r";\nCOMMIT;`);
42
+ });
43
+
44
+ test('the pin is the one statement text both transports share', () => {
45
+ expect(PIN_SEARCH_PATH_SQL).toBe('SET search_path = pg_catalog, pg_temp');
46
+ });
47
+ });
48
+
49
+ /** Every hand-written SQL builder in this family. The `*errors.ts` files are excluded: they name
50
+ * catalogs in error-message PROSE, which no server ever parses. The fakes match on the qualified
51
+ * text the builders emit, so their own tests pin them. */
52
+ const sources = readdirSync(import.meta.dir).filter(
53
+ (f) =>
54
+ f.endsWith('.ts') &&
55
+ !f.endsWith('.test.ts') &&
56
+ !f.startsWith('fake-') &&
57
+ !/errors?\.ts$/.test(f),
58
+ );
59
+ const CATALOGS =
60
+ /(?<![\w.])(pg_(?:namespace|class|proc|type|operator|roles|authid|auth_members|database|tablespace|attribute|default_acl|depend|constraint|trigger|rewrite|attrdef|policy))\b/g;
61
+
62
+ describe('catalog references', () => {
63
+ test('no SQL builder names a catalog without the pg_catalog. qualifier', () => {
64
+ const offenders: string[] = [];
65
+ for (const file of sources) {
66
+ const text = readFileSync(`${import.meta.dir}/${file}`, 'utf8');
67
+ // Only template/quoted SQL is judged: skip comment lines and `'pg_namespace'` literals
68
+ // (an `obj_description` class argument is a string, not a relation reference).
69
+ for (const [index, line] of text.split('\n').entries()) {
70
+ const trimmed = line.trim();
71
+ if (/^(\/\/|\*|\/\*)/.test(trimmed)) continue;
72
+ for (const match of line.matchAll(CATALOGS)) {
73
+ const before = line[(match.index ?? 0) - 1];
74
+ if (before === "'" || before === '`') continue;
75
+ offenders.push(`${file}:${String(index + 1)} ${match[1] ?? ''}`);
76
+ }
77
+ }
78
+ }
79
+ expect(offenders).toEqual([]);
80
+ });
81
+
82
+ test('the scan sees the catalogs it is meant to police', () => {
83
+ const joined = sources.map((f) => readFileSync(`${import.meta.dir}/${f}`, 'utf8')).join('\n');
84
+ for (const needle of [
85
+ 'pg_catalog.pg_namespace',
86
+ 'pg_catalog.pg_class',
87
+ 'pg_catalog.pg_depend',
88
+ 'pg_catalog.pg_roles',
89
+ 'pg_catalog.pg_database',
90
+ ]) {
91
+ expect(joined).toContain(needle);
92
+ }
93
+ });
94
+
95
+ test('the scan itself fails on an unqualified reference', () => {
96
+ const bad = ' FROM pg_namespace n\n JOIN pg_catalog.pg_class c ON true';
97
+ const hits = [...bad.matchAll(CATALOGS)].map((m) => m[1]);
98
+ expect(hits).toEqual(['pg_namespace']);
99
+ });
100
+ });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The session setup every `Postgres.*` connection runs first: `search_path = pg_catalog, pg_temp`.
3
+ *
4
+ * ⛔ AN UNPINNED SESSION READS ITS OWN CATALOGS THROUGH `search_path`. Postgres searches
5
+ * `pg_catalog` first only while the path does not NAME it (ddl.sgml 5.10.3); a role- or
6
+ * database-level `ALTER … SET search_path = public, pg_catalog` (or a path naming any schema
7
+ * another role may create in) puts a writable schema ahead of it, and a `public.pg_namespace`
8
+ * TABLE then answers the delete proof's `oid`/`owner` re-read. Found by the Opus read of PR 334
9
+ * (2026-10-02). The pin makes the order ours whatever the role, database or server says; the SQL
10
+ * builders ALSO write `pg_catalog.<name>` (`catalog-qualified.test.ts` greps for it), so no
11
+ * single layer is the whole defence.
12
+ * ★ `pg_temp` goes LAST on purpose: unnamed, it is searched FIRST for relations.
13
+ * ★ TWO TRANSPORTS, TWO MECHANISMS. The runner path prefixes the stdin script: `psql` argv is
14
+ * the consumer's to join into a remote command, and a value with a space would split. The
15
+ * socket path pins the ONE connection an operation reserves, because the driver's startup
16
+ * message carries user, database and application_name only (`PgConnection.ts`, 4.0.0-rc.115)
17
+ * and a pool hands each statement a different, unpinned connection.
18
+ */
19
+ import type { PgClient } from '@effect/sql-pg/PgClient';
20
+ import * as Effect from 'effect/Effect';
21
+ import type * as Scope from 'effect/Scope';
22
+ import type { SqlError } from 'effect/sql/SqlError';
23
+ import type { PgExecutor } from './database-sql.ts';
24
+
25
+ export const PIN_SEARCH_PATH_SQL = 'SET search_path = pg_catalog, pg_temp';
26
+
27
+ /** The runner path's script prefix. */
28
+ export const PIN_SCRIPT_PREFIX = `${PIN_SEARCH_PATH_SQL};\n`;
29
+
30
+ /** A runner stdin without its pin — for tests that assert the statement that follows it. */
31
+ export const stripPin = (stdin: string): string =>
32
+ stdin.startsWith(PIN_SCRIPT_PREFIX) ? stdin.slice(PIN_SCRIPT_PREFIX.length) : stdin;
33
+
34
+ /**
35
+ * A `PgExecutor` over ONE reserved, pinned connection, for the life of the surrounding scope.
36
+ * `unsafe` runs on it (the client routes any statement under `transactionService` to that
37
+ * connection, so spans and error classification stay the driver's); `transaction` is a plain
38
+ * `BEGIN` … `COMMIT` on it — `withTransaction` would open a SAVEPOINT, because the service is
39
+ * already provided. A failure rolls back, and the pin is re-asserted by the next operation's own
40
+ * reservation, never assumed to survive one.
41
+ */
42
+ export const pinnedSocketExecutor = (
43
+ pg: PgClient,
44
+ ): Effect.Effect<PgExecutor, SqlError, Scope.Scope> =>
45
+ Effect.gen(function* () {
46
+ const connection = yield* pg.reserve;
47
+ const run = <A extends object>(sql: string, params?: ReadonlyArray<unknown>) =>
48
+ Effect.provideService(pg.unsafe<A>(sql, params), pg.transactionService, [connection, 0]);
49
+ yield* run(PIN_SEARCH_PATH_SQL);
50
+ return {
51
+ unsafe: run,
52
+ transaction: (statements) =>
53
+ Effect.gen(function* () {
54
+ yield* run('BEGIN');
55
+ for (const sql of statements) yield* run(sql);
56
+ yield* run('COMMIT');
57
+ }).pipe(
58
+ Effect.onError(() => run('ROLLBACK').pipe(Effect.ignore)),
59
+ Effect.asVoid,
60
+ ),
61
+ };
62
+ });