@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.
- package/README.md +10 -10
- package/dist/argocd/cluster.d.ts +5 -5
- package/dist/argocd/cluster.d.ts.map +1 -1
- package/dist/argocd/fake-argocd.d.ts +1 -1
- package/dist/argocd/fake-argocd.d.ts.map +1 -1
- package/dist/argocd/index.js.map +1 -1
- package/dist/argocd/providers.d.ts +1 -1
- package/dist/argocd/providers.d.ts.map +1 -1
- package/dist/argocd/repo-creds.d.ts +5 -5
- package/dist/argocd/repo-creds.d.ts.map +1 -1
- package/dist/argocd/repository.d.ts +5 -5
- package/dist/argocd/repository.d.ts.map +1 -1
- package/dist/argocd/resource.d.ts +1 -1
- package/dist/argocd/resource.d.ts.map +1 -1
- package/dist/caddy/admin.d.ts +1 -1
- package/dist/caddy/admin.d.ts.map +1 -1
- package/dist/caddy/caddy-http-client.d.ts +2 -2
- package/dist/caddy/caddy-http-client.d.ts.map +1 -1
- package/dist/caddy/format.d.ts +1 -1
- package/dist/caddy/format.d.ts.map +1 -1
- package/dist/caddy/index.js +6 -6
- package/dist/caddy/index.js.map +4 -4
- package/dist/ceph/auth-entity.d.ts +1 -1
- package/dist/ceph/auth-entity.d.ts.map +1 -1
- package/dist/ceph/ceph-auth-reconcile.d.ts +1 -1
- package/dist/ceph/ceph-auth-reconcile.d.ts.map +1 -1
- package/dist/ceph/index.js +5 -5
- package/dist/ceph/index.js.map +4 -4
- package/dist/cloudflare/fake-mesh.d.ts +2 -2
- package/dist/cloudflare/fake-mesh.d.ts.map +1 -1
- package/dist/cloudflare/fake-r2-lock.d.ts +1 -1
- package/dist/cloudflare/fake-r2-lock.d.ts.map +1 -1
- package/dist/cloudflare/index.js +3 -3
- package/dist/cloudflare/index.js.map +3 -3
- package/dist/cloudflare/mesh-node-token.d.ts +1 -1
- package/dist/cloudflare/mesh-node-token.d.ts.map +1 -1
- package/dist/cloudflare/mesh-node.d.ts +1 -1
- package/dist/cloudflare/mesh-node.d.ts.map +1 -1
- package/dist/cloudflare/providers.d.ts +1 -1
- package/dist/cloudflare/providers.d.ts.map +1 -1
- package/dist/cloudflare/r2-bucket-lock.d.ts +1 -1
- package/dist/cloudflare/r2-bucket-lock.d.ts.map +1 -1
- package/dist/discord/application-command.d.ts +6 -6
- package/dist/discord/application-command.d.ts.map +1 -1
- package/dist/discord/fake-discord.d.ts +1 -1
- package/dist/discord/fake-discord.d.ts.map +1 -1
- package/dist/discord/guild-application-command.d.ts +6 -6
- package/dist/discord/guild-application-command.d.ts.map +1 -1
- package/dist/discord/index.js.map +1 -1
- package/dist/discord/providers.d.ts +1 -1
- package/dist/discord/providers.d.ts.map +1 -1
- package/dist/discord/resource.d.ts +1 -1
- package/dist/discord/resource.d.ts.map +1 -1
- package/dist/forgejo/branch-protection.d.ts +5 -5
- package/dist/forgejo/branch-protection.d.ts.map +1 -1
- package/dist/forgejo/fake-forgejo.d.ts +1 -1
- package/dist/forgejo/fake-forgejo.d.ts.map +1 -1
- package/dist/forgejo/index.js.map +1 -1
- package/dist/forgejo/org-actions-secrets.d.ts +5 -5
- package/dist/forgejo/org-actions-secrets.d.ts.map +1 -1
- package/dist/forgejo/org-label.d.ts +5 -5
- package/dist/forgejo/org-label.d.ts.map +1 -1
- package/dist/forgejo/org-team.d.ts +5 -5
- package/dist/forgejo/org-team.d.ts.map +1 -1
- package/dist/forgejo/repo-webhook.d.ts +5 -5
- package/dist/forgejo/repo-webhook.d.ts.map +1 -1
- package/dist/forgejo/repository.d.ts +5 -5
- package/dist/forgejo/repository.d.ts.map +1 -1
- package/dist/forgejo/resource.d.ts +1 -1
- package/dist/forgejo/resource.d.ts.map +1 -1
- package/dist/forgejo/team-member.d.ts +5 -5
- package/dist/forgejo/team-member.d.ts.map +1 -1
- package/dist/github/repository-ruleset-providers.d.ts +1 -1
- package/dist/github/repository-ruleset-providers.d.ts.map +1 -1
- package/dist/google-workspace/domain-alias.d.ts +5 -5
- package/dist/google-workspace/domain-alias.d.ts.map +1 -1
- package/dist/google-workspace/fake-google-workspace.d.ts +1 -1
- package/dist/google-workspace/fake-google-workspace.d.ts.map +1 -1
- package/dist/google-workspace/group-member.d.ts +5 -5
- package/dist/google-workspace/group-member.d.ts.map +1 -1
- package/dist/google-workspace/group.d.ts +5 -5
- package/dist/google-workspace/group.d.ts.map +1 -1
- package/dist/google-workspace/index.js.map +1 -1
- package/dist/google-workspace/org-unit.d.ts +5 -5
- package/dist/google-workspace/org-unit.d.ts.map +1 -1
- package/dist/google-workspace/providers.d.ts +1 -1
- package/dist/google-workspace/providers.d.ts.map +1 -1
- package/dist/google-workspace/resource.d.ts +1 -1
- package/dist/google-workspace/resource.d.ts.map +1 -1
- package/dist/grafana/alert-rule-group.d.ts +4 -4
- package/dist/grafana/alert-rule-group.d.ts.map +1 -1
- package/dist/grafana/contact-point.d.ts +4 -4
- package/dist/grafana/dashboard.d.ts +4 -4
- package/dist/grafana/datasource.d.ts +4 -4
- package/dist/grafana/fake-grafana.d.ts +1 -1
- package/dist/grafana/fake-grafana.d.ts.map +1 -1
- package/dist/grafana/folder.d.ts +4 -4
- package/dist/grafana/message-template.d.ts +4 -4
- package/dist/grafana/mute-timing.d.ts +4 -4
- package/dist/grafana/notification-policy.d.ts +4 -4
- package/dist/grafana/notification-policy.d.ts.map +1 -1
- package/dist/grafana/providers.d.ts +1 -1
- package/dist/grafana/providers.d.ts.map +1 -1
- package/dist/litellm/access-group.d.ts +1 -1
- package/dist/litellm/budget-operations.d.ts +1 -1
- package/dist/litellm/budget-operations.d.ts.map +1 -1
- package/dist/litellm/budget.d.ts +2 -2
- package/dist/litellm/credential-errors.d.ts +1 -1
- package/dist/litellm/credential-errors.d.ts.map +1 -1
- package/dist/litellm/credential.d.ts +1 -1
- package/dist/litellm/index.js +26 -5
- package/dist/litellm/index.js.map +8 -8
- package/dist/litellm/key-errors.d.ts +1 -1
- package/dist/litellm/key-errors.d.ts.map +1 -1
- package/dist/litellm/key.d.ts +2 -2
- package/dist/litellm/mcp-server-locate.d.ts +1 -1
- package/dist/litellm/mcp-server-locate.d.ts.map +1 -1
- package/dist/litellm/mcp-server.d.ts +2 -2
- package/dist/litellm/model-operations.d.ts +1 -1
- package/dist/litellm/model-operations.d.ts.map +1 -1
- package/dist/litellm/model.d.ts +2 -2
- package/dist/litellm/operations.d.ts +1 -1
- package/dist/litellm/operations.d.ts.map +1 -1
- package/dist/litellm/policy-attachment.d.ts +1 -1
- package/dist/litellm/policy.d.ts +1 -1
- package/dist/litellm/providers.d.ts +1 -1
- package/dist/litellm/providers.d.ts.map +1 -1
- package/dist/litellm/team-operations.d.ts +1 -1
- package/dist/litellm/team-operations.d.ts.map +1 -1
- package/dist/litellm/team.d.ts +1 -1
- package/dist/litellm/tool-policy-operations.d.ts +1 -1
- package/dist/litellm/tool-policy-operations.d.ts.map +1 -1
- package/dist/litellm/tool-policy.d.ts +1 -1
- package/dist/litellm/toolset.d.ts +1 -1
- package/dist/netbox/fake-netbox.d.ts +1 -1
- package/dist/netbox/fake-netbox.d.ts.map +1 -1
- package/dist/netbox/index.js.map +1 -1
- package/dist/netbox/prefix.d.ts +5 -5
- package/dist/netbox/prefix.d.ts.map +1 -1
- package/dist/netbox/resource.d.ts +1 -1
- package/dist/netbox/resource.d.ts.map +1 -1
- package/dist/openbao/approle-login.d.ts +1 -1
- package/dist/openbao/approle-login.d.ts.map +1 -1
- package/dist/openbao/auth-method-reconcile.d.ts +1 -1
- package/dist/openbao/auth-method-reconcile.d.ts.map +1 -1
- package/dist/openbao/auth-method-wire.d.ts +4 -4
- package/dist/openbao/auth-method-wire.d.ts.map +1 -1
- package/dist/openbao/auth-method.d.ts +1 -1
- package/dist/openbao/auth-method.d.ts.map +1 -1
- package/dist/openbao/auth-role-identity.d.ts +1 -1
- package/dist/openbao/auth-role-identity.d.ts.map +1 -1
- package/dist/openbao/auth-role-wire.d.ts +4 -4
- package/dist/openbao/auth-role-wire.d.ts.map +1 -1
- package/dist/openbao/auth-role.d.ts +1 -1
- package/dist/openbao/auth-role.d.ts.map +1 -1
- package/dist/openbao/bao-http.d.ts +1 -1
- package/dist/openbao/bao-http.d.ts.map +1 -1
- package/dist/openbao/bao-identity.d.ts +1 -1
- package/dist/openbao/bao-identity.d.ts.map +1 -1
- package/dist/openbao/cloudflare-permission-groups.d.ts +1 -1
- package/dist/openbao/cloudflare-permission-groups.d.ts.map +1 -1
- package/dist/openbao/cloudflare-role-wire.d.ts +1 -1
- package/dist/openbao/cloudflare-role-wire.d.ts.map +1 -1
- package/dist/openbao/cloudflare-role.d.ts +1 -1
- package/dist/openbao/cloudflare-role.d.ts.map +1 -1
- package/dist/openbao/distilled.d.ts +1 -1
- package/dist/openbao/distilled.d.ts.map +1 -1
- package/dist/openbao/fake-bao.d.ts +1 -1
- package/dist/openbao/fake-bao.d.ts.map +1 -1
- package/dist/openbao/fake-core.d.ts +1 -1
- package/dist/openbao/fake-core.d.ts.map +1 -1
- package/dist/openbao/fake-engines.d.ts +1 -1
- package/dist/openbao/fake-engines.d.ts.map +1 -1
- package/dist/openbao/fake-families.d.ts +2 -2
- package/dist/openbao/fake-families.d.ts.map +1 -1
- package/dist/openbao/fake-stack.d.ts +5 -0
- package/dist/openbao/fake-stack.d.ts.map +1 -1
- package/dist/openbao/forgejo-bootstrap.d.ts +1 -1
- package/dist/openbao/forgejo-bootstrap.d.ts.map +1 -1
- package/dist/openbao/index.js +31 -10
- package/dist/openbao/index.js.map +31 -31
- package/dist/openbao/jwt-config.d.ts +1 -1
- package/dist/openbao/jwt-config.d.ts.map +1 -1
- package/dist/openbao/jwt-role.d.ts +1 -1
- package/dist/openbao/jwt-role.d.ts.map +1 -1
- package/dist/openbao/kubernetes-role.d.ts +1 -1
- package/dist/openbao/kubernetes-role.d.ts.map +1 -1
- package/dist/openbao/mfa-enforcement.d.ts +1 -1
- package/dist/openbao/mfa-enforcement.d.ts.map +1 -1
- package/dist/openbao/mfa-totp.d.ts +1 -1
- package/dist/openbao/mfa-totp.d.ts.map +1 -1
- package/dist/openbao/mfa-wire.d.ts +1 -1
- package/dist/openbao/mfa-wire.d.ts.map +1 -1
- package/dist/openbao/mount-move.d.ts +1 -1
- package/dist/openbao/mount-move.d.ts.map +1 -1
- package/dist/openbao/mount-reconcile.d.ts +1 -1
- package/dist/openbao/mount-reconcile.d.ts.map +1 -1
- package/dist/openbao/mount-wire.d.ts +4 -4
- package/dist/openbao/mount-wire.d.ts.map +1 -1
- package/dist/openbao/mount.d.ts +1 -1
- package/dist/openbao/mount.d.ts.map +1 -1
- package/dist/openbao/pki-role.d.ts +1 -1
- package/dist/openbao/pki-role.d.ts.map +1 -1
- package/dist/openbao/plugin-reconcile.d.ts +1 -1
- package/dist/openbao/plugin-reconcile.d.ts.map +1 -1
- package/dist/openbao/plugin-wire.d.ts +1 -1
- package/dist/openbao/plugin-wire.d.ts.map +1 -1
- package/dist/openbao/plugin.d.ts +1 -1
- package/dist/openbao/plugin.d.ts.map +1 -1
- package/dist/openbao/policy-identity.d.ts +1 -1
- package/dist/openbao/policy-identity.d.ts.map +1 -1
- package/dist/openbao/policy-wire.d.ts +4 -4
- package/dist/openbao/policy-wire.d.ts.map +1 -1
- package/dist/openbao/policy.d.ts +1 -1
- package/dist/openbao/policy.d.ts.map +1 -1
- package/dist/openbao/proxmox-role-wire.d.ts +1 -1
- package/dist/openbao/proxmox-role-wire.d.ts.map +1 -1
- package/dist/openbao/proxmox-role.d.ts +1 -1
- package/dist/openbao/proxmox-role.d.ts.map +1 -1
- package/dist/openbao/remount-wire.d.ts +1 -1
- package/dist/openbao/remount-wire.d.ts.map +1 -1
- package/dist/openbao/rename-identity.d.ts +1 -1
- package/dist/openbao/rename-identity.d.ts.map +1 -1
- package/dist/openbao/rename.d.ts +1 -1
- package/dist/openbao/rename.d.ts.map +1 -1
- package/dist/openbao/role-reconcile.d.ts +1 -1
- package/dist/openbao/role-reconcile.d.ts.map +1 -1
- package/dist/openbao/ssh-role.d.ts +1 -1
- package/dist/openbao/ssh-role.d.ts.map +1 -1
- package/dist/opnsense/alias.d.ts +5 -5
- package/dist/opnsense/alias.d.ts.map +1 -1
- package/dist/opnsense/category.d.ts +5 -5
- package/dist/opnsense/category.d.ts.map +1 -1
- package/dist/opnsense/fake-opnsense.d.ts +1 -1
- package/dist/opnsense/fake-opnsense.d.ts.map +1 -1
- package/dist/opnsense/group.d.ts +5 -5
- package/dist/opnsense/group.d.ts.map +1 -1
- package/dist/opnsense/index.js.map +1 -1
- package/dist/opnsense/providers.d.ts +1 -1
- package/dist/opnsense/providers.d.ts.map +1 -1
- package/dist/opnsense/resource.d.ts +1 -1
- package/dist/opnsense/resource.d.ts.map +1 -1
- package/dist/ownership/probe.d.ts.map +1 -1
- package/dist/paperless/custom-field.d.ts +5 -5
- package/dist/paperless/custom-field.d.ts.map +1 -1
- package/dist/paperless/document-type.d.ts +5 -5
- package/dist/paperless/document-type.d.ts.map +1 -1
- package/dist/paperless/fake-paperless.d.ts +1 -1
- package/dist/paperless/fake-paperless.d.ts.map +1 -1
- package/dist/paperless/matching-types.d.ts +1 -1
- package/dist/paperless/matching-types.d.ts.map +1 -1
- package/dist/paperless/matching.d.ts +4 -4
- package/dist/paperless/providers.d.ts +1 -1
- package/dist/paperless/providers.d.ts.map +1 -1
- package/dist/paperless/storage-path.d.ts +5 -5
- package/dist/paperless/storage-path.d.ts.map +1 -1
- package/dist/paperless/tag.d.ts +5 -5
- package/dist/paperless/tag.d.ts.map +1 -1
- package/dist/postgres/connection.d.ts +2 -2
- package/dist/postgres/connection.d.ts.map +1 -1
- package/dist/postgres/database-sql.d.ts +1 -1
- package/dist/postgres/database-sql.d.ts.map +1 -1
- package/dist/postgres/database.d.ts +1 -1
- package/dist/postgres/database.d.ts.map +1 -1
- package/dist/postgres/fake-grants-read.d.ts +1 -1
- package/dist/postgres/fake-grants-read.d.ts.map +1 -1
- package/dist/postgres/fake-grants-write.d.ts +1 -1
- package/dist/postgres/fake-grants-write.d.ts.map +1 -1
- package/dist/postgres/fake-role-sql.d.ts +1 -1
- package/dist/postgres/fake-role-sql.d.ts.map +1 -1
- package/dist/postgres/fake-schema-drop.d.ts +13 -0
- package/dist/postgres/fake-schema-drop.d.ts.map +1 -0
- package/dist/postgres/fake-schema-sql.d.ts +6 -1
- package/dist/postgres/fake-schema-sql.d.ts.map +1 -1
- package/dist/postgres/fake-sql.d.ts +4 -0
- package/dist/postgres/fake-sql.d.ts.map +1 -1
- package/dist/postgres/grants-existence.d.ts +1 -1
- package/dist/postgres/grants-existence.d.ts.map +1 -1
- package/dist/postgres/grants-ops.d.ts +1 -1
- package/dist/postgres/grants-ops.d.ts.map +1 -1
- package/dist/postgres/grants-ownership.d.ts +1 -1
- package/dist/postgres/grants-ownership.d.ts.map +1 -1
- package/dist/postgres/grants-read-defaults.d.ts +1 -1
- package/dist/postgres/grants-read-defaults.d.ts.map +1 -1
- package/dist/postgres/grants-read.d.ts +1 -1
- package/dist/postgres/grants-read.d.ts.map +1 -1
- package/dist/postgres/index.d.ts +2 -1
- package/dist/postgres/index.d.ts.map +1 -1
- package/dist/postgres/index.js +523 -324
- package/dist/postgres/index.js.map +26 -22
- package/dist/postgres/installed-classifier.d.ts +1 -1
- package/dist/postgres/installed-classifier.d.ts.map +1 -1
- package/dist/postgres/psql-executor.d.ts.map +1 -1
- package/dist/postgres/role-membership-sql.d.ts +1 -1
- package/dist/postgres/role-membership-sql.d.ts.map +1 -1
- package/dist/postgres/role-sql.d.ts +1 -1
- package/dist/postgres/role-sql.d.ts.map +1 -1
- package/dist/postgres/role.d.ts +1 -1
- package/dist/postgres/role.d.ts.map +1 -1
- package/dist/postgres/schema-assert.d.ts +1 -1
- package/dist/postgres/schema-assert.d.ts.map +1 -1
- package/dist/postgres/schema-closure-sql.d.ts +45 -0
- package/dist/postgres/schema-closure-sql.d.ts.map +1 -0
- package/dist/postgres/schema-delete.d.ts +18 -9
- package/dist/postgres/schema-delete.d.ts.map +1 -1
- package/dist/postgres/schema-drop-sql.d.ts +66 -0
- package/dist/postgres/schema-drop-sql.d.ts.map +1 -0
- package/dist/postgres/schema-errors.d.ts +19 -1
- package/dist/postgres/schema-errors.d.ts.map +1 -1
- package/dist/postgres/schema-reconcile.d.ts +1 -1
- package/dist/postgres/schema-reconcile.d.ts.map +1 -1
- package/dist/postgres/schema-sequence-error.d.ts +29 -0
- package/dist/postgres/schema-sequence-error.d.ts.map +1 -0
- package/dist/postgres/schema-sql.d.ts +17 -1
- package/dist/postgres/schema-sql.d.ts.map +1 -1
- package/dist/postgres/schema-test-kit.d.ts +3 -1
- package/dist/postgres/schema-test-kit.d.ts.map +1 -1
- package/dist/postgres/schema.d.ts +1 -1
- package/dist/postgres/schema.d.ts.map +1 -1
- package/dist/postgres/search-path.d.ts +38 -0
- package/dist/postgres/search-path.d.ts.map +1 -0
- package/dist/proxmox/acl.d.ts +1 -1
- package/dist/proxmox/acl.d.ts.map +1 -1
- package/dist/proxmox/api-token.d.ts +1 -1
- package/dist/proxmox/api-token.d.ts.map +1 -1
- package/dist/proxmox/backup-job-distilled.d.ts +2 -2
- package/dist/proxmox/backup-job-distilled.d.ts.map +1 -1
- package/dist/proxmox/backup-job.d.ts +1 -1
- package/dist/proxmox/backup-job.d.ts.map +1 -1
- package/dist/proxmox/ceph-daemon-wire.d.ts +3 -3
- package/dist/proxmox/ceph-daemon-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-daemon.d.ts +2 -2
- package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
- package/dist/proxmox/ceph-flag-wire.d.ts +3 -3
- package/dist/proxmox/ceph-flag-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-flag.d.ts +1 -1
- package/dist/proxmox/ceph-flag.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs-distilled.d.ts +3 -3
- package/dist/proxmox/ceph-fs-distilled.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs.d.ts +1 -1
- package/dist/proxmox/ceph-fs.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-tree.d.ts +1 -1
- package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-write.d.ts +2 -2
- package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd.d.ts +1 -1
- package/dist/proxmox/ceph-osd.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool-settle.d.ts +2 -2
- package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool-wire.d.ts +1 -1
- package/dist/proxmox/ceph-pool-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool.d.ts +1 -1
- package/dist/proxmox/ceph-pool.d.ts.map +1 -1
- package/dist/proxmox/client.d.ts +1 -1
- package/dist/proxmox/client.d.ts.map +1 -1
- package/dist/proxmox/distilled-pbs.d.ts +1 -1
- package/dist/proxmox/distilled-pbs.d.ts.map +1 -1
- package/dist/proxmox/distilled-pve.d.ts +1 -1
- package/dist/proxmox/distilled-pve.d.ts.map +1 -1
- package/dist/proxmox/fake-pbs-jobs.d.ts +1 -1
- package/dist/proxmox/fake-pve.d.ts +1 -1
- package/dist/proxmox/fake-pve.d.ts.map +1 -1
- package/dist/proxmox/firewall-alias-lifecycle.d.ts +6 -6
- package/dist/proxmox/firewall-alias-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/firewall-alias.d.ts +1 -1
- package/dist/proxmox/firewall-alias.d.ts.map +1 -1
- package/dist/proxmox/group-wire.d.ts +2 -2
- package/dist/proxmox/group-wire.d.ts.map +1 -1
- package/dist/proxmox/group.d.ts +1 -1
- package/dist/proxmox/group.d.ts.map +1 -1
- package/dist/proxmox/ha-resource.d.ts +1 -1
- package/dist/proxmox/ha-resource.d.ts.map +1 -1
- package/dist/proxmox/ha-rule.d.ts +1 -1
- package/dist/proxmox/ha-rule.d.ts.map +1 -1
- package/dist/proxmox/index.js +38 -17
- package/dist/proxmox/index.js.map +9 -9
- package/dist/proxmox/lease-cache.d.ts +2 -2
- package/dist/proxmox/lease-cache.d.ts.map +1 -1
- package/dist/proxmox/live-core-fixtures.d.ts +1 -1
- package/dist/proxmox/live-core-fixtures.d.ts.map +1 -1
- package/dist/proxmox/lxc-lifecycle.d.ts +3 -3
- package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/lxc-read.d.ts +1 -1
- package/dist/proxmox/lxc-read.d.ts.map +1 -1
- package/dist/proxmox/lxc-task.d.ts +1 -1
- package/dist/proxmox/lxc-task.d.ts.map +1 -1
- package/dist/proxmox/lxc.d.ts +1 -1
- package/dist/proxmox/lxc.d.ts.map +1 -1
- package/dist/proxmox/members.d.ts +3 -3
- package/dist/proxmox/members.d.ts.map +1 -1
- package/dist/proxmox/metric-server-distilled.d.ts +3 -3
- package/dist/proxmox/metric-server-distilled.d.ts.map +1 -1
- package/dist/proxmox/metric-server.d.ts +1 -1
- package/dist/proxmox/metric-server.d.ts.map +1 -1
- package/dist/proxmox/mint.d.ts +1 -1
- package/dist/proxmox/mint.d.ts.map +1 -1
- package/dist/proxmox/network-apply-read.d.ts +3 -3
- package/dist/proxmox/network-apply-read.d.ts.map +1 -1
- package/dist/proxmox/network-apply-run.d.ts +1 -1
- package/dist/proxmox/network-apply-run.d.ts.map +1 -1
- package/dist/proxmox/network-apply.d.ts +1 -1
- package/dist/proxmox/network-apply.d.ts.map +1 -1
- package/dist/proxmox/node-network-wire.d.ts +2 -2
- package/dist/proxmox/node-network-wire.d.ts.map +1 -1
- package/dist/proxmox/node-network.d.ts +1 -1
- package/dist/proxmox/node-network.d.ts.map +1 -1
- package/dist/proxmox/notification-matcher-distilled.d.ts +4 -4
- package/dist/proxmox/notification-matcher-distilled.d.ts.map +1 -1
- package/dist/proxmox/notification-matcher-lifecycle.d.ts +4 -4
- package/dist/proxmox/notification-matcher.d.ts +1 -1
- package/dist/proxmox/notification-matcher.d.ts.map +1 -1
- package/dist/proxmox/notification-target-distilled.d.ts +4 -4
- package/dist/proxmox/notification-target-distilled.d.ts.map +1 -1
- package/dist/proxmox/notification-target-lifecycle.d.ts +4 -4
- package/dist/proxmox/notification-target.d.ts +1 -1
- package/dist/proxmox/notification-target.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-datastore-wire.d.ts +4 -4
- package/dist/proxmox/pbs-datastore-wire.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore.d.ts +1 -1
- package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-matcher-distilled.d.ts +4 -4
- package/dist/proxmox/pbs-notification-matcher-distilled.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-matcher.d.ts +1 -1
- package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-target-distilled.d.ts +4 -4
- package/dist/proxmox/pbs-notification-target-distilled.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-notification-target.d.ts +1 -1
- package/dist/proxmox/pbs-notification-target.d.ts.map +1 -1
- package/dist/proxmox/pbs-prune-job-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-prune-job-wire.d.ts +4 -4
- package/dist/proxmox/pbs-prune-job-wire.d.ts.map +1 -1
- package/dist/proxmox/pbs-prune-job.d.ts +1 -1
- package/dist/proxmox/pbs-prune-job.d.ts.map +1 -1
- package/dist/proxmox/pbs-sync-job-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-sync-job-wire.d.ts +4 -4
- package/dist/proxmox/pbs-sync-job-wire.d.ts.map +1 -1
- package/dist/proxmox/pbs-sync-job.d.ts +1 -1
- package/dist/proxmox/pbs-sync-job.d.ts.map +1 -1
- package/dist/proxmox/pbs-verify-job-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-verify-job-wire.d.ts +4 -4
- package/dist/proxmox/pbs-verify-job-wire.d.ts.map +1 -1
- package/dist/proxmox/pbs-verify-job.d.ts +1 -1
- package/dist/proxmox/pbs-verify-job.d.ts.map +1 -1
- package/dist/proxmox/pool.d.ts +3 -3
- package/dist/proxmox/pool.d.ts.map +1 -1
- package/dist/proxmox/provision-declare.d.ts +1 -1
- package/dist/proxmox/provision-declare.d.ts.map +1 -1
- package/dist/proxmox/qemu-lifecycle.d.ts +3 -3
- package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/qemu-read.d.ts +1 -1
- package/dist/proxmox/qemu-read.d.ts.map +1 -1
- package/dist/proxmox/qemu-resize.d.ts +1 -1
- package/dist/proxmox/qemu-resize.d.ts.map +1 -1
- package/dist/proxmox/qemu-task.d.ts +1 -1
- package/dist/proxmox/qemu-task.d.ts.map +1 -1
- package/dist/proxmox/qemu.d.ts +1 -1
- package/dist/proxmox/qemu.d.ts.map +1 -1
- package/dist/proxmox/replication-job-lifecycle.d.ts +6 -6
- package/dist/proxmox/replication-job-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/replication-job.d.ts +1 -1
- package/dist/proxmox/replication-job.d.ts.map +1 -1
- package/dist/proxmox/resource-spec.d.ts +1 -1
- package/dist/proxmox/resource-spec.d.ts.map +1 -1
- package/dist/proxmox/resource.d.ts +8 -8
- package/dist/proxmox/role.d.ts +1 -1
- package/dist/proxmox/role.d.ts.map +1 -1
- package/dist/proxmox/sdn-apply-read.d.ts +1 -1
- package/dist/proxmox/sdn-apply-read.d.ts.map +1 -1
- package/dist/proxmox/sdn-apply.d.ts +1 -1
- package/dist/proxmox/sdn-apply.d.ts.map +1 -1
- package/dist/proxmox/sdn-subnet.d.ts +1 -1
- package/dist/proxmox/sdn-subnet.d.ts.map +1 -1
- package/dist/proxmox/sdn-vnet.d.ts +1 -1
- package/dist/proxmox/sdn-vnet.d.ts.map +1 -1
- package/dist/proxmox/sdn-zone.d.ts +1 -1
- package/dist/proxmox/sdn-zone.d.ts.map +1 -1
- package/dist/proxmox/storage-download-lifecycle.d.ts +6 -6
- package/dist/proxmox/storage-download-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/storage-download-task.d.ts +1 -1
- package/dist/proxmox/storage-download-task.d.ts.map +1 -1
- package/dist/proxmox/storage-download.d.ts +1 -1
- package/dist/proxmox/storage-download.d.ts.map +1 -1
- package/dist/proxmox/storage-wire.d.ts +2 -2
- package/dist/proxmox/storage-wire.d.ts.map +1 -1
- package/dist/proxmox/storage.d.ts +1 -1
- package/dist/proxmox/storage.d.ts.map +1 -1
- package/dist/proxmox/user-wire.d.ts +2 -2
- package/dist/proxmox/user-wire.d.ts.map +1 -1
- package/dist/proxmox/user.d.ts +1 -1
- package/dist/proxmox/user.d.ts.map +1 -1
- package/dist/proxmox/zfs-pool-form.d.ts +2 -2
- package/dist/proxmox/zfs-pool-form.d.ts.map +1 -1
- package/dist/proxmox/zfs-pool-wire.d.ts +2 -2
- package/dist/proxmox/zfs-pool-wire.d.ts.map +1 -1
- package/dist/proxmox/zfs-pool.d.ts +1 -1
- package/dist/proxmox/zfs-pool.d.ts.map +1 -1
- package/dist/release/binary.d.ts +1 -1
- package/dist/release/binary.d.ts.map +1 -1
- package/dist/release/download.d.ts +1 -1
- package/dist/release/download.d.ts.map +1 -1
- package/dist/release/index.js +6 -5
- package/dist/release/index.js.map +5 -5
- package/dist/talos/credentials-write.d.ts +1 -1
- package/dist/talos/credentials-write.d.ts.map +1 -1
- package/dist/talos/credentials.d.ts +1 -1
- package/dist/talos/credentials.d.ts.map +1 -1
- package/dist/talos/fake-process.d.ts +2 -2
- package/dist/talos/fake-process.d.ts.map +1 -1
- package/dist/talos/index.js +7 -7
- package/dist/talos/index.js.map +4 -4
- package/dist/talos/kubeconfig.d.ts +4 -4
- package/dist/talos/kubeconfig.d.ts.map +1 -1
- package/dist/talos/machine-config-fixtures.d.ts +1 -1
- package/dist/talos/machine-config-fixtures.d.ts.map +1 -1
- package/dist/talos/machine-config-read.d.ts +3 -3
- package/dist/talos/machine-config-read.d.ts.map +1 -1
- package/dist/talos/resource.d.ts +1 -1
- package/dist/talos/resource.d.ts.map +1 -1
- package/dist/talos/talos-bootstrap-etcd.d.ts +2 -2
- package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -1
- package/dist/talos/talos-bootstrap.d.ts +4 -4
- package/dist/talos/talos-bootstrap.d.ts.map +1 -1
- package/dist/talos/talos-cluster-health.d.ts +4 -4
- package/dist/talos/talos-cluster-health.d.ts.map +1 -1
- package/dist/talos/talos-machine-config.d.ts +2 -2
- package/dist/talos/talos-machine-config.d.ts.map +1 -1
- package/dist/talos/talosctl.d.ts +1 -1
- package/dist/talos/talosctl.d.ts.map +1 -1
- package/dist/telemetry/index.js +4 -4
- package/dist/telemetry/index.js.map +3 -3
- package/dist/telemetry/redact-serialization.d.ts +2 -2
- package/dist/telemetry/redact-serialization.d.ts.map +1 -1
- package/dist/unifi/acl-rule-ordering.d.ts +6 -6
- package/dist/unifi/acl-rule-ordering.d.ts.map +1 -1
- package/dist/unifi/acl-rule.d.ts +6 -6
- package/dist/unifi/acl-rule.d.ts.map +1 -1
- package/dist/unifi/dns-policy.d.ts +6 -6
- package/dist/unifi/dns-policy.d.ts.map +1 -1
- package/dist/unifi/fake-unifi.d.ts +1 -1
- package/dist/unifi/fake-unifi.d.ts.map +1 -1
- package/dist/unifi/firewall-policy-ordering.d.ts +6 -6
- package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -1
- package/dist/unifi/firewall-policy.d.ts +6 -6
- package/dist/unifi/firewall-policy.d.ts.map +1 -1
- package/dist/unifi/firewall-zone.d.ts +6 -6
- package/dist/unifi/firewall-zone.d.ts.map +1 -1
- package/dist/unifi/index.js +2 -2
- package/dist/unifi/index.js.map +2 -2
- package/dist/unifi/network.d.ts +6 -6
- package/dist/unifi/network.d.ts.map +1 -1
- package/dist/unifi/providers.d.ts +1 -1
- package/dist/unifi/providers.d.ts.map +1 -1
- package/dist/unifi/resource.d.ts +1 -1
- package/dist/unifi/resource.d.ts.map +1 -1
- package/dist/unifi/traffic-matching-list.d.ts +6 -6
- package/dist/unifi/traffic-matching-list.d.ts.map +1 -1
- package/dist/unifi/wifi-broadcast.d.ts +6 -6
- package/dist/unifi/wifi-broadcast.d.ts.map +1 -1
- package/dist/verify/cli.js.map +1 -1
- package/dist/verify/index.js.map +1 -1
- package/docs/distilled-interim.md +1 -1
- package/docs/mesh-node.md +1 -1
- package/docs/paperless.md +1 -1
- package/docs/peers.md +8 -8
- package/docs/postgres-schema.md +22 -1
- package/docs/telemetry.md +1 -1
- package/package.json +20 -20
- package/src/argocd/fake-argocd.ts +1 -1
- package/src/argocd/resource.ts +1 -1
- package/src/caddy/admin-transport-scope.test.ts +2 -2
- package/src/caddy/admin.ts +1 -1
- package/src/caddy/caddy-http-client.ts +5 -5
- package/src/caddy/config-adopt.test.ts +2 -2
- package/src/caddy/format.ts +2 -2
- package/src/caddy/local-admin.test.ts +1 -1
- package/src/ceph/auth-entity.ts +1 -1
- package/src/ceph/ceph-auth-reconcile.ts +1 -1
- package/src/cloudflare/fake-mesh.ts +1 -1
- package/src/cloudflare/fake-r2-lock.ts +1 -1
- package/src/cloudflare/mesh-node-harness.ts +1 -1
- package/src/cloudflare/mesh-node.ts +1 -1
- package/src/cloudflare/r2-bucket-lock.ts +1 -1
- package/src/discord/fake-discord.ts +1 -1
- package/src/discord/resource.ts +1 -1
- package/src/forgejo/fake-forgejo.ts +1 -1
- package/src/forgejo/resource.ts +1 -1
- package/src/google-workspace/fake-google-workspace.ts +1 -1
- package/src/google-workspace/resource.ts +1 -1
- package/src/grafana/fake-grafana.ts +1 -1
- package/src/litellm/access-group.test.ts +1 -1
- package/src/litellm/credential-errors.ts +1 -1
- package/src/litellm/credential-guards.test.ts +1 -1
- package/src/litellm/credential-operations.ts +1 -1
- package/src/litellm/credential-rewrite.test.ts +1 -1
- package/src/litellm/fake-stack.ts +1 -1
- package/src/litellm/key-errors.ts +1 -1
- package/src/litellm/key-harness.ts +1 -1
- package/src/litellm/key-operations.ts +1 -1
- package/src/litellm/key.test.ts +2 -1
- package/src/litellm/mcp-server-handlers.test.ts +1 -1
- package/src/litellm/mcp-server-registry.test.ts +1 -1
- package/src/litellm/model-operations.test.ts +1 -1
- package/src/litellm/operations.ts +1 -1
- package/src/litellm/pass-through-endpoint-delete-swallow.test.ts +1 -1
- package/src/litellm/pass-through-endpoint.test.ts +1 -1
- package/src/litellm/pass-through-fetch-client.test.ts +2 -2
- package/src/litellm/policy-attachment.test.ts +1 -1
- package/src/litellm/policy.test.ts +1 -1
- package/src/litellm/team-members.test.ts +1 -1
- package/src/litellm/team-read.test.ts +1 -1
- package/src/litellm/tool-policy.test.ts +1 -1
- package/src/litellm/toolset.test.ts +1 -1
- package/src/netbox/fake-netbox.ts +1 -1
- package/src/netbox/resource.ts +1 -1
- package/src/openbao/adopt-core.test.ts +4 -1
- package/src/openbao/adopt-families.test.ts +4 -1
- package/src/openbao/adopt-holes.test.ts +1 -1
- package/src/openbao/adopt-recovery.test.ts +24 -0
- package/src/openbao/approle-login.ts +2 -2
- package/src/openbao/auth-method-reconcile.ts +1 -1
- package/src/openbao/auth-method.ts +1 -1
- package/src/openbao/auth-role-sdk.test.ts +1 -1
- package/src/openbao/auth-role.ts +1 -1
- package/src/openbao/bao-http.test.ts +3 -3
- package/src/openbao/bao-http.ts +4 -4
- package/src/openbao/bao-identity.ts +2 -2
- package/src/openbao/cloudflare-permission-groups.ts +1 -1
- package/src/openbao/cloudflare-role-wire.ts +1 -1
- package/src/openbao/cloudflare-role.ts +1 -1
- package/src/openbao/distilled-retry.test.ts +3 -3
- package/src/openbao/distilled.test.ts +3 -3
- package/src/openbao/distilled.ts +2 -2
- package/src/openbao/fake-bao.ts +2 -2
- package/src/openbao/fake-core.ts +1 -1
- package/src/openbao/fake-engines.ts +1 -1
- package/src/openbao/fake-families.ts +1 -1
- package/src/openbao/fake-stack.ts +13 -3
- package/src/openbao/jwt-config.ts +1 -1
- package/src/openbao/jwt-role.ts +1 -1
- package/src/openbao/kubernetes-role.ts +1 -1
- package/src/openbao/mfa-enforcement.ts +1 -1
- package/src/openbao/mfa-totp.ts +1 -1
- package/src/openbao/mfa-wire.ts +1 -1
- package/src/openbao/mount-move.ts +1 -1
- package/src/openbao/mount-reconcile.ts +1 -1
- package/src/openbao/mount.ts +1 -1
- package/src/openbao/pki-role.ts +1 -1
- package/src/openbao/plugin-reconcile.ts +1 -1
- package/src/openbao/plugin-wire.ts +1 -1
- package/src/openbao/plugin.ts +1 -1
- package/src/openbao/policy.ts +1 -1
- package/src/openbao/proxmox-role.ts +1 -1
- package/src/openbao/remount-wire.ts +1 -1
- package/src/openbao/rename-occupied.test.ts +1 -1
- package/src/openbao/role-reconcile.ts +1 -1
- package/src/openbao/role-rename.test.ts +1 -1
- package/src/openbao/ssh-role.ts +1 -1
- package/src/opnsense/fake-opnsense.ts +1 -1
- package/src/opnsense/resource.ts +1 -1
- package/src/ownership/probe.ts +51 -2
- package/src/paperless/fake-paperless.ts +1 -1
- package/src/paperless/matching-types.ts +1 -1
- package/src/postgres/connection.ts +11 -15
- package/src/postgres/database-bigint-serialization.test.ts +3 -3
- package/src/postgres/database-sql.ts +7 -7
- package/src/postgres/database.ts +1 -1
- package/src/postgres/fake-grants-read.ts +4 -4
- package/src/postgres/fake-grants-sql.ts +1 -1
- package/src/postgres/fake-grants-write.ts +1 -1
- package/src/postgres/fake-role-sql.ts +3 -3
- package/src/postgres/fake-schema-drop.ts +75 -0
- package/src/postgres/fake-schema-sql.ts +11 -2
- package/src/postgres/fake-sql.ts +11 -4
- package/src/postgres/grants-database.test.ts +5 -5
- package/src/postgres/grants-existence.ts +8 -8
- package/src/postgres/grants-ops.ts +1 -1
- package/src/postgres/grants-ownership.ts +6 -6
- package/src/postgres/grants-psql-lifecycle.test.ts +7 -3
- package/src/postgres/grants-read-defaults.ts +6 -6
- package/src/postgres/grants-read.ts +17 -17
- package/src/postgres/grants-relkind-wire.test.ts +6 -4
- package/src/postgres/index.ts +2 -0
- package/src/postgres/installed-classifier.ts +1 -1
- package/src/postgres/psql-executor-escaping.test.ts +3 -1
- package/src/postgres/psql-executor.test.ts +11 -5
- package/src/postgres/psql-executor.ts +5 -7
- package/src/postgres/role-adopt.test.ts +3 -1
- package/src/postgres/role-membership-options.test.ts +3 -1
- package/src/postgres/role-membership-repair.test.ts +3 -3
- package/src/postgres/role-membership-sql.ts +5 -5
- package/src/postgres/role-password-transports.test.ts +6 -4
- package/src/postgres/role-sql.ts +2 -2
- package/src/postgres/role.ts +1 -1
- package/src/postgres/schema-assert.ts +1 -1
- package/src/postgres/schema-closure-sql.ts +108 -0
- package/src/postgres/schema-delete-proofs.test.ts +7 -7
- package/src/postgres/schema-delete.ts +89 -47
- package/src/postgres/schema-drop-2bp01.test.ts +30 -18
- package/src/postgres/schema-drop-real.test.ts +190 -0
- package/src/postgres/schema-drop-sql.ts +135 -0
- package/src/postgres/schema-drop.test.ts +241 -0
- package/src/postgres/schema-errors.ts +26 -0
- package/src/postgres/schema-handlers.test.ts +21 -14
- package/src/postgres/schema-lifecycle.test.ts +6 -60
- package/src/postgres/schema-reconcile.ts +1 -1
- package/src/postgres/schema-sequence-error.ts +38 -0
- package/src/postgres/schema-socket.test.ts +20 -6
- package/src/postgres/schema-sql.ts +17 -12
- package/src/postgres/schema-takeover.test.ts +7 -4
- package/src/postgres/schema-test-kit.ts +18 -4
- package/src/postgres/search-path.test.ts +100 -0
- package/src/postgres/search-path.ts +62 -0
- package/src/proxmox/ceph-flag-wire.test.ts +1 -1
- package/src/proxmox/ceph-fs-destroy-sdk.test.ts +1 -1
- package/src/proxmox/ceph-pool-write.test.ts +1 -1
- package/src/proxmox/client.test.ts +2 -2
- package/src/proxmox/client.ts +2 -2
- package/src/proxmox/credentials.test.ts +1 -1
- package/src/proxmox/distilled-pbs.test.ts +1 -1
- package/src/proxmox/distilled-pbs.ts +1 -1
- package/src/proxmox/distilled-pve.test.ts +2 -2
- package/src/proxmox/distilled-pve.ts +1 -1
- package/src/proxmox/fake-pbs-jobs.ts +1 -1
- package/src/proxmox/fake-pve.ts +1 -1
- package/src/proxmox/lease-cache-mint.test.ts +1 -1
- package/src/proxmox/live-core-fixtures.ts +1 -1
- package/src/proxmox/lxc-distilled.test.ts +1 -1
- package/src/proxmox/lxc-harness.ts +1 -1
- package/src/proxmox/members-timeout.test.ts +3 -3
- package/src/proxmox/members.test.ts +1 -1
- package/src/proxmox/members.ts +4 -4
- package/src/proxmox/mint.ts +4 -4
- package/src/proxmox/node-network-read-failure.test.ts +1 -1
- package/src/proxmox/qemu-lifecycle.ts +1 -1
- package/src/proxmox/read-failure-propagation.test.ts +1 -1
- package/src/proxmox/resource-spec.ts +1 -1
- package/src/proxmox/storage-read-failure.test.ts +1 -1
- package/src/proxmox/typed-absence.test.ts +2 -2
- package/src/proxmox/unreadable-read.test.ts +1 -1
- package/src/proxmox/user.test.ts +1 -1
- package/src/proxmox/zfs-pool-read-failure.test.ts +1 -1
- package/src/release/adopt-parity.test.ts +3 -1
- package/src/release/apply-pins.test.ts +2 -2
- package/src/release/binary-root.test.ts +2 -2
- package/src/release/binary.ts +9 -2
- package/src/release/download.test.ts +3 -3
- package/src/release/download.ts +1 -1
- package/src/release/fake-deploy.ts +2 -2
- package/src/release/fake-engine.ts +2 -2
- package/src/release/fake-provider.ts +2 -2
- package/src/release/plan.test.ts +2 -2
- package/src/release/providers.ts +1 -1
- package/src/talos/credentials-write.test.ts +1 -1
- package/src/talos/credentials-write.ts +2 -2
- package/src/talos/credentials.test.ts +1 -1
- package/src/talos/credentials.ts +2 -2
- package/src/talos/fake-process.ts +2 -2
- package/src/talos/kubeconfig.test.ts +1 -1
- package/src/talos/machine-config-fixtures.ts +1 -1
- package/src/talos/resource.ts +1 -1
- package/src/talos/talos-bootstrap.test.ts +1 -1
- package/src/talos/talos-cluster-health.test.ts +1 -1
- package/src/talos/talosctl.ts +2 -2
- package/src/telemetry/http-client-sealing.test.ts +2 -2
- package/src/telemetry/layer.test.ts +3 -3
- package/src/telemetry/layer.ts +2 -2
- package/src/telemetry/redact-serialization.ts +2 -2
- package/src/unifi/fake-unifi.ts +1 -1
- package/src/unifi/get-only-guard.test.ts +3 -3
- package/src/unifi/resource.ts +1 -1
- package/src/verify/args.ts +1 -1
|
@@ -17,9 +17,10 @@ import * as PgClient from '@effect/sql-pg/PgClient';
|
|
|
17
17
|
import * as Context from 'effect/Context';
|
|
18
18
|
import * as Effect from 'effect/Effect';
|
|
19
19
|
import * as Layer from 'effect/Layer';
|
|
20
|
-
import type { SqlError } from 'effect/
|
|
20
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
21
21
|
import type { PgExecutor } from './database-sql.ts';
|
|
22
22
|
import { type PsqlRunner, makePsqlExecutor } from './psql-executor.ts';
|
|
23
|
+
import { pinnedSocketExecutor } from './search-path.ts';
|
|
23
24
|
|
|
24
25
|
/** What a stack passes to reach one cluster. `host` may be a socket directory (one beginning
|
|
25
26
|
* with `/` expands to `${host}/.s.PGSQL.${port}` — measured in
|
|
@@ -109,21 +110,16 @@ export const withPg = <A, E>(
|
|
|
109
110
|
});
|
|
110
111
|
}
|
|
111
112
|
const pool = yield* PostgresPool;
|
|
113
|
+
// ⛔ ONE RESERVED, PINNED CONNECTION FOR THE WHOLE OPERATION (`search-path.ts`): the pin is a
|
|
114
|
+
// session setting, so a pool checkout per statement would run most statements unpinned — and
|
|
115
|
+
// would autocommit CREATE before GRANT. `Effect.scoped` releases the reservation; the pool
|
|
116
|
+
// layer below closes the pool after.
|
|
112
117
|
return yield* Effect.provide(
|
|
113
|
-
Effect.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// statement would autocommit CREATE before GRANT.
|
|
119
|
-
transaction: (statements) =>
|
|
120
|
-
pg.withTransaction(
|
|
121
|
-
Effect.gen(function* () {
|
|
122
|
-
for (const sql of statements) yield* pg.unsafe(sql).pipe(Effect.asVoid);
|
|
123
|
-
}),
|
|
124
|
-
),
|
|
125
|
-
},
|
|
126
|
-
{ database: target.database },
|
|
118
|
+
Effect.scoped(
|
|
119
|
+
Effect.flatMap(PgClient.PgClient, (pg) =>
|
|
120
|
+
Effect.flatMap(pinnedSocketExecutor(pg), (executor) =>
|
|
121
|
+
build(executor, { database: target.database }),
|
|
122
|
+
),
|
|
127
123
|
),
|
|
128
124
|
),
|
|
129
125
|
pool(target),
|
|
@@ -18,7 +18,7 @@ import { describe, expect, test } from 'bun:test';
|
|
|
18
18
|
import * as Effect from 'effect/Effect';
|
|
19
19
|
import * as Result from 'effect/Result';
|
|
20
20
|
import * as PgTypes from '@effect/sql-pg/PgTypes';
|
|
21
|
-
import type { SqlError } from 'effect/
|
|
21
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
22
22
|
import { encodeState } from 'alchemy/State/StateEncoding';
|
|
23
23
|
import { reconcileWithClient } from './database.ts';
|
|
24
24
|
import { PostgresDatabaseDrift } from './errors.ts';
|
|
@@ -76,10 +76,10 @@ const wireAccuratePg = (seed?: {
|
|
|
76
76
|
return {
|
|
77
77
|
unsafe: <A extends object>(text: string, params: ReadonlyArray<unknown> = []) =>
|
|
78
78
|
Effect.suspend(() => {
|
|
79
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_roles')) {
|
|
79
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_roles')) {
|
|
80
80
|
return Effect.succeed([{ present: 1 }] as unknown as ReadonlyArray<A>);
|
|
81
81
|
}
|
|
82
|
-
if (text.includes('FROM pg_database')) {
|
|
82
|
+
if (text.includes('FROM pg_catalog.pg_database')) {
|
|
83
83
|
if (created === undefined) return Effect.succeed([] as unknown as ReadonlyArray<A>);
|
|
84
84
|
const row = wireAccurateRow(text, created.oid, created.connectionLimit);
|
|
85
85
|
return Effect.succeed([row] as unknown as ReadonlyArray<A>);
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* Measured 2026-10-01: the former quote-only escaper allowed comment SQL injection when
|
|
25
25
|
* that setting was off; an input backslash escaped the first quote of a doubled pair.
|
|
26
26
|
*/
|
|
27
|
-
import type { SqlError } from 'effect/
|
|
27
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
28
28
|
import * as Effect from 'effect/Effect';
|
|
29
29
|
import type { PostgresDatabaseAttributes, PostgresDatabaseProps } from './database-attrs.ts';
|
|
30
30
|
|
|
@@ -103,7 +103,7 @@ export const isDuplicateDatabaseRace = (error: SqlError): boolean => {
|
|
|
103
103
|
);
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
-
const ROLE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_roles WHERE rolname = $1';
|
|
106
|
+
const ROLE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_catalog.pg_roles WHERE rolname = $1';
|
|
107
107
|
|
|
108
108
|
/** `OWNER` is checked against `pg_roles` before any `CREATE`, so a missing role is
|
|
109
109
|
* `PostgresDatabaseOwnerMissing` at reconcile time rather than the server's own
|
|
@@ -114,7 +114,7 @@ export const roleExists = (pg: PgExecutor, role: string): Effect.Effect<boolean,
|
|
|
114
114
|
(rows) => rows.length > 0,
|
|
115
115
|
);
|
|
116
116
|
|
|
117
|
-
const DATABASE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_database WHERE datname = $1';
|
|
117
|
+
const DATABASE_EXISTS_SQL = 'SELECT 1 AS present FROM pg_catalog.pg_database WHERE datname = $1';
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Does one database of the cluster exist? `Postgres.Schema` runs this over the FAMILY
|
|
@@ -152,8 +152,8 @@ export const databaseExists = (pg: PgExecutor, name: string): Effect.Effect<bool
|
|
|
152
152
|
const SELECT_DATABASE_SQL = `SELECT
|
|
153
153
|
d.oid AS oid,
|
|
154
154
|
d.datname AS name,
|
|
155
|
-
pg_get_userbyid(d.datdba) AS owner,
|
|
156
|
-
pg_encoding_to_char(d.encoding) AS encoding,
|
|
155
|
+
pg_catalog.pg_get_userbyid(d.datdba) AS owner,
|
|
156
|
+
pg_catalog.pg_encoding_to_char(d.encoding) AS encoding,
|
|
157
157
|
CASE d.datlocprovider
|
|
158
158
|
WHEN 'b' THEN 'builtin' WHEN 'i' THEN 'icu' WHEN 'c' THEN 'libc'
|
|
159
159
|
ELSE 'libc'
|
|
@@ -164,8 +164,8 @@ const SELECT_DATABASE_SQL = `SELECT
|
|
|
164
164
|
d.datconnlimit AS "connectionLimit",
|
|
165
165
|
d.datistemplate AS "isTemplate",
|
|
166
166
|
t.spcname AS tablespace
|
|
167
|
-
FROM pg_database d
|
|
168
|
-
JOIN pg_tablespace t ON t.oid = d.dattablespace
|
|
167
|
+
FROM pg_catalog.pg_database d
|
|
168
|
+
JOIN pg_catalog.pg_tablespace t ON t.oid = d.dattablespace
|
|
169
169
|
WHERE d.datname = $1`;
|
|
170
170
|
|
|
171
171
|
/** The read: one bound `SELECT` on `pg_database`, joined to the two functions that turn its raw
|
package/src/postgres/database.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { isResolved } from 'alchemy/Diff';
|
|
|
20
20
|
import type { Input } from 'alchemy/Input';
|
|
21
21
|
import * as Provider from 'alchemy/Provider';
|
|
22
22
|
import * as Effect from 'effect/Effect';
|
|
23
|
-
import type { SqlError } from 'effect/
|
|
23
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
24
24
|
import type { PostgresDatabaseAttributes, PostgresDatabaseProps } from './database-attrs.ts';
|
|
25
25
|
import { nameByteRefusal } from './database-attrs.ts';
|
|
26
26
|
import {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* cycle.
|
|
7
7
|
*/
|
|
8
8
|
import * as Effect from 'effect/Effect';
|
|
9
|
-
import type { SqlError } from 'effect/
|
|
9
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
10
10
|
import type { AclObject } from './fake-grants-parse.ts';
|
|
11
11
|
|
|
12
12
|
/** One `aclitem` as the fake stores it: one (object, grantee, grantor) with the words that
|
|
@@ -96,17 +96,17 @@ export const answerRead = <A extends object>(
|
|
|
96
96
|
): Effect.Effect<ReadonlyArray<A>, SqlError> | undefined => {
|
|
97
97
|
const { acl, schemas, roles, databases, tables } = model;
|
|
98
98
|
|
|
99
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_roles')) {
|
|
99
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_roles')) {
|
|
100
100
|
return Effect.succeed(
|
|
101
101
|
(roles.has(params[0] as string) ? [{ present: 1 }] : []) as unknown as ReadonlyArray<A>,
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_namespace')) {
|
|
104
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_namespace')) {
|
|
105
105
|
return Effect.succeed(
|
|
106
106
|
(schemas.has(params[0] as string) ? [{ present: 1 }] : []) as unknown as ReadonlyArray<A>,
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_database')) {
|
|
109
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_database')) {
|
|
110
110
|
return Effect.succeed(
|
|
111
111
|
(databases.has(params[0] as string) ? [{ present: 1 }] : []) as unknown as ReadonlyArray<A>,
|
|
112
112
|
);
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* `42703`, the way the server refuses a missing object.
|
|
16
16
|
*/
|
|
17
17
|
import * as Effect from 'effect/Effect';
|
|
18
|
-
import { SqlError, SqlSyntaxError } from 'effect/
|
|
18
|
+
import { SqlError, SqlSyntaxError } from 'effect/sql/SqlError';
|
|
19
19
|
import type { PgExecutor } from './database-sql.ts';
|
|
20
20
|
import { type AclEntry, type FakeCatalogTable, answerRead } from './fake-grants-read.ts';
|
|
21
21
|
import { parseGrantStatement } from './fake-grants-parse.ts';
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* same grantee SURVIVES silently (the survival `PostgresGrantsRepairRefused` surfaces), and
|
|
16
16
|
* a grantee that re-granted onward fails like the server without CASCADE (`2BP01`).
|
|
17
17
|
*/
|
|
18
|
-
import { SqlError, SqlSyntaxError } from 'effect/
|
|
18
|
+
import { SqlError, SqlSyntaxError } from 'effect/sql/SqlError';
|
|
19
19
|
import type { AclObject } from './fake-grants-parse.ts';
|
|
20
20
|
import { type FakeGrantsModel, revokesAsOwner } from './fake-grants-read.ts';
|
|
21
21
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* attributes a test seeds or a reconcile returns.
|
|
13
13
|
*/
|
|
14
14
|
import * as Effect from 'effect/Effect';
|
|
15
|
-
import type { SqlError } from 'effect/
|
|
15
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
16
16
|
import type { PostgresRoleAttributes } from './role-attrs.ts';
|
|
17
17
|
import { unquoteIdent, unquoteLiteral } from './fake-sql-quote.ts';
|
|
18
18
|
|
|
@@ -97,7 +97,7 @@ export const applyRoleStatement = <A extends object>(
|
|
|
97
97
|
text: string,
|
|
98
98
|
params: ReadonlyArray<unknown>,
|
|
99
99
|
): Effect.Effect<ReadonlyArray<A>, SqlError> | undefined => {
|
|
100
|
-
if (text.includes('FROM pg_auth_members')) {
|
|
100
|
+
if (text.includes('FROM pg_catalog.pg_auth_members')) {
|
|
101
101
|
const member = params[0] as string;
|
|
102
102
|
const rows = [...state.memberships]
|
|
103
103
|
.filter((key) => key.split('\0')[0] === member)
|
|
@@ -119,7 +119,7 @@ export const applyRoleStatement = <A extends object>(
|
|
|
119
119
|
return Effect.succeed(rows as unknown as ReadonlyArray<A>);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
if (text.includes('FROM pg_roles r')) {
|
|
122
|
+
if (text.includes('FROM pg_catalog.pg_roles r')) {
|
|
123
123
|
const name = params[0] as string;
|
|
124
124
|
const row = state.roleRows.get(name);
|
|
125
125
|
// pg_roles answers no password value (S25): even a seeded seal is not read back — state
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fake's reading of the atomic `DO` drop `schema-drop-sql.ts` emits.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ IT PARSES ITS OWN OUTPUT (the rule `fake-sql.ts` documents): the four `DECLARE` literals are
|
|
5
|
+
* read back out of the generated text and the block's decisions are replayed against the
|
|
6
|
+
* in-memory catalog in the same order the SQL makes them — absent → return, identity, empty or
|
|
7
|
+
* cross-schema dependents, drop. A changed block shape fails the parse loudly.
|
|
8
|
+
*/
|
|
9
|
+
import * as Effect from 'effect/Effect';
|
|
10
|
+
import { SqlError, UnknownError } from 'effect/sql/SqlError';
|
|
11
|
+
import { parseLiteral } from './fake-sql-quote.ts';
|
|
12
|
+
import { parseDropSchema } from './fake-sql-parse.ts';
|
|
13
|
+
import type { FakeSchemaState } from './fake-schema-sql.ts';
|
|
14
|
+
import {
|
|
15
|
+
CASCADE_SEQUENCES,
|
|
16
|
+
CROSS_SCHEMA_DEPENDENTS,
|
|
17
|
+
IDENTITY_CHANGED,
|
|
18
|
+
NOT_EMPTY,
|
|
19
|
+
} from './schema-drop-sql.ts';
|
|
20
|
+
|
|
21
|
+
const refusal = (code: string, message: string): SqlError =>
|
|
22
|
+
new SqlError({
|
|
23
|
+
reason: new UnknownError({
|
|
24
|
+
cause: Object.assign(new Error(message), { code }),
|
|
25
|
+
message,
|
|
26
|
+
operation: 'DO',
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/** `E'…'` literal at the end of a generated line, decoded. */
|
|
31
|
+
const literalAfter = (body: string, label: string): string => {
|
|
32
|
+
const match = new RegExp(`${label} [a-z]+ := (E'(?:[^']|'')*');`).exec(body);
|
|
33
|
+
if (match === null) throw new Error(`fake-sql: could not parse DO block ${label}: ${body}`);
|
|
34
|
+
return parseLiteral(match[1] as string);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const applyAtomicDrop = (
|
|
38
|
+
state: FakeSchemaState,
|
|
39
|
+
text: string,
|
|
40
|
+
): Effect.Effect<ReadonlyArray<never>, SqlError> => {
|
|
41
|
+
const body = parseLiteral(text.slice('DO '.length));
|
|
42
|
+
const name = literalAfter(body, 'v_name');
|
|
43
|
+
const owner = literalAfter(body, 'v_owner');
|
|
44
|
+
const oid = Number(/v_oid oid := (\d+);/.exec(body)?.[1]);
|
|
45
|
+
const cascade = /v_cascade boolean := (true|false);/.exec(body)?.[1] === 'true';
|
|
46
|
+
const drop = /EXECUTE (E'(?:[^']|'')*');/.exec(body)?.[1];
|
|
47
|
+
if (drop === undefined || Number.isNaN(oid)) {
|
|
48
|
+
throw new Error(`fake-sql: could not parse DO block: ${body}`);
|
|
49
|
+
}
|
|
50
|
+
if (parseDropSchema(parseLiteral(drop)).name !== name) {
|
|
51
|
+
throw new Error('fake-sql: DO block drops a different schema than it proves');
|
|
52
|
+
}
|
|
53
|
+
const row = state.schemas.get(name);
|
|
54
|
+
if (row === undefined) return Effect.succeed([]);
|
|
55
|
+
if (row.oid !== oid || row.owner !== owner) {
|
|
56
|
+
return Effect.fail(refusal(IDENTITY_CHANGED, 'schema identity changed'));
|
|
57
|
+
}
|
|
58
|
+
if (!cascade) {
|
|
59
|
+
if (state.relationsIn.has(name)) return Effect.fail(refusal(NOT_EMPTY, 'schema not empty'));
|
|
60
|
+
} else {
|
|
61
|
+
const sequences = state.sequencesIn.get(name) ?? 0;
|
|
62
|
+
if (sequences > 0) {
|
|
63
|
+
return Effect.fail(refusal(CASCADE_SEQUENCES, `cascade sequences: ${String(sequences)}`));
|
|
64
|
+
}
|
|
65
|
+
const outside = state.dependentsOutside.get(name) ?? 0;
|
|
66
|
+
if (outside > 0) {
|
|
67
|
+
return Effect.fail(
|
|
68
|
+
refusal(CROSS_SCHEMA_DEPENDENTS, `cross-schema dependents: ${String(outside)}`),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
state.relationsIn.delete(name);
|
|
72
|
+
}
|
|
73
|
+
state.schemas.delete(name);
|
|
74
|
+
return Effect.succeed([]);
|
|
75
|
+
};
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* answers for the connection it opened — and `schemaIsEmpty` from a seeded relation set.
|
|
10
10
|
*/
|
|
11
11
|
import * as Effect from 'effect/Effect';
|
|
12
|
-
import { SqlError, SqlSyntaxError, UnknownError } from 'effect/
|
|
12
|
+
import { SqlError, SqlSyntaxError, UnknownError } from 'effect/sql/SqlError';
|
|
13
|
+
import { applyAtomicDrop } from './fake-schema-drop.ts';
|
|
13
14
|
import { parseCommentSchema, parseCreateSchema, parseDropSchema } from './fake-sql-parse.ts';
|
|
14
15
|
import type { PostgresSchemaAttributes } from './schema-attrs.ts';
|
|
15
16
|
|
|
@@ -18,6 +19,11 @@ export interface FakeSchemaState {
|
|
|
18
19
|
readonly schemas: Map<string, PostgresSchemaAttributes>;
|
|
19
20
|
/** Names of schemas this fake pretends hold at least one relation. */
|
|
20
21
|
readonly relationsIn: Set<string>;
|
|
22
|
+
/** Per schema name: how many objects in OTHER schemas depend on it (what the atomic drop's
|
|
23
|
+
* `pg_depend` count answers). Absent means none. */
|
|
24
|
+
readonly dependentsOutside: Map<string, number>;
|
|
25
|
+
/** Per schema name: how many sequences it holds (a cascade drop refuses any: `HF004`). */
|
|
26
|
+
readonly sequencesIn: Map<string, number>;
|
|
21
27
|
/** What `current_database()` answers, and the stamp on every read row. */
|
|
22
28
|
readonly database: string;
|
|
23
29
|
/** What `current_user` answers, and the owner of a `CREATE SCHEMA` without `AUTHORIZATION`. */
|
|
@@ -44,6 +50,9 @@ export const applySchemaStatement = <A extends object>(
|
|
|
44
50
|
text: string,
|
|
45
51
|
params: ReadonlyArray<unknown>,
|
|
46
52
|
): Effect.Effect<ReadonlyArray<A>, SqlError> | undefined => {
|
|
53
|
+
// The atomic drop's text contains every marker below; matched first, by its own prefix.
|
|
54
|
+
if (text.startsWith('DO ')) return applyAtomicDrop(state, text);
|
|
55
|
+
|
|
47
56
|
if (text.startsWith('SELECT current_database()')) {
|
|
48
57
|
return Effect.succeed([{ database: state.database }] as unknown as ReadonlyArray<A>);
|
|
49
58
|
}
|
|
@@ -57,7 +66,7 @@ export const applySchemaStatement = <A extends object>(
|
|
|
57
66
|
return Effect.succeed([{ empty: !state.relationsIn.has(name) }] as unknown as ReadonlyArray<A>);
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
if (text.includes('FROM pg_namespace')) {
|
|
69
|
+
if (text.includes('FROM pg_catalog.pg_namespace')) {
|
|
61
70
|
const name = params[0] as string;
|
|
62
71
|
const row = state.schemas.get(name);
|
|
63
72
|
return Effect.succeed(
|
package/src/postgres/fake-sql.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* halves live in their own files under the same rule.
|
|
13
13
|
*/
|
|
14
14
|
import * as Effect from 'effect/Effect';
|
|
15
|
-
import { SqlError, SqlSyntaxError, UnknownError } from 'effect/
|
|
15
|
+
import { SqlError, SqlSyntaxError, UnknownError } from 'effect/sql/SqlError';
|
|
16
16
|
import type { PostgresDatabaseAttributes } from './database-attrs.ts';
|
|
17
17
|
import type { PgExecutor } from './database-sql.ts';
|
|
18
18
|
import { parseCreate } from './fake-sql-parse.ts';
|
|
@@ -65,6 +65,10 @@ export interface FakeSqlOptions {
|
|
|
65
65
|
readonly schemas?: ReadonlyArray<PostgresSchemaAttributes>;
|
|
66
66
|
/** Names of schemas the fake answers `schemaIsEmpty` with `false` for. */
|
|
67
67
|
readonly schemasWithRelations?: ReadonlyArray<string>;
|
|
68
|
+
/** Per schema name, how many objects in OTHER schemas depend on it (a cascade would drop
|
|
69
|
+
* them): what the atomic drop's `pg_depend` count answers. */
|
|
70
|
+
readonly dependentsOutside?: Readonly<Record<string, number>>;
|
|
71
|
+
readonly sequencesIn?: Readonly<Record<string, number>>; // per schema: sequences held (HF004)
|
|
68
72
|
/** Accept the NEXT `CREATE SCHEMA` (no error) but record nothing — the S10 case where the
|
|
69
73
|
* write's own report is a lie and the immediate re-read finds nothing. */
|
|
70
74
|
readonly swallowNextCreateSchema?: boolean;
|
|
@@ -93,6 +97,7 @@ export const makeFakeSql = (options: FakeSqlOptions = {}): FakeSql => {
|
|
|
93
97
|
>();
|
|
94
98
|
const schemas = seedSchemas(options.schemas, options.database ?? 'postgres');
|
|
95
99
|
const relationsIn = new Set(options.schemasWithRelations ?? []);
|
|
100
|
+
const dependentsOutside = new Map(Object.entries(options.dependentsOutside ?? {}));
|
|
96
101
|
let raceRemaining = options.raceNextCreate === true ? 1 : 0;
|
|
97
102
|
let failNext = options.failNext;
|
|
98
103
|
let oidCounter = 20000;
|
|
@@ -111,6 +116,8 @@ export const makeFakeSql = (options: FakeSqlOptions = {}): FakeSql => {
|
|
|
111
116
|
const schemaState: FakeSchemaState = {
|
|
112
117
|
schemas,
|
|
113
118
|
relationsIn,
|
|
119
|
+
dependentsOutside,
|
|
120
|
+
sequencesIn: new Map(Object.entries(options.sequencesIn ?? {})),
|
|
114
121
|
database: options.database ?? 'postgres',
|
|
115
122
|
standardConformingStrings: options.standardConformingStrings ?? true,
|
|
116
123
|
sessionRole: options.currentUser ?? 'postgres',
|
|
@@ -139,7 +146,7 @@ export const makeFakeSql = (options: FakeSqlOptions = {}): FakeSql => {
|
|
|
139
146
|
);
|
|
140
147
|
}
|
|
141
148
|
|
|
142
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_roles')) {
|
|
149
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_roles')) {
|
|
143
150
|
const role = params[0] as string;
|
|
144
151
|
return Effect.succeed(
|
|
145
152
|
(roleNames.has(role) || roleRows.has(role)
|
|
@@ -151,14 +158,14 @@ export const makeFakeSql = (options: FakeSqlOptions = {}): FakeSql => {
|
|
|
151
158
|
// ⚠️ startsWith, BEFORE the `FROM pg_database` branch: the full-row select also contains
|
|
152
159
|
// `FROM pg_database`, but starts with `SELECT d.oid` — only the existence probe starts
|
|
153
160
|
// with `SELECT 1 AS present`.
|
|
154
|
-
if (text.startsWith('SELECT 1 AS present FROM pg_database')) {
|
|
161
|
+
if (text.startsWith('SELECT 1 AS present FROM pg_catalog.pg_database')) {
|
|
155
162
|
const name = params[0] as string;
|
|
156
163
|
return Effect.succeed(
|
|
157
164
|
(databases.has(name) ? [{ present: 1 }] : []) as unknown as ReadonlyArray<A>,
|
|
158
165
|
);
|
|
159
166
|
}
|
|
160
167
|
|
|
161
|
-
if (text.includes('FROM pg_database')) {
|
|
168
|
+
if (text.includes('FROM pg_catalog.pg_database')) {
|
|
162
169
|
const name = params[0] as string;
|
|
163
170
|
const row = databases.get(name);
|
|
164
171
|
return Effect.succeed((row === undefined ? [] : [row]) as unknown as ReadonlyArray<A>);
|
|
@@ -48,7 +48,7 @@ const recording = (probe: string, proof: string) => {
|
|
|
48
48
|
const run: PsqlRunner = ({ stdin, argv }) => {
|
|
49
49
|
stdins.push(stdin);
|
|
50
50
|
argvs.push(argv);
|
|
51
|
-
const stdout = stdin.includes('FROM pg_database')
|
|
51
|
+
const stdout = stdin.includes('FROM pg_catalog.pg_database')
|
|
52
52
|
? probe
|
|
53
53
|
: stdin.includes('current_database()')
|
|
54
54
|
? proof
|
|
@@ -79,7 +79,7 @@ describe('a missing declared database is absent', () => {
|
|
|
79
79
|
// current_database()/GRANT/REVOKE ever targeted the (absent) declared database.
|
|
80
80
|
expect(result).toBeUndefined();
|
|
81
81
|
expect(stdins.length).toBe(1);
|
|
82
|
-
expect(stdins[0]).toContain('FROM pg_database');
|
|
82
|
+
expect(stdins[0]).toContain('FROM pg_catalog.pg_database');
|
|
83
83
|
expect(stdins[0]).not.toContain('current_database()');
|
|
84
84
|
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
85
85
|
});
|
|
@@ -106,7 +106,7 @@ describe('a present database is opened and proved', () => {
|
|
|
106
106
|
.pipe(Effect.provide(provide(run))),
|
|
107
107
|
);
|
|
108
108
|
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
109
|
-
expect(stdins[0]).toContain('FROM pg_database');
|
|
109
|
+
expect(stdins[0]).toContain('FROM pg_catalog.pg_database');
|
|
110
110
|
expect(argvs.slice(1).every((argv) => argv.at(-1) === 'agents')).toBe(true);
|
|
111
111
|
expect(stdins[1]).toContain('current_database()');
|
|
112
112
|
});
|
|
@@ -129,7 +129,7 @@ describe('a present database is opened and proved', () => {
|
|
|
129
129
|
// declared database and proves current_database() there.
|
|
130
130
|
expect(argvs.length).toBe(2);
|
|
131
131
|
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
132
|
-
expect(stdins[0]).toContain('FROM pg_database');
|
|
132
|
+
expect(stdins[0]).toContain('FROM pg_catalog.pg_database');
|
|
133
133
|
expect(argvs[1]?.at(-1)).toBe('agents');
|
|
134
134
|
expect(stdins[1]).toContain('current_database()');
|
|
135
135
|
});
|
|
@@ -152,7 +152,7 @@ describe('a missing declared database on reconcile is a typed refusal', () => {
|
|
|
152
152
|
expect(error).toMatchObject({ database: 'agents' });
|
|
153
153
|
// Only the family-connection probe ran; reconcile never opened the declared database.
|
|
154
154
|
expect(stdins.length).toBe(1);
|
|
155
|
-
expect(stdins[0]).toContain('FROM pg_database');
|
|
155
|
+
expect(stdins[0]).toContain('FROM pg_catalog.pg_database');
|
|
156
156
|
expect(argvs[0]?.at(-1)).toBe('postgres');
|
|
157
157
|
});
|
|
158
158
|
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* row `creating` and the resume failing OwnedBySomeoneElse.
|
|
6
6
|
*/
|
|
7
7
|
import * as Effect from 'effect/Effect';
|
|
8
|
-
import type { SqlError } from 'effect/
|
|
8
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
9
9
|
import type { PgExecutor } from './database-sql.ts';
|
|
10
10
|
import type { DeclaredGrants } from './grants-declare.ts';
|
|
11
11
|
import { PostgresGrantsColumnMissing, PostgresGrantsTableMissing } from './grants-errors.ts';
|
|
@@ -15,9 +15,9 @@ import { PostgresGrantsColumnMissing, PostgresGrantsTableMissing } from './grant
|
|
|
15
15
|
* (`func.sgml@REL_18_6`). */
|
|
16
16
|
const TABLES_PRESENT_SQL = `SELECT
|
|
17
17
|
c.relname AS table
|
|
18
|
-
FROM pg_class c
|
|
19
|
-
WHERE c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
20
|
-
AND c.relname::text IN (SELECT json_array_elements_text($2::json))`;
|
|
18
|
+
FROM pg_catalog.pg_class c
|
|
19
|
+
WHERE c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
20
|
+
AND c.relname::text IN (SELECT pg_catalog.json_array_elements_text($2::json))`;
|
|
21
21
|
|
|
22
22
|
const findMissingTable = (
|
|
23
23
|
pg: PgExecutor,
|
|
@@ -41,13 +41,13 @@ const findMissingTable = (
|
|
|
41
41
|
const COLUMNS_PRESENT_SQL = `SELECT
|
|
42
42
|
c.relname AS table,
|
|
43
43
|
a.attname AS column
|
|
44
|
-
FROM pg_attribute a
|
|
45
|
-
JOIN pg_class c ON c.oid = a.attrelid
|
|
46
|
-
WHERE c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
44
|
+
FROM pg_catalog.pg_attribute a
|
|
45
|
+
JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
|
|
46
|
+
WHERE c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
47
47
|
AND a.attnum > 0
|
|
48
48
|
AND NOT a.attisdropped
|
|
49
49
|
AND (c.relname, a.attname) IN (
|
|
50
|
-
SELECT x->>0, x->>1 FROM json_array_elements($2::json) x
|
|
50
|
+
SELECT x->>0, x->>1 FROM pg_catalog.json_array_elements($2::json) x
|
|
51
51
|
)`;
|
|
52
52
|
|
|
53
53
|
const findMissingColumn = (
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
import type { Input } from 'alchemy/Input';
|
|
45
45
|
import * as Effect from 'effect/Effect';
|
|
46
46
|
import { isResolved } from 'alchemy/Diff';
|
|
47
|
-
import type { SqlError } from 'effect/
|
|
47
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
48
48
|
import type { PostgresGrantsAttributes, PostgresGrantsProps } from './grants-attrs.ts';
|
|
49
49
|
import { roleExists } from './database-sql.ts';
|
|
50
50
|
import type { PgExecutor } from './database-sql.ts';
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* queries, still inside the read's one bounded burst.
|
|
12
12
|
*/
|
|
13
13
|
import * as Effect from 'effect/Effect';
|
|
14
|
-
import type { SqlError } from 'effect/
|
|
14
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
15
15
|
import type { PgExecutor } from './database-sql.ts';
|
|
16
16
|
|
|
17
17
|
/** `pg_namespace.nspowner = <role>` for one schema. No rows when the schema is absent —
|
|
18
18
|
* the caller then reads the fact as `false`. */
|
|
19
19
|
const SCHEMA_OWNER_SQL = `SELECT
|
|
20
|
-
n.nspowner = (SELECT oid FROM pg_roles WHERE rolname = $2) AS role_owns
|
|
21
|
-
FROM pg_namespace n
|
|
20
|
+
n.nspowner = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2) AS role_owns
|
|
21
|
+
FROM pg_catalog.pg_namespace n
|
|
22
22
|
WHERE n.nspname = $1`;
|
|
23
23
|
|
|
24
24
|
export const readSchemaOwnership = (
|
|
@@ -34,9 +34,9 @@ export const readSchemaOwnership = (
|
|
|
34
34
|
/** Every relation in the schema the declared role OWNS, all relkinds (the table class is
|
|
35
35
|
* not relkind-filtered, and neither is this). */
|
|
36
36
|
const OWNED_TABLES_SQL = `SELECT c.relname AS table
|
|
37
|
-
FROM pg_class c
|
|
38
|
-
WHERE c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
39
|
-
AND c.relowner = (SELECT oid FROM pg_roles WHERE rolname = $2)
|
|
37
|
+
FROM pg_catalog.pg_class c
|
|
38
|
+
WHERE c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
39
|
+
AND c.relowner = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2)
|
|
40
40
|
ORDER BY c.relname`;
|
|
41
41
|
|
|
42
42
|
export const readOwnedTables = (
|
|
@@ -8,6 +8,7 @@ import { describe, expect, test } from 'bun:test';
|
|
|
8
8
|
import * as Effect from 'effect/Effect';
|
|
9
9
|
import type { PsqlRunner } from './psql-executor.ts';
|
|
10
10
|
import { makePsqlExecutor } from './psql-executor.ts';
|
|
11
|
+
import { stripPin } from './search-path.ts';
|
|
11
12
|
import { reconcileWithClient } from './grants-ops.ts';
|
|
12
13
|
import { requireDeclaredObjectsExist } from './grants-existence.ts';
|
|
13
14
|
import { resolveProps } from './grants-declare.ts';
|
|
@@ -26,7 +27,8 @@ const props: PostgresGrantsProps = {
|
|
|
26
27
|
const runner = (): { run: PsqlRunner; stdins: string[] } => {
|
|
27
28
|
const stdins: string[] = [];
|
|
28
29
|
let granted = false;
|
|
29
|
-
const run: PsqlRunner = ({ stdin }) => {
|
|
30
|
+
const run: PsqlRunner = ({ stdin: raw }) => {
|
|
31
|
+
const stdin = stripPin(raw);
|
|
30
32
|
stdins.push(stdin);
|
|
31
33
|
if (stdin.startsWith('BEGIN')) granted = true;
|
|
32
34
|
return Promise.resolve({ code: 0, stdout: answer(stdin, granted), stderr: '' });
|
|
@@ -40,8 +42,10 @@ const answer = (stdin: string, granted: boolean): string => {
|
|
|
40
42
|
if (stdin.includes('json_array_elements')) {
|
|
41
43
|
return '[{"table":"a","column":"b.c"},{"table":"a.b","column":"c"}]';
|
|
42
44
|
}
|
|
43
|
-
if (stdin.includes('SELECT 1 AS present FROM pg_roles')) return '[{"present":1}]';
|
|
44
|
-
if (stdin.includes('SELECT 1 AS present FROM pg_namespace'))
|
|
45
|
+
if (stdin.includes('SELECT 1 AS present FROM pg_catalog.pg_roles')) return '[{"present":1}]';
|
|
46
|
+
if (stdin.includes('SELECT 1 AS present FROM pg_catalog.pg_namespace')) {
|
|
47
|
+
return '[{"present":1}]';
|
|
48
|
+
}
|
|
45
49
|
if (stdin.includes('aclexplode(n.nspacl)')) {
|
|
46
50
|
return granted ? '[{"public":false,"privilege":"usage","grantable":false}]' : '[]';
|
|
47
51
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* header for the doctrine), never the `aclitem` text.
|
|
8
8
|
*/
|
|
9
9
|
import * as Effect from 'effect/Effect';
|
|
10
|
-
import type { SqlError } from 'effect/
|
|
10
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
11
11
|
import type { PgExecutor } from './database-sql.ts';
|
|
12
12
|
import { type AclRow, encodeWord } from './grants-words.ts';
|
|
13
13
|
|
|
@@ -15,14 +15,14 @@ import { type AclRow, encodeWord } from './grants-words.ts';
|
|
|
15
15
|
* role's words, whatever role created the entry. Sorted by forRole so two reads of the
|
|
16
16
|
* same state compare equal. */
|
|
17
17
|
const DEFAULTS_SQL = `SELECT
|
|
18
|
-
pg_get_userbyid(d.defaclrole) AS for_role,
|
|
18
|
+
pg_catalog.pg_get_userbyid(d.defaclrole) AS for_role,
|
|
19
19
|
a.privilege_type AS privilege,
|
|
20
20
|
a.is_grantable AS grantable
|
|
21
|
-
FROM pg_default_acl d
|
|
22
|
-
CROSS JOIN LATERAL aclexplode(d.defaclacl) AS a
|
|
23
|
-
WHERE d.defaclnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
21
|
+
FROM pg_catalog.pg_default_acl d
|
|
22
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(d.defaclacl) AS a
|
|
23
|
+
WHERE d.defaclnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
24
24
|
AND d.defaclobjtype = 'r'
|
|
25
|
-
AND a.grantee = (SELECT oid FROM pg_roles WHERE rolname = $2)
|
|
25
|
+
AND a.grantee = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2)
|
|
26
26
|
ORDER BY for_role`;
|
|
27
27
|
|
|
28
28
|
export interface LiveDefault {
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
* CASE in `database-sql.ts`, which casts `"char"` columns to text for the same reason.
|
|
33
33
|
*/
|
|
34
34
|
import * as Effect from 'effect/Effect';
|
|
35
|
-
import type { SqlError } from 'effect/
|
|
35
|
+
import type { SqlError } from 'effect/sql/SqlError';
|
|
36
36
|
import type { PgExecutor } from './database-sql.ts';
|
|
37
37
|
import { readOwnedTables, readSchemaOwnership } from './grants-ownership.ts';
|
|
38
38
|
import { type LiveDefault, readDefaultAcls } from './grants-read-defaults.ts';
|
|
39
39
|
import { type AclRow, encodeWord, wordsOf } from './grants-words.ts';
|
|
40
40
|
|
|
41
|
-
const SCHEMA_PRESENT_SQL = 'SELECT 1 AS present FROM pg_namespace WHERE nspname = $1';
|
|
41
|
+
const SCHEMA_PRESENT_SQL = 'SELECT 1 AS present FROM pg_catalog.pg_namespace WHERE nspname = $1';
|
|
42
42
|
|
|
43
43
|
export const schemaExists = (pg: PgExecutor, schema: string): Effect.Effect<boolean, SqlError> =>
|
|
44
44
|
Effect.map(
|
|
@@ -52,10 +52,10 @@ const SCHEMA_ACL_SQL = `SELECT
|
|
|
52
52
|
a.grantee = 0 AS public,
|
|
53
53
|
a.privilege_type AS privilege,
|
|
54
54
|
a.is_grantable AS grantable
|
|
55
|
-
FROM pg_namespace n
|
|
56
|
-
CROSS JOIN LATERAL aclexplode(n.nspacl) AS a
|
|
55
|
+
FROM pg_catalog.pg_namespace n
|
|
56
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(n.nspacl) AS a
|
|
57
57
|
WHERE n.nspname = $1
|
|
58
|
-
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_roles WHERE rolname = $2))`;
|
|
58
|
+
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2))`;
|
|
59
59
|
|
|
60
60
|
export interface LiveSchemaAcl {
|
|
61
61
|
readonly role: ReadonlyArray<string>;
|
|
@@ -84,10 +84,10 @@ const TABLES_SQL = `SELECT
|
|
|
84
84
|
a.grantee = 0 AS public,
|
|
85
85
|
a.privilege_type AS privilege,
|
|
86
86
|
a.is_grantable AS grantable
|
|
87
|
-
FROM pg_class c
|
|
88
|
-
CROSS JOIN LATERAL aclexplode(c.relacl) AS a
|
|
89
|
-
WHERE c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
90
|
-
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_roles WHERE rolname = $2))
|
|
87
|
+
FROM pg_catalog.pg_class c
|
|
88
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(c.relacl) AS a
|
|
89
|
+
WHERE c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
90
|
+
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2))
|
|
91
91
|
ORDER BY c.relname`;
|
|
92
92
|
|
|
93
93
|
export interface LiveTable {
|
|
@@ -146,17 +146,17 @@ const COLUMNS_SQL = `SELECT
|
|
|
146
146
|
a.grantee = 0 AS public,
|
|
147
147
|
a.privilege_type AS privilege,
|
|
148
148
|
a.is_grantable AS grantable,
|
|
149
|
-
pg_get_userbyid(a.grantor) AS grantor,
|
|
150
|
-
pg_get_userbyid(c.relowner) AS owner,
|
|
149
|
+
pg_catalog.pg_get_userbyid(a.grantor) AS grantor,
|
|
150
|
+
pg_catalog.pg_get_userbyid(c.relowner) AS owner,
|
|
151
151
|
current_user AS revoker,
|
|
152
|
-
pg_has_role(current_user, c.relowner, 'USAGE') AS revoker_as_owner
|
|
153
|
-
FROM pg_attribute v
|
|
154
|
-
JOIN pg_class c ON c.oid = v.attrelid
|
|
155
|
-
CROSS JOIN LATERAL aclexplode(v.attacl) AS a
|
|
156
|
-
WHERE c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = $1)
|
|
152
|
+
pg_catalog.pg_has_role(current_user, c.relowner, 'USAGE') AS revoker_as_owner
|
|
153
|
+
FROM pg_catalog.pg_attribute v
|
|
154
|
+
JOIN pg_catalog.pg_class c ON c.oid = v.attrelid
|
|
155
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(v.attacl) AS a
|
|
156
|
+
WHERE c.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1)
|
|
157
157
|
AND v.attnum > 0
|
|
158
158
|
AND NOT v.attisdropped
|
|
159
|
-
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_roles WHERE rolname = $2))
|
|
159
|
+
AND (a.grantee = 0 OR a.grantee = (SELECT oid FROM pg_catalog.pg_roles WHERE rolname = $2))
|
|
160
160
|
ORDER BY c.relname, v.attname`;
|
|
161
161
|
|
|
162
162
|
export interface LiveColumn {
|