@homeflare/alchemy 0.15.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/README.md +29 -0
  2. package/dist/linux/directory-lifecycle.d.ts +50 -0
  3. package/dist/linux/directory-lifecycle.d.ts.map +1 -0
  4. package/dist/linux/directory.d.ts +19 -0
  5. package/dist/linux/directory.d.ts.map +1 -0
  6. package/dist/linux/fake-linux-host.d.ts +35 -0
  7. package/dist/linux/fake-linux-host.d.ts.map +1 -0
  8. package/dist/linux/fake-systemd.d.ts +34 -0
  9. package/dist/linux/fake-systemd.d.ts.map +1 -0
  10. package/dist/linux/index.d.ts +27 -0
  11. package/dist/linux/index.d.ts.map +1 -0
  12. package/dist/linux/index.js +1554 -0
  13. package/dist/linux/index.js.map +37 -0
  14. package/dist/linux/providers.d.ts +17 -0
  15. package/dist/linux/providers.d.ts.map +1 -0
  16. package/dist/linux/region.d.ts +43 -0
  17. package/dist/linux/region.d.ts.map +1 -0
  18. package/dist/linux/remote-file-form.d.ts +47 -0
  19. package/dist/linux/remote-file-form.d.ts.map +1 -0
  20. package/dist/linux/remote-file-lifecycle.d.ts +36 -0
  21. package/dist/linux/remote-file-lifecycle.d.ts.map +1 -0
  22. package/dist/linux/remote-file-plan.d.ts +33 -0
  23. package/dist/linux/remote-file-plan.d.ts.map +1 -0
  24. package/dist/linux/remote-file.d.ts +28 -0
  25. package/dist/linux/remote-file.d.ts.map +1 -0
  26. package/dist/linux/ssh-command.d.ts +68 -0
  27. package/dist/linux/ssh-command.d.ts.map +1 -0
  28. package/dist/linux/ssh-runner.d.ts +22 -0
  29. package/dist/linux/ssh-runner.d.ts.map +1 -0
  30. package/dist/linux/ssh-scripts.d.ts +27 -0
  31. package/dist/linux/ssh-scripts.d.ts.map +1 -0
  32. package/dist/linux/systemctl.d.ts +67 -0
  33. package/dist/linux/systemctl.d.ts.map +1 -0
  34. package/dist/linux/unit-form.d.ts +78 -0
  35. package/dist/linux/unit-form.d.ts.map +1 -0
  36. package/dist/linux/unit-handlers.d.ts +15 -0
  37. package/dist/linux/unit-handlers.d.ts.map +1 -0
  38. package/dist/linux/unit-lifecycle.d.ts +44 -0
  39. package/dist/linux/unit-lifecycle.d.ts.map +1 -0
  40. package/dist/linux/unit-settle.d.ts +31 -0
  41. package/dist/linux/unit-settle.d.ts.map +1 -0
  42. package/dist/linux/unit.d.ts +35 -0
  43. package/dist/linux/unit.d.ts.map +1 -0
  44. package/dist/netbox/client.d.ts +52 -0
  45. package/dist/netbox/client.d.ts.map +1 -0
  46. package/dist/netbox/constraint-guard.d.ts +26 -0
  47. package/dist/netbox/constraint-guard.d.ts.map +1 -0
  48. package/dist/netbox/constraints.d.ts +76 -0
  49. package/dist/netbox/constraints.d.ts.map +1 -0
  50. package/dist/netbox/generated/constraints/index.d.ts +19 -0
  51. package/dist/netbox/generated/constraints/index.d.ts.map +1 -0
  52. package/dist/netbox/generated/constraints/netbox-ipam.d.ts +21 -0
  53. package/dist/netbox/generated/constraints/netbox-ipam.d.ts.map +1 -0
  54. package/dist/netbox/index.d.ts +17 -0
  55. package/dist/netbox/index.d.ts.map +1 -0
  56. package/dist/netbox/index.js +331 -0
  57. package/dist/netbox/index.js.map +18 -0
  58. package/dist/netbox/prefix-form.d.ts +54 -0
  59. package/dist/netbox/prefix-form.d.ts.map +1 -0
  60. package/dist/netbox/prefix.d.ts +80 -0
  61. package/dist/netbox/prefix.d.ts.map +1 -0
  62. package/dist/netbox/resource.d.ts +94 -0
  63. package/dist/netbox/resource.d.ts.map +1 -0
  64. package/dist/netbox/values.d.ts +24 -0
  65. package/dist/netbox/values.d.ts.map +1 -0
  66. package/dist/proxmox/api-token-form.d.ts.map +1 -1
  67. package/dist/proxmox/apply-endpoints.d.ts +30 -0
  68. package/dist/proxmox/apply-endpoints.d.ts.map +1 -0
  69. package/dist/proxmox/ceph-daemon-form.d.ts +29 -1
  70. package/dist/proxmox/ceph-daemon-form.d.ts.map +1 -1
  71. package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
  72. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  73. package/dist/proxmox/ceph-fs.d.ts.map +1 -1
  74. package/dist/proxmox/ceph-osd-write.d.ts +19 -0
  75. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  76. package/dist/proxmox/ceph-pool.d.ts.map +1 -1
  77. package/dist/proxmox/constraints.d.ts +28 -5
  78. package/dist/proxmox/constraints.d.ts.map +1 -1
  79. package/dist/proxmox/generated/constraints/index.d.ts +1 -1
  80. package/dist/proxmox/generated/constraints/index.d.ts.map +1 -1
  81. package/dist/proxmox/generated/constraints/pbs-config.d.ts +6 -1
  82. package/dist/proxmox/generated/constraints/pbs-config.d.ts.map +1 -1
  83. package/dist/proxmox/generated/constraints/pve-access.d.ts +6 -1
  84. package/dist/proxmox/generated/constraints/pve-access.d.ts.map +1 -1
  85. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +23 -0
  86. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts.map +1 -0
  87. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +23 -0
  88. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts.map +1 -0
  89. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +23 -0
  90. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts.map +1 -0
  91. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +23 -0
  92. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts.map +1 -0
  93. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +23 -0
  94. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts.map +1 -0
  95. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +23 -0
  96. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts.map +1 -0
  97. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +23 -0
  98. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts.map +1 -0
  99. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +23 -0
  100. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts.map +1 -0
  101. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +23 -0
  102. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts.map +1 -0
  103. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +23 -0
  104. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts.map +1 -0
  105. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +23 -0
  106. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts.map +1 -0
  107. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +23 -0
  108. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts.map +1 -0
  109. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +23 -0
  110. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts.map +1 -0
  111. package/dist/proxmox/generated/constraints/pve-pools.d.ts +6 -1
  112. package/dist/proxmox/generated/constraints/pve-pools.d.ts.map +1 -1
  113. package/dist/proxmox/generated/constraints/pve-storage.d.ts +6 -1
  114. package/dist/proxmox/generated/constraints/pve-storage.d.ts.map +1 -1
  115. package/dist/proxmox/generated/pbs/access-users.d.ts +137 -0
  116. package/dist/proxmox/generated/pbs/access-users.d.ts.map +1 -0
  117. package/dist/proxmox/generated/pbs/access.d.ts +171 -0
  118. package/dist/proxmox/generated/pbs/access.d.ts.map +1 -0
  119. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts +252 -0
  120. package/dist/proxmox/generated/pbs/admin-datastore-store.d.ts.map +1 -0
  121. package/dist/proxmox/generated/pbs/admin-metrics.d.ts +147 -0
  122. package/dist/proxmox/generated/pbs/admin-metrics.d.ts.map +1 -0
  123. package/dist/proxmox/generated/pbs/admin.d.ts +217 -0
  124. package/dist/proxmox/generated/pbs/admin.d.ts.map +1 -0
  125. package/dist/proxmox/generated/pbs/backup.d.ts +114 -0
  126. package/dist/proxmox/generated/pbs/backup.d.ts.map +1 -0
  127. package/dist/proxmox/generated/pbs/config-access-pam.d.ts +218 -0
  128. package/dist/proxmox/generated/pbs/config-access-pam.d.ts.map +1 -0
  129. package/dist/proxmox/generated/pbs/config-access.d.ts +203 -0
  130. package/dist/proxmox/generated/pbs/config-access.d.ts.map +1 -0
  131. package/dist/proxmox/generated/pbs/config-datastore.d.ts +195 -0
  132. package/dist/proxmox/generated/pbs/config-datastore.d.ts.map +1 -0
  133. package/dist/proxmox/generated/pbs/config-media-pool.d.ts +207 -0
  134. package/dist/proxmox/generated/pbs/config-media-pool.d.ts.map +1 -0
  135. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts +159 -0
  136. package/dist/proxmox/generated/pbs/config-notifications-matchers.d.ts.map +1 -0
  137. package/dist/proxmox/generated/pbs/config-notifications.d.ts +199 -0
  138. package/dist/proxmox/generated/pbs/config-notifications.d.ts.map +1 -0
  139. package/dist/proxmox/generated/pbs/config-remote.d.ts +175 -0
  140. package/dist/proxmox/generated/pbs/config-remote.d.ts.map +1 -0
  141. package/dist/proxmox/generated/pbs/config-sync.d.ts +145 -0
  142. package/dist/proxmox/generated/pbs/config-sync.d.ts.map +1 -0
  143. package/dist/proxmox/generated/pbs/config-tape.d.ts +200 -0
  144. package/dist/proxmox/generated/pbs/config-tape.d.ts.map +1 -0
  145. package/dist/proxmox/generated/pbs/config-verify.d.ts +77 -0
  146. package/dist/proxmox/generated/pbs/config-verify.d.ts.map +1 -0
  147. package/dist/proxmox/generated/pbs/config.d.ts +119 -0
  148. package/dist/proxmox/generated/pbs/config.d.ts.map +1 -0
  149. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts +178 -0
  150. package/dist/proxmox/generated/pbs/nodes-node-dns.d.ts.map +1 -0
  151. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts +205 -0
  152. package/dist/proxmox/generated/pbs/nodes-node-services.d.ts.map +1 -0
  153. package/dist/proxmox/generated/pbs/nodes-node.d.ts +166 -0
  154. package/dist/proxmox/generated/pbs/nodes-node.d.ts.map +1 -0
  155. package/dist/proxmox/generated/pbs/nodes.d.ts +171 -0
  156. package/dist/proxmox/generated/pbs/nodes.d.ts.map +1 -0
  157. package/dist/proxmox/generated/pbs/ping.d.ts +18 -0
  158. package/dist/proxmox/generated/pbs/ping.d.ts.map +1 -0
  159. package/dist/proxmox/generated/pbs/pull.d.ts +37 -0
  160. package/dist/proxmox/generated/pbs/pull.d.ts.map +1 -0
  161. package/dist/proxmox/generated/pbs/push.d.ts +36 -0
  162. package/dist/proxmox/generated/pbs/push.d.ts.map +1 -0
  163. package/dist/proxmox/generated/pbs/reader.d.ts +41 -0
  164. package/dist/proxmox/generated/pbs/reader.d.ts.map +1 -0
  165. package/dist/proxmox/generated/pbs/root.d.ts +16 -0
  166. package/dist/proxmox/generated/pbs/root.d.ts.map +1 -0
  167. package/dist/proxmox/generated/pbs/status.d.ts +54 -0
  168. package/dist/proxmox/generated/pbs/status.d.ts.map +1 -0
  169. package/dist/proxmox/generated/pbs/tape-drive.d.ts +181 -0
  170. package/dist/proxmox/generated/pbs/tape-drive.d.ts.map +1 -0
  171. package/dist/proxmox/generated/pbs/tape-media.d.ts +126 -0
  172. package/dist/proxmox/generated/pbs/tape-media.d.ts.map +1 -0
  173. package/dist/proxmox/generated/pbs/tape.d.ts +90 -0
  174. package/dist/proxmox/generated/pbs/tape.d.ts.map +1 -0
  175. package/dist/proxmox/generated/pbs/version.d.ts +20 -0
  176. package/dist/proxmox/generated/pbs/version.d.ts.map +1 -0
  177. package/dist/proxmox/generated/pbs.d.ts +44 -662
  178. package/dist/proxmox/generated/pbs.d.ts.map +1 -1
  179. package/dist/proxmox/generated/pve/access-roles.d.ts +164 -0
  180. package/dist/proxmox/generated/pve/access-roles.d.ts.map +1 -0
  181. package/dist/proxmox/generated/pve/access-users.d.ts +152 -0
  182. package/dist/proxmox/generated/pve/access-users.d.ts.map +1 -0
  183. package/dist/proxmox/generated/pve/access.d.ts +221 -0
  184. package/dist/proxmox/generated/pve/access.d.ts.map +1 -0
  185. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts +45 -0
  186. package/dist/proxmox/generated/pve/cluster-acme-plugins-id.d.ts.map +1 -0
  187. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts +47 -0
  188. package/dist/proxmox/generated/pve/cluster-acme-plugins.d.ts.map +1 -0
  189. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts +240 -0
  190. package/dist/proxmox/generated/pve/cluster-acme-tos.d.ts.map +1 -0
  191. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts +200 -0
  192. package/dist/proxmox/generated/pve/cluster-bulk-action.d.ts.map +1 -0
  193. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts +109 -0
  194. package/dist/proxmox/generated/pve/cluster-firewall-refs.d.ts.map +1 -0
  195. package/dist/proxmox/generated/pve/cluster-firewall.d.ts +225 -0
  196. package/dist/proxmox/generated/pve/cluster-firewall.d.ts.map +1 -0
  197. package/dist/proxmox/generated/pve/cluster-ha.d.ts +199 -0
  198. package/dist/proxmox/generated/pve/cluster-ha.d.ts.map +1 -0
  199. package/dist/proxmox/generated/pve/cluster-jobs.d.ts +183 -0
  200. package/dist/proxmox/generated/pve/cluster-jobs.d.ts.map +1 -0
  201. package/dist/proxmox/generated/pve/cluster-metrics.d.ts +110 -0
  202. package/dist/proxmox/generated/pve/cluster-metrics.d.ts.map +1 -0
  203. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts +224 -0
  204. package/dist/proxmox/generated/pve/cluster-notifications-endpoints.d.ts.map +1 -0
  205. package/dist/proxmox/generated/pve/cluster-notifications.d.ts +91 -0
  206. package/dist/proxmox/generated/pve/cluster-notifications.d.ts.map +1 -0
  207. package/dist/proxmox/generated/pve/cluster-options.d.ts +85 -0
  208. package/dist/proxmox/generated/pve/cluster-options.d.ts.map +1 -0
  209. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts +48 -0
  210. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.d.ts.map +1 -0
  211. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts +45 -0
  212. package/dist/proxmox/generated/pve/cluster-qemu-custom-cpu-models.d.ts.map +1 -0
  213. package/dist/proxmox/generated/pve/cluster-replication.d.ts +130 -0
  214. package/dist/proxmox/generated/pve/cluster-replication.d.ts.map +1 -0
  215. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts +220 -0
  216. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts.map +1 -0
  217. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts +229 -0
  218. package/dist/proxmox/generated/pve/cluster-sdn-ipams.d.ts.map +1 -0
  219. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts +229 -0
  220. package/dist/proxmox/generated/pve/cluster-sdn-vnets-vnet.d.ts.map +1 -0
  221. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts +51 -0
  222. package/dist/proxmox/generated/pve/cluster-sdn-vnets.d.ts.map +1 -0
  223. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts +225 -0
  224. package/dist/proxmox/generated/pve/cluster-sdn-zones.d.ts.map +1 -0
  225. package/dist/proxmox/generated/pve/cluster-sdn.d.ts +202 -0
  226. package/dist/proxmox/generated/pve/cluster-sdn.d.ts.map +1 -0
  227. package/dist/proxmox/generated/pve/cluster.d.ts +69 -0
  228. package/dist/proxmox/generated/pve/cluster.d.ts.map +1 -0
  229. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts +167 -0
  230. package/dist/proxmox/generated/pve/nodes-node-ceph.d.ts.map +1 -0
  231. package/dist/proxmox/generated/pve/nodes-node-config.d.ts +43 -0
  232. package/dist/proxmox/generated/pve/nodes-node-config.d.ts.map +1 -0
  233. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts +225 -0
  234. package/dist/proxmox/generated/pve/nodes-node-disks.d.ts.map +1 -0
  235. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts +145 -0
  236. package/dist/proxmox/generated/pve/nodes-node-firewall.d.ts.map +1 -0
  237. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts +195 -0
  238. package/dist/proxmox/generated/pve/nodes-node-hardware.d.ts.map +1 -0
  239. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts +191 -0
  240. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.d.ts.map +1 -0
  241. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts +33 -0
  242. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.d.ts.map +1 -0
  243. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts +56 -0
  244. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.d.ts.map +1 -0
  245. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts +28 -0
  246. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-resize.d.ts.map +1 -0
  247. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts +186 -0
  248. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.d.ts.map +1 -0
  249. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts +191 -0
  250. package/dist/proxmox/generated/pve/nodes-node-lxc-vmid.d.ts.map +1 -0
  251. package/dist/proxmox/generated/pve/nodes-node-network.d.ts +150 -0
  252. package/dist/proxmox/generated/pve/nodes-node-network.d.ts.map +1 -0
  253. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts +301 -0
  254. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-config.d.ts.map +1 -0
  255. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts +170 -0
  256. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.d.ts.map +1 -0
  257. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts +144 -0
  258. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.d.ts.map +1 -0
  259. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts +34 -0
  260. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.d.ts.map +1 -0
  261. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts +137 -0
  262. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.d.ts.map +1 -0
  263. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts +179 -0
  264. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid-status.d.ts.map +1 -0
  265. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts +143 -0
  266. package/dist/proxmox/generated/pve/nodes-node-qemu-vmid.d.ts.map +1 -0
  267. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts +158 -0
  268. package/dist/proxmox/generated/pve/nodes-node-qemu.d.ts.map +1 -0
  269. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts +187 -0
  270. package/dist/proxmox/generated/pve/nodes-node-replication.d.ts.map +1 -0
  271. package/dist/proxmox/generated/pve/nodes-node-services.d.ts +115 -0
  272. package/dist/proxmox/generated/pve/nodes-node-services.d.ts.map +1 -0
  273. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts +202 -0
  274. package/dist/proxmox/generated/pve/nodes-node-storage-storage.d.ts.map +1 -0
  275. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts +40 -0
  276. package/dist/proxmox/generated/pve/nodes-node-storage.d.ts.map +1 -0
  277. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts +173 -0
  278. package/dist/proxmox/generated/pve/nodes-node-subscription.d.ts.map +1 -0
  279. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts +97 -0
  280. package/dist/proxmox/generated/pve/nodes-node-vzdump.d.ts.map +1 -0
  281. package/dist/proxmox/generated/pve/nodes-node.d.ts +207 -0
  282. package/dist/proxmox/generated/pve/nodes-node.d.ts.map +1 -0
  283. package/dist/proxmox/generated/pve/nodes.d.ts +236 -0
  284. package/dist/proxmox/generated/pve/nodes.d.ts.map +1 -0
  285. package/dist/proxmox/generated/pve/pools.d.ts +82 -0
  286. package/dist/proxmox/generated/pve/pools.d.ts.map +1 -0
  287. package/dist/proxmox/generated/pve/storage.d.ts +159 -0
  288. package/dist/proxmox/generated/pve/storage.d.ts.map +1 -0
  289. package/dist/proxmox/generated/pve/version.d.ts +21 -0
  290. package/dist/proxmox/generated/pve/version.d.ts.map +1 -0
  291. package/dist/proxmox/generated/pve.d.ts +69 -4766
  292. package/dist/proxmox/generated/pve.d.ts.map +1 -1
  293. package/dist/proxmox/index.js +996 -372
  294. package/dist/proxmox/index.js.map +48 -32
  295. package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
  296. package/dist/proxmox/metric-server-form.d.ts +11 -0
  297. package/dist/proxmox/metric-server-form.d.ts.map +1 -1
  298. package/dist/proxmox/metric-server.d.ts.map +1 -1
  299. package/dist/proxmox/network-apply.d.ts.map +1 -1
  300. package/dist/proxmox/node-network-form.d.ts +15 -0
  301. package/dist/proxmox/node-network-form.d.ts.map +1 -1
  302. package/dist/proxmox/node-network.d.ts.map +1 -1
  303. package/dist/proxmox/notification-target-endpoint.d.ts +26 -0
  304. package/dist/proxmox/notification-target-endpoint.d.ts.map +1 -0
  305. package/dist/proxmox/notification-target-form.d.ts +7 -0
  306. package/dist/proxmox/notification-target-form.d.ts.map +1 -1
  307. package/dist/proxmox/notification-target.d.ts.map +1 -1
  308. package/dist/proxmox/pbs-notification-target-endpoint.d.ts +29 -0
  309. package/dist/proxmox/pbs-notification-target-endpoint.d.ts.map +1 -0
  310. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -1
  311. package/dist/proxmox/qemu.d.ts +10 -0
  312. package/dist/proxmox/qemu.d.ts.map +1 -1
  313. package/dist/proxmox/resource-guard.d.ts +15 -0
  314. package/dist/proxmox/resource-guard.d.ts.map +1 -0
  315. package/dist/proxmox/resource-spec.d.ts +15 -4
  316. package/dist/proxmox/resource-spec.d.ts.map +1 -1
  317. package/dist/proxmox/resource.d.ts +8 -0
  318. package/dist/proxmox/resource.d.ts.map +1 -1
  319. package/dist/proxmox/sdn-apply.d.ts.map +1 -1
  320. package/dist/proxmox/sdn-subnet.d.ts.map +1 -1
  321. package/dist/proxmox/zfs-pool-write.d.ts +11 -0
  322. package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
  323. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  324. package/docs/linux-host-measured.md +56 -0
  325. package/docs/linux-host.md +186 -0
  326. package/docs/netbox.md +103 -0
  327. package/package.json +9 -1
  328. package/src/linux/directory-lifecycle.ts +220 -0
  329. package/src/linux/directory.test.ts +132 -0
  330. package/src/linux/directory.ts +71 -0
  331. package/src/linux/fake-linux-host.ts +197 -0
  332. package/src/linux/fake-systemd.ts +103 -0
  333. package/src/linux/index.ts +32 -0
  334. package/src/linux/providers.ts +26 -0
  335. package/src/linux/region.test.ts +89 -0
  336. package/src/linux/region.ts +118 -0
  337. package/src/linux/remote-file-form.ts +96 -0
  338. package/src/linux/remote-file-lifecycle.test.ts +191 -0
  339. package/src/linux/remote-file-lifecycle.ts +161 -0
  340. package/src/linux/remote-file-plan.ts +154 -0
  341. package/src/linux/remote-file.ts +88 -0
  342. package/src/linux/ssh-command.test.ts +140 -0
  343. package/src/linux/ssh-command.ts +99 -0
  344. package/src/linux/ssh-runner.ts +188 -0
  345. package/src/linux/ssh-scripts.ts +105 -0
  346. package/src/linux/systemctl.ts +145 -0
  347. package/src/linux/unit-form.ts +183 -0
  348. package/src/linux/unit-handlers.ts +73 -0
  349. package/src/linux/unit-lifecycle.test.ts +220 -0
  350. package/src/linux/unit-lifecycle.ts +193 -0
  351. package/src/linux/unit-settle.ts +110 -0
  352. package/src/linux/unit.ts +81 -0
  353. package/src/netbox/client.test.ts +67 -0
  354. package/src/netbox/client.ts +146 -0
  355. package/src/netbox/constraint-guard.ts +57 -0
  356. package/src/netbox/constraints.test.ts +114 -0
  357. package/src/netbox/constraints.ts +152 -0
  358. package/src/netbox/generated/constraints/index.ts +23 -0
  359. package/src/netbox/generated/constraints/netbox-ipam.ts +32 -0
  360. package/src/netbox/index.ts +34 -0
  361. package/src/netbox/prefix-form.test.ts +127 -0
  362. package/src/netbox/prefix-form.ts +84 -0
  363. package/src/netbox/prefix.ts +136 -0
  364. package/src/netbox/resource.ts +208 -0
  365. package/src/netbox/values.test.ts +66 -0
  366. package/src/netbox/values.ts +40 -0
  367. package/src/proxmox/api-token-form.ts +5 -0
  368. package/src/proxmox/apply-endpoints.ts +34 -0
  369. package/src/proxmox/ceph-daemon-form.ts +56 -2
  370. package/src/proxmox/ceph-daemon.ts +10 -21
  371. package/src/proxmox/ceph-flag.ts +1 -0
  372. package/src/proxmox/ceph-fs.ts +1 -0
  373. package/src/proxmox/ceph-osd-write.ts +30 -4
  374. package/src/proxmox/ceph-pool.ts +10 -0
  375. package/src/proxmox/constraints-dialect.test.ts +165 -0
  376. package/src/proxmox/constraints-forms.test.ts +220 -0
  377. package/src/proxmox/constraints-host-forms.test.ts +132 -0
  378. package/src/proxmox/constraints-live.test.ts +155 -0
  379. package/src/proxmox/constraints-node-forms.test.ts +188 -0
  380. package/src/proxmox/constraints-required.test.ts +172 -0
  381. package/src/proxmox/constraints.test.ts +8 -63
  382. package/src/proxmox/constraints.ts +31 -6
  383. package/src/proxmox/generated/constraints/index.ts +27 -3
  384. package/src/proxmox/generated/constraints/pbs-config.ts +63 -1
  385. package/src/proxmox/generated/constraints/pve-access.ts +15 -3
  386. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +74 -0
  387. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +27 -0
  388. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +35 -0
  389. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +55 -0
  390. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +59 -0
  391. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +80 -0
  392. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +43 -0
  393. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +90 -0
  394. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +57 -0
  395. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +31 -0
  396. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +82 -0
  397. package/src/proxmox/generated/constraints/pve-nodes-network.ts +77 -0
  398. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +125 -0
  399. package/src/proxmox/generated/constraints/pve-pools.ts +6 -1
  400. package/src/proxmox/generated/constraints/pve-storage.ts +8 -3
  401. package/src/proxmox/generated/pbs/access-users.ts +137 -0
  402. package/src/proxmox/generated/pbs/access.ts +232 -0
  403. package/src/proxmox/generated/pbs/admin-datastore-store.ts +238 -0
  404. package/src/proxmox/generated/pbs/admin-metrics.ts +147 -0
  405. package/src/proxmox/generated/pbs/admin.ts +225 -0
  406. package/src/proxmox/generated/pbs/backup.ts +121 -0
  407. package/src/proxmox/generated/pbs/config-access-pam.ts +228 -0
  408. package/src/proxmox/generated/pbs/config-access.ts +228 -0
  409. package/src/proxmox/generated/pbs/config-datastore.ts +217 -0
  410. package/src/proxmox/generated/pbs/config-media-pool.ts +232 -0
  411. package/src/proxmox/generated/pbs/config-notifications-matchers.ts +187 -0
  412. package/src/proxmox/generated/pbs/config-notifications.ts +221 -0
  413. package/src/proxmox/generated/pbs/config-remote.ts +192 -0
  414. package/src/proxmox/generated/pbs/config-sync.ts +167 -0
  415. package/src/proxmox/generated/pbs/config-tape.ts +226 -0
  416. package/src/proxmox/generated/pbs/config-verify.ts +87 -0
  417. package/src/proxmox/generated/pbs/config.ts +135 -0
  418. package/src/proxmox/generated/pbs/nodes-node-dns.ts +229 -0
  419. package/src/proxmox/generated/pbs/nodes-node-services.ts +181 -0
  420. package/src/proxmox/generated/pbs/nodes-node.ts +244 -0
  421. package/src/proxmox/generated/pbs/nodes.ts +160 -0
  422. package/src/proxmox/generated/pbs/ping.ts +16 -0
  423. package/src/proxmox/generated/pbs/pull.ts +37 -0
  424. package/src/proxmox/generated/pbs/push.ts +36 -0
  425. package/src/proxmox/generated/pbs/reader.ts +41 -0
  426. package/src/proxmox/generated/pbs/root.ts +16 -0
  427. package/src/proxmox/generated/pbs/status.ts +50 -0
  428. package/src/proxmox/generated/pbs/tape-drive.ts +220 -0
  429. package/src/proxmox/generated/pbs/tape-media.ts +133 -0
  430. package/src/proxmox/generated/pbs/tape.ts +92 -0
  431. package/src/proxmox/generated/pbs/version.ts +16 -0
  432. package/src/proxmox/generated/pbs.ts +44 -787
  433. package/src/proxmox/generated/pve/access-roles.ts +168 -0
  434. package/src/proxmox/generated/pve/access-users.ts +155 -0
  435. package/src/proxmox/generated/pve/access.ts +217 -0
  436. package/src/proxmox/generated/pve/cluster-acme-plugins-id.ts +367 -0
  437. package/src/proxmox/generated/pve/cluster-acme-plugins.ts +366 -0
  438. package/src/proxmox/generated/pve/cluster-acme-tos.ts +232 -0
  439. package/src/proxmox/generated/pve/cluster-bulk-action.ts +227 -0
  440. package/src/proxmox/generated/pve/cluster-firewall-refs.ts +110 -0
  441. package/src/proxmox/generated/pve/cluster-firewall.ts +236 -0
  442. package/src/proxmox/generated/pve/cluster-ha.ts +203 -0
  443. package/src/proxmox/generated/pve/cluster-jobs.ts +190 -0
  444. package/src/proxmox/generated/pve/cluster-metrics.ts +116 -0
  445. package/src/proxmox/generated/pve/cluster-notifications-endpoints.ts +244 -0
  446. package/src/proxmox/generated/pve/cluster-notifications.ts +99 -0
  447. package/src/proxmox/generated/pve/cluster-options.ts +189 -0
  448. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models-cputype.ts +272 -0
  449. package/src/proxmox/generated/pve/cluster-qemu-custom-cpu-models.ts +268 -0
  450. package/src/proxmox/generated/pve/cluster-replication.ts +127 -0
  451. package/src/proxmox/generated/pve/cluster-sdn-fabrics.ts +218 -0
  452. package/src/proxmox/generated/pve/cluster-sdn-ipams.ts +229 -0
  453. package/src/proxmox/generated/pve/cluster-sdn-vnets-vnet.ts +245 -0
  454. package/src/proxmox/generated/pve/cluster-sdn-vnets.ts +49 -0
  455. package/src/proxmox/generated/pve/cluster-sdn-zones.ts +224 -0
  456. package/src/proxmox/generated/pve/cluster-sdn.ts +201 -0
  457. package/src/proxmox/generated/pve/cluster.ts +71 -0
  458. package/src/proxmox/generated/pve/nodes-node-ceph.ts +167 -0
  459. package/src/proxmox/generated/pve/nodes-node-config.ts +56 -0
  460. package/src/proxmox/generated/pve/nodes-node-disks.ts +237 -0
  461. package/src/proxmox/generated/pve/nodes-node-firewall.ts +239 -0
  462. package/src/proxmox/generated/pve/nodes-node-hardware.ts +215 -0
  463. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-firewall.ts +232 -0
  464. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-move-volume.ts +1059 -0
  465. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-mtunnel.ts +49 -0
  466. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-resize.ts +285 -0
  467. package/src/proxmox/generated/pve/nodes-node-lxc-vmid-rrd.ts +184 -0
  468. package/src/proxmox/generated/pve/nodes-node-lxc-vmid.ts +240 -0
  469. package/src/proxmox/generated/pve/nodes-node-network.ts +234 -0
  470. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-config.ts +441 -0
  471. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-dbus-vmstate.ts +215 -0
  472. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-firewall-rules.ts +145 -0
  473. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-move-disk.ts +664 -0
  474. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-mtunnel.ts +188 -0
  475. package/src/proxmox/generated/pve/nodes-node-qemu-vmid-status.ts +233 -0
  476. package/src/proxmox/generated/pve/nodes-node-qemu-vmid.ts +187 -0
  477. package/src/proxmox/generated/pve/nodes-node-qemu.ts +204 -0
  478. package/src/proxmox/generated/pve/nodes-node-replication.ts +187 -0
  479. package/src/proxmox/generated/pve/nodes-node-services.ts +221 -0
  480. package/src/proxmox/generated/pve/nodes-node-storage-storage.ts +226 -0
  481. package/src/proxmox/generated/pve/nodes-node-storage.ts +40 -0
  482. package/src/proxmox/generated/pve/nodes-node-subscription.ts +168 -0
  483. package/src/proxmox/generated/pve/nodes-node-vzdump.ts +96 -0
  484. package/src/proxmox/generated/pve/nodes-node.ts +211 -0
  485. package/src/proxmox/generated/pve/nodes.ts +235 -0
  486. package/src/proxmox/generated/pve/pools.ts +78 -0
  487. package/src/proxmox/generated/pve/storage.ts +213 -0
  488. package/src/proxmox/generated/pve/version.ts +21 -0
  489. package/src/proxmox/generated/pve.ts +69 -7403
  490. package/src/proxmox/lxc-interior.test.ts +17 -1
  491. package/src/proxmox/lxc-lifecycle.ts +48 -9
  492. package/src/proxmox/metric-server-form.ts +10 -0
  493. package/src/proxmox/metric-server.ts +11 -2
  494. package/src/proxmox/network-apply.ts +4 -0
  495. package/src/proxmox/node-network-form.ts +19 -0
  496. package/src/proxmox/node-network.ts +9 -3
  497. package/src/proxmox/notification-target-endpoint.ts +46 -0
  498. package/src/proxmox/notification-target-form.ts +11 -0
  499. package/src/proxmox/notification-target.ts +5 -2
  500. package/src/proxmox/pbs-notification-target-endpoint.ts +45 -0
  501. package/src/proxmox/pbs-notification-target-lifecycle.ts +16 -14
  502. package/src/proxmox/qemu.ts +9 -1
  503. package/src/proxmox/resource-guard.ts +61 -0
  504. package/src/proxmox/resource-spec.ts +16 -4
  505. package/src/proxmox/resource.ts +27 -27
  506. package/src/proxmox/sdn-apply.ts +4 -0
  507. package/src/proxmox/sdn-subnet.ts +5 -0
  508. package/src/proxmox/zfs-pool-write.ts +12 -0
  509. package/src/proxmox/zfs-pool.ts +2 -1
  510. package/dist/proxmox/generated/constraints/pve-cluster.d.ts +0 -18
  511. package/dist/proxmox/generated/constraints/pve-cluster.d.ts.map +0 -1
  512. package/src/proxmox/generated/constraints/pve-cluster.ts +0 -174
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/netbox/client.ts", "../src/netbox/constraint-guard.ts", "../src/netbox/constraints.ts", "../src/netbox/generated/constraints/netbox-ipam.ts", "../src/netbox/generated/constraints/index.ts", "../src/netbox/prefix.ts", "../src/netbox/prefix-form.ts", "../src/netbox/resource.ts", "../src/netbox/values.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * One authenticated call to the NetBox REST API at `/api`.\n *\n * ⚠️ `Authorization: Token <value>`, NOT `Bearer`. NetBox is Django REST Framework using DRF's own\n * `TokenAuthentication`. MEASURED on this estate's own instance while it was up: `Bearer`\n * returns 401 and `Token` returns 200. ⛔ A wrong scheme and a wrong credential are\n * indistinguishable in the response, which is why this is written down rather than inferred.\n *\n * ⚠️ NETBOX DOES NOT WRAP A DETAIL RESPONSE THE WAY PVE DOES — a GET of one object returns the\n * object. A LIST, however, IS wrapped: `{count, next, previous, results: [...]}`. A caller that\n * treats a list like a detail sees `undefined` and calls a healthy object absent, which plans a\n * create over something that already exists.\n *\n * ⛔ THE TOKEN IS NEVER A PROP. It is read from `NETBOX_TOKEN` at call time only. Alchemy persists\n * attributes unencrypted; nothing stored here may be a credential.\n */\nimport * as Effect from 'effect/Effect';\nimport * as HttpClient from 'effect/unstable/http/HttpClient';\nimport * as HttpClientRequest from 'effect/unstable/http/HttpClientRequest';\n\nconst PATH_PREFIX = '/api';\n\n/**\n * The instance, from `NETBOX_URL`. Trailing slash stripped.\n *\n * ⛔ NO DEFAULT HOSTNAME AND NO DEFAULT PORT. A published package that fell back to a loopback\n * address would let a consumer who forgot the variable watch every call fail against a machine\n * that is not theirs, instead of being told which variable is missing.\n * ⚠️ Read at CALL time, never at module scope — a value captured at import is pinned to whatever\n * the first isolate saw.\n */\nexport const apiBase = (): string => {\n const raw = process.env['NETBOX_URL'];\n if (raw === undefined || raw.trim() === '') {\n throw new Error(\n 'NETBOX_URL is not set. Point it at your NetBox instance, e.g. https://netbox.example.com',\n );\n }\n return raw.trim().replace(/\\/$/, '');\n};\n\nexport class NetboxError extends Error {\n constructor(\n readonly status: number,\n readonly method: string,\n readonly path: string,\n detail: string,\n ) {\n super(`NetBox ${method} ${path} -> ${String(status)}: ${detail}`);\n this.name = 'NetboxError';\n }\n}\n\nconst token = (): Effect.Effect<string, NetboxError> =>\n Effect.gen(function* () {\n const raw = process.env['NETBOX_TOKEN'];\n if (raw === undefined || raw.trim() === '') {\n return yield* Effect.fail(\n new NetboxError(\n 0,\n 'GET',\n '',\n 'NETBOX_TOKEN is unset. Mint a scoped token and export it — never store it in Alchemy props.',\n ),\n );\n }\n return raw.trim();\n });\n\n/** A NetBox list response. ⚠️ Paginated: `next` is a URL, not a cursor to guess at. */\nexport interface NetboxList<T> {\n readonly count: number;\n readonly next: string | null;\n readonly results: readonly T[];\n}\n\nexport type NetboxRow = Record<string, unknown>;\n\n/** One JSON call. Returns the parsed body, or `undefined` when the response is empty (DELETE). */\nexport const netbox = <T>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n body?: Record<string, unknown>,\n) =>\n Effect.gen(function* () {\n const credential = yield* token();\n const url = `${apiBase()}${PATH_PREFIX}/${path.replace(/^\\//, '')}`;\n /**\n * ★ THROUGH `HttpClient`, NOT THE GLOBAL `fetch` — the idiom Alchemy's own providers follow.\n * It buys a typed error channel, interruption when a plan is cancelled, the runtime's\n * tracing, and a client a test can replace without monkey-patching a global.\n */\n const client = yield* HttpClient.HttpClient;\n /**\n * ⛔ THE CONTENT TYPE GOES ON `bodyText`, NOT IN THE HEADER MAP. `bodyText(s)` with no second\n * argument sets `text/plain` and OVERWRITES a `Content-Type` set by `setHeaders`, because it\n * is piped afterwards. That shipped `@homeflare/alchemy/forgejo` unable to write at all —\n * every create and update in the package, broken identically, for as long as the only\n * credential on the shelf was read-only and so never reached a request body.\n */\n const request = HttpClientRequest.make(method)(url).pipe(\n HttpClientRequest.setHeaders({\n Accept: 'application/json',\n Authorization: `Token ${credential}`,\n }),\n body === undefined\n ? (self) => self\n : HttpClientRequest.bodyText(JSON.stringify(body), 'application/json'),\n );\n const response = yield* client\n .execute(request)\n .pipe(Effect.mapError((cause) => new NetboxError(0, method, path, String(cause))));\n // ⛔ Status first, body once — a NetBox error body is JSON but a reverse proxy's 502 is not.\n // ⚠️ AND A 502 IS THE EXPECTED SYMPTOM WHEN NETBOX IS DOWN BUT ITS FRONT DOOR IS UP, which\n // is the state the reference instance has been in since 2026-09-14. Folding it to \"absent\"\n // would plan a create for every object that already exists.\n if (response.status < 200 || response.status >= 300) {\n const detail = yield* response.text.pipe(Effect.orElseSucceed(() => ''));\n return yield* Effect.fail(\n new NetboxError(response.status, method, path, detail.slice(0, 300)),\n );\n }\n // ⚠️ 204 AND AN EMPTY BODY ARE REAL: a DELETE answers no content, and parsing an empty body\n // throws. Read the text once and parse only when there is something to parse.\n const text = yield* response.text.pipe(\n Effect.mapError((cause) => new NetboxError(0, method, path, String(cause))),\n );\n return (text === '' ? undefined : JSON.parse(text)) as T;\n });\n\n/**\n * The single row a filtered list returns, or `undefined`.\n *\n * ⛔ MORE THAN ONE MATCH IS A DEFECT, NOT A REASON TO TAKE THE FIRST. A `locate` filter that is\n * not unique would let adopt bind to whichever row NetBox happened to order first, and the next\n * plan would bind to the other one and report drift that is not there.\n */\nexport const soleMatch = <T>(rows: readonly T[], describe: string): T | undefined => {\n if (rows.length > 1) {\n throw new Error(\n `${describe} matched ${String(rows.length)} NetBox objects. An object's identity must be ` +\n 'unique; narrow it (the VRF, the site, the tenant) rather than taking the first row.',\n );\n }\n return rows[0];\n};\n",
6
+ "/**\n * The generated tables, looked up by endpoint, and the refusal that stops a plan.\n *\n * ★ ONE FILE BETWEEN THE PROVIDERS AND THE GENERATED DATA, so `resource.ts` gains three lines\n * rather than an import of the generated module and a merge, and so a family that writes its\n * own handlers reaches the same check by the same name.\n *\n * ⛔ AN UNKNOWN KEY IS A DEFECT, NOT A REASON TO SKIP THE CHECK. Silently passing would put us\n * back where this started: a declaration nothing checked, and a plan that says so in no way at\n * all. The generator resolves every key in its source scan against the vendor document, so a\n * key that is absent here means the tables were not regenerated — which the message says.\n */\nimport * as Effect from 'effect/Effect';\nimport {\n type EndpointConstraints,\n type EndpointKey,\n type NetboxBody,\n refusal,\n violations,\n} from './constraints.ts';\nimport { NETBOX_CONSTRAINTS } from './generated/constraints/index.ts';\n\nexport { NETBOX_CONSTRAINTS };\n\nexport const constraintsFor = (key: EndpointKey): EndpointConstraints => {\n const table = NETBOX_CONSTRAINTS[key];\n if (table === undefined) {\n throw new Error(\n `no vendor constraint table for '${key}'. It is named in this package but not generated: ` +\n 'run `bun codegen/netbox.ts` (see codegen/README.md).',\n );\n }\n return table;\n};\n\n/** Every vendor rule this body breaks. Pure — a test calls it with a literal body. */\nexport const bodyViolations = (\n key: EndpointKey,\n body: NetboxBody,\n presence: boolean,\n): readonly string[] => violations(constraintsFor(key), body, { presence });\n\n/**\n * ⛔ `Effect.die`, NOT `Effect.fail`. A declaration the vendor would reject is a DEFECT in the\n * stack file, not a recoverable condition: there is no retry and no fallback that makes a\n * 201-character description legal.\n */\nexport const guardBody = (\n key: EndpointKey | undefined,\n body: NetboxBody,\n presence: boolean,\n): Effect.Effect<void> =>\n Effect.suspend(() => {\n if (key === undefined) return Effect.void;\n const found = bodyViolations(key, body, presence);\n return found.length === 0 ? Effect.void : Effect.die(new Error(refusal(key, found)));\n });\n",
7
+ "/**\n * NetBox's own rules, checked here, before the request is built.\n *\n * 🔴 THE INCIDENT THIS PATTERN EXISTS FOR, 2026-09-22 (Proxmox, not NetBox). `homeflare-proxmox`'s\n * first `deploy:pbs` adopted ten objects and then failed its one create:\n * `comment: value may only be 128 characters long`. Half a deploy in, on the server, from a\n * limit the vendor publishes in its own schema and the generated type did not carry. Plan was\n * green, `bun run check` was green, the adopt verifier was green. ★ NetBox gets the same\n * treatment BEFORE its first write rather than after it.\n *\n * ★ SO THE TABLE IS GENERATED AND THIS FILE IS THE READER. `generated/constraints/*` is emitted\n * from NetBox's own OpenAPI document by `bun codegen/netbox.ts`; nothing here is hand-typed,\n * because a hand-typed limit is tribal knowledge that does not run.\n *\n * ⛔ A SEPARATE READER FROM `../proxmox/constraints.ts`, AND IT IS NOT DUPLICATION. That one\n * checks a `PveForm` — every value already a string, because PVE takes form encoding. A NetBox\n * body is JSON: a number stays a number, a boolean stays a boolean, a foreign key is an\n * integer, and `String(value)` on any of them would make `minimum: 0` pass for `false` and\n * `maxLength` meaningless. Sharing one reader would mean stringifying at the door, which is\n * exactly the mangling the Proxmox version's own ⛔ warns about.\n *\n * ⚠️ WHAT IT DELIBERATELY DOES NOT ENFORCE, so nobody reads a green plan as more than it is:\n * - a `format` NAME (`uri`, `email`, `date-time`): a validator DRF implements server-side.\n * Recorded, never checked.\n * - a pattern the generator could not carry faithfully (codegen/py-pattern.ts). Recorded\n * verbatim as `patternSource`, never checked.\n * - UNIQUENESS, VRF containment, custom-field validators, and every other rule that lives in\n * Django rather than in the schema. Those still arrive as a server-side 400.\n * Each is a fact in the table rather than a guess, which is the rule this follows: if the\n * vendor did not state it, it is not enforced and the table says so.\n */\n\nexport interface ParamConstraint {\n readonly type?: string;\n /** From the schema's `required` array. ⚠️ Checked on CREATE only — see `violations`. */\n readonly required?: boolean;\n readonly maxLength?: number;\n readonly minLength?: number;\n readonly minimum?: number;\n readonly maximum?: number;\n readonly enum?: readonly string[];\n /** A JavaScript-safe translation. Absent when Python's dialect could not be carried over. */\n readonly pattern?: string;\n /** The vendor's own spelling, always — what a violation message quotes, and the audit trail. */\n readonly patternSource?: string;\n /** DRF's server-side validator name. Recorded so a reader knows what is NOT checked here. */\n readonly format?: string;\n readonly default?: string;\n}\n\nexport type EndpointConstraints = Readonly<Record<string, ParamConstraint>>;\n\n/** `netbox:POST /api/ipam/prefixes/` — exactly how the generated tables key an endpoint. */\nexport type EndpointKey = string;\n\n/** A NetBox request body: JSON, with the types the schema declares. */\nexport type NetboxBody = Record<string, unknown>;\n\nexport interface ViolationOptions {\n /**\n * Check that every schema-required property is present.\n *\n * ⛔ CREATE ONLY. A NetBox update is a PATCH and is deliberately PARTIAL — it carries the fields\n * that changed and nothing else — so requiring presence there would refuse every ordinary\n * edit.\n */\n readonly presence?: boolean;\n}\n\n/**\n * ⚠️ `[...value].length`, NOT `value.length`. Django counts characters (Python `len` on a `str`\n * counts code points); JavaScript counts UTF-16 code units, so an emoji in a description counts\n * twice and a 200-character limit would refuse a description NetBox accepts. Rejecting a legal\n * value at plan time is the one failure mode worse than the server 400 this replaces.\n */\nconst lengthOf = (value: string): number => [...value].length;\n\nconst checkString = (name: string, value: string, rule: ParamConstraint): string[] => {\n const out: string[] = [];\n if (rule.maxLength !== undefined && lengthOf(value) > rule.maxLength) {\n out.push(`${name}: at most ${String(rule.maxLength)} characters`);\n }\n if (rule.minLength !== undefined && lengthOf(value) < rule.minLength) {\n out.push(`${name}: at least ${String(rule.minLength)} characters`);\n }\n if (rule.enum !== undefined && !rule.enum.includes(value)) {\n out.push(`${name}: must be one of ${rule.enum.join(', ')}`);\n }\n if (rule.pattern !== undefined && !new RegExp(rule.pattern).test(value)) {\n out.push(`${name}: must match ${rule.patternSource ?? rule.pattern}`);\n }\n return out;\n};\n\n/**\n * ⛔ BOUNDS ARE CHECKED ONLY ON A REAL NUMBER, NEVER ON A COERCED ONE. `Number(false)` is 0 and\n * `Number('')` is 0, so coercing would silently pass a boolean and an empty string through a\n * `minimum: 0`. A NetBox body carries real numbers; anything else is a type error upstream.\n */\nconst checkNumber = (name: string, value: number, rule: ParamConstraint): string[] => {\n const out: string[] = [];\n if (!Number.isFinite(value)) return out;\n if (rule.minimum !== undefined && value < rule.minimum) {\n out.push(`${name}: at least ${String(rule.minimum)}`);\n }\n if (rule.maximum !== undefined && value > rule.maximum) {\n out.push(`${name}: at most ${String(rule.maximum)}`);\n }\n return out;\n};\n\nconst checkValue = (name: string, value: unknown, rule: ParamConstraint): readonly string[] => {\n if (typeof value === 'string') return checkString(name, value, rule);\n if (typeof value === 'number') return checkNumber(name, value, rule);\n return [];\n};\n\n/**\n * Every vendor rule this body breaks, in the order the properties are declared. Pure: no network,\n * no clock, no environment — so `diff` can call it and a test can call it with a literal.\n *\n * ⚠️ A KEY THE TABLE DOES NOT MENTION IS NOT AN ERROR. The table carries the constrained\n * properties, not every property, and a body may legitimately send an unconstrained one.\n * ⚠️ `null` IS A VALUE, NOT AN ABSENCE. NetBox uses explicit `null` to CLEAR a nullable foreign\n * key, so it must not trip the presence check — and no string or number rule applies to it.\n */\nexport const violations = (\n table: EndpointConstraints,\n body: NetboxBody,\n options: ViolationOptions = {},\n): readonly string[] => {\n const out: string[] = [];\n for (const [name, rule] of Object.entries(table)) {\n if (!Object.hasOwn(body, name)) {\n if (options.presence === true && rule.required === true) out.push(`${name}: required`);\n continue;\n }\n const value = body[name];\n // ⚠️ AN ARRAY IS A REPEATED VALUE (tags, and every many-to-many), so every element faces the\n // same rule rather than the array being skipped as \"not a scalar\".\n for (const item of Array.isArray(value) ? value : [value]) {\n out.push(...checkValue(name, item, rule));\n }\n }\n return out;\n};\n\n/** The message a plan dies with. ⛔ Names the endpoint, because the rule belongs to the vendor. */\nexport const refusal = (endpoint: EndpointKey, found: readonly string[]): string =>\n `${endpoint} would be rejected by the vendor:\\n - ${found.join('\\n - ')}\\n` +\n \"These are NetBox's own limits, read from its published OpenAPI document \" +\n '(packages/alchemy/src/netbox/generated/constraints). Fix the declaration.';\n",
8
+ "/**\n * Generated NetBox REST API (OpenAPI 3.0.3) request-body constraints for `/api/ipam` — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/netbox.ts\n * Manifest entry: `netbox-openapi` — NetBox REST API (OpenAPI 3.0.3) 4.7.0\n * sha256 be7f971179b1d6ba, vendor repository, pinned to the release tag\n * contrib/openapi.json in netbox-community/netbox, at tag v4.7.0\n *\n * 2 of this product's 949 POST/PUT/PATCH/DELETE endpoints are tabled across all\n * areas: the ones this package writes to, named in its own source. Every other vendor write\n * endpoint is UNTABLED and therefore unchecked at plan time.\n *\n * ⚠️ A `patternSource` with no `pattern` beside it could NOT be carried into a JavaScript\n * RegExp faithfully — Python's `\\w` is Unicode and JavaScript's is ASCII\n * (codegen/py-pattern.ts). It is recorded and NOT enforced.\n * ⚠️ A FOREIGN KEY CARRIES ONLY ITS TYPE. `tenant`, `vlan`, `role` and friends are\n * `integer|object` in the schema, and the related object's own rules do not govern them.\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\n\nexport const NETBOX_IPAM_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n \"netbox:PATCH /api/ipam/prefixes/{id}/\": {\n \"description\": {\"maxLength\":200,\"type\":\"string\"},\n \"prefix\": {\"minLength\":1,\"type\":\"string\"},\n \"status\": {\"enum\":[\"container\",\"active\",\"reserved\",\"deprecated\"],\"type\":\"string\"},\n },\n \"netbox:POST /api/ipam/prefixes/\": {\n \"description\": {\"maxLength\":200,\"type\":\"string\"},\n \"prefix\": {\"minLength\":1,\"required\":true,\"type\":\"string\"},\n \"status\": {\"enum\":[\"container\",\"active\",\"reserved\",\"deprecated\"],\"type\":\"string\"},\n },\n};\n",
9
+ "/**\n * Every generated NetBox constraint table, merged — DO NOT EDIT BY HAND.\n *\n * Run: bun codegen/netbox.ts\n *\n * ⚠️ EVERY KEY IS PREFIXED `netbox:` FOR THE SAME REASON THE PROXMOX TABLES ARE PREFIXED. One\n * estate runs several vendors and the reader is shared; an unprefixed `POST /api/…` would be\n * one vendor away from colliding.\n */\nimport type { EndpointConstraints } from '../../constraints.ts';\nimport { NETBOX_IPAM_CONSTRAINTS } from './netbox-ipam.ts';\n\nexport const NETBOX_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>> = {\n ...NETBOX_IPAM_CONSTRAINTS,\n};\n\n/**\n * sha256 of the merged table, truncated.\n *\n * ★ A DIGEST OF THE DATA, NOT OF THE FILE TEXT, so reformatting is not a stale generation while\n * changing a 200 to a 201 by hand is. `tests/netbox-manifest.test.ts` recomputes it.\n */\nexport const NETBOX_CONSTRAINTS_DIGEST = '1de1cebe7491d94f';\n",
10
+ "/**\n * `Netbox.Prefix` — one IP prefix and the decision recorded against it.\n *\n * ★ WHY THIS OBJECT CLASS IS THE FIRST ONE, AND NOT `Device`, `VLAN` OR `Site`. Three reasons,\n * each measurable rather than aesthetic:\n *\n * 1. **It is the only interesting NetBox object with no foreign-key prerequisite.** MEASURED in\n * the 4.7.0 schema: `WritablePrefixRequest.required` is exactly `[\"prefix\"]`. A `VLAN` needs\n * `vid` AND `name` and belongs to a group or site; a `Device` needs a role, a type, a site\n * and usually a manufacturer — four more Resources before the first one can be declared.\n * A scaffold that cannot declare anything until five families exist proves nothing.\n * 2. **It is what the estate's NetBox is FOR.** The house's own IPAM agent describes its job as\n * reconciling \"what the network IS against what NetBox says it was DECIDED to be\". A prefix\n * is the atom of that decision. The estate has prefixes whose status is currently recorded\n * only in an SSH config comment and a retirement doc — a management VLAN, a Thunderbolt\n * point-to-point, and three ranges that are retired and still resolve in people's heads.\n * 3. **`status: 'deprecated'` makes retirement declarable.** That is the move this unlocks:\n * a retired range stops being folklore and becomes a line in a stack file with a reviewable\n * diff. No other NetBox class turns an estate decision into one field this cleanly.\n *\n * ⚠️ ADOPT-FRIENDLY BY CONSTRUCTION. `locate` filters on the exact `prefix`; `identifies` then\n * picks the declared VRF, because NetBox allows the same CIDR in two VRFs and in the global\n * table. An instance that already holds `10.0.0.0/24` is BOUND, never duplicated — and ⛔ an\n * adopt never clears prose it did not declare (prefix-form.ts).\n *\n * ⛔ THIS RESOURCE DOES NOT REMOVE PREFIXES IT DOES NOT DECLARE, and `defaultRemovalPolicy` is\n * `retain` (resource.ts). Deleting a prefix in NetBox reparents its children and detaches its\n * IP assignments; the record of why it existed survives only in the change log.\n *\n * ⛔ NO CREDENTIAL IS A PROP. `NETBOX_URL` and `NETBOX_TOKEN` are read from the environment at\n * call time — the house convention, and the only shape that keeps a token out of Alchemy state.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { prefixBody, prefixMatches } from './prefix-form.ts';\nimport { type NetboxRequirements, netboxHandlers } from './resource.ts';\nimport { choice, fk, text } from './values.ts';\n\n/**\n * ⚠️ THE FOUR VALUES ARE THE VENDOR'S, NOT OURS — copied from the generated table, which is\n * generated from NetBox's own enum. The table is what ENFORCES them; this type is what makes\n * the mistake visible in an editor.\n */\nexport type PrefixStatus = 'container' | 'active' | 'reserved' | 'deprecated';\n\nexport interface PrefixProps {\n /** CIDR, exactly as NetBox stores it — `10.0.0.0/24`. The stable key for locate. */\n prefix: string;\n /**\n * VRF id, or omitted for the global table.\n *\n * ⛔ PART OF THE IDENTITY, NOT A SETTING. NetBox's uniqueness on a prefix is per-VRF, so a\n * locate that ignored it could match two rows — which `soleMatch` refuses rather than\n * guessing between.\n */\n vrf?: number;\n status?: PrefixStatus;\n /** ⚠️ `maxLength: 200` in the schema; the generated table enforces it at plan time. */\n description?: string;\n /** Free text. ⚠️ NetBox states no length limit, so nothing here checks one. */\n comments?: string;\n tenant?: number;\n vlan?: number;\n /** All addresses inside are usable. */\n isPool?: boolean;\n markUtilized?: boolean;\n}\n\nexport interface PrefixAttributes {\n prefixId: number;\n prefix: string;\n status: string;\n description: string;\n comments: string;\n vrf: number | undefined;\n tenant: number | undefined;\n vlan: number | undefined;\n isPool: boolean;\n markUtilized: boolean;\n}\n\nexport interface NetboxPrefix extends Resource<\n 'Netbox.Prefix',\n PrefixProps,\n PrefixAttributes,\n never,\n NetboxRequirements\n> {}\n\nexport const NetboxPrefix = Resource<NetboxPrefix>('Netbox.Prefix', {\n defaultRemovalPolicy: 'retain',\n});\n\nconst handlers = netboxHandlers<PrefixProps, PrefixAttributes>({\n attributes: (live, props) => {\n const id = live['id'];\n if (typeof id !== 'number') return undefined;\n return {\n comments: text(live['comments']),\n description: text(live['description']),\n isPool: live['is_pool'] === true,\n markUtilized: live['mark_utilized'] === true,\n prefix: text(live['prefix']) || props.prefix,\n prefixId: id,\n status: choice(live['status']),\n tenant: fk(live['tenant']),\n vlan: fk(live['vlan']),\n vrf: fk(live['vrf']),\n };\n },\n collection: 'ipam/prefixes',\n createBody: prefixBody,\n describe: (props) => `ipam/prefixes ${props.prefix}`,\n endpoint: {\n create: 'netbox:POST /api/ipam/prefixes/',\n update: 'netbox:PATCH /api/ipam/prefixes/{id}/',\n },\n /**\n * 🔴 THE VRF IS **NOT** IN THIS FILTER, AND THE REASON IS A GUESS THAT WAS CAUGHT. This read\n * `vrf_id=null` for the global table — NetBox does define `FILTERS_NULL_CHOICE_VALUE = 'null'`\n * and does honour it on filters that opt in. ⛔ MEASURED IN THE VENDOR'S OWN SOURCE at\n * v4.7.0: `PrefixFilterSet.vrf_id` is a plain `django_filters.ModelMultipleChoiceFilter` with\n * no `null_value`, so `'null'` is validated against the VRF queryset, fails, and NetBox\n * answers 400 under strict filtering — on EVERY plan for EVERY global prefix.\n * ★ So the CIDR narrows server-side with a filter the document plainly declares, and `identifies`\n * picks the VRF in this process. One extra page of candidates, no vendor semantics guessed.\n */\n identifies: (live, props) => fk(live['vrf']) === props.vrf,\n locate: (props) => [['prefix', props.prefix]],\n matches: prefixMatches,\n updateBody: prefixBody,\n});\n\nexport const NetboxPrefixProvider = () =>\n Provider.effect(NetboxPrefix, Effect.succeed(NetboxPrefix.Provider.of(handlers)));\n",
11
+ "/**\n * The wire body for a `Netbox.Prefix`, and the comparison that decides whether it needs writing.\n *\n * ★ EXTRACTED SO IT CAN BE TESTED WITHOUT A SERVER. `body` and `matches` are where a NetBox\n * resource either converges or quietly destroys something, and both are pure functions of the\n * props — so they belong somewhere a test can call them with a literal, the way the Proxmox\n * families keep their `*-form.ts` beside the resource.\n */\nimport type { PrefixAttributes, PrefixProps, PrefixStatus } from './prefix.ts';\n\n/** ⚠️ NetBox's own default when the property is omitted, copied from the schema, not assumed. */\nconst DEFAULT_STATUS: PrefixStatus = 'active';\n\n/**\n * The fields an undeclared prop still settles, because NetBox itself would.\n *\n * ⛔ FREE TEXT IS NOT IN HERE, AND THE LINE IS NOT COSMETIC. `status`, `is_pool` and\n * `mark_utilized` have vendor defaults in the schema — omitting one genuinely means \"the\n * default\", so settling it says what NetBox would have done anyway. `description` and\n * `comments` have no such default: the schema's `''` is the absence of a value, not a decision.\n * Treating \"I did not mention it\" as \"set it to empty\" is how a declaration that says nothing\n * about prose ERASES prose somebody wrote.\n */\nexport const settled = (props: PrefixProps) => ({\n isPool: props.isPool ?? false,\n markUtilized: props.markUtilized ?? false,\n status: props.status ?? DEFAULT_STATUS,\n});\n\n/**\n * ⛔ THE BODY IS BUILT ONCE AND USED FOR BOTH CREATE AND UPDATE, so a field cannot be settable on\n * one path and forgotten on the other — the failure mode that makes a resource converge on\n * create and drift forever after.\n *\n * 🔴 AN UNDECLARED FIELD THAT NETBOX DOES NOT DEFAULT IS OMITTED, NEVER SENT EMPTY OR NULL. This\n * resource shipped sending `description: ''` whenever the prop was absent. On a fresh create\n * that is invisible — the field was empty anyway. ⛔ ON AN ADOPT IT IS DATA LOSS: NetBox is the\n * estate's record of DECISIONS, so the description on an existing prefix is usually the only\n * written trace of why that range exists, and the first deploy that adopted it would have\n * PATCHed it to empty. `matches` would have reported drift, the plan would have said `update`,\n * and the diff would have read as converging a declaration rather than deleting a sentence.\n * ★ THE TELL WAS ALREADY IN THIS FILE: foreign keys were omitted for exactly this reason while\n * free text was not. An inconsistency between two fields with the same hazard is the bug.\n * ⚠️ THE COST IS THAT PROSE CANNOT BE CLEARED BY OMISSION — clearing it is `description: ''`,\n * written on purpose, which is the readable way to say a destructive thing.\n */\nexport const prefixBody = (props: PrefixProps): Record<string, unknown> => {\n const fixed = settled(props);\n const out: Record<string, unknown> = {\n is_pool: fixed.isPool,\n mark_utilized: fixed.markUtilized,\n prefix: props.prefix,\n status: fixed.status,\n };\n if (props.description !== undefined) out['description'] = props.description;\n if (props.comments !== undefined) out['comments'] = props.comments;\n if (props.vrf !== undefined) out['vrf'] = props.vrf;\n if (props.tenant !== undefined) out['tenant'] = props.tenant;\n if (props.vlan !== undefined) out['vlan'] = props.vlan;\n return out;\n};\n\n/**\n * Whether the live object already says what the declaration says.\n *\n * ⛔ EVERY FIELD `prefixBody` OMITS IS ALSO UNCOMPARED HERE, AND THE TWO MUST MOVE TOGETHER. A\n * comparison against a field the body does not send reports drift no write can fix: the plan\n * says `update`, the PATCH omits the field, and the next plan says `update` again — forever.\n * An undeclared prop means \"not mine\", in both directions.\n * ⚠️ `vrf` IS ABSENT ON PURPOSE. It is identity, not settings: `identifies` has already proved\n * this row is in the declared VRF, and a prefix's VRF cannot be edited into another one here.\n */\nexport const prefixMatches = (attributes: PrefixAttributes, props: PrefixProps): boolean => {\n const fixed = settled(props);\n return (\n attributes.status === fixed.status &&\n attributes.isPool === fixed.isPool &&\n attributes.markUtilized === fixed.markUtilized &&\n (props.description === undefined || attributes.description === props.description) &&\n (props.comments === undefined || attributes.comments === props.comments) &&\n (props.tenant === undefined || attributes.tenant === props.tenant) &&\n (props.vlan === undefined || attributes.vlan === props.vlan)\n );\n};\n",
12
+ "/**\n * One shape for every NetBox object — the same four operations, different path and JSON body.\n *\n * ⛔ THE ALTERNATIVE IS COPYING THE SAME HANDLERS PER RESOURCE. Prefixes, VLANs, devices, tenants\n * and interfaces are all create / read / update / delete over `/api` with JSON bodies and a\n * numeric primary key. Hand-rolling the fourth copy is where someone drops the read-back or the\n * constraint guard and the plan lies.\n *\n * ★ ADOPT IS THE DEFAULT POSTURE, NOT A FLAG. `reconcile` LOCATES before it writes: an object the\n * estate already has is bound, not duplicated. NetBox is a record that predates this code by\n * years; a provider that created a second `10.20.10.0/24` on first deploy would be worse than\n * no provider.\n *\n * ★ `defaultRemovalPolicy: 'retain'` ON EVERY FAMILY. NetBox holds the estate's record of what\n * the network was DECIDED to be, and deleting a row deletes history — child prefixes reparent,\n * IP assignments detach, and the change log is the only trace left. `retain` means the engine\n * skips `delete` when a resource is orphaned unless the caller opts into\n * `.pipe(RemovalPolicy.destroy())`. The `delete` handler is FULLY IMPLEMENTED anyway: a stub\n * that silently does nothing lies to whoever reads the plan.\n */\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { NetboxError, type NetboxList, type NetboxRow, netbox, soleMatch } from './client.ts';\nimport { guardBody } from './constraint-guard.ts';\nimport type { EndpointKey, NetboxBody } from './constraints.ts';\n\n/**\n * ★ WHAT EVERY OPERATION HERE NEEDS FROM THE RUNTIME, AND NOTHING MORE. The token comes from\n * `NETBOX_TOKEN` in the environment, so there is no process to spawn and no `bao` to shell out\n * to. Declaring a service you never use is not harmless — it makes a stack provide a layer for\n * nothing, and it hides the one service you DO need.\n */\nexport type NetboxRequirements = HttpClient.HttpClient;\n\nexport interface NetboxSpec<Props extends object, Attributes> {\n /** `ipam/prefixes` — where a new one is POSTed and where `locate` filters. */\n readonly collection: string;\n /**\n * The query that narrows the candidates, as `URLSearchParams` pairs.\n *\n * ⛔ ONLY FILTERS THE VENDOR DOCUMENT DECLARES, AND ONLY IN THE FORM IT DECLARES THEM. A\n * filter NetBox rejects answers 400, which `absentOn404` correctly does NOT fold to \"absent\" —\n * so a guessed filter shape is a hard failure on every plan, not a soft one.\n * ★ IT DOES NOT HAVE TO BE UNIQUE. `identifies` finishes the job in this process, where the\n * rule is readable and testable offline.\n */\n readonly locate: (props: Props) => readonly (readonly [string, string])[];\n /**\n * Which of the returned rows IS this object.\n *\n * 🔴 THIS EXISTS BECAUSE THE OBVIOUS ALTERNATIVE WAS A GUESS. `Netbox.Prefix` first narrowed\n * server-side with `vrf_id=null`, the sentinel NetBox uses elsewhere for \"no foreign key\".\n * ⛔ MEASURED IN THE VENDOR'S OWN SOURCE at v4.7.0: `PrefixFilterSet.vrf_id` is a plain\n * `django_filters.ModelMultipleChoiceFilter` with NO `null_value`, so `'null'` is validated\n * against the VRF queryset, fails, and NetBox answers 400 under strict filtering. The\n * sentinel is real (`FILTERS_NULL_CHOICE_VALUE = 'null'`) but it is opt-in per filter, and\n * this one did not opt in.\n * ★ SO THE DISCRIMINATOR MOVED INTO THIS PROCESS. It costs one page of candidates and buys a\n * rule that can be read, tested without a server, and cannot be wrong about a vendor's\n * filter semantics. Omit it when `locate` really is unique on its own.\n */\n readonly identifies?: (live: NetboxRow, props: Props) => boolean;\n readonly attributes: (live: NetboxRow, props: Props) => Attributes | undefined;\n readonly createBody: (props: Props) => NetboxBody;\n /** ⚠️ PARTIAL BY DESIGN: NetBox updates are PATCH, so presence is not checked on this body. */\n readonly updateBody?: (props: Props) => NetboxBody;\n readonly matches: (attributes: Attributes, props: Props) => boolean;\n /** The generated constraint table to check each body against, by endpoint key. */\n readonly endpoint: { readonly create: EndpointKey; readonly update?: EndpointKey };\n /** For the message `soleMatch` raises and for read-back failures. */\n readonly describe: (props: Props) => string;\n}\n\n/** ⚠️ Only 404 folds to \"absent\". A 403 or a 502 is a real failure — folding it would plan a create over an existing object. */\nconst absentOn404 = <A>(io: Effect.Effect<A, NetboxError, NetboxRequirements>) =>\n io.pipe(\n Effect.catchIf(\n (cause): cause is NetboxError => cause instanceof NetboxError && cause.status === 404,\n () => Effect.succeed(undefined as A),\n ),\n );\n\n/**\n * ⚠️ NOT `limit=1`, AND NOT `limit=2` EITHER. One row is all a caller wants, but the page has to\n * be wide enough for `identifies` to see every candidate `locate` matched — a prefix that\n * exists in several VRFs comes back several times, and a page of two would hide the third.\n * ★ TWENTY, AND THE NUMBER IS AN ASSERTION: a natural key matching more than twenty rows is not\n * a natural key. `count` is checked against it, so the failure is \"your filter is too broad\"\n * rather than a silent truncation.\n */\nconst LOCATE_PAGE = 20;\n\nconst query = (pairs: readonly (readonly [string, string])[]): string =>\n new URLSearchParams([\n ...pairs.map(([k, v]) => [k, v] as [string, string]),\n ['limit', String(LOCATE_PAGE)],\n ]).toString();\n\nexport const netboxOperations = <Props extends object, Attributes>(\n spec: NetboxSpec<Props, Attributes>,\n) => {\n const fetchLive = (props: Props) =>\n absentOn404(\n netbox<NetboxList<NetboxRow>>('GET', `${spec.collection}/?${query(spec.locate(props))}`),\n ).pipe(\n Effect.map((list) => {\n if (list !== undefined && list.count > LOCATE_PAGE) {\n throw new Error(\n `${spec.describe(props)}: the locate filter matched ${String(list.count)} rows, more ` +\n `than the ${String(LOCATE_PAGE)}-row page this reads. That is not a natural key — ` +\n 'narrow the filter rather than paging through candidates.',\n );\n }\n const rows = list?.results ?? [];\n const narrow = spec.identifies;\n return soleMatch(\n narrow === undefined ? rows : rows.filter((row) => narrow(row, props)),\n spec.describe(props),\n );\n }),\n );\n\n /** ⛔ The numeric `id` is the wire path. NetBox has no update-by-natural-key. */\n const objectPath = (live: NetboxRow): string => `${spec.collection}/${String(live['id'])}`;\n\n const read = (props: Props) =>\n fetchLive(props).pipe(\n Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))),\n );\n\n return {\n read,\n\n diff: (news: Input<Props>, output: Attributes | undefined) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* read(news);\n if (live === undefined) return { action: 'update' } as const;\n if (spec.matches(live, news)) return { action: 'noop' } as const;\n return spec.updateBody === undefined\n ? ({ action: 'replace' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: (news: Props) =>\n Effect.gen(function* () {\n const before = yield* fetchLive(news);\n if (before === undefined) {\n const body = spec.createBody(news);\n // ⛔ GUARD BEFORE THE REQUEST, WITH PRESENCE ON. This is the only place a missing\n // required property can still be caught locally.\n yield* guardBody(spec.endpoint.create, body, true);\n yield* netbox('POST', `${spec.collection}/`, body);\n } else if (spec.updateBody !== undefined) {\n const mapped = spec.attributes(before, news);\n // ⚠️ ADOPTION IS THE `mapped === undefined` CASE TOO: a row this spec cannot map is not\n // a row to PATCH blindly.\n if (mapped !== undefined && !spec.matches(mapped, news)) {\n const body = spec.updateBody(news);\n yield* guardBody(spec.endpoint.update, body, false);\n if (Object.keys(body).length > 0) {\n yield* netbox('PATCH', `${objectPath(before)}/`, body);\n }\n }\n }\n const after = yield* read(news);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `${spec.describe(news)}: the write returned no error but the object is still ` +\n 'absent. NetBox returns the object it wrote — read back rather than trusting the ' +\n 'status code.',\n ),\n );\n }\n return after;\n }),\n\n destroy: (olds: Props) =>\n Effect.gen(function* () {\n const live = yield* fetchLive(olds);\n if (live === undefined) return;\n yield* netbox('DELETE', `${objectPath(live)}/`);\n }),\n };\n};\n\n/**\n * The five provider handlers for a spec'd NetBox object, wired once.\n *\n * ⚠️ `list` answers empty. NetBox index endpoints return the whole estate — tens of thousands of\n * rows on a real instance — so adoption stays explicit rather than sweeping.\n */\nexport const netboxHandlers = <Props extends object, Attributes extends object>(\n spec: NetboxSpec<Props, Attributes>,\n) => {\n const ops = netboxOperations(spec);\n return {\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: Props }) => ops.read(olds),\n diff: ({ news, output }: { news: Input<Props>; output: Attributes | undefined }) =>\n ops.diff(news, output),\n reconcile: ({ news }: { news: Props }) => ops.reconcile(news),\n delete: ({ olds }: { olds: Props }) => ops.destroy(olds),\n };\n};\n",
13
+ "/**\n * Reading a NetBox row into settled values.\n *\n * ⛔ A NETBOX READ AND A NETBOX WRITE ARE NOT THE SAME SHAPE, AND THIS IS WHERE THAT IS HANDLED.\n * MEASURED in the 4.7.0 document: `WritablePrefixRequest.status` is a bare string enum\n * (`\"active\"`), while `Prefix.status` on the way back is an OBJECT — `{value, label}`. A `diff`\n * that compared the declared string against the live object would see drift on every plan, for\n * every prefix, forever, and each \"update\" would PATCH the same value back.\n * ⚠️ The same asymmetry holds for every choice field in NetBox (`dcim` device `status`,\n * `ipam` IP `role`, …). Anything read through `choice` is safe against it.\n */\n\n/** ⚠️ `''` for absent, not `undefined` — NetBox stores an empty string, never null, for text. */\nexport const text = (value: unknown): string => (typeof value === 'string' ? value : '');\n\nexport const bool = (value: unknown): boolean => value === true;\n\n/** A `{value, label}` choice object, reduced to the string a declaration writes. */\nexport const choice = (value: unknown): string => {\n if (typeof value === 'string') return value;\n if (typeof value === 'object' && value !== null && 'value' in value) {\n return text((value as { value: unknown }).value);\n }\n return '';\n};\n\n/**\n * A foreign key, as the integer a declaration writes.\n *\n * ⚠️ IT ARRIVES AS A NESTED OBJECT ON READ AND AN INTEGER ON WRITE — `{id, url, display, …}`\n * versus `4`. Comparing the two directly is the same never-converges bug as `choice`.\n */\nexport const fk = (value: unknown): number | undefined => {\n if (typeof value === 'number') return value;\n if (typeof value === 'object' && value !== null && 'id' in value) {\n const id = (value as { id: unknown }).id;\n return typeof id === 'number' ? id : undefined;\n }\n return undefined;\n};\n"
14
+ ],
15
+ "mappings": "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",
16
+ "debugId": "8207BD9178A5636864756E2164756E21",
17
+ "names": []
18
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The wire body for a `Netbox.Prefix`, and the comparison that decides whether it needs writing.
3
+ *
4
+ * ★ EXTRACTED SO IT CAN BE TESTED WITHOUT A SERVER. `body` and `matches` are where a NetBox
5
+ * resource either converges or quietly destroys something, and both are pure functions of the
6
+ * props — so they belong somewhere a test can call them with a literal, the way the Proxmox
7
+ * families keep their `*-form.ts` beside the resource.
8
+ */
9
+ import type { PrefixAttributes, PrefixProps, PrefixStatus } from './prefix.ts';
10
+ /**
11
+ * The fields an undeclared prop still settles, because NetBox itself would.
12
+ *
13
+ * ⛔ FREE TEXT IS NOT IN HERE, AND THE LINE IS NOT COSMETIC. `status`, `is_pool` and
14
+ * `mark_utilized` have vendor defaults in the schema — omitting one genuinely means "the
15
+ * default", so settling it says what NetBox would have done anyway. `description` and
16
+ * `comments` have no such default: the schema's `''` is the absence of a value, not a decision.
17
+ * Treating "I did not mention it" as "set it to empty" is how a declaration that says nothing
18
+ * about prose ERASES prose somebody wrote.
19
+ */
20
+ export declare const settled: (props: PrefixProps) => {
21
+ isPool: boolean;
22
+ markUtilized: boolean;
23
+ status: PrefixStatus;
24
+ };
25
+ /**
26
+ * ⛔ THE BODY IS BUILT ONCE AND USED FOR BOTH CREATE AND UPDATE, so a field cannot be settable on
27
+ * one path and forgotten on the other — the failure mode that makes a resource converge on
28
+ * create and drift forever after.
29
+ *
30
+ * 🔴 AN UNDECLARED FIELD THAT NETBOX DOES NOT DEFAULT IS OMITTED, NEVER SENT EMPTY OR NULL. This
31
+ * resource shipped sending `description: ''` whenever the prop was absent. On a fresh create
32
+ * that is invisible — the field was empty anyway. ⛔ ON AN ADOPT IT IS DATA LOSS: NetBox is the
33
+ * estate's record of DECISIONS, so the description on an existing prefix is usually the only
34
+ * written trace of why that range exists, and the first deploy that adopted it would have
35
+ * PATCHed it to empty. `matches` would have reported drift, the plan would have said `update`,
36
+ * and the diff would have read as converging a declaration rather than deleting a sentence.
37
+ * ★ THE TELL WAS ALREADY IN THIS FILE: foreign keys were omitted for exactly this reason while
38
+ * free text was not. An inconsistency between two fields with the same hazard is the bug.
39
+ * ⚠️ THE COST IS THAT PROSE CANNOT BE CLEARED BY OMISSION — clearing it is `description: ''`,
40
+ * written on purpose, which is the readable way to say a destructive thing.
41
+ */
42
+ export declare const prefixBody: (props: PrefixProps) => Record<string, unknown>;
43
+ /**
44
+ * Whether the live object already says what the declaration says.
45
+ *
46
+ * ⛔ EVERY FIELD `prefixBody` OMITS IS ALSO UNCOMPARED HERE, AND THE TWO MUST MOVE TOGETHER. A
47
+ * comparison against a field the body does not send reports drift no write can fix: the plan
48
+ * says `update`, the PATCH omits the field, and the next plan says `update` again — forever.
49
+ * An undeclared prop means "not mine", in both directions.
50
+ * ⚠️ `vrf` IS ABSENT ON PURPOSE. It is identity, not settings: `identifies` has already proved
51
+ * this row is in the declared VRF, and a prefix's VRF cannot be edited into another one here.
52
+ */
53
+ export declare const prefixMatches: (attributes: PrefixAttributes, props: PrefixProps) => boolean;
54
+ //# sourceMappingURL=prefix-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix-form.d.ts","sourceRoot":"","sources":["../../src/netbox/prefix-form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK/E;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,UAAW,WAAW;IACxC,MAAM;IACN,YAAY;IACZ,MAAM;CACN,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAcrE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,eAAgB,gBAAgB,SAAS,WAAW,KAAG,OAWhF,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * `Netbox.Prefix` — one IP prefix and the decision recorded against it.
3
+ *
4
+ * ★ WHY THIS OBJECT CLASS IS THE FIRST ONE, AND NOT `Device`, `VLAN` OR `Site`. Three reasons,
5
+ * each measurable rather than aesthetic:
6
+ *
7
+ * 1. **It is the only interesting NetBox object with no foreign-key prerequisite.** MEASURED in
8
+ * the 4.7.0 schema: `WritablePrefixRequest.required` is exactly `["prefix"]`. A `VLAN` needs
9
+ * `vid` AND `name` and belongs to a group or site; a `Device` needs a role, a type, a site
10
+ * and usually a manufacturer — four more Resources before the first one can be declared.
11
+ * A scaffold that cannot declare anything until five families exist proves nothing.
12
+ * 2. **It is what the estate's NetBox is FOR.** The house's own IPAM agent describes its job as
13
+ * reconciling "what the network IS against what NetBox says it was DECIDED to be". A prefix
14
+ * is the atom of that decision. The estate has prefixes whose status is currently recorded
15
+ * only in an SSH config comment and a retirement doc — a management VLAN, a Thunderbolt
16
+ * point-to-point, and three ranges that are retired and still resolve in people's heads.
17
+ * 3. **`status: 'deprecated'` makes retirement declarable.** That is the move this unlocks:
18
+ * a retired range stops being folklore and becomes a line in a stack file with a reviewable
19
+ * diff. No other NetBox class turns an estate decision into one field this cleanly.
20
+ *
21
+ * ⚠️ ADOPT-FRIENDLY BY CONSTRUCTION. `locate` filters on the exact `prefix`; `identifies` then
22
+ * picks the declared VRF, because NetBox allows the same CIDR in two VRFs and in the global
23
+ * table. An instance that already holds `10.0.0.0/24` is BOUND, never duplicated — and ⛔ an
24
+ * adopt never clears prose it did not declare (prefix-form.ts).
25
+ *
26
+ * ⛔ THIS RESOURCE DOES NOT REMOVE PREFIXES IT DOES NOT DECLARE, and `defaultRemovalPolicy` is
27
+ * `retain` (resource.ts). Deleting a prefix in NetBox reparents its children and detaches its
28
+ * IP assignments; the record of why it existed survives only in the change log.
29
+ *
30
+ * ⛔ NO CREDENTIAL IS A PROP. `NETBOX_URL` and `NETBOX_TOKEN` are read from the environment at
31
+ * call time — the house convention, and the only shape that keeps a token out of Alchemy state.
32
+ */
33
+ import { Resource } from 'alchemy';
34
+ import * as Provider from 'alchemy/Provider';
35
+ import { type NetboxRequirements } from './resource.ts';
36
+ /**
37
+ * ⚠️ THE FOUR VALUES ARE THE VENDOR'S, NOT OURS — copied from the generated table, which is
38
+ * generated from NetBox's own enum. The table is what ENFORCES them; this type is what makes
39
+ * the mistake visible in an editor.
40
+ */
41
+ export type PrefixStatus = 'container' | 'active' | 'reserved' | 'deprecated';
42
+ export interface PrefixProps {
43
+ /** CIDR, exactly as NetBox stores it — `10.0.0.0/24`. The stable key for locate. */
44
+ prefix: string;
45
+ /**
46
+ * VRF id, or omitted for the global table.
47
+ *
48
+ * ⛔ PART OF THE IDENTITY, NOT A SETTING. NetBox's uniqueness on a prefix is per-VRF, so a
49
+ * locate that ignored it could match two rows — which `soleMatch` refuses rather than
50
+ * guessing between.
51
+ */
52
+ vrf?: number;
53
+ status?: PrefixStatus;
54
+ /** ⚠️ `maxLength: 200` in the schema; the generated table enforces it at plan time. */
55
+ description?: string;
56
+ /** Free text. ⚠️ NetBox states no length limit, so nothing here checks one. */
57
+ comments?: string;
58
+ tenant?: number;
59
+ vlan?: number;
60
+ /** All addresses inside are usable. */
61
+ isPool?: boolean;
62
+ markUtilized?: boolean;
63
+ }
64
+ export interface PrefixAttributes {
65
+ prefixId: number;
66
+ prefix: string;
67
+ status: string;
68
+ description: string;
69
+ comments: string;
70
+ vrf: number | undefined;
71
+ tenant: number | undefined;
72
+ vlan: number | undefined;
73
+ isPool: boolean;
74
+ markUtilized: boolean;
75
+ }
76
+ export interface NetboxPrefix extends Resource<'Netbox.Prefix', PrefixProps, PrefixAttributes, never, NetboxRequirements> {
77
+ }
78
+ export declare const NetboxPrefix: import("alchemy").ResourceClass<NetboxPrefix>;
79
+ export declare const NetboxPrefixProvider: () => import("effect/Layer").Layer<Provider.Provider<NetboxPrefix>, never, import("effect/unstable/http/HttpClient").HttpClient>;
80
+ //# sourceMappingURL=prefix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix.d.ts","sourceRoot":"","sources":["../../src/netbox/prefix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,KAAK,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AAGxE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;AAE9E,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,kBAAkB,CACnB;CAAG;AAEJ,eAAO,MAAM,YAAY,+CAEvB,CAAC;AA0CH,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
@@ -0,0 +1,94 @@
1
+ import type { Input } from 'alchemy/Input';
2
+ import * as Effect from 'effect/Effect';
3
+ import type * as HttpClient from 'effect/unstable/http/HttpClient';
4
+ import { NetboxError, type NetboxRow } from './client.ts';
5
+ import type { EndpointKey, NetboxBody } from './constraints.ts';
6
+ /**
7
+ * ★ WHAT EVERY OPERATION HERE NEEDS FROM THE RUNTIME, AND NOTHING MORE. The token comes from
8
+ * `NETBOX_TOKEN` in the environment, so there is no process to spawn and no `bao` to shell out
9
+ * to. Declaring a service you never use is not harmless — it makes a stack provide a layer for
10
+ * nothing, and it hides the one service you DO need.
11
+ */
12
+ export type NetboxRequirements = HttpClient.HttpClient;
13
+ export interface NetboxSpec<Props extends object, Attributes> {
14
+ /** `ipam/prefixes` — where a new one is POSTed and where `locate` filters. */
15
+ readonly collection: string;
16
+ /**
17
+ * The query that narrows the candidates, as `URLSearchParams` pairs.
18
+ *
19
+ * ⛔ ONLY FILTERS THE VENDOR DOCUMENT DECLARES, AND ONLY IN THE FORM IT DECLARES THEM. A
20
+ * filter NetBox rejects answers 400, which `absentOn404` correctly does NOT fold to "absent" —
21
+ * so a guessed filter shape is a hard failure on every plan, not a soft one.
22
+ * ★ IT DOES NOT HAVE TO BE UNIQUE. `identifies` finishes the job in this process, where the
23
+ * rule is readable and testable offline.
24
+ */
25
+ readonly locate: (props: Props) => readonly (readonly [string, string])[];
26
+ /**
27
+ * Which of the returned rows IS this object.
28
+ *
29
+ * 🔴 THIS EXISTS BECAUSE THE OBVIOUS ALTERNATIVE WAS A GUESS. `Netbox.Prefix` first narrowed
30
+ * server-side with `vrf_id=null`, the sentinel NetBox uses elsewhere for "no foreign key".
31
+ * ⛔ MEASURED IN THE VENDOR'S OWN SOURCE at v4.7.0: `PrefixFilterSet.vrf_id` is a plain
32
+ * `django_filters.ModelMultipleChoiceFilter` with NO `null_value`, so `'null'` is validated
33
+ * against the VRF queryset, fails, and NetBox answers 400 under strict filtering. The
34
+ * sentinel is real (`FILTERS_NULL_CHOICE_VALUE = 'null'`) but it is opt-in per filter, and
35
+ * this one did not opt in.
36
+ * ★ SO THE DISCRIMINATOR MOVED INTO THIS PROCESS. It costs one page of candidates and buys a
37
+ * rule that can be read, tested without a server, and cannot be wrong about a vendor's
38
+ * filter semantics. Omit it when `locate` really is unique on its own.
39
+ */
40
+ readonly identifies?: (live: NetboxRow, props: Props) => boolean;
41
+ readonly attributes: (live: NetboxRow, props: Props) => Attributes | undefined;
42
+ readonly createBody: (props: Props) => NetboxBody;
43
+ /** ⚠️ PARTIAL BY DESIGN: NetBox updates are PATCH, so presence is not checked on this body. */
44
+ readonly updateBody?: (props: Props) => NetboxBody;
45
+ readonly matches: (attributes: Attributes, props: Props) => boolean;
46
+ /** The generated constraint table to check each body against, by endpoint key. */
47
+ readonly endpoint: {
48
+ readonly create: EndpointKey;
49
+ readonly update?: EndpointKey;
50
+ };
51
+ /** For the message `soleMatch` raises and for read-back failures. */
52
+ readonly describe: (props: Props) => string;
53
+ }
54
+ export declare const netboxOperations: <Props extends object, Attributes>(spec: NetboxSpec<Props, Attributes>) => {
55
+ read: (props: Props) => Effect.Effect<Attributes | undefined, never, HttpClient.HttpClient>;
56
+ diff: (news: Input<Props>, output: Attributes | undefined) => Effect.Effect<{
57
+ readonly action: 'update';
58
+ } | {
59
+ readonly action: 'noop';
60
+ } | {
61
+ readonly action: 'replace';
62
+ } | undefined, never, HttpClient.HttpClient>;
63
+ reconcile: (news: Props) => Effect.Effect<Attributes & ({} | null), NetboxError, HttpClient.HttpClient>;
64
+ destroy: (olds: Props) => Effect.Effect<void, NetboxError, HttpClient.HttpClient>;
65
+ };
66
+ /**
67
+ * The five provider handlers for a spec'd NetBox object, wired once.
68
+ *
69
+ * ⚠️ `list` answers empty. NetBox index endpoints return the whole estate — tens of thousands of
70
+ * rows on a real instance — so adoption stays explicit rather than sweeping.
71
+ */
72
+ export declare const netboxHandlers: <Props extends object, Attributes extends object>(spec: NetboxSpec<Props, Attributes>) => {
73
+ list: () => Effect.Effect<never[], never, never>;
74
+ read: ({ olds }: {
75
+ olds: Props;
76
+ }) => Effect.Effect<Attributes | undefined, never, HttpClient.HttpClient>;
77
+ diff: ({ news, output }: {
78
+ news: Input<Props>;
79
+ output: Attributes | undefined;
80
+ }) => Effect.Effect<{
81
+ readonly action: 'update';
82
+ } | {
83
+ readonly action: 'noop';
84
+ } | {
85
+ readonly action: 'replace';
86
+ } | undefined, never, HttpClient.HttpClient>;
87
+ reconcile: ({ news }: {
88
+ news: Props;
89
+ }) => Effect.Effect<Attributes, NetboxError, HttpClient.HttpClient>;
90
+ delete: ({ olds }: {
91
+ olds: Props;
92
+ }) => Effect.Effect<void, NetboxError, HttpClient.HttpClient>;
93
+ };
94
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/netbox/resource.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAmB,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAE9F,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,UAAU,CAAC;AAEvD,MAAM,WAAW,UAAU,CAAC,KAAK,SAAS,MAAM,EAAE,UAAU;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC1E;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACjE,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,KAAK,UAAU,GAAG,SAAS,CAAC;IAC/E,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,UAAU,CAAC;IAClD,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,UAAU,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACpE,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IACnF,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC;CAC7C;AA2BD,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,MAAM,EAAE,UAAU,QACzD,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC;kBA0Bd,KAAK;iBAQX,KAAK,CAAC,KAAK,CAAC,UAAU,UAAU,GAAG,SAAS;yBAIZ,QAAQ;;yBACF,MAAM;;yBAEtC,SAAS;;sBAIV,KAAK;oBAkCP,KAAK;CAOxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM,QACtE,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC;IAIjC,IAAI;IACJ,IAAI,aAAa;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IAChC,IAAI,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;yBA/DlC,QAAQ;;yBACF,MAAM;;yBAEtC,SAAS;;IA8D5B,SAAS,aAAa;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IACrC,MAAM,aAAa;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;CAErC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Reading a NetBox row into settled values.
3
+ *
4
+ * ⛔ A NETBOX READ AND A NETBOX WRITE ARE NOT THE SAME SHAPE, AND THIS IS WHERE THAT IS HANDLED.
5
+ * MEASURED in the 4.7.0 document: `WritablePrefixRequest.status` is a bare string enum
6
+ * (`"active"`), while `Prefix.status` on the way back is an OBJECT — `{value, label}`. A `diff`
7
+ * that compared the declared string against the live object would see drift on every plan, for
8
+ * every prefix, forever, and each "update" would PATCH the same value back.
9
+ * ⚠️ The same asymmetry holds for every choice field in NetBox (`dcim` device `status`,
10
+ * `ipam` IP `role`, …). Anything read through `choice` is safe against it.
11
+ */
12
+ /** ⚠️ `''` for absent, not `undefined` — NetBox stores an empty string, never null, for text. */
13
+ export declare const text: (value: unknown) => string;
14
+ export declare const bool: (value: unknown) => boolean;
15
+ /** A `{value, label}` choice object, reduced to the string a declaration writes. */
16
+ export declare const choice: (value: unknown) => string;
17
+ /**
18
+ * A foreign key, as the integer a declaration writes.
19
+ *
20
+ * ⚠️ IT ARRIVES AS A NESTED OBJECT ON READ AND AN INTEGER ON WRITE — `{id, url, display, …}`
21
+ * versus `4`. Comparing the two directly is the same never-converges bug as `choice`.
22
+ */
23
+ export declare const fk: (value: unknown) => number | undefined;
24
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/netbox/values.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iGAAiG;AACjG,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,MAAkD,CAAC;AAEzF,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,OAAyB,CAAC;AAEhE,oFAAoF;AACpF,eAAO,MAAM,MAAM,UAAW,OAAO,KAAG,MAMvC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,EAAE,UAAW,OAAO,KAAG,MAAM,GAAG,SAO5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"api-token-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token-form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxE;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,UAAW,aAAa,WAAuC,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,KAAK,UAAW,aAAa,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAIhE,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,kBAAkB,CAwDnE,CAAC"}
1
+ {"version":3,"file":"api-token-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token-form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxE;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,UAAW,aAAa,WAAuC,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,KAAK,UAAW,aAAa,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAIhE,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,kBAAkB,CA6DnE,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The two applies, and the vendor endpoints they publish through.
3
+ *
4
+ * ★ AN ACTION ENDPOINT IS STILL WIRED, EVEN THOUGH ITS TABLE IS EMPTY, AND THE REASON IS THE
5
+ * GENERATOR RATHER THAN THE VALIDATOR. `PUT /nodes/{node}/network` and `PUT /cluster/sdn` take
6
+ * no body at all — there is nothing for a length or a range to be wrong about — but
7
+ * `codegen/constraints.ts` RESOLVES every key named in this package against the vendor's own
8
+ * schema and STOPS when one is absent. So the key buys the thing these two families most need:
9
+ * a PVE that moves, renames or withdraws the apply fails `bun run check` instead of failing an
10
+ * `ifreload -a` on three nodes at once.
11
+ * ⚠️ AND THE LOOKUP IS NOT FREE EITHER. `constraintsFor` throws when a key has no table, so a
12
+ * checkout whose generated tables were never refreshed refuses the apply with the command to
13
+ * run rather than quietly doing nothing — the same defect `constraint-guard.ts` names.
14
+ *
15
+ * ⛔ NEITHER OF THESE IS A CREATE, AND NEITHER FAMILY HAS A `PveSpec`. Both write their own five
16
+ * handlers (an apply is not an object — see the ⛔ in each file), so they reach the shared check
17
+ * through `guardForm` by name, exactly as `pbs-datastore-endpoint.ts` does.
18
+ */
19
+ import type * as Effect from 'effect/Effect';
20
+ import type { EndpointKey } from './constraints.ts';
21
+ /** ⚠️ `{node}` is a path segment, so this really does take no form keys at all. */
22
+ export declare const NETWORK_APPLY_ENDPOINT: EndpointKey;
23
+ /**
24
+ * ⛔ CLUSTER-WIDE. One PUT publishes every staged zone, vnet and subnet on every node; there is no
25
+ * per-object apply and no pre-apply veto. `sdn-apply.ts` is the whole argument.
26
+ */
27
+ export declare const SDN_APPLY_ENDPOINT: EndpointKey;
28
+ export declare const guardNetworkApply: Effect.Effect<void>;
29
+ export declare const guardSdnApply: Effect.Effect<void>;
30
+ //# sourceMappingURL=apply-endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-endpoints.d.ts","sourceRoot":"","sources":["../../src/proxmox/apply-endpoints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,EAAE,WAA6C,CAAC;AAEnF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAoC,CAAC;AAEtE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAA+C,CAAC;AAElG,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAA2C,CAAC"}
@@ -28,7 +28,24 @@
28
28
  * the task in the PVE UI before concluding the create failed.
29
29
  *
30
30
  */
31
- import type { CephDaemonProps } from './ceph-daemon.ts';
31
+ import type { CephDaemonAttributes, CephDaemonKind, CephDaemonProps } from './ceph-daemon.ts';
32
+ import type { EndpointPair } from './resource-spec.ts';
33
+ /**
34
+ * The vendor endpoint each kind is created at, as the generated tables key it.
35
+ *
36
+ * ⛔ ONE PER KIND, NOT A `{type}` PATH. PVE registers `mds`, `mgr` and `mon` as three separate
37
+ * nodes with three separate parameter schemas — `hotstandby` belongs to the first and
38
+ * `mon-address` to the third — so a single key would enforce one kind's rules on all three.
39
+ * That is why `PveSpec['endpoint']` admits a function of props at all.
40
+ * ⛔ THE STRINGS MUST STAY LITERALS. `codegen/constraints.ts` finds the endpoints to table by
41
+ * SCANNING THIS PACKAGE'S TEXT, so a key assembled from `props.kind` would be tabled by
42
+ * nothing and `constraintsFor` would throw on the first deploy that reached it.
43
+ * ⚠️ THE PARAMETER NAMES DIFFER AND ARE THE VENDOR'S OWN — `{name}`, `{id}`, `{monid}`. The
44
+ * generator resolves each against the schema, so a tidied-up spelling stops the build.
45
+ * ⚠️ NO `update` ON ANY OF THEM: none of the three has a PUT, which is why the spec declares no
46
+ * `updateForm` either.
47
+ */
48
+ export declare const DAEMON_ENDPOINTS: Readonly<Record<CephDaemonKind, EndpointPair>>;
32
49
  /**
33
50
  * PVE defaults the id to the nodename for all three kinds, and that default is resolved HERE
34
51
  * rather than left to PVE, because the id is a PATH SEGMENT: create, delete and the row lookup in
@@ -67,4 +84,15 @@ export declare const createForm: (props: CephDaemonProps) => Record<string, stri
67
84
  * depending on which node was asked. See the ⚠️ on `collectionPath` above.
68
85
  */
69
86
  export declare const findRow: (live: unknown, props: CephDaemonProps) => Record<string, unknown> | undefined;
87
+ /**
88
+ * One live row as attributes, or `undefined` — "no daemon of this kind carries this name".
89
+ *
90
+ * ★ HERE RATHER THAN IN ceph-daemon.ts FOR THE REASON THAT FILE'S SIBLING EXISTS AT ALL: the
91
+ * 250-line cap, and a seam that is real. It reads the row `findRow` picked out of an answer its
92
+ * caller already fetched, three lines above, so the lookup and the mapping now live together
93
+ * instead of a function call apart.
94
+ *
95
+ * ⚠️ `undefined` WHEN NO ROW CARRIES THIS NAME: that is how the factory learns to create.
96
+ */
97
+ export declare const daemonAttributes: (live: Record<string, unknown>, props: CephDaemonProps) => CephDaemonAttributes | undefined;
70
98
  //# sourceMappingURL=ceph-daemon-form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-daemon-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-daemon-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,UAAW,eAAe,WAA6B,CAAC;AAE7E;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAW,eAAe,WAA6C,CAAC;AAEnG,kGAAkG;AAClG,eAAO,MAAM,UAAU,UAAW,eAAe,WAAkD,CAAC;AAEpG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,UAAW,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAMxE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,SAAU,OAAO,SAAS,eAAe,wCAGV,CAAC"}
1
+ {"version":3,"file":"ceph-daemon-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-daemon-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,YAAY,CAAC,CAI3E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,UAAW,eAAe,WAA6B,CAAC;AAE7E;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAW,eAAe,WAA6C,CAAC;AAEnG,kGAAkG;AAClG,eAAO,MAAM,UAAU,UAAW,eAAe,WAAkD,CAAC;AAEpG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,UAAW,eAAe,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAMxE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,SAAU,OAAO,SAAS,eAAe,wCAGV,CAAC;AAEpD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,SACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SACtB,eAAe,KACrB,oBAAoB,GAAG,SAiBzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-daemon.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAGnF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,cAAc,CAAC;IACrB;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAC;IAChB,+EAA+E;IAC/E,aAAa,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ,CACjD,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,oDAE5B,CAAC;AA+CH,eAAO,MAAM,yBAAyB,uIAoBnC,CAAC"}
1
+ {"version":3,"file":"ceph-daemon.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAU7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAEnF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,cAAc,CAAC;IACrB;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAC;IAChB,+EAA+E;IAC/E,aAAa,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ,CACjD,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,oDAE5B,CAAC;AA+BH,eAAO,MAAM,yBAAyB,uIAoBnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-flag.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAGnF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GACpB,YAAY,GACZ,cAAc,GACd,QAAQ,GACR,MAAM,GACN,OAAO,GACP,aAAa,GACb,WAAW,GACX,SAAS,GACT,aAAa,GACb,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C;;;;;;;;;;;;;OAaG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;;;;;;OAOG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB,kFAAkF;IAClF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,eAAe,kDAAgD,CAAC;AAqD7E,eAAO,MAAM,uBAAuB,qIA4CjC,CAAC"}
1
+ {"version":3,"file":"ceph-flag.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAGnF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GACpB,YAAY,GACZ,cAAc,GACd,QAAQ,GACR,MAAM,GACN,OAAO,GACP,aAAa,GACb,WAAW,GACX,SAAS,GACT,aAAa,GACb,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C;;;;;;;;;;;;;OAaG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;;;;;;OAOG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB,kFAAkF;IAClF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,eAAe,kDAAgD,CAAC;AAsD7E,eAAO,MAAM,uBAAuB,qIA4CjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-fs.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAW7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAiB,MAAM,eAAe,CAAC;AAErF,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+FAA+F;IAC/F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ,CAC7C,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,qGAAqG;AACrG,eAAO,MAAM,aAAa,gDAExB,CAAC;AA4BH,eAAO,MAAM,qBAAqB,mIA6E/B,CAAC"}
1
+ {"version":3,"file":"ceph-fs.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAW7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAiB,MAAM,eAAe,CAAC;AAErF,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+FAA+F;IAC/F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ,CAC7C,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,qGAAqG;AACrG,eAAO,MAAM,aAAa,gDAExB,CAAC;AA6BH,eAAO,MAAM,qBAAqB,mIA6E/B,CAAC"}
@@ -13,6 +13,25 @@
13
13
  */
14
14
  import * as Effect from 'effect/Effect';
15
15
  import type { CephOsdProps } from './ceph-osd.ts';
16
+ import type { EndpointKey } from './constraints.ts';
17
+ /**
18
+ * The vendor rules the create form is checked against at plan time.
19
+ *
20
+ * ⛔ DECLARED HERE RATHER THAN ON A SPEC BECAUSE THIS FAMILY HAS NO SPEC — `ceph-osd.ts` writes
21
+ * all five handlers by hand (the ⛔ there says why), so it cannot inherit the shared guard and
22
+ * would otherwise be the one family that writes to Ceph with nothing checking the body.
23
+ * ⚠️ `dev` IS REQUIRED AND THE REFUSAL BELOW ALREADY COVERS IT, with a message about a missing
24
+ * replica that is far more useful than `dev: required`. The table is still worth checking: it
25
+ * also carries `db_dev_size` ≥ 1, `wal_dev_size` ≥ 0.5 and `osds-per-device` ≥ 1, and nothing
26
+ * else in this package knows those numbers.
27
+ * ⚠️ THERE IS NO UPDATE KEY: PVE registers no PUT under `ceph/osd`, and an OSD is not editable.
28
+ */
29
+ export declare const OSD_CREATE_ENDPOINT: EndpointKey;
30
+ /**
31
+ * The create body. ★ Exported so the constraint proof can run the REAL form.
32
+ * ⚠️ `dev` is `string | undefined` on the props and non-optional here: `createOsd` refuses first.
33
+ */
34
+ export declare const createOsdForm: (props: CephOsdProps, dev: string) => Record<string, string>;
16
35
  export declare const createOsd: (news: CephOsdProps) => Effect.Effect<import("./ceph-osd-tree.ts").CephOsdAttributes, Error, import("effect/unstable/http/HttpClient").HttpClient>;
17
36
  /**
18
37
  * ⛔ REMOVING THE DECLARATION REMOVES THE ASSERTION, NOT THE REPLICA, AND THAT ASYMMETRY IS THE
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-osd-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD,eAAO,MAAM,SAAS,oJA4BpB,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,SAAU,YAAY,wFAO1C,CAAC"}
1
+ {"version":3,"file":"ceph-osd-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAA+C,CAAC;AAIlF;;;GAGG;AACH,eAAO,MAAM,aAAa,UAAW,YAAY,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAGpF,CAAC;AAEH,eAAO,MAAM,SAAS,oJA6BpB,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,SAAU,YAAY,wFAO1C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EASnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,KAAK,eAAe,EAA+B,MAAM,eAAe,CAAC;AAIlF,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAElD,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,kGAAkG;AAClG,eAAO,MAAM,eAAe,kDAE1B,CAAC;AAiEH,eAAO,MAAM,uBAAuB,qIAkFjC,CAAC"}
1
+ {"version":3,"file":"ceph-pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EASnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,KAAK,eAAe,EAA+B,MAAM,eAAe,CAAC;AAIlF,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAElD,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,kGAAkG;AAClG,eAAO,MAAM,eAAe,kDAE1B,CAAC;AAsEH,eAAO,MAAM,uBAAuB,qIAuFjC,CAAC"}