@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,60 @@
|
|
|
1
|
+
/** Mount path without a trailing slash — props and `sys/mounts/<path>` use this shape. */
|
|
2
|
+
export declare const mountPath: (path: string) => string;
|
|
3
|
+
/** Parse a Vault duration string (`15m`, `768h`, `0`) to seconds. */
|
|
4
|
+
export declare const parseDuration: (text: string) => number | undefined;
|
|
5
|
+
/** Seconds from live JSON (`2764800`) or a duration prop (`768h`). */
|
|
6
|
+
export declare const ttlSeconds: (value: unknown) => number | undefined;
|
|
7
|
+
export interface BaoMountProps {
|
|
8
|
+
/** Mount path without trailing slash, as `sys/mounts/<path>` takes it. */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Secrets engine type, e.g. `kv`, `pki`, `openbao-plugin-secrets-cloudflare`. */
|
|
11
|
+
type: string;
|
|
12
|
+
/** Human description — tuned via `sys/mounts/<path>/tune`, as apply-roles.py describe_mounts does. */
|
|
13
|
+
description?: string;
|
|
14
|
+
/** Default lease TTL, e.g. `768h`. */
|
|
15
|
+
defaultLeaseTtl?: string;
|
|
16
|
+
/** Max lease TTL, e.g. `8760h`. */
|
|
17
|
+
maxLeaseTtl?: string;
|
|
18
|
+
/** KV only — sent as `options.version` on enable, as `-version=2` was. Immutable after create. */
|
|
19
|
+
version?: 1 | 2;
|
|
20
|
+
}
|
|
21
|
+
export interface BaoMountAttributes {
|
|
22
|
+
path: string;
|
|
23
|
+
type: string;
|
|
24
|
+
description: string;
|
|
25
|
+
defaultLeaseTtl: string;
|
|
26
|
+
maxLeaseTtl: string;
|
|
27
|
+
/** SHA-256 of the managed fields — safe to persist; see policy.ts. */
|
|
28
|
+
digest: string;
|
|
29
|
+
}
|
|
30
|
+
export declare const attributesOf: (props: BaoMountProps, live: Record<string, unknown>) => BaoMountAttributes;
|
|
31
|
+
/** `sys/mounts/<path>` — read, enable and disable all address the mount here. */
|
|
32
|
+
export declare const readPath: (path: string) => string;
|
|
33
|
+
/**
|
|
34
|
+
* ★ NO TRAILING SLASH NEEDED ON THE WIRE. `bao secrets tune` appended one itself; the server's
|
|
35
|
+
* route `mounts/(?P<path>.+?)/tune$` captures the bare path and `sanitizePath` appends the slash
|
|
36
|
+
* OpenBao stores in sys/mounts (openbao v2.6.2 vault/logical_system_paths.go:4248,
|
|
37
|
+
* vault/logical_system.go:4825-4833).
|
|
38
|
+
*/
|
|
39
|
+
export declare const tunePath: (path: string) => string;
|
|
40
|
+
/**
|
|
41
|
+
* The enable body. `-version=2` on the CLI became `options.version = "2"` (openbao v2.6.2
|
|
42
|
+
* command/secrets_enable.go:278 into api MountInput.Options), so that is what is sent.
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ DESCRIPTION AND TTLs ARE NOT SENT HERE. reconcile tunes them straight after the enable,
|
|
45
|
+
* exactly as the CLI path did, so a create and an update converge through the same call.
|
|
46
|
+
*/
|
|
47
|
+
export declare const enableBody: (props: BaoMountProps) => Record<string, unknown>;
|
|
48
|
+
/**
|
|
49
|
+
* The tune body — only the fields the declaration names.
|
|
50
|
+
*
|
|
51
|
+
* ★ AN OMITTED FIELD IS LEFT ALONE. The server reads an absent TTL as "" and keeps the mount's
|
|
52
|
+
* current value for "" (vault/logical_system.go:1614-1630), and applies `description` only when
|
|
53
|
+
* present (:1725). The CLI sent unset TTL flags as "" and set description only when given
|
|
54
|
+
* (command/secrets_tune.go Visit), so omitting them is the same request.
|
|
55
|
+
*/
|
|
56
|
+
export declare const tuneBody: (props: BaoMountProps) => Record<string, string>;
|
|
57
|
+
/** True when live already matches the declaration on every managed field. */
|
|
58
|
+
export declare const matches: (attributes: BaoMountAttributes, props: BaoMountProps) => boolean;
|
|
59
|
+
export declare const wantsTune: (props: BaoMountProps) => boolean;
|
|
60
|
+
//# sourceMappingURL=mount-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-form.d.ts","sourceRoot":"","sources":["../../src/openbao/mount-form.ts"],"names":[],"mappings":"AAEA,0FAA0F;AAC1F,eAAO,MAAM,SAAS,SAAU,MAAM,WAA6B,CAAC;AAIpE,qEAAqE;AACrE,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAAM,GAAG,SAkBrD,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,MAAM,GAAG,SAIpD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB;AAiBD,eAAO,MAAM,YAAY,UAChB,aAAa,QACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,kBAYF,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,QAAQ,SAAU,MAAM,WAAoC,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,SAAU,MAAM,WAA6B,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,UAAW,aAAa,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CACsB,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,UAAW,aAAa,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAMpE,CAAC;AASF,6EAA6E;AAC7E,eAAO,MAAM,OAAO,eAAgB,kBAAkB,SAAS,aAAa,YAIxB,CAAC;AAErD,eAAO,MAAM,SAAS,UAAW,aAAa,YAGb,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OpenBao calls Bao.Mount makes — read one mount, enable, tune, disable. Split from mount.ts so
|
|
3
|
+
* the classification of a MISSING mount can be tested against a fake server.
|
|
4
|
+
*
|
|
5
|
+
* ★ ENDPOINTS, READ FROM openbao v2.6.2 api/sys_mounts.go — the client the CLI used:
|
|
6
|
+
* read GET sys/mounts/<path> (MountInfo, :254) — what `bao read sys/mounts/<path>` hit
|
|
7
|
+
* enable POST sys/mounts/<path> (Mount, :57) — `bao secrets enable`
|
|
8
|
+
* tune POST sys/mounts/<path>/tune (TuneMount, :201) — `bao secrets tune`
|
|
9
|
+
* disable DELETE sys/mounts/<path> (Unmount, :79) — `bao secrets disable`
|
|
10
|
+
*/
|
|
11
|
+
import * as Effect from 'effect/Effect';
|
|
12
|
+
import { BaoError } from './bao-status.ts';
|
|
13
|
+
import { type BaoMountProps } from './mount-form.ts';
|
|
14
|
+
/** One mount's config (`type`, `description`, `config.*_lease_ttl`), or undefined when absent. */
|
|
15
|
+
export declare const readMountData: (path: string) => Effect.Effect<Record<string, unknown> | undefined, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
16
|
+
export declare const enableMount: (props: BaoMountProps) => Effect.Effect<void, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
17
|
+
export declare const tuneMount: (props: BaoMountProps) => Effect.Effect<void, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
18
|
+
/**
|
|
19
|
+
* ⚠️ THERE IS NO FORCE. The old delete ran `bao secrets disable -force`, and v2.6.2's
|
|
20
|
+
* command/secrets_disable.go defines no `-force` flag, so that argv would have been refused at
|
|
21
|
+
* flag parsing. `Unmount` is a plain DELETE (api/sys_mounts.go:79); nothing else was ever sent.
|
|
22
|
+
*/
|
|
23
|
+
export declare const disableMount: (path: string) => Effect.Effect<void, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
24
|
+
//# sourceMappingURL=mount-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-wire.d.ts","sourceRoot":"","sources":["../../src/openbao/mount-wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EACL,KAAK,aAAa,EAMnB,MAAM,iBAAiB,CAAC;AAsCzB,kGAAkG;AAClG,eAAO,MAAM,aAAa,SAAU,MAAM,uHAMvC,CAAC;AAEJ,eAAO,MAAM,WAAW,UAAW,aAAa,wFACW,CAAC;AAE5D,eAAO,MAAM,SAAS,UAAW,aAAa,wFACW,CAAC;AAE1D;;;;GAIG;AACH,eAAO,MAAM,YAAY,SAAU,MAAM,wFAA8B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An OpenBao secrets engine mount — path, type, description and lease TTLs.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ NO SECRET IN PROPS OR ATTRIBUTES — see policy.ts for why. This declares mount
|
|
5
|
+
* SHAPE only: names, types, TTL strings and a digest. KV values and CA material live
|
|
6
|
+
* in OpenBao, not Alchemy state.
|
|
7
|
+
*
|
|
8
|
+
* ★ `defaultRemovalPolicy: 'retain'` — disabling a mount destroys every secret under it.
|
|
9
|
+
* Opt in with `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.
|
|
10
|
+
*/
|
|
11
|
+
import { Resource } from 'alchemy';
|
|
12
|
+
import * as Provider from 'alchemy/Provider';
|
|
13
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
14
|
+
import { type BaoMountAttributes, type BaoMountProps } from './mount-form.ts';
|
|
15
|
+
export type { BaoMountAttributes, BaoMountProps };
|
|
16
|
+
export interface BaoMount extends Resource<'Bao.Mount', BaoMountProps, BaoMountAttributes, never, HttpClient.HttpClient> {
|
|
17
|
+
}
|
|
18
|
+
export declare const BaoMount: import("alchemy").ResourceClass<BaoMount>;
|
|
19
|
+
export declare const BaoMountProvider: () => import("effect/Layer").Layer<Provider.Provider<BaoMount>, never, HttpClient.HttpClient>;
|
|
20
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/openbao/mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AACnE,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAKnB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAElD,MAAM,WAAW,QAAS,SAAQ,QAAQ,CACxC,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,UAAU,CAAC,UAAU,CACtB;CAAG;AAEJ,eAAO,MAAM,QAAQ,2CAEnB,CAAC;AASH,eAAO,MAAM,gBAAgB,+FAqF1B,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/** ★ MEASURED: the OpenAPI enum for `key_type` is exactly these four, lowercase. */
|
|
2
|
+
export type BaoPkiKeyType = 'any' | 'ec' | 'ed25519' | 'rsa';
|
|
3
|
+
/** ★ MEASURED: live roles carry `["hostname"]` or the default `["email","hostname"]`. */
|
|
4
|
+
export type BaoPkiCnValidation = 'disabled' | 'email' | 'hostname';
|
|
5
|
+
export interface BaoPkiRoleProps {
|
|
6
|
+
/** Role name, as `pki/roles/{name}` takes it. */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Mount holding the engine. Defaults to `pki` — the only PKI mount live today. */
|
|
9
|
+
mount?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Domains this role may issue for.
|
|
12
|
+
*
|
|
13
|
+
* ⛔ AN EMPTY LIST IS REFUSED IN reconcile, NOT WRITTEN. With `allow_any_name` false — the
|
|
14
|
+
* default, and what all eight live roles use — a role with no allowed domains can issue
|
|
15
|
+
* nothing, so a mistyped or unresolved prop would quietly brick every renewal under it.
|
|
16
|
+
*/
|
|
17
|
+
allowedDomains: readonly string[];
|
|
18
|
+
/** Permit `foo.<allowed domain>`. Default false. */
|
|
19
|
+
allowSubdomains?: boolean;
|
|
20
|
+
/** Permit the allowed domain itself as the CN. Default false. */
|
|
21
|
+
allowBareDomains?: boolean;
|
|
22
|
+
/** Treat `*` inside an allowed domain as a glob. Default false. */
|
|
23
|
+
allowGlobDomains?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Default certificate lifetime, as a duration string (`720h`).
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ WRITTEN AS A DURATION, READ BACK AS SECONDS — `ttl` and `max_ttl` both carry
|
|
28
|
+
* `format: seconds` in the OpenAPI and come back as integers (`2592000`). The prop
|
|
29
|
+
* string reaches `bao write` verbatim; the compare happens in seconds. See canonical().
|
|
30
|
+
*/
|
|
31
|
+
ttl: string;
|
|
32
|
+
/** Ceiling on a requested lifetime, as a duration string (`8760h`). */
|
|
33
|
+
maxTtl: string;
|
|
34
|
+
/** Key algorithm. Default `rsa` — OpenBao's own default. */
|
|
35
|
+
keyType?: BaoPkiKeyType;
|
|
36
|
+
/** Key size; `0` means "engine default for keyType". rsa 2048/3072/4096, ec 224/256/384/521. */
|
|
37
|
+
keyBits?: number;
|
|
38
|
+
/** Flag certificates for TLS server auth. ⚠️ OpenBao defaults this TRUE. */
|
|
39
|
+
serverFlag?: boolean;
|
|
40
|
+
/** Flag certificates for TLS client auth. ⚠️ OpenBao defaults this TRUE. */
|
|
41
|
+
clientFlag?: boolean;
|
|
42
|
+
/** Extended key usages minus the `ExtKeyUsage` prefix (`ServerAuth`). Empty on all 8 live roles. */
|
|
43
|
+
extKeyUsage?: readonly string[];
|
|
44
|
+
/** Permit IP SANs. ⚠️ OpenBao defaults TRUE; this resource defaults FALSE — see pki-role.ts. */
|
|
45
|
+
allowIpSans?: boolean;
|
|
46
|
+
/** Permit `localhost`/`localdomain` CNs. ⚠️ OpenBao TRUE, this resource FALSE. */
|
|
47
|
+
allowLocalhost?: boolean;
|
|
48
|
+
/** Permit wildcard CNs. ⚠️ OpenBao TRUE, this resource FALSE. */
|
|
49
|
+
allowWildcardCertificates?: boolean;
|
|
50
|
+
/** CN validations to run. ⚠️ OpenBao `["email","hostname"]`, this resource `["hostname"]`. */
|
|
51
|
+
cnValidations?: readonly BaoPkiCnValidation[];
|
|
52
|
+
/** Signature hash bits; `0` auto-detects from key length. One live role pins 256. */
|
|
53
|
+
signatureBits?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The managed field set, normalised so both sides of a diff are byte-comparable.
|
|
57
|
+
*
|
|
58
|
+
* ⚠️ KEY ORDER IS THE DIGEST. The props side and the live side are both built by the single
|
|
59
|
+
* canonical() literal below, so `JSON.stringify` emits the same key order for each. Two
|
|
60
|
+
* hand-written object literals would drift apart and produce a forever-diff nobody could
|
|
61
|
+
* read from the plan output.
|
|
62
|
+
*/
|
|
63
|
+
export interface BaoPkiRoleCanonical {
|
|
64
|
+
allowBareDomains: boolean;
|
|
65
|
+
allowGlobDomains: boolean;
|
|
66
|
+
allowIpSans: boolean;
|
|
67
|
+
allowLocalhost: boolean;
|
|
68
|
+
allowSubdomains: boolean;
|
|
69
|
+
allowWildcardCertificates: boolean;
|
|
70
|
+
allowedDomains: readonly string[];
|
|
71
|
+
clientFlag: boolean;
|
|
72
|
+
cnValidations: readonly string[];
|
|
73
|
+
extKeyUsage: readonly string[];
|
|
74
|
+
keyBits: number;
|
|
75
|
+
keyType: string;
|
|
76
|
+
/** ⚠️ `-1` means the duration prop did not parse — reconcile refuses rather than writing it. */
|
|
77
|
+
maxTtlSeconds: number;
|
|
78
|
+
serverFlag: boolean;
|
|
79
|
+
signatureBits: number;
|
|
80
|
+
ttlSeconds: number;
|
|
81
|
+
}
|
|
82
|
+
export interface BaoPkiRoleAttributes extends BaoPkiRoleCanonical {
|
|
83
|
+
name: string;
|
|
84
|
+
mount: string;
|
|
85
|
+
/** Human rendering of ttlSeconds — the compare uses the seconds, this is for the plan. */
|
|
86
|
+
ttl: string;
|
|
87
|
+
maxTtl: string;
|
|
88
|
+
/** SHA-256 of the canonical form — safe to persist; see policy.ts. */
|
|
89
|
+
digest: string;
|
|
90
|
+
}
|
|
91
|
+
export declare const canonicalFromProps: (props: BaoPkiRoleProps) => BaoPkiRoleCanonical;
|
|
92
|
+
export declare const canonicalFromLive: (live: Record<string, unknown>) => BaoPkiRoleCanonical;
|
|
93
|
+
export declare const digestOf: (form: BaoPkiRoleCanonical) => string;
|
|
94
|
+
export declare const rolePath: (props: {
|
|
95
|
+
name: string;
|
|
96
|
+
mount?: string;
|
|
97
|
+
}) => string;
|
|
98
|
+
export declare const attributesOf: (props: BaoPkiRoleProps, live: Record<string, unknown>) => BaoPkiRoleAttributes;
|
|
99
|
+
/**
|
|
100
|
+
* ⚠️ ARRAYS GO OVER AS COMMA-JOINED STRINGS. `allowed_domains` and `ext_key_usage` are
|
|
101
|
+
* documented as "a comma-separated string or list"; `cn_validations` is not, so its
|
|
102
|
+
* splitting is REASONED, not measured. reconcile re-reads and re-compares after every
|
|
103
|
+
* write, so a value that arrived unsplit fails loudly instead of landing wrong.
|
|
104
|
+
*
|
|
105
|
+
* ⚠️ TTLs GO OVER AS THE AUTHOR'S OWN DURATION STRING, never as a re-rendered one — so this
|
|
106
|
+
* never has to know whether OpenBao's parser accepts the `d` suffix ttlText() produces for
|
|
107
|
+
* display. Rendering is for humans; the wire only ever sees what was declared.
|
|
108
|
+
*
|
|
109
|
+
* ★ `ext_key_usage` is OMITTED when empty rather than sent as `ext_key_usage=`. The write
|
|
110
|
+
* replaces the whole role, so an absent field already lands on the `[]` default, and
|
|
111
|
+
* omitting sidesteps how an empty value would be encoded.
|
|
112
|
+
*
|
|
113
|
+
* ★ THE BODY FOR `PUT <mount>/roles/<name>`, ALL STRINGS — the same `k=v` pairs `bao write` sent.
|
|
114
|
+
*/
|
|
115
|
+
export declare const writeBody: (props: BaoPkiRoleProps) => Record<string, string>;
|
|
116
|
+
/** True when live already matches the declaration on every managed field. */
|
|
117
|
+
export declare const matches: (attributes: BaoPkiRoleAttributes, props: BaoPkiRoleProps) => boolean;
|
|
118
|
+
//# sourceMappingURL=pki-role-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pki-role-form.d.ts","sourceRoot":"","sources":["../../src/openbao/pki-role-form.ts"],"names":[],"mappings":"AAGA,oFAAoF;AACpF,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7D,yFAAyF;AACzF,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,gGAAgG;IAChG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oGAAoG;IACpG,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,gGAAgG;IAChG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kFAAkF;IAClF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,8FAA8F;IAC9F,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC9C,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,yBAAyB,EAAE,OAAO,CAAC;IACnC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB;AA8BD,eAAO,MAAM,kBAAkB,UAAW,eAAe,KAAG,mBAkBxD,CAAC;AAYL,eAAO,MAAM,iBAAiB,SAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,mBAkB9D,CAAC;AAWL,eAAO,MAAM,QAAQ,SAAU,mBAAmB,WAAiC,CAAC;AAEpF,eAAO,MAAM,QAAQ,UAAW;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,WACN,CAAC;AAE3D,eAAO,MAAM,YAAY,UAChB,eAAe,QAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,oBAUF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,UAAW,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAsBvE,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,OAAO,eAAgB,oBAAoB,SAAS,eAAe,YACrB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An OpenBao PKI role — the policy a future issuance is checked against, and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ THE ROLE IS THE POLICY, NEVER THE CERTIFICATE. Nothing here touches `pki/issue/*` (which
|
|
5
|
+
* RETURNS a private key) or `pki/root/generate/*` (which CREATES one). Every value this
|
|
6
|
+
* resource stores is a domain name, a flag, a bit count or a TTL — safe to sit in Alchemy's
|
|
7
|
+
* UNENCRYPTED Postgres state. See policy.ts for why that line is load-bearing here.
|
|
8
|
+
*
|
|
9
|
+
* ⛔ `bao write pki/roles/<name>` REPLACES THE WHOLE ROLE — it is not a merge. OpenBao builds
|
|
10
|
+
* a fresh role entry from the request, so every field left out reverts to its SCHEMA
|
|
11
|
+
* DEFAULT. MEASURED 2026-09-13 against the live OpenBao 2.6.2, from its own
|
|
12
|
+
* `sys/internal/specs/openapi` cross-read against all eight live `pki/roles/*`, four of
|
|
13
|
+
* those defaults are WIDER than what this estate actually runs:
|
|
14
|
+
*
|
|
15
|
+
* allow_ip_sans default true — false on 5 of the 8 roles
|
|
16
|
+
* allow_localhost default true — false on 6 of the 8
|
|
17
|
+
* allow_wildcard_certificates default true — false on 6 of the 8
|
|
18
|
+
* cn_validations default ["email","hostname"] — ["hostname"] on 5 of the 8
|
|
19
|
+
*
|
|
20
|
+
* A resource that managed only the eleven fields the brief named would therefore, on any
|
|
21
|
+
* unrelated TTL edit, silently re-open wildcards and localhost on six production roles.
|
|
22
|
+
* That is why those four are props in pki-role-form.ts though they were not in the brief,
|
|
23
|
+
* and why their default there is the CLOSED value rather than OpenBao's open one.
|
|
24
|
+
*
|
|
25
|
+
* ★ NARROWING IS THE FAIL-SAFE DIRECTION. A default tighter than OpenBao's can only refuse a
|
|
26
|
+
* certificate that should have been issued — loud, and cured by declaring the field. A
|
|
27
|
+
* default looser than OpenBao's issues one that should have been refused, in silence.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ WHAT WAS NOT MEASURED. Only reads were run against the live engine; no `bao write`
|
|
30
|
+
* happened, so nothing below is a verified round-trip. Two consequences carried into the
|
|
31
|
+
* form file: every live role has `ext_key_usage: []`, so the stored casing of a non-empty
|
|
32
|
+
* list was never observed (the compare folds case because OpenBao matches these
|
|
33
|
+
* case-insensitively at issuance); and every live role has exactly ONE allowed domain, so
|
|
34
|
+
* whether OpenBao preserves list order was never observed either (the compare sorts,
|
|
35
|
+
* because allowed_domains is a set). Both choices can only mask a cosmetic difference,
|
|
36
|
+
* never a policy one — but neither is a measurement.
|
|
37
|
+
*
|
|
38
|
+
* ★ `defaultRemovalPolicy: 'retain'` — see the delete comment below. Opt in with
|
|
39
|
+
* `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.
|
|
40
|
+
*/
|
|
41
|
+
import { Resource } from 'alchemy';
|
|
42
|
+
import * as Provider from 'alchemy/Provider';
|
|
43
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
44
|
+
import { type BaoPkiRoleAttributes, type BaoPkiRoleProps } from './pki-role-form.ts';
|
|
45
|
+
export type { BaoPkiRoleAttributes, BaoPkiRoleProps };
|
|
46
|
+
export interface BaoPkiRole extends Resource<'Bao.PkiRole', BaoPkiRoleProps, BaoPkiRoleAttributes, never, HttpClient.HttpClient> {
|
|
47
|
+
}
|
|
48
|
+
export declare const BaoPkiRole: import("alchemy").ResourceClass<BaoPkiRole>;
|
|
49
|
+
export declare const BaoPkiRoleProvider: () => import("effect/Layer").Layer<Provider.Provider<BaoPkiRole>, never, HttpClient.HttpClient>;
|
|
50
|
+
//# sourceMappingURL=pki-role.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pki-role.d.ts","sourceRoot":"","sources":["../../src/openbao/pki-role.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAGnE,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,eAAe,EAKrB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,CAAC;AAEtD,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,KAAK,EACL,UAAU,CAAC,UAAU,CACtB;CAAG;AAEJ,eAAO,MAAM,UAAU,6CAErB,CAAC;AAeH,eAAO,MAAM,kBAAkB,iGAsH5B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether an assembled policy would carry NO GRANT — the one write `Bao.Policy` must refuse.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ EMPTY MEANS NO `path` GRANT, NOT NO FILES. Writing `sys/policies/acl/<name>` with nothing in it
|
|
5
|
+
* SILENTLY REVOKES every grant the policy carries, for every token bound to it. The first guard
|
|
6
|
+
* only counted fragment files, so a directory whose one fragment was empty, whitespace or
|
|
7
|
+
* comments — a truncated edit, a bad checkout — assembled to text with no grant in it, passed,
|
|
8
|
+
* and would have replaced the live policy with nothing. Found by grok's review on 2026-09-14.
|
|
9
|
+
* ★ A GRANT IS A `path "…"` STANZA, the unit apply-agent-policy.sh counts and `grantsOf` in
|
|
10
|
+
* policy.ts reports. Leading whitespace is allowed here, so an indented stanza still counts.
|
|
11
|
+
*/
|
|
12
|
+
export declare const isEmptyAssembly: (parts: number, joined: string) => boolean;
|
|
13
|
+
//# sourceMappingURL=policy-assembly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-assembly.d.ts","sourceRoot":"","sources":["../../src/openbao/policy-assembly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,UAAW,MAAM,UAAU,MAAM,KAAG,OAClB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three OpenBao calls Bao.Policy makes — read, write and delete of `sys/policies/acl/<name>`.
|
|
3
|
+
* Split from policy.ts so the trailing-newline round trip can be tested against a fake server.
|
|
4
|
+
*/
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import { BaoError } from './bao-status.ts';
|
|
7
|
+
/** The endpoint the CLI's policy commands used — openbao v2.6.2 api/sys_policy.go:60, :100, :122. */
|
|
8
|
+
export declare const policyPath: (name: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* The live policy text, or '' when the policy is genuinely absent. Anything else FAILS.
|
|
11
|
+
*
|
|
12
|
+
* 🔴 THE ABSENCE WORDING WAS THE POLICY COMMAND'S OWN, AND ASSUMING OTHERWISE MADE A NEW POLICY
|
|
13
|
+
* UNCREATABLE. `No value found at` was measured for `bao read`; `bao policy read` never printed
|
|
14
|
+
* it. Its API client turned a 404 into an empty string and the CLI reported that in its own
|
|
15
|
+
* words — openbao v2.6.2 api/sys_policy.go:65-67 and command/policy_read.go:85-87:
|
|
16
|
+
*
|
|
17
|
+
* No policy named: <name> exit 2
|
|
18
|
+
*
|
|
19
|
+
* So `read` on a policy that did not exist yet FAILED instead of answering absent, and
|
|
20
|
+
* `reconcile` failed at its own pre-write read. Every policy declared so far already existed,
|
|
21
|
+
* which is the only reason nothing broke. MEASURED 2026-09-14 under the admin lane —
|
|
22
|
+
* `bao policy read zz-probe-absent-policy-4c1e` printed exactly that line and exited 2. (The
|
|
23
|
+
* agent lane cannot measure it: it is refused `sys/policies/acl` with a 403 first.)
|
|
24
|
+
* ★ THE WORDING PROBLEM IS GONE WITH THE CLI. The line above was the CLI's rendering of the 404 that
|
|
25
|
+
* the server returns for a missing policy (vault/logical_system.go handlePoliciesRead returns no
|
|
26
|
+
* response, which RespondErrorCommon turns into 404). That status is now read directly, and a
|
|
27
|
+
* refused read is a 403 — two codes, no text to confuse.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ `data.policy` IS THE TEXT, and a 200 without it is a failure, as it was in the CLI's client
|
|
30
|
+
* ("no policy found in response", api/sys_policy.go:81-85).
|
|
31
|
+
*/
|
|
32
|
+
export declare const readPolicy: (name: string) => Effect.Effect<string, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
33
|
+
/**
|
|
34
|
+
* ★ THE HCL TRAVELS IN THE REQUEST BODY (`{"policy": …}`, api/sys_policy.go:96-101). The CLI path
|
|
35
|
+
* needed a scoped temp file because passing HCL on argv would have put every grant in the process
|
|
36
|
+
* list; a JSON body never reaches argv, so the temp file is gone with it.
|
|
37
|
+
*/
|
|
38
|
+
export declare const writePolicy: (name: string, hcl: string) => Effect.Effect<void, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
39
|
+
/** Deleting a policy that is already gone answers success (handlePoliciesDelete returns nothing). */
|
|
40
|
+
export declare const deletePolicy: (name: string) => Effect.Effect<void, BaoError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
41
|
+
//# sourceMappingURL=policy-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-wire.d.ts","sourceRoot":"","sources":["../../src/openbao/policy-wire.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,qGAAqG;AACrG,eAAO,MAAM,UAAU,SAAU,MAAM,WAA+B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,UAAU,SAAU,MAAM,0FAOnC,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,WAAW,SAAU,MAAM,OAAO,MAAM,wFACD,CAAC;AAErD,qGAAqG;AACrG,eAAO,MAAM,YAAY,SAAU,MAAM,wFAAgC,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Resource } from 'alchemy';
|
|
2
|
+
import * as Provider from 'alchemy/Provider';
|
|
3
|
+
import * as FileSystem from 'effect/FileSystem';
|
|
4
|
+
import * as Path from 'effect/Path';
|
|
5
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
6
|
+
/**
|
|
7
|
+
* An OpenBao ACL policy, assembled from the HCL fragments that declare it.
|
|
8
|
+
*
|
|
9
|
+
* ★ WHY THIS EXISTS. The estate already hand-rolled both halves of what Alchemy provides:
|
|
10
|
+
* five `apply-*.sh`/`apply-*.py` scripts converge OpenBao, and separate `check-*.sh`
|
|
11
|
+
* gates compare live to repo and refuse on drift. That is `reconcile` and `diff` written
|
|
12
|
+
* twice, in two languages, with nothing recording what was applied — and one of those
|
|
13
|
+
* gates blocked a deploy today because its own path had rotted.
|
|
14
|
+
*
|
|
15
|
+
* ⛔ THERE IS NO `Bao.Secret`, AND THERE MUST NEVER BE ONE. Alchemy persists attributes to
|
|
16
|
+
* its state store and does NOT encrypt them: StateEncoding.ts unwraps `Redacted` to
|
|
17
|
+
* plaintext under a marker key, and nothing under alchemy/src/State encrypts. This
|
|
18
|
+
* estate's state store is the `alchemy` Postgres database, which pg-backup.sh dumps
|
|
19
|
+
* nightly (it enumerates EVERY non-template database), copies to CT100, and PBS backs up
|
|
20
|
+
* from there. A KV value here would exist in four places, none of them OpenBao.
|
|
21
|
+
*
|
|
22
|
+
* So this declares the SHAPE AROUND secrets. Every attribute it stores is a name, a
|
|
23
|
+
* count, or a hash.
|
|
24
|
+
*
|
|
25
|
+
* ⛔ EVERY PRIMITIVE IS ALCHEMY'S OR EFFECT'S, NOT NODE'S. An earlier cut of this file used
|
|
26
|
+
* `node:child_process` + `promisify(execFile)` and `node:fs/promises`, which is
|
|
27
|
+
* hand-rolling inside a bun + Effect codebase: it loses the Scope, the typed
|
|
28
|
+
* PlatformError, and the Layer that makes the provider testable without a real vault.
|
|
29
|
+
* ★ `CommandExecutor.run` was tried first and blocked read/diff: Alchemy passes a session
|
|
30
|
+
* to reconcile/delete but NOT to read/diff (Provider.ts:258-289), so the fix was Alchemy's
|
|
31
|
+
* OWN Docker pattern — `ChildProcessSpawner` + `ChildProcess.make`, which needs only a
|
|
32
|
+
* Scope (Docker.ts:476-553). ★ SINCE 2026-09-14 THE CALLS ARE OpenBao's HTTP API through
|
|
33
|
+
* Effect's `HttpClient` (bao-http.ts), which needs no session either, so read/diff still work.
|
|
34
|
+
* FileSystem and Path come from `effect/*` directly — in Effect 4 they moved into core.
|
|
35
|
+
*/
|
|
36
|
+
export interface BaoPolicyProps {
|
|
37
|
+
/** Policy name, as `sys/policies/acl/<name>` takes it. */
|
|
38
|
+
name: string;
|
|
39
|
+
/**
|
|
40
|
+
* Directory of `*.hcl` fragments.
|
|
41
|
+
*
|
|
42
|
+
* ⚠️ CONCATENATED IN SORTED ORDER, EACH FOLLOWED BY A NEWLINE — byte-identical to
|
|
43
|
+
* apply-agent-policy.sh, which is what wrote the live policy. Any other joining makes
|
|
44
|
+
* the first plan report an update on a policy nobody changed.
|
|
45
|
+
*/
|
|
46
|
+
fragments: string;
|
|
47
|
+
}
|
|
48
|
+
export interface BaoPolicyAttributes {
|
|
49
|
+
/** Policy name. */
|
|
50
|
+
name: string;
|
|
51
|
+
/** SHA-256 of the assembled HCL. The whole diff, and safe to persist. */
|
|
52
|
+
digest: string;
|
|
53
|
+
/** `path "..."` grants — the number apply-agent-policy.sh prints. */
|
|
54
|
+
grants: number;
|
|
55
|
+
/** Fragment files that produced it, so a plan reads like the directory. */
|
|
56
|
+
parts: number;
|
|
57
|
+
}
|
|
58
|
+
export interface BaoPolicy extends Resource<'Bao.Policy', BaoPolicyProps, BaoPolicyAttributes, never, HttpClient.HttpClient | FileSystem.FileSystem | Path.Path> {
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* ⛔ `retain` — DELETING A POLICY REVOKES EVERY GRANT IT CARRIES, and this is the ONLY family in
|
|
62
|
+
* this package with live instances, so it is the only one where the default could ever fire.
|
|
63
|
+
*
|
|
64
|
+
* 🔴 IT WAS THE ONLY FAMILY WITHOUT IT. Every sibling passes `{ defaultRemovalPolicy: 'retain' }`
|
|
65
|
+
* — auth-role.ts:37, mount.ts:40, pki-role.ts, proxmox-role.ts, ssh-role.ts — each with a ★
|
|
66
|
+
* explaining what deletion destroys. This file has the same warning on its own `delete` handler
|
|
67
|
+
* and did not carry the option, which is the worst possible combination: the danger is
|
|
68
|
+
* documented and the guard is missing.
|
|
69
|
+
* ⛔ WHAT THAT MEANT IN PRACTICE, on 2026-09-13: ten live policies are named in a `const` array
|
|
70
|
+
* in alchemy.run.ts. Removing a name from that array orphans the resource, and without
|
|
71
|
+
* `retain` the next deploy calls `bao policy delete` on it — including the 86-line policy that
|
|
72
|
+
* decides what the agent working in this repo can reach. A one-word edit, no plan line saying
|
|
73
|
+
* "revoke", and the grants are gone. The array grew from four names to ten that same day,
|
|
74
|
+
* which multiplied the blast radius of a mistake nobody had guarded against.
|
|
75
|
+
*
|
|
76
|
+
* ⚠️ `retain` DOES NOT WEAKEN `delete`, WHICH STAYS FULLY IMPLEMENTED. The engine skips it for an
|
|
77
|
+
* orphaned resource; a caller that means it opts in with `.pipe(RemovalPolicy.destroy())`. This
|
|
78
|
+
* is Terraform's `prevent_destroy`, not a stubbed operation — a delete that silently did nothing
|
|
79
|
+
* would lie to whoever read the plan.
|
|
80
|
+
*/
|
|
81
|
+
export declare const BaoPolicy: import("alchemy").ResourceClass<BaoPolicy>;
|
|
82
|
+
export declare const BaoPolicyProvider: () => import("effect/Layer").Layer<Provider.Provider<BaoPolicy>, never, FileSystem.FileSystem | HttpClient.HttpClient | Path.Path>;
|
|
83
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/openbao/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAKnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ,CACzC,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,KAAK,EACL,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1D;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,4CAEpB,CAAC;AAYH,eAAO,MAAM,iBAAiB,oIAuG3B,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export interface BaoProxmoxRoleProps {
|
|
2
|
+
/** Mount path of the proxmox secrets engine, e.g. `proxmox-tb4`. A trailing slash is fine. */
|
|
3
|
+
mount: string;
|
|
4
|
+
/**
|
|
5
|
+
* Role name, as `<mount>/roles/<name>` takes it.
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ The plugin's own schema says the name "Appears in the minted token's id, so keep it
|
|
8
|
+
* short." Both live roles are one word (`read`, `provision`). A long name here becomes a
|
|
9
|
+
* long PVE token id on every mint.
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* ⛔ THE ENTIRE SECURITY BOUNDARY OF THIS RESOURCE. A minted token inherits this PVE user's
|
|
14
|
+
* standing ACL and nothing else — the engine never grants ACLs, it only borrows one. Change
|
|
15
|
+
* this string and every credential the role issues from then on carries a different
|
|
16
|
+
* privilege set, with no other field in the declaration changing to hint at it. That is why
|
|
17
|
+
* it is compared in `matches` below, and why reconcile refuses to move it without
|
|
18
|
+
* `allowMintUserChange`.
|
|
19
|
+
*/
|
|
20
|
+
mintUser: string;
|
|
21
|
+
/** Default lease TTL for minted tokens, e.g. `1h`. REQUIRED — see the ⛔ on writeBody. */
|
|
22
|
+
ttl: string;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum lease TTL, e.g. `6h`. REQUIRED — see the ⛔ on writeBody.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ "Narrows the mount's; can never widen it." A role declaring `6h` under a mount whose
|
|
27
|
+
* max_lease_ttl is `1h` still READS BACK as 21600, so this resource reports noop and the
|
|
28
|
+
* plan is green — while every actual mint is capped at 3600 by the mount. The role is not
|
|
29
|
+
* lying and neither is the plan; the ceiling simply lives one level up. If a consumer gets
|
|
30
|
+
* a shorter lease than declared here, check `bao read sys/mounts/<mount>` before touching
|
|
31
|
+
* the role.
|
|
32
|
+
*/
|
|
33
|
+
maxTtl: string;
|
|
34
|
+
/**
|
|
35
|
+
* Permission to re-scope `mintUser` on an EXISTING role: set it to the CURRENT live mint_user
|
|
36
|
+
* that this change is allowed to replace.
|
|
37
|
+
*
|
|
38
|
+
* ★ IT IS A STRING AND NOT A BOOLEAN, AND THAT IS THE WHOLE POINT. A `true` left behind after
|
|
39
|
+
* one legitimate rename would wave through every future re-scope of that role forever —
|
|
40
|
+
* including one pasted in by whoever copies this block as a template. Naming the value being
|
|
41
|
+
* replaced makes the permission SELF-EXPIRING: the moment the change lands, live equals
|
|
42
|
+
* `mintUser`, the guard stops consulting it, and the next re-scope finds a stale string that
|
|
43
|
+
* does not match live and is refused on its own merits.
|
|
44
|
+
*
|
|
45
|
+
* Not persisted, not in attributes, not in `matches` — it describes the operator's intent, not
|
|
46
|
+
* the server, so changing it alone is correctly a noop. See the ⛔ in proxmox-role.ts reconcile.
|
|
47
|
+
*/
|
|
48
|
+
allowMintUserChange?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface BaoProxmoxRoleAttributes {
|
|
51
|
+
/** Mount path, trailing slash stripped. */
|
|
52
|
+
mount: string;
|
|
53
|
+
/** Role name. */
|
|
54
|
+
name: string;
|
|
55
|
+
/** The PVE `user@realm` live tokens are minted under. A name, never a credential. */
|
|
56
|
+
mintUser: string;
|
|
57
|
+
/** Live default lease TTL, rendered back into the duration shape props use. */
|
|
58
|
+
ttl: string;
|
|
59
|
+
/** Live maximum lease TTL, same shape. */
|
|
60
|
+
maxTtl: string;
|
|
61
|
+
/** SHA-256 of the managed fields — safe to persist; see policy.ts. */
|
|
62
|
+
digest: string;
|
|
63
|
+
}
|
|
64
|
+
/** `proxmox-tb4/roles/read` — read, write and delete all address the role here. */
|
|
65
|
+
export declare const rolePath: (mount: string, name: string) => string;
|
|
66
|
+
export declare const attributesOf: (props: BaoProxmoxRoleProps, live: Record<string, unknown>) => BaoProxmoxRoleAttributes;
|
|
67
|
+
/**
|
|
68
|
+
* The body for `PUT <mount>/roles/<name>` — all strings, the `k=v` pairs `bao write` sent — or
|
|
69
|
+
* the prop names whose duration would not parse.
|
|
70
|
+
*
|
|
71
|
+
* ⛔ A WRITE TO roles/{name} REPLACES THE ROLE, IT DOES NOT MERGE. An omitted `ttl` is written
|
|
72
|
+
* as the field's zero value, so a resource that treated undeclared TTLs as "unmanaged" — the
|
|
73
|
+
* Bao.Mount shape — would silently reset a lease ceiling every time it rewrote the role for an
|
|
74
|
+
* unrelated reason. Both TTLs are therefore required props and EVERY write carries all three
|
|
75
|
+
* fields. REASONED from the Vault secrets-framework write semantics plus this plugin's schema
|
|
76
|
+
* marking only `mint_user` required; NOT measured, because this session was read-only and
|
|
77
|
+
* proving it would have meant writing to the live engine.
|
|
78
|
+
*
|
|
79
|
+
* ⚠️ Seconds go on the wire as integers, not as `1h`. The schema declares both TTLs
|
|
80
|
+
* `"format": "seconds"`, and an integer is accepted unambiguously by every path that reads
|
|
81
|
+
* them back — which is what keeps the round-trip through `matches` stable.
|
|
82
|
+
*/
|
|
83
|
+
export declare const writeBody: (props: BaoProxmoxRoleProps) => {
|
|
84
|
+
ok: true;
|
|
85
|
+
body: Record<string, string>;
|
|
86
|
+
} | {
|
|
87
|
+
ok: false;
|
|
88
|
+
bad: string[];
|
|
89
|
+
};
|
|
90
|
+
/** True when the live role already matches the declaration on every field the plugin stores. */
|
|
91
|
+
export declare const matches: (attributes: BaoProxmoxRoleAttributes, props: BaoProxmoxRoleProps) => boolean;
|
|
92
|
+
//# sourceMappingURL=proxmox-role-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxmox-role-form.d.ts","sourceRoot":"","sources":["../../src/openbao/proxmox-role-form.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB;AAmBD,mFAAmF;AACnF,eAAO,MAAM,QAAQ,UAAW,MAAM,QAAQ,MAAM,WAAwC,CAAC;AAE7F,eAAO,MAAM,YAAY,UAChB,mBAAmB,QACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,wBAYF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,UACb,mBAAmB,KACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAWzE,CAAC;AAaF,gGAAgG;AAChG,eAAO,MAAM,OAAO,eAAgB,wBAAwB,SAAS,mBAAmB,YAG9C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A role on the estate's proxmox secrets plugin — the mapping from one consumer to one PVE
|
|
3
|
+
* mint user, plus the lease ceilings that consumer's tokens get. METADATA ONLY.
|
|
4
|
+
*
|
|
5
|
+
* ★ WHY THIS FAMILY MATTERS MORE THAN IT LOOKS. Declaring these roles is how the estate
|
|
6
|
+
* replaces HAND-MADE PERMANENT PVE TOKENS with short-lived minted ones. On TB4, SEVEN tokens
|
|
7
|
+
* carry expire=0 and privsep=0 — root@pam!proxbox-sync, mcp@pve!executor,
|
|
8
|
+
* monitoring@pve!exporter, sablier@pve!sablier, tofu@pve!ro, tofu@pve!apply and
|
|
9
|
+
* vaultmint@pve!engine. Six of those are one Bao.ProxmoxRole plus a scoped PVE user away from
|
|
10
|
+
* being a 5-minute lease instead of a forever key.
|
|
11
|
+
*
|
|
12
|
+
* The seventh cannot be. vaultmint@pve!engine is the credential the ENGINE ITSELF
|
|
13
|
+
* authenticates with in order to mint anything at all: the thing that issues short-lived
|
|
14
|
+
* tokens needs a standing one, and no role can resolve that chicken-and-egg. It stays
|
|
15
|
+
* permanent, which makes it the single most valuable token on the cluster and the one whose
|
|
16
|
+
* rotation must be a deliberate, hand-run procedure rather than a plan.
|
|
17
|
+
*
|
|
18
|
+
* MEASURED here: `bao read proxmox-tb4/config` returns parent_token_id
|
|
19
|
+
* `vaultmint@pve!engine`, parent_secret_set true, parent_secret_tail `…eb01` — the engine's
|
|
20
|
+
* own key, present and, by the schema's own "Write-only: never returned by a read", not
|
|
21
|
+
* retrievable. The seven-token inventory was handed to this change and NOT re-counted against
|
|
22
|
+
* the PVE API in this session.
|
|
23
|
+
*
|
|
24
|
+
* ⛔ NO SECRET IN PROPS OR ATTRIBUTES — see policy.ts for the full reasoning. Every attribute
|
|
25
|
+
* here is a mount path, a role name, a PVE username or a TTL. Nothing this resource stores
|
|
26
|
+
* would help anyone authenticate to anything.
|
|
27
|
+
*
|
|
28
|
+
* ⛔ ISSUANCE IS NOT THIS RESOURCE, AND MUST NEVER BECOME ONE. `<mount>/creds/<name>` returns a
|
|
29
|
+
* LIVE PVE TOKEN. Alchemy persists attributes unencrypted (StateEncoding.ts tags Redacted
|
|
30
|
+
* values rather than encrypting them) into the `alchemy` Postgres, which pg-backup.sh dumps
|
|
31
|
+
* nightly to CT100, from where PBS backs it up. A minted token declared as a resource would
|
|
32
|
+
* outlive its own lease in at least four places, none of them OpenBao. This resource declares
|
|
33
|
+
* the DOOR; walking through it is a runtime call, not a plan.
|
|
34
|
+
*
|
|
35
|
+
* ★ `defaultRemovalPolicy: 'retain'` — deleting a role breaks every consumer that mints from
|
|
36
|
+
* it. Opt in with `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.
|
|
37
|
+
*/
|
|
38
|
+
import { Resource } from 'alchemy';
|
|
39
|
+
import * as Provider from 'alchemy/Provider';
|
|
40
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
41
|
+
import { type BaoProxmoxRoleAttributes, type BaoProxmoxRoleProps } from './proxmox-role-form.ts';
|
|
42
|
+
export type { BaoProxmoxRoleAttributes, BaoProxmoxRoleProps };
|
|
43
|
+
export interface BaoProxmoxRole extends Resource<'Bao.ProxmoxRole', BaoProxmoxRoleProps, BaoProxmoxRoleAttributes, never, HttpClient.HttpClient> {
|
|
44
|
+
}
|
|
45
|
+
export declare const BaoProxmoxRole: import("alchemy").ResourceClass<BaoProxmoxRole>;
|
|
46
|
+
export declare const BaoProxmoxRoleProvider: () => import("effect/Layer").Layer<Provider.Provider<BaoProxmoxRole>, never, HttpClient.HttpClient>;
|
|
47
|
+
//# sourceMappingURL=proxmox-role.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxmox-role.d.ts","sourceRoot":"","sources":["../../src/openbao/proxmox-role.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EAKzB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,CAAC;AAE9D,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAC9C,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,EACL,UAAU,CAAC,UAAU,CACtB;CAAG;AAEJ,eAAO,MAAM,cAAc,iDAEzB,CAAC;AAiBH,eAAO,MAAM,sBAAsB,qGAoIhC,CAAC"}
|