@homeflare/alchemy 0.15.0 → 0.19.1

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 (516) 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 +1575 -0
  13. package/dist/linux/index.js.map +38 -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 +40 -0
  39. package/dist/linux/unit-lifecycle.d.ts.map +1 -0
  40. package/dist/linux/unit-preflight.d.ts +41 -0
  41. package/dist/linux/unit-preflight.d.ts.map +1 -0
  42. package/dist/linux/unit-settle.d.ts +31 -0
  43. package/dist/linux/unit-settle.d.ts.map +1 -0
  44. package/dist/linux/unit.d.ts +35 -0
  45. package/dist/linux/unit.d.ts.map +1 -0
  46. package/dist/netbox/client.d.ts +52 -0
  47. package/dist/netbox/client.d.ts.map +1 -0
  48. package/dist/netbox/constraint-guard.d.ts +26 -0
  49. package/dist/netbox/constraint-guard.d.ts.map +1 -0
  50. package/dist/netbox/constraints.d.ts +76 -0
  51. package/dist/netbox/constraints.d.ts.map +1 -0
  52. package/dist/netbox/generated/constraints/index.d.ts +19 -0
  53. package/dist/netbox/generated/constraints/index.d.ts.map +1 -0
  54. package/dist/netbox/generated/constraints/netbox-ipam.d.ts +21 -0
  55. package/dist/netbox/generated/constraints/netbox-ipam.d.ts.map +1 -0
  56. package/dist/netbox/index.d.ts +17 -0
  57. package/dist/netbox/index.d.ts.map +1 -0
  58. package/dist/netbox/index.js +331 -0
  59. package/dist/netbox/index.js.map +18 -0
  60. package/dist/netbox/prefix-form.d.ts +54 -0
  61. package/dist/netbox/prefix-form.d.ts.map +1 -0
  62. package/dist/netbox/prefix.d.ts +80 -0
  63. package/dist/netbox/prefix.d.ts.map +1 -0
  64. package/dist/netbox/resource.d.ts +94 -0
  65. package/dist/netbox/resource.d.ts.map +1 -0
  66. package/dist/netbox/values.d.ts +24 -0
  67. package/dist/netbox/values.d.ts.map +1 -0
  68. package/dist/proxmox/api-token-form.d.ts.map +1 -1
  69. package/dist/proxmox/apply-endpoints.d.ts +30 -0
  70. package/dist/proxmox/apply-endpoints.d.ts.map +1 -0
  71. package/dist/proxmox/ceph-daemon-form.d.ts +29 -1
  72. package/dist/proxmox/ceph-daemon-form.d.ts.map +1 -1
  73. package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
  74. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  75. package/dist/proxmox/ceph-fs.d.ts.map +1 -1
  76. package/dist/proxmox/ceph-osd-write.d.ts +19 -0
  77. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  78. package/dist/proxmox/ceph-pool.d.ts.map +1 -1
  79. package/dist/proxmox/constraints.d.ts +28 -5
  80. package/dist/proxmox/constraints.d.ts.map +1 -1
  81. package/dist/proxmox/generated/constraints/index.d.ts +1 -1
  82. package/dist/proxmox/generated/constraints/index.d.ts.map +1 -1
  83. package/dist/proxmox/generated/constraints/pbs-config.d.ts +6 -1
  84. package/dist/proxmox/generated/constraints/pbs-config.d.ts.map +1 -1
  85. package/dist/proxmox/generated/constraints/pve-access.d.ts +6 -1
  86. package/dist/proxmox/generated/constraints/pve-access.d.ts.map +1 -1
  87. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +23 -0
  88. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts.map +1 -0
  89. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +23 -0
  90. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts.map +1 -0
  91. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +23 -0
  92. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts.map +1 -0
  93. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +23 -0
  94. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts.map +1 -0
  95. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +23 -0
  96. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts.map +1 -0
  97. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +23 -0
  98. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts.map +1 -0
  99. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +23 -0
  100. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts.map +1 -0
  101. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +23 -0
  102. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts.map +1 -0
  103. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +23 -0
  104. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts.map +1 -0
  105. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +23 -0
  106. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts.map +1 -0
  107. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +23 -0
  108. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts.map +1 -0
  109. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +23 -0
  110. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts.map +1 -0
  111. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +23 -0
  112. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts.map +1 -0
  113. package/dist/proxmox/generated/constraints/pve-pools.d.ts +6 -1
  114. package/dist/proxmox/generated/constraints/pve-pools.d.ts.map +1 -1
  115. package/dist/proxmox/generated/constraints/pve-storage.d.ts +6 -1
  116. package/dist/proxmox/generated/constraints/pve-storage.d.ts.map +1 -1
  117. package/dist/proxmox/generated/pbs/access-users.d.ts +137 -0
  118. package/dist/proxmox/generated/pbs/access-users.d.ts.map +1 -0
  119. package/dist/proxmox/generated/pbs/access.d.ts +171 -0
  120. package/dist/proxmox/generated/pbs/access.d.ts.map +1 -0
  121. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts +252 -0
  122. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts.map +1 -0
  123. package/dist/proxmox/generated/pbs/admin-metrics.d.ts +147 -0
  124. package/dist/proxmox/generated/pbs/admin-metrics.d.ts.map +1 -0
  125. package/dist/proxmox/generated/pbs/admin.d.ts +217 -0
  126. package/dist/proxmox/generated/pbs/admin.d.ts.map +1 -0
  127. package/dist/proxmox/generated/pbs/backup.d.ts +114 -0
  128. package/dist/proxmox/generated/pbs/backup.d.ts.map +1 -0
  129. package/dist/proxmox/generated/pbs/config-access-pam.d.ts +218 -0
  130. package/dist/proxmox/generated/pbs/config-access-pam.d.ts.map +1 -0
  131. package/dist/proxmox/generated/pbs/config-access.d.ts +203 -0
  132. package/dist/proxmox/generated/pbs/config-access.d.ts.map +1 -0
  133. package/dist/proxmox/generated/pbs/config-datastore.d.ts +195 -0
  134. package/dist/proxmox/generated/pbs/config-datastore.d.ts.map +1 -0
  135. package/dist/proxmox/generated/pbs/config-media-pool.d.ts +207 -0
  136. package/dist/proxmox/generated/pbs/config-media-pool.d.ts.map +1 -0
  137. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts +159 -0
  138. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts.map +1 -0
  139. package/dist/proxmox/generated/pbs/config-notifications.d.ts +199 -0
  140. package/dist/proxmox/generated/pbs/config-notifications.d.ts.map +1 -0
  141. package/dist/proxmox/generated/pbs/config-remote.d.ts +175 -0
  142. package/dist/proxmox/generated/pbs/config-remote.d.ts.map +1 -0
  143. package/dist/proxmox/generated/pbs/config-sync.d.ts +145 -0
  144. package/dist/proxmox/generated/pbs/config-sync.d.ts.map +1 -0
  145. package/dist/proxmox/generated/pbs/config-tape.d.ts +200 -0
  146. package/dist/proxmox/generated/pbs/config-tape.d.ts.map +1 -0
  147. package/dist/proxmox/generated/pbs/config-verify.d.ts +77 -0
  148. package/dist/proxmox/generated/pbs/config-verify.d.ts.map +1 -0
  149. package/dist/proxmox/generated/pbs/config.d.ts +119 -0
  150. package/dist/proxmox/generated/pbs/config.d.ts.map +1 -0
  151. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts +178 -0
  152. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts.map +1 -0
  153. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts +205 -0
  154. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts.map +1 -0
  155. package/dist/proxmox/generated/pbs/nodes-node.d.ts +166 -0
  156. package/dist/proxmox/generated/pbs/nodes-node.d.ts.map +1 -0
  157. package/dist/proxmox/generated/pbs/nodes.d.ts +171 -0
  158. package/dist/proxmox/generated/pbs/nodes.d.ts.map +1 -0
  159. package/dist/proxmox/generated/pbs/ping.d.ts +18 -0
  160. package/dist/proxmox/generated/pbs/ping.d.ts.map +1 -0
  161. package/dist/proxmox/generated/pbs/pull.d.ts +37 -0
  162. package/dist/proxmox/generated/pbs/pull.d.ts.map +1 -0
  163. package/dist/proxmox/generated/pbs/push.d.ts +36 -0
  164. package/dist/proxmox/generated/pbs/push.d.ts.map +1 -0
  165. package/dist/proxmox/generated/pbs/reader.d.ts +41 -0
  166. package/dist/proxmox/generated/pbs/reader.d.ts.map +1 -0
  167. package/dist/proxmox/generated/pbs/root.d.ts +16 -0
  168. package/dist/proxmox/generated/pbs/root.d.ts.map +1 -0
  169. package/dist/proxmox/generated/pbs/status.d.ts +54 -0
  170. package/dist/proxmox/generated/pbs/status.d.ts.map +1 -0
  171. package/dist/proxmox/generated/pbs/tape-drive.d.ts +181 -0
  172. package/dist/proxmox/generated/pbs/tape-drive.d.ts.map +1 -0
  173. package/dist/proxmox/generated/pbs/tape-media.d.ts +126 -0
  174. package/dist/proxmox/generated/pbs/tape-media.d.ts.map +1 -0
  175. package/dist/proxmox/generated/pbs/tape.d.ts +90 -0
  176. package/dist/proxmox/generated/pbs/tape.d.ts.map +1 -0
  177. package/dist/proxmox/generated/pbs/version.d.ts +20 -0
  178. package/dist/proxmox/generated/pbs/version.d.ts.map +1 -0
  179. package/dist/proxmox/generated/pbs.d.ts +44 -662
  180. package/dist/proxmox/generated/pbs.d.ts.map +1 -1
  181. package/dist/proxmox/generated/pve/access-roles.d.ts +164 -0
  182. package/dist/proxmox/generated/pve/access-roles.d.ts.map +1 -0
  183. package/dist/proxmox/generated/pve/access-users.d.ts +152 -0
  184. package/dist/proxmox/generated/pve/access-users.d.ts.map +1 -0
  185. package/dist/proxmox/generated/pve/access.d.ts +221 -0
  186. package/dist/proxmox/generated/pve/access.d.ts.map +1 -0
  187. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts +45 -0
  188. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts.map +1 -0
  189. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts +47 -0
  190. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts.map +1 -0
  191. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts +240 -0
  192. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts.map +1 -0
  193. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts +200 -0
  194. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts.map +1 -0
  195. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts +109 -0
  196. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts.map +1 -0
  197. package/dist/proxmox/generated/pve/cluster-firewall.d.ts +225 -0
  198. package/dist/proxmox/generated/pve/cluster-firewall.d.ts.map +1 -0
  199. package/dist/proxmox/generated/pve/cluster-ha.d.ts +199 -0
  200. package/dist/proxmox/generated/pve/cluster-ha.d.ts.map +1 -0
  201. package/dist/proxmox/generated/pve/cluster-jobs.d.ts +183 -0
  202. package/dist/proxmox/generated/pve/cluster-jobs.d.ts.map +1 -0
  203. package/dist/proxmox/generated/pve/cluster-metrics.d.ts +110 -0
  204. package/dist/proxmox/generated/pve/cluster-metrics.d.ts.map +1 -0
  205. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts +224 -0
  206. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts.map +1 -0
  207. package/dist/proxmox/generated/pve/cluster-notifications.d.ts +91 -0
  208. package/dist/proxmox/generated/pve/cluster-notifications.d.ts.map +1 -0
  209. package/dist/proxmox/generated/pve/cluster-options.d.ts +85 -0
  210. package/dist/proxmox/generated/pve/cluster-options.d.ts.map +1 -0
  211. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts +48 -0
  212. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts.map +1 -0
  213. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts +45 -0
  214. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts.map +1 -0
  215. package/dist/proxmox/generated/pve/cluster-replication.d.ts +130 -0
  216. package/dist/proxmox/generated/pve/cluster-replication.d.ts.map +1 -0
  217. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts +220 -0
  218. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts.map +1 -0
  219. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts +229 -0
  220. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts.map +1 -0
  221. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts +229 -0
  222. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts.map +1 -0
  223. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts +51 -0
  224. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts.map +1 -0
  225. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts +225 -0
  226. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts.map +1 -0
  227. package/dist/proxmox/generated/pve/cluster-sdn.d.ts +202 -0
  228. package/dist/proxmox/generated/pve/cluster-sdn.d.ts.map +1 -0
  229. package/dist/proxmox/generated/pve/cluster.d.ts +69 -0
  230. package/dist/proxmox/generated/pve/cluster.d.ts.map +1 -0
  231. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts +167 -0
  232. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts.map +1 -0
  233. package/dist/proxmox/generated/pve/nodes-node-config.d.ts +43 -0
  234. package/dist/proxmox/generated/pve/nodes-node-config.d.ts.map +1 -0
  235. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts +225 -0
  236. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts.map +1 -0
  237. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts +145 -0
  238. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts.map +1 -0
  239. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts +195 -0
  240. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts.map +1 -0
  241. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts +191 -0
  242. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts.map +1 -0
  243. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts +33 -0
  244. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts.map +1 -0
  245. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts +56 -0
  246. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts.map +1 -0
  247. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts +28 -0
  248. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts.map +1 -0
  249. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts +186 -0
  250. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts.map +1 -0
  251. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts +191 -0
  252. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts.map +1 -0
  253. package/dist/proxmox/generated/pve/nodes-node-network.d.ts +150 -0
  254. package/dist/proxmox/generated/pve/nodes-node-network.d.ts.map +1 -0
  255. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts +301 -0
  256. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts.map +1 -0
  257. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts +170 -0
  258. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts.map +1 -0
  259. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts +144 -0
  260. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts.map +1 -0
  261. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts +34 -0
  262. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts.map +1 -0
  263. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts +137 -0
  264. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts.map +1 -0
  265. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts +179 -0
  266. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts.map +1 -0
  267. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts +143 -0
  268. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts.map +1 -0
  269. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts +158 -0
  270. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts.map +1 -0
  271. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts +187 -0
  272. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts.map +1 -0
  273. package/dist/proxmox/generated/pve/nodes-node-services.d.ts +115 -0
  274. package/dist/proxmox/generated/pve/nodes-node-services.d.ts.map +1 -0
  275. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts +202 -0
  276. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts.map +1 -0
  277. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts +40 -0
  278. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts.map +1 -0
  279. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts +173 -0
  280. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts.map +1 -0
  281. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts +97 -0
  282. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts.map +1 -0
  283. package/dist/proxmox/generated/pve/nodes-node.d.ts +207 -0
  284. package/dist/proxmox/generated/pve/nodes-node.d.ts.map +1 -0
  285. package/dist/proxmox/generated/pve/nodes.d.ts +236 -0
  286. package/dist/proxmox/generated/pve/nodes.d.ts.map +1 -0
  287. package/dist/proxmox/generated/pve/pools.d.ts +82 -0
  288. package/dist/proxmox/generated/pve/pools.d.ts.map +1 -0
  289. package/dist/proxmox/generated/pve/storage.d.ts +159 -0
  290. package/dist/proxmox/generated/pve/storage.d.ts.map +1 -0
  291. package/dist/proxmox/generated/pve/version.d.ts +21 -0
  292. package/dist/proxmox/generated/pve/version.d.ts.map +1 -0
  293. package/dist/proxmox/generated/pve.d.ts +69 -4766
  294. package/dist/proxmox/generated/pve.d.ts.map +1 -1
  295. package/dist/proxmox/index.js +996 -372
  296. package/dist/proxmox/index.js.map +48 -32
  297. package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
  298. package/dist/proxmox/metric-server-form.d.ts +11 -0
  299. package/dist/proxmox/metric-server-form.d.ts.map +1 -1
  300. package/dist/proxmox/metric-server.d.ts.map +1 -1
  301. package/dist/proxmox/network-apply.d.ts.map +1 -1
  302. package/dist/proxmox/node-network-form.d.ts +15 -0
  303. package/dist/proxmox/node-network-form.d.ts.map +1 -1
  304. package/dist/proxmox/node-network.d.ts.map +1 -1
  305. package/dist/proxmox/notification-target-endpoint.d.ts +26 -0
  306. package/dist/proxmox/notification-target-endpoint.d.ts.map +1 -0
  307. package/dist/proxmox/notification-target-form.d.ts +7 -0
  308. package/dist/proxmox/notification-target-form.d.ts.map +1 -1
  309. package/dist/proxmox/notification-target.d.ts.map +1 -1
  310. package/dist/proxmox/pbs-notification-target-endpoint.d.ts +29 -0
  311. package/dist/proxmox/pbs-notification-target-endpoint.d.ts.map +1 -0
  312. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -1
  313. package/dist/proxmox/qemu.d.ts +10 -0
  314. package/dist/proxmox/qemu.d.ts.map +1 -1
  315. package/dist/proxmox/resource-guard.d.ts +15 -0
  316. package/dist/proxmox/resource-guard.d.ts.map +1 -0
  317. package/dist/proxmox/resource-spec.d.ts +15 -4
  318. package/dist/proxmox/resource-spec.d.ts.map +1 -1
  319. package/dist/proxmox/resource.d.ts +8 -0
  320. package/dist/proxmox/resource.d.ts.map +1 -1
  321. package/dist/proxmox/sdn-apply.d.ts.map +1 -1
  322. package/dist/proxmox/sdn-subnet.d.ts.map +1 -1
  323. package/dist/proxmox/zfs-pool-write.d.ts +11 -0
  324. package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
  325. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  326. package/docs/linux-host-measured.md +56 -0
  327. package/docs/linux-host.md +192 -0
  328. package/docs/netbox.md +103 -0
  329. package/package.json +9 -1
  330. package/src/linux/directory-lifecycle.ts +220 -0
  331. package/src/linux/directory.test.ts +132 -0
  332. package/src/linux/directory.ts +71 -0
  333. package/src/linux/fake-linux-host.ts +197 -0
  334. package/src/linux/fake-systemd.ts +103 -0
  335. package/src/linux/index.ts +32 -0
  336. package/src/linux/providers.ts +26 -0
  337. package/src/linux/region.test.ts +89 -0
  338. package/src/linux/region.ts +118 -0
  339. package/src/linux/remote-file-form.ts +96 -0
  340. package/src/linux/remote-file-lifecycle.test.ts +191 -0
  341. package/src/linux/remote-file-lifecycle.ts +161 -0
  342. package/src/linux/remote-file-plan.ts +154 -0
  343. package/src/linux/remote-file.ts +88 -0
  344. package/src/linux/ssh-command.test.ts +140 -0
  345. package/src/linux/ssh-command.ts +99 -0
  346. package/src/linux/ssh-runner.ts +188 -0
  347. package/src/linux/ssh-scripts.ts +105 -0
  348. package/src/linux/systemctl.ts +145 -0
  349. package/src/linux/unit-form.ts +183 -0
  350. package/src/linux/unit-handlers.ts +73 -0
  351. package/src/linux/unit-lifecycle.test.ts +220 -0
  352. package/src/linux/unit-lifecycle.ts +175 -0
  353. package/src/linux/unit-preflight.test.ts +128 -0
  354. package/src/linux/unit-preflight.ts +100 -0
  355. package/src/linux/unit-settle.ts +110 -0
  356. package/src/linux/unit.ts +81 -0
  357. package/src/netbox/client.test.ts +67 -0
  358. package/src/netbox/client.ts +146 -0
  359. package/src/netbox/constraint-guard.ts +57 -0
  360. package/src/netbox/constraints.test.ts +114 -0
  361. package/src/netbox/constraints.ts +152 -0
  362. package/src/netbox/generated/constraints/index.ts +23 -0
  363. package/src/netbox/generated/constraints/netbox-ipam.ts +32 -0
  364. package/src/netbox/index.ts +34 -0
  365. package/src/netbox/prefix-form.test.ts +127 -0
  366. package/src/netbox/prefix-form.ts +84 -0
  367. package/src/netbox/prefix.ts +136 -0
  368. package/src/netbox/resource.ts +208 -0
  369. package/src/netbox/values.test.ts +66 -0
  370. package/src/netbox/values.ts +40 -0
  371. package/src/proxmox/api-token-form.ts +5 -0
  372. package/src/proxmox/apply-endpoints.ts +34 -0
  373. package/src/proxmox/ceph-daemon-form.ts +56 -2
  374. package/src/proxmox/ceph-daemon.ts +10 -21
  375. package/src/proxmox/ceph-flag.ts +1 -0
  376. package/src/proxmox/ceph-fs.ts +1 -0
  377. package/src/proxmox/ceph-osd-write.ts +30 -4
  378. package/src/proxmox/ceph-pool.ts +10 -0
  379. package/src/proxmox/constraints-dialect.test.ts +165 -0
  380. package/src/proxmox/constraints-forms.test.ts +228 -0
  381. package/src/proxmox/constraints-host-forms.test.ts +132 -0
  382. package/src/proxmox/constraints-live.test.ts +155 -0
  383. package/src/proxmox/constraints-node-forms.test.ts +197 -0
  384. package/src/proxmox/constraints-required.test.ts +172 -0
  385. package/src/proxmox/constraints.test.ts +8 -63
  386. package/src/proxmox/constraints.ts +31 -6
  387. package/src/proxmox/generated/constraints/index.ts +27 -3
  388. package/src/proxmox/generated/constraints/pbs-config.ts +63 -1
  389. package/src/proxmox/generated/constraints/pve-access.ts +15 -3
  390. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +74 -0
  391. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +27 -0
  392. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +35 -0
  393. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +55 -0
  394. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +59 -0
  395. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +80 -0
  396. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +43 -0
  397. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +90 -0
  398. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +57 -0
  399. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +31 -0
  400. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +82 -0
  401. package/src/proxmox/generated/constraints/pve-nodes-network.ts +77 -0
  402. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +125 -0
  403. package/src/proxmox/generated/constraints/pve-pools.ts +6 -1
  404. package/src/proxmox/generated/constraints/pve-storage.ts +8 -3
  405. package/src/proxmox/generated/pbs/access-users.ts +137 -0
  406. package/src/proxmox/generated/pbs/access.ts +232 -0
  407. package/src/proxmox/generated/pbs/admin-datastore-store.ts +238 -0
  408. package/src/proxmox/generated/pbs/admin-metrics.ts +147 -0
  409. package/src/proxmox/generated/pbs/admin.ts +225 -0
  410. package/src/proxmox/generated/pbs/backup.ts +121 -0
  411. package/src/proxmox/generated/pbs/config-access-pam.ts +228 -0
  412. package/src/proxmox/generated/pbs/config-access.ts +228 -0
  413. package/src/proxmox/generated/pbs/config-datastore.ts +217 -0
  414. package/src/proxmox/generated/pbs/config-media-pool.ts +232 -0
  415. package/src/proxmox/generated/pbs/config-notifications-matchers.ts +187 -0
  416. package/src/proxmox/generated/pbs/config-notifications.ts +221 -0
  417. package/src/proxmox/generated/pbs/config-remote.ts +192 -0
  418. package/src/proxmox/generated/pbs/config-sync.ts +167 -0
  419. package/src/proxmox/generated/pbs/config-tape.ts +226 -0
  420. package/src/proxmox/generated/pbs/config-verify.ts +87 -0
  421. package/src/proxmox/generated/pbs/config.ts +135 -0
  422. package/src/proxmox/generated/pbs/nodes-node-dns.ts +229 -0
  423. package/src/proxmox/generated/pbs/nodes-node-services.ts +181 -0
  424. package/src/proxmox/generated/pbs/nodes-node.ts +244 -0
  425. package/src/proxmox/generated/pbs/nodes.ts +160 -0
  426. package/src/proxmox/generated/pbs/ping.ts +16 -0
  427. package/src/proxmox/generated/pbs/pull.ts +37 -0
  428. package/src/proxmox/generated/pbs/push.ts +36 -0
  429. package/src/proxmox/generated/pbs/reader.ts +41 -0
  430. package/src/proxmox/generated/pbs/root.ts +16 -0
  431. package/src/proxmox/generated/pbs/status.ts +50 -0
  432. package/src/proxmox/generated/pbs/tape-drive.ts +220 -0
  433. package/src/proxmox/generated/pbs/tape-media.ts +133 -0
  434. package/src/proxmox/generated/pbs/tape.ts +92 -0
  435. package/src/proxmox/generated/pbs/version.ts +16 -0
  436. package/src/proxmox/generated/pbs.ts +44 -787
  437. package/src/proxmox/generated/pve/access-roles.ts +168 -0
  438. package/src/proxmox/generated/pve/access-users.ts +155 -0
  439. package/src/proxmox/generated/pve/access.ts +217 -0
  440. package/src/proxmox/generated/pve/cluster-acme-plugins-id.ts +367 -0
  441. package/src/proxmox/generated/pve/cluster-acme-plugins.ts +366 -0
  442. package/src/proxmox/generated/pve/cluster-acme-tos.ts +232 -0
  443. package/src/proxmox/generated/pve/cluster-bulk-action.ts +227 -0
  444. package/src/proxmox/generated/pve/cluster-firewall-refs.ts +110 -0
  445. package/src/proxmox/generated/pve/cluster-firewall.ts +236 -0
  446. package/src/proxmox/generated/pve/cluster-ha.ts +203 -0
  447. package/src/proxmox/generated/pve/cluster-jobs.ts +190 -0
  448. package/src/proxmox/generated/pve/cluster-metrics.ts +116 -0
  449. package/src/proxmox/generated/pve/cluster-notifications-endpoints.ts +244 -0
  450. package/src/proxmox/generated/pve/cluster-notifications.ts +99 -0
  451. package/src/proxmox/generated/pve/cluster-options.ts +189 -0
  452. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.ts +272 -0
  453. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models.ts +268 -0
  454. package/src/proxmox/generated/pve/cluster-replication.ts +127 -0
  455. package/src/proxmox/generated/pve/cluster-sdn-fabrics.ts +218 -0
  456. package/src/proxmox/generated/pve/cluster-sdn-ipams.ts +229 -0
  457. package/src/proxmox/generated/pve/cluster-sdn-vnets-vnet.ts +245 -0
  458. package/src/proxmox/generated/pve/cluster-sdn-vnets.ts +49 -0
  459. package/src/proxmox/generated/pve/cluster-sdn-zones.ts +224 -0
  460. package/src/proxmox/generated/pve/cluster-sdn.ts +201 -0
  461. package/src/proxmox/generated/pve/cluster.ts +71 -0
  462. package/src/proxmox/generated/pve/nodes-node-ceph.ts +167 -0
  463. package/src/proxmox/generated/pve/nodes-node-config.ts +56 -0
  464. package/src/proxmox/generated/pve/nodes-node-disks.ts +237 -0
  465. package/src/proxmox/generated/pve/nodes-node-firewall.ts +239 -0
  466. package/src/proxmox/generated/pve/nodes-node-hardware.ts +215 -0
  467. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.ts +232 -0
  468. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.ts +1059 -0
  469. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.ts +49 -0
  470. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-resize.ts +285 -0
  471. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.ts +184 -0
  472. package/src/proxmox/generated/pve/nodes-node-lxc-vmid.ts +240 -0
  473. package/src/proxmox/generated/pve/nodes-node-network.ts +234 -0
  474. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-config.ts +441 -0
  475. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.ts +215 -0
  476. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.ts +145 -0
  477. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.ts +664 -0
  478. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.ts +188 -0
  479. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-status.ts +233 -0
  480. package/src/proxmox/generated/pve/nodes-node-qemu-vmid.ts +187 -0
  481. package/src/proxmox/generated/pve/nodes-node-qemu.ts +204 -0
  482. package/src/proxmox/generated/pve/nodes-node-replication.ts +187 -0
  483. package/src/proxmox/generated/pve/nodes-node-services.ts +221 -0
  484. package/src/proxmox/generated/pve/nodes-node-storage-storage.ts +226 -0
  485. package/src/proxmox/generated/pve/nodes-node-storage.ts +40 -0
  486. package/src/proxmox/generated/pve/nodes-node-subscription.ts +168 -0
  487. package/src/proxmox/generated/pve/nodes-node-vzdump.ts +96 -0
  488. package/src/proxmox/generated/pve/nodes-node.ts +211 -0
  489. package/src/proxmox/generated/pve/nodes.ts +235 -0
  490. package/src/proxmox/generated/pve/pools.ts +78 -0
  491. package/src/proxmox/generated/pve/storage.ts +213 -0
  492. package/src/proxmox/generated/pve/version.ts +21 -0
  493. package/src/proxmox/generated/pve.ts +69 -7403
  494. package/src/proxmox/lxc-interior.test.ts +17 -1
  495. package/src/proxmox/lxc-lifecycle.ts +48 -9
  496. package/src/proxmox/metric-server-form.ts +10 -0
  497. package/src/proxmox/metric-server.ts +11 -2
  498. package/src/proxmox/network-apply.ts +4 -0
  499. package/src/proxmox/node-network-form.ts +19 -0
  500. package/src/proxmox/node-network.ts +9 -3
  501. package/src/proxmox/notification-target-endpoint.ts +46 -0
  502. package/src/proxmox/notification-target-form.ts +11 -0
  503. package/src/proxmox/notification-target.ts +5 -2
  504. package/src/proxmox/pbs-notification-target-endpoint.ts +45 -0
  505. package/src/proxmox/pbs-notification-target-lifecycle.ts +16 -14
  506. package/src/proxmox/qemu.ts +9 -1
  507. package/src/proxmox/resource-guard.ts +61 -0
  508. package/src/proxmox/resource-spec.ts +16 -4
  509. package/src/proxmox/resource.ts +27 -27
  510. package/src/proxmox/sdn-apply.ts +4 -0
  511. package/src/proxmox/sdn-subnet.ts +5 -0
  512. package/src/proxmox/zfs-pool-write.ts +12 -0
  513. package/src/proxmox/zfs-pool.ts +2 -1
  514. package/dist/proxmox/generated/constraints/pve-cluster.d.ts +0 -18
  515. package/dist/proxmox/generated/constraints/pve-cluster.d.ts.map +0 -1
  516. package/src/proxmox/generated/constraints/pve-cluster.ts +0 -174
@@ -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 Effect7 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,6 +223,9 @@ 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
226
229
  import * as Effect6 from "effect/Effect";
227
230
 
228
231
  // src/proxmox/constraint-guard.ts
@@ -241,7 +244,7 @@ var checkValue = (name, value, rule) => {
241
244
  if (rule.enum !== undefined && !rule.enum.includes(value)) {
242
245
  out.push(`${name}: must be one of ${rule.enum.join(", ")}`);
243
246
  }
244
- if (rule.pattern !== undefined && !new RegExp(rule.pattern).test(value)) {
247
+ if (rule.pattern !== undefined && !new RegExp(rule.pattern, rule.patternFlags).test(value)) {
245
248
  out.push(`${name}: must match ${rule.patternSource ?? rule.pattern}`);
246
249
  }
247
250
  const numeric = Number(value);
@@ -291,11 +294,14 @@ var PVE_ACCESS_CONSTRAINTS = {
291
294
  expire: { minimum: 0, type: "integer" },
292
295
  firstname: { maxLength: 1024, type: "string" },
293
296
  groups: { format: "pve-groupid-list", type: "string" },
294
- keys: { pattern: "[0-9a-zA-Z!=]{0,4096}", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
297
+ keys: { pattern: "^[0-9a-zA-Z!=]{0,4096}\\n?$", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
295
298
  lastname: { maxLength: 1024, type: "string" },
296
299
  password: { maxLength: 64, minLength: 8, type: "string" },
297
300
  userid: { format: "pve-userid", maxLength: 64, required: true, type: "string" }
298
301
  },
302
+ "pve:POST /access/users/{userid}/token/{tokenid}": {
303
+ expire: { default: "same as user", minimum: 0, type: "integer" }
304
+ },
299
305
  "pve:PUT /access/acl": {
300
306
  groups: { format: "pve-groupid-list", type: "string" },
301
307
  path: { required: true, type: "string" },
@@ -313,13 +319,17 @@ var PVE_ACCESS_CONSTRAINTS = {
313
319
  expire: { minimum: 0, type: "integer" },
314
320
  firstname: { maxLength: 1024, type: "string" },
315
321
  groups: { format: "pve-groupid-list", type: "string" },
316
- keys: { pattern: "[0-9a-zA-Z!=]{0,4096}", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
322
+ keys: { pattern: "^[0-9a-zA-Z!=]{0,4096}\\n?$", patternSource: "[0-9a-zA-Z!=]{0,4096}", type: "string" },
317
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" }
318
328
  }
319
329
  };
320
330
 
321
- // src/proxmox/generated/constraints/pve-cluster.ts
322
- var PVE_CLUSTER_CONSTRAINTS = {
331
+ // src/proxmox/generated/constraints/pve-cluster-backup.ts
332
+ var PVE_CLUSTER_BACKUP_CONSTRAINTS = {
323
333
  "pve:POST /cluster/backup": {
324
334
  bwlimit: { default: "0", minimum: 0, type: "integer" },
325
335
  comment: { maxLength: 512, type: "string" },
@@ -340,64 +350,11 @@ var PVE_CLUSTER_CONSTRAINTS = {
340
350
  performance: { format: "backup-performance", type: "string" },
341
351
  "prune-backups": { default: "keep-all=1", format: "prune-backups", type: "string" },
342
352
  schedule: { format: "pve-calendar-event", maxLength: 128, type: "string" },
343
- starttime: { pattern: "\\d{1,2}:\\d{1,2}", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
353
+ starttime: { pattern: "^\\d{1,2}:\\d{1,2}\\n?$", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
344
354
  stopwait: { default: "10", minimum: 0, type: "integer" },
345
355
  storage: { format: "pve-storage-id", type: "string" },
346
356
  vmid: { format: "pve-vmid-list", type: "string" }
347
357
  },
348
- "pve:POST /cluster/firewall/aliases": {
349
- cidr: { format: "IPorCIDR", required: true, type: "string" },
350
- comment: { format: "pve-fw-comment-spec", type: "string" },
351
- name: { maxLength: 64, minLength: 2, pattern: "[A-Za-z][A-Za-z0-9\\-\\_]+", patternSource: "[A-Za-z][A-Za-z0-9\\-\\_]+", required: true, type: "string" }
352
- },
353
- "pve:POST /cluster/ha/resources": {
354
- comment: { maxLength: 4096, type: "string" },
355
- group: { format: "pve-configid", type: "string" },
356
- max_relocate: { default: "1", minimum: 0, type: "integer" },
357
- max_restart: { default: "1", minimum: 0, type: "integer" },
358
- sid: { format: "pve-ha-resource-or-vm-id", required: true, type: "string" },
359
- state: { default: "started", enum: ["started", "stopped", "enabled", "disabled", "ignored"], type: "string" },
360
- type: { enum: ["ct", "vm"], type: "string" }
361
- },
362
- "pve:POST /cluster/ha/rules": {},
363
- "pve:POST /cluster/notifications/matchers": {
364
- mode: { default: "all", enum: ["all", "any"], type: "string" },
365
- name: { format: "pve-configid", required: true, type: "string" }
366
- },
367
- "pve:POST /cluster/replication": {
368
- comment: { maxLength: 4096, type: "string" },
369
- id: { format: "pve-replication-job-id", pattern: "[1-9][0-9]{2,8}-\\d{1,9}", patternSource: "[1-9][0-9]{2,8}-\\d{1,9}", required: true, type: "string" },
370
- rate: { minimum: 1, type: "number" },
371
- remove_job: { enum: ["local", "full"], type: "string" },
372
- schedule: { default: "*/15", format: "pve-calendar-event", maxLength: 128, type: "string" },
373
- source: { format: "pve-node", type: "string" },
374
- target: { format: "pve-node", required: true, type: "string" },
375
- type: { enum: ["local"], required: true, type: "string" }
376
- },
377
- "pve:POST /cluster/sdn/vnets": {
378
- alias: { maxLength: 256, patternSource: "(?^i:[\\(\\)-_.\\w\\d\\s]{0,256})", type: "string" },
379
- tag: { maximum: 16777215, minimum: 1, type: "integer" },
380
- type: { enum: ["vnet"], type: "string" },
381
- vnet: { maxLength: 8, minLength: 2, pattern: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", patternSource: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", required: true, type: "string" },
382
- zone: { required: true, type: "string" }
383
- },
384
- "pve:POST /cluster/sdn/zones": {
385
- dhcp: { enum: ["dnsmasq"], type: "string" },
386
- dnszone: { format: "dns-name", type: "string" },
387
- exitnodes: { format: "pve-node-list", type: "string" },
388
- "exitnodes-primary": { format: "pve-node", type: "string" },
389
- fabric: { format: "pve-sdn-fabric-id", type: "string" },
390
- mac: { format: "mac-addr", type: "string" },
391
- nodes: { format: "pve-node-list", type: "string" },
392
- peers: { format: "ip-list", type: "string" },
393
- "rt-import": { format: "pve-sdn-bgp-rt-list", type: "string" },
394
- tag: { minimum: 0, type: "integer" },
395
- type: { enum: ["evpn", "faucet", "qinq", "simple", "vlan", "vxlan"], format: "pve-configid", required: true, type: "string" },
396
- "vlan-protocol": { default: "802.1q", enum: ["802.1q", "802.1ad"], type: "string" },
397
- "vrf-vxlan": { maximum: 16777215, minimum: 1, type: "integer" },
398
- "vxlan-port": { default: "4789", maximum: 65536, minimum: 1, type: "integer" },
399
- zone: { maxLength: 8, minLength: 2, pattern: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", patternSource: "[a-zA-Z][a-zA-Z0-9]*[a-zA-Z0-9]", required: true, type: "string" }
400
- },
401
358
  "pve:PUT /cluster/backup/{id}": {
402
359
  bwlimit: { default: "0", minimum: 0, type: "integer" },
403
360
  comment: { maxLength: 512, type: "string" },
@@ -418,16 +375,51 @@ var PVE_CLUSTER_CONSTRAINTS = {
418
375
  performance: { format: "backup-performance", type: "string" },
419
376
  "prune-backups": { default: "keep-all=1", format: "prune-backups", type: "string" },
420
377
  schedule: { format: "pve-calendar-event", maxLength: 128, type: "string" },
421
- starttime: { pattern: "\\d{1,2}:\\d{1,2}", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
378
+ starttime: { pattern: "^\\d{1,2}:\\d{1,2}\\n?$", patternSource: "\\d{1,2}:\\d{1,2}", type: "string" },
422
379
  stopwait: { default: "10", minimum: 0, type: "integer" },
423
380
  storage: { format: "pve-storage-id", type: "string" },
424
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" }
425
398
  },
426
399
  "pve:PUT /cluster/firewall/aliases/{name}": {
427
400
  cidr: { format: "IPorCIDR", required: true, type: "string" },
428
401
  comment: { format: "pve-fw-comment-spec", type: "string" },
429
402
  digest: { maxLength: 64, type: "string" },
430
- rename: { maxLength: 64, minLength: 2, pattern: "[A-Za-z][A-Za-z0-9\\-\\_]+", patternSource: "[A-Za-z][A-Za-z0-9\\-\\_]+", 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" }
431
423
  },
432
424
  "pve:PUT /cluster/ha/resources/{sid}": {
433
425
  comment: { maxLength: 4096, type: "string" },
@@ -438,10 +430,125 @@ var PVE_CLUSTER_CONSTRAINTS = {
438
430
  max_restart: { default: "1", minimum: 0, type: "integer" },
439
431
  state: { default: "started", enum: ["started", "stopped", "enabled", "disabled", "ignored"], type: "string" }
440
432
  },
441
- "pve:PUT /cluster/ha/rules/{rule}": {},
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
+ },
442
533
  "pve:PUT /cluster/notifications/matchers/{name}": {
534
+ delete: { each: true, format: "pve-configid", type: "array" },
443
535
  digest: { maxLength: 64, type: "string" },
444
- mode: { default: "all", enum: ["all", "any"], 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" }
445
552
  },
446
553
  "pve:PUT /cluster/replication/{id}": {
447
554
  comment: { maxLength: 4096, type: "string" },
@@ -451,13 +558,59 @@ var PVE_CLUSTER_CONSTRAINTS = {
451
558
  remove_job: { enum: ["local", "full"], type: "string" },
452
559
  schedule: { default: "*/15", format: "pve-calendar-event", maxLength: 128, type: "string" },
453
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" }
454
598
  },
599
+ "pve:PUT /cluster/sdn": {},
455
600
  "pve:PUT /cluster/sdn/vnets/{vnet}": {
456
601
  alias: { maxLength: 256, patternSource: "(?^i:[\\(\\)-_.\\w\\d\\s]{0,256})", type: "string" },
457
602
  delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
458
603
  digest: { maxLength: 64, type: "string" },
459
604
  tag: { maximum: 16777215, minimum: 1, type: "integer" }
460
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
+ },
461
614
  "pve:PUT /cluster/sdn/zones/{zone}": {
462
615
  delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
463
616
  dhcp: { enum: ["dnsmasq"], type: "string" },
@@ -470,6 +623,7 @@ var PVE_CLUSTER_CONSTRAINTS = {
470
623
  nodes: { format: "pve-node-list", type: "string" },
471
624
  peers: { format: "ip-list", type: "string" },
472
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" },
473
627
  tag: { minimum: 0, type: "integer" },
474
628
  "vlan-protocol": { default: "802.1q", enum: ["802.1q", "802.1ad"], type: "string" },
475
629
  "vrf-vxlan": { maximum: 16777215, minimum: 1, type: "integer" },
@@ -477,6 +631,278 @@ var PVE_CLUSTER_CONSTRAINTS = {
477
631
  }
478
632
  };
479
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
+
480
906
  // src/proxmox/generated/constraints/pve-pools.ts
481
907
  var PVE_POOLS_CONSTRAINTS = {
482
908
  "pve:POST /pools": {
@@ -497,7 +923,7 @@ var PVE_STORAGE_CONSTRAINTS = {
497
923
  "content-dirs": { format: "pve-dir-override-list", type: "string" },
498
924
  domain: { maxLength: 256, type: "string" },
499
925
  export: { format: "pve-storage-path", type: "string" },
500
- fingerprint: { pattern: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", patternSource: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", 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" },
501
927
  format: { enum: ["raw", "qcow2", "subvol", "vmdk"], type: "string" },
502
928
  "fs-name": { format: "pve-configid", type: "string" },
503
929
  "max-protected-backups": { default: "Unlimited for users with Datastore.Allocate privilege, 5 for other users", minimum: -1, type: "integer" },
@@ -528,7 +954,7 @@ var PVE_STORAGE_CONSTRAINTS = {
528
954
  delete: { format: "pve-configid-list", maxLength: 4096, type: "string" },
529
955
  digest: { maxLength: 64, type: "string" },
530
956
  domain: { maxLength: 256, type: "string" },
531
- fingerprint: { pattern: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", patternSource: "([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}", 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" },
532
958
  format: { enum: ["raw", "qcow2", "subvol", "vmdk"], type: "string" },
533
959
  "fs-name": { format: "pve-configid", type: "string" },
534
960
  "max-protected-backups": { default: "Unlimited for users with Datastore.Allocate privilege, 5 for other users", minimum: -1, type: "integer" },
@@ -564,11 +990,37 @@ var PBS_CONFIG_CONSTRAINTS = {
564
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" },
565
991
  path: { maxLength: 4096, minLength: 1, required: true, type: "string" }
566
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
+ },
567
1018
  "pbs:POST /config/notifications/matchers": {
568
1019
  comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
569
1020
  mode: { default: "all", enum: ["all", "any"], type: "string" },
570
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" },
571
- origin: { enum: ["user-created", "builtin", "modified-builtin"], 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" }
572
1024
  },
573
1025
  "pbs:POST /config/prune": {
574
1026
  comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
@@ -586,6 +1038,7 @@ var PBS_CONFIG_CONSTRAINTS = {
586
1038
  },
587
1039
  "pbs:POST /config/sync": {
588
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" },
589
1042
  "burst-in": { maxLength: 64, minLength: 1, type: "string" },
590
1043
  "burst-out": { maxLength: 64, minLength: 1, type: "string" },
591
1044
  comment: { maxLength: 128, pattern: "^[^\\x00-\\x1f\\x7f]*$", patternSource: "/^[[:^cntrl:]]*$/", type: "string" },
@@ -615,6 +1068,7 @@ var PBS_CONFIG_CONSTRAINTS = {
615
1068
  },
616
1069
  "pbs:PUT /config/datastore/{name}": {
617
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" },
618
1072
  digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
619
1073
  "keep-daily": { minimum: 1, type: "integer" },
620
1074
  "keep-hourly": { minimum: 1, type: "integer" },
@@ -625,13 +1079,39 @@ var PBS_CONFIG_CONSTRAINTS = {
625
1079
  "notification-mode": { default: "notification-system", enum: ["legacy-sendmail", "notification-system"], type: "string" },
626
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" }
627
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
+ },
628
1105
  "pbs:PUT /config/notifications/matchers/{name}": {
629
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" },
630
1108
  digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
631
- mode: { default: "all", enum: ["all", "any"], 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" }
632
1111
  },
633
1112
  "pbs:PUT /config/prune/{id}": {
634
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" },
635
1115
  digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
636
1116
  "keep-daily": { minimum: 1, type: "integer" },
637
1117
  "keep-hourly": { minimum: 1, type: "integer" },
@@ -645,9 +1125,11 @@ var PBS_CONFIG_CONSTRAINTS = {
645
1125
  },
646
1126
  "pbs:PUT /config/sync/{id}": {
647
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" },
648
1129
  "burst-in": { maxLength: 64, minLength: 1, type: "string" },
649
1130
  "burst-out": { maxLength: 64, minLength: 1, type: "string" },
650
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" },
651
1133
  digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
652
1134
  "max-depth": { maximum: 7, minimum: 0, type: "integer" },
653
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" },
@@ -664,6 +1146,7 @@ var PBS_CONFIG_CONSTRAINTS = {
664
1146
  },
665
1147
  "pbs:PUT /config/verify/{id}": {
666
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" },
667
1150
  digest: { pattern: "^[a-f0-9]{64}$", patternSource: "/^[a-f0-9]{64}$/", type: "string" },
668
1151
  "max-depth": { default: "7", maximum: 7, minimum: 0, type: "integer" },
669
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" },
@@ -677,7 +1160,19 @@ var PBS_CONFIG_CONSTRAINTS = {
677
1160
  // src/proxmox/generated/constraints/index.ts
678
1161
  var PROXMOX_CONSTRAINTS = {
679
1162
  ...PVE_ACCESS_CONSTRAINTS,
680
- ...PVE_CLUSTER_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,
681
1176
  ...PVE_POOLS_CONSTRAINTS,
682
1177
  ...PVE_STORAGE_CONSTRAINTS,
683
1178
  ...PBS_CONFIG_CONSTRAINTS
@@ -699,43 +1194,56 @@ var guardForm = (key, form, presence) => Effect5.suspend(() => {
699
1194
  return found.length === 0 ? Effect5.void : Effect5.die(new Error(refusal(key, found)));
700
1195
  });
701
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
+
702
1214
  // src/proxmox/update-guard.ts
703
1215
  var formToSend = (matches, live, props, form) => matches(live, props) || Object.keys(form).length === 0 ? undefined : form;
704
1216
 
705
1217
  // src/proxmox/resource.ts
706
1218
  var pveOperations = (spec) => {
707
- const guardForms = (props) => Effect6.gen(function* () {
708
- const create = spec.endpoint?.create;
709
- if (create !== undefined)
710
- yield* guardForm(create, spec.createForm(props), true);
711
- const update = spec.endpoint?.update;
712
- if (update === undefined)
713
- return;
714
- const form = spec.updateForm?.(props);
715
- if (form !== undefined)
716
- yield* guardForm(update, form, false);
717
- });
718
- const read = (props) => pve(props.target, spec.readRole ?? "read", "GET", spec.path(props)).pipe(Effect6.map((data) => data == null ? undefined : spec.attributes(data, props)), Effect6.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(() => {
719
1221
  return;
720
1222
  }));
721
1223
  return {
1224
+ guardCreate,
1225
+ guardUpdate,
722
1226
  read,
723
- diff: (news, output) => Effect6.gen(function* () {
1227
+ diff: (news, output) => Effect7.gen(function* () {
724
1228
  if (!isResolved(news))
725
1229
  return;
726
- yield* guardForms(news);
1230
+ yield* guardCreate(news, output === undefined);
1231
+ yield* guardUpdate(news);
727
1232
  if (output === undefined)
728
1233
  return;
729
1234
  const live = yield* read(news);
730
- if (live === undefined)
1235
+ if (live === undefined) {
1236
+ yield* guardCreate(news, true);
731
1237
  return { action: "update" };
1238
+ }
732
1239
  if (spec.matches(live, news))
733
1240
  return { action: "noop" };
734
1241
  return spec.updateForm === undefined ? { action: "replace" } : { action: "update" };
735
1242
  }),
736
- reconcile: (news) => Effect6.gen(function* () {
737
- yield* guardForms(news);
1243
+ reconcile: (news) => Effect7.gen(function* () {
738
1244
  const live = yield* read(news);
1245
+ yield* guardCreate(news, live === undefined);
1246
+ yield* guardUpdate(news);
739
1247
  if (live === undefined) {
740
1248
  yield* pve(news.target, "provision", "POST", spec.collection(news), spec.createForm(news));
741
1249
  } else if (spec.updateForm !== undefined) {
@@ -746,7 +1254,7 @@ var pveOperations = (spec) => {
746
1254
  }
747
1255
  const after = yield* read(news);
748
1256
  if (after === undefined) {
749
- return yield* Effect6.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."));
750
1258
  }
751
1259
  return after;
752
1260
  }),
@@ -756,7 +1264,7 @@ var pveOperations = (spec) => {
756
1264
  var pveHandlers = (spec) => {
757
1265
  const ops = pveOperations(spec);
758
1266
  return {
759
- list: () => Effect6.succeed([]),
1267
+ list: () => Effect7.succeed([]),
760
1268
  read: ({ olds }) => ops.read(olds),
761
1269
  diff: ({ news, output }) => ops.diff(news, output),
762
1270
  reconcile: ({ news }) => ops.reconcile(news),
@@ -803,25 +1311,25 @@ var ops = pveOperations({
803
1311
  path: () => "access/acl",
804
1312
  updateForm: bind
805
1313
  });
806
- var ProxmoxAclProvider = () => Provider.effect(ProxmoxAcl, Effect7.succeed(ProxmoxAcl.Provider.of({
807
- list: () => Effect7.succeed([]),
808
- read: Effect7.fn(function* ({ olds }) {
1314
+ var ProxmoxAclProvider = () => Provider.effect(ProxmoxAcl, Effect8.succeed(ProxmoxAcl.Provider.of({
1315
+ list: () => Effect8.succeed([]),
1316
+ read: Effect8.fn(function* ({ olds }) {
809
1317
  return yield* ops.read(olds);
810
1318
  }),
811
- diff: Effect7.fn(function* ({ news, output }) {
1319
+ diff: Effect8.fn(function* ({ news, output }) {
812
1320
  if (output !== undefined && isResolved2(news) && identity(news) !== identity(output)) {
813
1321
  return { action: "replace" };
814
1322
  }
815
1323
  return yield* ops.diff(news, output);
816
1324
  }),
817
- reconcile: Effect7.fn(function* ({ news }) {
1325
+ reconcile: Effect8.fn(function* ({ news }) {
818
1326
  const after = yield* ops.reconcile(news);
819
1327
  if (!after.bound) {
820
- return yield* Effect7.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."));
821
1329
  }
822
1330
  return after;
823
1331
  }),
824
- delete: Effect7.fn(function* ({ olds }) {
1332
+ delete: Effect8.fn(function* ({ olds }) {
825
1333
  const removal = { delete: "1", ...tuple(olds) };
826
1334
  yield* pve(olds.target, "provision", "PUT", "access/acl", removal);
827
1335
  })
@@ -879,7 +1387,7 @@ var alertmanagerAlertBody = (options = {}) => {
879
1387
  // src/proxmox/api-token.ts
880
1388
  import { Resource as Resource2 } from "alchemy";
881
1389
  import * as Provider2 from "alchemy/Provider";
882
- import * as Effect8 from "effect/Effect";
1390
+ import * as Effect9 from "effect/Effect";
883
1391
 
884
1392
  // src/proxmox/values.ts
885
1393
  var num = (value, fallback) => typeof value === "number" ? value : fallback;
@@ -947,6 +1455,10 @@ var apiTokenSpec = {
947
1455
  },
948
1456
  collection: (props) => `access/users/${props.userid}/token/${props.tokenid}`,
949
1457
  createForm: shape,
1458
+ endpoint: {
1459
+ create: "pve:POST /access/users/{userid}/token/{tokenid}",
1460
+ update: "pve:PUT /access/users/{userid}/token/{tokenid}"
1461
+ },
950
1462
  matches: (attributes, props) => attributes.comment === (props.comment ?? "") && attributes.expire === props.expire && attributes.privsep === props.privsep,
951
1463
  path: (props) => `access/users/${props.userid}/token/${props.tokenid}`,
952
1464
  updateForm: shape
@@ -959,19 +1471,19 @@ var ProxmoxApiToken = Resource2("Proxmox.ApiToken", {
959
1471
  var ops2 = pveOperations(apiTokenSpec);
960
1472
  var handlers = {
961
1473
  ...pveHandlers(apiTokenSpec),
962
- reconcile: Effect8.fn(function* ({ news }) {
1474
+ reconcile: Effect9.fn(function* ({ news }) {
963
1475
  const live = yield* ops2.read(news);
964
1476
  if (live === undefined) {
965
- return yield* Effect8.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."));
966
1478
  }
967
1479
  return yield* ops2.reconcile(news);
968
1480
  })
969
1481
  };
970
- var ProxmoxApiTokenProvider = () => Provider2.effect(ProxmoxApiToken, Effect8.succeed(ProxmoxApiToken.Provider.of(handlers)));
1482
+ var ProxmoxApiTokenProvider = () => Provider2.effect(ProxmoxApiToken, Effect9.succeed(ProxmoxApiToken.Provider.of(handlers)));
971
1483
  // src/proxmox/backup-job.ts
972
1484
  import { Resource as Resource3 } from "alchemy";
973
1485
  import * as Provider3 from "alchemy/Provider";
974
- import * as Effect9 from "effect/Effect";
1486
+ import * as Effect10 from "effect/Effect";
975
1487
  var ProxmoxBackupJob = Resource3("Proxmox.BackupJob");
976
1488
  var shape2 = (props) => ({
977
1489
  all: props.all === true ? "1" : "0",
@@ -1015,13 +1527,18 @@ var handlers2 = pveHandlers({
1015
1527
  path: (props) => `cluster/backup/${props.id}`,
1016
1528
  updateForm: shape2
1017
1529
  });
1018
- var ProxmoxBackupJobProvider = () => Provider3.effect(ProxmoxBackupJob, Effect9.succeed(ProxmoxBackupJob.Provider.of(handlers2)));
1530
+ var ProxmoxBackupJobProvider = () => Provider3.effect(ProxmoxBackupJob, Effect10.succeed(ProxmoxBackupJob.Provider.of(handlers2)));
1019
1531
  // src/proxmox/ceph-daemon.ts
1020
1532
  import { Resource as Resource4 } from "alchemy";
1021
1533
  import * as Provider4 from "alchemy/Provider";
1022
- import * as Effect10 from "effect/Effect";
1534
+ import * as Effect11 from "effect/Effect";
1023
1535
 
1024
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
+ };
1025
1542
  var daemonId = (props) => props.name ?? props.node;
1026
1543
  var collectionPath = (props) => `nodes/${props.node}/ceph/${props.kind}`;
1027
1544
  var daemonPath = (props) => `${collectionPath(props)}/${daemonId(props)}`;
@@ -1033,60 +1550,63 @@ var createForm = (props) => {
1033
1550
  return hotstandby === undefined ? {} : { hotstandby };
1034
1551
  };
1035
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
+ };
1036
1572
 
1037
1573
  // src/proxmox/ceph-daemon.ts
1038
1574
  var ProxmoxCephDaemon = Resource4("Proxmox.CephDaemon", {
1039
1575
  defaultRemovalPolicy: "retain"
1040
1576
  });
1041
1577
  var handlers3 = pveHandlers({
1042
- attributes: (live, props) => {
1043
- const row = findRow(live, props);
1044
- if (row === undefined)
1045
- return;
1046
- return {
1047
- addr: text(row["addr"]),
1048
- fsName: text(row["fs_name"]),
1049
- host: text(row["host"]),
1050
- kind: props.kind,
1051
- name: daemonId(props),
1052
- node: props.node,
1053
- quorum: bool(row["quorum"]),
1054
- rank: num(row["rank"], -1),
1055
- service: bool(row["service"]),
1056
- standbyReplay: bool(row["standby_replay"]),
1057
- state: text(row["state"]),
1058
- version: text(row["ceph_version_short"])
1059
- };
1060
- },
1578
+ attributes: daemonAttributes,
1061
1579
  collection: daemonPath,
1062
1580
  createForm,
1581
+ endpoint: (props) => DAEMON_ENDPOINTS[props.kind],
1063
1582
  matches: () => true,
1064
1583
  path: collectionPath
1065
1584
  });
1066
- var ProxmoxCephDaemonProvider = () => Provider4.effect(ProxmoxCephDaemon, Effect10.succeed(ProxmoxCephDaemon.Provider.of({
1585
+ var ProxmoxCephDaemonProvider = () => Provider4.effect(ProxmoxCephDaemon, Effect11.succeed(ProxmoxCephDaemon.Provider.of({
1067
1586
  ...handlers3,
1068
1587
  delete: ({ olds }) => pve(olds.target, "provision", "DELETE", daemonPath(olds))
1069
1588
  })));
1070
1589
  // src/proxmox/ceph-flag.ts
1071
1590
  import { Resource as Resource5 } from "alchemy";
1072
1591
  import * as Provider5 from "alchemy/Provider";
1073
- import * as Effect11 from "effect/Effect";
1592
+ import * as Effect12 from "effect/Effect";
1074
1593
  var ProxmoxCephFlag = Resource5("Proxmox.CephFlag");
1075
1594
  var handlers4 = pveHandlers({
1076
1595
  attributes: (live, props) => ({ flag: props.flag, value: bool(live) }),
1077
1596
  collection: () => "cluster/ceph/flags",
1078
1597
  createForm: (props) => ({ [props.flag]: flag(props.value) ?? "0" }),
1598
+ endpoint: { update: "pve:PUT /cluster/ceph/flags/{flag}" },
1079
1599
  matches: (attributes, props) => attributes.value === props.value,
1080
1600
  path: (props) => `cluster/ceph/flags/${props.flag}`,
1081
1601
  updateForm: (props) => ({ value: flag(props.value) ?? "0" })
1082
1602
  });
1083
- var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect11.succeed(ProxmoxCephFlag.Provider.of({
1603
+ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect12.succeed(ProxmoxCephFlag.Provider.of({
1084
1604
  ...handlers4,
1085
- delete: () => Effect11.void,
1086
- reconcile: Effect11.fn(function* ({ news }) {
1605
+ delete: () => Effect12.void,
1606
+ reconcile: Effect12.fn(function* ({ news }) {
1087
1607
  const after = yield* handlers4.reconcile({ news });
1088
1608
  if (after.value !== news.value) {
1089
- return yield* Effect11.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."));
1090
1610
  }
1091
1611
  return after;
1092
1612
  })
@@ -1095,10 +1615,10 @@ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect11.s
1095
1615
  import { Resource as Resource6 } from "alchemy";
1096
1616
  import { isResolved as isResolved3 } from "alchemy/Diff";
1097
1617
  import * as Provider6 from "alchemy/Provider";
1098
- import * as Effect13 from "effect/Effect";
1618
+ import * as Effect14 from "effect/Effect";
1099
1619
 
1100
1620
  // src/proxmox/ceph-fs-wire.ts
1101
- import * as Effect12 from "effect/Effect";
1621
+ import * as Effect13 from "effect/Effect";
1102
1622
  var readRow = (live, props) => {
1103
1623
  const row = (Array.isArray(live) ? live : []).filter((entry) => typeof entry === "object" && entry !== null).find((entry) => entry["name"] === props.name);
1104
1624
  if (row === undefined)
@@ -1126,29 +1646,29 @@ var destroyPath = (props) => {
1126
1646
  ].filter((part) => part !== undefined);
1127
1647
  return query.length === 0 ? objectPath(props) : `${objectPath(props)}?${query.join("&")}`;
1128
1648
  };
1129
- var settle = (target, node, upid, what) => Effect12.gen(function* () {
1649
+ var settle = (target, node, upid, what) => Effect13.gen(function* () {
1130
1650
  for (let attempt = 0;attempt < POLL_ATTEMPTS; attempt += 1) {
1131
- const status = yield* pve(target, "read", "GET", `nodes/${node}/tasks/${encodeURIComponent(upid)}/status`).pipe(Effect12.orElseSucceed(() => {
1651
+ const status = yield* pve(target, "read", "GET", `nodes/${node}/tasks/${encodeURIComponent(upid)}/status`).pipe(Effect13.orElseSucceed(() => {
1132
1652
  return;
1133
1653
  }));
1134
1654
  if (status?.status === "stopped") {
1135
1655
  const exit = text(status.exitstatus);
1136
1656
  if (exit === "OK")
1137
1657
  return;
1138
- return yield* Effect12.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\`.`));
1139
1659
  }
1140
- yield* Effect12.sleep(POLL_SECONDS * 1000);
1660
+ yield* Effect13.sleep(POLL_SECONDS * 1000);
1141
1661
  }
1142
- return yield* Effect12.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."));
1143
1663
  });
1144
- var createFs = (props) => Effect12.gen(function* () {
1664
+ var createFs = (props) => Effect13.gen(function* () {
1145
1665
  const upid = text(yield* pve(props.target, "provision", "POST", objectPath(props), createForm2(props)));
1146
1666
  if (upid === "") {
1147
- return yield* Effect12.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.'));
1148
1668
  }
1149
1669
  yield* settle(props.target, props.node, upid, objectPath(props));
1150
1670
  });
1151
- var destroyFs = (props) => Effect12.gen(function* () {
1671
+ var destroyFs = (props) => Effect13.gen(function* () {
1152
1672
  const upid = text(yield* pve(props.target, "provision", "DELETE", destroyPath(props)));
1153
1673
  if (upid !== "")
1154
1674
  yield* settle(props.target, props.node, upid, destroyPath(props));
@@ -1164,47 +1684,48 @@ var ops3 = pveOperations({
1164
1684
  attributes: readRow,
1165
1685
  collection: objectPath,
1166
1686
  createForm: createForm2,
1687
+ endpoint: { create: "pve:POST /nodes/{node}/ceph/fs/{name}" },
1167
1688
  matches: () => true,
1168
1689
  path: (props) => `nodes/${props.node}/ceph/fs`
1169
1690
  });
1170
- var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect13.succeed(ProxmoxCephFs.Provider.of({
1171
- list: () => Effect13.succeed([]),
1172
- read: Effect13.fn(function* ({ olds }) {
1691
+ var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect14.succeed(ProxmoxCephFs.Provider.of({
1692
+ list: () => Effect14.succeed([]),
1693
+ read: Effect14.fn(function* ({ olds }) {
1173
1694
  return yield* ops3.read(olds);
1174
1695
  }),
1175
- diff: Effect13.fn(function* ({ news, output }) {
1696
+ diff: Effect14.fn(function* ({ news, output }) {
1176
1697
  if (output !== undefined && isResolved3(news) && news.name !== output.name) {
1177
1698
  return { action: "replace" };
1178
1699
  }
1179
1700
  return yield* ops3.diff(news, output);
1180
1701
  }),
1181
- reconcile: Effect13.fn(function* ({ news }) {
1702
+ reconcile: Effect14.fn(function* ({ news }) {
1182
1703
  const live = yield* ops3.read(news);
1183
1704
  if (live !== undefined)
1184
1705
  return live;
1185
1706
  yield* createFs(news);
1186
1707
  const after = yield* ops3.read(news);
1187
1708
  if (after === undefined)
1188
- return yield* Effect13.die(notCreated(news));
1709
+ return yield* Effect14.die(notCreated(news));
1189
1710
  return after;
1190
1711
  }),
1191
- delete: Effect13.fn(function* ({ olds }) {
1712
+ delete: Effect14.fn(function* ({ olds }) {
1192
1713
  if ((yield* ops3.read(olds)) === undefined)
1193
1714
  return;
1194
1715
  yield* destroyFs(olds);
1195
1716
  const after = yield* ops3.read(olds);
1196
1717
  if (after !== undefined)
1197
- return yield* Effect13.die(notDestroyed(olds));
1718
+ return yield* Effect14.die(notDestroyed(olds));
1198
1719
  })
1199
1720
  })));
1200
1721
  // src/proxmox/ceph-osd.ts
1201
1722
  import { Resource as Resource7 } from "alchemy";
1202
1723
  import { isResolved as isResolved4 } from "alchemy/Diff";
1203
1724
  import * as Provider7 from "alchemy/Provider";
1204
- import * as Effect16 from "effect/Effect";
1725
+ import * as Effect17 from "effect/Effect";
1205
1726
 
1206
1727
  // src/proxmox/ceph-osd-tree.ts
1207
- import * as Effect14 from "effect/Effect";
1728
+ import * as Effect15 from "effect/Effect";
1208
1729
  var branches = (node) => (Array.isArray(node["children"]) ? node["children"] : []).filter((child) => typeof child === "object" && child !== null);
1209
1730
  var osdLeaves = (tree) => {
1210
1731
  const root = tree["root"];
@@ -1230,25 +1751,29 @@ var osdAttributes = (leaf, props) => ({
1230
1751
  status: text(leaf["status"]),
1231
1752
  total_space: num(leaf["total_space"], 0)
1232
1753
  });
1233
- var readOsd = (props) => pve(props.target, "read", "GET", `nodes/${props.node}/ceph/osd`).pipe(Effect14.map((t) => {
1754
+ var readOsd = (props) => pve(props.target, "read", "GET", `nodes/${props.node}/ceph/osd`).pipe(Effect15.map((t) => {
1234
1755
  const leaf = t === undefined ? undefined : findOsd(t, props.osdid);
1235
1756
  return leaf === undefined ? undefined : osdAttributes(leaf, props);
1236
1757
  }));
1237
1758
 
1238
1759
  // src/proxmox/ceph-osd-write.ts
1239
- import * as Effect15 from "effect/Effect";
1760
+ import * as Effect16 from "effect/Effect";
1761
+ var OSD_CREATE_ENDPOINT = "pve:POST /nodes/{node}/ceph/osd";
1240
1762
  var describe = (props) => `osd.${String(props.osdid)} on ${props.node}`;
1241
- var createOsd = Effect15.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) {
1242
1768
  if (news.dev === undefined) {
1243
- return yield* Effect15.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."));
1244
1770
  }
1245
- yield* pve(news.target, "provision", "POST", `nodes/${news.node}/ceph/osd`, {
1246
- dev: news.dev,
1247
- ...news.device_class === undefined ? {} : { "crush-device-class": news.device_class }
1248
- });
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);
1249
1774
  const created = yield* readOsd(news);
1250
1775
  if (created === undefined) {
1251
- return yield* Effect15.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."));
1252
1777
  }
1253
1778
  return created;
1254
1779
  });
@@ -1261,11 +1786,11 @@ var ProxmoxCephOsd = Resource7("Proxmox.CephOsd", {
1261
1786
  var settled = (live, props) => (props.host === undefined || props.host === live.host) && (props.device_class === undefined || props.device_class === live.device_class);
1262
1787
  var describe2 = (props) => `osd.${String(props.osdid)} (read via nodes/${props.node}/ceph/osd)`;
1263
1788
  var handlers5 = {
1264
- list: () => Effect16.succeed([]),
1265
- read: Effect16.fn(function* ({ olds }) {
1789
+ list: () => Effect17.succeed([]),
1790
+ read: Effect17.fn(function* ({ olds }) {
1266
1791
  return yield* readOsd(olds);
1267
1792
  }),
1268
- diff: Effect16.fn(function* ({
1793
+ diff: Effect17.fn(function* ({
1269
1794
  news,
1270
1795
  output
1271
1796
  }) {
@@ -1278,25 +1803,25 @@ var handlers5 = {
1278
1803
  return { action: "update" };
1279
1804
  return settled(live, news) ? { action: "noop" } : { action: "update" };
1280
1805
  }),
1281
- reconcile: Effect16.fn(function* ({ news }) {
1806
+ reconcile: Effect17.fn(function* ({ news }) {
1282
1807
  const live = yield* readOsd(news);
1283
1808
  if (live === undefined) {
1284
1809
  return yield* createOsd(news);
1285
1810
  }
1286
1811
  if (!settled(live, news)) {
1287
- return yield* Effect16.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."));
1288
1813
  }
1289
1814
  return live;
1290
1815
  }),
1291
- delete: Effect16.fn(function* ({ olds }) {
1816
+ delete: Effect17.fn(function* ({ olds }) {
1292
1817
  yield* destroyOsd(olds);
1293
1818
  })
1294
1819
  };
1295
- var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect16.succeed(ProxmoxCephOsd.Provider.of(handlers5)));
1820
+ var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect17.succeed(ProxmoxCephOsd.Provider.of(handlers5)));
1296
1821
  // src/proxmox/ceph-pool.ts
1297
1822
  import { Resource as Resource8 } from "alchemy";
1298
1823
  import * as Provider8 from "alchemy/Provider";
1299
- import * as Effect18 from "effect/Effect";
1824
+ import * as Effect19 from "effect/Effect";
1300
1825
 
1301
1826
  // src/proxmox/ceph-pool-form.ts
1302
1827
  var object = (props) => `nodes/${props.node}/ceph/pool/${props.name}`;
@@ -1325,14 +1850,14 @@ var createBody = (props) => ({
1325
1850
  });
1326
1851
 
1327
1852
  // src/proxmox/ceph-pool-settle.ts
1328
- import * as Effect17 from "effect/Effect";
1329
- var confirmAbsent = (props, collection2, describe3) => pve(props.target, "read", "GET", collection2).pipe(Effect17.flatMap((rows) => (rows ?? []).some((row) => row.pool_name === props.name) ? Effect17.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.")) : Effect17.void));
1330
- var settle2 = (props, read, done) => Effect17.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* () {
1331
1856
  for (let attempt = 0;attempt < 30; attempt += 1) {
1332
1857
  const live = yield* read(props);
1333
1858
  if (done(live))
1334
1859
  return live;
1335
- yield* Effect17.sleep("2 seconds");
1860
+ yield* Effect18.sleep("2 seconds");
1336
1861
  }
1337
1862
  return yield* read(props);
1338
1863
  });
@@ -1365,38 +1890,44 @@ var spec = {
1365
1890
  },
1366
1891
  collection,
1367
1892
  createForm: createBody,
1893
+ endpoint: {
1894
+ create: "pve:POST /nodes/{node}/ceph/pool",
1895
+ update: "pve:PUT /nodes/{node}/ceph/pool/{name}"
1896
+ },
1368
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),
1369
1898
  path: (props) => `${object(props)}/status?verbose=1`,
1370
1899
  updateForm: updateBody
1371
1900
  };
1372
1901
  var ops4 = pveOperations(spec);
1373
- var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect18.succeed(ProxmoxCephPool.Provider.of({
1374
- list: () => Effect18.succeed([]),
1902
+ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect19.succeed(ProxmoxCephPool.Provider.of({
1903
+ list: () => Effect19.succeed([]),
1375
1904
  read: ({ olds }) => ops4.read(olds),
1376
1905
  diff: ({ news, output }) => ops4.diff(news, output),
1377
- reconcile: Effect18.fn(function* ({ news }) {
1906
+ reconcile: Effect19.fn(function* ({ news }) {
1378
1907
  const live = yield* ops4.read(news);
1379
1908
  let upid;
1380
1909
  if (live === undefined) {
1910
+ yield* ops4.guardCreate(news, true);
1381
1911
  yield* confirmAbsent(news, spec.collection(news), object(news));
1382
1912
  upid = yield* pve(news.target, "provision", "POST", collection(news), createBody(news));
1383
1913
  } else {
1384
1914
  const form = formToSend(spec.matches, live, news, updateBody(news));
1385
1915
  if (form !== undefined) {
1916
+ yield* ops4.guardUpdate(news);
1386
1917
  upid = yield* pve(news.target, "provision", "PUT", object(news), form);
1387
1918
  }
1388
1919
  }
1389
1920
  const after = yield* settle2(news, ops4.read, (row) => row !== undefined && spec.matches(row, news));
1390
1921
  if (after === undefined || !spec.matches(after, news)) {
1391
- return yield* Effect18.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."));
1392
1923
  }
1393
1924
  return after;
1394
1925
  }),
1395
- delete: Effect18.fn(function* ({ olds }) {
1926
+ delete: Effect19.fn(function* ({ olds }) {
1396
1927
  yield* pve(olds.target, "provision", "DELETE", object(olds));
1397
1928
  const left = yield* settle2(olds, ops4.read, (row) => row === undefined);
1398
1929
  if (left !== undefined) {
1399
- return yield* Effect18.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."));
1400
1931
  }
1401
1932
  })
1402
1933
  })));
@@ -1404,7 +1935,7 @@ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect18.s
1404
1935
  import { Resource as Resource9 } from "alchemy";
1405
1936
  import { isResolved as isResolved5 } from "alchemy/Diff";
1406
1937
  import * as Provider9 from "alchemy/Provider";
1407
- import * as Effect19 from "effect/Effect";
1938
+ import * as Effect20 from "effect/Effect";
1408
1939
 
1409
1940
  // src/proxmox/firewall-alias-form.ts
1410
1941
  var fold = (name) => name.trim().toLowerCase();
@@ -1444,9 +1975,9 @@ var handlers6 = pveHandlers({
1444
1975
  path: (props) => `cluster/firewall/aliases/${props.name}`,
1445
1976
  updateForm: body
1446
1977
  });
1447
- var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect19.succeed(ProxmoxFirewallAlias.Provider.of({
1978
+ var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect20.succeed(ProxmoxFirewallAlias.Provider.of({
1448
1979
  ...handlers6,
1449
- diff: Effect19.fn(function* ({ news, output }) {
1980
+ diff: Effect20.fn(function* ({ news, output }) {
1450
1981
  if (output !== undefined && isResolved5(news) && fold(news.name) !== fold(output.name)) {
1451
1982
  return { action: "replace" };
1452
1983
  }
@@ -1456,7 +1987,7 @@ var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias,
1456
1987
  // src/proxmox/group.ts
1457
1988
  import { Resource as Resource10 } from "alchemy";
1458
1989
  import * as Provider10 from "alchemy/Provider";
1459
- import * as Effect20 from "effect/Effect";
1990
+ import * as Effect21 from "effect/Effect";
1460
1991
  var ProxmoxGroup = Resource10("Proxmox.Group", {
1461
1992
  defaultRemovalPolicy: "retain"
1462
1993
  });
@@ -1481,11 +2012,11 @@ var handlers7 = pveHandlers({
1481
2012
  path: (props) => `access/groups/${props.groupid}`,
1482
2013
  updateForm: (props) => ({ comment: storedComment(props.comment) })
1483
2014
  });
1484
- var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect20.succeed(ProxmoxGroup.Provider.of(handlers7)));
2015
+ var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect21.succeed(ProxmoxGroup.Provider.of(handlers7)));
1485
2016
  // src/proxmox/ha-resource.ts
1486
2017
  import { Resource as Resource11 } from "alchemy";
1487
2018
  import * as Provider11 from "alchemy/Provider";
1488
- import * as Effect21 from "effect/Effect";
2019
+ import * as Effect22 from "effect/Effect";
1489
2020
  var ProxmoxHaResource = Resource11("Proxmox.HaResource");
1490
2021
  var kind = (sid) => sid.split(":")[0] ?? "";
1491
2022
  var shape3 = (props) => ({
@@ -1513,11 +2044,11 @@ var handlers8 = pveHandlers({
1513
2044
  path: (props) => `cluster/ha/resources/${props.sid}`,
1514
2045
  updateForm: shape3
1515
2046
  });
1516
- var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect21.succeed(ProxmoxHaResource.Provider.of(handlers8)));
2047
+ var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect22.succeed(ProxmoxHaResource.Provider.of(handlers8)));
1517
2048
  // src/proxmox/ha-rule.ts
1518
2049
  import { Resource as Resource12 } from "alchemy";
1519
2050
  import * as Provider12 from "alchemy/Provider";
1520
- import * as Effect22 from "effect/Effect";
2051
+ import * as Effect23 from "effect/Effect";
1521
2052
 
1522
2053
  // src/proxmox/ha-rule-form.ts
1523
2054
  var nodeList = (value) => {
@@ -1594,43 +2125,43 @@ var handlers9 = pveHandlers({
1594
2125
  return withClears(fields, clear);
1595
2126
  }
1596
2127
  });
1597
- var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect22.succeed(ProxmoxHaRule.Provider.of(handlers9)));
2128
+ var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect23.succeed(ProxmoxHaRule.Provider.of(handlers9)));
1598
2129
  // src/proxmox/lxc.ts
1599
2130
  import { Resource as Resource13 } from "alchemy";
1600
2131
  import { isResolved as isResolved6 } from "alchemy/Diff";
1601
2132
  import * as Provider13 from "alchemy/Provider";
1602
- import * as Effect32 from "effect/Effect";
2133
+ import * as Effect33 from "effect/Effect";
1603
2134
 
1604
2135
  // src/ownership/adopt.ts
1605
2136
  import { AdoptPolicy } from "alchemy/AdoptPolicy";
1606
2137
  import { AlchemyContext } from "alchemy/AlchemyContext";
1607
2138
  import { Stack as Stack3 } from "alchemy/Stack";
1608
- import * as Effect26 from "effect/Effect";
2139
+ import * as Effect27 from "effect/Effect";
1609
2140
  import * as Option5 from "effect/Option";
1610
2141
 
1611
2142
  // src/ownership/resume.ts
1612
2143
  import { Unowned } from "alchemy/AdoptPolicy";
1613
2144
  import { Artifacts } from "alchemy/Artifacts";
1614
- import * as Effect23 from "effect/Effect";
2145
+ import * as Effect24 from "effect/Effect";
1615
2146
  import * as Option2 from "effect/Option";
1616
2147
  var PROVEN = "homeflare/ownership/resumes";
1617
2148
  var UNFINISHED = "homeflare/ownership/unfinished";
1618
- var note = (key, instanceId) => Effect23.gen(function* () {
1619
- const bag = yield* Effect23.serviceOption(Artifacts);
2149
+ var note = (key, instanceId) => Effect24.gen(function* () {
2150
+ const bag = yield* Effect24.serviceOption(Artifacts);
1620
2151
  if (Option2.isSome(bag))
1621
2152
  yield* bag.value.set(key, instanceId);
1622
2153
  });
1623
- var noted = (key, instanceId) => Effect23.gen(function* () {
1624
- const bag = yield* Effect23.serviceOption(Artifacts);
2154
+ var noted = (key, instanceId) => Effect24.gen(function* () {
2155
+ const bag = yield* Effect24.serviceOption(Artifacts);
1625
2156
  if (Option2.isNone(bag))
1626
2157
  return false;
1627
2158
  return (yield* bag.value.get(key)) === instanceId;
1628
2159
  });
1629
- var noteUnfinished = (instanceId) => Effect23.as(note(UNFINISHED, instanceId), undefined);
1630
- var noteResume = (instanceId, recovered) => Effect23.gen(function* () {
2160
+ var noteUnfinished = (instanceId) => Effect24.as(note(UNFINISHED, instanceId), undefined);
2161
+ var noteResume = (instanceId, recovered) => Effect24.gen(function* () {
1631
2162
  yield* noteUnfinished(instanceId);
1632
- const unproven = () => Effect23.succeed(undefined);
1633
- const found = yield* recovered.pipe(Effect23.catch(unproven), Effect23.catchDefect(unproven));
2163
+ const unproven = () => Effect24.succeed(undefined);
2164
+ const found = yield* recovered.pipe(Effect24.catch(unproven), Effect24.catchDefect(unproven));
1634
2165
  if (found === undefined || found === null || Unowned.is(found))
1635
2166
  return;
1636
2167
  yield* note(PROVEN, instanceId);
@@ -1641,7 +2172,7 @@ var provingResumes = (service) => {
1641
2172
  const { diff, read } = service;
1642
2173
  if (diff === undefined || read === undefined)
1643
2174
  return service;
1644
- const proving = (input) => Effect23.gen(function* () {
2175
+ const proving = (input) => Effect24.gen(function* () {
1645
2176
  if (input.output === undefined) {
1646
2177
  yield* noteResume(input.instanceId, read({ ...input, output: undefined }));
1647
2178
  }
@@ -1653,12 +2184,12 @@ var provingResumes = (service) => {
1653
2184
  // src/ownership/rows.ts
1654
2185
  import { Stack as Stack2 } from "alchemy/Stack";
1655
2186
  import { State, isActionState } from "alchemy/State/State";
1656
- import * as Effect25 from "effect/Effect";
2187
+ import * as Effect26 from "effect/Effect";
1657
2188
  import * as Option4 from "effect/Option";
1658
2189
 
1659
2190
  // src/ownership/whole.ts
1660
2191
  import { Stack } from "alchemy/Stack";
1661
- import * as Effect24 from "effect/Effect";
2192
+ import * as Effect25 from "effect/Effect";
1662
2193
  import * as Option3 from "effect/Option";
1663
2194
  var absent = (value) => value === undefined || value === null;
1664
2195
  var isPlainObject = (value) => {
@@ -1684,22 +2215,22 @@ var carries = (declared, recorded) => {
1684
2215
  }
1685
2216
  return true;
1686
2217
  };
1687
- var wholeDeclaration = (fqn, props) => Effect24.map(Effect24.serviceOption(Stack), (stack) => {
2218
+ var wholeDeclaration = (fqn, props) => Effect25.map(Effect25.serviceOption(Stack), (stack) => {
1688
2219
  const declared = Option3.isSome(stack) ? stack.value.resources[fqn] : undefined;
1689
2220
  return declared !== undefined && carries(declared.Props, props);
1690
2221
  });
1691
2222
 
1692
2223
  // src/ownership/rows.ts
1693
- var storeOf = Effect25.gen(function* () {
1694
- const stack = yield* Effect25.serviceOption(Stack2);
1695
- const state = yield* Effect25.serviceOption(State);
2224
+ var storeOf = Effect26.gen(function* () {
2225
+ const stack = yield* Effect26.serviceOption(Stack2);
2226
+ const state = yield* Effect26.serviceOption(State);
1696
2227
  if (Option4.isNone(stack) || Option4.isNone(state))
1697
2228
  return;
1698
2229
  const store = yield* state.value;
1699
2230
  const where = { stack: stack.value.name, stage: stack.value.stage };
1700
2231
  return { resources: stack.value.resources, store, where };
1701
2232
  });
1702
- var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect25.orElseSucceed(() => {
2233
+ var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect26.orElseSucceed(() => {
1703
2234
  return;
1704
2235
  }));
1705
2236
  var generationOf = (row, instanceId) => {
@@ -1712,7 +2243,7 @@ var generationOf = (row, instanceId) => {
1712
2243
  }
1713
2244
  return;
1714
2245
  };
1715
- var recordedGeneration = (fqn, instanceId) => Effect25.gen(function* () {
2246
+ var recordedGeneration = (fqn, instanceId) => Effect26.gen(function* () {
1716
2247
  const found = yield* storeOf;
1717
2248
  if (found === undefined)
1718
2249
  return;
@@ -1723,14 +2254,14 @@ var recordedGeneration = (fqn, instanceId) => Effect25.gen(function* () {
1723
2254
  }
1724
2255
  return;
1725
2256
  });
1726
- var recordedInstance = (fqn, instanceId) => Effect25.gen(function* () {
2257
+ var recordedInstance = (fqn, instanceId) => Effect26.gen(function* () {
1727
2258
  const generation = yield* recordedGeneration(fqn, instanceId);
1728
2259
  if (generation === undefined)
1729
2260
  return "absent";
1730
2261
  return (yield* wholeDeclaration(fqn, generation.props)) ? "whole" : "partial";
1731
2262
  });
1732
- var isCreate = (fqn, instanceId) => Effect25.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
1733
- var forgetRefusedCreate = (fqn, instanceId) => Effect25.gen(function* () {
2263
+ var isCreate = (fqn, instanceId) => Effect26.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
2264
+ var forgetRefusedCreate = (fqn, instanceId) => Effect26.gen(function* () {
1734
2265
  const found = yield* storeOf;
1735
2266
  if (found === undefined)
1736
2267
  return;
@@ -1739,32 +2270,32 @@ var forgetRefusedCreate = (fqn, instanceId) => Effect25.gen(function* () {
1739
2270
  if (mine?.status !== "creating" || mine.instanceId !== instanceId || mine.attr !== undefined) {
1740
2271
  return;
1741
2272
  }
1742
- yield* found.store.delete({ ...found.where, fqn }).pipe(Effect25.ignore);
2273
+ yield* found.store.delete({ ...found.where, fqn }).pipe(Effect26.ignore);
1743
2274
  });
1744
2275
 
1745
2276
  // src/ownership/adopt.ts
1746
- var adoptEnabled = (fqn) => Effect26.gen(function* () {
1747
- const stack = yield* Effect26.serviceOption(Stack3);
2277
+ var adoptEnabled = (fqn) => Effect27.gen(function* () {
2278
+ const stack = yield* Effect27.serviceOption(Stack3);
1748
2279
  const scoped = Option5.isSome(stack) ? stack.value.resources[fqn]?.Adopt : undefined;
1749
2280
  if (scoped !== undefined)
1750
2281
  return scoped;
1751
- const policy = yield* Effect26.serviceOption(AdoptPolicy);
2282
+ const policy = yield* Effect27.serviceOption(AdoptPolicy);
1752
2283
  if (Option5.isSome(policy))
1753
2284
  return policy.value;
1754
- const context = yield* Effect26.serviceOption(AlchemyContext);
2285
+ const context = yield* Effect27.serviceOption(AlchemyContext);
1755
2286
  return Option5.isSome(context) ? context.value.adopt : false;
1756
2287
  });
1757
- var adoptable = (owner) => Effect26.gen(function* () {
2288
+ var adoptable = (owner) => Effect27.gen(function* () {
1758
2289
  if (yield* isCreate(owner.fqn, owner.instanceId))
1759
2290
  return true;
1760
2291
  return yield* unfinished(owner.instanceId);
1761
2292
  });
1762
- var adoptsAtApply = (owner) => Effect26.gen(function* () {
2293
+ var adoptsAtApply = (owner) => Effect27.gen(function* () {
1763
2294
  if (!(yield* adoptEnabled(owner.fqn)))
1764
2295
  return false;
1765
2296
  return yield* adoptable(owner);
1766
2297
  });
1767
- var refuseTakeover = (owner, what) => Effect26.gen(function* () {
2298
+ var refuseTakeover = (owner, what) => Effect27.gen(function* () {
1768
2299
  if (owner.output !== undefined)
1769
2300
  return;
1770
2301
  if (yield* resumes(owner.instanceId))
@@ -1774,25 +2305,25 @@ var refuseTakeover = (owner, what) => Effect26.gen(function* () {
1774
2305
  return;
1775
2306
  yield* forgetRefusedCreate(owner.fqn, owner.instanceId);
1776
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.";
1777
- return yield* Effect26.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}`));
1778
2309
  });
1779
2310
  var claimFor = (owner) => (what) => refuseTakeover(owner, what);
1780
2311
 
1781
2312
  // src/ownership/probe.ts
1782
2313
  import { Unowned as Unowned2 } from "alchemy/AdoptPolicy";
1783
- import * as Effect27 from "effect/Effect";
1784
- var provenOurs = (ask, settled2) => Effect27.gen(function* () {
2314
+ import * as Effect28 from "effect/Effect";
2315
+ var provenOurs = (ask, settled2) => Effect28.gen(function* () {
1785
2316
  const recorded = yield* recordedInstance(ask.fqn, ask.instanceId);
1786
2317
  if (recorded === "absent")
1787
2318
  return false;
1788
2319
  if (recorded === "partial") {
1789
- yield* Effect27.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");
1790
2321
  return false;
1791
2322
  }
1792
- const unproven = (reason) => Effect27.as(Effect27.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);
1793
- return yield* settled2.pipe(Effect27.catch(unproven), Effect27.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));
1794
2325
  });
1795
- var ownedRead = (ask, found, settled2) => Effect27.gen(function* () {
2326
+ var ownedRead = (ask, found, settled2) => Effect28.gen(function* () {
1796
2327
  if (found === undefined || ask.output !== undefined)
1797
2328
  return found;
1798
2329
  return (yield* provenOurs(ask, settled2)) ? found : Unowned2(found);
@@ -2247,11 +2778,11 @@ var identityRefusals = (news, olds, output) => {
2247
2778
  };
2248
2779
 
2249
2780
  // src/proxmox/lxc-adoption.ts
2250
- import * as Effect31 from "effect/Effect";
2781
+ import * as Effect32 from "effect/Effect";
2251
2782
 
2252
2783
  // src/ownership/adopting.ts
2253
- import * as Effect28 from "effect/Effect";
2254
- var adopting = (owner, settled2) => Effect28.gen(function* () {
2784
+ import * as Effect29 from "effect/Effect";
2785
+ var adopting = (owner, settled2) => Effect29.gen(function* () {
2255
2786
  if (owner.output === undefined)
2256
2787
  return false;
2257
2788
  const generation = yield* recordedGeneration(owner.fqn, owner.instanceId);
@@ -2263,11 +2794,11 @@ var adopting = (owner, settled2) => Effect28.gen(function* () {
2263
2794
  });
2264
2795
 
2265
2796
  // src/proxmox/lxc-lifecycle.ts
2266
- import * as Effect30 from "effect/Effect";
2797
+ import * as Effect31 from "effect/Effect";
2267
2798
 
2268
2799
  // src/proxmox/network-apply-read.ts
2269
- import * as Effect29 from "effect/Effect";
2270
- var stagedDiff = (target, node) => Effect29.gen(function* () {
2800
+ import * as Effect30 from "effect/Effect";
2801
+ var stagedDiff = (target, node) => Effect30.gen(function* () {
2271
2802
  const path = `nodes/${node}/network`;
2272
2803
  const credential = yield* leased(target, "read");
2273
2804
  const envelope = yield* pveEnvelopeWith(target, credential, "GET", path);
@@ -2280,8 +2811,8 @@ var pendingLines = (diff) => {
2280
2811
  `).filter((line) => (line.startsWith("+") || line.startsWith("-")) && !line.startsWith("+++") && !line.startsWith("---")).length;
2281
2812
  return Math.max(changed, 1);
2282
2813
  };
2283
- var pendingCount = (target, node) => stagedDiff(target, node).pipe(Effect29.map(pendingLines));
2284
- var clusterHealth = (target) => pve(target, "read", "GET", "cluster/status").pipe(Effect29.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) => {
2285
2816
  const all = rows ?? [];
2286
2817
  const cluster = all.find((row) => row.type === "cluster");
2287
2818
  return {
@@ -2289,21 +2820,21 @@ var clusterHealth = (target) => pve(target, "read", "GET", "cluster/status").pip
2289
2820
  quorate: cluster === undefined ? true : bool(cluster.quorate)
2290
2821
  };
2291
2822
  }));
2292
- var degradedReason = (target) => clusterHealth(target).pipe(Effect29.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(", ")}]`));
2293
2824
  var UNREACHABLE = "the task could not be read -- the node stopped answering, or this lease cannot see it";
2294
2825
  var STILL_RUNNING = "still running when this provider stopped waiting";
2295
2826
  var ATTEMPTS = 30;
2296
- var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect29.gen(function* () {
2827
+ var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect30.gen(function* () {
2297
2828
  const path = `nodes/${node}/tasks/${upid}/status`;
2298
2829
  for (let attempt = 0;attempt < attempts; attempt += 1) {
2299
- const status = yield* pveWith(target, credential, "GET", path).pipe(Effect29.orElseSucceed(() => {
2830
+ const status = yield* pveWith(target, credential, "GET", path).pipe(Effect30.orElseSucceed(() => {
2300
2831
  return;
2301
2832
  }));
2302
2833
  if (status === undefined)
2303
2834
  return UNREACHABLE;
2304
2835
  if (status.status === "stopped")
2305
2836
  return text(status.exitstatus, "stopped with no exitstatus");
2306
- yield* Effect29.sleep("1 second");
2837
+ yield* Effect30.sleep("1 second");
2307
2838
  }
2308
2839
  return STILL_RUNNING;
2309
2840
  });
@@ -2313,20 +2844,25 @@ class LxcRefusedError extends Error {
2313
2844
  name = "LxcRefusedError";
2314
2845
  }
2315
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
+ };
2316
2852
  var CREATE_POLLS = 180;
2317
2853
  var TASK_POLLS = 60;
2318
2854
  var isServerError = (error) => error instanceof PveError && error.status === 500;
2319
- var readLive = (where) => Effect30.gen(function* () {
2320
- const answer = yield* pve(where.target, "read", "GET", `${guestPath(where)}/config`).pipe(Effect30.map((data) => ({ data, error: undefined })), Effect30.catchIf(isServerError, (error) => Effect30.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 })));
2321
2857
  if (answer.data !== undefined && answer.data !== null)
2322
2858
  return answer.data;
2323
2859
  const rows = yield* pve(where.target, "read", "GET", "cluster/resources?type=vm");
2324
2860
  const found = (rows ?? []).find((row) => Number(row.vmid) === where.vmid);
2325
2861
  if (found !== undefined && found.node === where.node && found.type === "lxc") {
2326
- return yield* Effect30.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.`));
2327
2863
  }
2328
2864
  if (found !== undefined) {
2329
- return yield* Effect30.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."));
2330
2866
  }
2331
2867
  return;
2332
2868
  });
@@ -2336,54 +2872,61 @@ var attributesOf = (where, live) => ({
2336
2872
  rawKeys: rawKeysOf(live),
2337
2873
  vmid: where.vmid
2338
2874
  });
2339
- var task = (where, method, path, what, polls, form) => Effect30.gen(function* () {
2875
+ var task = (where, method, path, what, polls, form) => Effect31.gen(function* () {
2340
2876
  const credential = yield* mint(where.target, "provision");
2341
2877
  const upid = text(yield* pveWith(where.target, credential, method, path, form));
2342
2878
  if (upid === "") {
2343
- return yield* Effect30.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.`));
2344
2880
  }
2345
2881
  const exit = yield* awaitTask(where.target, credential, where.node, upid, polls);
2346
2882
  if (exit !== "OK") {
2347
- return yield* Effect30.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.`));
2348
2884
  }
2349
2885
  });
2350
- var createGuest = (props) => task(props, "POST", `nodes/${props.node}/lxc`, `create CT ${String(props.vmid)}`, CREATE_POLLS, createForm3(props));
2351
- var updateGuest = (props, change, digest) => Effect30.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* () {
2352
2892
  if (Object.keys(change.put).length > 0 || change.clear.length > 0) {
2353
2893
  const form = withClears({ ...change.put, ...digest === "" ? {} : { digest } }, change.clear);
2894
+ yield* guardForm(LXC_ENDPOINTS.update, form, false);
2354
2895
  yield* pve(props.target, "provision", "PUT", `${guestPath(props)}/config`, form);
2355
2896
  }
2356
2897
  for (const grow of change.resize) {
2357
- 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);
2358
2901
  }
2359
2902
  });
2360
- var destroyGuest = (where, declared) => Effect30.gen(function* () {
2903
+ var destroyGuest = (where, declared) => Effect31.gen(function* () {
2361
2904
  const live = yield* readLive(where);
2362
2905
  if (live === undefined)
2363
2906
  return;
2364
2907
  const drift = judge(declared, live).drift;
2365
2908
  if (drift.length > 0) {
2366
- return yield* Effect30.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."));
2367
2910
  }
2368
2911
  yield* task(where, "DELETE", guestPath(where), `destroy CT ${String(where.vmid)}`, TASK_POLLS);
2369
2912
  });
2370
2913
 
2371
2914
  // src/proxmox/lxc-adoption.ts
2372
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.";
2373
- var refuseAdoptedDrift = (owner, props, live, change) => Effect31.gen(function* () {
2916
+ var refuseAdoptedDrift = (owner, props, live, change) => Effect32.gen(function* () {
2374
2917
  if (change.drift.length === 0)
2375
2918
  return;
2376
- const settled2 = (recorded) => Effect31.sync(() => judge(recorded, live).drift.length === 0);
2919
+ const settled2 = (recorded) => Effect32.sync(() => judge(recorded, live).drift.length === 0);
2377
2920
  if (!(yield* adopting(owner, settled2)))
2378
2921
  return;
2379
- return yield* Effect31.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
2922
+ return yield* Effect32.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
2380
2923
  });
2381
2924
 
2382
2925
  // src/proxmox/lxc.ts
2383
2926
  var ProxmoxLxc = Resource13("Proxmox.Lxc", { defaultRemovalPolicy: "retain" });
2384
- var refused = (reasons) => Effect32.fail(new LxcRefusedError(reasons.join(`
2927
+ var refused = (reasons) => Effect33.fail(new LxcRefusedError(reasons.join(`
2385
2928
  `)));
2386
- var diff = (owner, news, olds) => Effect32.gen(function* () {
2929
+ var diff = (owner, news, olds) => Effect33.gen(function* () {
2387
2930
  const { output } = owner;
2388
2931
  const identity2 = identityRefusals(news, olds, output);
2389
2932
  if (identity2.length > 0)
@@ -2397,7 +2940,7 @@ var diff = (owner, news, olds) => Effect32.gen(function* () {
2397
2940
  const refusals = createRefusals(news);
2398
2941
  if (refusals.length > 0)
2399
2942
  return yield* refused(refusals);
2400
- yield* Effect32.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.");
2401
2944
  return { action: "update" };
2402
2945
  }
2403
2946
  const change = judge(news, live);
@@ -2408,10 +2951,10 @@ var diff = (owner, news, olds) => Effect32.gen(function* () {
2408
2951
  if (change.drift.length === 0 && !moved)
2409
2952
  return { action: "noop" };
2410
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.";
2411
- yield* Effect32.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
2954
+ yield* Effect33.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
2412
2955
  return { action: "update" };
2413
2956
  });
2414
- var reconcile = (owner, news) => Effect32.gen(function* () {
2957
+ var reconcile = (owner, news) => Effect33.gen(function* () {
2415
2958
  const { output } = owner;
2416
2959
  const identity2 = identityRefusals(news, news, output);
2417
2960
  if (identity2.length > 0)
@@ -2457,12 +3000,12 @@ var whereOf = (olds, output) => ({
2457
3000
  target: olds.target,
2458
3001
  vmid: output?.vmid ?? olds.vmid
2459
3002
  });
2460
- var read = (owner, olds) => Effect32.gen(function* () {
3003
+ var read = (owner, olds) => Effect33.gen(function* () {
2461
3004
  const where = whereOf(olds, owner.output);
2462
3005
  const live = yield* readLive(where);
2463
3006
  if (live === undefined)
2464
3007
  return;
2465
- const settled2 = Effect32.sync(() => judge(olds, live).drift.length === 0);
3008
+ const settled2 = Effect33.sync(() => judge(olds, live).drift.length === 0);
2466
3009
  return yield* ownedRead(owner, attributesOf(where, live), settled2);
2467
3010
  });
2468
3011
  var handlers10 = {
@@ -2474,7 +3017,7 @@ var handlers10 = {
2474
3017
  olds,
2475
3018
  output
2476
3019
  }) => diff({ fqn, instanceId, output }, news, olds),
2477
- list: () => Effect32.succeed([]),
3020
+ list: () => Effect33.succeed([]),
2478
3021
  read: ({
2479
3022
  fqn,
2480
3023
  instanceId,
@@ -2488,11 +3031,11 @@ var handlers10 = {
2488
3031
  output
2489
3032
  }) => reconcile({ fqn, instanceId, output }, news)
2490
3033
  };
2491
- var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect32.succeed(ProxmoxLxc.Provider.of(handlers10)).pipe(Effect32.map(provingResumes)));
3034
+ var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect33.succeed(ProxmoxLxc.Provider.of(handlers10)).pipe(Effect33.map(provingResumes)));
2492
3035
  // src/proxmox/metric-server.ts
2493
3036
  import { Resource as Resource14 } from "alchemy";
2494
3037
  import * as Provider14 from "alchemy/Provider";
2495
- import * as Effect33 from "effect/Effect";
3038
+ import * as Effect34 from "effect/Effect";
2496
3039
 
2497
3040
  // src/proxmox/metric-server-form.ts
2498
3041
  var UNSET2 = -1;
@@ -2549,6 +3092,7 @@ var update = (props) => {
2549
3092
  const clear = Object.entries(optional2(props)).filter(([, value]) => value === undefined).map(([option]) => option);
2550
3093
  return withClears(body3(props), clear);
2551
3094
  };
3095
+ var createBody2 = (props) => ({ ...body3(props), type: props.type });
2552
3096
 
2553
3097
  // src/proxmox/metric-server-otel.ts
2554
3098
  var otelAttributes = (live) => ({
@@ -2595,27 +3139,39 @@ var handlers11 = pveHandlers({
2595
3139
  };
2596
3140
  },
2597
3141
  collection: (props) => `cluster/metrics/server/${props.id}`,
2598
- 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
+ },
2599
3147
  matches: (attributes, props) => attributes.server === props.server && attributes.port === props.port && attributes.disable === (props.disable === true) && matchesType(attributes, props),
2600
3148
  path: (props) => `cluster/metrics/server/${props.id}`,
2601
3149
  updateForm: update
2602
3150
  });
2603
- var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect33.succeed(ProxmoxMetricServer.Provider.of(handlers11)));
3151
+ var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect34.succeed(ProxmoxMetricServer.Provider.of(handlers11)));
2604
3152
  // src/proxmox/network-apply.ts
2605
3153
  import { Resource as Resource15 } from "alchemy";
2606
3154
  import { isResolved as isResolved7 } from "alchemy/Diff";
2607
3155
  import * as Provider15 from "alchemy/Provider";
2608
- import * as Effect34 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
2609
3165
  var ProxmoxNetworkApply = Resource15("Proxmox.NetworkApply");
2610
- var read2 = (props) => pendingCount(props.target, props.node).pipe(Effect34.map((pending) => ({ node: props.node, pending })));
2611
- var diff2 = (news) => Effect34.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* () {
2612
3168
  if (!isResolved7(news))
2613
3169
  return;
2614
3170
  const { pending } = yield* read2(news);
2615
3171
  return pending === 0 ? { action: "noop" } : { action: "update" };
2616
3172
  });
2617
- var refuse = (node, why) => Effect34.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
2618
- var apply = (props) => Effect34.gen(function* () {
3173
+ var refuse = (node, why) => Effect35.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
3174
+ var apply = (props) => Effect35.gen(function* () {
2619
3175
  const node = props.node;
2620
3176
  const staged = yield* pendingCount(props.target, node);
2621
3177
  if (staged === 0)
@@ -2624,6 +3180,7 @@ var apply = (props) => Effect34.gen(function* () {
2624
3180
  if (before !== undefined) {
2625
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.");
2626
3182
  }
3183
+ yield* guardNetworkApply;
2627
3184
  const credential = yield* mint(props.target, "provision");
2628
3185
  const upid = yield* pveWith(props.target, credential, "PUT", `nodes/${node}/network`);
2629
3186
  if (upid === undefined) {
@@ -2644,17 +3201,17 @@ var apply = (props) => Effect34.gen(function* () {
2644
3201
  return { node, pending: left };
2645
3202
  });
2646
3203
  var handlers12 = {
2647
- delete: () => Effect34.void,
3204
+ delete: () => Effect35.void,
2648
3205
  diff: ({ news }) => diff2(news),
2649
- list: () => Effect34.succeed([]),
3206
+ list: () => Effect35.succeed([]),
2650
3207
  read: ({ olds }) => read2(olds),
2651
3208
  reconcile: ({ news }) => apply(news)
2652
3209
  };
2653
- var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect34.succeed(ProxmoxNetworkApply.Provider.of(handlers12)));
3210
+ var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect35.succeed(ProxmoxNetworkApply.Provider.of(handlers12)));
2654
3211
  // src/proxmox/node-network.ts
2655
3212
  import { Resource as Resource16 } from "alchemy";
2656
3213
  import * as Provider16 from "alchemy/Provider";
2657
- import * as Effect35 from "effect/Effect";
3214
+ import * as Effect36 from "effect/Effect";
2658
3215
 
2659
3216
  // src/proxmox/node-network-form.ts
2660
3217
  var UNSET3 = -1;
@@ -2681,6 +3238,10 @@ var body4 = (props) => ({
2681
3238
  ...field3("vlan-raw-device", props["vlan-raw-device"]),
2682
3239
  type: props.type
2683
3240
  });
3241
+ var createBody3 = (props) => ({
3242
+ ...body4(props),
3243
+ iface: props.iface
3244
+ });
2684
3245
  var updateBody2 = (props) => {
2685
3246
  const clear = [
2686
3247
  ...props.cidr === undefined ? ["cidr"] : [],
@@ -2729,16 +3290,20 @@ var ProxmoxNodeNetwork = Resource16("Proxmox.NodeNetwork", {
2729
3290
  var handlers13 = pveHandlers({
2730
3291
  attributes: readAttributes,
2731
3292
  collection: (props) => `nodes/${props.node}/network`,
2732
- createForm: body4,
3293
+ createForm: createBody3,
3294
+ endpoint: {
3295
+ create: "pve:POST /nodes/{node}/network",
3296
+ update: "pve:PUT /nodes/{node}/network/{iface}"
3297
+ },
2733
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"]),
2734
3299
  path: (props) => `nodes/${props.node}/network/${props.iface}`,
2735
3300
  updateForm: updateBody2
2736
3301
  });
2737
- var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect35.succeed(ProxmoxNodeNetwork.Provider.of(handlers13)));
3302
+ var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect36.succeed(ProxmoxNodeNetwork.Provider.of(handlers13)));
2738
3303
  // src/proxmox/notification-matcher.ts
2739
3304
  import { Resource as Resource17 } from "alchemy";
2740
3305
  import * as Provider17 from "alchemy/Provider";
2741
- import * as Effect36 from "effect/Effect";
3306
+ import * as Effect37 from "effect/Effect";
2742
3307
 
2743
3308
  // src/proxmox/notification-matcher-form.ts
2744
3309
  var list = (value) => Array.isArray(value) ? value.map((item) => String(item)) : [];
@@ -2828,11 +3393,32 @@ var handlers14 = pveHandlers({
2828
3393
  path: (props) => `cluster/notifications/matchers/${props.name}`,
2829
3394
  updateForm: matcherUpdateForm
2830
3395
  });
2831
- var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect36.succeed(ProxmoxNotificationMatcher.Provider.of(handlers14)));
3396
+ var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect37.succeed(ProxmoxNotificationMatcher.Provider.of(handlers14)));
2832
3397
  // src/proxmox/notification-target.ts
2833
3398
  import { Resource as Resource18 } from "alchemy";
2834
3399
  import * as Provider18 from "alchemy/Provider";
2835
- import * as Effect37 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];
2836
3422
 
2837
3423
  // src/proxmox/notification-target-form.ts
2838
3424
  var REPEATED_KEY = "\x00";
@@ -2860,6 +3446,10 @@ var shape4 = (props) => ({
2860
3446
  ...set("url", props.url),
2861
3447
  ...set("username", props.username)
2862
3448
  });
3449
+ var createShape = (props) => ({
3450
+ ...shape4(props),
3451
+ name: props.name
3452
+ });
2863
3453
 
2864
3454
  // src/proxmox/notification-target.ts
2865
3455
  var ProxmoxNotificationTarget = Resource18("Proxmox.NotificationTarget");
@@ -2883,20 +3473,21 @@ var handlers15 = pveHandlers({
2883
3473
  username: text(live["username"])
2884
3474
  }),
2885
3475
  collection: (props) => `cluster/notifications/endpoints/${props.type}`,
2886
- createForm: (props) => ({ ...shape4(props), name: props.name }),
3476
+ createForm: createShape,
3477
+ endpoint: targetEndpoint,
2887
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)),
2888
3479
  path: (props) => `cluster/notifications/endpoints/${props.type}/${props.name}`,
2889
3480
  updateForm: shape4
2890
3481
  });
2891
- var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect37.succeed(ProxmoxNotificationTarget.Provider.of(handlers15)));
3482
+ var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect38.succeed(ProxmoxNotificationTarget.Provider.of(handlers15)));
2892
3483
  // src/proxmox/pbs-datastore.ts
2893
3484
  import { Resource as Resource19 } from "alchemy";
2894
3485
  import { isResolved as isResolved8 } from "alchemy/Diff";
2895
3486
  import * as Provider19 from "alchemy/Provider";
2896
- import * as Effect41 from "effect/Effect";
3487
+ import * as Effect42 from "effect/Effect";
2897
3488
 
2898
3489
  // src/proxmox/pbs-datastore-form.ts
2899
- import * as Effect38 from "effect/Effect";
3490
+ import * as Effect39 from "effect/Effect";
2900
3491
  var attributes = (live, props) => ({
2901
3492
  backend: propertyString(live["backend"]),
2902
3493
  comment: text(live["comment"]),
@@ -2948,35 +3539,35 @@ var createForm4 = (props) => ({
2948
3539
  });
2949
3540
  var updateForm = (props) => mutable(props);
2950
3541
  var object2 = (props) => `config/datastore/${props.name}`;
2951
- var readOne = (props) => pve(props.target, "read", "GET", object2(props)).pipe(Effect38.map((live) => live === undefined || typeof live["name"] !== "string" ? undefined : attributes(live, props)), Effect38.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(() => {
2952
3543
  return;
2953
3544
  }));
2954
3545
 
2955
3546
  // src/proxmox/pbs-datastore-guard.ts
2956
- import * as Effect39 from "effect/Effect";
3547
+ import * as Effect40 from "effect/Effect";
2957
3548
  var samePath = (left, right) => {
2958
3549
  const trim = (value) => value.length > 1 ? value.replace(/\/+$/, "") : value;
2959
3550
  return trim(left) === trim(right);
2960
3551
  };
2961
- var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect39.void : Effect39.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."));
2962
- var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect39.void : Effect39.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."));
2963
- var settle3 = (read3, done) => Effect39.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* () {
2964
3555
  for (let attempt = 0;attempt < 60; attempt += 1) {
2965
3556
  const live = yield* read3;
2966
3557
  if (done(live))
2967
3558
  return live;
2968
- yield* Effect39.sleep("2 seconds");
3559
+ yield* Effect40.sleep("2 seconds");
2969
3560
  }
2970
3561
  return yield* read3;
2971
3562
  });
2972
3563
 
2973
3564
  // src/proxmox/pbs-datastore-endpoint.ts
2974
- import * as Effect40 from "effect/Effect";
3565
+ import * as Effect41 from "effect/Effect";
2975
3566
  var DATASTORE_ENDPOINT = {
2976
3567
  create: "pbs:POST /config/datastore",
2977
3568
  update: "pbs:PUT /config/datastore/{name}"
2978
3569
  };
2979
- var guardDatastoreForms = (props) => Effect40.gen(function* () {
3570
+ var guardDatastoreForms = (props) => Effect41.gen(function* () {
2980
3571
  yield* guardForm(DATASTORE_ENDPOINT.create, createForm4(props), true);
2981
3572
  yield* guardForm(DATASTORE_ENDPOINT.update, updateForm(props), false);
2982
3573
  });
@@ -2985,10 +3576,10 @@ var guardDatastoreForms = (props) => Effect40.gen(function* () {
2985
3576
  var PbsDatastore = Resource19("Pbs.Datastore", {
2986
3577
  defaultRemovalPolicy: "retain"
2987
3578
  });
2988
- var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect41.succeed(PbsDatastore.Provider.of({
2989
- list: () => Effect41.succeed([]),
3579
+ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect42.succeed(PbsDatastore.Provider.of({
3580
+ list: () => Effect42.succeed([]),
2990
3581
  read: ({ olds }) => readOne(olds),
2991
- diff: ({ news, output }) => Effect41.gen(function* () {
3582
+ diff: ({ news, output }) => Effect42.gen(function* () {
2992
3583
  if (!isResolved8(news))
2993
3584
  return;
2994
3585
  yield* guardDatastoreForms(news);
@@ -3001,7 +3592,7 @@ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect41.succee
3001
3592
  yield* guardBackend(live, news);
3002
3593
  return matches(live, news) ? { action: "noop" } : { action: "update" };
3003
3594
  }),
3004
- reconcile: Effect41.fn(function* ({ news }) {
3595
+ reconcile: Effect42.fn(function* ({ news }) {
3005
3596
  yield* guardDatastoreForms(news);
3006
3597
  const live = yield* readOne(news);
3007
3598
  let upid;
@@ -3017,22 +3608,22 @@ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect41.succee
3017
3608
  }
3018
3609
  const after = yield* settle3(readOne(news), (row) => row !== undefined && matches(row, news));
3019
3610
  if (after === undefined || !matches(after, news)) {
3020
- return yield* Effect41.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."));
3021
3612
  }
3022
3613
  return after;
3023
3614
  }),
3024
- delete: Effect41.fn(function* ({ olds }) {
3615
+ delete: Effect42.fn(function* ({ olds }) {
3025
3616
  yield* pve(olds.target, "provision", "DELETE", object2(olds));
3026
3617
  const left = yield* settle3(readOne(olds), (row) => row === undefined);
3027
3618
  if (left !== undefined) {
3028
- return yield* Effect41.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>\`.`));
3029
3620
  }
3030
3621
  })
3031
3622
  })));
3032
3623
  // src/proxmox/pbs-notification-matcher.ts
3033
3624
  import { Resource as Resource20 } from "alchemy";
3034
3625
  import * as Provider20 from "alchemy/Provider";
3035
- import * as Effect42 from "effect/Effect";
3626
+ import * as Effect43 from "effect/Effect";
3036
3627
  var PbsNotificationMatcher = Resource20("Pbs.NotificationMatcher");
3037
3628
  var handlers16 = pveHandlers({
3038
3629
  attributes: (live, props) => matcherAttributes(live, props.name),
@@ -3046,15 +3637,32 @@ var handlers16 = pveHandlers({
3046
3637
  path: (props) => `config/notifications/matchers/${props.name}`,
3047
3638
  updateForm: matcherUpdateForm
3048
3639
  });
3049
- var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect42.succeed(PbsNotificationMatcher.Provider.of(handlers16)));
3640
+ var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect43.succeed(PbsNotificationMatcher.Provider.of(handlers16)));
3050
3641
  // src/proxmox/pbs-notification-target.ts
3051
3642
  import { Resource as Resource21 } from "alchemy";
3052
3643
  import * as Provider21 from "alchemy/Provider";
3053
- import * as Effect44 from "effect/Effect";
3644
+ import * as Effect45 from "effect/Effect";
3054
3645
 
3055
3646
  // src/proxmox/pbs-notification-target-lifecycle.ts
3056
3647
  import { isResolved as isResolved9 } from "alchemy/Diff";
3057
- import * as Effect43 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];
3058
3666
 
3059
3667
  // src/proxmox/credential-literals.ts
3060
3668
  var READS_SECRET = /\{\{[^}]*\bsecrets\./;
@@ -3314,12 +3922,12 @@ var targetForm = (props, groups, carry, mode) => {
3314
3922
 
3315
3923
  // src/proxmox/pbs-notification-target-lifecycle.ts
3316
3924
  var path = (props) => `config/notifications/endpoints/${props.type}/${props.name}`;
3317
- var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(Effect43.map((data) => data == null ? undefined : targetAttributes(data, props)), Effect43.orElseSucceed(() => {
3925
+ var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(Effect44.map((data) => data == null ? undefined : targetAttributes(data, props)), Effect44.orElseSucceed(() => {
3318
3926
  return;
3319
3927
  }));
3320
3928
  var refuse2 = (props) => {
3321
3929
  const reasons = refusals(props);
3322
- return reasons.length === 0 ? Effect43.void : Effect43.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
3930
+ return reasons.length === 0 ? Effect44.void : Effect44.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
3323
3931
  };
3324
3932
  var toCarry = (live, props, groups, sealed) => {
3325
3933
  const header = headerState(live, props, groups) === "stale";
@@ -3331,16 +3939,16 @@ var requireValues = (props, groups, carry) => {
3331
3939
  ...carry.header ? groups.header.missing : [],
3332
3940
  ...carry.sealed ? groups.sealed.missing : []
3333
3941
  ];
3334
- return missing.length === 0 ? Effect43.void : Effect43.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."));
3335
3943
  };
3336
3944
  var handlers17 = {
3337
- list: () => Effect43.succeed([]),
3338
- read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect43.void).pipe(Effect43.andThen(readLive2(olds)), Effect43.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 ?? "" })),
3339
3947
  diff: ({
3340
3948
  news,
3341
3949
  olds,
3342
3950
  output
3343
- }) => Effect43.gen(function* () {
3951
+ }) => Effect44.gen(function* () {
3344
3952
  if (output === undefined || !isResolved9(news))
3345
3953
  return;
3346
3954
  if (olds !== undefined && (olds.type !== news.type || olds.name !== news.name)) {
@@ -3352,7 +3960,7 @@ var handlers17 = {
3352
3960
  return { action: "update" };
3353
3961
  return toCarry(live, news, resolveGroups(news), output.sealed) === undefined ? { action: "noop" } : { action: "update" };
3354
3962
  }),
3355
- reconcile: ({ news, output }) => Effect43.gen(function* () {
3963
+ reconcile: ({ news, output }) => Effect44.gen(function* () {
3356
3964
  yield* refuse2(news);
3357
3965
  const groups = resolveGroups(news);
3358
3966
  const live = yield* readLive2(news);
@@ -3361,20 +3969,24 @@ var handlers17 = {
3361
3969
  const carry = { header: true, sealed: true };
3362
3970
  yield* requireValues(news, groups, carry);
3363
3971
  const collection2 = `config/notifications/endpoints/${news.type}`;
3364
- 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);
3365
3975
  sealed = seal(groups.sealed.values);
3366
3976
  } else {
3367
3977
  const carry = toCarry(live, news, groups, sealed);
3368
3978
  if (carry !== undefined) {
3369
3979
  yield* requireValues(news, groups, carry);
3370
- 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);
3371
3983
  if (carry.sealed)
3372
3984
  sealed = seal(groups.sealed.values);
3373
3985
  }
3374
3986
  }
3375
3987
  const after = yield* readLive2(news);
3376
3988
  if (after === undefined) {
3377
- return yield* Effect43.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.`));
3378
3990
  }
3379
3991
  return { ...after, sealed };
3380
3992
  }),
@@ -3383,11 +3995,11 @@ var handlers17 = {
3383
3995
 
3384
3996
  // src/proxmox/pbs-notification-target.ts
3385
3997
  var PbsNotificationTarget = Resource21("Pbs.NotificationTarget");
3386
- var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect44.succeed(PbsNotificationTarget.Provider.of(handlers17)));
3998
+ var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect45.succeed(PbsNotificationTarget.Provider.of(handlers17)));
3387
3999
  // src/proxmox/pbs-prune-job.ts
3388
4000
  import { Resource as Resource22 } from "alchemy";
3389
4001
  import * as Provider22 from "alchemy/Provider";
3390
- import * as Effect45 from "effect/Effect";
4002
+ import * as Effect46 from "effect/Effect";
3391
4003
 
3392
4004
  // src/proxmox/pbs-prune-job-form.ts
3393
4005
  var KEEP_KEYS = [
@@ -3433,7 +4045,7 @@ var shape5 = (props) => ({
3433
4045
  schedule: props.schedule,
3434
4046
  store: props.store
3435
4047
  });
3436
- var createBody2 = (props) => {
4048
+ var createBody4 = (props) => {
3437
4049
  requireKeeps(props);
3438
4050
  return { ...shape5(props), id: props.id };
3439
4051
  };
@@ -3457,17 +4069,17 @@ var handlers18 = pveHandlers({
3457
4069
  store: text(live["store"], props.store)
3458
4070
  }),
3459
4071
  collection: () => "config/prune",
3460
- createForm: createBody2,
4072
+ createForm: createBody4,
3461
4073
  endpoint: { create: "pbs:POST /config/prune", update: "pbs:PUT /config/prune/{id}" },
3462
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),
3463
4075
  path: (props) => `config/prune/${props.id}`,
3464
4076
  updateForm: updateBody3
3465
4077
  });
3466
- var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect45.succeed(PbsPruneJob.Provider.of(handlers18)));
4078
+ var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect46.succeed(PbsPruneJob.Provider.of(handlers18)));
3467
4079
  // src/proxmox/pbs-sync-job.ts
3468
4080
  import { Resource as Resource23 } from "alchemy";
3469
4081
  import * as Provider23 from "alchemy/Provider";
3470
- import * as Effect46 from "effect/Effect";
4082
+ import * as Effect47 from "effect/Effect";
3471
4083
 
3472
4084
  // src/proxmox/pbs-sync-job-form.ts
3473
4085
  var UNSET4 = -1;
@@ -3509,7 +4121,7 @@ var shape6 = (props) => ({
3509
4121
  ...props["verified-only"] === undefined ? {} : { "verified-only": props["verified-only"] ? "1" : "0" },
3510
4122
  ...props["transfer-last"] === undefined ? {} : { "transfer-last": String(props["transfer-last"]) }
3511
4123
  });
3512
- var createBody3 = (props) => ({
4124
+ var createBody5 = (props) => ({
3513
4125
  ...shape6(props),
3514
4126
  id: props.id,
3515
4127
  ...props["sync-direction"] === undefined ? {} : { "sync-direction": props["sync-direction"] }
@@ -3535,7 +4147,7 @@ var handlers19 = pveHandlers({
3535
4147
  "transfer-last": int(live["transfer-last"], UNSET4)
3536
4148
  }),
3537
4149
  collection: () => "config/sync",
3538
- createForm: createBody3,
4150
+ createForm: createBody5,
3539
4151
  endpoint: { create: "pbs:POST /config/sync", update: "pbs:PUT /config/sync/{id}" },
3540
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"]),
3541
4153
  path: (props) => `config/sync/${props.id}`,
@@ -3544,11 +4156,11 @@ var handlers19 = pveHandlers({
3544
4156
 
3545
4157
  // src/proxmox/pbs-sync-job.ts
3546
4158
  var PbsSyncJob = Resource23("Pbs.SyncJob");
3547
- var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect46.succeed(PbsSyncJob.Provider.of(handlers19)));
4159
+ var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect47.succeed(PbsSyncJob.Provider.of(handlers19)));
3548
4160
  // src/proxmox/pbs-verify-job.ts
3549
4161
  import { Resource as Resource24 } from "alchemy";
3550
4162
  import * as Provider24 from "alchemy/Provider";
3551
- import * as Effect47 from "effect/Effect";
4163
+ import * as Effect48 from "effect/Effect";
3552
4164
 
3553
4165
  // src/proxmox/pbs-verify-job-form.ts
3554
4166
  var rechecks = (ignoreVerified, outdatedAfter) => {
@@ -3593,11 +4205,11 @@ var handlers20 = pveHandlers({
3593
4205
  path: (props) => `config/verify/${props.id}`,
3594
4206
  updateForm: shape7
3595
4207
  });
3596
- var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect47.succeed(PbsVerifyJob.Provider.of(handlers20)));
4208
+ var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect48.succeed(PbsVerifyJob.Provider.of(handlers20)));
3597
4209
  // src/proxmox/pool.ts
3598
4210
  import { Resource as Resource25 } from "alchemy";
3599
4211
  import * as Provider25 from "alchemy/Provider";
3600
- import * as Effect48 from "effect/Effect";
4212
+ import * as Effect49 from "effect/Effect";
3601
4213
  var ProxmoxPool = Resource25("Proxmox.Pool");
3602
4214
  var poolCreateForm = (props) => ({
3603
4215
  comment: props.comment ?? "",
@@ -3622,7 +4234,7 @@ var handlers21 = pveHandlers({
3622
4234
  path: (props) => `pools/${props.poolid}`,
3623
4235
  updateForm: poolUpdateForm
3624
4236
  });
3625
- var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect48.succeed(ProxmoxPool.Provider.of(handlers21)));
4237
+ var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect49.succeed(ProxmoxPool.Provider.of(handlers21)));
3626
4238
  // src/proxmox/provision-baseline.ts
3627
4239
  var PROVISION_PRIVILEGES = Object.freeze([
3628
4240
  "Datastore.Allocate",
@@ -3815,12 +4427,12 @@ echo 'provision baseline: done. Next: point the OpenBao proxmox mount at these u
3815
4427
  // src/proxmox/provision-declare.ts
3816
4428
  import { adopt } from "alchemy/AdoptPolicy";
3817
4429
  import * as RemovalPolicy from "alchemy/RemovalPolicy";
3818
- import * as Effect51 from "effect/Effect";
4430
+ import * as Effect52 from "effect/Effect";
3819
4431
 
3820
4432
  // src/proxmox/role.ts
3821
4433
  import { Resource as Resource26 } from "alchemy";
3822
4434
  import * as Provider26 from "alchemy/Provider";
3823
- import * as Effect49 from "effect/Effect";
4435
+ import * as Effect50 from "effect/Effect";
3824
4436
  var ProxmoxRole = Resource26("Proxmox.Role");
3825
4437
  var canonical2 = (privs) => [...new Set(privs.map((priv) => priv.trim()).filter((priv) => priv.length > 0))].sort();
3826
4438
  var livePrivs = (live) => {
@@ -3838,12 +4450,12 @@ var handlers22 = pveHandlers({
3838
4450
  path: (props) => `access/roles/${props.roleid}`,
3839
4451
  updateForm: (props) => ({ privs: canonical2(props.privs).join(",") })
3840
4452
  });
3841
- var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect49.succeed(ProxmoxRole.Provider.of(handlers22)));
4453
+ var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect50.succeed(ProxmoxRole.Provider.of(handlers22)));
3842
4454
 
3843
4455
  // src/proxmox/user.ts
3844
4456
  import { Resource as Resource27 } from "alchemy";
3845
4457
  import * as Provider27 from "alchemy/Provider";
3846
- import * as Effect50 from "effect/Effect";
4458
+ import * as Effect51 from "effect/Effect";
3847
4459
  var ProxmoxUser = Resource27("Proxmox.User");
3848
4460
  var str2 = (value) => typeof value === "string" ? value : "";
3849
4461
  var int2 = (value) => {
@@ -3884,11 +4496,11 @@ var handlers23 = pveHandlers({
3884
4496
  path: (props) => `access/users/${props.userid}`,
3885
4497
  updateForm: shape8
3886
4498
  });
3887
- var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect50.succeed(ProxmoxUser.Provider.of(handlers23)));
4499
+ var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect51.succeed(ProxmoxUser.Provider.of(handlers23)));
3888
4500
 
3889
4501
  // src/proxmox/provision-declare.ts
3890
- var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect51.gen(function* () {
3891
- const baseline = yield* Effect51.try({
4502
+ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect52.gen(function* () {
4503
+ const baseline = yield* Effect52.try({
3892
4504
  catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
3893
4505
  try: () => provisionBaseline(names2)
3894
4506
  });
@@ -3902,13 +4514,13 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
3902
4514
  target
3903
4515
  }));
3904
4516
  const group = yield* owned(ProxmoxGroup(`${id}-mint-group`, { ...baseline.group, target }));
3905
- const users = yield* Effect51.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`, {
3906
4518
  comment: user.comment,
3907
4519
  groups: [...user.groups],
3908
4520
  target,
3909
4521
  userid: user.userid
3910
4522
  }))));
3911
- const grants = yield* Effect51.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`, {
3912
4524
  path: "/",
3913
4525
  propagate: true,
3914
4526
  roleid: grant.roleid,
@@ -3921,8 +4533,9 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
3921
4533
  // src/proxmox/qemu.ts
3922
4534
  import { Resource as Resource28 } from "alchemy";
3923
4535
  import * as Provider28 from "alchemy/Provider";
3924
- import * as Effect52 from "effect/Effect";
4536
+ import * as Effect53 from "effect/Effect";
3925
4537
  var ProxmoxVm = Resource28("Proxmox.Vm");
4538
+ var createForm5 = (props) => ({ ...shape9(props), vmid: String(props.vmid) });
3926
4539
  var shape9 = (props) => ({
3927
4540
  cores: String(props.cores ?? 1),
3928
4541
  memory: String(props.memory ?? 512),
@@ -3942,16 +4555,20 @@ var handlers24 = pveHandlers({
3942
4555
  vmid: props.vmid
3943
4556
  }),
3944
4557
  collection: (props) => `nodes/${props.node}/qemu`,
3945
- 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
+ },
3946
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),
3947
4564
  path: (props) => `nodes/${props.node}/qemu/${String(props.vmid)}/config`,
3948
4565
  updateForm: shape9
3949
4566
  });
3950
- var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect52.succeed(ProxmoxVm.Provider.of(handlers24)));
4567
+ var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect53.succeed(ProxmoxVm.Provider.of(handlers24)));
3951
4568
  // src/proxmox/replication-job.ts
3952
4569
  import { Resource as Resource29 } from "alchemy";
3953
4570
  import * as Provider29 from "alchemy/Provider";
3954
- import * as Effect53 from "effect/Effect";
4571
+ import * as Effect54 from "effect/Effect";
3955
4572
 
3956
4573
  // src/proxmox/replication-job-form.ts
3957
4574
  var DEFAULT_SCHEDULE = "*/15";
@@ -3962,7 +4579,7 @@ var shape10 = (props) => ({
3962
4579
  schedule: props.schedule ?? DEFAULT_SCHEDULE,
3963
4580
  ...props.rate === undefined ? {} : { rate: String(props.rate) }
3964
4581
  });
3965
- var createBody4 = (props) => ({
4582
+ var createBody6 = (props) => ({
3966
4583
  ...shape10(props),
3967
4584
  id: jobId(props),
3968
4585
  target: props.targetNode,
@@ -3996,7 +4613,7 @@ var handlers25 = pveHandlers({
3996
4613
  type: text(live["type"], "local")
3997
4614
  }),
3998
4615
  collection: () => "cluster/replication",
3999
- createForm: createBody4,
4616
+ createForm: createBody6,
4000
4617
  endpoint: {
4001
4618
  create: "pve:POST /cluster/replication",
4002
4619
  update: "pve:PUT /cluster/replication/{id}"
@@ -4005,15 +4622,15 @@ var handlers25 = pveHandlers({
4005
4622
  path: (props) => `cluster/replication/${jobId(props)}`,
4006
4623
  updateForm: updateBody5
4007
4624
  });
4008
- var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob, Effect53.succeed(ProxmoxReplicationJob.Provider.of(handlers25)));
4625
+ var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob, Effect54.succeed(ProxmoxReplicationJob.Provider.of(handlers25)));
4009
4626
  // src/proxmox/sdn-apply.ts
4010
4627
  import { Resource as Resource30 } from "alchemy";
4011
4628
  import { isResolved as isResolved10 } from "alchemy/Diff";
4012
4629
  import * as Provider30 from "alchemy/Provider";
4013
- import * as Effect55 from "effect/Effect";
4630
+ import * as Effect56 from "effect/Effect";
4014
4631
 
4015
4632
  // src/proxmox/sdn-apply-read.ts
4016
- import * as Effect54 from "effect/Effect";
4633
+ import * as Effect55 from "effect/Effect";
4017
4634
  var MARKED = [
4018
4635
  "cluster/sdn/zones",
4019
4636
  "cluster/sdn/vnets",
@@ -4022,7 +4639,7 @@ var MARKED = [
4022
4639
  "cluster/sdn/route-maps"
4023
4640
  ];
4024
4641
  var subsystemAbsent = (error) => error instanceof PveError && error.status === 501;
4025
- var markedPending = (target) => Effect54.all(MARKED.map((collection2) => pve(target, "read", "GET", `${collection2}?pending=1`).pipe(Effect54.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect54.catchIf(subsystemAbsent, () => Effect54.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect54.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)));
4026
4643
  var fabricStaged = (staged, running) => {
4027
4644
  if (staged === undefined && running === undefined)
4028
4645
  return 0;
@@ -4030,9 +4647,9 @@ var fabricStaged = (staged, running) => {
4030
4647
  return "inconsistent";
4031
4648
  return staged === running ? 0 : 1;
4032
4649
  };
4033
- var fabricPending = (target) => Effect54.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect54.map(canonical3), Effect54.catchIf(subsystemAbsent, () => Effect54.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect54.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]) => {
4034
4651
  const verdict = fabricStaged(staged, running);
4035
- return verdict === "inconsistent" ? Effect54.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.")) : Effect54.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);
4036
4653
  }));
4037
4654
  var canonical3 = (value) => JSON.stringify(sortDeep(value));
4038
4655
  var sortDeep = (value) => {
@@ -4045,39 +4662,40 @@ var sortDeep = (value) => {
4045
4662
  }
4046
4663
  return value;
4047
4664
  };
4048
- var sdnPendingCount = (target) => Effect54.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect54.map(([marked, fabric]) => marked + fabric));
4665
+ var sdnPendingCount = (target) => Effect55.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect55.map(([marked, fabric]) => marked + fabric));
4049
4666
 
4050
4667
  // src/proxmox/sdn-apply.ts
4051
4668
  var ProxmoxSdnApply = Resource30("Proxmox.SdnApply");
4052
- var read3 = (props) => sdnPendingCount(props.target).pipe(Effect55.map((pending) => ({ pending })));
4053
- var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply, Effect55.succeed(ProxmoxSdnApply.Provider.of({
4054
- list: () => Effect55.succeed([]),
4055
- read: Effect55.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 }) {
4056
4673
  return yield* read3(olds);
4057
4674
  }),
4058
- diff: Effect55.fn(function* ({ news }) {
4675
+ diff: Effect56.fn(function* ({ news }) {
4059
4676
  if (!isResolved10(news))
4060
4677
  return;
4061
4678
  const { pending } = yield* read3(news);
4062
4679
  return pending === 0 ? { action: "noop" } : { action: "update" };
4063
4680
  }),
4064
- reconcile: Effect55.fn(function* ({ news }) {
4681
+ reconcile: Effect56.fn(function* ({ news }) {
4065
4682
  const staged = yield* read3(news);
4066
4683
  if (staged.pending === 0)
4067
4684
  return staged;
4685
+ yield* guardSdnApply;
4068
4686
  yield* pve(news.target, "provision", "PUT", "cluster/sdn");
4069
4687
  const after = yield* read3(news);
4070
4688
  if (after.pending !== 0) {
4071
- return yield* Effect55.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."));
4072
4690
  }
4073
4691
  return after;
4074
4692
  }),
4075
- delete: () => Effect55.void
4693
+ delete: () => Effect56.void
4076
4694
  })));
4077
4695
  // src/proxmox/sdn-subnet.ts
4078
4696
  import { Resource as Resource31 } from "alchemy";
4079
4697
  import * as Provider31 from "alchemy/Provider";
4080
- import * as Effect56 from "effect/Effect";
4698
+ import * as Effect57 from "effect/Effect";
4081
4699
 
4082
4700
  // src/proxmox/sdn-subnet-form.ts
4083
4701
  var subnetId = (props) => `${props.zone}-${props.cidr.replace("/", "-")}`;
@@ -4096,7 +4714,7 @@ var body5 = (props) => ({
4096
4714
  vnet: props.vnet,
4097
4715
  ...Object.fromEntries(Object.entries(optional3(props)).filter((entry) => entry[1] !== undefined))
4098
4716
  });
4099
- var createForm5 = (props) => ({
4717
+ var createForm6 = (props) => ({
4100
4718
  ...body5(props),
4101
4719
  subnet: props.cidr,
4102
4720
  type: "subnet"
@@ -4128,16 +4746,20 @@ var handlers26 = pveHandlers({
4128
4746
  };
4129
4747
  },
4130
4748
  collection: (props) => `cluster/sdn/vnets/${props.vnet}/subnets`,
4131
- 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
+ },
4132
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),
4133
4755
  path: (props) => `cluster/sdn/vnets/${props.vnet}/subnets/${subnetId(props)}`,
4134
4756
  updateForm: updateForm2
4135
4757
  });
4136
- var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet, Effect56.succeed(ProxmoxSdnSubnet.Provider.of(handlers26)));
4758
+ var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet, Effect57.succeed(ProxmoxSdnSubnet.Provider.of(handlers26)));
4137
4759
  // src/proxmox/sdn-vnet.ts
4138
4760
  import { Resource as Resource32 } from "alchemy";
4139
4761
  import * as Provider32 from "alchemy/Provider";
4140
- import * as Effect57 from "effect/Effect";
4762
+ import * as Effect58 from "effect/Effect";
4141
4763
  var ProxmoxSdnVnet = Resource32("Proxmox.SdnVnet");
4142
4764
  var tagOf = (value) => typeof value === "number" ? value : undefined;
4143
4765
  var shape11 = (props) => {
@@ -4175,11 +4797,11 @@ var handlers27 = pveHandlers({
4175
4797
  path: (props) => `cluster/sdn/vnets/${props.vnet}`,
4176
4798
  updateForm: updateForm3
4177
4799
  });
4178
- var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet, Effect57.succeed(ProxmoxSdnVnet.Provider.of(handlers27)));
4800
+ var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet, Effect58.succeed(ProxmoxSdnVnet.Provider.of(handlers27)));
4179
4801
  // src/proxmox/sdn-zone.ts
4180
4802
  import { Resource as Resource33 } from "alchemy";
4181
4803
  import * as Provider33 from "alchemy/Provider";
4182
- import * as Effect58 from "effect/Effect";
4804
+ import * as Effect59 from "effect/Effect";
4183
4805
  var ProxmoxSdnZone = Resource33("Proxmox.SdnZone");
4184
4806
  var sameIpam = (live, declared2) => (live === "" ? "pve" : live) === (declared2 === undefined || declared2 === "" ? "pve" : declared2);
4185
4807
  var body6 = (props) => ({
@@ -4232,11 +4854,11 @@ var handlers28 = pveHandlers({
4232
4854
  return withClears(fields, clear);
4233
4855
  }
4234
4856
  });
4235
- var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone, Effect58.succeed(ProxmoxSdnZone.Provider.of(handlers28)));
4857
+ var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone, Effect59.succeed(ProxmoxSdnZone.Provider.of(handlers28)));
4236
4858
  // src/proxmox/storage.ts
4237
4859
  import { Resource as Resource34 } from "alchemy";
4238
4860
  import * as Provider34 from "alchemy/Provider";
4239
- import * as Effect59 from "effect/Effect";
4861
+ import * as Effect60 from "effect/Effect";
4240
4862
  var ProxmoxStorage = Resource34("Proxmox.Storage", {
4241
4863
  defaultRemovalPolicy: "retain"
4242
4864
  });
@@ -4282,15 +4904,16 @@ var handlers29 = pveHandlers({
4282
4904
  path: (props) => `storage/${props.storage}`,
4283
4905
  updateForm: mutable2
4284
4906
  });
4285
- var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect59.succeed(ProxmoxStorage.Provider.of(handlers29)));
4907
+ var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect60.succeed(ProxmoxStorage.Provider.of(handlers29)));
4286
4908
  // src/proxmox/zfs-pool.ts
4287
4909
  import { Resource as Resource35 } from "alchemy";
4288
4910
  import * as Provider35 from "alchemy/Provider";
4289
- import * as Effect61 from "effect/Effect";
4911
+ import * as Effect62 from "effect/Effect";
4290
4912
 
4291
4913
  // src/proxmox/zfs-pool-write.ts
4292
- import * as Effect60 from "effect/Effect";
4293
- 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) => ({
4294
4917
  devices: props.devices.join(","),
4295
4918
  name: props.name,
4296
4919
  raidlevel: props.raidlevel,
@@ -4299,21 +4922,21 @@ var createForm6 = (props) => ({
4299
4922
  ...props["draid-config"] === undefined ? {} : { "draid-config": props["draid-config"] }
4300
4923
  });
4301
4924
  var SETTLE_ATTEMPTS = 30;
4302
- var createPool = (props, collection2, path2, read4) => Effect60.gen(function* () {
4925
+ var createPool = (props, collection2, path2, read4) => Effect61.gen(function* () {
4303
4926
  const existing = yield* read4(props);
4304
4927
  if (existing !== undefined)
4305
4928
  return existing;
4306
- const upid = yield* pve(props.target, "provision", "POST", collection2, createForm6(props));
4307
- const settle4 = (attempts) => Effect60.gen(function* () {
4929
+ const upid = yield* pve(props.target, "provision", "POST", collection2, createForm7(props));
4930
+ const settle4 = (attempts) => Effect61.gen(function* () {
4308
4931
  const live = yield* read4(props);
4309
4932
  if (live !== undefined || attempts <= 0)
4310
4933
  return live;
4311
- yield* Effect60.sleep("2 seconds");
4934
+ yield* Effect61.sleep("2 seconds");
4312
4935
  return yield* settle4(attempts - 1);
4313
4936
  });
4314
4937
  const after = yield* settle4(SETTLE_ATTEMPTS);
4315
4938
  if (after === undefined) {
4316
- return yield* Effect60.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."));
4317
4940
  }
4318
4941
  return after;
4319
4942
  });
@@ -4341,19 +4964,20 @@ var spec2 = {
4341
4964
  };
4342
4965
  },
4343
4966
  collection: (props) => `nodes/${props.node}/disks/zfs`,
4344
- createForm: createForm6,
4967
+ createForm: createForm7,
4968
+ endpoint: ZFS_POOL_ENDPOINT,
4345
4969
  matches: () => true,
4346
4970
  path: (props) => `nodes/${props.node}/disks/zfs/${props.name}`
4347
4971
  };
4348
4972
  var ops5 = pveOperations(spec2);
4349
4973
  var handlers30 = {
4350
4974
  ...pveHandlers(spec2),
4351
- delete: Effect61.fn(function* ({ olds }) {
4975
+ delete: Effect62.fn(function* ({ olds }) {
4352
4976
  yield* destroyPool(olds, spec2.path(olds));
4353
4977
  }),
4354
4978
  reconcile: ({ news }) => createPool(news, spec2.collection(news), spec2.path(news), ops5.read)
4355
4979
  };
4356
- var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect61.succeed(ProxmoxZfsPool.Provider.of(handlers30)));
4980
+ var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect62.succeed(ProxmoxZfsPool.Provider.of(handlers30)));
4357
4981
  export {
4358
4982
  PROVISION_DEFAULTS,
4359
4983
  PROVISION_PRIVILEGES,
@@ -4425,5 +5049,5 @@ export {
4425
5049
  violations
4426
5050
  };
4427
5051
 
4428
- //# debugId=78DC295524EE261D64756E2164756E21
5052
+ //# debugId=35B6C615E87D256B64756E2164756E21
4429
5053
  //# sourceMappingURL=index.js.map