@homeflare/alchemy 0.1.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/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/cloudflare/client.d.ts +45 -0
- package/dist/cloudflare/client.d.ts.map +1 -0
- package/dist/cloudflare/index.d.ts +11 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +129 -0
- package/dist/cloudflare/index.js.map +13 -0
- package/dist/cloudflare/lock-rules.d.ts +50 -0
- package/dist/cloudflare/lock-rules.d.ts.map +1 -0
- package/dist/cloudflare/providers.d.ts +19 -0
- package/dist/cloudflare/providers.d.ts.map +1 -0
- package/dist/cloudflare/r2-bucket-lock.d.ts +100 -0
- package/dist/cloudflare/r2-bucket-lock.d.ts.map +1 -0
- package/dist/forgejo/branch-protection-form.d.ts +19 -0
- package/dist/forgejo/branch-protection-form.d.ts.map +1 -0
- package/dist/forgejo/branch-protection.d.ts +47 -0
- package/dist/forgejo/branch-protection.d.ts.map +1 -0
- package/dist/forgejo/client.d.ts +37 -0
- package/dist/forgejo/client.d.ts.map +1 -0
- package/dist/forgejo/index.d.ts +18 -0
- package/dist/forgejo/index.d.ts.map +1 -0
- package/dist/forgejo/index.js +479 -0
- package/dist/forgejo/index.js.map +21 -0
- package/dist/forgejo/org-actions-secrets.d.ts +45 -0
- package/dist/forgejo/org-actions-secrets.d.ts.map +1 -0
- package/dist/forgejo/org-label.d.ts +46 -0
- package/dist/forgejo/org-label.d.ts.map +1 -0
- package/dist/forgejo/org-team.d.ts +42 -0
- package/dist/forgejo/org-team.d.ts.map +1 -0
- package/dist/forgejo/repo-webhook-form.d.ts +27 -0
- package/dist/forgejo/repo-webhook-form.d.ts.map +1 -0
- package/dist/forgejo/repo-webhook.d.ts +46 -0
- package/dist/forgejo/repo-webhook.d.ts.map +1 -0
- package/dist/forgejo/repository.d.ts +45 -0
- package/dist/forgejo/repository.d.ts.map +1 -0
- package/dist/forgejo/resource.d.ts +83 -0
- package/dist/forgejo/resource.d.ts.map +1 -0
- package/dist/forgejo/team-member.d.ts +39 -0
- package/dist/forgejo/team-member.d.ts.map +1 -0
- package/dist/forgejo/values.d.ts +24 -0
- package/dist/forgejo/values.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +9 -0
- package/dist/openbao/auth-role-form.d.ts +38 -0
- package/dist/openbao/auth-role-form.d.ts.map +1 -0
- package/dist/openbao/auth-role.d.ts +20 -0
- package/dist/openbao/auth-role.d.ts.map +1 -0
- package/dist/openbao/bao-address.d.ts +72 -0
- package/dist/openbao/bao-address.d.ts.map +1 -0
- package/dist/openbao/bao-http.d.ts +71 -0
- package/dist/openbao/bao-http.d.ts.map +1 -0
- package/dist/openbao/bao-status.d.ts +74 -0
- package/dist/openbao/bao-status.d.ts.map +1 -0
- package/dist/openbao/cloudflare-group-scope.d.ts +73 -0
- package/dist/openbao/cloudflare-group-scope.d.ts.map +1 -0
- package/dist/openbao/cloudflare-parity-catalog.d.ts +28 -0
- package/dist/openbao/cloudflare-parity-catalog.d.ts.map +1 -0
- package/dist/openbao/cloudflare-parity-snapshot.d.ts +31 -0
- package/dist/openbao/cloudflare-parity-snapshot.d.ts.map +1 -0
- package/dist/openbao/cloudflare-parity.d.ts +14 -0
- package/dist/openbao/cloudflare-parity.d.ts.map +1 -0
- package/dist/openbao/cloudflare-permission-groups-solve.d.ts +85 -0
- package/dist/openbao/cloudflare-permission-groups-solve.d.ts.map +1 -0
- package/dist/openbao/cloudflare-permission-groups.d.ts +87 -0
- package/dist/openbao/cloudflare-permission-groups.d.ts.map +1 -0
- package/dist/openbao/cloudflare-policy.d.ts +65 -0
- package/dist/openbao/cloudflare-policy.d.ts.map +1 -0
- package/dist/openbao/cloudflare-role-form.d.ts +110 -0
- package/dist/openbao/cloudflare-role-form.d.ts.map +1 -0
- package/dist/openbao/cloudflare-role-wire.d.ts +27 -0
- package/dist/openbao/cloudflare-role-wire.d.ts.map +1 -0
- package/dist/openbao/cloudflare-role.d.ts +35 -0
- package/dist/openbao/cloudflare-role.d.ts.map +1 -0
- package/dist/openbao/cloudflare-roles-config.d.ts +67 -0
- package/dist/openbao/cloudflare-roles-config.d.ts.map +1 -0
- package/dist/openbao/cloudflare-roles-expand.d.ts +76 -0
- package/dist/openbao/cloudflare-roles-expand.d.ts.map +1 -0
- package/dist/openbao/digest.d.ts +24 -0
- package/dist/openbao/digest.d.ts.map +1 -0
- package/dist/openbao/fake-bao.d.ts +40 -0
- package/dist/openbao/fake-bao.d.ts.map +1 -0
- package/dist/openbao/forgejo-bootstrap-parse.d.ts +46 -0
- package/dist/openbao/forgejo-bootstrap-parse.d.ts.map +1 -0
- package/dist/openbao/forgejo-bootstrap.d.ts +29 -0
- package/dist/openbao/forgejo-bootstrap.d.ts.map +1 -0
- package/dist/openbao/index.d.ts +18 -0
- package/dist/openbao/index.d.ts.map +1 -0
- package/dist/openbao/index.js +1158 -0
- package/dist/openbao/index.js.map +33 -0
- package/dist/openbao/mount-form.d.ts +60 -0
- package/dist/openbao/mount-form.d.ts.map +1 -0
- package/dist/openbao/mount-wire.d.ts +24 -0
- package/dist/openbao/mount-wire.d.ts.map +1 -0
- package/dist/openbao/mount.d.ts +20 -0
- package/dist/openbao/mount.d.ts.map +1 -0
- package/dist/openbao/pki-role-form.d.ts +118 -0
- package/dist/openbao/pki-role-form.d.ts.map +1 -0
- package/dist/openbao/pki-role.d.ts +50 -0
- package/dist/openbao/pki-role.d.ts.map +1 -0
- package/dist/openbao/policy-assembly.d.ts +13 -0
- package/dist/openbao/policy-assembly.d.ts.map +1 -0
- package/dist/openbao/policy-wire.d.ts +41 -0
- package/dist/openbao/policy-wire.d.ts.map +1 -0
- package/dist/openbao/policy.d.ts +83 -0
- package/dist/openbao/policy.d.ts.map +1 -0
- package/dist/openbao/proxmox-role-form.d.ts +92 -0
- package/dist/openbao/proxmox-role-form.d.ts.map +1 -0
- package/dist/openbao/proxmox-role.d.ts +47 -0
- package/dist/openbao/proxmox-role.d.ts.map +1 -0
- package/dist/openbao/ssh-role-form.d.ts +99 -0
- package/dist/openbao/ssh-role-form.d.ts.map +1 -0
- package/dist/openbao/ssh-role.d.ts +43 -0
- package/dist/openbao/ssh-role.d.ts.map +1 -0
- package/dist/proxmox/acl.d.ts +72 -0
- package/dist/proxmox/acl.d.ts.map +1 -0
- package/dist/proxmox/api-token-form.d.ts +59 -0
- package/dist/proxmox/api-token-form.d.ts.map +1 -0
- package/dist/proxmox/api-token.d.ts +159 -0
- package/dist/proxmox/api-token.d.ts.map +1 -0
- package/dist/proxmox/backup-job.d.ts +112 -0
- package/dist/proxmox/backup-job.d.ts.map +1 -0
- package/dist/proxmox/ceph-daemon-form.d.ts +70 -0
- package/dist/proxmox/ceph-daemon-form.d.ts.map +1 -0
- package/dist/proxmox/ceph-daemon.d.ts +162 -0
- package/dist/proxmox/ceph-daemon.d.ts.map +1 -0
- package/dist/proxmox/ceph-flag.d.ts +131 -0
- package/dist/proxmox/ceph-flag.d.ts.map +1 -0
- package/dist/proxmox/ceph-fs-wire.d.ts +106 -0
- package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -0
- package/dist/proxmox/ceph-fs.d.ts +124 -0
- package/dist/proxmox/ceph-fs.d.ts.map +1 -0
- package/dist/proxmox/ceph-osd-tree.d.ts +154 -0
- package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -0
- package/dist/proxmox/ceph-osd-write.d.ts +36 -0
- package/dist/proxmox/ceph-osd-write.d.ts.map +1 -0
- package/dist/proxmox/ceph-osd.d.ts +102 -0
- package/dist/proxmox/ceph-osd.d.ts.map +1 -0
- package/dist/proxmox/ceph-pool-form.d.ts +217 -0
- package/dist/proxmox/ceph-pool-form.d.ts.map +1 -0
- package/dist/proxmox/ceph-pool-settle.d.ts +39 -0
- package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -0
- package/dist/proxmox/ceph-pool.d.ts +48 -0
- package/dist/proxmox/ceph-pool.d.ts.map +1 -0
- package/dist/proxmox/client.d.ts +64 -0
- package/dist/proxmox/client.d.ts.map +1 -0
- package/dist/proxmox/credentials.d.ts +153 -0
- package/dist/proxmox/credentials.d.ts.map +1 -0
- package/dist/proxmox/firewall-alias-form.d.ts +98 -0
- package/dist/proxmox/firewall-alias-form.d.ts.map +1 -0
- package/dist/proxmox/firewall-alias.d.ts +141 -0
- package/dist/proxmox/firewall-alias.d.ts.map +1 -0
- package/dist/proxmox/generated/pbs.d.ts +388 -0
- package/dist/proxmox/generated/pbs.d.ts.map +1 -0
- package/dist/proxmox/generated/pve.d.ts +4713 -0
- package/dist/proxmox/generated/pve.d.ts.map +1 -0
- package/dist/proxmox/group.d.ts +104 -0
- package/dist/proxmox/group.d.ts.map +1 -0
- package/dist/proxmox/ha-resource.d.ts +104 -0
- package/dist/proxmox/ha-resource.d.ts.map +1 -0
- package/dist/proxmox/ha-rule-form.d.ts +103 -0
- package/dist/proxmox/ha-rule-form.d.ts.map +1 -0
- package/dist/proxmox/ha-rule.d.ts +156 -0
- package/dist/proxmox/ha-rule.d.ts.map +1 -0
- package/dist/proxmox/index.d.ts +43 -0
- package/dist/proxmox/index.d.ts.map +1 -0
- package/dist/proxmox/index.js +2322 -0
- package/dist/proxmox/index.js.map +70 -0
- package/dist/proxmox/lease-cache.d.ts +98 -0
- package/dist/proxmox/lease-cache.d.ts.map +1 -0
- package/dist/proxmox/lxc.d.ts +59 -0
- package/dist/proxmox/lxc.d.ts.map +1 -0
- package/dist/proxmox/members.d.ts +56 -0
- package/dist/proxmox/members.d.ts.map +1 -0
- package/dist/proxmox/metric-server-form.d.ts +53 -0
- package/dist/proxmox/metric-server-form.d.ts.map +1 -0
- package/dist/proxmox/metric-server-otel.d.ts +49 -0
- package/dist/proxmox/metric-server-otel.d.ts.map +1 -0
- package/dist/proxmox/metric-server.d.ts +123 -0
- package/dist/proxmox/metric-server.d.ts.map +1 -0
- package/dist/proxmox/network-apply-read.d.ts +93 -0
- package/dist/proxmox/network-apply-read.d.ts.map +1 -0
- package/dist/proxmox/network-apply.d.ts +102 -0
- package/dist/proxmox/network-apply.d.ts.map +1 -0
- package/dist/proxmox/node-network-form.d.ts +128 -0
- package/dist/proxmox/node-network-form.d.ts.map +1 -0
- package/dist/proxmox/node-network.d.ts +173 -0
- package/dist/proxmox/node-network.d.ts.map +1 -0
- package/dist/proxmox/notification-target-form.d.ts +44 -0
- package/dist/proxmox/notification-target-form.d.ts.map +1 -0
- package/dist/proxmox/notification-target.d.ts +146 -0
- package/dist/proxmox/notification-target.d.ts.map +1 -0
- package/dist/proxmox/pbs-datastore-form.d.ts +147 -0
- package/dist/proxmox/pbs-datastore-form.d.ts.map +1 -0
- package/dist/proxmox/pbs-datastore-guard.d.ts +55 -0
- package/dist/proxmox/pbs-datastore-guard.d.ts.map +1 -0
- package/dist/proxmox/pbs-datastore.d.ts +140 -0
- package/dist/proxmox/pbs-datastore.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job-form.d.ts +97 -0
- package/dist/proxmox/pbs-prune-job-form.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job.d.ts +168 -0
- package/dist/proxmox/pbs-prune-job.d.ts.map +1 -0
- package/dist/proxmox/pbs-sync-job-form.d.ts +83 -0
- package/dist/proxmox/pbs-sync-job-form.d.ts.map +1 -0
- package/dist/proxmox/pbs-sync-job.d.ts +246 -0
- package/dist/proxmox/pbs-sync-job.d.ts.map +1 -0
- package/dist/proxmox/pbs-verify-job-form.d.ts +114 -0
- package/dist/proxmox/pbs-verify-job-form.d.ts.map +1 -0
- package/dist/proxmox/pbs-verify-job.d.ts +145 -0
- package/dist/proxmox/pbs-verify-job.d.ts.map +1 -0
- package/dist/proxmox/pool.d.ts +42 -0
- package/dist/proxmox/pool.d.ts.map +1 -0
- package/dist/proxmox/qemu.d.ts +46 -0
- package/dist/proxmox/qemu.d.ts.map +1 -0
- package/dist/proxmox/replication-job-form.d.ts +71 -0
- package/dist/proxmox/replication-job-form.d.ts.map +1 -0
- package/dist/proxmox/replication-job.d.ts +162 -0
- package/dist/proxmox/replication-job.d.ts.map +1 -0
- package/dist/proxmox/resource.d.ts +157 -0
- package/dist/proxmox/resource.d.ts.map +1 -0
- package/dist/proxmox/role.d.ts +97 -0
- package/dist/proxmox/role.d.ts.map +1 -0
- package/dist/proxmox/sdn-apply-read.d.ts +80 -0
- package/dist/proxmox/sdn-apply-read.d.ts.map +1 -0
- package/dist/proxmox/sdn-apply.d.ts +63 -0
- package/dist/proxmox/sdn-apply.d.ts.map +1 -0
- package/dist/proxmox/sdn-subnet-form.d.ts +111 -0
- package/dist/proxmox/sdn-subnet-form.d.ts.map +1 -0
- package/dist/proxmox/sdn-subnet.d.ts +161 -0
- package/dist/proxmox/sdn-subnet.d.ts.map +1 -0
- package/dist/proxmox/sdn-vnet.d.ts +113 -0
- package/dist/proxmox/sdn-vnet.d.ts.map +1 -0
- package/dist/proxmox/sdn-zone.d.ts +126 -0
- package/dist/proxmox/sdn-zone.d.ts.map +1 -0
- package/dist/proxmox/storage.d.ts +120 -0
- package/dist/proxmox/storage.d.ts.map +1 -0
- package/dist/proxmox/user.d.ts +107 -0
- package/dist/proxmox/user.d.ts.map +1 -0
- package/dist/proxmox/values.d.ts +134 -0
- package/dist/proxmox/values.d.ts.map +1 -0
- package/dist/proxmox/zfs-pool-write.d.ts +76 -0
- package/dist/proxmox/zfs-pool-write.d.ts.map +1 -0
- package/dist/proxmox/zfs-pool.d.ts +146 -0
- package/dist/proxmox/zfs-pool.d.ts.map +1 -0
- package/dist/talos/credentials.d.ts +30 -0
- package/dist/talos/credentials.d.ts.map +1 -0
- package/dist/talos/index.d.ts +15 -0
- package/dist/talos/index.d.ts.map +1 -0
- package/dist/talos/index.js +392 -0
- package/dist/talos/index.js.map +16 -0
- package/dist/talos/kubeconfig.d.ts +53 -0
- package/dist/talos/kubeconfig.d.ts.map +1 -0
- package/dist/talos/resource.d.ts +32 -0
- package/dist/talos/resource.d.ts.map +1 -0
- package/dist/talos/talos-bootstrap.d.ts +27 -0
- package/dist/talos/talos-bootstrap.d.ts.map +1 -0
- package/dist/talos/talos-cluster-health.d.ts +36 -0
- package/dist/talos/talos-cluster-health.d.ts.map +1 -0
- package/dist/talos/talos-machine-config.d.ts +41 -0
- package/dist/talos/talos-machine-config.d.ts.map +1 -0
- package/dist/talos/talosctl.d.ts +29 -0
- package/dist/talos/talosctl.d.ts.map +1 -0
- package/dist/talos/values.d.ts +20 -0
- package/dist/talos/values.d.ts.map +1 -0
- package/package.json +57 -0
- package/src/cloudflare/client.ts +76 -0
- package/src/cloudflare/index.ts +10 -0
- package/src/cloudflare/lock-rules.ts +60 -0
- package/src/cloudflare/providers.ts +23 -0
- package/src/cloudflare/r2-bucket-lock.ts +220 -0
- package/src/forgejo/branch-protection-form.ts +29 -0
- package/src/forgejo/branch-protection.ts +101 -0
- package/src/forgejo/client.ts +136 -0
- package/src/forgejo/index.ts +17 -0
- package/src/forgejo/org-actions-secrets.ts +99 -0
- package/src/forgejo/org-label.ts +100 -0
- package/src/forgejo/org-team.ts +105 -0
- package/src/forgejo/repo-webhook-form.ts +47 -0
- package/src/forgejo/repo-webhook.ts +118 -0
- package/src/forgejo/repository.ts +126 -0
- package/src/forgejo/resource.ts +171 -0
- package/src/forgejo/team-member.ts +97 -0
- package/src/forgejo/values.test.ts +48 -0
- package/src/forgejo/values.ts +61 -0
- package/src/index.ts +18 -0
- package/src/openbao/auth-role-form.ts +112 -0
- package/src/openbao/auth-role.ts +101 -0
- package/src/openbao/bao-address.test.ts +89 -0
- package/src/openbao/bao-address.ts +97 -0
- package/src/openbao/bao-http-gate.test.ts +88 -0
- package/src/openbao/bao-http-unix.test.ts +70 -0
- package/src/openbao/bao-http.test.ts +161 -0
- package/src/openbao/bao-http.ts +185 -0
- package/src/openbao/bao-status.test.ts +114 -0
- package/src/openbao/bao-status.ts +137 -0
- package/src/openbao/cloudflare-group-scope.test.ts +103 -0
- package/src/openbao/cloudflare-group-scope.ts +83 -0
- package/src/openbao/cloudflare-parity-catalog.ts +104 -0
- package/src/openbao/cloudflare-parity-snapshot.ts +84 -0
- package/src/openbao/cloudflare-parity.ts +152 -0
- package/src/openbao/cloudflare-permission-groups-solve.test.ts +171 -0
- package/src/openbao/cloudflare-permission-groups-solve.ts +197 -0
- package/src/openbao/cloudflare-permission-groups.test.ts +369 -0
- package/src/openbao/cloudflare-permission-groups.ts +299 -0
- package/src/openbao/cloudflare-policy.ts +180 -0
- package/src/openbao/cloudflare-role-form.test.ts +177 -0
- package/src/openbao/cloudflare-role-form.ts +183 -0
- package/src/openbao/cloudflare-role-wire.test.ts +132 -0
- package/src/openbao/cloudflare-role-wire.ts +41 -0
- package/src/openbao/cloudflare-role.ts +189 -0
- package/src/openbao/cloudflare-roles-config.ts +230 -0
- package/src/openbao/cloudflare-roles-expand-bucket.test.ts +134 -0
- package/src/openbao/cloudflare-roles-expand.ts +231 -0
- package/src/openbao/digest.ts +26 -0
- package/src/openbao/fake-bao.ts +84 -0
- package/src/openbao/forgejo-bootstrap-parse.test.ts +76 -0
- package/src/openbao/forgejo-bootstrap-parse.ts +90 -0
- package/src/openbao/forgejo-bootstrap.ts +181 -0
- package/src/openbao/index.ts +17 -0
- package/src/openbao/mount-form.ts +147 -0
- package/src/openbao/mount-wire.test.ts +108 -0
- package/src/openbao/mount-wire.ts +79 -0
- package/src/openbao/mount.ts +132 -0
- package/src/openbao/pki-role-form.ts +248 -0
- package/src/openbao/pki-role.ts +202 -0
- package/src/openbao/policy-assembly.test.ts +28 -0
- package/src/openbao/policy-assembly.ts +13 -0
- package/src/openbao/policy-wire.test.ts +90 -0
- package/src/openbao/policy-wire.ts +53 -0
- package/src/openbao/policy.ts +212 -0
- package/src/openbao/proxmox-role-form.ts +174 -0
- package/src/openbao/proxmox-role.ts +214 -0
- package/src/openbao/ssh-role-form.ts +248 -0
- package/src/openbao/ssh-role.ts +240 -0
- package/src/proxmox/acl.ts +267 -0
- package/src/proxmox/api-token-form.ts +122 -0
- package/src/proxmox/api-token.ts +222 -0
- package/src/proxmox/backup-job.ts +213 -0
- package/src/proxmox/ceph-daemon-form.ts +84 -0
- package/src/proxmox/ceph-daemon.ts +243 -0
- package/src/proxmox/ceph-flag.ts +249 -0
- package/src/proxmox/ceph-fs-wire.ts +246 -0
- package/src/proxmox/ceph-fs.ts +249 -0
- package/src/proxmox/ceph-osd-tree.ts +193 -0
- package/src/proxmox/ceph-osd-write.ts +76 -0
- package/src/proxmox/ceph-osd.ts +244 -0
- package/src/proxmox/ceph-pool-form.ts +249 -0
- package/src/proxmox/ceph-pool-settle.ts +70 -0
- package/src/proxmox/ceph-pool.ts +212 -0
- package/src/proxmox/client.test.ts +185 -0
- package/src/proxmox/client.ts +240 -0
- package/src/proxmox/credentials.test.ts +144 -0
- package/src/proxmox/credentials.ts +254 -0
- package/src/proxmox/firewall-alias-form.ts +112 -0
- package/src/proxmox/firewall-alias.ts +208 -0
- package/src/proxmox/generated/pbs.ts +461 -0
- package/src/proxmox/generated/pve.ts +7344 -0
- package/src/proxmox/group.ts +199 -0
- package/src/proxmox/ha-resource.ts +169 -0
- package/src/proxmox/ha-rule-form.ts +185 -0
- package/src/proxmox/ha-rule.ts +240 -0
- package/src/proxmox/index.ts +42 -0
- package/src/proxmox/lease-cache.test.ts +163 -0
- package/src/proxmox/lease-cache.ts +131 -0
- package/src/proxmox/lxc.ts +117 -0
- package/src/proxmox/members.test.ts +54 -0
- package/src/proxmox/members.ts +174 -0
- package/src/proxmox/metric-server-form.ts +128 -0
- package/src/proxmox/metric-server-otel.ts +99 -0
- package/src/proxmox/metric-server.ts +214 -0
- package/src/proxmox/network-apply-read.ts +228 -0
- package/src/proxmox/network-apply.ts +244 -0
- package/src/proxmox/node-network-form.ts +213 -0
- package/src/proxmox/node-network.ts +243 -0
- package/src/proxmox/notification-target-form.ts +104 -0
- package/src/proxmox/notification-target.ts +222 -0
- package/src/proxmox/pbs-datastore-form.ts +248 -0
- package/src/proxmox/pbs-datastore-guard.ts +105 -0
- package/src/proxmox/pbs-datastore.ts +271 -0
- package/src/proxmox/pbs-prune-job-form.ts +208 -0
- package/src/proxmox/pbs-prune-job.ts +227 -0
- package/src/proxmox/pbs-sync-job-form.ts +234 -0
- package/src/proxmox/pbs-sync-job.ts +258 -0
- package/src/proxmox/pbs-verify-job-form.ts +131 -0
- package/src/proxmox/pbs-verify-job.ts +227 -0
- package/src/proxmox/pool.test.ts +42 -0
- package/src/proxmox/pool.ts +80 -0
- package/src/proxmox/qemu.ts +89 -0
- package/src/proxmox/replication-job-form.ts +89 -0
- package/src/proxmox/replication-job.ts +248 -0
- package/src/proxmox/resource.ts +257 -0
- package/src/proxmox/role.ts +161 -0
- package/src/proxmox/sdn-apply-read.test.ts +152 -0
- package/src/proxmox/sdn-apply-read.ts +189 -0
- package/src/proxmox/sdn-apply.ts +154 -0
- package/src/proxmox/sdn-subnet-form.ts +156 -0
- package/src/proxmox/sdn-subnet.ts +238 -0
- package/src/proxmox/sdn-vnet.ts +228 -0
- package/src/proxmox/sdn-zone.ts +246 -0
- package/src/proxmox/storage.ts +245 -0
- package/src/proxmox/user.ts +214 -0
- package/src/proxmox/values.test.ts +193 -0
- package/src/proxmox/values.ts +203 -0
- package/src/proxmox/zfs-pool-write.ts +130 -0
- package/src/proxmox/zfs-pool.ts +253 -0
- package/src/talos/credentials.ts +136 -0
- package/src/talos/index.ts +14 -0
- package/src/talos/kubeconfig.ts +170 -0
- package/src/talos/resource.ts +31 -0
- package/src/talos/talos-bootstrap.ts +109 -0
- package/src/talos/talos-cluster-health.ts +119 -0
- package/src/talos/talos-machine-config.ts +146 -0
- package/src/talos/talosctl.ts +94 -0
- package/src/talos/values.test.ts +80 -0
- package/src/talos/values.ts +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pbs-prune-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-prune-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAe,MAAM,eAAe,CAAC;AAGtF;;;;;GAKG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,uFAAuF;IACvF,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;+FAC2F;IAC3F,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gGAC4F;IAC5F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,mGAAmG;IACnG,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;GAIG;AACH,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAgDjE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,iIACiD,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { SyncJobAttributes, SyncJobProps } from './pbs-sync-job.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The marker for "PBS has no value for this number".
|
|
4
|
+
*
|
|
5
|
+
* ⚠️ `-1` RATHER THAN `0`, AND metric-server.ts's `UNSET = -1` IS THE PRECEDENT. `max-depth` has a
|
|
6
|
+
* legal value of 0 — sync this namespace and no child of it — which is a completely different
|
|
7
|
+
* instruction from the absent field, where PBS recurses as deep as it is allowed. Using 0 as the
|
|
8
|
+
* marker would make "no recursion" and "full recursion" the same attribute. `rate-in` and
|
|
9
|
+
* `transfer-last` take the same marker for uniformity rather than because 0 is legal for them:
|
|
10
|
+
* depending on a schema minimum I could not measure is exactly the kind of guess that becomes a
|
|
11
|
+
* forever-diff.
|
|
12
|
+
*/
|
|
13
|
+
export declare const UNSET = -1;
|
|
14
|
+
/**
|
|
15
|
+
* A PBS rate limit off the wire, as a plain byte count.
|
|
16
|
+
*
|
|
17
|
+
* ⛔ THE VALUE GOES OUT AS A NUMBER AND COMES BACK AS PROSE. PBS types `rate-in` as a `HumanByte`,
|
|
18
|
+
* which parses `10485760` on the way in and prints something like `10.00 MiB` on the way out, so
|
|
19
|
+
* the two sides of a comparison are never the same string. Flattening both to bytes is what makes
|
|
20
|
+
* the field comparable at all. REASONED from the type's parse/print asymmetry, NOT measured —
|
|
21
|
+
* there was no credential to round-trip one with.
|
|
22
|
+
* ⚠️ IT ROUNDS, AND A RATE THAT DOES NOT DIVIDE EVENLY WILL NEVER SETTLE. `10.00 MiB` carries two
|
|
23
|
+
* decimals, so a declared 10485761 reads back as 10485760, `matches` reports an update, the PUT
|
|
24
|
+
* writes the same rounded value, and the next plan reports it again — forever. Declare a whole
|
|
25
|
+
* multiple of a binary unit. This is the likeliest forever-diff in the family and the first thing
|
|
26
|
+
* to check on the first plan against a live PBS.
|
|
27
|
+
* ⚠️ AN UNPARSEABLE ANSWER READS AS `UNSET`, which for a DECLARED rate means "not equal" and so an
|
|
28
|
+
* update rather than a silent noop. Wrong-but-loud is the right way round here.
|
|
29
|
+
*/
|
|
30
|
+
export declare const bytes: (value: unknown) => number;
|
|
31
|
+
/**
|
|
32
|
+
* The live group filters, joined for a human.
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ DISPLAY ONLY — NEVER SENT, NEVER COMPARED. The ⛔ on the `group-filter` prop says why the field
|
|
35
|
+
* is not declarable; this exists so that a plan against an adopted job SHOWS the filters this
|
|
36
|
+
* resource is deliberately leaving alone, rather than making them invisible.
|
|
37
|
+
* ⚠️ THE SEPARATOR IS ` | `, NOT A COMMA: a `regex:` filter may contain either, so no join here is
|
|
38
|
+
* unambiguous — and a comma is the one that would invite somebody to parse this back.
|
|
39
|
+
*/
|
|
40
|
+
export declare const filters: (value: unknown) => string;
|
|
41
|
+
/**
|
|
42
|
+
* ⛔ `id` IS SENT AND IS NOT OPTIONAL. PBS's create takes it rather than inventing one, so this
|
|
43
|
+
* family avoids backup-job.ts's worst failure by construction — but only while the id is here.
|
|
44
|
+
* A POST without one would be refused rather than silently duplicating the job, which is the
|
|
45
|
+
* better failure, and it is still not a reason to leave it out.
|
|
46
|
+
* ⛔ `sync-direction` IS THE ONE FIELD SENT ONLY ON CREATE. It decides which side `remove-vanished`
|
|
47
|
+
* deletes from, it is not compared (see `matches`), and on a PBS old enough to have no push
|
|
48
|
+
* support it is an unknown parameter — so sending it on every update would turn every deploy
|
|
49
|
+
* against such a server into a 400 over a field nobody was changing.
|
|
50
|
+
*/
|
|
51
|
+
export declare const createBody: (props: SyncJobProps) => Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* ⚠️ THE UPDATE IS THE SHARED HALF AND NOTHING ELSE — no `id` (it is the path), no
|
|
54
|
+
* `sync-direction`, no `delete` list. The factory only PUTs when `matches` is false and the form
|
|
55
|
+
* is non-empty, and this form is never empty because `remove-vanished` and the two store names
|
|
56
|
+
* are always present. That is fine here: reconcile reaches this line only when something really
|
|
57
|
+
* does differ, and re-sending the two store names it just compared is a write of what is already
|
|
58
|
+
* there rather than a change.
|
|
59
|
+
*/
|
|
60
|
+
export declare const updateBody: (props: SyncJobProps) => Record<string, string>;
|
|
61
|
+
export declare const handlers: {
|
|
62
|
+
list: () => import("effect/Effect").Effect<never[], never, never>;
|
|
63
|
+
read: ({ olds }: {
|
|
64
|
+
olds: SyncJobProps;
|
|
65
|
+
}) => import("effect/Effect").Effect<SyncJobAttributes | undefined, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
66
|
+
diff: ({ news, output }: {
|
|
67
|
+
news: import("alchemy").Input<SyncJobProps>;
|
|
68
|
+
output: SyncJobAttributes | undefined;
|
|
69
|
+
}) => import("effect/Effect").Effect<{
|
|
70
|
+
readonly action: 'update';
|
|
71
|
+
} | {
|
|
72
|
+
readonly action: 'noop';
|
|
73
|
+
} | {
|
|
74
|
+
readonly action: 'replace';
|
|
75
|
+
} | undefined, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
76
|
+
reconcile: ({ news }: {
|
|
77
|
+
news: SyncJobProps;
|
|
78
|
+
}) => import("effect/Effect").Effect<SyncJobAttributes, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
79
|
+
delete: ({ olds }: {
|
|
80
|
+
olds: SyncJobProps;
|
|
81
|
+
}) => import("effect/Effect").Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=pbs-sync-job-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pbs-sync-job-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-sync-job-form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAsBzE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,KAAK,CAAC;AAgBxB;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,UAAW,OAAO,KAAG,MAOtC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,UAAW,OAAO,KAAG,MACsD,CAAC;AA0ChG;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,UAAW,YAAY,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAIpE,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,UAAW,YAAY,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAiB,CAAC;AAExF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;CAiFnB,CAAC"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Pbs.SyncJob` — one section of Proxmox Backup Server's `sync.cfg`, declared: a remote datastore's
|
|
3
|
+
* snapshots pulled into a local one on a schedule.
|
|
4
|
+
*
|
|
5
|
+
* ★ IT USES THE SHARED PVE CLIENT, AND THE TYPES STOP THE TWO HOSTS BEING SWAPPED. An earlier
|
|
6
|
+
* draft imported a `./pbs-client.ts` that never existed, arguing that reusing the PVE machinery
|
|
7
|
+
* would COMPILE and that this was the danger — a PBS host accepted wherever a PVE one belongs,
|
|
8
|
+
* every call 401ing, `read` folding that into "absent". The argument was right and the fix is
|
|
9
|
+
* the discriminant rather than a second client: `scheme` is REQUIRED on a target, so a PBS host
|
|
10
|
+
* is not assignable to a PVE resource or the reverse, and the mistake is a compile error. See
|
|
11
|
+
* the ⛔ on `scheme` in credentials.ts.
|
|
12
|
+
*
|
|
13
|
+
* ⛔ THE CREDENTIAL IS A PBS TOKEN AND IT DOES NOT EXIST YET; NO MOUNT NAME IS INVENTED IN THIS
|
|
14
|
+
* FILE. PBS wants `user@realm!tokenname` plus a UUID secret, issued by PBS — a PVE token is not
|
|
15
|
+
* one, whatever it is spelled like. MEASURED from this machine on 2026-09-13: the `claude-code`
|
|
16
|
+
* approle cannot enumerate mounts (`bao secrets list` -> 403) and
|
|
17
|
+
* `bao token capabilities kv/infra/proxmox/pbs` -> `deny`, so I could not confirm from here what
|
|
18
|
+
* does or does not exist. What credentials.ts records is that every PBS token on the kv shelf is
|
|
19
|
+
* READ-ONLY (`Audit`, as `monitoring@pve`) and STATIC — too narrow to create a sync job, and
|
|
20
|
+
* exactly the kind of credential this provider exists to avoid writing with.
|
|
21
|
+
* ★ SO THE MOUNT IS A `PbsTarget.mount` THE STACK SUPPLIES, and somebody has to build it first:
|
|
22
|
+
* a dynamic PBS mount with `read` and `provision` roles mirroring `proxmox-tb4`. Until it
|
|
23
|
+
* exists this family can be declared and cannot be deployed. `permission denied` means the
|
|
24
|
+
* grant is missing — say which mount and role you needed; do not fall back to the shelf token.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ WHAT IS MEASURED AND WHAT IS NOT. MEASURED on 2026-09-13 from this machine, read-only and
|
|
27
|
+
* under STRICT TLS (no `-k`; curl reports `ssl_verify_result` 0):
|
|
28
|
+
* `GET https://pbs.example.com:8007/api2/json/ping` -> HTTP 200 `{"data":{"pong":true}}`. So
|
|
29
|
+
* the host is real, its certificate validates, and PBS WRAPS ITS ANSWER IN THE SAME `{"data": …}`
|
|
30
|
+
* ENVELOPE AS PVE — which is what lets the PVE-shaped client body be reused at all.
|
|
31
|
+
* ⛔ EVERYTHING ELSE BELOW IS DOCUMENTED, FROM PBS'S PUBLISHED API SCHEMA, AND NOT MEASURED — the
|
|
32
|
+
* field list, the parameter spellings, which of them a PUT accepts, the privileges. Without a
|
|
33
|
+
* credential every other endpoint answers 401, and PBS answers 401 BEFORE it routes:
|
|
34
|
+
* `/api2/json/config/nosuchthing` -> 401, not 404 (measured). So the 401 from
|
|
35
|
+
* `/api2/json/config/sync` is not even evidence that the endpoint exists. THE FIRST PLAN
|
|
36
|
+
* AGAINST A LIVE PBS IS THE MEASUREMENT. Read it; do not deploy it unseen.
|
|
37
|
+
* ⚠️ AN ERROR BODY IS NOT WRAPPED: the 401 body is the bare text `authentication failed`, not
|
|
38
|
+
* JSON. `pve()` checks `response.ok` before it parses, so a `pbs()` copied from it is safe —
|
|
39
|
+
* provided the check stays in that order.
|
|
40
|
+
*
|
|
41
|
+
* ⚠️ `Proxmox.BackupJob` AND `Pbs.SyncJob` ARE NOT THE SAME FAMILY AND THE NAMES NEARLY COLLIDE.
|
|
42
|
+
* The first is a PVE vzdump schedule; this is a Proxmox Backup SERVER sync job, on a different
|
|
43
|
+
* host. The `Pbs.` prefix is what keeps them apart in a plan, so it is not shortened.
|
|
44
|
+
*
|
|
45
|
+
* ★ THE SEAM, SINCE IT IS NOT THE USUAL ONE. This file answers "what a sync job is and what it
|
|
46
|
+
* costs to declare one": the props, the attributes, the resource. pbs-sync-job-form.ts answers
|
|
47
|
+
* "how it meets PBS": the coercions, the create and update bodies, and — the part that normally
|
|
48
|
+
* lives here — `matches`. `matches` went with the wire because it is DOWNSTREAM of the wire:
|
|
49
|
+
* ha-rule.ts's rule is that only a field a write can actually set may be compared, so every line
|
|
50
|
+
* of that predicate is an argument about what the PUT accepts. Splitting it from the forms would
|
|
51
|
+
* have put the claim and its evidence in different files. `Provider.of(handlers)` stays HERE, for
|
|
52
|
+
* resource.ts's ⛔: it is the one place the handlers are checked against the concrete resource
|
|
53
|
+
* types, and a cast there would be a lie about whether they match.
|
|
54
|
+
*/
|
|
55
|
+
import { Resource } from 'alchemy';
|
|
56
|
+
import * as Provider from 'alchemy/Provider';
|
|
57
|
+
import type { PveRequirements } from './resource.ts';
|
|
58
|
+
import type { WithPbsTarget } from './resource.ts';
|
|
59
|
+
/**
|
|
60
|
+
* ⚠️ THE PROPS ARE PBS'S OWN PARAMETER NAMES, DASHES INCLUDED, for backup-job.ts's reason: the form
|
|
61
|
+
* builder is then a copy rather than a translation table, and a translation table is one more
|
|
62
|
+
* place for a key to be renamed and silently never sent.
|
|
63
|
+
*/
|
|
64
|
+
export interface SyncJobProps extends WithPbsTarget {
|
|
65
|
+
/**
|
|
66
|
+
* ⛔ PBS'S SECTION ID AND THIS RESOURCE'S KEY, REQUIRED. Unlike a PVE vzdump job PBS does not
|
|
67
|
+
* autogenerate one — `POST /config/sync` takes `id` — so the backup-job.ts failure of creating
|
|
68
|
+
* a second job beside the first on every reconcile cannot happen here. It is still required
|
|
69
|
+
* rather than derived: to adopt a job that exists, declare the id it already has.
|
|
70
|
+
* ⚠️ A PROXMOX SAFE ID — letters, digits, `_`, `.`, `-`, 3 to 32 characters — so there is nothing
|
|
71
|
+
* in it for `path` below to encode.
|
|
72
|
+
*/
|
|
73
|
+
id: string;
|
|
74
|
+
/** The LOCAL datastore the snapshots land in. Required by PBS at create. */
|
|
75
|
+
store: string;
|
|
76
|
+
/** Local namespace, e.g. `tenant/db`. Unset means the root namespace, which PBS spells `''`. */
|
|
77
|
+
ns?: string;
|
|
78
|
+
/**
|
|
79
|
+
* ⛔ A REMOTE BY NAME ONLY. THIS RESOURCE NEVER MODELS THE CREDENTIAL BEHIND IT, and a
|
|
80
|
+
* `Pbs.Remote` family is OUT OF SCOPE for this package rather than merely unwritten:
|
|
81
|
+
* `POST /config/remote` requires `password`, and Alchemy persists props and attributes to its
|
|
82
|
+
* state store UNENCRYPTED (StateEncoding.ts tags Redacted values rather than encrypting them),
|
|
83
|
+
* which here is the `alchemy` Postgres that pg-backup.sh dumps nightly to CT100. A remote's
|
|
84
|
+
* password in a prop is that password in four places, for months. The only Remote resource that
|
|
85
|
+
* could exist would refuse `password` the way storage.ts refuses it — as a `never` — and could
|
|
86
|
+
* therefore never CREATE a remote, which is a resource that cannot do what its name promises.
|
|
87
|
+
* Create remotes out of band (`proxmox-backup-manager remote create`) and name one here.
|
|
88
|
+
* ⚠️ The fingerprint is not the problem: a certificate fingerprint is public. The password is.
|
|
89
|
+
* ⚠️ UNSET MEANS A LOCAL SYNC — datastore to datastore on this same PBS — which is a real and
|
|
90
|
+
* supported mode, not an omission. See `matches`: an unset `remote` is NOT compared, so leaving
|
|
91
|
+
* it out does not claim a job with a remote is local; it claims nothing at all.
|
|
92
|
+
*/
|
|
93
|
+
remote?: string;
|
|
94
|
+
/** The datastore on that remote. Required by PBS at create. */
|
|
95
|
+
'remote-store': string;
|
|
96
|
+
/** Namespace on the remote. Unset means its root namespace. */
|
|
97
|
+
'remote-ns'?: string;
|
|
98
|
+
/**
|
|
99
|
+
* A PBS calendar event — `daily`, `hourly`, `mon..fri 02:30`. Unset means the job runs ONLY when
|
|
100
|
+
* somebody starts it by hand, which is a sync that is not happening; declare one.
|
|
101
|
+
* ⚠️ THIS COMPARES STRINGS, NOT MEANINGS. A calendar event has many equivalent spellings and PBS
|
|
102
|
+
* stores the one it was handed, so declare the spelling the server echoes back.
|
|
103
|
+
*/
|
|
104
|
+
schedule?: string;
|
|
105
|
+
/** Single line only — PBS's comment schema rejects a newline. */
|
|
106
|
+
comment?: string;
|
|
107
|
+
/**
|
|
108
|
+
* ⛔ THIS DELETES SNAPSHOTS. NOT "prunes", NOT "tidies" — DELETES, on a schedule, driven by
|
|
109
|
+
* ANOTHER SERVER'S STATE. On a PULL job (the default), every backup group in the local `store`
|
|
110
|
+
* and `ns` that is no longer on the remote is REMOVED LOCALLY the next time the job runs. The
|
|
111
|
+
* remote decides; this side obeys. Somebody pruning hard on the remote, a remote datastore
|
|
112
|
+
* restored from an older copy, a remote namespace renamed, or a remote that has simply lost
|
|
113
|
+
* data — each of those becomes deletion HERE, and the local copy is usually the copy that was
|
|
114
|
+
* supposed to survive the remote.
|
|
115
|
+
* ⛔ AND ON A PUSH JOB IT DELETES ON THE REMOTE INSTEAD — same flag, opposite victim. Read
|
|
116
|
+
* `sync-direction` before reading this one.
|
|
117
|
+
* ⚠️ IT IS COMPARED AND SENT EVEN WHEN UNDECLARED, unlike every other optional field here, and
|
|
118
|
+
* that is deliberate: undeclared means `false`, so adopting a job somebody had switched this on
|
|
119
|
+
* for plans as an UPDATE that switches it off — a real edit, and NOT a free one. It is the
|
|
120
|
+
* direction that does not delete, but a job that was BOUNDING a datastore now grows it, and a
|
|
121
|
+
* full PBS datastore fails every backup on it. The plan says only "update"; read the live job.
|
|
122
|
+
*/
|
|
123
|
+
'remove-vanished'?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* The PBS Authid that owns the synced groups, e.g. `sync@pbs` or `sync@pbs!job1`. Unset leaves
|
|
126
|
+
* the config without one, which PBS reads as `root@pam` AT RUNTIME — so unset and `root@pam` are
|
|
127
|
+
* not the same value in the config even though they behave alike. Owning a group is what lets an
|
|
128
|
+
* Authid prune or delete it, so changing this is a permissions change, not a label.
|
|
129
|
+
* ⚠️ AN AUTHID IS AN IDENTIFIER, NEVER A SECRET — it may name an API token (`user@realm!name`),
|
|
130
|
+
* and the token's VALUE is the secret. This resource stores the name and never the value.
|
|
131
|
+
*/
|
|
132
|
+
owner?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Incoming rate limit in BYTES PER SECOND. Unset means unlimited.
|
|
135
|
+
* ⚠️ DECLARED IN BYTES, STORED AS A HUMAN STRING. PBS types this as a `HumanByte`, so a written
|
|
136
|
+
* `10485760` comes back as something like `10.00 MiB`; `bytes()` in the form file parses both
|
|
137
|
+
* ends back to a byte count so the two can be compared at all. REASONED from the type, NOT
|
|
138
|
+
* measured — I had no credential to round-trip one.
|
|
139
|
+
* ⛔ DECLARE A VALUE PBS CAN PRINT EXACTLY — a whole multiple of a binary unit. A rate that
|
|
140
|
+
* rounds in the printed form (10485761) reads back as the rounded value, never equals what was
|
|
141
|
+
* declared, and becomes an update reported on every plan forever. This is the single most
|
|
142
|
+
* likely forever-diff in this file; it is the first thing to check on the first plan.
|
|
143
|
+
* ⚠️ `burst-in`, `rate-out` AND `burst-out` ARE NOT MODELLED. PBS's rate limit is four fields
|
|
144
|
+
* flattened into the job; this resource manages one and leaves the others alone, which is safe
|
|
145
|
+
* because PBS's update assigns only the parameters it was sent.
|
|
146
|
+
*/
|
|
147
|
+
'rate-in'?: number;
|
|
148
|
+
/**
|
|
149
|
+
* How many namespace levels below `remote-ns` to sync, 0 (no recursion) upwards. Unset means PBS
|
|
150
|
+
* recurses as deep as it is allowed — which is MORE data, not less, so it is not a safe default
|
|
151
|
+
* to leave implicit on a job whose target namespace has children.
|
|
152
|
+
*/
|
|
153
|
+
'max-depth'?: number;
|
|
154
|
+
/** Sync only the last N snapshots of each group. Unset means all of them. */
|
|
155
|
+
'transfer-last'?: number;
|
|
156
|
+
/**
|
|
157
|
+
* ⛔ NOT DECLARABLE, AND A COMPILE ERROR RATHER THAN A PROP THAT HALF WORKS — the storage.ts
|
|
158
|
+
* `password` idiom, for two independent reasons, either of which alone would be enough.
|
|
159
|
+
* 1. THE WIRE FORM IS AN ARRAY. PBS takes `group-filter` as a repeated parameter
|
|
160
|
+
* (`group-filter=type:ct&group-filter=regex:^web`), and `pve()`'s form is
|
|
161
|
+
* `Record<string, string>` — one value per key — so a list cannot be expressed at all.
|
|
162
|
+
* 2. NARROWING A FILTER MAY BE A DELETE. Whether `remove-vanished` skips the groups a filter
|
|
163
|
+
* excludes is NOT something I could measure without a credential. If it does not, then
|
|
164
|
+
* editing this field on a job with `remove-vanished` set removes every local group the new
|
|
165
|
+
* filter excludes. A field that MIGHT delete snapshots when changed does not get a
|
|
166
|
+
* half-working prop.
|
|
167
|
+
* ★ IT IS STILL REPORTED in the attributes, so a plan shows the filters a hand-made job carries
|
|
168
|
+
* and this resource never strips them: undeclared is unmanaged, and PBS's update assigns only
|
|
169
|
+
* what it was sent. To make it declarable, fix both halves — a form type that can repeat a
|
|
170
|
+
* key, and a MEASURED answer to (2) — in that order.
|
|
171
|
+
*/
|
|
172
|
+
'group-filter'?: never;
|
|
173
|
+
/**
|
|
174
|
+
* `pull` (default) or `push`. ⛔ IT DECIDES WHICH SIDE `remove-vanished` DELETES FROM. Push also
|
|
175
|
+
* needs a newer PBS: on a server that predates it the parameter is unknown and the create is
|
|
176
|
+
* refused, which is the honest failure.
|
|
177
|
+
* ⚠️ CREATE-ONLY HERE, SO A CHANGED DIRECTION PLANS AS NOOP — see `matches`. That is the
|
|
178
|
+
* deliberately safe half of an unmeasured question: if PBS does accept it on PUT, the cost of
|
|
179
|
+
* this choice is a noop; if PBS refuses it, comparing it would be an update the PUT can never
|
|
180
|
+
* perform, on every plan, forever. Retire the declaration and add another, as user.ts says for
|
|
181
|
+
* `userid`.
|
|
182
|
+
*/
|
|
183
|
+
'sync-direction'?: 'pull' | 'push';
|
|
184
|
+
/**
|
|
185
|
+
* ⚠️ SYNC ONLY SNAPSHOTS THAT HAVE PASSED VERIFICATION. Present on 4.2 (`sync-job update
|
|
186
|
+
* --verified-only <boolean>`, and in its `--delete` enum), and the estate sets it: the parked
|
|
187
|
+
* `sync-all-to-dc` job carries `verified-only: true`, so without this prop that job cannot be
|
|
188
|
+
* declared as it actually is.
|
|
189
|
+
* ⛔ IT PAIRS WITH A VERIFICATION JOB THAT ACTUALLY RUNS. With PBS's defaults a snapshot is
|
|
190
|
+
* verified once and never again — see `rechecks` in pbs-verify-job-form.ts — so `verified-only`
|
|
191
|
+
* on a datastore whose verify job is parked means "sync only what was checked once, long ago".
|
|
192
|
+
*/
|
|
193
|
+
'verified-only'?: boolean;
|
|
194
|
+
}
|
|
195
|
+
export interface SyncJobAttributes {
|
|
196
|
+
/** From the props — it is the path this object was read by. */
|
|
197
|
+
id: string;
|
|
198
|
+
store: string;
|
|
199
|
+
/** `''` is the root namespace, which is also how PBS spells it. */
|
|
200
|
+
ns: string;
|
|
201
|
+
/** `''` means a LOCAL sync — datastore to datastore on this PBS. */
|
|
202
|
+
remote: string;
|
|
203
|
+
'remote-store': string;
|
|
204
|
+
'remote-ns': string;
|
|
205
|
+
/** `''` means the job runs only when somebody starts it. */
|
|
206
|
+
schedule: string;
|
|
207
|
+
comment: string;
|
|
208
|
+
'remove-vanished': boolean;
|
|
209
|
+
/** ⚠️ Absent on the wire means `false`, PBS's own default. */
|
|
210
|
+
'verified-only': boolean;
|
|
211
|
+
/** `''` means no owner in the config, i.e. `root@pam` at runtime. An identifier, never a secret. */
|
|
212
|
+
owner: string;
|
|
213
|
+
/** Bytes per second, or `UNSET` (-1). See `bytes()`. */
|
|
214
|
+
'rate-in': number;
|
|
215
|
+
/** `UNSET` (-1) means unset, which means full recursion. `0` is a real value meaning none. */
|
|
216
|
+
'max-depth': number;
|
|
217
|
+
/** `UNSET` (-1) means all snapshots. */
|
|
218
|
+
'transfer-last': number;
|
|
219
|
+
/**
|
|
220
|
+
* ⚠️ REPORTED, NEVER SENT, NEVER COMPARED — the live filter list joined for display only. See the
|
|
221
|
+
* ⛔ on the prop for why it is not declarable.
|
|
222
|
+
*/
|
|
223
|
+
'group-filter': string;
|
|
224
|
+
/** `pull` or `push`. Reported, never compared — create-only here. */
|
|
225
|
+
'sync-direction': string;
|
|
226
|
+
}
|
|
227
|
+
export interface PbsSyncJob extends Resource<'Pbs.SyncJob', SyncJobProps, SyncJobAttributes, never, PveRequirements> {
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* ⚠️ NO `defaultRemovalPolicy: 'retain'`, and the reasoning is replication-job.ts's. Deleting this
|
|
231
|
+
* object removes a SCHEDULE, not data: every snapshot already synced stays in the local
|
|
232
|
+
* datastore, and PBS's own pruning is a different job. What is lost is freshness — which is
|
|
233
|
+
* destructive in six months rather than today, and is exactly why the plan line deserves reading.
|
|
234
|
+
*/
|
|
235
|
+
export declare const PbsSyncJob: import("alchemy").ResourceClass<PbsSyncJob>;
|
|
236
|
+
/**
|
|
237
|
+
* ⛔ THE EMPTY `list` FROM THE FACTORY STANDS. `GET /config/sync` hands back every sync job an
|
|
238
|
+
* operator ever made in the UI, and adopting one is how a later `alchemy destroy` silently stops
|
|
239
|
+
* a second copy being refreshed. Adoption is an explicit act — declare the `id` you mean.
|
|
240
|
+
* ⚠️ DELETING THE JOB DOES NOT DELETE SNAPSHOTS, AND `remove-vanished` DOES. Those two sentences
|
|
241
|
+
* are the whole risk model of this family and they point opposite ways: the DELETE plan line is
|
|
242
|
+
* safe today and expensive in six months, while a single `remove-vanished: true` is a standing
|
|
243
|
+
* instruction to delete local snapshots whenever another server loses them.
|
|
244
|
+
*/
|
|
245
|
+
export declare const PbsSyncJobProvider: () => import("effect/Layer").Layer<Provider.Provider<PbsSyncJob>, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
246
|
+
//# sourceMappingURL=pbs-sync-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pbs-sync-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-sync-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD;;;;;;;OAOG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;IACvB;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,8DAA8D;IAC9D,eAAe,EAAE,OAAO,CAAC;IACzB,oGAAoG;IACpG,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,gIACgD,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A verification job's props as the form PBS wants, and the one derived string worth reporting.
|
|
3
|
+
*
|
|
4
|
+
* ★ SPLIT OUT OF pbs-verify-job.ts TO KEEP BOTH FILES UNDER THE 250-LINE CAP, on the seam
|
|
5
|
+
* replication-job-form.ts and ha-rule-form.ts already cut: this file answers "how does a
|
|
6
|
+
* declaration become a PBS write, and what do the two filter fields actually mean", and
|
|
7
|
+
* pbs-verify-job.ts answers "what is a verification job and when has it changed". Nothing here
|
|
8
|
+
* reads the host and nothing here decides a diff.
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ THE `import type` BACK TO pbs-verify-job.ts IS A CYCLE ON PAPER ONLY — type-only, erased
|
|
11
|
+
* before anything runs, and `PbsVerifyJobProps` stays public in the file declaring the resource.
|
|
12
|
+
*
|
|
13
|
+
* ⛔ THERE IS NO `disable` FIELD ON A PBS VERIFICATION JOB, AND SHIPPING A PROP FOR ONE WOULD HAVE
|
|
14
|
+
* BEEN THE WORST BUG IN THIS FAMILY. Prune jobs have `disable` and sync jobs have `disable`;
|
|
15
|
+
* `VerificationJobConfig` does not, in the struct, in the API schema, or in the update handler's
|
|
16
|
+
* `DeletableProperty` enum — read at HEAD of pbs-api-types and src/api2/config/verify.rs on
|
|
17
|
+
* 2026-09-13. A `disable` prop would therefore be a prop that either does nothing or 400s the
|
|
18
|
+
* whole call (the create schema has `additional_properties: false`, so an unknown key is
|
|
19
|
+
* rejected with "schema does not allow additional properties"). Either way it would be a
|
|
20
|
+
* declaration saying "verification is paused" that PBS never agreed to. The real off switch is
|
|
21
|
+
* an absent `schedule`.
|
|
22
|
+
* ★ NOW VERIFIED AGAINST THE RUNNING HOST, which this comment previously said it was not.
|
|
23
|
+
* `proxmox-backup-manager verify-job update --help` on the live 4.2 server offers
|
|
24
|
+
* `--comment --delete --digest --ignore-verified --max-depth --ns --outdated-after
|
|
25
|
+
* --read-threads --schedule --store --verify-threads` — no `--disable` — and its `--delete`
|
|
26
|
+
* enum contains `schedule`. Both halves of the claim hold on this estate's actual version.
|
|
27
|
+
* ⚠️ `read-threads` AND `verify-threads` EXIST ON 4.2 AND ARE NOT PROPS HERE. Nothing on this
|
|
28
|
+
* estate sets either, and a prop nobody uses is an abstraction with no user — the same reason
|
|
29
|
+
* `PveSpec.immutable` was backed out. Add them when something needs them.
|
|
30
|
+
*
|
|
31
|
+
* ⛔ `withClears` FROM values.ts IS DELIBERATELY NOT USED HERE, AND USING IT WOULD BREAK EVERY
|
|
32
|
+
* UPDATE. PVE's `delete` is ONE comma-separated string; PBS's is an ARRAY of an enum. MEASURED in
|
|
33
|
+
* proxmox-schema's `do_parse_parameter_strings`: for an `Schema::Array` property each occurrence
|
|
34
|
+
* of the key pushes ONE element, so a form body must REPEAT the key — `delete=ns&delete=comment`.
|
|
35
|
+
* `withClears` emits `delete: 'ns,comment'`, which PBS parses as a single element `"ns,comment"`,
|
|
36
|
+
* which is not a `DeletableProperty` variant, so the call fails with a parameter error. It fails
|
|
37
|
+
* loudly rather than quietly, which is the only good news in it.
|
|
38
|
+
* ★ AND IT COULD NOT BE FIXED IN THIS FILE ANYWAY. `client.ts` types a form as
|
|
39
|
+
* `Record<string, string>` and builds it with `new URLSearchParams(form)`; neither a plain
|
|
40
|
+
* object nor that constructor overload can express a repeated key. Clearing a PBS field needs
|
|
41
|
+
* a client that takes entry pairs. Until one exists, this form SETS and never CLEARS — so an
|
|
42
|
+
* undeclared field is left alone and, in pbs-verify-job.ts, is not compared either.
|
|
43
|
+
*/
|
|
44
|
+
import type { PbsVerifyJobProps } from './pbs-verify-job.ts';
|
|
45
|
+
/**
|
|
46
|
+
* What the live pair actually causes, rendered for a plan line.
|
|
47
|
+
*
|
|
48
|
+
* ⛔ THE DEFAULTS MEAN "VERIFY EACH SNAPSHOT EXACTLY ONCE, EVER", AND THAT IS THE FAILURE THIS
|
|
49
|
+
* WHOLE FAMILY EXISTS TO MAKE VISIBLE. Read from src/backup/verify.rs `verify_filter` and
|
|
50
|
+
* src/server/verify_job.rs at HEAD on 2026-09-13, the filter is:
|
|
51
|
+
*
|
|
52
|
+
* ignore_verified = ignore_verified.unwrap_or(true) // absent means TRUE
|
|
53
|
+
* if !ignore_verified -> verify
|
|
54
|
+
* manifest has no verify state -> verify
|
|
55
|
+
* outdated_after is None -> SKIP, forever
|
|
56
|
+
* days_since_last_verify > outdated_after -> verify
|
|
57
|
+
*
|
|
58
|
+
* So a job created with neither field set — the shape the PBS web UI produces when nobody
|
|
59
|
+
* touches those two boxes — checks every snapshot once on the run after it is written and then
|
|
60
|
+
* never looks at it again. Bit rot that appears a month later is never found. The job stays
|
|
61
|
+
* green the entire time, because a job that verified nothing verified nothing badly.
|
|
62
|
+
*
|
|
63
|
+
* ⚠️ A FAILED PAST VERIFICATION IS SKIPPED TOO. `verify_filter` looks only at whether a verify
|
|
64
|
+
* state EXISTS, never at whether it says Ok or Failed, so a snapshot that failed once is not
|
|
65
|
+
* re-checked by a defaulted job either. Pair that with a prune job and the failure ages out
|
|
66
|
+
* without anyone confirming it.
|
|
67
|
+
*
|
|
68
|
+
* ⛔ `outdated-after: 0` DOES NOT MEAN "NEVER", THOUGH PBS'S OWN STRUCT DOC SAYS IT DOES. That
|
|
69
|
+
* comment — "Reverify snapshots after X days, never if 0" — contradicts the code beside it: the
|
|
70
|
+
* test is `days_since_last_verify > max_age`, so `0` re-verifies everything checked more than a
|
|
71
|
+
* day ago, i.e. very nearly every run. The schema text calls `0` deprecated and the minimum is
|
|
72
|
+
* `0`, so it is accepted. "Never" is the ABSENT value, not the zero — and this resource cannot
|
|
73
|
+
* get a job back to absent (see the ⛔ on `withClears` above), so a declaration that sets
|
|
74
|
+
* `outdated-after` has made a one-way choice. Undo it by hand:
|
|
75
|
+
* `proxmox-backup-manager verify-job update <id> --delete outdated-after`.
|
|
76
|
+
*
|
|
77
|
+
* ⚠️ THE COMPARISON IS INTEGER DAYS SINCE THE LAST RUN'S START, `(now - upid.starttime) / 86400`,
|
|
78
|
+
* and it is strictly greater-than. `outdated-after: 30` therefore re-checks on day 31.
|
|
79
|
+
*/
|
|
80
|
+
export declare const rechecks: (ignoreVerified: boolean, outdatedAfter: number) => string;
|
|
81
|
+
/**
|
|
82
|
+
* The form for create and update alike.
|
|
83
|
+
*
|
|
84
|
+
* ⛔ `schedule: null` OMITS THE KEY, AND ON AN UPDATE THAT DOES NOT CLEAR AN EXISTING ONE. This
|
|
85
|
+
* form SETS and never CLEARS — the ⛔ on `withClears` above is why — so declaring `null` against
|
|
86
|
+
* a job that already has a schedule plans an update that changes nothing, every time. Park a job
|
|
87
|
+
* by hand once and the declaration then describes it truthfully:
|
|
88
|
+
* `proxmox-backup-manager verify-job update <id> --delete schedule`. The honest failure is a
|
|
89
|
+
* plan that keeps asking; the dishonest one would be a form that quietly reported success.
|
|
90
|
+
*
|
|
91
|
+
* ⚠️ `store` AND `ignore-verified` ARE ALWAYS SENT BECAUSE THEY ARE ALWAYS COMPARED.
|
|
92
|
+
* A field compared against a default but not sent as that default is an update reported on every
|
|
93
|
+
* plan that the write never performs — backup-job.ts and replication-job-form.ts both record the
|
|
94
|
+
* same trade. `ignore-verified` is the only one of the three with a PBS-side default, and it is
|
|
95
|
+
* TRUE, so an undeclared prop is sent as `1` rather than left out.
|
|
96
|
+
*
|
|
97
|
+
* ⚠️ THE BOOLEAN IS SPELLED INLINE RATHER THAN THROUGH `flag()` FROM values.ts, AND THAT IS A TYPE
|
|
98
|
+
* FACT RATHER THAN A STYLE ONE. `flag` answers `'1' | '0' | undefined` so that an undeclared
|
|
99
|
+
* field is dropped; here the field must never be dropped, and the `undefined` in its return type
|
|
100
|
+
* is not assignable to a `Record<string, string>` form body.
|
|
101
|
+
*
|
|
102
|
+
* ⚠️ PBS ACCEPTS BOTH `application/x-www-form-urlencoded` AND `application/json` AND NOTHING ELSE —
|
|
103
|
+
* any other content type is rejected outright with "unsupported content type", measured in
|
|
104
|
+
* proxmox-rest-server's `get_request_parameters`. `client.ts` sends the form encoding whenever a
|
|
105
|
+
* body is present, so it is already speaking one of the two. Numbers are stringified here for
|
|
106
|
+
* that reason; PBS parses them back through the integer schema.
|
|
107
|
+
*
|
|
108
|
+
* ⛔ `ns` IS DROPPED WHEN IT IS EMPTY, NOT SENT AS `''`. The empty string IS a legal namespace
|
|
109
|
+
* value — `BACKUP_NS_RE` is wrapped in `(?:…)?`, so it passes the schema and reaches the update
|
|
110
|
+
* handler — and the handler then throws it away at `if !ns.is_root()`. Sending it would look like
|
|
111
|
+
* a write that moves the job to the root namespace and would silently be nothing at all.
|
|
112
|
+
*/
|
|
113
|
+
export declare const shape: (props: PbsVerifyJobProps) => Record<string, string>;
|
|
114
|
+
//# sourceMappingURL=pbs-verify-job-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pbs-verify-job-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,QAAQ,mBAAoB,OAAO,iBAAiB,MAAM,KAAG,MAMzE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,KAAK,UAAW,iBAAiB,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAUpE,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Pbs.VerifyJob` — one section of PBS's `verification.cfg`, declared.
|
|
3
|
+
*
|
|
4
|
+
* ★ THIS IS THE FAMILY THAT ANSWERS "ARE THE BACKUPS ACTUALLY GOOD", AND NOTHING ELSE IN THIS
|
|
5
|
+
* PACKAGE DOES. A datastore reports free space, a prune job reports that it ran, and every
|
|
6
|
+
* snapshot in the store can still be unreadable: PBS learns a chunk has rotted only when
|
|
7
|
+
* something reads it back and checks its digest, and verification is the only thing that does
|
|
8
|
+
* that on a schedule. An undeclared verify job is the reason nobody notices for months — and a
|
|
9
|
+
* green `Proxmox.BackupJob` makes it worse rather than better, because a vzdump job that says
|
|
10
|
+
* "OK" every night is exactly the evidence people stop at.
|
|
11
|
+
*
|
|
12
|
+
* ⛔ THIS FILE CANNOT AUTHENTICATE UNTIL TWO THINGS OUTSIDE IT CHANGE, AND IT IS SHIPPED SAYING SO
|
|
13
|
+
* RATHER THAN SHIPPED LOOKING FINISHED. Both are recorded on `PbsTarget` below:
|
|
14
|
+
* 1. `credentials.ts` has no PBS mint. MEASURED 2026-09-13 from this Mac: the `claude-code`
|
|
15
|
+
* approle is refused `sys/mounts`, `kv/infra/proxmox` and `proxmox-pbs/creds/read` alike —
|
|
16
|
+
* 403 permission denied on all three — so there is no mount to name and none is invented.
|
|
17
|
+
* 2. `client.ts`'s `authorization()` builds a PVE header, and PBS will not accept it. See the
|
|
18
|
+
* ⛔ on `PbsTarget`.
|
|
19
|
+
* Until both land, every call 401s, `pveOperations.read` folds that into "absent", and the plan
|
|
20
|
+
* reports `create` for a job that is plainly there. The deploy then FAILS at the POST rather
|
|
21
|
+
* than clobbering anything — an unauthenticated POST 401s, and an authenticated one is refused
|
|
22
|
+
* because PBS will not take a duplicate section id — so the cost is a LYING PLAN and a broken
|
|
23
|
+
* run, not a lost job. That is still reason enough not to wire it into a stack yet: a plan
|
|
24
|
+
* nobody can trust is its own outage.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ THE SHAPES BELOW ARE READ FROM PUBLISHED SOURCE, NOT MEASURED ON THIS ESTATE. Everything is
|
|
27
|
+
* taken from `pbs-api-types/src/jobs.rs`, `src/api2/config/verify.rs`, `src/server/verify_job.rs`
|
|
28
|
+
* and `src/backup/verify.rs` at HEAD of the Proxmox git mirrors on 2026-09-13. What WAS measured
|
|
29
|
+
* here: `pbs.example.com:8007` and `pbs.mgmt.example.com:8007` both answer HTTP 401 under
|
|
30
|
+
* STRICT TLS (curl `ssl_verify_result=0`), so no `-k` is needed and `client.ts`'s plain `fetch`
|
|
31
|
+
* reaches PBS unchanged. The running host's own schema was NOT read — no credential — so a PBS
|
|
32
|
+
* older than HEAD may differ.
|
|
33
|
+
*/
|
|
34
|
+
import { Resource } from 'alchemy';
|
|
35
|
+
import * as Provider from 'alchemy/Provider';
|
|
36
|
+
import type { PbsTarget } from './credentials.ts';
|
|
37
|
+
import { type PveRequirements } from './resource.ts';
|
|
38
|
+
export interface PbsVerifyJobProps {
|
|
39
|
+
/** ⛔ A PBS host, never a PVE cluster. See `PbsTarget`. */
|
|
40
|
+
target: PbsTarget;
|
|
41
|
+
/**
|
|
42
|
+
* ⛔ The primary key, REQUIRED, and never left to PBS. 3–32 chars of
|
|
43
|
+
* `[A-Za-z0-9_][A-Za-z0-9._-]*`. PBS refuses a duplicate section id outright, which is the loud
|
|
44
|
+
* failure `Proxmox.BackupJob` had to engineer for itself — but only because the id is sent.
|
|
45
|
+
*/
|
|
46
|
+
id: string;
|
|
47
|
+
/** Datastore name, 3–32 safe-id chars. ⚠️ MUTABLE — see the ⚠️ on `matches`. */
|
|
48
|
+
store: string;
|
|
49
|
+
/**
|
|
50
|
+
* ⛔ THE KEY IS REQUIRED AND THE VALUE MAY BE `null`. PBS makes the field optional; this family
|
|
51
|
+
* refuses to let you OMIT it, which is not the same thing. A verification job with no schedule
|
|
52
|
+
* never runs on its own and PBS reports it as perfectly healthy — and an absent schedule is also
|
|
53
|
+
* the only way to turn one off, because there is NO `disable` field on a verification job.
|
|
54
|
+
* ⛔ THAT LAST CLAIM IS NOW MEASURED, not read from source. `proxmox-backup-manager verify-job
|
|
55
|
+
* update --help` on the live 4.2 host lists `--delete
|
|
56
|
+
* ignore-verified|comment|schedule|outdated-after|ns|max-depth|read-threads|verify-threads`
|
|
57
|
+
* and no `--disable` anywhere. So `schedule` is deletable — "parked" is a state PBS supports —
|
|
58
|
+
* and `disable` genuinely does not exist. pbs-verify-job-form.ts said this was read off the
|
|
59
|
+
* source and NOT verified against a running host; it is now verified, on this one.
|
|
60
|
+
* ★ SO `null` MEANS "DELIBERATELY PARKED" AND OMITTING IT IS STILL AN ERROR. The original
|
|
61
|
+
* required-string kept you from declaring verification that never happens, which is right, but
|
|
62
|
+
* it also made a genuinely parked job UNDECLARABLE — and the estate has one: `v-datacenter` is
|
|
63
|
+
* parked because syno1 is powered off, comment and runbook and all. A resource that cannot
|
|
64
|
+
* describe what is really there pushes the operator back to the CLI, which is the failure this
|
|
65
|
+
* package exists to end. Writing `schedule: null` costs a word and says the quiet part out
|
|
66
|
+
* loud; leaving the key out still will not compile.
|
|
67
|
+
* ⚠️ ADOPTING A SCHEDULELESS JOB WITH A SCHEDULE DECLARED GIVES IT ONE ON THE FIRST DEPLOY, which
|
|
68
|
+
* is the intended direction and is still a write nobody asked for in words. `matches` compares
|
|
69
|
+
* `schedule`, the live value reads `''`, so the first reconcile PUTs the declared one and
|
|
70
|
+
* verification starts running that night. Read the first plan against an adopted job.
|
|
71
|
+
* ⚠️ A systemd calendar event. Spelled `daily`, `sat 02:00`, `mon..fri 23:00`. A step expression
|
|
72
|
+
* is legal too and is not written out here: those two characters would close this comment.
|
|
73
|
+
*/
|
|
74
|
+
schedule: string | null;
|
|
75
|
+
/**
|
|
76
|
+
* The namespace to verify, e.g. `tier1/prod`. Omitted means the datastore root.
|
|
77
|
+
* ⛔ NEVER SENT AS THE EMPTY STRING. MEASURED in the update handler: `if !ns.is_root()` — a root
|
|
78
|
+
* namespace on a PUT is accepted by the schema, reaches the handler and is then SILENTLY
|
|
79
|
+
* DISCARDED. A job cannot be moved back to the root namespace by this resource at all; that
|
|
80
|
+
* needs `--delete ns` by hand. So an undeclared `ns` is neither sent nor compared.
|
|
81
|
+
*/
|
|
82
|
+
ns?: string;
|
|
83
|
+
/**
|
|
84
|
+
* How many namespace levels below `ns` to descend. `0` is that level only; PBS's maximum is 7.
|
|
85
|
+
* ⚠️ PBS's own default is FULL recursion (7), not 0. Undeclared means undeclared here: not sent,
|
|
86
|
+
* not compared, because "unset" and "7" are stored differently and only one is reachable.
|
|
87
|
+
*/
|
|
88
|
+
'max-depth'?: number;
|
|
89
|
+
/**
|
|
90
|
+
* ⛔ THE HALF OF THE PAIR THAT DECIDES WHETHER THIS JOB EVER RE-CHECKS ANYTHING. Defaults to
|
|
91
|
+
* TRUE. Read `rechecks` and the ⛔ in pbs-verify-job-form.ts before setting either of these.
|
|
92
|
+
*/
|
|
93
|
+
'ignore-verified'?: boolean;
|
|
94
|
+
/** Days after which a past verification is stale. ⛔ See the pair's ⛔ in the form file. */
|
|
95
|
+
'outdated-after'?: number;
|
|
96
|
+
/** ⚠️ PBS TRIMS IT AND STORES AN EMPTY ONE AS ABSENT, so `' '` reads back as `''`. */
|
|
97
|
+
comment?: string;
|
|
98
|
+
}
|
|
99
|
+
export interface PbsVerifyJobAttributes {
|
|
100
|
+
id: string;
|
|
101
|
+
store: string;
|
|
102
|
+
schedule: string;
|
|
103
|
+
ns: string;
|
|
104
|
+
/** ⚠️ `-1` means "no max-depth in the section". `0` is a real setting meaning no recursion. */
|
|
105
|
+
'max-depth': number;
|
|
106
|
+
'ignore-verified': boolean;
|
|
107
|
+
/** ⚠️ `-1` means "unset", which is NOT `0`. See the ⛔ in the form file. */
|
|
108
|
+
'outdated-after': number;
|
|
109
|
+
comment: string;
|
|
110
|
+
/**
|
|
111
|
+
* ★ WHAT THIS JOB ACTUALLY RE-CHECKS, IN ENGLISH, COMPUTED FROM THE LIVE PAIR. REPORTED, NEVER
|
|
112
|
+
* COMPARED — it is derived from two fields `matches` already compares, so diffing it would
|
|
113
|
+
* double-count them. It exists because the failure this family guards against is a job that
|
|
114
|
+
* looks healthy in every column and verifies each snapshot exactly once, ever; that job reads
|
|
115
|
+
* `never` here. A plan line is the only place anyone will see it.
|
|
116
|
+
*/
|
|
117
|
+
rechecks: string;
|
|
118
|
+
}
|
|
119
|
+
export interface PbsVerifyJob extends Resource<'Pbs.VerifyJob', PbsVerifyJobProps, PbsVerifyJobAttributes, never, PveRequirements> {
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* ⚠️ NO `defaultRemovalPolicy: 'retain'`, DELIBERATELY, AND IT IS THE CLOSER CALL THAN IT LOOKS.
|
|
123
|
+
* The section holds no data — deleting it destroys nothing, the way `Proxmox.BackupJob`'s delete
|
|
124
|
+
* destroys no archives. What it destroys is the CHECKING, silently and permanently, and PBS will
|
|
125
|
+
* not refuse it the way it refuses to remove a datastore in use. `retain` would hide that behind
|
|
126
|
+
* a state-row drop instead of showing it as a plan line, and the plan line is the only warning
|
|
127
|
+
* anyone gets. Pipe `RemovalPolicy.retain()` per declaration where the job must outlive the code.
|
|
128
|
+
*/
|
|
129
|
+
export declare const PbsVerifyJob: import("alchemy").ResourceClass<PbsVerifyJob>;
|
|
130
|
+
/**
|
|
131
|
+
* ⛔ `list` IS EMPTY, INHERITED FROM `pveHandlers`, AND THE REASON IS SHARPER HERE THAN ELSEWHERE.
|
|
132
|
+
* `GET /config/verify` returns every verification job the caller can see, including the
|
|
133
|
+
* ones the PBS installer and a human made. Adopting those would put Alchemy one dropped line
|
|
134
|
+
* away from DELETING a datastore's only verification schedule — and deleting it destroys nothing
|
|
135
|
+
* visible, so the loss is discovered the day a restore fails and there is no verification history
|
|
136
|
+
* to say when the rot started. Adoption stays explicit: declare the existing id.
|
|
137
|
+
*
|
|
138
|
+
* ⚠️ NO `digest` IS SENT ON UPDATE OR DELETE, SO THIS IS LAST-WRITER-WINS. PBS accepts an optional
|
|
139
|
+
* `digest` on both and would refuse a write made against a stale read. Sending one would need a
|
|
140
|
+
* read-then-write window this provider does not have — `pveOperations` reads and writes in two
|
|
141
|
+
* separate calls with two separate mints — so a concurrent edit from the PBS UI is overwritten
|
|
142
|
+
* rather than refused. Same behaviour as every PVE family here; stated because PBS offers better.
|
|
143
|
+
*/
|
|
144
|
+
export declare const PbsVerifyJobProvider: () => import("effect/Layer").Layer<Provider.Provider<PbsVerifyJob>, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
145
|
+
//# sourceMappingURL=pbs-verify-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pbs-verify-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,KAAK,eAAe,EAAe,MAAM,eAAe,CAAC;AAGlE,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,+CAA0C,CAAC;AAuEpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
|