@homeflare/alchemy 0.14.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (567) hide show
  1. package/README.md +29 -0
  2. package/dist/linux/directory-lifecycle.d.ts +50 -0
  3. package/dist/linux/directory-lifecycle.d.ts.map +1 -0
  4. package/dist/linux/directory.d.ts +19 -0
  5. package/dist/linux/directory.d.ts.map +1 -0
  6. package/dist/linux/fake-linux-host.d.ts +35 -0
  7. package/dist/linux/fake-linux-host.d.ts.map +1 -0
  8. package/dist/linux/fake-systemd.d.ts +34 -0
  9. package/dist/linux/fake-systemd.d.ts.map +1 -0
  10. package/dist/linux/index.d.ts +27 -0
  11. package/dist/linux/index.d.ts.map +1 -0
  12. package/dist/linux/index.js +1554 -0
  13. package/dist/linux/index.js.map +37 -0
  14. package/dist/linux/providers.d.ts +17 -0
  15. package/dist/linux/providers.d.ts.map +1 -0
  16. package/dist/linux/region.d.ts +43 -0
  17. package/dist/linux/region.d.ts.map +1 -0
  18. package/dist/linux/remote-file-form.d.ts +47 -0
  19. package/dist/linux/remote-file-form.d.ts.map +1 -0
  20. package/dist/linux/remote-file-lifecycle.d.ts +36 -0
  21. package/dist/linux/remote-file-lifecycle.d.ts.map +1 -0
  22. package/dist/linux/remote-file-plan.d.ts +33 -0
  23. package/dist/linux/remote-file-plan.d.ts.map +1 -0
  24. package/dist/linux/remote-file.d.ts +28 -0
  25. package/dist/linux/remote-file.d.ts.map +1 -0
  26. package/dist/linux/ssh-command.d.ts +68 -0
  27. package/dist/linux/ssh-command.d.ts.map +1 -0
  28. package/dist/linux/ssh-runner.d.ts +22 -0
  29. package/dist/linux/ssh-runner.d.ts.map +1 -0
  30. package/dist/linux/ssh-scripts.d.ts +27 -0
  31. package/dist/linux/ssh-scripts.d.ts.map +1 -0
  32. package/dist/linux/systemctl.d.ts +67 -0
  33. package/dist/linux/systemctl.d.ts.map +1 -0
  34. package/dist/linux/unit-form.d.ts +78 -0
  35. package/dist/linux/unit-form.d.ts.map +1 -0
  36. package/dist/linux/unit-handlers.d.ts +15 -0
  37. package/dist/linux/unit-handlers.d.ts.map +1 -0
  38. package/dist/linux/unit-lifecycle.d.ts +44 -0
  39. package/dist/linux/unit-lifecycle.d.ts.map +1 -0
  40. package/dist/linux/unit-settle.d.ts +31 -0
  41. package/dist/linux/unit-settle.d.ts.map +1 -0
  42. package/dist/linux/unit.d.ts +35 -0
  43. package/dist/linux/unit.d.ts.map +1 -0
  44. package/dist/netbox/client.d.ts +52 -0
  45. package/dist/netbox/client.d.ts.map +1 -0
  46. package/dist/netbox/constraint-guard.d.ts +26 -0
  47. package/dist/netbox/constraint-guard.d.ts.map +1 -0
  48. package/dist/netbox/constraints.d.ts +76 -0
  49. package/dist/netbox/constraints.d.ts.map +1 -0
  50. package/dist/netbox/generated/constraints/index.d.ts +19 -0
  51. package/dist/netbox/generated/constraints/index.d.ts.map +1 -0
  52. package/dist/netbox/generated/constraints/netbox-ipam.d.ts +21 -0
  53. package/dist/netbox/generated/constraints/netbox-ipam.d.ts.map +1 -0
  54. package/dist/netbox/index.d.ts +17 -0
  55. package/dist/netbox/index.d.ts.map +1 -0
  56. package/dist/netbox/index.js +331 -0
  57. package/dist/netbox/index.js.map +18 -0
  58. package/dist/netbox/prefix-form.d.ts +54 -0
  59. package/dist/netbox/prefix-form.d.ts.map +1 -0
  60. package/dist/netbox/prefix.d.ts +80 -0
  61. package/dist/netbox/prefix.d.ts.map +1 -0
  62. package/dist/netbox/resource.d.ts +94 -0
  63. package/dist/netbox/resource.d.ts.map +1 -0
  64. package/dist/netbox/values.d.ts +24 -0
  65. package/dist/netbox/values.d.ts.map +1 -0
  66. package/dist/openbao/index.d.ts +10 -3
  67. package/dist/openbao/index.d.ts.map +1 -1
  68. package/dist/proxmox/acl.d.ts.map +1 -1
  69. package/dist/proxmox/api-token-form.d.ts.map +1 -1
  70. package/dist/proxmox/apply-endpoints.d.ts +30 -0
  71. package/dist/proxmox/apply-endpoints.d.ts.map +1 -0
  72. package/dist/proxmox/backup-job.d.ts.map +1 -1
  73. package/dist/proxmox/ceph-daemon-form.d.ts +29 -1
  74. package/dist/proxmox/ceph-daemon-form.d.ts.map +1 -1
  75. package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
  76. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  77. package/dist/proxmox/ceph-fs.d.ts.map +1 -1
  78. package/dist/proxmox/ceph-osd-write.d.ts +19 -0
  79. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  80. package/dist/proxmox/ceph-pool.d.ts.map +1 -1
  81. package/dist/proxmox/constraint-guard.d.ts +28 -0
  82. package/dist/proxmox/constraint-guard.d.ts.map +1 -0
  83. package/dist/proxmox/constraints.d.ts +94 -0
  84. package/dist/proxmox/constraints.d.ts.map +1 -0
  85. package/dist/proxmox/firewall-alias.d.ts.map +1 -1
  86. package/dist/proxmox/generated/constraints/index.d.ts +19 -0
  87. package/dist/proxmox/generated/constraints/index.d.ts.map +1 -0
  88. package/dist/proxmox/generated/constraints/pbs-config.d.ts +23 -0
  89. package/dist/proxmox/generated/constraints/pbs-config.d.ts.map +1 -0
  90. package/dist/proxmox/generated/constraints/pve-access.d.ts +23 -0
  91. package/dist/proxmox/generated/constraints/pve-access.d.ts.map +1 -0
  92. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +23 -0
  93. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts.map +1 -0
  94. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +23 -0
  95. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts.map +1 -0
  96. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +23 -0
  97. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts.map +1 -0
  98. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +23 -0
  99. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts.map +1 -0
  100. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +23 -0
  101. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts.map +1 -0
  102. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +23 -0
  103. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts.map +1 -0
  104. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +23 -0
  105. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts.map +1 -0
  106. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +23 -0
  107. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts.map +1 -0
  108. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +23 -0
  109. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts.map +1 -0
  110. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +23 -0
  111. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts.map +1 -0
  112. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +23 -0
  113. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts.map +1 -0
  114. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +23 -0
  115. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts.map +1 -0
  116. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +23 -0
  117. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts.map +1 -0
  118. package/dist/proxmox/generated/constraints/pve-pools.d.ts +23 -0
  119. package/dist/proxmox/generated/constraints/pve-pools.d.ts.map +1 -0
  120. package/dist/proxmox/generated/constraints/pve-storage.d.ts +23 -0
  121. package/dist/proxmox/generated/constraints/pve-storage.d.ts.map +1 -0
  122. package/dist/proxmox/generated/pbs/access-users.d.ts +137 -0
  123. package/dist/proxmox/generated/pbs/access-users.d.ts.map +1 -0
  124. package/dist/proxmox/generated/pbs/access.d.ts +171 -0
  125. package/dist/proxmox/generated/pbs/access.d.ts.map +1 -0
  126. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts +252 -0
  127. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts.map +1 -0
  128. package/dist/proxmox/generated/pbs/admin-metrics.d.ts +147 -0
  129. package/dist/proxmox/generated/pbs/admin-metrics.d.ts.map +1 -0
  130. package/dist/proxmox/generated/pbs/admin.d.ts +217 -0
  131. package/dist/proxmox/generated/pbs/admin.d.ts.map +1 -0
  132. package/dist/proxmox/generated/pbs/backup.d.ts +114 -0
  133. package/dist/proxmox/generated/pbs/backup.d.ts.map +1 -0
  134. package/dist/proxmox/generated/pbs/config-access-pam.d.ts +218 -0
  135. package/dist/proxmox/generated/pbs/config-access-pam.d.ts.map +1 -0
  136. package/dist/proxmox/generated/pbs/config-access.d.ts +203 -0
  137. package/dist/proxmox/generated/pbs/config-access.d.ts.map +1 -0
  138. package/dist/proxmox/generated/pbs/config-datastore.d.ts +195 -0
  139. package/dist/proxmox/generated/pbs/config-datastore.d.ts.map +1 -0
  140. package/dist/proxmox/generated/pbs/config-media-pool.d.ts +207 -0
  141. package/dist/proxmox/generated/pbs/config-media-pool.d.ts.map +1 -0
  142. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts +159 -0
  143. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts.map +1 -0
  144. package/dist/proxmox/generated/pbs/config-notifications.d.ts +199 -0
  145. package/dist/proxmox/generated/pbs/config-notifications.d.ts.map +1 -0
  146. package/dist/proxmox/generated/pbs/config-remote.d.ts +175 -0
  147. package/dist/proxmox/generated/pbs/config-remote.d.ts.map +1 -0
  148. package/dist/proxmox/generated/pbs/config-sync.d.ts +145 -0
  149. package/dist/proxmox/generated/pbs/config-sync.d.ts.map +1 -0
  150. package/dist/proxmox/generated/pbs/config-tape.d.ts +200 -0
  151. package/dist/proxmox/generated/pbs/config-tape.d.ts.map +1 -0
  152. package/dist/proxmox/generated/pbs/config-verify.d.ts +77 -0
  153. package/dist/proxmox/generated/pbs/config-verify.d.ts.map +1 -0
  154. package/dist/proxmox/generated/pbs/config.d.ts +119 -0
  155. package/dist/proxmox/generated/pbs/config.d.ts.map +1 -0
  156. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts +178 -0
  157. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts.map +1 -0
  158. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts +205 -0
  159. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts.map +1 -0
  160. package/dist/proxmox/generated/pbs/nodes-node.d.ts +166 -0
  161. package/dist/proxmox/generated/pbs/nodes-node.d.ts.map +1 -0
  162. package/dist/proxmox/generated/pbs/nodes.d.ts +171 -0
  163. package/dist/proxmox/generated/pbs/nodes.d.ts.map +1 -0
  164. package/dist/proxmox/generated/pbs/ping.d.ts +18 -0
  165. package/dist/proxmox/generated/pbs/ping.d.ts.map +1 -0
  166. package/dist/proxmox/generated/pbs/pull.d.ts +37 -0
  167. package/dist/proxmox/generated/pbs/pull.d.ts.map +1 -0
  168. package/dist/proxmox/generated/pbs/push.d.ts +36 -0
  169. package/dist/proxmox/generated/pbs/push.d.ts.map +1 -0
  170. package/dist/proxmox/generated/pbs/reader.d.ts +41 -0
  171. package/dist/proxmox/generated/pbs/reader.d.ts.map +1 -0
  172. package/dist/proxmox/generated/pbs/root.d.ts +16 -0
  173. package/dist/proxmox/generated/pbs/root.d.ts.map +1 -0
  174. package/dist/proxmox/generated/pbs/status.d.ts +54 -0
  175. package/dist/proxmox/generated/pbs/status.d.ts.map +1 -0
  176. package/dist/proxmox/generated/pbs/tape-drive.d.ts +181 -0
  177. package/dist/proxmox/generated/pbs/tape-drive.d.ts.map +1 -0
  178. package/dist/proxmox/generated/pbs/tape-media.d.ts +126 -0
  179. package/dist/proxmox/generated/pbs/tape-media.d.ts.map +1 -0
  180. package/dist/proxmox/generated/pbs/tape.d.ts +90 -0
  181. package/dist/proxmox/generated/pbs/tape.d.ts.map +1 -0
  182. package/dist/proxmox/generated/pbs/version.d.ts +20 -0
  183. package/dist/proxmox/generated/pbs/version.d.ts.map +1 -0
  184. package/dist/proxmox/generated/pbs.d.ts +44 -662
  185. package/dist/proxmox/generated/pbs.d.ts.map +1 -1
  186. package/dist/proxmox/generated/pve/access-roles.d.ts +164 -0
  187. package/dist/proxmox/generated/pve/access-roles.d.ts.map +1 -0
  188. package/dist/proxmox/generated/pve/access-users.d.ts +152 -0
  189. package/dist/proxmox/generated/pve/access-users.d.ts.map +1 -0
  190. package/dist/proxmox/generated/pve/access.d.ts +221 -0
  191. package/dist/proxmox/generated/pve/access.d.ts.map +1 -0
  192. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts +45 -0
  193. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts.map +1 -0
  194. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts +47 -0
  195. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts.map +1 -0
  196. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts +240 -0
  197. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts.map +1 -0
  198. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts +200 -0
  199. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts.map +1 -0
  200. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts +109 -0
  201. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts.map +1 -0
  202. package/dist/proxmox/generated/pve/cluster-firewall.d.ts +225 -0
  203. package/dist/proxmox/generated/pve/cluster-firewall.d.ts.map +1 -0
  204. package/dist/proxmox/generated/pve/cluster-ha.d.ts +199 -0
  205. package/dist/proxmox/generated/pve/cluster-ha.d.ts.map +1 -0
  206. package/dist/proxmox/generated/pve/cluster-jobs.d.ts +183 -0
  207. package/dist/proxmox/generated/pve/cluster-jobs.d.ts.map +1 -0
  208. package/dist/proxmox/generated/pve/cluster-metrics.d.ts +110 -0
  209. package/dist/proxmox/generated/pve/cluster-metrics.d.ts.map +1 -0
  210. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts +224 -0
  211. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts.map +1 -0
  212. package/dist/proxmox/generated/pve/cluster-notifications.d.ts +91 -0
  213. package/dist/proxmox/generated/pve/cluster-notifications.d.ts.map +1 -0
  214. package/dist/proxmox/generated/pve/cluster-options.d.ts +85 -0
  215. package/dist/proxmox/generated/pve/cluster-options.d.ts.map +1 -0
  216. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts +48 -0
  217. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts.map +1 -0
  218. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts +45 -0
  219. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts.map +1 -0
  220. package/dist/proxmox/generated/pve/cluster-replication.d.ts +130 -0
  221. package/dist/proxmox/generated/pve/cluster-replication.d.ts.map +1 -0
  222. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts +220 -0
  223. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts.map +1 -0
  224. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts +229 -0
  225. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts.map +1 -0
  226. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts +229 -0
  227. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts.map +1 -0
  228. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts +51 -0
  229. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts.map +1 -0
  230. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts +225 -0
  231. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts.map +1 -0
  232. package/dist/proxmox/generated/pve/cluster-sdn.d.ts +202 -0
  233. package/dist/proxmox/generated/pve/cluster-sdn.d.ts.map +1 -0
  234. package/dist/proxmox/generated/pve/cluster.d.ts +69 -0
  235. package/dist/proxmox/generated/pve/cluster.d.ts.map +1 -0
  236. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts +167 -0
  237. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts.map +1 -0
  238. package/dist/proxmox/generated/pve/nodes-node-config.d.ts +43 -0
  239. package/dist/proxmox/generated/pve/nodes-node-config.d.ts.map +1 -0
  240. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts +225 -0
  241. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts.map +1 -0
  242. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts +145 -0
  243. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts.map +1 -0
  244. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts +195 -0
  245. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts.map +1 -0
  246. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts +191 -0
  247. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts.map +1 -0
  248. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts +33 -0
  249. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts.map +1 -0
  250. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts +56 -0
  251. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts.map +1 -0
  252. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts +28 -0
  253. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts.map +1 -0
  254. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts +186 -0
  255. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts.map +1 -0
  256. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts +191 -0
  257. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts.map +1 -0
  258. package/dist/proxmox/generated/pve/nodes-node-network.d.ts +150 -0
  259. package/dist/proxmox/generated/pve/nodes-node-network.d.ts.map +1 -0
  260. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts +301 -0
  261. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts.map +1 -0
  262. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts +170 -0
  263. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts.map +1 -0
  264. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts +144 -0
  265. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts.map +1 -0
  266. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts +34 -0
  267. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts.map +1 -0
  268. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts +137 -0
  269. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts.map +1 -0
  270. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts +179 -0
  271. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts.map +1 -0
  272. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts +143 -0
  273. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts.map +1 -0
  274. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts +158 -0
  275. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts.map +1 -0
  276. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts +187 -0
  277. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts.map +1 -0
  278. package/dist/proxmox/generated/pve/nodes-node-services.d.ts +115 -0
  279. package/dist/proxmox/generated/pve/nodes-node-services.d.ts.map +1 -0
  280. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts +202 -0
  281. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts.map +1 -0
  282. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts +40 -0
  283. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts.map +1 -0
  284. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts +173 -0
  285. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts.map +1 -0
  286. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts +97 -0
  287. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts.map +1 -0
  288. package/dist/proxmox/generated/pve/nodes-node.d.ts +207 -0
  289. package/dist/proxmox/generated/pve/nodes-node.d.ts.map +1 -0
  290. package/dist/proxmox/generated/pve/nodes.d.ts +236 -0
  291. package/dist/proxmox/generated/pve/nodes.d.ts.map +1 -0
  292. package/dist/proxmox/generated/pve/pools.d.ts +82 -0
  293. package/dist/proxmox/generated/pve/pools.d.ts.map +1 -0
  294. package/dist/proxmox/generated/pve/storage.d.ts +159 -0
  295. package/dist/proxmox/generated/pve/storage.d.ts.map +1 -0
  296. package/dist/proxmox/generated/pve/version.d.ts +21 -0
  297. package/dist/proxmox/generated/pve/version.d.ts.map +1 -0
  298. package/dist/proxmox/generated/pve.d.ts +69 -4766
  299. package/dist/proxmox/generated/pve.d.ts.map +1 -1
  300. package/dist/proxmox/group.d.ts.map +1 -1
  301. package/dist/proxmox/ha-resource.d.ts.map +1 -1
  302. package/dist/proxmox/ha-rule.d.ts.map +1 -1
  303. package/dist/proxmox/index.d.ts +6 -1
  304. package/dist/proxmox/index.d.ts.map +1 -1
  305. package/dist/proxmox/index.js +1483 -300
  306. package/dist/proxmox/index.js.map +70 -45
  307. package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
  308. package/dist/proxmox/metric-server-form.d.ts +11 -0
  309. package/dist/proxmox/metric-server-form.d.ts.map +1 -1
  310. package/dist/proxmox/metric-server.d.ts.map +1 -1
  311. package/dist/proxmox/network-apply.d.ts.map +1 -1
  312. package/dist/proxmox/node-network-form.d.ts +15 -0
  313. package/dist/proxmox/node-network-form.d.ts.map +1 -1
  314. package/dist/proxmox/node-network.d.ts.map +1 -1
  315. package/dist/proxmox/notification-matcher.d.ts.map +1 -1
  316. package/dist/proxmox/notification-target-endpoint.d.ts +26 -0
  317. package/dist/proxmox/notification-target-endpoint.d.ts.map +1 -0
  318. package/dist/proxmox/notification-target-form.d.ts +7 -0
  319. package/dist/proxmox/notification-target-form.d.ts.map +1 -1
  320. package/dist/proxmox/notification-target.d.ts.map +1 -1
  321. package/dist/proxmox/pbs-datastore-endpoint.d.ts +22 -0
  322. package/dist/proxmox/pbs-datastore-endpoint.d.ts.map +1 -0
  323. package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
  324. package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -1
  325. package/dist/proxmox/pbs-notification-target-endpoint.d.ts +29 -0
  326. package/dist/proxmox/pbs-notification-target-endpoint.d.ts.map +1 -0
  327. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -1
  328. package/dist/proxmox/pbs-prune-job.d.ts.map +1 -1
  329. package/dist/proxmox/pbs-sync-job-form.d.ts.map +1 -1
  330. package/dist/proxmox/pbs-verify-job.d.ts.map +1 -1
  331. package/dist/proxmox/pool.d.ts.map +1 -1
  332. package/dist/proxmox/provision-baseline.d.ts +30 -5
  333. package/dist/proxmox/provision-baseline.d.ts.map +1 -1
  334. package/dist/proxmox/qemu.d.ts +10 -0
  335. package/dist/proxmox/qemu.d.ts.map +1 -1
  336. package/dist/proxmox/replication-job.d.ts.map +1 -1
  337. package/dist/proxmox/resource-guard.d.ts +15 -0
  338. package/dist/proxmox/resource-guard.d.ts.map +1 -0
  339. package/dist/proxmox/resource-spec.d.ts +131 -0
  340. package/dist/proxmox/resource-spec.d.ts.map +1 -0
  341. package/dist/proxmox/resource.d.ts +17 -90
  342. package/dist/proxmox/resource.d.ts.map +1 -1
  343. package/dist/proxmox/role.d.ts.map +1 -1
  344. package/dist/proxmox/sdn-apply.d.ts.map +1 -1
  345. package/dist/proxmox/sdn-subnet.d.ts.map +1 -1
  346. package/dist/proxmox/sdn-vnet.d.ts.map +1 -1
  347. package/dist/proxmox/sdn-zone.d.ts.map +1 -1
  348. package/dist/proxmox/storage.d.ts.map +1 -1
  349. package/dist/proxmox/user.d.ts.map +1 -1
  350. package/dist/proxmox/zfs-pool-write.d.ts +11 -0
  351. package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
  352. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  353. package/docs/linux-host-measured.md +56 -0
  354. package/docs/linux-host.md +186 -0
  355. package/docs/netbox.md +103 -0
  356. package/docs/provision-baseline.md +34 -7
  357. package/docs/proxmox-lxc.md +40 -0
  358. package/package.json +9 -1
  359. package/src/linux/directory-lifecycle.ts +220 -0
  360. package/src/linux/directory.test.ts +132 -0
  361. package/src/linux/directory.ts +71 -0
  362. package/src/linux/fake-linux-host.ts +197 -0
  363. package/src/linux/fake-systemd.ts +103 -0
  364. package/src/linux/index.ts +32 -0
  365. package/src/linux/providers.ts +26 -0
  366. package/src/linux/region.test.ts +89 -0
  367. package/src/linux/region.ts +118 -0
  368. package/src/linux/remote-file-form.ts +96 -0
  369. package/src/linux/remote-file-lifecycle.test.ts +191 -0
  370. package/src/linux/remote-file-lifecycle.ts +161 -0
  371. package/src/linux/remote-file-plan.ts +154 -0
  372. package/src/linux/remote-file.ts +88 -0
  373. package/src/linux/ssh-command.test.ts +140 -0
  374. package/src/linux/ssh-command.ts +99 -0
  375. package/src/linux/ssh-runner.ts +188 -0
  376. package/src/linux/ssh-scripts.ts +105 -0
  377. package/src/linux/systemctl.ts +145 -0
  378. package/src/linux/unit-form.ts +183 -0
  379. package/src/linux/unit-handlers.ts +73 -0
  380. package/src/linux/unit-lifecycle.test.ts +220 -0
  381. package/src/linux/unit-lifecycle.ts +193 -0
  382. package/src/linux/unit-settle.ts +110 -0
  383. package/src/linux/unit.ts +81 -0
  384. package/src/netbox/client.test.ts +67 -0
  385. package/src/netbox/client.ts +146 -0
  386. package/src/netbox/constraint-guard.ts +57 -0
  387. package/src/netbox/constraints.test.ts +114 -0
  388. package/src/netbox/constraints.ts +152 -0
  389. package/src/netbox/generated/constraints/index.ts +23 -0
  390. package/src/netbox/generated/constraints/netbox-ipam.ts +32 -0
  391. package/src/netbox/index.ts +34 -0
  392. package/src/netbox/prefix-form.test.ts +127 -0
  393. package/src/netbox/prefix-form.ts +84 -0
  394. package/src/netbox/prefix.ts +136 -0
  395. package/src/netbox/resource.ts +208 -0
  396. package/src/netbox/values.test.ts +66 -0
  397. package/src/netbox/values.ts +40 -0
  398. package/src/openbao/index-types.test.ts +87 -0
  399. package/src/openbao/index.ts +15 -3
  400. package/src/proxmox/acl.ts +2 -0
  401. package/src/proxmox/api-token-form.ts +5 -0
  402. package/src/proxmox/apply-endpoints.ts +34 -0
  403. package/src/proxmox/backup-job.ts +2 -0
  404. package/src/proxmox/ceph-daemon-form.ts +56 -2
  405. package/src/proxmox/ceph-daemon.ts +10 -21
  406. package/src/proxmox/ceph-flag.ts +1 -0
  407. package/src/proxmox/ceph-fs.ts +1 -0
  408. package/src/proxmox/ceph-osd-write.ts +30 -4
  409. package/src/proxmox/ceph-pool.ts +10 -0
  410. package/src/proxmox/constraint-guard.ts +53 -0
  411. package/src/proxmox/constraints-dialect.test.ts +165 -0
  412. package/src/proxmox/constraints-forms.test.ts +220 -0
  413. package/src/proxmox/constraints-host-forms.test.ts +132 -0
  414. package/src/proxmox/constraints-live.test.ts +155 -0
  415. package/src/proxmox/constraints-node-forms.test.ts +188 -0
  416. package/src/proxmox/constraints-required.test.ts +172 -0
  417. package/src/proxmox/constraints.test.ts +205 -0
  418. package/src/proxmox/constraints.ts +160 -0
  419. package/src/proxmox/firewall-alias.ts +5 -0
  420. package/src/proxmox/generated/constraints/index.ts +55 -0
  421. package/src/proxmox/generated/constraints/pbs-config.ts +203 -0
  422. package/src/proxmox/generated/constraints/pve-access.ts +69 -0
  423. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +74 -0
  424. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +27 -0
  425. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +35 -0
  426. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +55 -0
  427. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +59 -0
  428. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +80 -0
  429. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +43 -0
  430. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +90 -0
  431. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +57 -0
  432. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +31 -0
  433. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +82 -0
  434. package/src/proxmox/generated/constraints/pve-nodes-network.ts +77 -0
  435. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +125 -0
  436. package/src/proxmox/generated/constraints/pve-pools.ts +31 -0
  437. package/src/proxmox/generated/constraints/pve-storage.ts +80 -0
  438. package/src/proxmox/generated/pbs/access-users.ts +137 -0
  439. package/src/proxmox/generated/pbs/access.ts +232 -0
  440. package/src/proxmox/generated/pbs/admin-datastore-store.ts +238 -0
  441. package/src/proxmox/generated/pbs/admin-metrics.ts +147 -0
  442. package/src/proxmox/generated/pbs/admin.ts +225 -0
  443. package/src/proxmox/generated/pbs/backup.ts +121 -0
  444. package/src/proxmox/generated/pbs/config-access-pam.ts +228 -0
  445. package/src/proxmox/generated/pbs/config-access.ts +228 -0
  446. package/src/proxmox/generated/pbs/config-datastore.ts +217 -0
  447. package/src/proxmox/generated/pbs/config-media-pool.ts +232 -0
  448. package/src/proxmox/generated/pbs/config-notifications-matchers.ts +187 -0
  449. package/src/proxmox/generated/pbs/config-notifications.ts +221 -0
  450. package/src/proxmox/generated/pbs/config-remote.ts +192 -0
  451. package/src/proxmox/generated/pbs/config-sync.ts +167 -0
  452. package/src/proxmox/generated/pbs/config-tape.ts +226 -0
  453. package/src/proxmox/generated/pbs/config-verify.ts +87 -0
  454. package/src/proxmox/generated/pbs/config.ts +135 -0
  455. package/src/proxmox/generated/pbs/nodes-node-dns.ts +229 -0
  456. package/src/proxmox/generated/pbs/nodes-node-services.ts +181 -0
  457. package/src/proxmox/generated/pbs/nodes-node.ts +244 -0
  458. package/src/proxmox/generated/pbs/nodes.ts +160 -0
  459. package/src/proxmox/generated/pbs/ping.ts +16 -0
  460. package/src/proxmox/generated/pbs/pull.ts +37 -0
  461. package/src/proxmox/generated/pbs/push.ts +36 -0
  462. package/src/proxmox/generated/pbs/reader.ts +41 -0
  463. package/src/proxmox/generated/pbs/root.ts +16 -0
  464. package/src/proxmox/generated/pbs/status.ts +50 -0
  465. package/src/proxmox/generated/pbs/tape-drive.ts +220 -0
  466. package/src/proxmox/generated/pbs/tape-media.ts +133 -0
  467. package/src/proxmox/generated/pbs/tape.ts +92 -0
  468. package/src/proxmox/generated/pbs/version.ts +16 -0
  469. package/src/proxmox/generated/pbs.ts +44 -787
  470. package/src/proxmox/generated/pve/access-roles.ts +168 -0
  471. package/src/proxmox/generated/pve/access-users.ts +155 -0
  472. package/src/proxmox/generated/pve/access.ts +217 -0
  473. package/src/proxmox/generated/pve/cluster-acme-plugins-id.ts +367 -0
  474. package/src/proxmox/generated/pve/cluster-acme-plugins.ts +366 -0
  475. package/src/proxmox/generated/pve/cluster-acme-tos.ts +232 -0
  476. package/src/proxmox/generated/pve/cluster-bulk-action.ts +227 -0
  477. package/src/proxmox/generated/pve/cluster-firewall-refs.ts +110 -0
  478. package/src/proxmox/generated/pve/cluster-firewall.ts +236 -0
  479. package/src/proxmox/generated/pve/cluster-ha.ts +203 -0
  480. package/src/proxmox/generated/pve/cluster-jobs.ts +190 -0
  481. package/src/proxmox/generated/pve/cluster-metrics.ts +116 -0
  482. package/src/proxmox/generated/pve/cluster-notifications-endpoints.ts +244 -0
  483. package/src/proxmox/generated/pve/cluster-notifications.ts +99 -0
  484. package/src/proxmox/generated/pve/cluster-options.ts +189 -0
  485. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.ts +272 -0
  486. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models.ts +268 -0
  487. package/src/proxmox/generated/pve/cluster-replication.ts +127 -0
  488. package/src/proxmox/generated/pve/cluster-sdn-fabrics.ts +218 -0
  489. package/src/proxmox/generated/pve/cluster-sdn-ipams.ts +229 -0
  490. package/src/proxmox/generated/pve/cluster-sdn-vnets-vnet.ts +245 -0
  491. package/src/proxmox/generated/pve/cluster-sdn-vnets.ts +49 -0
  492. package/src/proxmox/generated/pve/cluster-sdn-zones.ts +224 -0
  493. package/src/proxmox/generated/pve/cluster-sdn.ts +201 -0
  494. package/src/proxmox/generated/pve/cluster.ts +71 -0
  495. package/src/proxmox/generated/pve/nodes-node-ceph.ts +167 -0
  496. package/src/proxmox/generated/pve/nodes-node-config.ts +56 -0
  497. package/src/proxmox/generated/pve/nodes-node-disks.ts +237 -0
  498. package/src/proxmox/generated/pve/nodes-node-firewall.ts +239 -0
  499. package/src/proxmox/generated/pve/nodes-node-hardware.ts +215 -0
  500. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.ts +232 -0
  501. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.ts +1059 -0
  502. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.ts +49 -0
  503. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-resize.ts +285 -0
  504. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.ts +184 -0
  505. package/src/proxmox/generated/pve/nodes-node-lxc-vmid.ts +240 -0
  506. package/src/proxmox/generated/pve/nodes-node-network.ts +234 -0
  507. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-config.ts +441 -0
  508. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.ts +215 -0
  509. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.ts +145 -0
  510. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.ts +664 -0
  511. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.ts +188 -0
  512. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-status.ts +233 -0
  513. package/src/proxmox/generated/pve/nodes-node-qemu-vmid.ts +187 -0
  514. package/src/proxmox/generated/pve/nodes-node-qemu.ts +204 -0
  515. package/src/proxmox/generated/pve/nodes-node-replication.ts +187 -0
  516. package/src/proxmox/generated/pve/nodes-node-services.ts +221 -0
  517. package/src/proxmox/generated/pve/nodes-node-storage-storage.ts +226 -0
  518. package/src/proxmox/generated/pve/nodes-node-storage.ts +40 -0
  519. package/src/proxmox/generated/pve/nodes-node-subscription.ts +168 -0
  520. package/src/proxmox/generated/pve/nodes-node-vzdump.ts +96 -0
  521. package/src/proxmox/generated/pve/nodes-node.ts +211 -0
  522. package/src/proxmox/generated/pve/nodes.ts +235 -0
  523. package/src/proxmox/generated/pve/pools.ts +78 -0
  524. package/src/proxmox/generated/pve/storage.ts +213 -0
  525. package/src/proxmox/generated/pve/version.ts +21 -0
  526. package/src/proxmox/generated/pve.ts +69 -7403
  527. package/src/proxmox/group.ts +2 -0
  528. package/src/proxmox/ha-resource.ts +5 -0
  529. package/src/proxmox/ha-rule.ts +2 -0
  530. package/src/proxmox/index.ts +12 -0
  531. package/src/proxmox/lxc-interior.test.ts +77 -0
  532. package/src/proxmox/lxc-lifecycle.ts +48 -9
  533. package/src/proxmox/metric-server-form.ts +10 -0
  534. package/src/proxmox/metric-server.ts +11 -2
  535. package/src/proxmox/network-apply.ts +4 -0
  536. package/src/proxmox/node-network-form.ts +19 -0
  537. package/src/proxmox/node-network.ts +9 -3
  538. package/src/proxmox/notification-matcher.ts +5 -0
  539. package/src/proxmox/notification-target-endpoint.ts +46 -0
  540. package/src/proxmox/notification-target-form.ts +11 -0
  541. package/src/proxmox/notification-target.ts +5 -2
  542. package/src/proxmox/pbs-datastore-endpoint.ts +29 -0
  543. package/src/proxmox/pbs-datastore.ts +8 -1
  544. package/src/proxmox/pbs-notification-matcher.ts +5 -0
  545. package/src/proxmox/pbs-notification-target-endpoint.ts +45 -0
  546. package/src/proxmox/pbs-notification-target-lifecycle.ts +16 -14
  547. package/src/proxmox/pbs-prune-job.ts +2 -0
  548. package/src/proxmox/pbs-sync-job-form.ts +2 -0
  549. package/src/proxmox/pbs-verify-job.ts +2 -0
  550. package/src/proxmox/pool.ts +2 -0
  551. package/src/proxmox/provision-baseline.test.ts +38 -0
  552. package/src/proxmox/provision-baseline.ts +73 -14
  553. package/src/proxmox/provision-bootstrap.test.ts +51 -0
  554. package/src/proxmox/qemu.ts +9 -1
  555. package/src/proxmox/replication-job.ts +5 -0
  556. package/src/proxmox/resource-guard.ts +61 -0
  557. package/src/proxmox/resource-spec.ts +129 -0
  558. package/src/proxmox/resource.ts +52 -93
  559. package/src/proxmox/role.ts +2 -0
  560. package/src/proxmox/sdn-apply.ts +4 -0
  561. package/src/proxmox/sdn-subnet.ts +5 -0
  562. package/src/proxmox/sdn-vnet.ts +2 -0
  563. package/src/proxmox/sdn-zone.ts +2 -0
  564. package/src/proxmox/storage.ts +2 -0
  565. package/src/proxmox/user.ts +2 -0
  566. package/src/proxmox/zfs-pool-write.ts +12 -0
  567. package/src/proxmox/zfs-pool.ts +2 -1
@@ -2,7 +2,7 @@
2
2
  import { Resource } from "alchemy";
3
3
  import { isResolved as isResolved2 } from "alchemy/Diff";
4
4
  import * as Provider from "alchemy/Provider";
5
- import * as Effect6 from "effect/Effect";
5
+ import * as Effect8 from "effect/Effect";
6
6
 
7
7
  // src/proxmox/client.ts
8
8
  import * as Effect4 from "effect/Effect";
@@ -223,30 +223,1027 @@ var pve = (target, role, method, path, form) => Effect4.gen(function* () {
223
223
 
224
224
  // src/proxmox/resource.ts
225
225
  import { isResolved } from "alchemy/Diff";
226
+ import * as Effect7 from "effect/Effect";
227
+
228
+ // src/proxmox/resource-guard.ts
229
+ import * as Effect6 from "effect/Effect";
230
+
231
+ // src/proxmox/constraint-guard.ts
226
232
  import * as Effect5 from "effect/Effect";
227
233
 
234
+ // src/proxmox/constraints.ts
235
+ var lengthOf = (value) => [...value].length;
236
+ var checkValue = (name, value, rule) => {
237
+ const out = [];
238
+ if (rule.maxLength !== undefined && lengthOf(value) > rule.maxLength) {
239
+ out.push(`${name}: at most ${rule.maxLength} characters`);
240
+ }
241
+ if (rule.minLength !== undefined && lengthOf(value) < rule.minLength) {
242
+ out.push(`${name}: at least ${rule.minLength} characters`);
243
+ }
244
+ if (rule.enum !== undefined && !rule.enum.includes(value)) {
245
+ out.push(`${name}: must be one of ${rule.enum.join(", ")}`);
246
+ }
247
+ if (rule.pattern !== undefined && !new RegExp(rule.pattern, rule.patternFlags).test(value)) {
248
+ out.push(`${name}: must match ${rule.patternSource ?? rule.pattern}`);
249
+ }
250
+ const numeric = Number(value);
251
+ const bounded = rule.minimum !== undefined || rule.maximum !== undefined;
252
+ if (bounded && value !== "" && Number.isFinite(numeric)) {
253
+ if (rule.minimum !== undefined && numeric < rule.minimum) {
254
+ out.push(`${name}: at least ${rule.minimum}`);
255
+ }
256
+ if (rule.maximum !== undefined && numeric > rule.maximum) {
257
+ out.push(`${name}: at most ${rule.maximum}`);
258
+ }
259
+ }
260
+ return out;
261
+ };
262
+ var violations = (table, form, options = {}) => {
263
+ const out = [];
264
+ for (const [name, rule] of Object.entries(table)) {
265
+ const value = form[name];
266
+ if (value === undefined) {
267
+ if (options.presence === true && rule.required === true)
268
+ out.push(`${name}: required`);
269
+ continue;
270
+ }
271
+ for (const item of typeof value === "string" ? [value] : value) {
272
+ out.push(...checkValue(name, item, rule));
273
+ }
274
+ }
275
+ return out;
276
+ };
277
+ var refusal = (endpoint, found) => `${endpoint} would be rejected by the vendor:
278
+ - ${found.join(`
279
+ - `)}
280
+ ` + "These are the vendor's own limits, read from its published schema " + "(packages/alchemy/src/proxmox/generated/constraints). Fix the declaration.";
281
+
282
+ // src/proxmox/generated/constraints/pve-access.ts
283
+ var PVE_ACCESS_CONSTRAINTS = {
284
+ "pve:POST /access/groups": {
285
+ groupid: { format: "pve-groupid", required: true, type: "string" }
286
+ },
287
+ "pve:POST /access/roles": {
288
+ privs: { format: "pve-priv-list", type: "string" },
289
+ roleid: { format: "pve-roleid", required: true, type: "string" }
290
+ },
291
+ "pve:POST /access/users": {
292
+ comment: { maxLength: 2048, type: "string" },
293
+ email: { format: "email-opt", maxLength: 254, type: "string" },
294
+ expire: { minimum: 0, type: "integer" },
295
+ firstname: { maxLength: 1024, type: "string" },
296
+ groups: { format: "pve-groupid-list", type: "string" },
297
+ keys: { pattern: "^[0-9a-zA-Z!=]{0,4096}\\n?$", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
298
+ lastname: { maxLength: 1024, type: "string" },
299
+ password: { maxLength: 64, minLength: 8, type: "string" },
300
+ userid: { format: "pve-userid", maxLength: 64, required: true, type: "string" }
301
+ },
302
+ "pve:POST /access/users/{userid}/token/{tokenid}": {
303
+ expire: { default: "same as user", minimum: 0, type: "integer" }
304
+ },
305
+ "pve:PUT /access/acl": {
306
+ groups: { format: "pve-groupid-list", type: "string" },
307
+ path: { required: true, type: "string" },
308
+ roles: { format: "pve-roleid-list", required: true, type: "string" },
309
+ tokens: { format: "pve-tokenid-list", type: "string" },
310
+ users: { format: "pve-userid-list", type: "string" }
311
+ },
312
+ "pve:PUT /access/groups/{groupid}": {},
313
+ "pve:PUT /access/roles/{roleid}": {
314
+ privs: { format: "pve-priv-list", type: "string" }
315
+ },
316
+ "pve:PUT /access/users/{userid}": {
317
+ comment: { maxLength: 2048, type: "string" },
318
+ email: { format: "email-opt", maxLength: 254, type: "string" },
319
+ expire: { minimum: 0, type: "integer" },
320
+ firstname: { maxLength: 1024, type: "string" },
321
+ groups: { format: "pve-groupid-list", type: "string" },
322
+ keys: { pattern: "^[0-9a-zA-Z!=]{0,4096}\\n?$", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
323
+ lastname: { maxLength: 1024, type: "string" }
324
+ },
325
+ "pve:PUT /access/users/{userid}/token/{tokenid}": {
326
+ delete: { format: "pve-configid-list", type: "string" },
327
+ expire: { default: "same as user", minimum: 0, type: "integer" }
328
+ }
329
+ };
330
+
331
+ // src/proxmox/generated/constraints/pve-cluster-backup.ts
332
+ var PVE_CLUSTER_BACKUP_CONSTRAINTS = {
333
+ "pve:POST /cluster/backup": {
334
+ bwlimit: { default: "0", minimum: 0, type: "integer" },
335
+ comment: { maxLength: 512, type: "string" },
336
+ compress: { default: "0", enum: ["0", "1", "gzip", "lzo", "zstd"], type: "string" },
337
+ dow: { default: "mon,tue,wed,thu,fri,sat,sun", format: "pve-day-of-week-list", type: "string" },
338
+ exclude: { format: "pve-vmid-list", type: "string" },
339
+ fleecing: { format: "backup-fleecing", type: "string" },
340
+ id: { format: "pve-configid", type: "string" },
341
+ ionice: { default: "7", maximum: 8, minimum: 0, type: "integer" },
342
+ lockwait: { default: "180", minimum: 0, type: "integer" },
343
+ mailnotification: { default: "always", enum: ["always", "failure"], type: "string" },
344
+ mailto: { format: "email-or-username-list", type: "string" },
345
+ mode: { default: "snapshot", enum: ["snapshot", "suspend", "stop"], type: "string" },
346
+ node: { format: "pve-node", type: "string" },
347
+ "notes-template": { maxLength: 1024, type: "string" },
348
+ "notification-mode": { default: "auto", enum: ["auto", "legacy-sendmail", "notification-system"], type: "string" },
349
+ "pbs-change-detection-mode": { enum: ["legacy", "data", "metadata"], type: "string" },
350
+ performance: { format: "backup-performance", type: "string" },
351
+ "prune-backups": { default: "keep-all=1", format: "prune-backups", type: "string" },
352
+ schedule: { format: "pve-calendar-event", maxLength: 128, type: "string" },
353
+ starttime: { pattern: "^\\d{1,2}:\\d{1,2}\\n?$", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
354
+ stopwait: { default: "10", minimum: 0, type: "integer" },
355
+ storage: { format: "pve-storage-id", type: "string" },
356
+ vmid: { format: "pve-vmid-list", type: "string" }
357
+ },
358
+ "pve:PUT /cluster/backup/{id}": {
359
+ bwlimit: { default: "0", minimum: 0, type: "integer" },
360
+ comment: { maxLength: 512, type: "string" },
361
+ compress: { default: "0", enum: ["0", "1", "gzip", "lzo", "zstd"], type: "string" },
362
+ delete: { format: "pve-configid-list", type: "string" },
363
+ dow: { format: "pve-day-of-week-list", type: "string" },
364
+ exclude: { format: "pve-vmid-list", type: "string" },
365
+ fleecing: { format: "backup-fleecing", type: "string" },
366
+ ionice: { default: "7", maximum: 8, minimum: 0, type: "integer" },
367
+ lockwait: { default: "180", minimum: 0, type: "integer" },
368
+ mailnotification: { default: "always", enum: ["always", "failure"], type: "string" },
369
+ mailto: { format: "email-or-username-list", type: "string" },
370
+ mode: { default: "snapshot", enum: ["snapshot", "suspend", "stop"], type: "string" },
371
+ node: { format: "pve-node", type: "string" },
372
+ "notes-template": { maxLength: 1024, type: "string" },
373
+ "notification-mode": { default: "auto", enum: ["auto", "legacy-sendmail", "notification-system"], type: "string" },
374
+ "pbs-change-detection-mode": { enum: ["legacy", "data", "metadata"], type: "string" },
375
+ performance: { format: "backup-performance", type: "string" },
376
+ "prune-backups": { default: "keep-all=1", format: "prune-backups", type: "string" },
377
+ schedule: { format: "pve-calendar-event", maxLength: 128, type: "string" },
378
+ starttime: { pattern: "^\\d{1,2}:\\d{1,2}\\n?$", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
379
+ stopwait: { default: "10", minimum: 0, type: "integer" },
380
+ storage: { format: "pve-storage-id", type: "string" },
381
+ vmid: { format: "pve-vmid-list", type: "string" }
382
+ }
383
+ };
384
+
385
+ // src/proxmox/generated/constraints/pve-cluster-ceph.ts
386
+ var PVE_CLUSTER_CEPH_CONSTRAINTS = {
387
+ "pve:PUT /cluster/ceph/flags/{flag}": {
388
+ value: { required: true, type: "boolean" }
389
+ }
390
+ };
391
+
392
+ // src/proxmox/generated/constraints/pve-cluster-firewall.ts
393
+ var PVE_CLUSTER_FIREWALL_CONSTRAINTS = {
394
+ "pve:POST /cluster/firewall/aliases": {
395
+ cidr: { format: "IPorCIDR", required: true, type: "string" },
396
+ comment: { format: "pve-fw-comment-spec", type: "string" },
397
+ name: { maxLength: 64, minLength: 2, pattern: "^[A-Za-z][A-Za-z0-9\\-\\_]+\\n?$", patternSource: "[A-Za-z][A-Za-z0-9\\-\\_]+", required: true, type: "string" }
398
+ },
399
+ "pve:PUT /cluster/firewall/aliases/{name}": {
400
+ cidr: { format: "IPorCIDR", required: true, type: "string" },
401
+ comment: { format: "pve-fw-comment-spec", type: "string" },
402
+ digest: { maxLength: 64, type: "string" },
403
+ rename: { maxLength: 64, minLength: 2, pattern: "^[A-Za-z][A-Za-z0-9\\-\\_]+\\n?$", patternSource: "[A-Za-z][A-Za-z0-9\\-\\_]+", type: "string" }
404
+ }
405
+ };
406
+
407
+ // src/proxmox/generated/constraints/pve-cluster-ha.ts
408
+ var PVE_CLUSTER_HA_CONSTRAINTS = {
409
+ "pve:POST /cluster/ha/resources": {
410
+ comment: { maxLength: 4096, type: "string" },
411
+ group: { format: "pve-configid", type: "string" },
412
+ max_relocate: { default: "1", minimum: 0, type: "integer" },
413
+ max_restart: { default: "1", minimum: 0, type: "integer" },
414
+ sid: { format: "pve-ha-resource-or-vm-id", required: true, type: "string" },
415
+ state: { default: "started", enum: ["started", "stopped", "enabled", "disabled", "ignored"], type: "string" },
416
+ type: { enum: ["ct", "vm"], type: "string" }
417
+ },
418
+ "pve:POST /cluster/ha/rules": {
419
+ affinity: { enum: ["positive", "negative"], type: "string" },
420
+ comment: { maxLength: 4096, type: "string" },
421
+ resources: { format: "pve-ha-resource-id-list", required: true, type: "string" },
422
+ rule: { format: "pve-configid", required: true, type: "string" }
423
+ },
424
+ "pve:PUT /cluster/ha/resources/{sid}": {
425
+ comment: { maxLength: 4096, type: "string" },
426
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
427
+ digest: { maxLength: 64, type: "string" },
428
+ group: { format: "pve-configid", type: "string" },
429
+ max_relocate: { default: "1", minimum: 0, type: "integer" },
430
+ max_restart: { default: "1", minimum: 0, type: "integer" },
431
+ state: { default: "started", enum: ["started", "stopped", "enabled", "disabled", "ignored"], type: "string" }
432
+ },
433
+ "pve:PUT /cluster/ha/rules/{rule}": {
434
+ affinity: { enum: ["positive", "negative"], type: "string" },
435
+ comment: { maxLength: 4096, type: "string" },
436
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
437
+ digest: { maxLength: 64, type: "string" },
438
+ resources: { format: "pve-ha-resource-id-list", type: "string" }
439
+ }
440
+ };
441
+
442
+ // src/proxmox/generated/constraints/pve-cluster-metrics.ts
443
+ var PVE_CLUSTER_METRICS_CONSTRAINTS = {
444
+ "pve:POST /cluster/metrics/server/{id}": {
445
+ influxdbproto: { default: "udp", enum: ["udp", "http", "https"], type: "string" },
446
+ "max-body-size": { default: "25000000", minimum: 1, type: "integer" },
447
+ mtu: { default: "1500", maximum: 65536, minimum: 512, type: "integer" },
448
+ "otel-compression": { default: "gzip", enum: ["none", "gzip"], type: "string" },
449
+ "otel-headers": { maxLength: 1024, type: "string" },
450
+ "otel-max-body-size": { default: "10000000", minimum: 1024, type: "integer" },
451
+ "otel-protocol": { default: "https", enum: ["http", "https"], type: "string" },
452
+ "otel-resource-attributes": { maxLength: 1024, type: "string" },
453
+ "otel-timeout": { default: "5", maximum: 10, minimum: 1, type: "integer" },
454
+ path: { format: "graphite-path", type: "string" },
455
+ port: { maximum: 65536, minimum: 1, required: true, type: "integer" },
456
+ proto: { enum: ["udp", "tcp"], type: "string" },
457
+ server: { format: "address", required: true, type: "string" },
458
+ timeout: { default: "1", minimum: 0, type: "integer" },
459
+ type: { enum: ["graphite", "influxdb", "opentelemetry"], format: "pve-configid", required: true, type: "string" }
460
+ },
461
+ "pve:PUT /cluster/metrics/server/{id}": {
462
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
463
+ digest: { maxLength: 64, type: "string" },
464
+ influxdbproto: { default: "udp", enum: ["udp", "http", "https"], type: "string" },
465
+ "max-body-size": { default: "25000000", minimum: 1, type: "integer" },
466
+ mtu: { default: "1500", maximum: 65536, minimum: 512, type: "integer" },
467
+ "otel-compression": { default: "gzip", enum: ["none", "gzip"], type: "string" },
468
+ "otel-headers": { maxLength: 1024, type: "string" },
469
+ "otel-max-body-size": { default: "10000000", minimum: 1024, type: "integer" },
470
+ "otel-protocol": { default: "https", enum: ["http", "https"], type: "string" },
471
+ "otel-resource-attributes": { maxLength: 1024, type: "string" },
472
+ "otel-timeout": { default: "5", maximum: 10, minimum: 1, type: "integer" },
473
+ path: { format: "graphite-path", type: "string" },
474
+ port: { maximum: 65536, minimum: 1, required: true, type: "integer" },
475
+ proto: { enum: ["udp", "tcp"], type: "string" },
476
+ server: { format: "address", required: true, type: "string" },
477
+ timeout: { default: "1", minimum: 0, type: "integer" }
478
+ }
479
+ };
480
+
481
+ // src/proxmox/generated/constraints/pve-cluster-notifications.ts
482
+ var PVE_CLUSTER_NOTIFICATIONS_CONSTRAINTS = {
483
+ "pve:POST /cluster/notifications/endpoints/gotify": {
484
+ name: { format: "pve-configid", required: true, type: "string" },
485
+ server: { required: true, type: "string" },
486
+ token: { required: true, type: "string" }
487
+ },
488
+ "pve:POST /cluster/notifications/endpoints/sendmail": {
489
+ mailto: { each: true, format: "email-or-username", type: "array" },
490
+ "mailto-user": { each: true, format: "pve-userid", type: "array" },
491
+ name: { format: "pve-configid", required: true, type: "string" }
492
+ },
493
+ "pve:POST /cluster/notifications/endpoints/smtp": {
494
+ "from-address": { required: true, type: "string" },
495
+ mailto: { each: true, format: "email-or-username", type: "array" },
496
+ "mailto-user": { each: true, format: "pve-userid", type: "array" },
497
+ mode: { default: "tls", enum: ["insecure", "starttls", "tls"], type: "string" },
498
+ name: { format: "pve-configid", required: true, type: "string" },
499
+ server: { required: true, type: "string" }
500
+ },
501
+ "pve:POST /cluster/notifications/endpoints/webhook": {
502
+ method: { enum: ["post", "put", "get"], required: true, type: "string" },
503
+ name: { format: "pve-configid", required: true, type: "string" },
504
+ url: { required: true, type: "string" }
505
+ },
506
+ "pve:POST /cluster/notifications/matchers": {
507
+ mode: { default: "all", enum: ["all", "any"], type: "string" },
508
+ name: { format: "pve-configid", required: true, type: "string" },
509
+ target: { each: true, format: "pve-configid", type: "array" }
510
+ },
511
+ "pve:PUT /cluster/notifications/endpoints/gotify/{name}": {
512
+ delete: { each: true, format: "pve-configid", type: "array" },
513
+ digest: { maxLength: 64, type: "string" }
514
+ },
515
+ "pve:PUT /cluster/notifications/endpoints/sendmail/{name}": {
516
+ delete: { each: true, format: "pve-configid", type: "array" },
517
+ digest: { maxLength: 64, type: "string" },
518
+ mailto: { each: true, format: "email-or-username", type: "array" },
519
+ "mailto-user": { each: true, format: "pve-userid", type: "array" }
520
+ },
521
+ "pve:PUT /cluster/notifications/endpoints/smtp/{name}": {
522
+ delete: { each: true, format: "pve-configid", type: "array" },
523
+ digest: { maxLength: 64, type: "string" },
524
+ mailto: { each: true, format: "email-or-username", type: "array" },
525
+ "mailto-user": { each: true, format: "pve-userid", type: "array" },
526
+ mode: { default: "tls", enum: ["insecure", "starttls", "tls"], type: "string" }
527
+ },
528
+ "pve:PUT /cluster/notifications/endpoints/webhook/{name}": {
529
+ delete: { each: true, format: "pve-configid", type: "array" },
530
+ digest: { maxLength: 64, type: "string" },
531
+ method: { enum: ["post", "put", "get"], type: "string" }
532
+ },
533
+ "pve:PUT /cluster/notifications/matchers/{name}": {
534
+ delete: { each: true, format: "pve-configid", type: "array" },
535
+ digest: { maxLength: 64, type: "string" },
536
+ mode: { default: "all", enum: ["all", "any"], type: "string" },
537
+ target: { each: true, format: "pve-configid", type: "array" }
538
+ }
539
+ };
540
+
541
+ // src/proxmox/generated/constraints/pve-cluster-replication.ts
542
+ var PVE_CLUSTER_REPLICATION_CONSTRAINTS = {
543
+ "pve:POST /cluster/replication": {
544
+ comment: { maxLength: 4096, type: "string" },
545
+ id: { format: "pve-replication-job-id", pattern: "^[1-9][0-9]{2,8}-\\d{1,9}\\n?$", patternSource: "[1-9][0-9]{2,8}-\\d{1,9}", required: true, type: "string" },
546
+ rate: { minimum: 1, type: "number" },
547
+ remove_job: { enum: ["local", "full"], type: "string" },
548
+ schedule: { default: "*/15", format: "pve-calendar-event", maxLength: 128, type: "string" },
549
+ source: { format: "pve-node", type: "string" },
550
+ target: { format: "pve-node", required: true, type: "string" },
551
+ type: { enum: ["local"], required: true, type: "string" }
552
+ },
553
+ "pve:PUT /cluster/replication/{id}": {
554
+ comment: { maxLength: 4096, type: "string" },
555
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
556
+ digest: { maxLength: 64, type: "string" },
557
+ rate: { minimum: 1, type: "number" },
558
+ remove_job: { enum: ["local", "full"], type: "string" },
559
+ schedule: { default: "*/15", format: "pve-calendar-event", maxLength: 128, type: "string" },
560
+ source: { format: "pve-node", type: "string" }
561
+ }
562
+ };
563
+
564
+ // src/proxmox/generated/constraints/pve-cluster-sdn.ts
565
+ var PVE_CLUSTER_SDN_CONSTRAINTS = {
566
+ "pve:POST /cluster/sdn/vnets": {
567
+ alias: { maxLength: 256, patternSource: "(?^i:[\\(\\)-_.\\w\\d\\s]{0,256})", type: "string" },
568
+ tag: { maximum: 16777215, minimum: 1, type: "integer" },
569
+ type: { enum: ["vnet"], type: "string" },
570
+ vnet: { maxLength: 8, minLength: 2, pattern: "^[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]\\n?$", patternSource: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", required: true, type: "string" },
571
+ zone: { required: true, type: "string" }
572
+ },
573
+ "pve:POST /cluster/sdn/vnets/{vnet}/subnets": {
574
+ "dhcp-dns-server": { format: "ip", type: "string" },
575
+ "dhcp-range": { each: true, format: "pve-sdn-dhcp-range", type: "array" },
576
+ dnszoneprefix: { format: "dns-name", type: "string" },
577
+ gateway: { format: "ip", type: "string" },
578
+ subnet: { format: "pve-sdn-subnet-id", required: true, type: "string" },
579
+ type: { enum: ["subnet"], required: true, type: "string" }
580
+ },
581
+ "pve:POST /cluster/sdn/zones": {
582
+ dhcp: { enum: ["dnsmasq"], type: "string" },
583
+ dnszone: { format: "dns-name", type: "string" },
584
+ exitnodes: { format: "pve-node-list", type: "string" },
585
+ "exitnodes-primary": { format: "pve-node", type: "string" },
586
+ fabric: { format: "pve-sdn-fabric-id", type: "string" },
587
+ mac: { format: "mac-addr", type: "string" },
588
+ nodes: { format: "pve-node-list", type: "string" },
589
+ peers: { format: "ip-list", type: "string" },
590
+ "rt-import": { format: "pve-sdn-bgp-rt-list", type: "string" },
591
+ "secondary-controllers": { each: true, maxLength: 64, minLength: 2, pattern: "^[a-zA-Z][a-zA-Z0-9_-]*[a-zA-Z0-9]\\n?$", patternSource: "[a-zA-Z][a-zA-Z0-9_-]*[a-zA-Z0-9]", type: "array" },
592
+ tag: { minimum: 0, type: "integer" },
593
+ type: { enum: ["evpn", "faucet", "qinq", "simple", "vlan", "vxlan"], format: "pve-configid", required: true, type: "string" },
594
+ "vlan-protocol": { default: "802.1q", enum: ["802.1q", "802.1ad"], type: "string" },
595
+ "vrf-vxlan": { maximum: 16777215, minimum: 1, type: "integer" },
596
+ "vxlan-port": { default: "4789", maximum: 65536, minimum: 1, type: "integer" },
597
+ zone: { maxLength: 8, minLength: 2, pattern: "^[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]\\n?$", patternSource: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", required: true, type: "string" }
598
+ },
599
+ "pve:PUT /cluster/sdn": {},
600
+ "pve:PUT /cluster/sdn/vnets/{vnet}": {
601
+ alias: { maxLength: 256, patternSource: "(?^i:[\\(\\)-_.\\w\\d\\s]{0,256})", type: "string" },
602
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
603
+ digest: { maxLength: 64, type: "string" },
604
+ tag: { maximum: 16777215, minimum: 1, type: "integer" }
605
+ },
606
+ "pve:PUT /cluster/sdn/vnets/{vnet}/subnets/{subnet}": {
607
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
608
+ "dhcp-dns-server": { format: "ip", type: "string" },
609
+ "dhcp-range": { each: true, format: "pve-sdn-dhcp-range", type: "array" },
610
+ digest: { maxLength: 64, type: "string" },
611
+ dnszoneprefix: { format: "dns-name", type: "string" },
612
+ gateway: { format: "ip", type: "string" }
613
+ },
614
+ "pve:PUT /cluster/sdn/zones/{zone}": {
615
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
616
+ dhcp: { enum: ["dnsmasq"], type: "string" },
617
+ digest: { maxLength: 64, type: "string" },
618
+ dnszone: { format: "dns-name", type: "string" },
619
+ exitnodes: { format: "pve-node-list", type: "string" },
620
+ "exitnodes-primary": { format: "pve-node", type: "string" },
621
+ fabric: { format: "pve-sdn-fabric-id", type: "string" },
622
+ mac: { format: "mac-addr", type: "string" },
623
+ nodes: { format: "pve-node-list", type: "string" },
624
+ peers: { format: "ip-list", type: "string" },
625
+ "rt-import": { format: "pve-sdn-bgp-rt-list", type: "string" },
626
+ "secondary-controllers": { each: true, maxLength: 64, minLength: 2, pattern: "^[a-zA-Z][a-zA-Z0-9_-]*[a-zA-Z0-9]\\n?$", patternSource: "[a-zA-Z][a-zA-Z0-9_-]*[a-zA-Z0-9]", type: "array" },
627
+ tag: { minimum: 0, type: "integer" },
628
+ "vlan-protocol": { default: "802.1q", enum: ["802.1q", "802.1ad"], type: "string" },
629
+ "vrf-vxlan": { maximum: 16777215, minimum: 1, type: "integer" },
630
+ "vxlan-port": { default: "4789", maximum: 65536, minimum: 1, type: "integer" }
631
+ }
632
+ };
633
+
634
+ // src/proxmox/generated/constraints/pve-nodes-ceph.ts
635
+ var PVE_NODES_CEPH_CONSTRAINTS = {
636
+ "pve:POST /nodes/{node}/ceph/fs/{name}": {
637
+ pg_num: { default: "128", maximum: 32768, minimum: 8, type: "integer" }
638
+ },
639
+ "pve:POST /nodes/{node}/ceph/mds/{name}": {},
640
+ "pve:POST /nodes/{node}/ceph/mgr/{id}": {},
641
+ "pve:POST /nodes/{node}/ceph/mon/{monid}": {
642
+ "mon-address": { format: "ip-list", type: "string" }
643
+ },
644
+ "pve:POST /nodes/{node}/ceph/osd": {
645
+ db_dev_size: { minimum: 1, type: "number" },
646
+ dev: { required: true, type: "string" },
647
+ "osds-per-device": { minimum: 1, type: "integer" },
648
+ wal_dev_size: { minimum: 0.5, type: "number" }
649
+ },
650
+ "pve:POST /nodes/{node}/ceph/pool": {
651
+ application: { default: "rbd", enum: ["rbd", "cephfs", "rgw"], type: "string" },
652
+ min_size: { default: "2", maximum: 7, minimum: 1, type: "integer" },
653
+ name: { patternSource: "(?^:^[^:/\\s]+$)", required: true, type: "string" },
654
+ pg_autoscale_mode: { default: "warn", enum: ["on", "off", "warn"], type: "string" },
655
+ pg_num: { default: "128", maximum: 32768, minimum: 1, type: "integer" },
656
+ pg_num_min: { maximum: 32768, type: "integer" },
657
+ size: { default: "3", maximum: 7, minimum: 1, type: "integer" },
658
+ target_size: { pattern: "^^(\\d+(\\.\\d+)?)([KMGT])?$\\n?$", patternSource: "^(\\d+(\\.\\d+)?)([KMGT])?$", type: "string" }
659
+ },
660
+ "pve:PUT /nodes/{node}/ceph/pool/{name}": {
661
+ application: { enum: ["rbd", "cephfs", "rgw"], type: "string" },
662
+ min_size: { maximum: 7, minimum: 1, type: "integer" },
663
+ pg_autoscale_mode: { enum: ["on", "off", "warn"], type: "string" },
664
+ pg_num: { maximum: 32768, minimum: 1, type: "integer" },
665
+ pg_num_min: { maximum: 32768, type: "integer" },
666
+ size: { maximum: 7, minimum: 1, type: "integer" },
667
+ target_size: { pattern: "^^(\\d+(\\.\\d+)?)([KMGT])?$\\n?$", patternSource: "^(\\d+(\\.\\d+)?)([KMGT])?$", type: "string" }
668
+ }
669
+ };
670
+
671
+ // src/proxmox/generated/constraints/pve-nodes-disks.ts
672
+ var PVE_NODES_DISKS_CONSTRAINTS = {
673
+ "pve:POST /nodes/{node}/disks/zfs": {
674
+ ashift: { default: "12", maximum: 16, minimum: 9, type: "integer" },
675
+ compression: { default: "on", enum: ["on", "off", "gzip", "lz4", "lzjb", "zle", "zstd"], type: "string" },
676
+ devices: { format: "string-list", required: true, type: "string" },
677
+ name: { format: "pve-storage-id", required: true, type: "string" },
678
+ raidlevel: { enum: ["single", "mirror", "raid10", "raidz", "raidz2", "raidz3", "draid", "draid2", "draid3"], required: true, type: "string" }
679
+ }
680
+ };
681
+
682
+ // src/proxmox/generated/constraints/pve-nodes-lxc.ts
683
+ var PVE_NODES_LXC_CONSTRAINTS = {
684
+ "pve:POST /nodes/{node}/lxc": {
685
+ arch: { default: "amd64", enum: ["amd64", "i386", "arm64", "armhf", "riscv32", "riscv64"], type: "string" },
686
+ bwlimit: { default: "restore limit from datacenter or storage config", minimum: 0, type: "number" },
687
+ cmode: { default: "tty", enum: ["shell", "console", "tty"], type: "string" },
688
+ cores: { maximum: 8192, minimum: 1, type: "integer" },
689
+ cpulimit: { default: "0", maximum: 8192, minimum: 0, type: "number" },
690
+ cpuunits: { default: "cgroup v1: 1024, cgroup v2: 100", maximum: 500000, minimum: 0, type: "integer" },
691
+ description: { maxLength: 8192, type: "string" },
692
+ entrypoint: { default: "/sbin/init", patternSource: "(?^:[^\\x00-\\x08\\x0a-\\x1F\\x7F]+)", type: "string" },
693
+ env: { patternSource: "(?^:(?:\\w+=[^\\x00-\\x08\\x0a-\\x1F\\x7F]*)(?:\\0\\w+=[^\\x00-\\x08\\x0a-\\x1F\\x7F]*)*)", type: "string" },
694
+ hookscript: { format: "pve-volume-id", type: "string" },
695
+ hostname: { format: "dns-name", maxLength: 255, type: "string" },
696
+ lock: { enum: ["backup", "create", "destroyed", "disk", "fstrim", "migrate", "mounted", "rollback", "snapshot", "snapshot-delete"], type: "string" },
697
+ memory: { default: "512", minimum: 16, type: "integer" },
698
+ nameserver: { format: "lxc-ip-with-ll-iface-list", type: "string" },
699
+ ostemplate: { maxLength: 255, required: true, type: "string" },
700
+ ostype: { enum: ["debian", "devuan", "ubuntu", "centos", "fedora", "opensuse", "archlinux", "alpine", "gentoo", "nixos", "unmanaged"], type: "string" },
701
+ password: { minLength: 5, type: "string" },
702
+ pool: { format: "pve-poolid", type: "string" },
703
+ searchdomain: { format: "dns-name-list", type: "string" },
704
+ startup: { format: "pve-startup-order", type: "string" },
705
+ storage: { default: "local", format: "pve-storage-id", type: "string" },
706
+ swap: { default: "512", minimum: 0, type: "integer" },
707
+ tags: { format: "pve-tag-list", type: "string" },
708
+ timezone: { format: "pve-ct-timezone", type: "string" },
709
+ tty: { default: "2", maximum: 6, minimum: 0, type: "integer" },
710
+ vmid: { format: "pve-vmid", maximum: 999999999, minimum: 100, required: true, type: "integer" }
711
+ },
712
+ "pve:PUT /nodes/{node}/lxc/{vmid}/config": {
713
+ arch: { default: "amd64", enum: ["amd64", "i386", "arm64", "armhf", "riscv32", "riscv64"], type: "string" },
714
+ cmode: { default: "tty", enum: ["shell", "console", "tty"], type: "string" },
715
+ cores: { maximum: 8192, minimum: 1, type: "integer" },
716
+ cpulimit: { default: "0", maximum: 8192, minimum: 0, type: "number" },
717
+ cpuunits: { default: "cgroup v1: 1024, cgroup v2: 100", maximum: 500000, minimum: 0, type: "integer" },
718
+ delete: { format: "pve-configid-list", type: "string" },
719
+ description: { maxLength: 8192, type: "string" },
720
+ digest: { maxLength: 40, type: "string" },
721
+ entrypoint: { default: "/sbin/init", patternSource: "(?^:[^\\x00-\\x08\\x0a-\\x1F\\x7F]+)", type: "string" },
722
+ env: { patternSource: "(?^:(?:\\w+=[^\\x00-\\x08\\x0a-\\x1F\\x7F]*)(?:\\0\\w+=[^\\x00-\\x08\\x0a-\\x1F\\x7F]*)*)", type: "string" },
723
+ hookscript: { format: "pve-volume-id", type: "string" },
724
+ hostname: { format: "dns-name", maxLength: 255, type: "string" },
725
+ lock: { enum: ["backup", "create", "destroyed", "disk", "fstrim", "migrate", "mounted", "rollback", "snapshot", "snapshot-delete"], type: "string" },
726
+ memory: { default: "512", minimum: 16, type: "integer" },
727
+ nameserver: { format: "lxc-ip-with-ll-iface-list", type: "string" },
728
+ ostype: { enum: ["debian", "devuan", "ubuntu", "centos", "fedora", "opensuse", "archlinux", "alpine", "gentoo", "nixos", "unmanaged"], type: "string" },
729
+ revert: { format: "pve-configid-list", type: "string" },
730
+ searchdomain: { format: "dns-name-list", type: "string" },
731
+ startup: { format: "pve-startup-order", type: "string" },
732
+ swap: { default: "512", minimum: 0, type: "integer" },
733
+ tags: { format: "pve-tag-list", type: "string" },
734
+ timezone: { format: "pve-ct-timezone", type: "string" },
735
+ tty: { default: "2", maximum: 6, minimum: 0, type: "integer" }
736
+ },
737
+ "pve:PUT /nodes/{node}/lxc/{vmid}/resize": {
738
+ digest: { maxLength: 40, type: "string" },
739
+ disk: { enum: ["rootfs", "mp0", "mp1", "mp2", "mp3", "mp4", "mp5", "mp6", "mp7", "mp8", "mp9", "mp10", "mp11", "mp12", "mp13", "mp14", "mp15", "mp16", "mp17", "mp18", "mp19", "mp20", "mp21", "mp22", "mp23", "mp24", "mp25", "mp26", "mp27", "mp28", "mp29", "mp30", "mp31", "mp32", "mp33", "mp34", "mp35", "mp36", "mp37", "mp38", "mp39", "mp40", "mp41", "mp42", "mp43", "mp44", "mp45", "mp46", "mp47", "mp48", "mp49", "mp50", "mp51", "mp52", "mp53", "mp54", "mp55", "mp56", "mp57", "mp58", "mp59", "mp60", "mp61", "mp62", "mp63", "mp64", "mp65", "mp66", "mp67", "mp68", "mp69", "mp70", "mp71", "mp72", "mp73", "mp74", "mp75", "mp76", "mp77", "mp78", "mp79", "mp80", "mp81", "mp82", "mp83", "mp84", "mp85", "mp86", "mp87", "mp88", "mp89", "mp90", "mp91", "mp92", "mp93", "mp94", "mp95", "mp96", "mp97", "mp98", "mp99", "mp100", "mp101", "mp102", "mp103", "mp104", "mp105", "mp106", "mp107", "mp108", "mp109", "mp110", "mp111", "mp112", "mp113", "mp114", "mp115", "mp116", "mp117", "mp118", "mp119", "mp120", "mp121", "mp122", "mp123", "mp124", "mp125", "mp126", "mp127", "mp128", "mp129", "mp130", "mp131", "mp132", "mp133", "mp134", "mp135", "mp136", "mp137", "mp138", "mp139", "mp140", "mp141", "mp142", "mp143", "mp144", "mp145", "mp146", "mp147", "mp148", "mp149", "mp150", "mp151", "mp152", "mp153", "mp154", "mp155", "mp156", "mp157", "mp158", "mp159", "mp160", "mp161", "mp162", "mp163", "mp164", "mp165", "mp166", "mp167", "mp168", "mp169", "mp170", "mp171", "mp172", "mp173", "mp174", "mp175", "mp176", "mp177", "mp178", "mp179", "mp180", "mp181", "mp182", "mp183", "mp184", "mp185", "mp186", "mp187", "mp188", "mp189", "mp190", "mp191", "mp192", "mp193", "mp194", "mp195", "mp196", "mp197", "mp198", "mp199", "mp200", "mp201", "mp202", "mp203", "mp204", "mp205", "mp206", "mp207", "mp208", "mp209", "mp210", "mp211", "mp212", "mp213", "mp214", "mp215", "mp216", "mp217", "mp218", "mp219", "mp220", "mp221", "mp222", "mp223", "mp224", "mp225", "mp226", "mp227", "mp228", "mp229", "mp230", "mp231", "mp232", "mp233", "mp234", "mp235", "mp236", "mp237", "mp238", "mp239", "mp240", "mp241", "mp242", "mp243", "mp244", "mp245", "mp246", "mp247", "mp248", "mp249", "mp250", "mp251", "mp252", "mp253", "mp254", "mp255"], required: true, type: "string" },
740
+ size: { pattern: "^\\+?\\d+(\\.\\d+)?[KMGT]?\\n?$", patternSource: "\\+?\\d+(\\.\\d+)?[KMGT]?", required: true, type: "string" }
741
+ }
742
+ };
743
+
744
+ // src/proxmox/generated/constraints/pve-nodes-network.ts
745
+ var PVE_NODES_NETWORK_CONSTRAINTS = {
746
+ "pve:POST /nodes/{node}/network": {
747
+ address: { format: "ipv4", type: "string" },
748
+ address6: { format: "ipv6", type: "string" },
749
+ "bond-primary": { format: "pve-iface", type: "string" },
750
+ bond_mode: { enum: ["balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", "balance-slb", "lacp-balance-slb", "lacp-balance-tcp"], type: "string" },
751
+ bond_xmit_hash_policy: { enum: ["layer2", "layer2+3", "layer3+4"], type: "string" },
752
+ bridge_ports: { format: "pve-iface-list", type: "string" },
753
+ bridge_vids: { format: "pve-vlan-id-or-range-list", type: "string" },
754
+ cidr: { format: "CIDRv4", type: "string" },
755
+ cidr6: { format: "CIDRv6", type: "string" },
756
+ gateway: { format: "ipv4", type: "string" },
757
+ gateway6: { format: "ipv6", type: "string" },
758
+ iface: { format: "pve-iface", maxLength: 20, minLength: 2, required: true, type: "string" },
759
+ mtu: { maximum: 65520, minimum: 1280, type: "integer" },
760
+ netmask: { format: "ipv4mask", type: "string" },
761
+ netmask6: { maximum: 128, minimum: 0, type: "integer" },
762
+ ovs_bonds: { format: "pve-iface-list", type: "string" },
763
+ ovs_bridge: { format: "pve-iface", type: "string" },
764
+ ovs_options: { maxLength: 1024, type: "string" },
765
+ ovs_ports: { format: "pve-iface-list", type: "string" },
766
+ ovs_tag: { maximum: 4094, minimum: 1, type: "integer" },
767
+ slaves: { format: "pve-iface-list", type: "string" },
768
+ type: { enum: ["bridge", "bond", "eth", "alias", "vlan", "fabric", "OVSBridge", "OVSBond", "OVSPort", "OVSIntPort", "vnet", "unknown"], required: true, type: "string" },
769
+ "vlan-id": { maximum: 4094, minimum: 1, type: "integer" },
770
+ "vlan-raw-device": { format: "pve-iface", type: "string" }
771
+ },
772
+ "pve:PUT /nodes/{node}/network": {},
773
+ "pve:PUT /nodes/{node}/network/{iface}": {
774
+ address: { format: "ipv4", type: "string" },
775
+ address6: { format: "ipv6", type: "string" },
776
+ "bond-primary": { format: "pve-iface", type: "string" },
777
+ bond_mode: { enum: ["balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", "balance-slb", "lacp-balance-slb", "lacp-balance-tcp"], type: "string" },
778
+ bond_xmit_hash_policy: { enum: ["layer2", "layer2+3", "layer3+4"], type: "string" },
779
+ bridge_ports: { format: "pve-iface-list", type: "string" },
780
+ bridge_vids: { format: "pve-vlan-id-or-range-list", type: "string" },
781
+ cidr: { format: "CIDRv4", type: "string" },
782
+ cidr6: { format: "CIDRv6", type: "string" },
783
+ delete: { format: "pve-configid-list", type: "string" },
784
+ gateway: { format: "ipv4", type: "string" },
785
+ gateway6: { format: "ipv6", type: "string" },
786
+ mtu: { maximum: 65520, minimum: 1280, type: "integer" },
787
+ netmask: { format: "ipv4mask", type: "string" },
788
+ netmask6: { maximum: 128, minimum: 0, type: "integer" },
789
+ ovs_bonds: { format: "pve-iface-list", type: "string" },
790
+ ovs_bridge: { format: "pve-iface", type: "string" },
791
+ ovs_options: { maxLength: 1024, type: "string" },
792
+ ovs_ports: { format: "pve-iface-list", type: "string" },
793
+ ovs_tag: { maximum: 4094, minimum: 1, type: "integer" },
794
+ slaves: { format: "pve-iface-list", type: "string" },
795
+ type: { enum: ["bridge", "bond", "eth", "alias", "vlan", "fabric", "OVSBridge", "OVSBond", "OVSPort", "OVSIntPort", "vnet", "unknown"], required: true, type: "string" },
796
+ "vlan-id": { maximum: 4094, minimum: 1, type: "integer" },
797
+ "vlan-raw-device": { format: "pve-iface", type: "string" }
798
+ }
799
+ };
800
+
801
+ // src/proxmox/generated/constraints/pve-nodes-qemu.ts
802
+ var PVE_NODES_QEMU_CONSTRAINTS = {
803
+ "pve:POST /nodes/{node}/qemu": {
804
+ affinity: { format: "pve-cpuset", type: "string" },
805
+ "amd-sev": { format: "pve-qemu-sev-fmt", type: "string" },
806
+ arch: { enum: ["x86_64", "aarch64"], type: "string" },
807
+ archive: { maxLength: 255, type: "string" },
808
+ balloon: { minimum: 0, type: "integer" },
809
+ bios: { default: "seabios", enum: ["seabios", "ovmf"], type: "string" },
810
+ boot: { format: "pve-qm-boot", type: "string" },
811
+ bootdisk: { format: "pve-qm-bootdisk", pattern: "^(ide|sata|scsi|virtio)\\d+\\n?$", patternSource: "(ide|sata|scsi|virtio)\\d+", type: "string" },
812
+ bwlimit: { default: "restore limit from datacenter or storage config", minimum: 0, type: "integer" },
813
+ cdrom: { format: "pve-qm-ide", type: "string" },
814
+ cicustom: { format: "pve-qm-cicustom", type: "string" },
815
+ citype: { enum: ["configdrive2", "nocloud", "opennebula"], type: "string" },
816
+ cores: { default: "1", minimum: 1, type: "integer" },
817
+ cpu: { format: "pve-vm-cpu-conf", type: "string" },
818
+ cpulimit: { default: "0", maximum: 128, minimum: 0, type: "number" },
819
+ cpuunits: { default: "cgroup v1: 1024, cgroup v2: 100", maximum: 262144, minimum: 1, type: "integer" },
820
+ description: { maxLength: 8192, type: "string" },
821
+ hookscript: { format: "pve-volume-id", type: "string" },
822
+ "hostpci[n]": { format: "pve-qm-hostpci", type: "string" },
823
+ hotplug: { default: "network,disk,usb", format: "pve-hotplug-features", type: "string" },
824
+ hugepages: { enum: ["any", "2", "1024"], type: "string" },
825
+ "import-working-storage": { format: "pve-storage-id", type: "string" },
826
+ "intel-tdx": { format: "pve-qemu-tdx-fmt", type: "string" },
827
+ "ipconfig[n]": { format: "pve-qm-ipconfig", type: "string" },
828
+ keyboard: { enum: ["de", "de-ch", "da", "en-gb", "en-us", "es", "fi", "fr", "fr-be", "fr-ca", "fr-ch", "hu", "is", "it", "ja", "lt", "mk", "nl", "no", "pl", "pt", "pt-br", "sv", "sl", "tr"], type: "string" },
829
+ lock: { enum: ["backup", "clone", "create", "migrate", "rollback", "snapshot", "snapshot-delete", "suspending", "suspended"], type: "string" },
830
+ migrate_downtime: { default: "0.1", minimum: 0, type: "number" },
831
+ migrate_speed: { default: "0", minimum: 0, type: "integer" },
832
+ name: { format: "dns-name", type: "string" },
833
+ nameserver: { format: "address-list", type: "string" },
834
+ ostype: { default: "other", enum: ["other", "wxp", "w2k", "w2k3", "w2k8", "wvista", "win7", "win8", "win10", "win11", "l24", "l26", "solaris"], type: "string" },
835
+ "parallel[n]": { pattern: "^/dev/parport\\d+|/dev/usb/lp\\d+\\n?$", patternSource: "/dev/parport\\d+|/dev/usb/lp\\d+", type: "string" },
836
+ pool: { format: "pve-poolid", type: "string" },
837
+ rng0: { format: "pve-qm-rng", type: "string" },
838
+ scsihw: { default: "lsi", enum: ["lsi", "lsi53c810", "virtio-scsi-pci", "virtio-scsi-single", "megasas", "pvscsi"], type: "string" },
839
+ "serial[n]": { pattern: "^(/dev/[^,]+|socket)\\n?$", patternSource: "(/dev/[^,]+|socket)", type: "string" },
840
+ shares: { default: "1000", maximum: 50000, minimum: 0, type: "integer" },
841
+ smbios1: { format: "pve-qm-smbios1", maxLength: 512, type: "string" },
842
+ smp: { default: "1", minimum: 1, type: "integer" },
843
+ sockets: { default: "1", minimum: 1, type: "integer" },
844
+ sshkeys: { format: "urlencoded", type: "string" },
845
+ startdate: { default: "now", pattern: "^(now|\\d{4}-\\d{1,2}-\\d{1,2}(T\\d{1,2}:\\d{1,2}:\\d{1,2})?)\\n?$", patternSource: "(now|\\d{4}-\\d{1,2}-\\d{1,2}(T\\d{1,2}:\\d{1,2}:\\d{1,2})?)", type: "string" },
846
+ startup: { format: "pve-startup-order", type: "string" },
847
+ storage: { format: "pve-storage-id", type: "string" },
848
+ tags: { format: "pve-tag-list", type: "string" },
849
+ vcpus: { default: "0", minimum: 1, type: "integer" },
850
+ vmgenid: { default: "1 (autogenerated)", pattern: "^(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])\\n?$", patternSource: "(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])", type: "string" },
851
+ vmid: { format: "pve-vmid", maximum: 999999999, minimum: 100, required: true, type: "integer" },
852
+ vmstatestorage: { format: "pve-storage-id", type: "string" },
853
+ watchdog: { format: "pve-qm-watchdog", type: "string" }
854
+ },
855
+ "pve:PUT /nodes/{node}/qemu/{vmid}/config": {
856
+ affinity: { format: "pve-cpuset", type: "string" },
857
+ "amd-sev": { format: "pve-qemu-sev-fmt", type: "string" },
858
+ arch: { enum: ["x86_64", "aarch64"], type: "string" },
859
+ balloon: { minimum: 0, type: "integer" },
860
+ bios: { default: "seabios", enum: ["seabios", "ovmf"], type: "string" },
861
+ boot: { format: "pve-qm-boot", type: "string" },
862
+ bootdisk: { format: "pve-qm-bootdisk", pattern: "^(ide|sata|scsi|virtio)\\d+\\n?$", patternSource: "(ide|sata|scsi|virtio)\\d+", type: "string" },
863
+ cdrom: { format: "pve-qm-ide", type: "string" },
864
+ cicustom: { format: "pve-qm-cicustom", type: "string" },
865
+ citype: { enum: ["configdrive2", "nocloud", "opennebula"], type: "string" },
866
+ cores: { default: "1", minimum: 1, type: "integer" },
867
+ cpu: { format: "pve-vm-cpu-conf", type: "string" },
868
+ cpulimit: { default: "0", maximum: 128, minimum: 0, type: "number" },
869
+ cpuunits: { default: "cgroup v1: 1024, cgroup v2: 100", maximum: 262144, minimum: 1, type: "integer" },
870
+ delete: { format: "pve-configid-list", type: "string" },
871
+ description: { maxLength: 8192, type: "string" },
872
+ digest: { maxLength: 40, type: "string" },
873
+ hookscript: { format: "pve-volume-id", type: "string" },
874
+ "hostpci[n]": { format: "pve-qm-hostpci", type: "string" },
875
+ hotplug: { default: "network,disk,usb", format: "pve-hotplug-features", type: "string" },
876
+ hugepages: { enum: ["any", "2", "1024"], type: "string" },
877
+ "intel-tdx": { format: "pve-qemu-tdx-fmt", type: "string" },
878
+ "ipconfig[n]": { format: "pve-qm-ipconfig", type: "string" },
879
+ keyboard: { enum: ["de", "de-ch", "da", "en-gb", "en-us", "es", "fi", "fr", "fr-be", "fr-ca", "fr-ch", "hu", "is", "it", "ja", "lt", "mk", "nl", "no", "pl", "pt", "pt-br", "sv", "sl", "tr"], type: "string" },
880
+ lock: { enum: ["backup", "clone", "create", "migrate", "rollback", "snapshot", "snapshot-delete", "suspending", "suspended"], type: "string" },
881
+ migrate_downtime: { default: "0.1", minimum: 0, type: "number" },
882
+ migrate_speed: { default: "0", minimum: 0, type: "integer" },
883
+ name: { format: "dns-name", type: "string" },
884
+ nameserver: { format: "address-list", type: "string" },
885
+ ostype: { default: "other", enum: ["other", "wxp", "w2k", "w2k3", "w2k8", "wvista", "win7", "win8", "win10", "win11", "l24", "l26", "solaris"], type: "string" },
886
+ "parallel[n]": { pattern: "^/dev/parport\\d+|/dev/usb/lp\\d+\\n?$", patternSource: "/dev/parport\\d+|/dev/usb/lp\\d+", type: "string" },
887
+ revert: { format: "pve-configid-list", type: "string" },
888
+ rng0: { format: "pve-qm-rng", type: "string" },
889
+ scsihw: { default: "lsi", enum: ["lsi", "lsi53c810", "virtio-scsi-pci", "virtio-scsi-single", "megasas", "pvscsi"], type: "string" },
890
+ "serial[n]": { pattern: "^(/dev/[^,]+|socket)\\n?$", patternSource: "(/dev/[^,]+|socket)", type: "string" },
891
+ shares: { default: "1000", maximum: 50000, minimum: 0, type: "integer" },
892
+ smbios1: { format: "pve-qm-smbios1", maxLength: 512, type: "string" },
893
+ smp: { default: "1", minimum: 1, type: "integer" },
894
+ sockets: { default: "1", minimum: 1, type: "integer" },
895
+ sshkeys: { format: "urlencoded", type: "string" },
896
+ startdate: { default: "now", pattern: "^(now|\\d{4}-\\d{1,2}-\\d{1,2}(T\\d{1,2}:\\d{1,2}:\\d{1,2})?)\\n?$", patternSource: "(now|\\d{4}-\\d{1,2}-\\d{1,2}(T\\d{1,2}:\\d{1,2}:\\d{1,2})?)", type: "string" },
897
+ startup: { format: "pve-startup-order", type: "string" },
898
+ tags: { format: "pve-tag-list", type: "string" },
899
+ vcpus: { default: "0", minimum: 1, type: "integer" },
900
+ vmgenid: { default: "1 (autogenerated)", pattern: "^(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])\\n?$", patternSource: "(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])", type: "string" },
901
+ vmstatestorage: { format: "pve-storage-id", type: "string" },
902
+ watchdog: { format: "pve-qm-watchdog", type: "string" }
903
+ }
904
+ };
905
+
906
+ // src/proxmox/generated/constraints/pve-pools.ts
907
+ var PVE_POOLS_CONSTRAINTS = {
908
+ "pve:POST /pools": {
909
+ poolid: { format: "pve-poolid", required: true, type: "string" }
910
+ },
911
+ "pve:PUT /pools/{poolid}": {
912
+ storage: { format: "pve-storage-id-list", type: "string" },
913
+ vms: { format: "pve-vmid-list", type: "string" }
914
+ }
915
+ };
916
+
917
+ // src/proxmox/generated/constraints/pve-storage.ts
918
+ var PVE_STORAGE_CONSTRAINTS = {
919
+ "pve:POST /storage": {
920
+ base: { format: "pve-volume-id", type: "string" },
921
+ blocksize: { format: "pve-storage-zfs-blocksize", type: "string" },
922
+ content: { format: "pve-storage-content-list", type: "string" },
923
+ "content-dirs": { format: "pve-dir-override-list", type: "string" },
924
+ domain: { maxLength: 256, type: "string" },
925
+ export: { format: "pve-storage-path", type: "string" },
926
+ fingerprint: { pattern: "^([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}\\n?$", patternSource: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", type: "string" },
927
+ format: { enum: ["raw", "qcow2", "subvol", "vmdk"], type: "string" },
928
+ "fs-name": { format: "pve-configid", type: "string" },
929
+ "max-protected-backups": { default: "Unlimited for users with Datastore.Allocate privilege, 5 for other users", minimum: -1, type: "integer" },
930
+ monhost: { format: "pve-storage-portal-dns-list", type: "string" },
931
+ mountpoint: { format: "pve-storage-path", type: "string" },
932
+ nodes: { format: "pve-node-list", type: "string" },
933
+ options: { format: "pve-storage-options", type: "string" },
934
+ password: { maxLength: 256, type: "string" },
935
+ path: { format: "pve-storage-path", type: "string" },
936
+ port: { maximum: 65535, minimum: 1, type: "integer" },
937
+ portal: { format: "pve-storage-portal-dns", type: "string" },
938
+ preallocation: { default: "metadata", enum: ["off", "metadata", "falloc", "full"], type: "string" },
939
+ "prune-backups": { format: "prune-backups", type: "string" },
940
+ "saferemove-stepsize": { default: "32", enum: ["1", "2", "4", "8", "16", "32"], type: "integer" },
941
+ server: { format: "pve-storage-server", type: "string" },
942
+ smbversion: { default: "default", enum: ["default", "2.0", "2.1", "3", "3.0", "3.11"], type: "string" },
943
+ storage: { format: "pve-storage-id", required: true, type: "string" },
944
+ subdir: { format: "pve-storage-path", type: "string" },
945
+ thinpool: { format: "pve-storage-vgname", type: "string" },
946
+ type: { enum: ["btrfs", "cephfs", "cifs", "dir", "esxi", "iscsi", "iscsidirect", "lvm", "lvmthin", "nfs", "pbs", "rbd", "zfs", "zfspool"], required: true, type: "string" },
947
+ vgname: { format: "pve-storage-vgname", type: "string" },
948
+ "zfs-base-path": { format: "pve-storage-path", type: "string" }
949
+ },
950
+ "pve:PUT /storage/{storage}": {
951
+ blocksize: { format: "pve-storage-zfs-blocksize", type: "string" },
952
+ content: { format: "pve-storage-content-list", type: "string" },
953
+ "content-dirs": { format: "pve-dir-override-list", type: "string" },
954
+ delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
955
+ digest: { maxLength: 64, type: "string" },
956
+ domain: { maxLength: 256, type: "string" },
957
+ fingerprint: { pattern: "^([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}\\n?$", patternSource: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", type: "string" },
958
+ format: { enum: ["raw", "qcow2", "subvol", "vmdk"], type: "string" },
959
+ "fs-name": { format: "pve-configid", type: "string" },
960
+ "max-protected-backups": { default: "Unlimited for users with Datastore.Allocate privilege, 5 for other users", minimum: -1, type: "integer" },
961
+ monhost: { format: "pve-storage-portal-dns-list", type: "string" },
962
+ mountpoint: { format: "pve-storage-path", type: "string" },
963
+ nodes: { format: "pve-node-list", type: "string" },
964
+ options: { format: "pve-storage-options", type: "string" },
965
+ password: { maxLength: 256, type: "string" },
966
+ port: { maximum: 65535, minimum: 1, type: "integer" },
967
+ preallocation: { default: "metadata", enum: ["off", "metadata", "falloc", "full"], type: "string" },
968
+ "prune-backups": { format: "prune-backups", type: "string" },
969
+ "saferemove-stepsize": { default: "32", enum: ["1", "2", "4", "8", "16", "32"], type: "integer" },
970
+ server: { format: "pve-storage-server", type: "string" },
971
+ smbversion: { default: "default", enum: ["default", "2.0", "2.1", "3", "3.0", "3.11"], type: "string" },
972
+ subdir: { format: "pve-storage-path", type: "string" },
973
+ "zfs-base-path": { format: "pve-storage-path", type: "string" }
974
+ }
975
+ };
976
+
977
+ // src/proxmox/generated/constraints/pbs-config.ts
978
+ var PBS_CONFIG_CONSTRAINTS = {
979
+ "pbs:POST /config/datastore": {
980
+ "backing-device": { pattern: "^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$", patternSource: "/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/", type: "string" },
981
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
982
+ "keep-daily": { minimum: 1, type: "integer" },
983
+ "keep-hourly": { minimum: 1, type: "integer" },
984
+ "keep-last": { minimum: 1, type: "integer" },
985
+ "keep-monthly": { minimum: 1, type: "integer" },
986
+ "keep-weekly": { minimum: 1, type: "integer" },
987
+ "keep-yearly": { minimum: 1, type: "integer" },
988
+ name: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
989
+ "notification-mode": { default: "notification-system", enum: ["legacy-sendmail", "notification-system"], type: "string" },
990
+ "notify-user": { maxLength: 64, minLength: 3, pattern: "^(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
991
+ path: { maxLength: 4096, minLength: 1, required: true, type: "string" }
992
+ },
993
+ "pbs:POST /config/notifications/endpoints/sendmail": {
994
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
995
+ mailto: { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
996
+ "mailto-user": { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
997
+ name: { maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
998
+ origin: { enum: ["user-created", "builtin", "modified-builtin"], type: "string" }
999
+ },
1000
+ "pbs:POST /config/notifications/endpoints/smtp": {
1001
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1002
+ "from-address": { required: true, type: "string" },
1003
+ mailto: { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
1004
+ "mailto-user": { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
1005
+ mode: { default: "tls", enum: ["insecure", "starttls", "tls"], type: "string" },
1006
+ name: { maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1007
+ origin: { enum: ["user-created", "builtin", "modified-builtin"], type: "string" },
1008
+ port: { maximum: 65535, minimum: 0, type: "integer" },
1009
+ server: { required: true, type: "string" }
1010
+ },
1011
+ "pbs:POST /config/notifications/endpoints/webhook": {
1012
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1013
+ method: { default: "post", enum: ["post", "put", "get"], required: true, type: "string" },
1014
+ name: { maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1015
+ origin: { enum: ["user-created", "builtin", "modified-builtin"], type: "string" },
1016
+ url: { pattern: "^https?://(?:(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?))|(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|\\[(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))\\]))(?::(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?)|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))(?:/[^\x00-\x1F]*)?$", patternSource: "/^https?://(?:(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?))|(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|\\[(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))\\]))(?::(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?)|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))(?:/[^\x00-\x1F]*)?$/", required: true, type: "string" }
1017
+ },
1018
+ "pbs:POST /config/notifications/matchers": {
1019
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1020
+ mode: { default: "all", enum: ["all", "any"], type: "string" },
1021
+ name: { maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1022
+ origin: { enum: ["user-created", "builtin", "modified-builtin"], type: "string" },
1023
+ target: { each: true, maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "array" }
1024
+ },
1025
+ "pbs:POST /config/prune": {
1026
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1027
+ id: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1028
+ "keep-daily": { minimum: 1, type: "integer" },
1029
+ "keep-hourly": { minimum: 1, type: "integer" },
1030
+ "keep-last": { minimum: 1, type: "integer" },
1031
+ "keep-monthly": { minimum: 1, type: "integer" },
1032
+ "keep-weekly": { minimum: 1, type: "integer" },
1033
+ "keep-yearly": { minimum: 1, type: "integer" },
1034
+ "max-depth": { maximum: 7, minimum: 0, type: "integer" },
1035
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1036
+ schedule: { required: true, type: "string" },
1037
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" }
1038
+ },
1039
+ "pbs:POST /config/sync": {
1040
+ "active-encryption-key": { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1041
+ "associated-key": { each: true, maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "array" },
1042
+ "burst-in": { maxLength: 64, minLength: 1, type: "string" },
1043
+ "burst-out": { maxLength: 64, minLength: 1, type: "string" },
1044
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1045
+ id: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1046
+ "max-depth": { maximum: 7, minimum: 0, type: "integer" },
1047
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1048
+ owner: { maxLength: 64, minLength: 3, pattern: "^(?:(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)|(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)!(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))$", patternSource: "/^(?:(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)|(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)!(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))$/", type: "string" },
1049
+ "rate-in": { maxLength: 64, minLength: 1, type: "string" },
1050
+ "rate-out": { maxLength: 64, minLength: 1, type: "string" },
1051
+ remote: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1052
+ "remote-ns": { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1053
+ "remote-store": { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1054
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1055
+ "sync-direction": { default: "pull", enum: ["pull", "push"], type: "string" },
1056
+ "transfer-last": { minimum: 1, type: "integer" },
1057
+ "worker-threads": { default: "1", maximum: 32, minimum: 1, type: "integer" }
1058
+ },
1059
+ "pbs:POST /config/verify": {
1060
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1061
+ id: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1062
+ "max-depth": { default: "7", maximum: 7, minimum: 0, type: "integer" },
1063
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1064
+ "outdated-after": { minimum: 0, type: "integer" },
1065
+ "read-threads": { default: "1", maximum: 32, minimum: 1, type: "integer" },
1066
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", required: true, type: "string" },
1067
+ "verify-threads": { default: "4", maximum: 32, minimum: 1, type: "integer" }
1068
+ },
1069
+ "pbs:PUT /config/datastore/{name}": {
1070
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1071
+ delete: { each: true, enum: ["comment", "gc-schedule", "gc-on-unmount", "prune-schedule", "keep-last", "keep-hourly", "keep-daily", "keep-weekly", "keep-monthly", "keep-yearly", "verify-new", "notify-user", "notify", "notification-mode", "tuning", "maintenance-mode", "notification-thresholds", "counter-reset-schedule"], type: "array" },
1072
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1073
+ "keep-daily": { minimum: 1, type: "integer" },
1074
+ "keep-hourly": { minimum: 1, type: "integer" },
1075
+ "keep-last": { minimum: 1, type: "integer" },
1076
+ "keep-monthly": { minimum: 1, type: "integer" },
1077
+ "keep-weekly": { minimum: 1, type: "integer" },
1078
+ "keep-yearly": { minimum: 1, type: "integer" },
1079
+ "notification-mode": { default: "notification-system", enum: ["legacy-sendmail", "notification-system"], type: "string" },
1080
+ "notify-user": { maxLength: 64, minLength: 3, pattern: "^(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" }
1081
+ },
1082
+ "pbs:PUT /config/notifications/endpoints/sendmail/{name}": {
1083
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1084
+ delete: { each: true, enum: ["author", "comment", "disable", "from-address", "mailto", "mailto-user"], type: "array" },
1085
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1086
+ mailto: { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
1087
+ "mailto-user": { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" }
1088
+ },
1089
+ "pbs:PUT /config/notifications/endpoints/smtp/{name}": {
1090
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1091
+ delete: { each: true, enum: ["author", "comment", "disable", "mailto", "mailto-user", "password", "port", "username"], type: "array" },
1092
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1093
+ mailto: { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
1094
+ "mailto-user": { each: true, maxLength: 64, minLength: 2, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "array" },
1095
+ mode: { default: "tls", enum: ["insecure", "starttls", "tls"], type: "string" },
1096
+ port: { maximum: 65535, minimum: 0, type: "integer" }
1097
+ },
1098
+ "pbs:PUT /config/notifications/endpoints/webhook/{name}": {
1099
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1100
+ delete: { each: true, enum: ["comment", "disable", "header", "body", "secret"], type: "array" },
1101
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1102
+ method: { default: "post", enum: ["post", "put", "get"], type: "string" },
1103
+ url: { pattern: "^https?://(?:(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?))|(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|\\[(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))\\]))(?::(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?)|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))(?:/[^\x00-\x1F]*)?$", patternSource: "/^https?://(?:(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?)\\.)*(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?))|(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|\\[(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))\\]))(?::(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?)|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){6})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:::(?:(?:[0-9a-fA-F]{1,4}):){5})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){4})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){3})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){2})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}):){1})(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,4}(?:[0-9a-fA-F]{1,4}))?::)(?:(?:(?:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])\\.){3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9]))|(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,5}(?:[0-9a-fA-F]{1,4}))?::)(?:[0-9a-fA-F]{1,4}))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4}):){0,6}(?:[0-9a-fA-F]{1,4}))?::))))(?:/[^\x00-\x1F]*)?$/", type: "string" }
1104
+ },
1105
+ "pbs:PUT /config/notifications/matchers/{name}": {
1106
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1107
+ delete: { each: true, enum: ["comment", "disable", "invert-match", "match-calendar", "match-field", "match-severity", "mode", "target"], type: "array" },
1108
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1109
+ mode: { default: "all", enum: ["all", "any"], type: "string" },
1110
+ target: { each: true, maxLength: 32, minLength: 2, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "array" }
1111
+ },
1112
+ "pbs:PUT /config/prune/{id}": {
1113
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1114
+ delete: { each: true, enum: ["comment", "disable", "ns", "max-depth", "keep-last", "keep-hourly", "keep-daily", "keep-weekly", "keep-monthly", "keep-yearly"], type: "array" },
1115
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1116
+ "keep-daily": { minimum: 1, type: "integer" },
1117
+ "keep-hourly": { minimum: 1, type: "integer" },
1118
+ "keep-last": { minimum: 1, type: "integer" },
1119
+ "keep-monthly": { minimum: 1, type: "integer" },
1120
+ "keep-weekly": { minimum: 1, type: "integer" },
1121
+ "keep-yearly": { minimum: 1, type: "integer" },
1122
+ "max-depth": { maximum: 7, minimum: 0, type: "integer" },
1123
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1124
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" }
1125
+ },
1126
+ "pbs:PUT /config/sync/{id}": {
1127
+ "active-encryption-key": { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1128
+ "associated-key": { each: true, maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "array" },
1129
+ "burst-in": { maxLength: 64, minLength: 1, type: "string" },
1130
+ "burst-out": { maxLength: 64, minLength: 1, type: "string" },
1131
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1132
+ delete: { each: true, enum: ["remote", "owner", "comment", "schedule", "remove-vanished", "group-filter", "rate-in", "burst-in", "rate-out", "burst-out", "ns", "remote-ns", "max-depth", "transfer-last", "encrypted-only", "verified-only", "run-on-mount", "unmount-on-done", "sync-direction", "worker-threads", "active-encryption-key", "associated-key"], type: "array" },
1133
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1134
+ "max-depth": { maximum: 7, minimum: 0, type: "integer" },
1135
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1136
+ owner: { maxLength: 64, minLength: 3, pattern: "^(?:(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)|(?:[^\\s:/\\x00-\\x1f\\x7f]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)!(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))$", patternSource: "/^(?:(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)|(?:[^\\s:/[:cntrl:]]+)@(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)!(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))$/", type: "string" },
1137
+ "rate-in": { maxLength: 64, minLength: 1, type: "string" },
1138
+ "rate-out": { maxLength: 64, minLength: 1, type: "string" },
1139
+ remote: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1140
+ "remote-ns": { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1141
+ "remote-store": { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1142
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1143
+ "sync-direction": { default: "pull", enum: ["pull", "push"], type: "string" },
1144
+ "transfer-last": { minimum: 1, type: "integer" },
1145
+ "worker-threads": { default: "1", maximum: 32, minimum: 1, type: "integer" }
1146
+ },
1147
+ "pbs:PUT /config/verify/{id}": {
1148
+ comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
1149
+ delete: { each: true, enum: ["ignore-verified", "comment", "schedule", "outdated-after", "ns", "max-depth", "read-threads", "verify-threads"], type: "array" },
1150
+ digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
1151
+ "max-depth": { default: "7", maximum: 7, minimum: 0, type: "integer" },
1152
+ ns: { maxLength: 256, pattern: "^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$", patternSource: "/^(?:(?:(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)/){0,7}(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*))?$/", type: "string" },
1153
+ "outdated-after": { minimum: 0, type: "integer" },
1154
+ "read-threads": { default: "1", maximum: 32, minimum: 1, type: "integer" },
1155
+ store: { maxLength: 32, minLength: 3, pattern: "^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$", patternSource: "/^(?:[A-Za-z0-9_][A-Za-z0-9._\\-]*)$/", type: "string" },
1156
+ "verify-threads": { default: "4", maximum: 32, minimum: 1, type: "integer" }
1157
+ }
1158
+ };
1159
+
1160
+ // src/proxmox/generated/constraints/index.ts
1161
+ var PROXMOX_CONSTRAINTS = {
1162
+ ...PVE_ACCESS_CONSTRAINTS,
1163
+ ...PVE_CLUSTER_BACKUP_CONSTRAINTS,
1164
+ ...PVE_CLUSTER_CEPH_CONSTRAINTS,
1165
+ ...PVE_CLUSTER_FIREWALL_CONSTRAINTS,
1166
+ ...PVE_CLUSTER_HA_CONSTRAINTS,
1167
+ ...PVE_CLUSTER_METRICS_CONSTRAINTS,
1168
+ ...PVE_CLUSTER_NOTIFICATIONS_CONSTRAINTS,
1169
+ ...PVE_CLUSTER_REPLICATION_CONSTRAINTS,
1170
+ ...PVE_CLUSTER_SDN_CONSTRAINTS,
1171
+ ...PVE_NODES_CEPH_CONSTRAINTS,
1172
+ ...PVE_NODES_DISKS_CONSTRAINTS,
1173
+ ...PVE_NODES_LXC_CONSTRAINTS,
1174
+ ...PVE_NODES_NETWORK_CONSTRAINTS,
1175
+ ...PVE_NODES_QEMU_CONSTRAINTS,
1176
+ ...PVE_POOLS_CONSTRAINTS,
1177
+ ...PVE_STORAGE_CONSTRAINTS,
1178
+ ...PBS_CONFIG_CONSTRAINTS
1179
+ };
1180
+
1181
+ // src/proxmox/constraint-guard.ts
1182
+ var constraintsFor = (key) => {
1183
+ const table = PROXMOX_CONSTRAINTS[key];
1184
+ if (table === undefined) {
1185
+ throw new Error(`no vendor constraint table for '${key}'. It is named in this package but not generated: ` + "run `bun codegen/constraints.ts` (see codegen/README.md).");
1186
+ }
1187
+ return table;
1188
+ };
1189
+ var formViolations = (key, form, presence) => violations(constraintsFor(key), form, { presence });
1190
+ var guardForm = (key, form, presence) => Effect5.suspend(() => {
1191
+ if (key === undefined)
1192
+ return Effect5.void;
1193
+ const found = formViolations(key, form, presence);
1194
+ return found.length === 0 ? Effect5.void : Effect5.die(new Error(refusal(key, found)));
1195
+ });
1196
+
1197
+ // src/proxmox/resource-guard.ts
1198
+ var specGuards = (spec) => {
1199
+ const endpointsOf = (props) => typeof spec.endpoint === "function" ? spec.endpoint(props) : spec.endpoint;
1200
+ const guardCreate = (props, presence) => Effect6.suspend(() => {
1201
+ const create = endpointsOf(props)?.create;
1202
+ return create === undefined ? Effect6.void : guardForm(create, spec.createForm(props), presence);
1203
+ });
1204
+ const guardUpdate = (props) => Effect6.suspend(() => {
1205
+ const update = endpointsOf(props)?.update;
1206
+ if (update === undefined)
1207
+ return Effect6.void;
1208
+ const form = spec.updateForm?.(props);
1209
+ return form === undefined ? Effect6.void : guardForm(update, form, false);
1210
+ });
1211
+ return { guardCreate, guardUpdate };
1212
+ };
1213
+
228
1214
  // src/proxmox/update-guard.ts
229
1215
  var formToSend = (matches, live, props, form) => matches(live, props) || Object.keys(form).length === 0 ? undefined : form;
230
1216
 
231
1217
  // src/proxmox/resource.ts
232
1218
  var pveOperations = (spec) => {
233
- const read = (props) => pve(props.target, spec.readRole ?? "read", "GET", spec.path(props)).pipe(Effect5.map((data) => data == null ? undefined : spec.attributes(data, props)), Effect5.orElseSucceed(() => {
1219
+ const { guardCreate, guardUpdate } = specGuards(spec);
1220
+ const read = (props) => pve(props.target, spec.readRole ?? "read", "GET", spec.path(props)).pipe(Effect7.map((data) => data == null ? undefined : spec.attributes(data, props)), Effect7.orElseSucceed(() => {
234
1221
  return;
235
1222
  }));
236
1223
  return {
1224
+ guardCreate,
1225
+ guardUpdate,
237
1226
  read,
238
- diff: (news, output) => Effect5.gen(function* () {
239
- if (output === undefined || !isResolved(news))
1227
+ diff: (news, output) => Effect7.gen(function* () {
1228
+ if (!isResolved(news))
1229
+ return;
1230
+ yield* guardCreate(news, output === undefined);
1231
+ yield* guardUpdate(news);
1232
+ if (output === undefined)
240
1233
  return;
241
1234
  const live = yield* read(news);
242
- if (live === undefined)
1235
+ if (live === undefined) {
1236
+ yield* guardCreate(news, true);
243
1237
  return { action: "update" };
1238
+ }
244
1239
  if (spec.matches(live, news))
245
1240
  return { action: "noop" };
246
1241
  return spec.updateForm === undefined ? { action: "replace" } : { action: "update" };
247
1242
  }),
248
- reconcile: (news) => Effect5.gen(function* () {
1243
+ reconcile: (news) => Effect7.gen(function* () {
249
1244
  const live = yield* read(news);
1245
+ yield* guardCreate(news, live === undefined);
1246
+ yield* guardUpdate(news);
250
1247
  if (live === undefined) {
251
1248
  yield* pve(news.target, "provision", "POST", spec.collection(news), spec.createForm(news));
252
1249
  } else if (spec.updateForm !== undefined) {
@@ -257,7 +1254,7 @@ var pveOperations = (spec) => {
257
1254
  }
258
1255
  const after = yield* read(news);
259
1256
  if (after === undefined) {
260
- return yield* Effect5.die(new Error(`${spec.path(news)}: the write returned no error but the object is still absent. ` + 'PVE wraps every answer in {"data":...} and can report success on a call that did ' + "nothing -- read back rather than trusting the status code."));
1257
+ return yield* Effect7.die(new Error(`${spec.path(news)}: the write returned no error but the object is still absent. ` + 'PVE wraps every answer in {"data":...} and can report success on a call that did ' + "nothing -- read back rather than trusting the status code."));
261
1258
  }
262
1259
  return after;
263
1260
  }),
@@ -267,7 +1264,7 @@ var pveOperations = (spec) => {
267
1264
  var pveHandlers = (spec) => {
268
1265
  const ops = pveOperations(spec);
269
1266
  return {
270
- list: () => Effect5.succeed([]),
1267
+ list: () => Effect7.succeed([]),
271
1268
  read: ({ olds }) => ops.read(olds),
272
1269
  diff: ({ news, output }) => ops.diff(news, output),
273
1270
  reconcile: ({ news }) => ops.reconcile(news),
@@ -309,29 +1306,30 @@ var ops = pveOperations({
309
1306
  readRole: "provision",
310
1307
  collection: () => "access/acl",
311
1308
  createForm: bind,
1309
+ endpoint: { create: "pve:PUT /access/acl", update: "pve:PUT /access/acl" },
312
1310
  matches: (attributes, props) => attributes.bound && attributes.propagate === (props.propagate !== false),
313
1311
  path: () => "access/acl",
314
1312
  updateForm: bind
315
1313
  });
316
- var ProxmoxAclProvider = () => Provider.effect(ProxmoxAcl, Effect6.succeed(ProxmoxAcl.Provider.of({
317
- list: () => Effect6.succeed([]),
318
- read: Effect6.fn(function* ({ olds }) {
1314
+ var ProxmoxAclProvider = () => Provider.effect(ProxmoxAcl, Effect8.succeed(ProxmoxAcl.Provider.of({
1315
+ list: () => Effect8.succeed([]),
1316
+ read: Effect8.fn(function* ({ olds }) {
319
1317
  return yield* ops.read(olds);
320
1318
  }),
321
- diff: Effect6.fn(function* ({ news, output }) {
1319
+ diff: Effect8.fn(function* ({ news, output }) {
322
1320
  if (output !== undefined && isResolved2(news) && identity(news) !== identity(output)) {
323
1321
  return { action: "replace" };
324
1322
  }
325
1323
  return yield* ops.diff(news, output);
326
1324
  }),
327
- reconcile: Effect6.fn(function* ({ news }) {
1325
+ reconcile: Effect8.fn(function* ({ news }) {
328
1326
  const after = yield* ops.reconcile(news);
329
1327
  if (!after.bound) {
330
- return yield* Effect6.die(new Error(`access/acl: the write returned no error but ${identity(news)} is still not ` + "bound. Either the PUT did nothing, or the read credential cannot see the " + "grant -- GET /access/acl is filtered to paths you may MODIFY permissions on, " + "so a read-only role is answered [] rather than 403."));
1328
+ return yield* Effect8.die(new Error(`access/acl: the write returned no error but ${identity(news)} is still not ` + "bound. Either the PUT did nothing, or the read credential cannot see the " + "grant -- GET /access/acl is filtered to paths you may MODIFY permissions on, " + "so a read-only role is answered [] rather than 403."));
331
1329
  }
332
1330
  return after;
333
1331
  }),
334
- delete: Effect6.fn(function* ({ olds }) {
1332
+ delete: Effect8.fn(function* ({ olds }) {
335
1333
  const removal = { delete: "1", ...tuple(olds) };
336
1334
  yield* pve(olds.target, "provision", "PUT", "access/acl", removal);
337
1335
  })
@@ -389,7 +1387,7 @@ var alertmanagerAlertBody = (options = {}) => {
389
1387
  // src/proxmox/api-token.ts
390
1388
  import { Resource as Resource2 } from "alchemy";
391
1389
  import * as Provider2 from "alchemy/Provider";
392
- import * as Effect7 from "effect/Effect";
1390
+ import * as Effect9 from "effect/Effect";
393
1391
 
394
1392
  // src/proxmox/values.ts
395
1393
  var num = (value, fallback) => typeof value === "number" ? value : fallback;
@@ -457,6 +1455,10 @@ var apiTokenSpec = {
457
1455
  },
458
1456
  collection: (props) => `access/users/${props.userid}/token/${props.tokenid}`,
459
1457
  createForm: shape,
1458
+ endpoint: {
1459
+ create: "pve:POST /access/users/{userid}/token/{tokenid}",
1460
+ update: "pve:PUT /access/users/{userid}/token/{tokenid}"
1461
+ },
460
1462
  matches: (attributes, props) => attributes.comment === (props.comment ?? "") && attributes.expire === props.expire && attributes.privsep === props.privsep,
461
1463
  path: (props) => `access/users/${props.userid}/token/${props.tokenid}`,
462
1464
  updateForm: shape
@@ -469,19 +1471,19 @@ var ProxmoxApiToken = Resource2("Proxmox.ApiToken", {
469
1471
  var ops2 = pveOperations(apiTokenSpec);
470
1472
  var handlers = {
471
1473
  ...pveHandlers(apiTokenSpec),
472
- reconcile: Effect7.fn(function* ({ news }) {
1474
+ reconcile: Effect9.fn(function* ({ news }) {
473
1475
  const live = yield* ops2.read(news);
474
1476
  if (live === undefined) {
475
- return yield* Effect7.die(new Error(`${news.userid}!${news.tokenid}: this resource does not create API tokens. PVE returns ` + "the secret only in the create response and it cannot be stored, so a token made here " + "would be a live credential nobody holds. Create it with `pveum user token add` and " + "capture the value, or mint a short-lived one from the OpenBao proxmox mount " + "(`bao read proxmox-c1/creds/<role>`) -- then declare it here to manage it."));
1477
+ return yield* Effect9.die(new Error(`${news.userid}!${news.tokenid}: this resource does not create API tokens. PVE returns ` + "the secret only in the create response and it cannot be stored, so a token made here " + "would be a live credential nobody holds. Create it with `pveum user token add` and " + "capture the value, or mint a short-lived one from the OpenBao proxmox mount " + "(`bao read proxmox-c1/creds/<role>`) -- then declare it here to manage it."));
476
1478
  }
477
1479
  return yield* ops2.reconcile(news);
478
1480
  })
479
1481
  };
480
- var ProxmoxApiTokenProvider = () => Provider2.effect(ProxmoxApiToken, Effect7.succeed(ProxmoxApiToken.Provider.of(handlers)));
1482
+ var ProxmoxApiTokenProvider = () => Provider2.effect(ProxmoxApiToken, Effect9.succeed(ProxmoxApiToken.Provider.of(handlers)));
481
1483
  // src/proxmox/backup-job.ts
482
1484
  import { Resource as Resource3 } from "alchemy";
483
1485
  import * as Provider3 from "alchemy/Provider";
484
- import * as Effect8 from "effect/Effect";
1486
+ import * as Effect10 from "effect/Effect";
485
1487
  var ProxmoxBackupJob = Resource3("Proxmox.BackupJob");
486
1488
  var shape2 = (props) => ({
487
1489
  all: props.all === true ? "1" : "0",
@@ -520,17 +1522,23 @@ var handlers2 = pveHandlers({
520
1522
  }),
521
1523
  collection: () => "cluster/backup",
522
1524
  createForm: (props) => ({ ...shape2(props), id: props.id }),
1525
+ endpoint: { create: "pve:POST /cluster/backup", update: "pve:PUT /cluster/backup/{id}" },
523
1526
  matches: (attributes, props) => attributes.schedule === props.schedule && attributes.enabled === (props.enabled !== false) && attributes.all === (props.all === true) && attributes.mode === (props.mode ?? "snapshot") && attributes["notification-mode"] === (props["notification-mode"] ?? "auto") && attributes["repeat-missed"] === (props["repeat-missed"] === true) && (props.storage === undefined || attributes.storage === props.storage) && (props.pool === undefined || attributes.pool === props.pool) && (props.comment === undefined || attributes.comment === props.comment) && (props.vmid === undefined || attributes.vmid === guestList(props.vmid)) && (props.exclude === undefined || attributes.exclude === guestList(props.exclude)) && (props["notes-template"] === undefined || attributes["notes-template"] === props["notes-template"]) && (props["prune-backups"] === undefined || attributes["prune-backups"] === propertyString(props["prune-backups"])) && (props.fleecing === undefined || attributes.fleecing === propertyString(props.fleecing, "enabled")),
524
1527
  path: (props) => `cluster/backup/${props.id}`,
525
1528
  updateForm: shape2
526
1529
  });
527
- var ProxmoxBackupJobProvider = () => Provider3.effect(ProxmoxBackupJob, Effect8.succeed(ProxmoxBackupJob.Provider.of(handlers2)));
1530
+ var ProxmoxBackupJobProvider = () => Provider3.effect(ProxmoxBackupJob, Effect10.succeed(ProxmoxBackupJob.Provider.of(handlers2)));
528
1531
  // src/proxmox/ceph-daemon.ts
529
1532
  import { Resource as Resource4 } from "alchemy";
530
1533
  import * as Provider4 from "alchemy/Provider";
531
- import * as Effect9 from "effect/Effect";
1534
+ import * as Effect11 from "effect/Effect";
532
1535
 
533
1536
  // src/proxmox/ceph-daemon-form.ts
1537
+ var DAEMON_ENDPOINTS = {
1538
+ mds: { create: "pve:POST /nodes/{node}/ceph/mds/{name}" },
1539
+ mgr: { create: "pve:POST /nodes/{node}/ceph/mgr/{id}" },
1540
+ mon: { create: "pve:POST /nodes/{node}/ceph/mon/{monid}" }
1541
+ };
534
1542
  var daemonId = (props) => props.name ?? props.node;
535
1543
  var collectionPath = (props) => `nodes/${props.node}/ceph/${props.kind}`;
536
1544
  var daemonPath = (props) => `${collectionPath(props)}/${daemonId(props)}`;
@@ -542,60 +1550,63 @@ var createForm = (props) => {
542
1550
  return hotstandby === undefined ? {} : { hotstandby };
543
1551
  };
544
1552
  var findRow = (live, props) => (Array.isArray(live) ? live : []).filter((row) => typeof row === "object" && row !== null).find((row) => row["name"] === daemonId(props));
1553
+ var daemonAttributes = (live, props) => {
1554
+ const row = findRow(live, props);
1555
+ if (row === undefined)
1556
+ return;
1557
+ return {
1558
+ addr: text(row["addr"]),
1559
+ fsName: text(row["fs_name"]),
1560
+ host: text(row["host"]),
1561
+ kind: props.kind,
1562
+ name: daemonId(props),
1563
+ node: props.node,
1564
+ quorum: bool(row["quorum"]),
1565
+ rank: num(row["rank"], -1),
1566
+ service: bool(row["service"]),
1567
+ standbyReplay: bool(row["standby_replay"]),
1568
+ state: text(row["state"]),
1569
+ version: text(row["ceph_version_short"])
1570
+ };
1571
+ };
545
1572
 
546
1573
  // src/proxmox/ceph-daemon.ts
547
1574
  var ProxmoxCephDaemon = Resource4("Proxmox.CephDaemon", {
548
1575
  defaultRemovalPolicy: "retain"
549
1576
  });
550
1577
  var handlers3 = pveHandlers({
551
- attributes: (live, props) => {
552
- const row = findRow(live, props);
553
- if (row === undefined)
554
- return;
555
- return {
556
- addr: text(row["addr"]),
557
- fsName: text(row["fs_name"]),
558
- host: text(row["host"]),
559
- kind: props.kind,
560
- name: daemonId(props),
561
- node: props.node,
562
- quorum: bool(row["quorum"]),
563
- rank: num(row["rank"], -1),
564
- service: bool(row["service"]),
565
- standbyReplay: bool(row["standby_replay"]),
566
- state: text(row["state"]),
567
- version: text(row["ceph_version_short"])
568
- };
569
- },
1578
+ attributes: daemonAttributes,
570
1579
  collection: daemonPath,
571
1580
  createForm,
1581
+ endpoint: (props) => DAEMON_ENDPOINTS[props.kind],
572
1582
  matches: () => true,
573
1583
  path: collectionPath
574
1584
  });
575
- var ProxmoxCephDaemonProvider = () => Provider4.effect(ProxmoxCephDaemon, Effect9.succeed(ProxmoxCephDaemon.Provider.of({
1585
+ var ProxmoxCephDaemonProvider = () => Provider4.effect(ProxmoxCephDaemon, Effect11.succeed(ProxmoxCephDaemon.Provider.of({
576
1586
  ...handlers3,
577
1587
  delete: ({ olds }) => pve(olds.target, "provision", "DELETE", daemonPath(olds))
578
1588
  })));
579
1589
  // src/proxmox/ceph-flag.ts
580
1590
  import { Resource as Resource5 } from "alchemy";
581
1591
  import * as Provider5 from "alchemy/Provider";
582
- import * as Effect10 from "effect/Effect";
1592
+ import * as Effect12 from "effect/Effect";
583
1593
  var ProxmoxCephFlag = Resource5("Proxmox.CephFlag");
584
1594
  var handlers4 = pveHandlers({
585
1595
  attributes: (live, props) => ({ flag: props.flag, value: bool(live) }),
586
1596
  collection: () => "cluster/ceph/flags",
587
1597
  createForm: (props) => ({ [props.flag]: flag(props.value) ?? "0" }),
1598
+ endpoint: { update: "pve:PUT /cluster/ceph/flags/{flag}" },
588
1599
  matches: (attributes, props) => attributes.value === props.value,
589
1600
  path: (props) => `cluster/ceph/flags/${props.flag}`,
590
1601
  updateForm: (props) => ({ value: flag(props.value) ?? "0" })
591
1602
  });
592
- var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect10.succeed(ProxmoxCephFlag.Provider.of({
1603
+ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect12.succeed(ProxmoxCephFlag.Provider.of({
593
1604
  ...handlers4,
594
- delete: () => Effect10.void,
595
- reconcile: Effect10.fn(function* ({ news }) {
1605
+ delete: () => Effect12.void,
1606
+ reconcile: Effect12.fn(function* ({ news }) {
596
1607
  const after = yield* handlers4.reconcile({ news });
597
1608
  if (after.value !== news.value) {
598
- return yield* Effect10.die(new Error(`cluster/ceph/flags/${news.flag}: the PUT returned no error but ceph still ` + `reports the flag ${after.value ? "set" : "clear"} rather than ` + `${news.value ? "set" : "clear"}. This endpoint's success is documented as a ` + "null body, so the status code proves nothing -- check `ceph osd dump | " + "head -1` and the cluster log. `pause` in particular is two ceph flags read " + "as one; see the header."));
1609
+ return yield* Effect12.die(new Error(`cluster/ceph/flags/${news.flag}: the PUT returned no error but ceph still ` + `reports the flag ${after.value ? "set" : "clear"} rather than ` + `${news.value ? "set" : "clear"}. This endpoint's success is documented as a ` + "null body, so the status code proves nothing -- check `ceph osd dump | " + "head -1` and the cluster log. `pause` in particular is two ceph flags read " + "as one; see the header."));
599
1610
  }
600
1611
  return after;
601
1612
  })
@@ -604,10 +1615,10 @@ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect10.s
604
1615
  import { Resource as Resource6 } from "alchemy";
605
1616
  import { isResolved as isResolved3 } from "alchemy/Diff";
606
1617
  import * as Provider6 from "alchemy/Provider";
607
- import * as Effect12 from "effect/Effect";
1618
+ import * as Effect14 from "effect/Effect";
608
1619
 
609
1620
  // src/proxmox/ceph-fs-wire.ts
610
- import * as Effect11 from "effect/Effect";
1621
+ import * as Effect13 from "effect/Effect";
611
1622
  var readRow = (live, props) => {
612
1623
  const row = (Array.isArray(live) ? live : []).filter((entry) => typeof entry === "object" && entry !== null).find((entry) => entry["name"] === props.name);
613
1624
  if (row === undefined)
@@ -635,29 +1646,29 @@ var destroyPath = (props) => {
635
1646
  ].filter((part) => part !== undefined);
636
1647
  return query.length === 0 ? objectPath(props) : `${objectPath(props)}?${query.join("&")}`;
637
1648
  };
638
- var settle = (target, node, upid, what) => Effect11.gen(function* () {
1649
+ var settle = (target, node, upid, what) => Effect13.gen(function* () {
639
1650
  for (let attempt = 0;attempt < POLL_ATTEMPTS; attempt += 1) {
640
- const status = yield* pve(target, "read", "GET", `nodes/${node}/tasks/${encodeURIComponent(upid)}/status`).pipe(Effect11.orElseSucceed(() => {
1651
+ const status = yield* pve(target, "read", "GET", `nodes/${node}/tasks/${encodeURIComponent(upid)}/status`).pipe(Effect13.orElseSucceed(() => {
641
1652
  return;
642
1653
  }));
643
1654
  if (status?.status === "stopped") {
644
1655
  const exit = text(status.exitstatus);
645
1656
  if (exit === "OK")
646
1657
  return;
647
- return yield* Effect11.die(new Error(`${what}: PVE task ${upid} finished with "${exit === "" ? "no exit status" : exit}". ` + "The write returned HTTP 200 because it only forked the worker -- the real error is " + `in \`pvesh get /nodes/${node}/tasks/${upid}/log\`.`));
1658
+ return yield* Effect13.die(new Error(`${what}: PVE task ${upid} finished with "${exit === "" ? "no exit status" : exit}". ` + "The write returned HTTP 200 because it only forked the worker -- the real error is " + `in \`pvesh get /nodes/${node}/tasks/${upid}/log\`.`));
648
1659
  }
649
- yield* Effect11.sleep(POLL_SECONDS * 1000);
1660
+ yield* Effect13.sleep(POLL_SECONDS * 1000);
650
1661
  }
651
- return yield* Effect11.die(new Error(`${what}: PVE task ${upid} was still running after ` + `${String(POLL_ATTEMPTS * POLL_SECONDS)}s, or its ` + "status could not be read. Check the task log, and check that the `read` role holds " + `Sys.Audit on /nodes/${node} -- each call mints a new token, so the poller is never the ` + "task owner and is answered 403 rather than told to wait."));
1662
+ return yield* Effect13.die(new Error(`${what}: PVE task ${upid} was still running after ` + `${String(POLL_ATTEMPTS * POLL_SECONDS)}s, or its ` + "status could not be read. Check the task log, and check that the `read` role holds " + `Sys.Audit on /nodes/${node} -- each call mints a new token, so the poller is never the ` + "task owner and is answered 403 rather than told to wait."));
652
1663
  });
653
- var createFs = (props) => Effect11.gen(function* () {
1664
+ var createFs = (props) => Effect13.gen(function* () {
654
1665
  const upid = text(yield* pve(props.target, "provision", "POST", objectPath(props), createForm2(props)));
655
1666
  if (upid === "") {
656
- return yield* Effect11.die(new Error(`${objectPath(props)}: POST returned no task id. PVE wraps every answer in ` + '{"data":...} and can report success on a call that did nothing.'));
1667
+ return yield* Effect13.die(new Error(`${objectPath(props)}: POST returned no task id. PVE wraps every answer in ` + '{"data":...} and can report success on a call that did nothing.'));
657
1668
  }
658
1669
  yield* settle(props.target, props.node, upid, objectPath(props));
659
1670
  });
660
- var destroyFs = (props) => Effect11.gen(function* () {
1671
+ var destroyFs = (props) => Effect13.gen(function* () {
661
1672
  const upid = text(yield* pve(props.target, "provision", "DELETE", destroyPath(props)));
662
1673
  if (upid !== "")
663
1674
  yield* settle(props.target, props.node, upid, destroyPath(props));
@@ -673,47 +1684,48 @@ var ops3 = pveOperations({
673
1684
  attributes: readRow,
674
1685
  collection: objectPath,
675
1686
  createForm: createForm2,
1687
+ endpoint: { create: "pve:POST /nodes/{node}/ceph/fs/{name}" },
676
1688
  matches: () => true,
677
1689
  path: (props) => `nodes/${props.node}/ceph/fs`
678
1690
  });
679
- var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect12.succeed(ProxmoxCephFs.Provider.of({
680
- list: () => Effect12.succeed([]),
681
- read: Effect12.fn(function* ({ olds }) {
1691
+ var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect14.succeed(ProxmoxCephFs.Provider.of({
1692
+ list: () => Effect14.succeed([]),
1693
+ read: Effect14.fn(function* ({ olds }) {
682
1694
  return yield* ops3.read(olds);
683
1695
  }),
684
- diff: Effect12.fn(function* ({ news, output }) {
1696
+ diff: Effect14.fn(function* ({ news, output }) {
685
1697
  if (output !== undefined && isResolved3(news) && news.name !== output.name) {
686
1698
  return { action: "replace" };
687
1699
  }
688
1700
  return yield* ops3.diff(news, output);
689
1701
  }),
690
- reconcile: Effect12.fn(function* ({ news }) {
1702
+ reconcile: Effect14.fn(function* ({ news }) {
691
1703
  const live = yield* ops3.read(news);
692
1704
  if (live !== undefined)
693
1705
  return live;
694
1706
  yield* createFs(news);
695
1707
  const after = yield* ops3.read(news);
696
1708
  if (after === undefined)
697
- return yield* Effect12.die(notCreated(news));
1709
+ return yield* Effect14.die(notCreated(news));
698
1710
  return after;
699
1711
  }),
700
- delete: Effect12.fn(function* ({ olds }) {
1712
+ delete: Effect14.fn(function* ({ olds }) {
701
1713
  if ((yield* ops3.read(olds)) === undefined)
702
1714
  return;
703
1715
  yield* destroyFs(olds);
704
1716
  const after = yield* ops3.read(olds);
705
1717
  if (after !== undefined)
706
- return yield* Effect12.die(notDestroyed(olds));
1718
+ return yield* Effect14.die(notDestroyed(olds));
707
1719
  })
708
1720
  })));
709
1721
  // src/proxmox/ceph-osd.ts
710
1722
  import { Resource as Resource7 } from "alchemy";
711
1723
  import { isResolved as isResolved4 } from "alchemy/Diff";
712
1724
  import * as Provider7 from "alchemy/Provider";
713
- import * as Effect15 from "effect/Effect";
1725
+ import * as Effect17 from "effect/Effect";
714
1726
 
715
1727
  // src/proxmox/ceph-osd-tree.ts
716
- import * as Effect13 from "effect/Effect";
1728
+ import * as Effect15 from "effect/Effect";
717
1729
  var branches = (node) => (Array.isArray(node["children"]) ? node["children"] : []).filter((child) => typeof child === "object" && child !== null);
718
1730
  var osdLeaves = (tree) => {
719
1731
  const root = tree["root"];
@@ -739,25 +1751,29 @@ var osdAttributes = (leaf, props) => ({
739
1751
  status: text(leaf["status"]),
740
1752
  total_space: num(leaf["total_space"], 0)
741
1753
  });
742
- var readOsd = (props) => pve(props.target, "read", "GET", `nodes/${props.node}/ceph/osd`).pipe(Effect13.map((t) => {
1754
+ var readOsd = (props) => pve(props.target, "read", "GET", `nodes/${props.node}/ceph/osd`).pipe(Effect15.map((t) => {
743
1755
  const leaf = t === undefined ? undefined : findOsd(t, props.osdid);
744
1756
  return leaf === undefined ? undefined : osdAttributes(leaf, props);
745
1757
  }));
746
1758
 
747
1759
  // src/proxmox/ceph-osd-write.ts
748
- import * as Effect14 from "effect/Effect";
1760
+ import * as Effect16 from "effect/Effect";
1761
+ var OSD_CREATE_ENDPOINT = "pve:POST /nodes/{node}/ceph/osd";
749
1762
  var describe = (props) => `osd.${String(props.osdid)} on ${props.node}`;
750
- var createOsd = Effect14.fn(function* (news) {
1763
+ var createOsdForm = (props, dev) => ({
1764
+ dev,
1765
+ ...props.device_class === undefined ? {} : { "crush-device-class": props.device_class }
1766
+ });
1767
+ var createOsd = Effect16.fn(function* (news) {
751
1768
  if (news.dev === undefined) {
752
- return yield* Effect14.die(new Error(`${describe(news)}: no such OSD in the CRUSH tree, and no \`dev\` was declared. ` + "Without a device this resource is an ASSERTION over an OSD that must already " + "exist. Declare `dev` to let it create one -- which WIPES that device -- or fix " + "the declaration; if the disk was there yesterday, a replica is missing and Ceph " + "is degraded."));
1769
+ return yield* Effect16.die(new Error(`${describe(news)}: no such OSD in the CRUSH tree, and no \`dev\` was declared. ` + "Without a device this resource is an ASSERTION over an OSD that must already " + "exist. Declare `dev` to let it create one -- which WIPES that device -- or fix " + "the declaration; if the disk was there yesterday, a replica is missing and Ceph " + "is degraded."));
753
1770
  }
754
- yield* pve(news.target, "provision", "POST", `nodes/${news.node}/ceph/osd`, {
755
- dev: news.dev,
756
- ...news.device_class === undefined ? {} : { "crush-device-class": news.device_class }
757
- });
1771
+ const form = createOsdForm(news, news.dev);
1772
+ yield* guardForm(OSD_CREATE_ENDPOINT, form, true);
1773
+ yield* pve(news.target, "provision", "POST", `nodes/${news.node}/ceph/osd`, form);
758
1774
  const created = yield* readOsd(news);
759
1775
  if (created === undefined) {
760
- return yield* Effect14.die(new Error(`${describe(news)}: the create returned no error but osd.${String(news.osdid)} is ` + "still absent. Ceph allocates OSD ids and cannot be told which to use, so it most " + "likely assigned a different number -- check `ceph osd tree`, and declare the id it " + "actually gave the device rather than deploying again."));
1776
+ return yield* Effect16.die(new Error(`${describe(news)}: the create returned no error but osd.${String(news.osdid)} is ` + "still absent. Ceph allocates OSD ids and cannot be told which to use, so it most " + "likely assigned a different number -- check `ceph osd tree`, and declare the id it " + "actually gave the device rather than deploying again."));
761
1777
  }
762
1778
  return created;
763
1779
  });
@@ -770,11 +1786,11 @@ var ProxmoxCephOsd = Resource7("Proxmox.CephOsd", {
770
1786
  var settled = (live, props) => (props.host === undefined || props.host === live.host) && (props.device_class === undefined || props.device_class === live.device_class);
771
1787
  var describe2 = (props) => `osd.${String(props.osdid)} (read via nodes/${props.node}/ceph/osd)`;
772
1788
  var handlers5 = {
773
- list: () => Effect15.succeed([]),
774
- read: Effect15.fn(function* ({ olds }) {
1789
+ list: () => Effect17.succeed([]),
1790
+ read: Effect17.fn(function* ({ olds }) {
775
1791
  return yield* readOsd(olds);
776
1792
  }),
777
- diff: Effect15.fn(function* ({
1793
+ diff: Effect17.fn(function* ({
778
1794
  news,
779
1795
  output
780
1796
  }) {
@@ -787,25 +1803,25 @@ var handlers5 = {
787
1803
  return { action: "update" };
788
1804
  return settled(live, news) ? { action: "noop" } : { action: "update" };
789
1805
  }),
790
- reconcile: Effect15.fn(function* ({ news }) {
1806
+ reconcile: Effect17.fn(function* ({ news }) {
791
1807
  const live = yield* readOsd(news);
792
1808
  if (live === undefined) {
793
1809
  return yield* createOsd(news);
794
1810
  }
795
1811
  if (!settled(live, news)) {
796
- return yield* Effect15.die(new Error(`${describe2(news)}: exists but not as declared -- live host=${live.host} ` + `device_class=${live.device_class}. Nothing here moves an OSD between hosts or ` + "reclassifies it; fix the declaration, or move it deliberately with `ceph osd crush " + "move` / `ceph osd crush set-device-class` and deploy again."));
1812
+ return yield* Effect17.die(new Error(`${describe2(news)}: exists but not as declared -- live host=${live.host} ` + `device_class=${live.device_class}. Nothing here moves an OSD between hosts or ` + "reclassifies it; fix the declaration, or move it deliberately with `ceph osd crush " + "move` / `ceph osd crush set-device-class` and deploy again."));
797
1813
  }
798
1814
  return live;
799
1815
  }),
800
- delete: Effect15.fn(function* ({ olds }) {
1816
+ delete: Effect17.fn(function* ({ olds }) {
801
1817
  yield* destroyOsd(olds);
802
1818
  })
803
1819
  };
804
- var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect15.succeed(ProxmoxCephOsd.Provider.of(handlers5)));
1820
+ var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect17.succeed(ProxmoxCephOsd.Provider.of(handlers5)));
805
1821
  // src/proxmox/ceph-pool.ts
806
1822
  import { Resource as Resource8 } from "alchemy";
807
1823
  import * as Provider8 from "alchemy/Provider";
808
- import * as Effect17 from "effect/Effect";
1824
+ import * as Effect19 from "effect/Effect";
809
1825
 
810
1826
  // src/proxmox/ceph-pool-form.ts
811
1827
  var object = (props) => `nodes/${props.node}/ceph/pool/${props.name}`;
@@ -834,14 +1850,14 @@ var createBody = (props) => ({
834
1850
  });
835
1851
 
836
1852
  // src/proxmox/ceph-pool-settle.ts
837
- import * as Effect16 from "effect/Effect";
838
- var confirmAbsent = (props, collection2, describe3) => pve(props.target, "read", "GET", collection2).pipe(Effect16.flatMap((rows) => (rows ?? []).some((row) => row.pool_name === props.name) ? Effect16.die(new Error(`${describe3}: the cluster lists this pool but its status could not be read, ` + "so this deploy will NOT create over it. Check that the node is up and that the " + "read role holds Sys.Audit or Datastore.Audit on / -- a create here would apply " + "pg_num to a live pool and start a PG merge.")) : Effect16.void));
839
- var settle2 = (props, read, done) => Effect16.gen(function* () {
1853
+ import * as Effect18 from "effect/Effect";
1854
+ var confirmAbsent = (props, collection2, describe3) => pve(props.target, "read", "GET", collection2).pipe(Effect18.flatMap((rows) => (rows ?? []).some((row) => row.pool_name === props.name) ? Effect18.die(new Error(`${describe3}: the cluster lists this pool but its status could not be read, ` + "so this deploy will NOT create over it. Check that the node is up and that the " + "read role holds Sys.Audit or Datastore.Audit on / -- a create here would apply " + "pg_num to a live pool and start a PG merge.")) : Effect18.void));
1855
+ var settle2 = (props, read, done) => Effect18.gen(function* () {
840
1856
  for (let attempt = 0;attempt < 30; attempt += 1) {
841
1857
  const live = yield* read(props);
842
1858
  if (done(live))
843
1859
  return live;
844
- yield* Effect16.sleep("2 seconds");
1860
+ yield* Effect18.sleep("2 seconds");
845
1861
  }
846
1862
  return yield* read(props);
847
1863
  });
@@ -874,38 +1890,44 @@ var spec = {
874
1890
  },
875
1891
  collection,
876
1892
  createForm: createBody,
1893
+ endpoint: {
1894
+ create: "pve:POST /nodes/{node}/ceph/pool",
1895
+ update: "pve:PUT /nodes/{node}/ceph/pool/{name}"
1896
+ },
877
1897
  matches: (attributes, props) => same(props.size, attributes.size, attributes.nosizechange) && same(props.min_size, attributes.min_size, attributes.nosizechange) && same(props.pg_autoscale_mode, attributes.pg_autoscale_mode) && same(hint(props.pg_num_min), attributes.pg_num_min, attributes.nopgchange) && same(props.crush_rule, attributes.crush_rule, attributes.crush_rule === "") && same(hint(props.target_size), attributes.target_size),
878
1898
  path: (props) => `${object(props)}/status?verbose=1`,
879
1899
  updateForm: updateBody
880
1900
  };
881
1901
  var ops4 = pveOperations(spec);
882
- var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect17.succeed(ProxmoxCephPool.Provider.of({
883
- list: () => Effect17.succeed([]),
1902
+ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect19.succeed(ProxmoxCephPool.Provider.of({
1903
+ list: () => Effect19.succeed([]),
884
1904
  read: ({ olds }) => ops4.read(olds),
885
1905
  diff: ({ news, output }) => ops4.diff(news, output),
886
- reconcile: Effect17.fn(function* ({ news }) {
1906
+ reconcile: Effect19.fn(function* ({ news }) {
887
1907
  const live = yield* ops4.read(news);
888
1908
  let upid;
889
1909
  if (live === undefined) {
1910
+ yield* ops4.guardCreate(news, true);
890
1911
  yield* confirmAbsent(news, spec.collection(news), object(news));
891
1912
  upid = yield* pve(news.target, "provision", "POST", collection(news), createBody(news));
892
1913
  } else {
893
1914
  const form = formToSend(spec.matches, live, news, updateBody(news));
894
1915
  if (form !== undefined) {
1916
+ yield* ops4.guardUpdate(news);
895
1917
  upid = yield* pve(news.target, "provision", "PUT", object(news), form);
896
1918
  }
897
1919
  }
898
1920
  const after = yield* settle2(news, ops4.read, (row) => row !== undefined && spec.matches(row, news));
899
1921
  if (after === undefined || !spec.matches(after, news)) {
900
- return yield* Effect17.die(new Error(`${object(news)}: the write returned no error but the pool still does not match ` + `the declaration after 60s. PVE answered with task ${upid ?? "(none)"} -- read ` + "its log with `pvesh get /nodes/<node>/tasks/<upid>/log` to see what Ceph " + "refused."));
1922
+ return yield* Effect19.die(new Error(`${object(news)}: the write returned no error but the pool still does not match ` + `the declaration after 60s. PVE answered with task ${upid ?? "(none)"} -- read ` + "its log with `pvesh get /nodes/<node>/tasks/<upid>/log` to see what Ceph " + "refused."));
901
1923
  }
902
1924
  return after;
903
1925
  }),
904
- delete: Effect17.fn(function* ({ olds }) {
1926
+ delete: Effect19.fn(function* ({ olds }) {
905
1927
  yield* pve(olds.target, "provision", "DELETE", object(olds));
906
1928
  const left = yield* settle2(olds, ops4.read, (row) => row === undefined);
907
1929
  if (left !== undefined) {
908
- return yield* Effect17.die(new Error(`${object(olds)}: the DELETE returned no error but the pool is still there after ` + "60s. Either a storage on it still holds RBD images, or the mons are running " + "with mon_allow_pool_delete false."));
1930
+ return yield* Effect19.die(new Error(`${object(olds)}: the DELETE returned no error but the pool is still there after ` + "60s. Either a storage on it still holds RBD images, or the mons are running " + "with mon_allow_pool_delete false."));
909
1931
  }
910
1932
  })
911
1933
  })));
@@ -913,7 +1935,7 @@ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect17.s
913
1935
  import { Resource as Resource9 } from "alchemy";
914
1936
  import { isResolved as isResolved5 } from "alchemy/Diff";
915
1937
  import * as Provider9 from "alchemy/Provider";
916
- import * as Effect18 from "effect/Effect";
1938
+ import * as Effect20 from "effect/Effect";
917
1939
 
918
1940
  // src/proxmox/firewall-alias-form.ts
919
1941
  var fold = (name) => name.trim().toLowerCase();
@@ -945,13 +1967,17 @@ var handlers6 = pveHandlers({
945
1967
  },
946
1968
  collection: () => "cluster/firewall/aliases",
947
1969
  createForm: (props) => ({ ...body(props), name: props.name }),
1970
+ endpoint: {
1971
+ create: "pve:POST /cluster/firewall/aliases",
1972
+ update: "pve:PUT /cluster/firewall/aliases/{name}"
1973
+ },
948
1974
  matches: (attributes, props) => attributes.cidr === cidr(props.cidr) && attributes.comment === comment(props.comment),
949
1975
  path: (props) => `cluster/firewall/aliases/${props.name}`,
950
1976
  updateForm: body
951
1977
  });
952
- var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect18.succeed(ProxmoxFirewallAlias.Provider.of({
1978
+ var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect20.succeed(ProxmoxFirewallAlias.Provider.of({
953
1979
  ...handlers6,
954
- diff: Effect18.fn(function* ({ news, output }) {
1980
+ diff: Effect20.fn(function* ({ news, output }) {
955
1981
  if (output !== undefined && isResolved5(news) && fold(news.name) !== fold(output.name)) {
956
1982
  return { action: "replace" };
957
1983
  }
@@ -961,7 +1987,7 @@ var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias,
961
1987
  // src/proxmox/group.ts
962
1988
  import { Resource as Resource10 } from "alchemy";
963
1989
  import * as Provider10 from "alchemy/Provider";
964
- import * as Effect19 from "effect/Effect";
1990
+ import * as Effect21 from "effect/Effect";
965
1991
  var ProxmoxGroup = Resource10("Proxmox.Group", {
966
1992
  defaultRemovalPolicy: "retain"
967
1993
  });
@@ -981,15 +2007,16 @@ var handlers7 = pveHandlers({
981
2007
  }),
982
2008
  collection: () => "access/groups",
983
2009
  createForm: (props) => ({ comment: storedComment(props.comment), groupid: props.groupid }),
2010
+ endpoint: { create: "pve:POST /access/groups", update: "pve:PUT /access/groups/{groupid}" },
984
2011
  matches: (attributes, props) => attributes.comment === storedComment(props.comment),
985
2012
  path: (props) => `access/groups/${props.groupid}`,
986
2013
  updateForm: (props) => ({ comment: storedComment(props.comment) })
987
2014
  });
988
- var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect19.succeed(ProxmoxGroup.Provider.of(handlers7)));
2015
+ var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect21.succeed(ProxmoxGroup.Provider.of(handlers7)));
989
2016
  // src/proxmox/ha-resource.ts
990
2017
  import { Resource as Resource11 } from "alchemy";
991
2018
  import * as Provider11 from "alchemy/Provider";
992
- import * as Effect20 from "effect/Effect";
2019
+ import * as Effect22 from "effect/Effect";
993
2020
  var ProxmoxHaResource = Resource11("Proxmox.HaResource");
994
2021
  var kind = (sid) => sid.split(":")[0] ?? "";
995
2022
  var shape3 = (props) => ({
@@ -1009,15 +2036,19 @@ var handlers8 = pveHandlers({
1009
2036
  }),
1010
2037
  collection: () => "cluster/ha/resources",
1011
2038
  createForm: (props) => ({ ...shape3(props), sid: props.sid }),
2039
+ endpoint: {
2040
+ create: "pve:POST /cluster/ha/resources",
2041
+ update: "pve:PUT /cluster/ha/resources/{sid}"
2042
+ },
1012
2043
  matches: (attributes, props) => attributes.state === (props.state ?? "started") && attributes.comment === (props.comment ?? "") && attributes.max_restart === (props.max_restart ?? 1) && attributes.max_relocate === (props.max_relocate ?? 1),
1013
2044
  path: (props) => `cluster/ha/resources/${props.sid}`,
1014
2045
  updateForm: shape3
1015
2046
  });
1016
- var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect20.succeed(ProxmoxHaResource.Provider.of(handlers8)));
2047
+ var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect22.succeed(ProxmoxHaResource.Provider.of(handlers8)));
1017
2048
  // src/proxmox/ha-rule.ts
1018
2049
  import { Resource as Resource12 } from "alchemy";
1019
2050
  import * as Provider12 from "alchemy/Provider";
1020
- import * as Effect21 from "effect/Effect";
2051
+ import * as Effect23 from "effect/Effect";
1021
2052
 
1022
2053
  // src/proxmox/ha-rule-form.ts
1023
2054
  var nodeList = (value) => {
@@ -1085,6 +2116,7 @@ var handlers9 = pveHandlers({
1085
2116
  },
1086
2117
  collection: () => "cluster/ha/rules",
1087
2118
  createForm: (props) => ({ ...body2(props), rule: props.rule }),
2119
+ endpoint: { create: "pve:POST /cluster/ha/rules", update: "pve:PUT /cluster/ha/rules/{rule}" },
1088
2120
  matches: (attributes, props) => attributes.resources === csv(props.resources) && attributes.affinity === props.affinity && attributes.comment === commentText(props.comment ?? "") && attributes.disable === (props.disable === true) && (props.type !== "node-affinity" || attributes.nodes === nodeList(props.nodes) && attributes.strict === (props.strict === true)),
1089
2121
  path: (props) => `cluster/ha/rules/${props.rule}`,
1090
2122
  updateForm: (props) => {
@@ -1093,43 +2125,43 @@ var handlers9 = pveHandlers({
1093
2125
  return withClears(fields, clear);
1094
2126
  }
1095
2127
  });
1096
- var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect21.succeed(ProxmoxHaRule.Provider.of(handlers9)));
2128
+ var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect23.succeed(ProxmoxHaRule.Provider.of(handlers9)));
1097
2129
  // src/proxmox/lxc.ts
1098
2130
  import { Resource as Resource13 } from "alchemy";
1099
2131
  import { isResolved as isResolved6 } from "alchemy/Diff";
1100
2132
  import * as Provider13 from "alchemy/Provider";
1101
- import * as Effect31 from "effect/Effect";
2133
+ import * as Effect33 from "effect/Effect";
1102
2134
 
1103
2135
  // src/ownership/adopt.ts
1104
2136
  import { AdoptPolicy } from "alchemy/AdoptPolicy";
1105
2137
  import { AlchemyContext } from "alchemy/AlchemyContext";
1106
2138
  import { Stack as Stack3 } from "alchemy/Stack";
1107
- import * as Effect25 from "effect/Effect";
2139
+ import * as Effect27 from "effect/Effect";
1108
2140
  import * as Option5 from "effect/Option";
1109
2141
 
1110
2142
  // src/ownership/resume.ts
1111
2143
  import { Unowned } from "alchemy/AdoptPolicy";
1112
2144
  import { Artifacts } from "alchemy/Artifacts";
1113
- import * as Effect22 from "effect/Effect";
2145
+ import * as Effect24 from "effect/Effect";
1114
2146
  import * as Option2 from "effect/Option";
1115
2147
  var PROVEN = "homeflare/ownership/resumes";
1116
2148
  var UNFINISHED = "homeflare/ownership/unfinished";
1117
- var note = (key, instanceId) => Effect22.gen(function* () {
1118
- const bag = yield* Effect22.serviceOption(Artifacts);
2149
+ var note = (key, instanceId) => Effect24.gen(function* () {
2150
+ const bag = yield* Effect24.serviceOption(Artifacts);
1119
2151
  if (Option2.isSome(bag))
1120
2152
  yield* bag.value.set(key, instanceId);
1121
2153
  });
1122
- var noted = (key, instanceId) => Effect22.gen(function* () {
1123
- const bag = yield* Effect22.serviceOption(Artifacts);
2154
+ var noted = (key, instanceId) => Effect24.gen(function* () {
2155
+ const bag = yield* Effect24.serviceOption(Artifacts);
1124
2156
  if (Option2.isNone(bag))
1125
2157
  return false;
1126
2158
  return (yield* bag.value.get(key)) === instanceId;
1127
2159
  });
1128
- var noteUnfinished = (instanceId) => Effect22.as(note(UNFINISHED, instanceId), undefined);
1129
- var noteResume = (instanceId, recovered) => Effect22.gen(function* () {
2160
+ var noteUnfinished = (instanceId) => Effect24.as(note(UNFINISHED, instanceId), undefined);
2161
+ var noteResume = (instanceId, recovered) => Effect24.gen(function* () {
1130
2162
  yield* noteUnfinished(instanceId);
1131
- const unproven = () => Effect22.succeed(undefined);
1132
- const found = yield* recovered.pipe(Effect22.catch(unproven), Effect22.catchDefect(unproven));
2163
+ const unproven = () => Effect24.succeed(undefined);
2164
+ const found = yield* recovered.pipe(Effect24.catch(unproven), Effect24.catchDefect(unproven));
1133
2165
  if (found === undefined || found === null || Unowned.is(found))
1134
2166
  return;
1135
2167
  yield* note(PROVEN, instanceId);
@@ -1140,7 +2172,7 @@ var provingResumes = (service) => {
1140
2172
  const { diff, read } = service;
1141
2173
  if (diff === undefined || read === undefined)
1142
2174
  return service;
1143
- const proving = (input) => Effect22.gen(function* () {
2175
+ const proving = (input) => Effect24.gen(function* () {
1144
2176
  if (input.output === undefined) {
1145
2177
  yield* noteResume(input.instanceId, read({ ...input, output: undefined }));
1146
2178
  }
@@ -1152,12 +2184,12 @@ var provingResumes = (service) => {
1152
2184
  // src/ownership/rows.ts
1153
2185
  import { Stack as Stack2 } from "alchemy/Stack";
1154
2186
  import { State, isActionState } from "alchemy/State/State";
1155
- import * as Effect24 from "effect/Effect";
2187
+ import * as Effect26 from "effect/Effect";
1156
2188
  import * as Option4 from "effect/Option";
1157
2189
 
1158
2190
  // src/ownership/whole.ts
1159
2191
  import { Stack } from "alchemy/Stack";
1160
- import * as Effect23 from "effect/Effect";
2192
+ import * as Effect25 from "effect/Effect";
1161
2193
  import * as Option3 from "effect/Option";
1162
2194
  var absent = (value) => value === undefined || value === null;
1163
2195
  var isPlainObject = (value) => {
@@ -1183,22 +2215,22 @@ var carries = (declared, recorded) => {
1183
2215
  }
1184
2216
  return true;
1185
2217
  };
1186
- var wholeDeclaration = (fqn, props) => Effect23.map(Effect23.serviceOption(Stack), (stack) => {
2218
+ var wholeDeclaration = (fqn, props) => Effect25.map(Effect25.serviceOption(Stack), (stack) => {
1187
2219
  const declared = Option3.isSome(stack) ? stack.value.resources[fqn] : undefined;
1188
2220
  return declared !== undefined && carries(declared.Props, props);
1189
2221
  });
1190
2222
 
1191
2223
  // src/ownership/rows.ts
1192
- var storeOf = Effect24.gen(function* () {
1193
- const stack = yield* Effect24.serviceOption(Stack2);
1194
- const state = yield* Effect24.serviceOption(State);
2224
+ var storeOf = Effect26.gen(function* () {
2225
+ const stack = yield* Effect26.serviceOption(Stack2);
2226
+ const state = yield* Effect26.serviceOption(State);
1195
2227
  if (Option4.isNone(stack) || Option4.isNone(state))
1196
2228
  return;
1197
2229
  const store = yield* state.value;
1198
2230
  const where = { stack: stack.value.name, stage: stack.value.stage };
1199
2231
  return { resources: stack.value.resources, store, where };
1200
2232
  });
1201
- var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect24.orElseSucceed(() => {
2233
+ var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect26.orElseSucceed(() => {
1202
2234
  return;
1203
2235
  }));
1204
2236
  var generationOf = (row, instanceId) => {
@@ -1211,7 +2243,7 @@ var generationOf = (row, instanceId) => {
1211
2243
  }
1212
2244
  return;
1213
2245
  };
1214
- var recordedGeneration = (fqn, instanceId) => Effect24.gen(function* () {
2246
+ var recordedGeneration = (fqn, instanceId) => Effect26.gen(function* () {
1215
2247
  const found = yield* storeOf;
1216
2248
  if (found === undefined)
1217
2249
  return;
@@ -1222,14 +2254,14 @@ var recordedGeneration = (fqn, instanceId) => Effect24.gen(function* () {
1222
2254
  }
1223
2255
  return;
1224
2256
  });
1225
- var recordedInstance = (fqn, instanceId) => Effect24.gen(function* () {
2257
+ var recordedInstance = (fqn, instanceId) => Effect26.gen(function* () {
1226
2258
  const generation = yield* recordedGeneration(fqn, instanceId);
1227
2259
  if (generation === undefined)
1228
2260
  return "absent";
1229
2261
  return (yield* wholeDeclaration(fqn, generation.props)) ? "whole" : "partial";
1230
2262
  });
1231
- var isCreate = (fqn, instanceId) => Effect24.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
1232
- var forgetRefusedCreate = (fqn, instanceId) => Effect24.gen(function* () {
2263
+ var isCreate = (fqn, instanceId) => Effect26.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
2264
+ var forgetRefusedCreate = (fqn, instanceId) => Effect26.gen(function* () {
1233
2265
  const found = yield* storeOf;
1234
2266
  if (found === undefined)
1235
2267
  return;
@@ -1238,32 +2270,32 @@ var forgetRefusedCreate = (fqn, instanceId) => Effect24.gen(function* () {
1238
2270
  if (mine?.status !== "creating" || mine.instanceId !== instanceId || mine.attr !== undefined) {
1239
2271
  return;
1240
2272
  }
1241
- yield* found.store.delete({ ...found.where, fqn }).pipe(Effect24.ignore);
2273
+ yield* found.store.delete({ ...found.where, fqn }).pipe(Effect26.ignore);
1242
2274
  });
1243
2275
 
1244
2276
  // src/ownership/adopt.ts
1245
- var adoptEnabled = (fqn) => Effect25.gen(function* () {
1246
- const stack = yield* Effect25.serviceOption(Stack3);
2277
+ var adoptEnabled = (fqn) => Effect27.gen(function* () {
2278
+ const stack = yield* Effect27.serviceOption(Stack3);
1247
2279
  const scoped = Option5.isSome(stack) ? stack.value.resources[fqn]?.Adopt : undefined;
1248
2280
  if (scoped !== undefined)
1249
2281
  return scoped;
1250
- const policy = yield* Effect25.serviceOption(AdoptPolicy);
2282
+ const policy = yield* Effect27.serviceOption(AdoptPolicy);
1251
2283
  if (Option5.isSome(policy))
1252
2284
  return policy.value;
1253
- const context = yield* Effect25.serviceOption(AlchemyContext);
2285
+ const context = yield* Effect27.serviceOption(AlchemyContext);
1254
2286
  return Option5.isSome(context) ? context.value.adopt : false;
1255
2287
  });
1256
- var adoptable = (owner) => Effect25.gen(function* () {
2288
+ var adoptable = (owner) => Effect27.gen(function* () {
1257
2289
  if (yield* isCreate(owner.fqn, owner.instanceId))
1258
2290
  return true;
1259
2291
  return yield* unfinished(owner.instanceId);
1260
2292
  });
1261
- var adoptsAtApply = (owner) => Effect25.gen(function* () {
2293
+ var adoptsAtApply = (owner) => Effect27.gen(function* () {
1262
2294
  if (!(yield* adoptEnabled(owner.fqn)))
1263
2295
  return false;
1264
2296
  return yield* adoptable(owner);
1265
2297
  });
1266
- var refuseTakeover = (owner, what) => Effect25.gen(function* () {
2298
+ var refuseTakeover = (owner, what) => Effect27.gen(function* () {
1267
2299
  if (owner.output !== undefined)
1268
2300
  return;
1269
2301
  if (yield* resumes(owner.instanceId))
@@ -1273,25 +2305,25 @@ var refuseTakeover = (owner, what) => Effect25.gen(function* () {
1273
2305
  return;
1274
2306
  yield* forgetRefusedCreate(owner.fqn, owner.instanceId);
1275
2307
  const remedy = may ? "Deploy with --adopt (or wrap the resource in adopt(true)) to take it over, or remove it first." : "It is the new identity of a replace, which --adopt does not cover: remove it first.";
1276
- return yield* Effect25.die(new Error(`${what}: already exists, and this stack holds no state for it — the plan could not ask ` + "first (a prop was still an Output, a replace moved onto it, or it appeared after the " + `plan). Nothing was written. ${remedy}`));
2308
+ return yield* Effect27.die(new Error(`${what}: already exists, and this stack holds no state for it — the plan could not ask ` + "first (a prop was still an Output, a replace moved onto it, or it appeared after the " + `plan). Nothing was written. ${remedy}`));
1277
2309
  });
1278
2310
  var claimFor = (owner) => (what) => refuseTakeover(owner, what);
1279
2311
 
1280
2312
  // src/ownership/probe.ts
1281
2313
  import { Unowned as Unowned2 } from "alchemy/AdoptPolicy";
1282
- import * as Effect26 from "effect/Effect";
1283
- var provenOurs = (ask, settled2) => Effect26.gen(function* () {
2314
+ import * as Effect28 from "effect/Effect";
2315
+ var provenOurs = (ask, settled2) => Effect28.gen(function* () {
1284
2316
  const recorded = yield* recordedInstance(ask.fqn, ask.instanceId);
1285
2317
  if (recorded === "absent")
1286
2318
  return false;
1287
2319
  if (recorded === "partial") {
1288
- yield* Effect26.logWarning(`${ask.fqn}: the interrupted create's state row lacks part of the declaration (a prop ` + "was still an Output when it was written), so the live object is not proven ours");
2320
+ yield* Effect28.logWarning(`${ask.fqn}: the interrupted create's state row lacks part of the declaration (a prop ` + "was still an Output when it was written), so the live object is not proven ours");
1289
2321
  return false;
1290
2322
  }
1291
- const unproven = (reason) => Effect26.as(Effect26.logWarning(`${ask.fqn}: the interrupted create's object could not be compared with its props ` + `(${reason instanceof Error ? reason.message : String(reason)}), so it is not treated as ours`), false);
1292
- return yield* settled2.pipe(Effect26.catch(unproven), Effect26.catchDefect(unproven));
2323
+ const unproven = (reason) => Effect28.as(Effect28.logWarning(`${ask.fqn}: the interrupted create's object could not be compared with its props ` + `(${reason instanceof Error ? reason.message : String(reason)}), so it is not treated as ours`), false);
2324
+ return yield* settled2.pipe(Effect28.catch(unproven), Effect28.catchDefect(unproven));
1293
2325
  });
1294
- var ownedRead = (ask, found, settled2) => Effect26.gen(function* () {
2326
+ var ownedRead = (ask, found, settled2) => Effect28.gen(function* () {
1295
2327
  if (found === undefined || ask.output !== undefined)
1296
2328
  return found;
1297
2329
  return (yield* provenOurs(ask, settled2)) ? found : Unowned2(found);
@@ -1746,11 +2778,11 @@ var identityRefusals = (news, olds, output) => {
1746
2778
  };
1747
2779
 
1748
2780
  // src/proxmox/lxc-adoption.ts
1749
- import * as Effect30 from "effect/Effect";
2781
+ import * as Effect32 from "effect/Effect";
1750
2782
 
1751
2783
  // src/ownership/adopting.ts
1752
- import * as Effect27 from "effect/Effect";
1753
- var adopting = (owner, settled2) => Effect27.gen(function* () {
2784
+ import * as Effect29 from "effect/Effect";
2785
+ var adopting = (owner, settled2) => Effect29.gen(function* () {
1754
2786
  if (owner.output === undefined)
1755
2787
  return false;
1756
2788
  const generation = yield* recordedGeneration(owner.fqn, owner.instanceId);
@@ -1762,11 +2794,11 @@ var adopting = (owner, settled2) => Effect27.gen(function* () {
1762
2794
  });
1763
2795
 
1764
2796
  // src/proxmox/lxc-lifecycle.ts
1765
- import * as Effect29 from "effect/Effect";
2797
+ import * as Effect31 from "effect/Effect";
1766
2798
 
1767
2799
  // src/proxmox/network-apply-read.ts
1768
- import * as Effect28 from "effect/Effect";
1769
- var stagedDiff = (target, node) => Effect28.gen(function* () {
2800
+ import * as Effect30 from "effect/Effect";
2801
+ var stagedDiff = (target, node) => Effect30.gen(function* () {
1770
2802
  const path = `nodes/${node}/network`;
1771
2803
  const credential = yield* leased(target, "read");
1772
2804
  const envelope = yield* pveEnvelopeWith(target, credential, "GET", path);
@@ -1779,8 +2811,8 @@ var pendingLines = (diff) => {
1779
2811
  `).filter((line) => (line.startsWith("+") || line.startsWith("-")) && !line.startsWith("+++") && !line.startsWith("---")).length;
1780
2812
  return Math.max(changed, 1);
1781
2813
  };
1782
- var pendingCount = (target, node) => stagedDiff(target, node).pipe(Effect28.map(pendingLines));
1783
- var clusterHealth = (target) => pve(target, "read", "GET", "cluster/status").pipe(Effect28.map((rows) => {
2814
+ var pendingCount = (target, node) => stagedDiff(target, node).pipe(Effect30.map(pendingLines));
2815
+ var clusterHealth = (target) => pve(target, "read", "GET", "cluster/status").pipe(Effect30.map((rows) => {
1784
2816
  const all = rows ?? [];
1785
2817
  const cluster = all.find((row) => row.type === "cluster");
1786
2818
  return {
@@ -1788,21 +2820,21 @@ var clusterHealth = (target) => pve(target, "read", "GET", "cluster/status").pip
1788
2820
  quorate: cluster === undefined ? true : bool(cluster.quorate)
1789
2821
  };
1790
2822
  }));
1791
- var degradedReason = (target) => clusterHealth(target).pipe(Effect28.map((health) => health.quorate && health.offline.length === 0 ? undefined : `quorate=${String(health.quorate)} offline=[${health.offline.join(", ")}]`));
2823
+ var degradedReason = (target) => clusterHealth(target).pipe(Effect30.map((health) => health.quorate && health.offline.length === 0 ? undefined : `quorate=${String(health.quorate)} offline=[${health.offline.join(", ")}]`));
1792
2824
  var UNREACHABLE = "the task could not be read -- the node stopped answering, or this lease cannot see it";
1793
2825
  var STILL_RUNNING = "still running when this provider stopped waiting";
1794
2826
  var ATTEMPTS = 30;
1795
- var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect28.gen(function* () {
2827
+ var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect30.gen(function* () {
1796
2828
  const path = `nodes/${node}/tasks/${upid}/status`;
1797
2829
  for (let attempt = 0;attempt < attempts; attempt += 1) {
1798
- const status = yield* pveWith(target, credential, "GET", path).pipe(Effect28.orElseSucceed(() => {
2830
+ const status = yield* pveWith(target, credential, "GET", path).pipe(Effect30.orElseSucceed(() => {
1799
2831
  return;
1800
2832
  }));
1801
2833
  if (status === undefined)
1802
2834
  return UNREACHABLE;
1803
2835
  if (status.status === "stopped")
1804
2836
  return text(status.exitstatus, "stopped with no exitstatus");
1805
- yield* Effect28.sleep("1 second");
2837
+ yield* Effect30.sleep("1 second");
1806
2838
  }
1807
2839
  return STILL_RUNNING;
1808
2840
  });
@@ -1812,20 +2844,25 @@ class LxcRefusedError extends Error {
1812
2844
  name = "LxcRefusedError";
1813
2845
  }
1814
2846
  var guestPath = (where) => `nodes/${where.node}/lxc/${String(where.vmid)}`;
2847
+ var LXC_ENDPOINTS = {
2848
+ create: "pve:POST /nodes/{node}/lxc",
2849
+ resize: "pve:PUT /nodes/{node}/lxc/{vmid}/resize",
2850
+ update: "pve:PUT /nodes/{node}/lxc/{vmid}/config"
2851
+ };
1815
2852
  var CREATE_POLLS = 180;
1816
2853
  var TASK_POLLS = 60;
1817
2854
  var isServerError = (error) => error instanceof PveError && error.status === 500;
1818
- var readLive = (where) => Effect29.gen(function* () {
1819
- const answer = yield* pve(where.target, "read", "GET", `${guestPath(where)}/config`).pipe(Effect29.map((data) => ({ data, error: undefined })), Effect29.catchIf(isServerError, (error) => Effect29.succeed({ data: undefined, error })));
2855
+ var readLive = (where) => Effect31.gen(function* () {
2856
+ const answer = yield* pve(where.target, "read", "GET", `${guestPath(where)}/config`).pipe(Effect31.map((data) => ({ data, error: undefined })), Effect31.catchIf(isServerError, (error) => Effect31.succeed({ data: undefined, error })));
1820
2857
  if (answer.data !== undefined && answer.data !== null)
1821
2858
  return answer.data;
1822
2859
  const rows = yield* pve(where.target, "read", "GET", "cluster/resources?type=vm");
1823
2860
  const found = (rows ?? []).find((row) => Number(row.vmid) === where.vmid);
1824
2861
  if (found !== undefined && found.node === where.node && found.type === "lxc") {
1825
- return yield* Effect29.fail(answer.error ?? new LxcRefusedError(`CT ${String(where.vmid)} is listed but its config read empty.`));
2862
+ return yield* Effect31.fail(answer.error ?? new LxcRefusedError(`CT ${String(where.vmid)} is listed but its config read empty.`));
1826
2863
  }
1827
2864
  if (found !== undefined) {
1828
- return yield* Effect29.fail(new LxcRefusedError(`vmid ${String(where.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a container on ${where.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
2865
+ return yield* Effect31.fail(new LxcRefusedError(`vmid ${String(where.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a container on ${where.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
1829
2866
  }
1830
2867
  return;
1831
2868
  });
@@ -1835,54 +2872,61 @@ var attributesOf = (where, live) => ({
1835
2872
  rawKeys: rawKeysOf(live),
1836
2873
  vmid: where.vmid
1837
2874
  });
1838
- var task = (where, method, path, what, polls, form) => Effect29.gen(function* () {
2875
+ var task = (where, method, path, what, polls, form) => Effect31.gen(function* () {
1839
2876
  const credential = yield* mint(where.target, "provision");
1840
2877
  const upid = text(yield* pveWith(where.target, credential, method, path, form));
1841
2878
  if (upid === "") {
1842
- return yield* Effect29.fail(new LxcRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
2879
+ return yield* Effect31.fail(new LxcRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
1843
2880
  }
1844
2881
  const exit = yield* awaitTask(where.target, credential, where.node, upid, polls);
1845
2882
  if (exit !== "OK") {
1846
- return yield* Effect29.fail(new LxcRefusedError(`${what}: task ${upid} ended "${exit}". Read \`pvesh get /nodes/${where.node}/tasks/` + `${upid}/log\` before running the deploy again.`));
2883
+ return yield* Effect31.fail(new LxcRefusedError(`${what}: task ${upid} ended "${exit}". Read \`pvesh get /nodes/${where.node}/tasks/` + `${upid}/log\` before running the deploy again.`));
1847
2884
  }
1848
2885
  });
1849
- var createGuest = (props) => task(props, "POST", `nodes/${props.node}/lxc`, `create CT ${String(props.vmid)}`, CREATE_POLLS, createForm3(props));
1850
- var updateGuest = (props, change, digest) => Effect29.gen(function* () {
2886
+ var createGuest = (props) => Effect31.gen(function* () {
2887
+ const form = createForm3(props);
2888
+ yield* guardForm(LXC_ENDPOINTS.create, form, true);
2889
+ return yield* task(props, "POST", `nodes/${props.node}/lxc`, `create CT ${String(props.vmid)}`, CREATE_POLLS, form);
2890
+ });
2891
+ var updateGuest = (props, change, digest) => Effect31.gen(function* () {
1851
2892
  if (Object.keys(change.put).length > 0 || change.clear.length > 0) {
1852
2893
  const form = withClears({ ...change.put, ...digest === "" ? {} : { digest } }, change.clear);
2894
+ yield* guardForm(LXC_ENDPOINTS.update, form, false);
1853
2895
  yield* pve(props.target, "provision", "PUT", `${guestPath(props)}/config`, form);
1854
2896
  }
1855
2897
  for (const grow of change.resize) {
1856
- yield* task(props, "PUT", `${guestPath(props)}/resize`, `grow ${grow.disk} of CT ${String(props.vmid)} to ${grow.size}`, TASK_POLLS, { disk: grow.disk, size: grow.size });
2898
+ const grown = { disk: grow.disk, size: grow.size };
2899
+ yield* guardForm(LXC_ENDPOINTS.resize, grown, true);
2900
+ yield* task(props, "PUT", `${guestPath(props)}/resize`, `grow ${grow.disk} of CT ${String(props.vmid)} to ${grow.size}`, TASK_POLLS, grown);
1857
2901
  }
1858
2902
  });
1859
- var destroyGuest = (where, declared) => Effect29.gen(function* () {
2903
+ var destroyGuest = (where, declared) => Effect31.gen(function* () {
1860
2904
  const live = yield* readLive(where);
1861
2905
  if (live === undefined)
1862
2906
  return;
1863
2907
  const drift = judge(declared, live).drift;
1864
2908
  if (drift.length > 0) {
1865
- return yield* Effect29.fail(new LxcRefusedError(`destroy CT ${String(where.vmid)}: the guest on ${where.node} no longer matches its last ` + `declaration (${drift.join(", ")}), so it may not be the guest this stack made. ` + "Nothing was deleted. Delete it by hand if it should go, or declare it again."));
2909
+ return yield* Effect31.fail(new LxcRefusedError(`destroy CT ${String(where.vmid)}: the guest on ${where.node} no longer matches its last ` + `declaration (${drift.join(", ")}), so it may not be the guest this stack made. ` + "Nothing was deleted. Delete it by hand if it should go, or declare it again."));
1866
2910
  }
1867
2911
  yield* task(where, "DELETE", guestPath(where), `destroy CT ${String(where.vmid)}`, TASK_POLLS);
1868
2912
  });
1869
2913
 
1870
2914
  // src/proxmox/lxc-adoption.ts
1871
2915
  var adoptionRefusal = (props, drift) => `CT ${String(props.vmid)} on ${props.node}: adopting it would change ${drift.join(", ")}. An ` + "adoption never changes a guest, so nothing is written. Declare what is live for these keys " + "(the plan names keys, never values) and plan again; change them after the adoption, as an " + "update.";
1872
- var refuseAdoptedDrift = (owner, props, live, change) => Effect30.gen(function* () {
2916
+ var refuseAdoptedDrift = (owner, props, live, change) => Effect32.gen(function* () {
1873
2917
  if (change.drift.length === 0)
1874
2918
  return;
1875
- const settled2 = (recorded) => Effect30.sync(() => judge(recorded, live).drift.length === 0);
2919
+ const settled2 = (recorded) => Effect32.sync(() => judge(recorded, live).drift.length === 0);
1876
2920
  if (!(yield* adopting(owner, settled2)))
1877
2921
  return;
1878
- return yield* Effect30.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
2922
+ return yield* Effect32.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
1879
2923
  });
1880
2924
 
1881
2925
  // src/proxmox/lxc.ts
1882
2926
  var ProxmoxLxc = Resource13("Proxmox.Lxc", { defaultRemovalPolicy: "retain" });
1883
- var refused = (reasons) => Effect31.fail(new LxcRefusedError(reasons.join(`
2927
+ var refused = (reasons) => Effect33.fail(new LxcRefusedError(reasons.join(`
1884
2928
  `)));
1885
- var diff = (owner, news, olds) => Effect31.gen(function* () {
2929
+ var diff = (owner, news, olds) => Effect33.gen(function* () {
1886
2930
  const { output } = owner;
1887
2931
  const identity2 = identityRefusals(news, olds, output);
1888
2932
  if (identity2.length > 0)
@@ -1896,7 +2940,7 @@ var diff = (owner, news, olds) => Effect31.gen(function* () {
1896
2940
  const refusals = createRefusals(news);
1897
2941
  if (refusals.length > 0)
1898
2942
  return yield* refused(refusals);
1899
- yield* Effect31.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: the cluster lists no guest with this ` + "vmid -- a deploy CREATES it again from ostemplate, with new, empty volumes.");
2943
+ yield* Effect33.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: the cluster lists no guest with this ` + "vmid -- a deploy CREATES it again from ostemplate, with new, empty volumes.");
1900
2944
  return { action: "update" };
1901
2945
  }
1902
2946
  const change = judge(news, live);
@@ -1907,10 +2951,10 @@ var diff = (owner, news, olds) => Effect31.gen(function* () {
1907
2951
  if (change.drift.length === 0 && !moved)
1908
2952
  return { action: "noop" };
1909
2953
  const what = change.drift.length === 0 ? `the guest is on ${news.node} now, not ${output.node} -- a deploy re-records it, ` + "writing nothing." : `live config differs from the declaration in ${change.drift.join(", ")} -- a ` + "deploy writes these.";
1910
- yield* Effect31.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
2954
+ yield* Effect33.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
1911
2955
  return { action: "update" };
1912
2956
  });
1913
- var reconcile = (owner, news) => Effect31.gen(function* () {
2957
+ var reconcile = (owner, news) => Effect33.gen(function* () {
1914
2958
  const { output } = owner;
1915
2959
  const identity2 = identityRefusals(news, news, output);
1916
2960
  if (identity2.length > 0)
@@ -1956,12 +3000,12 @@ var whereOf = (olds, output) => ({
1956
3000
  target: olds.target,
1957
3001
  vmid: output?.vmid ?? olds.vmid
1958
3002
  });
1959
- var read = (owner, olds) => Effect31.gen(function* () {
3003
+ var read = (owner, olds) => Effect33.gen(function* () {
1960
3004
  const where = whereOf(olds, owner.output);
1961
3005
  const live = yield* readLive(where);
1962
3006
  if (live === undefined)
1963
3007
  return;
1964
- const settled2 = Effect31.sync(() => judge(olds, live).drift.length === 0);
3008
+ const settled2 = Effect33.sync(() => judge(olds, live).drift.length === 0);
1965
3009
  return yield* ownedRead(owner, attributesOf(where, live), settled2);
1966
3010
  });
1967
3011
  var handlers10 = {
@@ -1973,7 +3017,7 @@ var handlers10 = {
1973
3017
  olds,
1974
3018
  output
1975
3019
  }) => diff({ fqn, instanceId, output }, news, olds),
1976
- list: () => Effect31.succeed([]),
3020
+ list: () => Effect33.succeed([]),
1977
3021
  read: ({
1978
3022
  fqn,
1979
3023
  instanceId,
@@ -1987,11 +3031,11 @@ var handlers10 = {
1987
3031
  output
1988
3032
  }) => reconcile({ fqn, instanceId, output }, news)
1989
3033
  };
1990
- var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect31.succeed(ProxmoxLxc.Provider.of(handlers10)).pipe(Effect31.map(provingResumes)));
3034
+ var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect33.succeed(ProxmoxLxc.Provider.of(handlers10)).pipe(Effect33.map(provingResumes)));
1991
3035
  // src/proxmox/metric-server.ts
1992
3036
  import { Resource as Resource14 } from "alchemy";
1993
3037
  import * as Provider14 from "alchemy/Provider";
1994
- import * as Effect32 from "effect/Effect";
3038
+ import * as Effect34 from "effect/Effect";
1995
3039
 
1996
3040
  // src/proxmox/metric-server-form.ts
1997
3041
  var UNSET2 = -1;
@@ -2048,6 +3092,7 @@ var update = (props) => {
2048
3092
  const clear = Object.entries(optional2(props)).filter(([, value]) => value === undefined).map(([option]) => option);
2049
3093
  return withClears(body3(props), clear);
2050
3094
  };
3095
+ var createBody2 = (props) => ({ ...body3(props), type: props.type });
2051
3096
 
2052
3097
  // src/proxmox/metric-server-otel.ts
2053
3098
  var otelAttributes = (live) => ({
@@ -2094,27 +3139,39 @@ var handlers11 = pveHandlers({
2094
3139
  };
2095
3140
  },
2096
3141
  collection: (props) => `cluster/metrics/server/${props.id}`,
2097
- createForm: (props) => ({ ...body3(props), type: props.type }),
3142
+ createForm: createBody2,
3143
+ endpoint: {
3144
+ create: "pve:POST /cluster/metrics/server/{id}",
3145
+ update: "pve:PUT /cluster/metrics/server/{id}"
3146
+ },
2098
3147
  matches: (attributes, props) => attributes.server === props.server && attributes.port === props.port && attributes.disable === (props.disable === true) && matchesType(attributes, props),
2099
3148
  path: (props) => `cluster/metrics/server/${props.id}`,
2100
3149
  updateForm: update
2101
3150
  });
2102
- var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect32.succeed(ProxmoxMetricServer.Provider.of(handlers11)));
3151
+ var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect34.succeed(ProxmoxMetricServer.Provider.of(handlers11)));
2103
3152
  // src/proxmox/network-apply.ts
2104
3153
  import { Resource as Resource15 } from "alchemy";
2105
3154
  import { isResolved as isResolved7 } from "alchemy/Diff";
2106
3155
  import * as Provider15 from "alchemy/Provider";
2107
- import * as Effect33 from "effect/Effect";
3156
+ import * as Effect35 from "effect/Effect";
3157
+
3158
+ // src/proxmox/apply-endpoints.ts
3159
+ var NETWORK_APPLY_ENDPOINT = "pve:PUT /nodes/{node}/network";
3160
+ var SDN_APPLY_ENDPOINT = "pve:PUT /cluster/sdn";
3161
+ var guardNetworkApply = guardForm(NETWORK_APPLY_ENDPOINT, {}, true);
3162
+ var guardSdnApply = guardForm(SDN_APPLY_ENDPOINT, {}, true);
3163
+
3164
+ // src/proxmox/network-apply.ts
2108
3165
  var ProxmoxNetworkApply = Resource15("Proxmox.NetworkApply");
2109
- var read2 = (props) => pendingCount(props.target, props.node).pipe(Effect33.map((pending) => ({ node: props.node, pending })));
2110
- var diff2 = (news) => Effect33.gen(function* () {
3166
+ var read2 = (props) => pendingCount(props.target, props.node).pipe(Effect35.map((pending) => ({ node: props.node, pending })));
3167
+ var diff2 = (news) => Effect35.gen(function* () {
2111
3168
  if (!isResolved7(news))
2112
3169
  return;
2113
3170
  const { pending } = yield* read2(news);
2114
3171
  return pending === 0 ? { action: "noop" } : { action: "update" };
2115
3172
  });
2116
- var refuse = (node, why) => Effect33.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
2117
- var apply = (props) => Effect33.gen(function* () {
3173
+ var refuse = (node, why) => Effect35.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
3174
+ var apply = (props) => Effect35.gen(function* () {
2118
3175
  const node = props.node;
2119
3176
  const staged = yield* pendingCount(props.target, node);
2120
3177
  if (staged === 0)
@@ -2123,6 +3180,7 @@ var apply = (props) => Effect33.gen(function* () {
2123
3180
  if (before !== undefined) {
2124
3181
  return yield* refuse(node, `refusing to reload networking on a cluster that is already degraded (${before}). ` + "Ceph spans these nodes -- fix the cluster first, then re-run the deploy.");
2125
3182
  }
3183
+ yield* guardNetworkApply;
2126
3184
  const credential = yield* mint(props.target, "provision");
2127
3185
  const upid = yield* pveWith(props.target, credential, "PUT", `nodes/${node}/network`);
2128
3186
  if (upid === undefined) {
@@ -2143,17 +3201,17 @@ var apply = (props) => Effect33.gen(function* () {
2143
3201
  return { node, pending: left };
2144
3202
  });
2145
3203
  var handlers12 = {
2146
- delete: () => Effect33.void,
3204
+ delete: () => Effect35.void,
2147
3205
  diff: ({ news }) => diff2(news),
2148
- list: () => Effect33.succeed([]),
3206
+ list: () => Effect35.succeed([]),
2149
3207
  read: ({ olds }) => read2(olds),
2150
3208
  reconcile: ({ news }) => apply(news)
2151
3209
  };
2152
- var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect33.succeed(ProxmoxNetworkApply.Provider.of(handlers12)));
3210
+ var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect35.succeed(ProxmoxNetworkApply.Provider.of(handlers12)));
2153
3211
  // src/proxmox/node-network.ts
2154
3212
  import { Resource as Resource16 } from "alchemy";
2155
3213
  import * as Provider16 from "alchemy/Provider";
2156
- import * as Effect34 from "effect/Effect";
3214
+ import * as Effect36 from "effect/Effect";
2157
3215
 
2158
3216
  // src/proxmox/node-network-form.ts
2159
3217
  var UNSET3 = -1;
@@ -2180,6 +3238,10 @@ var body4 = (props) => ({
2180
3238
  ...field3("vlan-raw-device", props["vlan-raw-device"]),
2181
3239
  type: props.type
2182
3240
  });
3241
+ var createBody3 = (props) => ({
3242
+ ...body4(props),
3243
+ iface: props.iface
3244
+ });
2183
3245
  var updateBody2 = (props) => {
2184
3246
  const clear = [
2185
3247
  ...props.cidr === undefined ? ["cidr"] : [],
@@ -2228,16 +3290,20 @@ var ProxmoxNodeNetwork = Resource16("Proxmox.NodeNetwork", {
2228
3290
  var handlers13 = pveHandlers({
2229
3291
  attributes: readAttributes,
2230
3292
  collection: (props) => `nodes/${props.node}/network`,
2231
- createForm: body4,
3293
+ createForm: createBody3,
3294
+ endpoint: {
3295
+ create: "pve:POST /nodes/{node}/network",
3296
+ update: "pve:PUT /nodes/{node}/network/{iface}"
3297
+ },
2232
3298
  matches: (attributes, props) => attributes.cidr === (props.cidr ?? "") && same2(props.gateway, attributes.gateway) && same2(props.autostart, attributes.autostart) && same2(props.mtu, attributes.mtu) && sameComment(props.comments, attributes.comments) && sameList(props.bridge_ports, attributes.bridge_ports) && sameList(props.bridge_vids, attributes.bridge_vids) && same2(props.bridge_vlan_aware, attributes.bridge_vlan_aware) && sameList(props.slaves, attributes.slaves) && same2(props.bond_mode, attributes.bond_mode) && same2(props.bond_xmit_hash_policy, attributes.bond_xmit_hash_policy) && same2(props["bond-primary"], attributes["bond-primary"]) && same2(props["vlan-id"], attributes["vlan-id"]) && same2(props["vlan-raw-device"], attributes["vlan-raw-device"]),
2233
3299
  path: (props) => `nodes/${props.node}/network/${props.iface}`,
2234
3300
  updateForm: updateBody2
2235
3301
  });
2236
- var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect34.succeed(ProxmoxNodeNetwork.Provider.of(handlers13)));
3302
+ var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect36.succeed(ProxmoxNodeNetwork.Provider.of(handlers13)));
2237
3303
  // src/proxmox/notification-matcher.ts
2238
3304
  import { Resource as Resource17 } from "alchemy";
2239
3305
  import * as Provider17 from "alchemy/Provider";
2240
- import * as Effect35 from "effect/Effect";
3306
+ import * as Effect37 from "effect/Effect";
2241
3307
 
2242
3308
  // src/proxmox/notification-matcher-form.ts
2243
3309
  var list = (value) => Array.isArray(value) ? value.map((item) => String(item)) : [];
@@ -2319,15 +3385,40 @@ var handlers14 = pveHandlers({
2319
3385
  attributes: (live, props) => matcherAttributes(live, props.name),
2320
3386
  collection: () => "cluster/notifications/matchers",
2321
3387
  createForm: matcherCreateForm,
3388
+ endpoint: {
3389
+ create: "pve:POST /cluster/notifications/matchers",
3390
+ update: "pve:PUT /cluster/notifications/matchers/{name}"
3391
+ },
2322
3392
  matches: matcherMatches,
2323
3393
  path: (props) => `cluster/notifications/matchers/${props.name}`,
2324
3394
  updateForm: matcherUpdateForm
2325
3395
  });
2326
- var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect35.succeed(ProxmoxNotificationMatcher.Provider.of(handlers14)));
3396
+ var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect37.succeed(ProxmoxNotificationMatcher.Provider.of(handlers14)));
2327
3397
  // src/proxmox/notification-target.ts
2328
3398
  import { Resource as Resource18 } from "alchemy";
2329
3399
  import * as Provider18 from "alchemy/Provider";
2330
- import * as Effect36 from "effect/Effect";
3400
+ import * as Effect38 from "effect/Effect";
3401
+
3402
+ // src/proxmox/notification-target-endpoint.ts
3403
+ var ENDPOINTS = {
3404
+ gotify: {
3405
+ create: "pve:POST /cluster/notifications/endpoints/gotify",
3406
+ update: "pve:PUT /cluster/notifications/endpoints/gotify/{name}"
3407
+ },
3408
+ sendmail: {
3409
+ create: "pve:POST /cluster/notifications/endpoints/sendmail",
3410
+ update: "pve:PUT /cluster/notifications/endpoints/sendmail/{name}"
3411
+ },
3412
+ smtp: {
3413
+ create: "pve:POST /cluster/notifications/endpoints/smtp",
3414
+ update: "pve:PUT /cluster/notifications/endpoints/smtp/{name}"
3415
+ },
3416
+ webhook: {
3417
+ create: "pve:POST /cluster/notifications/endpoints/webhook",
3418
+ update: "pve:PUT /cluster/notifications/endpoints/webhook/{name}"
3419
+ }
3420
+ };
3421
+ var targetEndpoint = (props) => ENDPOINTS[props.type];
2331
3422
 
2332
3423
  // src/proxmox/notification-target-form.ts
2333
3424
  var REPEATED_KEY = "\x00";
@@ -2355,6 +3446,10 @@ var shape4 = (props) => ({
2355
3446
  ...set("url", props.url),
2356
3447
  ...set("username", props.username)
2357
3448
  });
3449
+ var createShape = (props) => ({
3450
+ ...shape4(props),
3451
+ name: props.name
3452
+ });
2358
3453
 
2359
3454
  // src/proxmox/notification-target.ts
2360
3455
  var ProxmoxNotificationTarget = Resource18("Proxmox.NotificationTarget");
@@ -2378,20 +3473,21 @@ var handlers15 = pveHandlers({
2378
3473
  username: text(live["username"])
2379
3474
  }),
2380
3475
  collection: (props) => `cluster/notifications/endpoints/${props.type}`,
2381
- createForm: (props) => ({ ...shape4(props), name: props.name }),
3476
+ createForm: createShape,
3477
+ endpoint: targetEndpoint,
2382
3478
  matches: (attributes, props) => attributes.disable === (props.disable === true) && (props.comment === undefined || attributes.comment === props.comment) && (props.server === undefined || attributes.server === props.server) && (props.port === undefined || attributes.port === props.port) && (props.mode === undefined || attributes.mode === props.mode) && (props.username === undefined || attributes.username === props.username) && (props["from-address"] === undefined || attributes["from-address"] === props["from-address"]) && (props.author === undefined || attributes.author === props.author) && (props.url === undefined || attributes.url === props.url) && (props.method === undefined || attributes.method === props.method) && (props.body === undefined || attributes.body === props.body) && (props.mailto === undefined || attributes.mailto === addressList(props.mailto)) && (props["mailto-user"] === undefined || attributes["mailto-user"] === addressList(props["mailto-user"])) && (props.header === undefined || attributes.header === headerList(props.header)),
2383
3479
  path: (props) => `cluster/notifications/endpoints/${props.type}/${props.name}`,
2384
3480
  updateForm: shape4
2385
3481
  });
2386
- var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect36.succeed(ProxmoxNotificationTarget.Provider.of(handlers15)));
3482
+ var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect38.succeed(ProxmoxNotificationTarget.Provider.of(handlers15)));
2387
3483
  // src/proxmox/pbs-datastore.ts
2388
3484
  import { Resource as Resource19 } from "alchemy";
2389
3485
  import { isResolved as isResolved8 } from "alchemy/Diff";
2390
3486
  import * as Provider19 from "alchemy/Provider";
2391
- import * as Effect39 from "effect/Effect";
3487
+ import * as Effect42 from "effect/Effect";
2392
3488
 
2393
3489
  // src/proxmox/pbs-datastore-form.ts
2394
- import * as Effect37 from "effect/Effect";
3490
+ import * as Effect39 from "effect/Effect";
2395
3491
  var attributes = (live, props) => ({
2396
3492
  backend: propertyString(live["backend"]),
2397
3493
  comment: text(live["comment"]),
@@ -2443,37 +3539,51 @@ var createForm4 = (props) => ({
2443
3539
  });
2444
3540
  var updateForm = (props) => mutable(props);
2445
3541
  var object2 = (props) => `config/datastore/${props.name}`;
2446
- var readOne = (props) => pve(props.target, "read", "GET", object2(props)).pipe(Effect37.map((live) => live === undefined || typeof live["name"] !== "string" ? undefined : attributes(live, props)), Effect37.orElseSucceed(() => {
3542
+ var readOne = (props) => pve(props.target, "read", "GET", object2(props)).pipe(Effect39.map((live) => live === undefined || typeof live["name"] !== "string" ? undefined : attributes(live, props)), Effect39.orElseSucceed(() => {
2447
3543
  return;
2448
3544
  }));
2449
3545
 
2450
3546
  // src/proxmox/pbs-datastore-guard.ts
2451
- import * as Effect38 from "effect/Effect";
3547
+ import * as Effect40 from "effect/Effect";
2452
3548
  var samePath = (left, right) => {
2453
3549
  const trim = (value) => value.length > 1 ? value.replace(/\/+$/, "") : value;
2454
3550
  return trim(left) === trim(right);
2455
3551
  };
2456
- var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect38.void : Effect38.die(new Error(`${object2(props)}: declared path ${props.path} but PBS holds ${live.path}. \`path\` ` + "is create-only, so this cannot be reconciled and will NOT be planned as a silent " + "noop: backups would keep landing in the old directory behind a green plan. Correct " + "the declaration, or remove the datastore and declare a new one -- the contents live, " + "because `destroy-data` is never sent."));
2457
- var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect38.void : Effect38.die(new Error(`${object2(props)}: declared backend ${props.backend} but PBS holds ` + `${live.backend === "" ? "(none — a local datastore)" : live.backend}. \`backend\` ` + "is create-only: PBS has no update for it, so this cannot be reconciled and will NOT " + "be planned as a silent noop. Correct the declaration to match what is really there, " + "or remove the datastore and declare a new one -- the contents live, because " + "`destroy-data` is never sent."));
2458
- var settle3 = (read3, done) => Effect38.gen(function* () {
3552
+ var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect40.void : Effect40.die(new Error(`${object2(props)}: declared path ${props.path} but PBS holds ${live.path}. \`path\` ` + "is create-only, so this cannot be reconciled and will NOT be planned as a silent " + "noop: backups would keep landing in the old directory behind a green plan. Correct " + "the declaration, or remove the datastore and declare a new one -- the contents live, " + "because `destroy-data` is never sent."));
3553
+ var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect40.void : Effect40.die(new Error(`${object2(props)}: declared backend ${props.backend} but PBS holds ` + `${live.backend === "" ? "(none — a local datastore)" : live.backend}. \`backend\` ` + "is create-only: PBS has no update for it, so this cannot be reconciled and will NOT " + "be planned as a silent noop. Correct the declaration to match what is really there, " + "or remove the datastore and declare a new one -- the contents live, because " + "`destroy-data` is never sent."));
3554
+ var settle3 = (read3, done) => Effect40.gen(function* () {
2459
3555
  for (let attempt = 0;attempt < 60; attempt += 1) {
2460
3556
  const live = yield* read3;
2461
3557
  if (done(live))
2462
3558
  return live;
2463
- yield* Effect38.sleep("2 seconds");
3559
+ yield* Effect40.sleep("2 seconds");
2464
3560
  }
2465
3561
  return yield* read3;
2466
3562
  });
2467
3563
 
3564
+ // src/proxmox/pbs-datastore-endpoint.ts
3565
+ import * as Effect41 from "effect/Effect";
3566
+ var DATASTORE_ENDPOINT = {
3567
+ create: "pbs:POST /config/datastore",
3568
+ update: "pbs:PUT /config/datastore/{name}"
3569
+ };
3570
+ var guardDatastoreForms = (props) => Effect41.gen(function* () {
3571
+ yield* guardForm(DATASTORE_ENDPOINT.create, createForm4(props), true);
3572
+ yield* guardForm(DATASTORE_ENDPOINT.update, updateForm(props), false);
3573
+ });
3574
+
2468
3575
  // src/proxmox/pbs-datastore.ts
2469
3576
  var PbsDatastore = Resource19("Pbs.Datastore", {
2470
3577
  defaultRemovalPolicy: "retain"
2471
3578
  });
2472
- var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect39.succeed(PbsDatastore.Provider.of({
2473
- list: () => Effect39.succeed([]),
3579
+ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect42.succeed(PbsDatastore.Provider.of({
3580
+ list: () => Effect42.succeed([]),
2474
3581
  read: ({ olds }) => readOne(olds),
2475
- diff: ({ news, output }) => Effect39.gen(function* () {
2476
- if (output === undefined || !isResolved8(news))
3582
+ diff: ({ news, output }) => Effect42.gen(function* () {
3583
+ if (!isResolved8(news))
3584
+ return;
3585
+ yield* guardDatastoreForms(news);
3586
+ if (output === undefined)
2477
3587
  return;
2478
3588
  const live = yield* readOne(news);
2479
3589
  if (live === undefined)
@@ -2482,7 +3592,8 @@ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect39.succee
2482
3592
  yield* guardBackend(live, news);
2483
3593
  return matches(live, news) ? { action: "noop" } : { action: "update" };
2484
3594
  }),
2485
- reconcile: Effect39.fn(function* ({ news }) {
3595
+ reconcile: Effect42.fn(function* ({ news }) {
3596
+ yield* guardDatastoreForms(news);
2486
3597
  const live = yield* readOne(news);
2487
3598
  let upid;
2488
3599
  if (live === undefined) {
@@ -2497,40 +3608,61 @@ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect39.succee
2497
3608
  }
2498
3609
  const after = yield* settle3(readOne(news), (row) => row !== undefined && matches(row, news));
2499
3610
  if (after === undefined || !matches(after, news)) {
2500
- return yield* Effect39.die(new Error(`${object2(news)}: the write returned no error but the datastore still does not ` + `match the declaration after 120s. PBS answered with task ${upid ?? "(none)"} ` + "-- read it with `proxmox-backup-manager task log <upid>`. A slow disk is a " + "plausible cause (see `settle`); a create over an existing chunk store is not, " + "because PBS refuses that outright rather than timing out."));
3611
+ return yield* Effect42.die(new Error(`${object2(news)}: the write returned no error but the datastore still does not ` + `match the declaration after 120s. PBS answered with task ${upid ?? "(none)"} ` + "-- read it with `proxmox-backup-manager task log <upid>`. A slow disk is a " + "plausible cause (see `settle`); a create over an existing chunk store is not, " + "because PBS refuses that outright rather than timing out."));
2501
3612
  }
2502
3613
  return after;
2503
3614
  }),
2504
- delete: Effect39.fn(function* ({ olds }) {
3615
+ delete: Effect42.fn(function* ({ olds }) {
2505
3616
  yield* pve(olds.target, "provision", "DELETE", object2(olds));
2506
3617
  const left = yield* settle3(readOne(olds), (row) => row === undefined);
2507
3618
  if (left !== undefined) {
2508
- return yield* Effect39.die(new Error(`${object2(olds)}: the DELETE returned no error but the datastore is still in ` + "datastore.cfg after 120s. Either a backup, verify or GC task still holds it, " + "or the provision role lacks Datastore.Allocate on /datastore/" + `${olds.name}. Read the task log with \`proxmox-backup-manager task log <upid>\`.`));
3619
+ return yield* Effect42.die(new Error(`${object2(olds)}: the DELETE returned no error but the datastore is still in ` + "datastore.cfg after 120s. Either a backup, verify or GC task still holds it, " + "or the provision role lacks Datastore.Allocate on /datastore/" + `${olds.name}. Read the task log with \`proxmox-backup-manager task log <upid>\`.`));
2509
3620
  }
2510
3621
  })
2511
3622
  })));
2512
3623
  // src/proxmox/pbs-notification-matcher.ts
2513
3624
  import { Resource as Resource20 } from "alchemy";
2514
3625
  import * as Provider20 from "alchemy/Provider";
2515
- import * as Effect40 from "effect/Effect";
3626
+ import * as Effect43 from "effect/Effect";
2516
3627
  var PbsNotificationMatcher = Resource20("Pbs.NotificationMatcher");
2517
3628
  var handlers16 = pveHandlers({
2518
3629
  attributes: (live, props) => matcherAttributes(live, props.name),
2519
3630
  collection: () => "config/notifications/matchers",
2520
3631
  createForm: matcherCreateForm,
3632
+ endpoint: {
3633
+ create: "pbs:POST /config/notifications/matchers",
3634
+ update: "pbs:PUT /config/notifications/matchers/{name}"
3635
+ },
2521
3636
  matches: matcherMatches,
2522
3637
  path: (props) => `config/notifications/matchers/${props.name}`,
2523
3638
  updateForm: matcherUpdateForm
2524
3639
  });
2525
- var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect40.succeed(PbsNotificationMatcher.Provider.of(handlers16)));
3640
+ var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect43.succeed(PbsNotificationMatcher.Provider.of(handlers16)));
2526
3641
  // src/proxmox/pbs-notification-target.ts
2527
3642
  import { Resource as Resource21 } from "alchemy";
2528
3643
  import * as Provider21 from "alchemy/Provider";
2529
- import * as Effect42 from "effect/Effect";
3644
+ import * as Effect45 from "effect/Effect";
2530
3645
 
2531
3646
  // src/proxmox/pbs-notification-target-lifecycle.ts
2532
3647
  import { isResolved as isResolved9 } from "alchemy/Diff";
2533
- import * as Effect41 from "effect/Effect";
3648
+ import * as Effect44 from "effect/Effect";
3649
+
3650
+ // src/proxmox/pbs-notification-target-endpoint.ts
3651
+ var ENDPOINTS2 = {
3652
+ sendmail: {
3653
+ create: "pbs:POST /config/notifications/endpoints/sendmail",
3654
+ update: "pbs:PUT /config/notifications/endpoints/sendmail/{name}"
3655
+ },
3656
+ smtp: {
3657
+ create: "pbs:POST /config/notifications/endpoints/smtp",
3658
+ update: "pbs:PUT /config/notifications/endpoints/smtp/{name}"
3659
+ },
3660
+ webhook: {
3661
+ create: "pbs:POST /config/notifications/endpoints/webhook",
3662
+ update: "pbs:PUT /config/notifications/endpoints/webhook/{name}"
3663
+ }
3664
+ };
3665
+ var pbsTargetEndpoint = (props) => ENDPOINTS2[props.type];
2534
3666
 
2535
3667
  // src/proxmox/credential-literals.ts
2536
3668
  var READS_SECRET = /\{\{[^}]*\bsecrets\./;
@@ -2790,12 +3922,12 @@ var targetForm = (props, groups, carry, mode) => {
2790
3922
 
2791
3923
  // src/proxmox/pbs-notification-target-lifecycle.ts
2792
3924
  var path = (props) => `config/notifications/endpoints/${props.type}/${props.name}`;
2793
- var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(Effect41.map((data) => data == null ? undefined : targetAttributes(data, props)), Effect41.orElseSucceed(() => {
3925
+ var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(Effect44.map((data) => data == null ? undefined : targetAttributes(data, props)), Effect44.orElseSucceed(() => {
2794
3926
  return;
2795
3927
  }));
2796
3928
  var refuse2 = (props) => {
2797
3929
  const reasons = refusals(props);
2798
- return reasons.length === 0 ? Effect41.void : Effect41.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
3930
+ return reasons.length === 0 ? Effect44.void : Effect44.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
2799
3931
  };
2800
3932
  var toCarry = (live, props, groups, sealed) => {
2801
3933
  const header = headerState(live, props, groups) === "stale";
@@ -2807,16 +3939,16 @@ var requireValues = (props, groups, carry) => {
2807
3939
  ...carry.header ? groups.header.missing : [],
2808
3940
  ...carry.sealed ? groups.sealed.missing : []
2809
3941
  ];
2810
- return missing.length === 0 ? Effect41.void : Effect41.die(new Error(`${path(props)}: this write must send write-only values, and ${missing.join(", ")} ` + "is unset or empty in the deploying environment. Export it and deploy again."));
3942
+ return missing.length === 0 ? Effect44.void : Effect44.die(new Error(`${path(props)}: this write must send write-only values, and ${missing.join(", ")} ` + "is unset or empty in the deploying environment. Export it and deploy again."));
2811
3943
  };
2812
3944
  var handlers17 = {
2813
- list: () => Effect41.succeed([]),
2814
- read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect41.void).pipe(Effect41.andThen(readLive2(olds)), Effect41.map((live) => live === undefined ? undefined : { ...live, sealed: output?.sealed ?? "" })),
3945
+ list: () => Effect44.succeed([]),
3946
+ read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect44.void).pipe(Effect44.andThen(readLive2(olds)), Effect44.map((live) => live === undefined ? undefined : { ...live, sealed: output?.sealed ?? "" })),
2815
3947
  diff: ({
2816
3948
  news,
2817
3949
  olds,
2818
3950
  output
2819
- }) => Effect41.gen(function* () {
3951
+ }) => Effect44.gen(function* () {
2820
3952
  if (output === undefined || !isResolved9(news))
2821
3953
  return;
2822
3954
  if (olds !== undefined && (olds.type !== news.type || olds.name !== news.name)) {
@@ -2828,7 +3960,7 @@ var handlers17 = {
2828
3960
  return { action: "update" };
2829
3961
  return toCarry(live, news, resolveGroups(news), output.sealed) === undefined ? { action: "noop" } : { action: "update" };
2830
3962
  }),
2831
- reconcile: ({ news, output }) => Effect41.gen(function* () {
3963
+ reconcile: ({ news, output }) => Effect44.gen(function* () {
2832
3964
  yield* refuse2(news);
2833
3965
  const groups = resolveGroups(news);
2834
3966
  const live = yield* readLive2(news);
@@ -2837,20 +3969,24 @@ var handlers17 = {
2837
3969
  const carry = { header: true, sealed: true };
2838
3970
  yield* requireValues(news, groups, carry);
2839
3971
  const collection2 = `config/notifications/endpoints/${news.type}`;
2840
- yield* pve(news.target, "provision", "POST", collection2, targetForm(news, groups, carry, "create"));
3972
+ const form = targetForm(news, groups, carry, "create");
3973
+ yield* guardForm(pbsTargetEndpoint(news).create, form, true);
3974
+ yield* pve(news.target, "provision", "POST", collection2, form);
2841
3975
  sealed = seal(groups.sealed.values);
2842
3976
  } else {
2843
3977
  const carry = toCarry(live, news, groups, sealed);
2844
3978
  if (carry !== undefined) {
2845
3979
  yield* requireValues(news, groups, carry);
2846
- yield* pve(news.target, "provision", "PUT", path(news), targetForm(news, groups, carry, "update"));
3980
+ const form = targetForm(news, groups, carry, "update");
3981
+ yield* guardForm(pbsTargetEndpoint(news).update, form, false);
3982
+ yield* pve(news.target, "provision", "PUT", path(news), form);
2847
3983
  if (carry.sealed)
2848
3984
  sealed = seal(groups.sealed.values);
2849
3985
  }
2850
3986
  }
2851
3987
  const after = yield* readLive2(news);
2852
3988
  if (after === undefined) {
2853
- return yield* Effect41.die(new Error(`${path(news)}: the write returned no error but the target is still absent.`));
3989
+ return yield* Effect44.die(new Error(`${path(news)}: the write returned no error but the target is still absent.`));
2854
3990
  }
2855
3991
  return { ...after, sealed };
2856
3992
  }),
@@ -2859,11 +3995,11 @@ var handlers17 = {
2859
3995
 
2860
3996
  // src/proxmox/pbs-notification-target.ts
2861
3997
  var PbsNotificationTarget = Resource21("Pbs.NotificationTarget");
2862
- var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect42.succeed(PbsNotificationTarget.Provider.of(handlers17)));
3998
+ var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect45.succeed(PbsNotificationTarget.Provider.of(handlers17)));
2863
3999
  // src/proxmox/pbs-prune-job.ts
2864
4000
  import { Resource as Resource22 } from "alchemy";
2865
4001
  import * as Provider22 from "alchemy/Provider";
2866
- import * as Effect43 from "effect/Effect";
4002
+ import * as Effect46 from "effect/Effect";
2867
4003
 
2868
4004
  // src/proxmox/pbs-prune-job-form.ts
2869
4005
  var KEEP_KEYS = [
@@ -2909,7 +4045,7 @@ var shape5 = (props) => ({
2909
4045
  schedule: props.schedule,
2910
4046
  store: props.store
2911
4047
  });
2912
- var createBody2 = (props) => {
4048
+ var createBody4 = (props) => {
2913
4049
  requireKeeps(props);
2914
4050
  return { ...shape5(props), id: props.id };
2915
4051
  };
@@ -2933,16 +4069,17 @@ var handlers18 = pveHandlers({
2933
4069
  store: text(live["store"], props.store)
2934
4070
  }),
2935
4071
  collection: () => "config/prune",
2936
- createForm: createBody2,
4072
+ createForm: createBody4,
4073
+ endpoint: { create: "pbs:POST /config/prune", update: "pbs:PUT /config/prune/{id}" },
2937
4074
  matches: (attributes2, props) => attributes2.schedule === props.schedule && attributes2.store === props.store && same6(props.ns, attributes2.ns) && same6(props["max-depth"], attributes2["max-depth"]) && same6(props.disable, attributes2.disable) && same6(props.comment, attributes2.comment) && keepsMatch(attributes2, props),
2938
4075
  path: (props) => `config/prune/${props.id}`,
2939
4076
  updateForm: updateBody3
2940
4077
  });
2941
- var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect43.succeed(PbsPruneJob.Provider.of(handlers18)));
4078
+ var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect46.succeed(PbsPruneJob.Provider.of(handlers18)));
2942
4079
  // src/proxmox/pbs-sync-job.ts
2943
4080
  import { Resource as Resource23 } from "alchemy";
2944
4081
  import * as Provider23 from "alchemy/Provider";
2945
- import * as Effect44 from "effect/Effect";
4082
+ import * as Effect47 from "effect/Effect";
2946
4083
 
2947
4084
  // src/proxmox/pbs-sync-job-form.ts
2948
4085
  var UNSET4 = -1;
@@ -2984,7 +4121,7 @@ var shape6 = (props) => ({
2984
4121
  ...props["verified-only"] === undefined ? {} : { "verified-only": props["verified-only"] ? "1" : "0" },
2985
4122
  ...props["transfer-last"] === undefined ? {} : { "transfer-last": String(props["transfer-last"]) }
2986
4123
  });
2987
- var createBody3 = (props) => ({
4124
+ var createBody5 = (props) => ({
2988
4125
  ...shape6(props),
2989
4126
  id: props.id,
2990
4127
  ...props["sync-direction"] === undefined ? {} : { "sync-direction": props["sync-direction"] }
@@ -3010,7 +4147,8 @@ var handlers19 = pveHandlers({
3010
4147
  "transfer-last": int(live["transfer-last"], UNSET4)
3011
4148
  }),
3012
4149
  collection: () => "config/sync",
3013
- createForm: createBody3,
4150
+ createForm: createBody5,
4151
+ endpoint: { create: "pbs:POST /config/sync", update: "pbs:PUT /config/sync/{id}" },
3014
4152
  matches: (attributes2, props) => attributes2["remove-vanished"] === (props["remove-vanished"] === true) && attributes2.store === props.store && attributes2["remote-store"] === props["remote-store"] && (props.remote === undefined || attributes2.remote === props.remote) && (props.ns === undefined || attributes2.ns === props.ns) && (props["remote-ns"] === undefined || attributes2["remote-ns"] === props["remote-ns"]) && (props.schedule === undefined || attributes2.schedule === props.schedule) && (props.comment === undefined || attributes2.comment === props.comment) && (props.owner === undefined || attributes2.owner === props.owner) && (props["verified-only"] === undefined || attributes2["verified-only"] === props["verified-only"]) && (props["rate-in"] === undefined || attributes2["rate-in"] === props["rate-in"]) && (props["max-depth"] === undefined || attributes2["max-depth"] === props["max-depth"]) && (props["transfer-last"] === undefined || attributes2["transfer-last"] === props["transfer-last"]),
3015
4153
  path: (props) => `config/sync/${props.id}`,
3016
4154
  updateForm: updateBody4
@@ -3018,11 +4156,11 @@ var handlers19 = pveHandlers({
3018
4156
 
3019
4157
  // src/proxmox/pbs-sync-job.ts
3020
4158
  var PbsSyncJob = Resource23("Pbs.SyncJob");
3021
- var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect44.succeed(PbsSyncJob.Provider.of(handlers19)));
4159
+ var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect47.succeed(PbsSyncJob.Provider.of(handlers19)));
3022
4160
  // src/proxmox/pbs-verify-job.ts
3023
4161
  import { Resource as Resource24 } from "alchemy";
3024
4162
  import * as Provider24 from "alchemy/Provider";
3025
- import * as Effect45 from "effect/Effect";
4163
+ import * as Effect48 from "effect/Effect";
3026
4164
 
3027
4165
  // src/proxmox/pbs-verify-job-form.ts
3028
4166
  var rechecks = (ignoreVerified, outdatedAfter) => {
@@ -3062,15 +4200,16 @@ var handlers20 = pveHandlers({
3062
4200
  },
3063
4201
  collection: () => "config/verify",
3064
4202
  createForm: (props) => ({ ...shape7(props), id: props.id }),
4203
+ endpoint: { create: "pbs:POST /config/verify", update: "pbs:PUT /config/verify/{id}" },
3065
4204
  matches: (attributes2, props) => attributes2.store === props.store && attributes2.schedule === (props.schedule ?? "") && attributes2["ignore-verified"] === (props["ignore-verified"] !== false) && (props["outdated-after"] === undefined || attributes2["outdated-after"] === props["outdated-after"]) && (props["max-depth"] === undefined || attributes2["max-depth"] === props["max-depth"]) && (props.ns === undefined || attributes2.ns === props.ns) && (props.comment === undefined || attributes2.comment === props.comment),
3066
4205
  path: (props) => `config/verify/${props.id}`,
3067
4206
  updateForm: shape7
3068
4207
  });
3069
- var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect45.succeed(PbsVerifyJob.Provider.of(handlers20)));
4208
+ var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect48.succeed(PbsVerifyJob.Provider.of(handlers20)));
3070
4209
  // src/proxmox/pool.ts
3071
4210
  import { Resource as Resource25 } from "alchemy";
3072
4211
  import * as Provider25 from "alchemy/Provider";
3073
- import * as Effect46 from "effect/Effect";
4212
+ import * as Effect49 from "effect/Effect";
3074
4213
  var ProxmoxPool = Resource25("Proxmox.Pool");
3075
4214
  var poolCreateForm = (props) => ({
3076
4215
  comment: props.comment ?? "",
@@ -3090,11 +4229,12 @@ var handlers21 = pveHandlers({
3090
4229
  },
3091
4230
  collection: () => "pools",
3092
4231
  createForm: poolCreateForm,
4232
+ endpoint: { create: "pve:POST /pools", update: "pve:PUT /pools/{poolid}" },
3093
4233
  matches: (attributes2, props) => attributes2.comment === (props.comment ?? ""),
3094
4234
  path: (props) => `pools/${props.poolid}`,
3095
4235
  updateForm: poolUpdateForm
3096
4236
  });
3097
- var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect46.succeed(ProxmoxPool.Provider.of(handlers21)));
4237
+ var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect49.succeed(ProxmoxPool.Provider.of(handlers21)));
3098
4238
  // src/proxmox/provision-baseline.ts
3099
4239
  var PROVISION_PRIVILEGES = Object.freeze([
3100
4240
  "Datastore.Allocate",
@@ -3135,8 +4275,8 @@ var PROVISION_DEFAULTS = Object.freeze({
3135
4275
  });
3136
4276
  var ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
3137
4277
  var USERID = /^[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z][A-Za-z0-9._-]*$/;
3138
- var COMMENT = /^[A-Za-z0-9 ._,()@/+-]*$/;
3139
- var problems2 = (names2) => {
4278
+ var COMMENT = /^[A-Za-z0-9 ._,:()@/+-]*$/;
4279
+ var problems2 = (names2, comments, given) => {
3140
4280
  const found = [];
3141
4281
  if (!ID.test(names2.role))
3142
4282
  found.push(`role \`${names2.role}\` is not a PVE role id`);
@@ -3154,17 +4294,36 @@ var problems2 = (names2) => {
3154
4294
  }
3155
4295
  if (names2.readUser === names2.provisionUser)
3156
4296
  found.push("readUser and provisionUser are one user");
3157
- if (!COMMENT.test(names2.comment))
3158
- found.push("comment holds a character the bootstrap will not quote");
4297
+ const source = (override, field6) => override === undefined ? "comment" : field6;
4298
+ const checked = [
4299
+ [source(given.groupComment, "groupComment"), comments.group],
4300
+ [source(given.provisionComment, "provisionComment"), comments.provision]
4301
+ ];
4302
+ if (names2.readUser !== null) {
4303
+ checked.push([source(given.readComment, "readComment"), comments.read]);
4304
+ }
4305
+ const said = new Set;
4306
+ for (const [field6, comment3] of checked) {
4307
+ if (COMMENT.test(comment3) || said.has(field6))
4308
+ continue;
4309
+ said.add(field6);
4310
+ found.push(`${field6} holds a character the bootstrap will not quote`);
4311
+ }
3159
4312
  return found;
3160
4313
  };
3161
4314
  var provisionBaseline = (names2 = {}) => {
3162
- const given = Object.entries(names2).filter(([, value]) => value !== undefined);
4315
+ const { groupComment, provisionComment, readComment, ...core } = names2;
4316
+ const given = Object.entries(core).filter(([, value]) => value !== undefined);
3163
4317
  const resolved = {
3164
4318
  ...PROVISION_DEFAULTS,
3165
4319
  ...Object.fromEntries(given)
3166
4320
  };
3167
- const found = problems2(resolved);
4321
+ const comments = {
4322
+ group: groupComment ?? resolved.comment,
4323
+ provision: provisionComment ?? resolved.comment,
4324
+ read: readComment ?? resolved.comment
4325
+ };
4326
+ const found = problems2(resolved, comments, names2);
3168
4327
  if (found.length > 0)
3169
4328
  throw new Error(`provision baseline: ${found.join("; ")}`);
3170
4329
  const lanes = [
@@ -3174,10 +4333,10 @@ var provisionBaseline = (names2 = {}) => {
3174
4333
  lanes.push(["read", resolved.readUser, resolved.readRole]);
3175
4334
  return {
3176
4335
  grants: lanes.map(([lane, userid, roleid]) => ({ lane, roleid, userid })),
3177
- group: { comment: resolved.comment, groupid: resolved.mintGroup },
4336
+ group: { comment: comments.group, groupid: resolved.mintGroup },
3178
4337
  role: { privs: PROVISION_PRIVILEGES, roleid: resolved.role },
3179
4338
  users: lanes.map(([lane, userid]) => ({
3180
- comment: resolved.comment,
4339
+ comment: comments[lane],
3181
4340
  groups: [resolved.mintGroup],
3182
4341
  lane,
3183
4342
  userid
@@ -3268,12 +4427,12 @@ echo 'provision baseline: done. Next: point the OpenBao proxmox mount at these u
3268
4427
  // src/proxmox/provision-declare.ts
3269
4428
  import { adopt } from "alchemy/AdoptPolicy";
3270
4429
  import * as RemovalPolicy from "alchemy/RemovalPolicy";
3271
- import * as Effect49 from "effect/Effect";
4430
+ import * as Effect52 from "effect/Effect";
3272
4431
 
3273
4432
  // src/proxmox/role.ts
3274
4433
  import { Resource as Resource26 } from "alchemy";
3275
4434
  import * as Provider26 from "alchemy/Provider";
3276
- import * as Effect47 from "effect/Effect";
4435
+ import * as Effect50 from "effect/Effect";
3277
4436
  var ProxmoxRole = Resource26("Proxmox.Role");
3278
4437
  var canonical2 = (privs) => [...new Set(privs.map((priv) => priv.trim()).filter((priv) => priv.length > 0))].sort();
3279
4438
  var livePrivs = (live) => {
@@ -3286,16 +4445,17 @@ var handlers22 = pveHandlers({
3286
4445
  attributes: (live, props) => ({ privs: livePrivs(live), roleid: props.roleid }),
3287
4446
  collection: () => "access/roles",
3288
4447
  createForm: (props) => ({ privs: canonical2(props.privs).join(","), roleid: props.roleid }),
4448
+ endpoint: { create: "pve:POST /access/roles", update: "pve:PUT /access/roles/{roleid}" },
3289
4449
  matches: (attributes2, props) => canonical2(attributes2.privs).join(",") === canonical2(props.privs).join(","),
3290
4450
  path: (props) => `access/roles/${props.roleid}`,
3291
4451
  updateForm: (props) => ({ privs: canonical2(props.privs).join(",") })
3292
4452
  });
3293
- var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect47.succeed(ProxmoxRole.Provider.of(handlers22)));
4453
+ var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect50.succeed(ProxmoxRole.Provider.of(handlers22)));
3294
4454
 
3295
4455
  // src/proxmox/user.ts
3296
4456
  import { Resource as Resource27 } from "alchemy";
3297
4457
  import * as Provider27 from "alchemy/Provider";
3298
- import * as Effect48 from "effect/Effect";
4458
+ import * as Effect51 from "effect/Effect";
3299
4459
  var ProxmoxUser = Resource27("Proxmox.User");
3300
4460
  var str2 = (value) => typeof value === "string" ? value : "";
3301
4461
  var int2 = (value) => {
@@ -3331,15 +4491,16 @@ var handlers23 = pveHandlers({
3331
4491
  }),
3332
4492
  collection: () => "access/users",
3333
4493
  createForm: (props) => ({ ...shape8(props), userid: props.userid }),
4494
+ endpoint: { create: "pve:POST /access/users", update: "pve:PUT /access/users/{userid}" },
3334
4495
  matches: (attributes2, props) => attributes2.comment === (props.comment ?? "") && attributes2.email === (props.email ?? "") && attributes2.enable === (props.enable !== false) && attributes2.expire === (props.expire ?? 0) && attributes2.firstname === (props.firstname ?? "") && attributes2.lastname === (props.lastname ?? "") && attributes2.groups.join(",") === groupSet(props.groups).join(","),
3335
4496
  path: (props) => `access/users/${props.userid}`,
3336
4497
  updateForm: shape8
3337
4498
  });
3338
- var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect48.succeed(ProxmoxUser.Provider.of(handlers23)));
4499
+ var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect51.succeed(ProxmoxUser.Provider.of(handlers23)));
3339
4500
 
3340
4501
  // src/proxmox/provision-declare.ts
3341
- var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect49.gen(function* () {
3342
- const baseline = yield* Effect49.try({
4502
+ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect52.gen(function* () {
4503
+ const baseline = yield* Effect52.try({
3343
4504
  catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
3344
4505
  try: () => provisionBaseline(names2)
3345
4506
  });
@@ -3353,13 +4514,13 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
3353
4514
  target
3354
4515
  }));
3355
4516
  const group = yield* owned(ProxmoxGroup(`${id}-mint-group`, { ...baseline.group, target }));
3356
- const users = yield* Effect49.all(baseline.users.map((user) => owned(ProxmoxUser(`${id}-${user.lane}-user`, {
4517
+ const users = yield* Effect52.all(baseline.users.map((user) => owned(ProxmoxUser(`${id}-${user.lane}-user`, {
3357
4518
  comment: user.comment,
3358
4519
  groups: [...user.groups],
3359
4520
  target,
3360
4521
  userid: user.userid
3361
4522
  }))));
3362
- const grants = yield* Effect49.all(baseline.grants.map((grant) => owned(ProxmoxAcl(`${id}-${grant.lane}-grant`, {
4523
+ const grants = yield* Effect52.all(baseline.grants.map((grant) => owned(ProxmoxAcl(`${id}-${grant.lane}-grant`, {
3363
4524
  path: "/",
3364
4525
  propagate: true,
3365
4526
  roleid: grant.roleid,
@@ -3372,8 +4533,9 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
3372
4533
  // src/proxmox/qemu.ts
3373
4534
  import { Resource as Resource28 } from "alchemy";
3374
4535
  import * as Provider28 from "alchemy/Provider";
3375
- import * as Effect50 from "effect/Effect";
4536
+ import * as Effect53 from "effect/Effect";
3376
4537
  var ProxmoxVm = Resource28("Proxmox.Vm");
4538
+ var createForm5 = (props) => ({ ...shape9(props), vmid: String(props.vmid) });
3377
4539
  var shape9 = (props) => ({
3378
4540
  cores: String(props.cores ?? 1),
3379
4541
  memory: String(props.memory ?? 512),
@@ -3393,16 +4555,20 @@ var handlers24 = pveHandlers({
3393
4555
  vmid: props.vmid
3394
4556
  }),
3395
4557
  collection: (props) => `nodes/${props.node}/qemu`,
3396
- createForm: (props) => ({ ...shape9(props), vmid: String(props.vmid) }),
4558
+ createForm: createForm5,
4559
+ endpoint: {
4560
+ create: "pve:POST /nodes/{node}/qemu",
4561
+ update: "pve:PUT /nodes/{node}/qemu/{vmid}/config"
4562
+ },
3397
4563
  matches: (attributes2, props) => attributes2.name === (props.name ?? `vm${String(props.vmid)}`) && attributes2.memory === (props.memory ?? 512) && attributes2.cores === (props.cores ?? 1) && attributes2.sockets === (props.sockets ?? 1) && attributes2.onboot === (props.onboot === true),
3398
4564
  path: (props) => `nodes/${props.node}/qemu/${String(props.vmid)}/config`,
3399
4565
  updateForm: shape9
3400
4566
  });
3401
- var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect50.succeed(ProxmoxVm.Provider.of(handlers24)));
4567
+ var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect53.succeed(ProxmoxVm.Provider.of(handlers24)));
3402
4568
  // src/proxmox/replication-job.ts
3403
4569
  import { Resource as Resource29 } from "alchemy";
3404
4570
  import * as Provider29 from "alchemy/Provider";
3405
- import * as Effect51 from "effect/Effect";
4571
+ import * as Effect54 from "effect/Effect";
3406
4572
 
3407
4573
  // src/proxmox/replication-job-form.ts
3408
4574
  var DEFAULT_SCHEDULE = "*/15";
@@ -3413,7 +4579,7 @@ var shape10 = (props) => ({
3413
4579
  schedule: props.schedule ?? DEFAULT_SCHEDULE,
3414
4580
  ...props.rate === undefined ? {} : { rate: String(props.rate) }
3415
4581
  });
3416
- var createBody4 = (props) => ({
4582
+ var createBody6 = (props) => ({
3417
4583
  ...shape10(props),
3418
4584
  id: jobId(props),
3419
4585
  target: props.targetNode,
@@ -3447,20 +4613,24 @@ var handlers25 = pveHandlers({
3447
4613
  type: text(live["type"], "local")
3448
4614
  }),
3449
4615
  collection: () => "cluster/replication",
3450
- createForm: createBody4,
4616
+ createForm: createBody6,
4617
+ endpoint: {
4618
+ create: "pve:POST /cluster/replication",
4619
+ update: "pve:PUT /cluster/replication/{id}"
4620
+ },
3451
4621
  matches: (attributes2, props) => attributes2.remove_job === "" && attributes2.schedule === (props.schedule ?? DEFAULT_SCHEDULE) && attributes2.disable === (props.disable === true) && attributes2.comment === (props.comment ?? "") && (props.rate === undefined || attributes2.rate === props.rate),
3452
4622
  path: (props) => `cluster/replication/${jobId(props)}`,
3453
4623
  updateForm: updateBody5
3454
4624
  });
3455
- var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob, Effect51.succeed(ProxmoxReplicationJob.Provider.of(handlers25)));
4625
+ var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob, Effect54.succeed(ProxmoxReplicationJob.Provider.of(handlers25)));
3456
4626
  // src/proxmox/sdn-apply.ts
3457
4627
  import { Resource as Resource30 } from "alchemy";
3458
4628
  import { isResolved as isResolved10 } from "alchemy/Diff";
3459
4629
  import * as Provider30 from "alchemy/Provider";
3460
- import * as Effect53 from "effect/Effect";
4630
+ import * as Effect56 from "effect/Effect";
3461
4631
 
3462
4632
  // src/proxmox/sdn-apply-read.ts
3463
- import * as Effect52 from "effect/Effect";
4633
+ import * as Effect55 from "effect/Effect";
3464
4634
  var MARKED = [
3465
4635
  "cluster/sdn/zones",
3466
4636
  "cluster/sdn/vnets",
@@ -3469,7 +4639,7 @@ var MARKED = [
3469
4639
  "cluster/sdn/route-maps"
3470
4640
  ];
3471
4641
  var subsystemAbsent = (error) => error instanceof PveError && error.status === 501;
3472
- var markedPending = (target) => Effect52.all(MARKED.map((collection2) => pve(target, "read", "GET", `${collection2}?pending=1`).pipe(Effect52.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect52.catchIf(subsystemAbsent, () => Effect52.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect52.map((counts) => counts.reduce((total, count2) => total + count2, 0)));
4642
+ var markedPending = (target) => Effect55.all(MARKED.map((collection2) => pve(target, "read", "GET", `${collection2}?pending=1`).pipe(Effect55.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect55.catchIf(subsystemAbsent, () => Effect55.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect55.map((counts) => counts.reduce((total, count2) => total + count2, 0)));
3473
4643
  var fabricStaged = (staged, running) => {
3474
4644
  if (staged === undefined && running === undefined)
3475
4645
  return 0;
@@ -3477,9 +4647,9 @@ var fabricStaged = (staged, running) => {
3477
4647
  return "inconsistent";
3478
4648
  return staged === running ? 0 : 1;
3479
4649
  };
3480
- var fabricPending = (target) => Effect52.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect52.map(canonical3), Effect52.catchIf(subsystemAbsent, () => Effect52.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect52.flatMap(([staged, running]) => {
4650
+ var fabricPending = (target) => Effect55.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect55.map(canonical3), Effect55.catchIf(subsystemAbsent, () => Effect55.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect55.flatMap(([staged, running]) => {
3481
4651
  const verdict = fabricStaged(staged, running);
3482
- return verdict === "inconsistent" ? Effect52.die(new Error("cluster/sdn/fabrics/all answered 501 for one of ?pending=1 and ?running=1 and not " + "the other. Refusing to read that as a staged fabric change.")) : Effect52.succeed(verdict);
4652
+ return verdict === "inconsistent" ? Effect55.die(new Error("cluster/sdn/fabrics/all answered 501 for one of ?pending=1 and ?running=1 and not " + "the other. Refusing to read that as a staged fabric change.")) : Effect55.succeed(verdict);
3483
4653
  }));
3484
4654
  var canonical3 = (value) => JSON.stringify(sortDeep(value));
3485
4655
  var sortDeep = (value) => {
@@ -3492,39 +4662,40 @@ var sortDeep = (value) => {
3492
4662
  }
3493
4663
  return value;
3494
4664
  };
3495
- var sdnPendingCount = (target) => Effect52.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect52.map(([marked, fabric]) => marked + fabric));
4665
+ var sdnPendingCount = (target) => Effect55.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect55.map(([marked, fabric]) => marked + fabric));
3496
4666
 
3497
4667
  // src/proxmox/sdn-apply.ts
3498
4668
  var ProxmoxSdnApply = Resource30("Proxmox.SdnApply");
3499
- var read3 = (props) => sdnPendingCount(props.target).pipe(Effect53.map((pending) => ({ pending })));
3500
- var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply, Effect53.succeed(ProxmoxSdnApply.Provider.of({
3501
- list: () => Effect53.succeed([]),
3502
- read: Effect53.fn(function* ({ olds }) {
4669
+ var read3 = (props) => sdnPendingCount(props.target).pipe(Effect56.map((pending) => ({ pending })));
4670
+ var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply, Effect56.succeed(ProxmoxSdnApply.Provider.of({
4671
+ list: () => Effect56.succeed([]),
4672
+ read: Effect56.fn(function* ({ olds }) {
3503
4673
  return yield* read3(olds);
3504
4674
  }),
3505
- diff: Effect53.fn(function* ({ news }) {
4675
+ diff: Effect56.fn(function* ({ news }) {
3506
4676
  if (!isResolved10(news))
3507
4677
  return;
3508
4678
  const { pending } = yield* read3(news);
3509
4679
  return pending === 0 ? { action: "noop" } : { action: "update" };
3510
4680
  }),
3511
- reconcile: Effect53.fn(function* ({ news }) {
4681
+ reconcile: Effect56.fn(function* ({ news }) {
3512
4682
  const staged = yield* read3(news);
3513
4683
  if (staged.pending === 0)
3514
4684
  return staged;
4685
+ yield* guardSdnApply;
3515
4686
  yield* pve(news.target, "provision", "PUT", "cluster/sdn");
3516
4687
  const after = yield* read3(news);
3517
4688
  if (after.pending !== 0) {
3518
- return yield* Effect53.die(new Error(`PUT /cluster/sdn returned no error but ${String(after.pending)} SDN object(s) ` + "are still staged. The running config does not match the declared one -- check " + "`pvesh get /cluster/sdn/zones --pending 1` for the objects PVE refused."));
4689
+ return yield* Effect56.die(new Error(`PUT /cluster/sdn returned no error but ${String(after.pending)} SDN object(s) ` + "are still staged. The running config does not match the declared one -- check " + "`pvesh get /cluster/sdn/zones --pending 1` for the objects PVE refused."));
3519
4690
  }
3520
4691
  return after;
3521
4692
  }),
3522
- delete: () => Effect53.void
4693
+ delete: () => Effect56.void
3523
4694
  })));
3524
4695
  // src/proxmox/sdn-subnet.ts
3525
4696
  import { Resource as Resource31 } from "alchemy";
3526
4697
  import * as Provider31 from "alchemy/Provider";
3527
- import * as Effect54 from "effect/Effect";
4698
+ import * as Effect57 from "effect/Effect";
3528
4699
 
3529
4700
  // src/proxmox/sdn-subnet-form.ts
3530
4701
  var subnetId = (props) => `${props.zone}-${props.cidr.replace("/", "-")}`;
@@ -3543,7 +4714,7 @@ var body5 = (props) => ({
3543
4714
  vnet: props.vnet,
3544
4715
  ...Object.fromEntries(Object.entries(optional3(props)).filter((entry) => entry[1] !== undefined))
3545
4716
  });
3546
- var createForm5 = (props) => ({
4717
+ var createForm6 = (props) => ({
3547
4718
  ...body5(props),
3548
4719
  subnet: props.cidr,
3549
4720
  type: "subnet"
@@ -3575,16 +4746,20 @@ var handlers26 = pveHandlers({
3575
4746
  };
3576
4747
  },
3577
4748
  collection: (props) => `cluster/sdn/vnets/${props.vnet}/subnets`,
3578
- createForm: createForm5,
4749
+ createForm: createForm6,
4750
+ endpoint: {
4751
+ create: "pve:POST /cluster/sdn/vnets/{vnet}/subnets",
4752
+ update: "pve:PUT /cluster/sdn/vnets/{vnet}/subnets/{subnet}"
4753
+ },
3579
4754
  matches: (attributes2, props) => attributes2.gateway === (props.gateway ?? "") && attributes2.snat === (props.snat === true) && attributes2.dnszoneprefix === (props.dnszoneprefix ?? "") && attributes2.dhcpDnsServer === (props.dhcpDnsServer ?? "") && attributes2.dhcpRange === declaredRanges(props.dhcpRange),
3580
4755
  path: (props) => `cluster/sdn/vnets/${props.vnet}/subnets/${subnetId(props)}`,
3581
4756
  updateForm: updateForm2
3582
4757
  });
3583
- var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet, Effect54.succeed(ProxmoxSdnSubnet.Provider.of(handlers26)));
4758
+ var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet, Effect57.succeed(ProxmoxSdnSubnet.Provider.of(handlers26)));
3584
4759
  // src/proxmox/sdn-vnet.ts
3585
4760
  import { Resource as Resource32 } from "alchemy";
3586
4761
  import * as Provider32 from "alchemy/Provider";
3587
- import * as Effect55 from "effect/Effect";
4762
+ import * as Effect58 from "effect/Effect";
3588
4763
  var ProxmoxSdnVnet = Resource32("Proxmox.SdnVnet");
3589
4764
  var tagOf = (value) => typeof value === "number" ? value : undefined;
3590
4765
  var shape11 = (props) => {
@@ -3617,15 +4792,16 @@ var handlers27 = pveHandlers({
3617
4792
  }),
3618
4793
  collection: () => "cluster/sdn/vnets",
3619
4794
  createForm: (props) => ({ ...shape11(props), vnet: props.vnet }),
4795
+ endpoint: { create: "pve:POST /cluster/sdn/vnets", update: "pve:PUT /cluster/sdn/vnets/{vnet}" },
3620
4796
  matches: (attributes2, props) => attributes2.zone === props.zone && attributes2.alias === (props.alias ?? "") && attributes2.tag === props.tag && attributes2.vlanaware === (props.vlanaware === true) && attributes2.isolatePorts === (props.isolatePorts === true),
3621
4797
  path: (props) => `cluster/sdn/vnets/${props.vnet}`,
3622
4798
  updateForm: updateForm3
3623
4799
  });
3624
- var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet, Effect55.succeed(ProxmoxSdnVnet.Provider.of(handlers27)));
4800
+ var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet, Effect58.succeed(ProxmoxSdnVnet.Provider.of(handlers27)));
3625
4801
  // src/proxmox/sdn-zone.ts
3626
4802
  import { Resource as Resource33 } from "alchemy";
3627
4803
  import * as Provider33 from "alchemy/Provider";
3628
- import * as Effect56 from "effect/Effect";
4804
+ import * as Effect59 from "effect/Effect";
3629
4805
  var ProxmoxSdnZone = Resource33("Proxmox.SdnZone");
3630
4806
  var sameIpam = (live, declared2) => (live === "" ? "pve" : live) === (declared2 === undefined || declared2 === "" ? "pve" : declared2);
3631
4807
  var body6 = (props) => ({
@@ -3669,6 +4845,7 @@ var handlers28 = pveHandlers({
3669
4845
  },
3670
4846
  collection: () => "cluster/sdn/zones",
3671
4847
  createForm: (props) => ({ ...body6(props), type: props.type, zone: props.zone }),
4848
+ endpoint: { create: "pve:POST /cluster/sdn/zones", update: "pve:PUT /cluster/sdn/zones/{zone}" },
3672
4849
  matches: (attributes2, props) => attributes2.mtu === (props.mtu ?? 0) && attributes2.nodes === csv(props.nodes) && sameIpam(attributes2.ipam, props.ipam) && attributes2.dns === (props.dns ?? "") && attributes2.dnszone === (props.dnszone ?? "") && attributes2.peers === csv(props.peers) && attributes2["vrf-vxlan"] === (props["vrf-vxlan"] ?? 0) && attributes2.tag === (props.tag ?? 0) && attributes2.bridge === (props.bridge ?? ""),
3673
4850
  path: (props) => `cluster/sdn/zones/${props.zone}`,
3674
4851
  updateForm: (props) => {
@@ -3677,11 +4854,11 @@ var handlers28 = pveHandlers({
3677
4854
  return withClears(fields, clear);
3678
4855
  }
3679
4856
  });
3680
- var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone, Effect56.succeed(ProxmoxSdnZone.Provider.of(handlers28)));
4857
+ var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone, Effect59.succeed(ProxmoxSdnZone.Provider.of(handlers28)));
3681
4858
  // src/proxmox/storage.ts
3682
4859
  import { Resource as Resource34 } from "alchemy";
3683
4860
  import * as Provider34 from "alchemy/Provider";
3684
- import * as Effect57 from "effect/Effect";
4861
+ import * as Effect60 from "effect/Effect";
3685
4862
  var ProxmoxStorage = Resource34("Proxmox.Storage", {
3686
4863
  defaultRemovalPolicy: "retain"
3687
4864
  });
@@ -3722,19 +4899,21 @@ var handlers29 = pveHandlers({
3722
4899
  storage: props.storage,
3723
4900
  type: props.type
3724
4901
  }),
4902
+ endpoint: { create: "pve:POST /storage", update: "pve:PUT /storage/{storage}" },
3725
4903
  matches: (attributes2, props) => sameList2(props.content, attributes2.content) && sameList2(props.nodes, attributes2.nodes) && sameList2(props["prune-backups"], attributes2["prune-backups"]) && same7(props.disable, attributes2.disable) && same7(props.shared, attributes2.shared) && same7(props.preallocation, attributes2.preallocation) && same7(props.comment, attributes2.comment) && same7(props.maxfiles, attributes2.maxfiles),
3726
4904
  path: (props) => `storage/${props.storage}`,
3727
4905
  updateForm: mutable2
3728
4906
  });
3729
- var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect57.succeed(ProxmoxStorage.Provider.of(handlers29)));
4907
+ var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect60.succeed(ProxmoxStorage.Provider.of(handlers29)));
3730
4908
  // src/proxmox/zfs-pool.ts
3731
4909
  import { Resource as Resource35 } from "alchemy";
3732
4910
  import * as Provider35 from "alchemy/Provider";
3733
- import * as Effect59 from "effect/Effect";
4911
+ import * as Effect62 from "effect/Effect";
3734
4912
 
3735
4913
  // src/proxmox/zfs-pool-write.ts
3736
- import * as Effect58 from "effect/Effect";
3737
- var createForm6 = (props) => ({
4914
+ import * as Effect61 from "effect/Effect";
4915
+ var ZFS_POOL_ENDPOINT = { create: "pve:POST /nodes/{node}/disks/zfs" };
4916
+ var createForm7 = (props) => ({
3738
4917
  devices: props.devices.join(","),
3739
4918
  name: props.name,
3740
4919
  raidlevel: props.raidlevel,
@@ -3743,21 +4922,21 @@ var createForm6 = (props) => ({
3743
4922
  ...props["draid-config"] === undefined ? {} : { "draid-config": props["draid-config"] }
3744
4923
  });
3745
4924
  var SETTLE_ATTEMPTS = 30;
3746
- var createPool = (props, collection2, path2, read4) => Effect58.gen(function* () {
4925
+ var createPool = (props, collection2, path2, read4) => Effect61.gen(function* () {
3747
4926
  const existing = yield* read4(props);
3748
4927
  if (existing !== undefined)
3749
4928
  return existing;
3750
- const upid = yield* pve(props.target, "provision", "POST", collection2, createForm6(props));
3751
- const settle4 = (attempts) => Effect58.gen(function* () {
4929
+ const upid = yield* pve(props.target, "provision", "POST", collection2, createForm7(props));
4930
+ const settle4 = (attempts) => Effect61.gen(function* () {
3752
4931
  const live = yield* read4(props);
3753
4932
  if (live !== undefined || attempts <= 0)
3754
4933
  return live;
3755
- yield* Effect58.sleep("2 seconds");
4934
+ yield* Effect61.sleep("2 seconds");
3756
4935
  return yield* settle4(attempts - 1);
3757
4936
  });
3758
4937
  const after = yield* settle4(SETTLE_ATTEMPTS);
3759
4938
  if (after === undefined) {
3760
- return yield* Effect58.die(new Error(`${path2}: POST returned ${text(upid, "(no UPID)")} but the pool has not appeared. That ` + "POST only forks a `zfscreate` worker, so the task holds the real error -- read it " + `with \`pvesh get /nodes/${props.node}/tasks/<upid>/log\`. NOTHING WAS RETRIED AND ` + "NOTHING WAS CLEANED UP: if the worker reached `zpool create`, the declared devices " + "have already been written to."));
4939
+ return yield* Effect61.die(new Error(`${path2}: POST returned ${text(upid, "(no UPID)")} but the pool has not appeared. That ` + "POST only forks a `zfscreate` worker, so the task holds the real error -- read it " + `with \`pvesh get /nodes/${props.node}/tasks/<upid>/log\`. NOTHING WAS RETRIED AND ` + "NOTHING WAS CLEANED UP: if the worker reached `zpool create`, the declared devices " + "have already been written to."));
3761
4940
  }
3762
4941
  return after;
3763
4942
  });
@@ -3785,19 +4964,20 @@ var spec2 = {
3785
4964
  };
3786
4965
  },
3787
4966
  collection: (props) => `nodes/${props.node}/disks/zfs`,
3788
- createForm: createForm6,
4967
+ createForm: createForm7,
4968
+ endpoint: ZFS_POOL_ENDPOINT,
3789
4969
  matches: () => true,
3790
4970
  path: (props) => `nodes/${props.node}/disks/zfs/${props.name}`
3791
4971
  };
3792
4972
  var ops5 = pveOperations(spec2);
3793
4973
  var handlers30 = {
3794
4974
  ...pveHandlers(spec2),
3795
- delete: Effect59.fn(function* ({ olds }) {
4975
+ delete: Effect62.fn(function* ({ olds }) {
3796
4976
  yield* destroyPool(olds, spec2.path(olds));
3797
4977
  }),
3798
4978
  reconcile: ({ news }) => createPool(news, spec2.collection(news), spec2.path(news), ops5.read)
3799
4979
  };
3800
- var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect59.succeed(ProxmoxZfsPool.Provider.of(handlers30)));
4980
+ var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect62.succeed(ProxmoxZfsPool.Provider.of(handlers30)));
3801
4981
  export {
3802
4982
  PROVISION_DEFAULTS,
3803
4983
  PROVISION_PRIVILEGES,
@@ -3861,10 +5041,13 @@ export {
3861
5041
  ProxmoxVmProvider,
3862
5042
  ProxmoxZfsPoolProvider,
3863
5043
  alertmanagerAlertBody,
5044
+ constraintsFor,
3864
5045
  declareProvisionBaseline,
5046
+ formViolations,
3865
5047
  provisionBaseline,
3866
- provisionBootstrap
5048
+ provisionBootstrap,
5049
+ violations
3867
5050
  };
3868
5051
 
3869
- //# debugId=98691C143D2F953764756E2164756E21
5052
+ //# debugId=35B6C615E87D256B64756E2164756E21
3870
5053
  //# sourceMappingURL=index.js.map