@homeflare/alchemy 0.38.0 → 0.40.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 (353) hide show
  1. package/README.md +32 -8
  2. package/dist/ceph/auth-entity.d.ts +34 -0
  3. package/dist/ceph/auth-entity.d.ts.map +1 -0
  4. package/dist/ceph/ceph-argv-config.d.ts +10 -0
  5. package/dist/ceph/ceph-argv-config.d.ts.map +1 -0
  6. package/dist/ceph/ceph-argv.d.ts +19 -0
  7. package/dist/ceph/ceph-argv.d.ts.map +1 -0
  8. package/dist/ceph/ceph-auth-form.d.ts +54 -0
  9. package/dist/ceph/ceph-auth-form.d.ts.map +1 -0
  10. package/dist/ceph/ceph-auth-parse.d.ts +56 -0
  11. package/dist/ceph/ceph-auth-parse.d.ts.map +1 -0
  12. package/dist/ceph/ceph-auth-reconcile.d.ts +35 -0
  13. package/dist/ceph/ceph-auth-reconcile.d.ts.map +1 -0
  14. package/dist/ceph/ceph-config-options.d.ts +23 -0
  15. package/dist/ceph/ceph-config-options.d.ts.map +1 -0
  16. package/dist/ceph/ceph-key-leak-assert.d.ts +25 -0
  17. package/dist/ceph/ceph-key-leak-assert.d.ts.map +1 -0
  18. package/dist/ceph/ceph-transport.d.ts +37 -0
  19. package/dist/ceph/ceph-transport.d.ts.map +1 -0
  20. package/dist/ceph/fake-ceph-dial.d.ts +35 -0
  21. package/dist/ceph/fake-ceph-dial.d.ts.map +1 -0
  22. package/dist/ceph/index.d.ts +13 -0
  23. package/dist/ceph/index.d.ts.map +1 -0
  24. package/dist/ceph/index.js +1609 -0
  25. package/dist/ceph/index.js.map +38 -0
  26. package/dist/forgejo/index.js +4 -2
  27. package/dist/forgejo/index.js.map +3 -3
  28. package/dist/forgejo/team-member.d.ts +25 -0
  29. package/dist/forgejo/team-member.d.ts.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/proxmox/generated/constraints/index.d.ts +1 -1
  33. package/dist/proxmox/generated/constraints/index.d.ts.map +1 -1
  34. package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
  35. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
  36. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
  37. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
  38. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
  39. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
  40. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
  41. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
  42. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
  43. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
  44. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
  45. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
  46. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
  47. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
  48. package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts +23 -0
  49. package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts.map +1 -0
  50. package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
  51. package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
  52. package/dist/proxmox/index.d.ts +14 -3
  53. package/dist/proxmox/index.d.ts.map +1 -1
  54. package/dist/proxmox/index.js +574 -133
  55. package/dist/proxmox/index.js.map +33 -23
  56. package/dist/proxmox/qemu-form.d.ts +27 -18
  57. package/dist/proxmox/qemu-form.d.ts.map +1 -1
  58. package/dist/proxmox/qemu-judge.d.ts +30 -0
  59. package/dist/proxmox/qemu-judge.d.ts.map +1 -0
  60. package/dist/proxmox/qemu-lifecycle.d.ts +16 -2
  61. package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
  62. package/dist/proxmox/qemu-net.d.ts +9 -0
  63. package/dist/proxmox/qemu-net.d.ts.map +1 -0
  64. package/dist/proxmox/qemu-props.d.ts +112 -0
  65. package/dist/proxmox/qemu-props.d.ts.map +1 -0
  66. package/dist/proxmox/qemu-volume.d.ts +27 -0
  67. package/dist/proxmox/qemu-volume.d.ts.map +1 -0
  68. package/dist/proxmox/qemu.d.ts +14 -27
  69. package/dist/proxmox/qemu.d.ts.map +1 -1
  70. package/dist/proxmox/storage-download-errors.d.ts +5 -0
  71. package/dist/proxmox/storage-download-errors.d.ts.map +1 -0
  72. package/dist/proxmox/storage-download-identity.d.ts +27 -0
  73. package/dist/proxmox/storage-download-identity.d.ts.map +1 -0
  74. package/dist/proxmox/storage-download-lifecycle.d.ts +97 -0
  75. package/dist/proxmox/storage-download-lifecycle.d.ts.map +1 -0
  76. package/dist/proxmox/storage-download-props.d.ts +36 -0
  77. package/dist/proxmox/storage-download-props.d.ts.map +1 -0
  78. package/dist/proxmox/storage-download-task.d.ts +17 -0
  79. package/dist/proxmox/storage-download-task.d.ts.map +1 -0
  80. package/dist/proxmox/storage-download.d.ts +44 -0
  81. package/dist/proxmox/storage-download.d.ts.map +1 -0
  82. package/dist/talos/credentials-write.d.ts +46 -0
  83. package/dist/talos/credentials-write.d.ts.map +1 -0
  84. package/dist/talos/credentials.d.ts +51 -9
  85. package/dist/talos/credentials.d.ts.map +1 -1
  86. package/dist/talos/fake-process.d.ts +56 -0
  87. package/dist/talos/fake-process.d.ts.map +1 -0
  88. package/dist/talos/index.d.ts +19 -4
  89. package/dist/talos/index.d.ts.map +1 -1
  90. package/dist/talos/index.js +357 -173
  91. package/dist/talos/index.js.map +16 -10
  92. package/dist/talos/kubeconfig-attrs.d.ts +4 -0
  93. package/dist/talos/kubeconfig-attrs.d.ts.map +1 -0
  94. package/dist/talos/kubeconfig.d.ts +41 -23
  95. package/dist/talos/kubeconfig.d.ts.map +1 -1
  96. package/dist/talos/machine-config-fixtures.d.ts +60 -0
  97. package/dist/talos/machine-config-fixtures.d.ts.map +1 -0
  98. package/dist/talos/machine-config-poll.d.ts +43 -0
  99. package/dist/talos/machine-config-poll.d.ts.map +1 -0
  100. package/dist/talos/machine-config-read.d.ts +49 -0
  101. package/dist/talos/machine-config-read.d.ts.map +1 -0
  102. package/dist/talos/resource.d.ts +18 -0
  103. package/dist/talos/resource.d.ts.map +1 -1
  104. package/dist/talos/talos-bootstrap-etcd.d.ts +38 -0
  105. package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -0
  106. package/dist/talos/talos-bootstrap.d.ts +87 -0
  107. package/dist/talos/talos-bootstrap.d.ts.map +1 -1
  108. package/dist/talos/talos-cluster-health.d.ts +43 -1
  109. package/dist/talos/talos-cluster-health.d.ts.map +1 -1
  110. package/dist/talos/talos-errors.d.ts +68 -0
  111. package/dist/talos/talos-errors.d.ts.map +1 -0
  112. package/dist/talos/talos-machine-config.d.ts +51 -15
  113. package/dist/talos/talos-machine-config.d.ts.map +1 -1
  114. package/dist/talos/talosctl.d.ts +7 -0
  115. package/dist/talos/talosctl.d.ts.map +1 -1
  116. package/dist/talos/values.d.ts +23 -3
  117. package/dist/talos/values.d.ts.map +1 -1
  118. package/dist/telemetry/fake-collector.d.ts +36 -0
  119. package/dist/telemetry/fake-collector.d.ts.map +1 -0
  120. package/dist/telemetry/index.d.ts +11 -0
  121. package/dist/telemetry/index.d.ts.map +1 -0
  122. package/dist/telemetry/index.js +223 -0
  123. package/dist/telemetry/index.js.map +12 -0
  124. package/dist/telemetry/layer.d.ts +86 -0
  125. package/dist/telemetry/layer.d.ts.map +1 -0
  126. package/dist/telemetry/redact-serialization.d.ts +21 -0
  127. package/dist/telemetry/redact-serialization.d.ts.map +1 -0
  128. package/dist/telemetry/redact.d.ts +46 -0
  129. package/dist/telemetry/redact.d.ts.map +1 -0
  130. package/dist/unifi/acl-rule-drift.d.ts +22 -0
  131. package/dist/unifi/acl-rule-drift.d.ts.map +1 -0
  132. package/dist/unifi/acl-rule-form.d.ts +90 -0
  133. package/dist/unifi/acl-rule-form.d.ts.map +1 -0
  134. package/dist/unifi/acl-rule-ordering-form.d.ts +49 -0
  135. package/dist/unifi/acl-rule-ordering-form.d.ts.map +1 -0
  136. package/dist/unifi/acl-rule-ordering.d.ts +54 -0
  137. package/dist/unifi/acl-rule-ordering.d.ts.map +1 -0
  138. package/dist/unifi/acl-rule.d.ts +49 -0
  139. package/dist/unifi/acl-rule.d.ts.map +1 -0
  140. package/dist/unifi/dns-policy-drift.d.ts +21 -0
  141. package/dist/unifi/dns-policy-drift.d.ts.map +1 -0
  142. package/dist/unifi/dns-policy-form.d.ts +97 -0
  143. package/dist/unifi/dns-policy-form.d.ts.map +1 -0
  144. package/dist/unifi/dns-policy.d.ts +55 -0
  145. package/dist/unifi/dns-policy.d.ts.map +1 -0
  146. package/dist/unifi/drift.d.ts +27 -0
  147. package/dist/unifi/drift.d.ts.map +1 -0
  148. package/dist/unifi/fake-unifi.d.ts +5 -1
  149. package/dist/unifi/fake-unifi.d.ts.map +1 -1
  150. package/dist/unifi/firewall-policy-drift.d.ts +26 -0
  151. package/dist/unifi/firewall-policy-drift.d.ts.map +1 -0
  152. package/dist/unifi/firewall-policy-form.d.ts +102 -0
  153. package/dist/unifi/firewall-policy-form.d.ts.map +1 -0
  154. package/dist/unifi/firewall-policy-ordering-form.d.ts +66 -0
  155. package/dist/unifi/firewall-policy-ordering-form.d.ts.map +1 -0
  156. package/dist/unifi/firewall-policy-ordering.d.ts +57 -0
  157. package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -0
  158. package/dist/unifi/firewall-policy.d.ts +57 -0
  159. package/dist/unifi/firewall-policy.d.ts.map +1 -0
  160. package/dist/unifi/firewall-zone-form.d.ts +6 -0
  161. package/dist/unifi/firewall-zone-form.d.ts.map +1 -1
  162. package/dist/unifi/firewall-zone.d.ts +1 -1
  163. package/dist/unifi/firewall-zone.d.ts.map +1 -1
  164. package/dist/unifi/index.d.ts +11 -3
  165. package/dist/unifi/index.d.ts.map +1 -1
  166. package/dist/unifi/index.js +725 -60
  167. package/dist/unifi/index.js.map +31 -9
  168. package/dist/unifi/network-drift.d.ts +26 -0
  169. package/dist/unifi/network-drift.d.ts.map +1 -0
  170. package/dist/unifi/network-form.d.ts +40 -7
  171. package/dist/unifi/network-form.d.ts.map +1 -1
  172. package/dist/unifi/network.d.ts +1 -0
  173. package/dist/unifi/network.d.ts.map +1 -1
  174. package/dist/unifi/paginate.d.ts +24 -0
  175. package/dist/unifi/paginate.d.ts.map +1 -0
  176. package/dist/unifi/providers.d.ts +1 -1
  177. package/dist/unifi/providers.d.ts.map +1 -1
  178. package/dist/unifi/resource.d.ts +36 -1
  179. package/dist/unifi/resource.d.ts.map +1 -1
  180. package/dist/unifi/scan-source.d.ts +11 -0
  181. package/dist/unifi/scan-source.d.ts.map +1 -0
  182. package/dist/unifi/traffic-matching-list-drift.d.ts +22 -0
  183. package/dist/unifi/traffic-matching-list-drift.d.ts.map +1 -0
  184. package/dist/unifi/traffic-matching-list-form.d.ts +56 -0
  185. package/dist/unifi/traffic-matching-list-form.d.ts.map +1 -0
  186. package/dist/unifi/traffic-matching-list.d.ts +51 -0
  187. package/dist/unifi/traffic-matching-list.d.ts.map +1 -0
  188. package/dist/unifi/wifi-broadcast-drift.d.ts +22 -0
  189. package/dist/unifi/wifi-broadcast-drift.d.ts.map +1 -0
  190. package/dist/unifi/wifi-broadcast-form.d.ts +127 -0
  191. package/dist/unifi/wifi-broadcast-form.d.ts.map +1 -0
  192. package/dist/unifi/wifi-broadcast.d.ts +73 -0
  193. package/dist/unifi/wifi-broadcast.d.ts.map +1 -0
  194. package/docs/telemetry-spike.md +94 -0
  195. package/docs/telemetry.md +109 -0
  196. package/docs/unifi-acl-rule.md +122 -0
  197. package/docs/unifi-dns-policy.md +75 -0
  198. package/docs/unifi-firewall-policy.md +109 -0
  199. package/docs/unifi-traffic-matching-list.md +82 -0
  200. package/docs/unifi-wifi.md +120 -0
  201. package/docs/unifi.md +64 -3
  202. package/package.json +10 -2
  203. package/src/ceph/auth-entity.ts +74 -0
  204. package/src/ceph/ceph-argv-config.ts +78 -0
  205. package/src/ceph/ceph-argv.test.ts +226 -0
  206. package/src/ceph/ceph-argv.ts +189 -0
  207. package/src/ceph/ceph-auth-form.test.ts +103 -0
  208. package/src/ceph/ceph-auth-form.ts +107 -0
  209. package/src/ceph/ceph-auth-parse.test.ts +155 -0
  210. package/src/ceph/ceph-auth-parse.ts +121 -0
  211. package/src/ceph/ceph-auth-reconcile-secrecy.test.ts +82 -0
  212. package/src/ceph/ceph-auth-reconcile.test.ts +233 -0
  213. package/src/ceph/ceph-auth-reconcile.ts +119 -0
  214. package/src/ceph/ceph-config-options.test.ts +44 -0
  215. package/src/ceph/ceph-config-options.ts +36 -0
  216. package/src/ceph/ceph-key-leak-assert.ts +35 -0
  217. package/src/ceph/ceph-no-output-logging.test.ts +52 -0
  218. package/src/ceph/ceph-transport.test.ts +125 -0
  219. package/src/ceph/ceph-transport.ts +117 -0
  220. package/src/ceph/fake-ceph-dial.ts +55 -0
  221. package/src/ceph/index.ts +12 -0
  222. package/src/forgejo/team-member.test.ts +14 -0
  223. package/src/forgejo/team-member.ts +28 -1
  224. package/src/index.ts +1 -0
  225. package/src/proxmox/constraints-required.test.ts +1 -0
  226. package/src/proxmox/generated/constraints/index.ts +3 -1
  227. package/src/proxmox/generated/constraints/pve-access.ts +1 -1
  228. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
  229. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
  230. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
  231. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
  232. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
  233. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
  234. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
  235. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
  236. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
  237. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
  238. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
  239. package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
  240. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +1 -1
  241. package/src/proxmox/generated/constraints/pve-nodes-storage.ts +30 -0
  242. package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
  243. package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
  244. package/src/proxmox/index.test.ts +11 -6
  245. package/src/proxmox/index.ts +19 -3
  246. package/src/proxmox/qemu-form.ts +49 -13
  247. package/src/proxmox/qemu-identity.test.ts +30 -0
  248. package/src/proxmox/qemu-judge.test.ts +65 -0
  249. package/src/proxmox/qemu-judge.ts +84 -0
  250. package/src/proxmox/qemu-lifecycle.test.ts +78 -19
  251. package/src/proxmox/qemu-lifecycle.ts +131 -32
  252. package/src/proxmox/qemu-net.test.ts +48 -0
  253. package/src/proxmox/qemu-net.ts +78 -0
  254. package/src/proxmox/qemu-ownership.test.ts +44 -0
  255. package/src/proxmox/qemu-props.test.ts +87 -0
  256. package/src/proxmox/qemu-props.ts +157 -0
  257. package/src/proxmox/qemu-volume.test.ts +229 -0
  258. package/src/proxmox/qemu-volume.ts +178 -0
  259. package/src/proxmox/qemu.ts +15 -29
  260. package/src/proxmox/storage-download-errors.ts +7 -0
  261. package/src/proxmox/storage-download-identity.test.ts +54 -0
  262. package/src/proxmox/storage-download-identity.ts +50 -0
  263. package/src/proxmox/storage-download-lifecycle.ts +226 -0
  264. package/src/proxmox/storage-download-ownership.test.ts +50 -0
  265. package/src/proxmox/storage-download-props.ts +38 -0
  266. package/src/proxmox/storage-download-task.ts +72 -0
  267. package/src/proxmox/storage-download.test.ts +216 -0
  268. package/src/proxmox/storage-download.ts +58 -0
  269. package/src/talos/credentials-write.test.ts +81 -0
  270. package/src/talos/credentials-write.ts +95 -0
  271. package/src/talos/credentials.test.ts +157 -0
  272. package/src/talos/credentials.ts +160 -90
  273. package/src/talos/fake-process.ts +94 -0
  274. package/src/talos/index.ts +39 -4
  275. package/src/talos/kubeconfig-attrs.ts +55 -0
  276. package/src/talos/kubeconfig.test.ts +256 -0
  277. package/src/talos/kubeconfig.ts +170 -90
  278. package/src/talos/machine-config-fixtures.ts +86 -0
  279. package/src/talos/machine-config-poll.test.ts +57 -0
  280. package/src/talos/machine-config-poll.ts +82 -0
  281. package/src/talos/machine-config-read.ts +118 -0
  282. package/src/talos/resource.ts +19 -0
  283. package/src/talos/secrets-gate.test.ts +63 -0
  284. package/src/talos/talos-bootstrap-etcd.ts +71 -0
  285. package/src/talos/talos-bootstrap.test.ts +218 -0
  286. package/src/talos/talos-bootstrap.ts +151 -45
  287. package/src/talos/talos-cluster-health.test.ts +143 -0
  288. package/src/talos/talos-cluster-health.ts +91 -28
  289. package/src/talos/talos-errors.ts +85 -0
  290. package/src/talos/talos-machine-config.test.ts +189 -0
  291. package/src/talos/talos-machine-config.ts +102 -88
  292. package/src/talos/talosctl.ts +8 -0
  293. package/src/talos/values.test.ts +34 -6
  294. package/src/talos/values.ts +41 -7
  295. package/src/telemetry/fake-collector.ts +59 -0
  296. package/src/telemetry/http-client-sealing.test.ts +82 -0
  297. package/src/telemetry/index.ts +10 -0
  298. package/src/telemetry/layer.test.ts +204 -0
  299. package/src/telemetry/layer.ts +152 -0
  300. package/src/telemetry/redact-serialization.ts +178 -0
  301. package/src/telemetry/redact.test.ts +124 -0
  302. package/src/telemetry/redact.ts +147 -0
  303. package/src/unifi/acl-rule-drift.ts +57 -0
  304. package/src/unifi/acl-rule-form.ts +135 -0
  305. package/src/unifi/acl-rule-ordering-form.ts +79 -0
  306. package/src/unifi/acl-rule-ordering.test.ts +141 -0
  307. package/src/unifi/acl-rule-ordering.ts +70 -0
  308. package/src/unifi/acl-rule.test.ts +183 -0
  309. package/src/unifi/acl-rule.ts +61 -0
  310. package/src/unifi/discriminated-filter-decode.test.ts +134 -0
  311. package/src/unifi/dns-policy-drift.ts +48 -0
  312. package/src/unifi/dns-policy-form.ts +142 -0
  313. package/src/unifi/dns-policy.test.ts +154 -0
  314. package/src/unifi/dns-policy.ts +67 -0
  315. package/src/unifi/drift.test.ts +78 -0
  316. package/src/unifi/drift.ts +56 -0
  317. package/src/unifi/errors-and-secrets.test.ts +127 -0
  318. package/src/unifi/fake-unifi.ts +5 -1
  319. package/src/unifi/firewall-policy-drift.test.ts +151 -0
  320. package/src/unifi/firewall-policy-drift.ts +55 -0
  321. package/src/unifi/firewall-policy-filter-roundtrip.test.ts +143 -0
  322. package/src/unifi/firewall-policy-form.ts +146 -0
  323. package/src/unifi/firewall-policy-ordering-form.ts +111 -0
  324. package/src/unifi/firewall-policy-ordering.test.ts +185 -0
  325. package/src/unifi/firewall-policy-ordering.ts +87 -0
  326. package/src/unifi/firewall-policy.test.ts +183 -0
  327. package/src/unifi/firewall-policy.ts +73 -0
  328. package/src/unifi/firewall-zone-form.ts +31 -2
  329. package/src/unifi/firewall-zone.test.ts +21 -1
  330. package/src/unifi/firewall-zone.ts +1 -1
  331. package/src/unifi/get-only-guard.test.ts +165 -0
  332. package/src/unifi/index.ts +78 -1
  333. package/src/unifi/network-drift.test.ts +207 -0
  334. package/src/unifi/network-drift.ts +80 -0
  335. package/src/unifi/network-form.ts +11 -39
  336. package/src/unifi/network.test.ts +7 -82
  337. package/src/unifi/network.ts +6 -6
  338. package/src/unifi/paginate.test.ts +252 -0
  339. package/src/unifi/paginate.ts +141 -0
  340. package/src/unifi/providers.ts +19 -1
  341. package/src/unifi/resource.ts +73 -3
  342. package/src/unifi/scan-source.ts +64 -0
  343. package/src/unifi/traffic-matching-list-drift.ts +40 -0
  344. package/src/unifi/traffic-matching-list-form.ts +77 -0
  345. package/src/unifi/traffic-matching-list.test.ts +202 -0
  346. package/src/unifi/traffic-matching-list.ts +78 -0
  347. package/src/unifi/wifi-broadcast-details-call.test.ts +92 -0
  348. package/src/unifi/wifi-broadcast-drift.ts +69 -0
  349. package/src/unifi/wifi-broadcast-form.ts +211 -0
  350. package/src/unifi/wifi-broadcast-secrets.test.ts +145 -0
  351. package/src/unifi/wifi-broadcast.test.ts +155 -0
  352. package/src/unifi/wifi-broadcast.ts +90 -0
  353. package/src/unifi/write-op-reference.test.ts +190 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `Unifi.Network`'s `matches` AND `driftOf` (B6) — both built on the ONE field list below, not two
3
+ * hand-kept-in-sync comparisons. `matches` used to be a separate boolean expression in
4
+ * `network-form.ts`; MEDIUM-4 (red team, 2026-09-26) found that a `fieldDrift` entry could be
5
+ * deleted entirely and every test still passed, because `matches` never consulted `fieldDrift` at
6
+ * all. `matches(attrs, props) === (driftOf(live, props).length === 0)` is now true BY
7
+ * CONSTRUCTION — there is exactly one comparison — and every `fieldDrift` entry names ONE field
8
+ * plus its own live/declared value instead of collapsing straight to a boolean.
9
+ *
10
+ * ⚠️ `stripNullish: true` ON EVERY FIELD BY DEFAULT (`drift.ts`'s `defaultEqual`). UniFi's JSON
11
+ * answers `null` for an unset optional field; a declaration that omits the same prop carries
12
+ * `undefined`. Without this, every plan against an object with one unset optional field would
13
+ * report `update` forever — the exact "read and write are different shapes" trap
14
+ * `netbox/values.ts` and `proxmox/user-wire.ts` both work around, here solved once by
15
+ * `makeDriftOf`'s own default instead of a per-field coercion.
16
+ */
17
+ import type * as networks from '@distilled.cloud/unifi-network/networks';
18
+ import { type NetworkAttributes, type NetworkProps } from './network-form.ts';
19
+ export declare const matches: (attributes: NetworkAttributes, props: NetworkProps) => boolean;
20
+ /**
21
+ * Per-field live-vs-declared drift straight from one live read — the task's own API
22
+ * (`driftOf(live, props)`), so `homeflare-network`'s pre-import drift check never has to derive
23
+ * `attributesOf` itself just to call this.
24
+ */
25
+ export declare const driftOf: (live: networks.NetworkDetails, props: NetworkProps) => import("./drift.ts").FieldDrift[];
26
+ //# sourceMappingURL=network-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-drift.d.ts","sourceRoot":"","sources":["../../src/unifi/network-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAIlB,MAAM,mBAAmB,CAAC;AA8C3B,eAAO,MAAM,OAAO,eAAgB,iBAAiB,SAAS,YAAY,KAAG,OACjC,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,OAAO,SAAU,QAAQ,CAAC,cAAc,SAAS,YAAY,sCAC5B,CAAC"}
@@ -1,4 +1,38 @@
1
+ /**
2
+ * `Unifi.Network`'s wire shape: the declarable subset of `NetworkDetails`, and how a live read
3
+ * becomes both plan attributes and a rendered declaration.
4
+ *
5
+ * ⚠️ PROPS MIRROR `UpdateNetworkRequest`, NOT `NetworkDetails`. `default` and `metadata` are
6
+ * server-derived — no writable endpoint in `networks.ts` accepts either — so they are
7
+ * attributes-only, reported but never compared or declared. Everything else in `NetworkProps`
8
+ * is exactly what `updateNetwork`/`createNetwork` would accept, even though this family never
9
+ * calls either: the shape is what a future write path would need, and what today's read-only
10
+ * `matches` compares against.
11
+ *
12
+ * ⛔ `ipv4Configuration` STAYS `unknown`, ON THE SDK'S OWN AUTHORITY. `networks.ts`'s own comment
13
+ * ("Shape varies by variant — widened by scripts/convert.ts; see README") says the OpenAPI
14
+ * discriminator this field varies over was flattened at generation time, not decoded per
15
+ * variant. Comparing it as an opaque JSON value (below) is honest about that; guessing a
16
+ * narrower shape here would silently stop matching the day a new variant's key order differs.
17
+ * ⚠️ It may ALSO hide an unordered array the way `dhcpGuarding` and `ipv6Configuration` do
18
+ * below — this family just can't know, because the shape is never decoded. If a future variant
19
+ * plans spurious `update`s, suspect this field first and widen it into a typed, order-normalized
20
+ * shape rather than adding another opaque comparison.
21
+ *
22
+ * ⛔ THREE FIELDS ARE SETS, NOT SEQUENCES: `dhcpGuarding.trustedDhcpServerIpAddresses`,
23
+ * `ipv6Configuration.additionalHostIpSubnets`, and `ipv6Configuration.dnsServerIpAddressesOverride`.
24
+ * The vendor document gives no indication any of the three is ordered — same reasoning
25
+ * `firewall-zone-form.ts` gives for `networkIds`, and `proxmox/user-wire.ts`'s `groupSet` gives
26
+ * for PVE's `groups` — but `matches` compares via alchemy's `deepEqual`, which sorts object KEYS
27
+ * but NOT ARRAY ELEMENTS (`node_modules/alchemy/lib/Diff.js`). Left alone, a console that
28
+ * returns the same set in a different order between calls plans a spurious `update`, and the
29
+ * read-only reconcile then refuses every deploy. `sortedSet` (dedupe + sort) neutralizes that
30
+ * before any of the three is attributed, declared, or compared. Every OTHER array field in this
31
+ * family (there are none today besides these three) would stay declaration-order as written.
32
+ */
1
33
  import type * as networks from '@distilled.cloud/unifi-network/networks';
34
+ export declare const normalizeDhcpGuarding: (value: networks.NetworkDHCPGuarding | undefined) => networks.NetworkDHCPGuarding | undefined;
35
+ export declare const normalizeIpv6Configuration: (value: networks.NetworkIPv6Configuration | undefined) => networks.NetworkIPv6Configuration | undefined;
2
36
  /**
3
37
  * ⚠️ EVERY OPTIONAL FIELD SPELLS OUT `| undefined` ON PURPOSE. `tsconfig.json` sets
4
38
  * `exactOptionalPropertyTypes`, which treats `field?: T` (absent-or-T) and
@@ -47,14 +81,13 @@ export interface NetworkAttributes {
47
81
  }
48
82
  export declare const attributesOf: (live: networks.NetworkDetails, props: NetworkProps) => NetworkAttributes;
49
83
  /**
50
- * ⚠️ `stripNullish: true` ON EVERY COMPARISON. UniFi's JSON answers `null` for an unset optional
51
- * field; a declaration that omits the same prop carries `undefined`. Without this option every
52
- * plan against an object with one unset optional field would report `update` forever — the
53
- * exact "read and write are different shapes" trap `netbox/values.ts` and `proxmox/user-wire.ts`
54
- * both work around, here solved once with the engine's own `deepEqual` instead of a per-field
55
- * coercion, because nothing here needs PVE's or NetBox's extra wire-format translation.
84
+ * MEDIUM-4 (red team, 2026-09-26): `matches` used to be a hand-written boolean expression here,
85
+ * kept in sync BY HAND with `network-drift.ts`'s separately-maintained field list — two comparisons
86
+ * that could (and, per a red-team mutant, silently did) drift apart. `matches` now lives in
87
+ * `network-drift.ts`, defined as `fieldDrift(...).length === 0` — the SAME comparison `driftOf`
88
+ * runs, not a second one. See that file's own header for the `stripNullish`/normalizer reasoning
89
+ * this expression used to carry.
56
90
  */
57
- export declare const matches: (attributes: NetworkAttributes, props: NetworkProps) => boolean;
58
91
  /**
59
92
  * The declaration renderer (task spec: "given one live object, return the props a declaration
60
93
  * needs so its plan is noop"). A later import script feeds `getNetworkDetails`'s own response
@@ -1 +1 @@
1
- {"version":3,"file":"network-form.d.ts","sourceRoot":"","sources":["../../src/unifi/network-form.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AAwCzE;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,QAAQ,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACxD,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,QAAQ,CAAC,wBAAwB,GAAG,SAAS,CAAC;IAClE,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,QAAQ,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACvD,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,QAAQ,CAAC,wBAAwB,GAAG,SAAS,CAAC;IACjE,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,eAAO,MAAM,YAAY,SACjB,QAAQ,CAAC,cAAc,SACtB,YAAY,KAClB,iBAiBD,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,eAAgB,iBAAiB,SAAS,YAAY,KAAG,OA6BL,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,SAAU,QAAQ,CAAC,cAAc,UAAU,MAAM,KAAG,YAgB7E,CAAC"}
1
+ {"version":3,"file":"network-form.d.ts","sourceRoot":"","sources":["../../src/unifi/network-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AAgBzE,eAAO,MAAM,qBAAqB,UACzB,QAAQ,CAAC,mBAAmB,GAAG,SAAS,KAC9C,QAAQ,CAAC,mBAAmB,GAAG,SAG6D,CAAC;AAOhG,eAAO,MAAM,0BAA0B,UAC9B,QAAQ,CAAC,wBAAwB,GAAG,SAAS,KACnD,QAAQ,CAAC,wBAAwB,GAAG,SAWhC,CAAC;AAER;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,QAAQ,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACxD,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,QAAQ,CAAC,wBAAwB,GAAG,SAAS,CAAC;IAClE,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,QAAQ,CAAC,mBAAmB,GAAG,SAAS,CAAC;IACvD,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,QAAQ,CAAC,wBAAwB,GAAG,SAAS,CAAC;IACjE,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,eAAO,MAAM,YAAY,SACjB,QAAQ,CAAC,cAAc,SACtB,YAAY,KAClB,iBAiBD,CAAC;AAEH;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,SAAU,QAAQ,CAAC,cAAc,UAAU,MAAM,KAAG,YAgB7E,CAAC"}
@@ -26,6 +26,7 @@ import { type NetworkAttributes, type NetworkProps } from './network-form.ts';
26
26
  import type { UnifiRequirements, UnifiSpec } from './resource.ts';
27
27
  export type { NetworkAttributes, NetworkProps } from './network-form.ts';
28
28
  export { declareNetwork } from './network-form.ts';
29
+ export { driftOf } from './network-drift.ts';
29
30
  export interface UnifiNetwork extends Resource<'Unifi.Network', NetworkProps, NetworkAttributes, never, UnifiRequirements> {
30
31
  }
31
32
  export declare const UnifiNetwork: import("alchemy").ResourceClass<UnifiNetwork>;
@@ -1 +1 @@
1
- {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/unifi/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,iBAAiB,CAClB;CAAG;AAEJ,eAAO,MAAM,YAAY,+CAEvB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,OAAO,OAAQ,MAAM,SAAS,YAAY,6FACZ,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,SAAS,CAC1B,YAAY,EACZ,QAAQ,CAAC,cAAc,EACvB,iBAAiB,EACjB,QAAQ,CAAC,sBAAsB,CAUhC,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;CAAsB,CAAC;AAE5C,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/unifi/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAgB,MAAM,mBAAmB,CAAC;AAE5F,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,iBAAiB,CAClB;CAAG;AAEJ,eAAO,MAAM,YAAY,+CAEvB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,OAAO,OAAQ,MAAM,SAAS,YAAY,6FACZ,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,SAAS,CAC1B,YAAY,EACZ,QAAQ,CAAC,cAAc,EACvB,iBAAiB,EACjB,QAAQ,CAAC,sBAAsB,CAUhC,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;CAAsB,CAAC;AAE5C,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
@@ -0,0 +1,24 @@
1
+ import * as Effect from 'effect/Effect';
2
+ /** The one response shape every UniFi Network list operation already has (`protocol.ts`). */
3
+ export interface OffsetPage<T> {
4
+ readonly data: readonly T[];
5
+ readonly offset: number;
6
+ readonly totalCount: number;
7
+ }
8
+ /** The one request shape every UniFi Network list operation already accepts, plus its own fields. */
9
+ export type OffsetPageRequest = {
10
+ readonly offset?: number;
11
+ readonly limit?: number;
12
+ };
13
+ declare const UnifiPaginationInconsistent_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
14
+ readonly _tag: "UnifiPaginationInconsistent";
15
+ } & Readonly<A>;
16
+ export declare class UnifiPaginationInconsistent extends UnifiPaginationInconsistent_base<{
17
+ readonly reason: 'offset-mismatch' | 'total-count-changed' | 'row-count-mismatch' | 'page-ceiling';
18
+ readonly detail: string;
19
+ }> {
20
+ get message(): string;
21
+ }
22
+ export declare const pageAll: <Req extends OffsetPageRequest, T, E, R>(fetchPage: (request: Req) => Effect.Effect<OffsetPage<T>, E, R>, request: Req) => Effect.Effect<T[], E | UnifiPaginationInconsistent, R>;
23
+ export {};
24
+ //# sourceMappingURL=paginate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../../src/unifi/paginate.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,6FAA6F;AAC7F,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,qGAAqG;AACrG,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;;;;AAQtF,qBAAa,2BAA4B,SAAQ,iCAAgD;IAC/F,QAAQ,CAAC,MAAM,EACX,iBAAiB,GACjB,qBAAqB,GACrB,oBAAoB,GACpB,cAAc,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAK7B;CACF;AA0BD,eAAO,MAAM,OAAO,GAAI,GAAG,SAAS,iBAAiB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,aACjD,CAAC,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,WACtD,GAAG,KACX,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,2BAA2B,EAAE,CAAC,CA4CpD,CAAC"}
@@ -9,5 +9,5 @@
9
9
  * mirroring `../discord/providers.ts`.
10
10
  */
11
11
  import * as Layer from 'effect/Layer';
12
- export declare const providers: () => Layer.Layer<import("alchemy").Provider<import("./firewall-zone.ts").UnifiFirewallZone> | import("alchemy").Provider<import("./network.ts").UnifiNetwork>, never, import("effect/unstable/http/HttpClient").HttpClient>;
12
+ export declare const providers: () => Layer.Layer<import("alchemy").Provider<import("./acl-rule.ts").UnifiAclRule> | import("alchemy").Provider<import("./acl-rule-ordering.ts").UnifiAclRuleOrdering> | import("alchemy").Provider<import("./dns-policy.ts").UnifiDnsPolicy> | import("alchemy").Provider<import("./firewall-policy.ts").UnifiFirewallPolicy> | import("alchemy").Provider<import("./firewall-policy-ordering.ts").UnifiFirewallPolicyOrdering> | import("alchemy").Provider<import("./firewall-zone.ts").UnifiFirewallZone> | import("alchemy").Provider<import("./network.ts").UnifiNetwork> | import("alchemy").Provider<import("./traffic-matching-list.ts").UnifiTrafficMatchingList> | import("alchemy").Provider<import("./wifi-broadcast.ts").UnifiWifiBroadcast>, never, import("effect/unstable/http/HttpClient").HttpClient>;
13
13
  //# sourceMappingURL=providers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/unifi/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAItC,eAAO,MAAM,SAAS,8NAA4E,CAAC"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/unifi/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAWtC,eAAO,MAAM,SAAS,0xBAWnB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { Input } from 'alchemy/Input';
2
2
  import type { UnifiNetworkOpContext } from '@distilled.cloud/unifi-network/Protocol';
3
3
  import * as Effect from 'effect/Effect';
4
- import type * as HttpClient from 'effect/unstable/http/HttpClient';
4
+ import * as HttpClient from 'effect/unstable/http/HttpClient';
5
5
  /** What every handler needs from the caller's runtime once `CredentialsFromEnv` is baked in. */
6
6
  export type UnifiRequirements = HttpClient.HttpClient;
7
7
  /**
@@ -34,6 +34,41 @@ export declare const unifiOperations: <Props extends object, Live, Attributes ex
34
34
  reconcile: (news: Props) => Effect.Effect<Attributes, E | import("./policy.ts").UnifiWriteRefused, UnifiNetworkOpContext>;
35
35
  destroy: (olds: Props) => Effect.Effect<never, import("./policy.ts").UnifiWriteRefused, never>;
36
36
  };
37
+ /**
38
+ * B0a / T12 DEFENSE IN DEPTH. `policy.ts`'s `UnifiWriteRefused` stops write INTENT at
39
+ * `reconcile`/`destroy` — every path this engine exposes already returns that refusal instead of
40
+ * calling an SDK write op. This guard stops the same thing one layer lower, AT THE WIRE: it wraps
41
+ * whatever `HttpClient` the caller already provides (the stack's `FetchHttpClient.layer` in
42
+ * production, `fakeUnifiLayer` in tests — `openbao/bao-http.ts`'s header names this same
43
+ * "wrap, don't replace" seam) so a future resource file that, by mistake, called an SDK write
44
+ * operation directly — bypassing `unifiOperations` entirely — would still never reach the vendor
45
+ * API. `write-op-reference.test.ts` proves no such call exists today; this is what stops one from
46
+ * ever taking effect if one is ever added.
47
+ *
48
+ * ⚠️ `Effect.die`, NOT A TYPED FAILURE — classified per distilled-doctrine's "classify every
49
+ * die/orDie". Every generated SDK operation (`networks.getNetworkDetails`, …) declares its OWN
50
+ * closed error union from the pinned OpenAPI spec, and generated files are never hand-edited to
51
+ * add a member to it. A typed `Effect.fail` here would be a failure mode absent from every op's
52
+ * declared type the moment it occurred — a type-system lie. A defect is the sound way to add a
53
+ * NEW "this must be structurally impossible" failure underneath types this package does not
54
+ * own, exactly like `openbao`'s `refuse()` helpers' `Effect.die(new Error(...))` for a
55
+ * configuration move that should never be reachable.
56
+ */
57
+ export declare class UnifiNonGetRequest extends Error {
58
+ readonly method: string;
59
+ /** PATH ONLY, never the full URL — see `requestPath` below. */
60
+ readonly path: string;
61
+ constructor(method: string,
62
+ /** PATH ONLY, never the full URL — see `requestPath` below. */
63
+ path: string);
64
+ }
65
+ /**
66
+ * A `Layer` that reads whatever `HttpClient` is already in the calling context and replaces it,
67
+ * for everything downstream, with `guardGetOnly`'s wrapped version (`HttpClient.layerMergedContext`
68
+ * — see the guard above). Exported so `get-only-guard.test.ts` can prove the mechanism directly,
69
+ * against a bare `HttpClient` service, without needing `CredentialsFromEnv` or any env var at all.
70
+ */
71
+ export declare const GetOnlyHttpClient: import("effect/Layer").Layer<HttpClient.HttpClient, never, HttpClient.HttpClient>;
37
72
  /**
38
73
  * The four provider handlers for a spec'd read-only UniFi object, wired once.
39
74
  *
@@ -1 +1 @@
1
- {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/unifi/resource.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAGnE,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,UAAU,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,IAAI;IAChF,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAChG,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,UAAU,CAAC;IAC9D,QAAQ,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACpE,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC;CAC7C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,QAChF,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;kBAEtB,KAAK;oCAQQ;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;iBAUlE,KAAK,CAAC,KAAK,CAAC,UAAU,UAAU,GAAG,SAAS;yBAIZ,QAAQ;;yBAElC,MAAM;;sBAIP,KAAK;oBAYP,KAAK;CAExB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,QAC9E,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAMzC,IAAI;IACJ,IAAI,SAAS;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;IAE5D,IAAI,SAAS;QAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;yBAtCtB,QAAQ;;yBAElC,MAAM;;IAsCzB,SAAS,SAAS;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IACjC,MAAM,SAAS;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;CAEjC,CAAC"}
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/unifi/resource.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAG9D,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,UAAU,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,IAAI;IAChF,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAChG,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,UAAU,CAAC;IAC9D,QAAQ,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACpE,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC;CAC7C,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,QAChF,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;kBAEtB,KAAK;oCAQQ;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;iBAUlE,KAAK,CAAC,KAAK,CAAC,UAAU,UAAU,GAAG,SAAS;yBAIZ,QAAQ;;yBAElC,MAAM;;sBAIP,KAAK;oBAYP,KAAK;CAExB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM;IAHvB,YACW,MAAM,EAAE,MAAM;IACvB,+DAA+D;IACtD,IAAI,EAAE,MAAM,EAStB;CACF;AA0BD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,mFAE7B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,SAAS,MAAM,EAAE,CAAC,QAC9E,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAMzC,IAAI;IACJ,IAAI,SAAS;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;IAE5D,IAAI,SAAS;QAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;yBA5GtB,QAAQ;;yBAElC,MAAM;;IA4GzB,SAAS,SAAS;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IACjC,MAAM,SAAS;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;CAEjC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * One left-to-right scan tracking a single state (code / `//` / `/* *\/` / string). Comments are
3
+ * blanked to spaces (newlines kept, so a caller's own line-number diagnostics still line up);
4
+ * string and template literal CONTENTS are left untouched, because a banned token hidden inside
5
+ * one is still an offense a caller needs to see.
6
+ */
7
+ export declare const stripComments: (src: string) => string;
8
+ /** Every `.ts` file under `dir`, recursively — a future `src/unifi/<subdir>/*.ts` is walked too. */
9
+ export declare const walk: (dir: string) => string[];
10
+ export declare const readSource: (path: string) => string;
11
+ //# sourceMappingURL=scan-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-source.d.ts","sourceRoot":"","sources":["../../src/unifi/scan-source.ts"],"names":[],"mappings":"AAqBA;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,MA2B3C,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,IAAI,QAAS,MAAM,KAAG,MAAM,EAIrC,CAAC;AAEL,eAAO,MAAM,UAAU,SAAU,MAAM,KAAG,MAAoC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `Unifi.TrafficMatchingList`'s `matches` AND `driftOf` (B6) — both built on the ONE field list
3
+ * below, the same `fieldDrift`-is-the-only-comparison shape `network-drift.ts`'s header explains
4
+ * (MEDIUM-4, red team, 2026-09-26): `matches(attrs, props) === (driftOf(live, props).length === 0)`
5
+ * is true BY CONSTRUCTION, never two hand-kept-in-sync comparisons.
6
+ *
7
+ * ⚠️ `stripNullish: true` ON EVERY FIELD BY DEFAULT (`drift.ts`'s `defaultEqual`) — same "UniFi's
8
+ * JSON answers `null`, a declaration omits" tolerance every other family here relies on.
9
+ * ★ `items` compares with the plain default `equal` (whole-value `deepEqual`) — see
10
+ * `traffic-matching-list-form.ts`'s header for the accepted known gap this leaves for a
11
+ * membership-preserving reorder.
12
+ */
13
+ import type * as trafficMatchingLists from '@distilled.cloud/unifi-network/traffic_matching_lists';
14
+ import { type TrafficMatchingListAttributes, type TrafficMatchingListProps } from './traffic-matching-list-form.ts';
15
+ export declare const matches: (attributes: TrafficMatchingListAttributes, props: TrafficMatchingListProps) => boolean;
16
+ /**
17
+ * Per-field live-vs-declared drift straight from one live read — the task's own API
18
+ * (`driftOf(live, props)`), so `homeflare-network`'s pre-import drift check never has to derive
19
+ * `attributesOf` itself just to call this.
20
+ */
21
+ export declare const driftOf: (live: trafficMatchingLists.TrafficMatchingList, props: TrafficMatchingListProps) => import("./drift.ts").FieldDrift[];
22
+ //# sourceMappingURL=traffic-matching-list-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traffic-matching-list-drift.d.ts","sourceRoot":"","sources":["../../src/unifi/traffic-matching-list-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,KAAK,oBAAoB,MAAM,uDAAuD,CAAC;AAEnG,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAE9B,MAAM,iCAAiC,CAAC;AAQzC,eAAO,MAAM,OAAO,eACN,6BAA6B,SAClC,wBAAwB,KAC9B,OAAqD,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,OAAO,SACZ,oBAAoB,CAAC,mBAAmB,SACvC,wBAAwB,sCACgB,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `Unifi.TrafficMatchingList`'s wire shape — the declarable subset of `TrafficMatchingList`
3
+ * (`getTrafficMatchingList`'s own decode target), and how a live read becomes both plan attributes
4
+ * and a rendered declaration.
5
+ *
6
+ * ★ NO `metadata` FIELD AT ALL — the simplest object shape in this directory. Unlike every other
7
+ * family here (`FirewallZone`/`DNSPolicy`/`ACLRule`/`FirewallPolicy` all carry a server-derived
8
+ * `metadata.origin`), `TrafficMatchingList` is just `{id, name, type, items?}` — nothing here is
9
+ * attributes-only the way `metadataOrigin`/`index` are elsewhere.
10
+ *
11
+ * ★ `items` IS A REAL TS UNION POST-A3, COMPARED WHOLESALE — `Array<IPv4Matching> |
12
+ * Array<IPv6Matching> | Array<PortMatching>`, keyed by the sibling `type` field
13
+ * (`traffic_matching_lists.ts`'s own comment: "Shape depends on the sibling discriminator value").
14
+ * The runtime schema is still a passthrough `S.Unknown` (A3's own changeset: narrower for a reader
15
+ * at the type level only, so decode keeps every key including one this pinned spec doesn't yet
16
+ * declare — same proof `discriminated-filter-decode.test.ts` runs for `FirewallPolicy`/`AclRule`).
17
+ *
18
+ * ⚠️ KNOWN GAP (T15, same shape `acl-rule-form.ts`/`firewall-policy-form.ts` both carry): a traffic
19
+ * matching list's `items` is semantically a SET of match entries (matching is "is this traffic
20
+ * covered by ANY entry," not order-dependent, unlike `firewall-policy-ordering-form.ts`'s own
21
+ * sequences), but each entry is an OBJECT (`{type, value?, start?, stop?}`), not a bare string --
22
+ * there is no cheap canonical sort key the way `sortedSet` gives a `string[]`. `deepEqual` compares
23
+ * `items` order-sensitively, so a console-side reorder with no membership change would report a
24
+ * spurious drift this read-only family's `reconcile` then refuses forever. Accepted, not fixed,
25
+ * same proportion as ACL rule's own nested-filter gap: a generic object-set normalizer is bigger,
26
+ * separate modelling work, not a mechanical extension of typing `items` per-discriminator (A3).
27
+ */
28
+ import type * as trafficMatchingLists from '@distilled.cloud/unifi-network/traffic_matching_lists';
29
+ export interface TrafficMatchingListProps {
30
+ siteId: string;
31
+ trafficMatchingListId: string;
32
+ name: string;
33
+ /** Discriminator for `items`' own shape (e.g. an IPv4/IPv6/port list) — the spec enumerates no
34
+ * fixed value set for it (also accepts a future vendor value it did not enumerate). */
35
+ type: string;
36
+ /** Match entries — a SET semantically, compared wholesale; see the header's known gap. */
37
+ items?: trafficMatchingLists.TrafficMatchingListItems | undefined;
38
+ }
39
+ export interface TrafficMatchingListAttributes {
40
+ siteId: string;
41
+ trafficMatchingListId: string;
42
+ name: string;
43
+ type: string;
44
+ items: trafficMatchingLists.TrafficMatchingListItems | undefined;
45
+ }
46
+ export declare const attributesOf: (live: trafficMatchingLists.TrafficMatchingList, props: TrafficMatchingListProps) => TrafficMatchingListAttributes;
47
+ /**
48
+ * The declaration renderer (task spec: "given one live object, return the props a declaration
49
+ * needs so its plan is noop"). A later import script feeds `getTrafficMatchingList`'s own response
50
+ * straight in and writes the result as `trafficMatchingList('<id>',
51
+ * declareTrafficMatchingList(live, siteId))` — no field is invented or defaulted beyond what
52
+ * `attributesOf` already reports, so `matches(attributesOf(live, props), declareTrafficMatchingList(
53
+ * live, siteId))` is `true` by construction (`traffic-matching-list.test.ts` proves it).
54
+ */
55
+ export declare const declareTrafficMatchingList: (live: trafficMatchingLists.TrafficMatchingList, siteId: string) => TrafficMatchingListProps;
56
+ //# sourceMappingURL=traffic-matching-list-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traffic-matching-list-form.d.ts","sourceRoot":"","sources":["../../src/unifi/traffic-matching-list-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,KAAK,oBAAoB,MAAM,uDAAuD,CAAC;AAEnG,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb;4FACwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,KAAK,CAAC,EAAE,oBAAoB,CAAC,wBAAwB,GAAG,SAAS,CAAC;CACnE;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,oBAAoB,CAAC,wBAAwB,GAAG,SAAS,CAAC;CAClE;AAED,eAAO,MAAM,YAAY,SACjB,oBAAoB,CAAC,mBAAmB,SACvC,wBAAwB,KAC9B,6BAMD,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,SAC/B,oBAAoB,CAAC,mBAAmB,UACtC,MAAM,KACb,wBAMD,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `Unifi.TrafficMatchingList` — one traffic matching list (IPv4/IPv6/port match entries) on a UniFi
3
+ * Network site, READ-ONLY (`policy.ts`).
4
+ *
5
+ * ★ T11 GATE, CHECKED 2026-09-26: `Traffic Matching Lists`' 5 operations are byte-identical between
6
+ * 10.4.57 and 10.6.97, full raw operation objects; the 19-schema closure reachable from all 5
7
+ * (`$ref` + `discriminator.mapping`) shares zero names with the 14 schemas that DID change
8
+ * elsewhere in the document. Corroborated independently by the A3 changeset's own broader
9
+ * 25-operation/139-schema re-check (`.changeset/unifi-network-a3-typed-discriminator-filters.md`).
10
+ * Full breakdown: `docs/unifi-traffic-matching-list.md`.
11
+ */
12
+ import { Resource } from 'alchemy';
13
+ import * as Provider from 'alchemy/Provider';
14
+ import * as trafficMatchingLists from '@distilled.cloud/unifi-network/traffic_matching_lists';
15
+ import * as Effect from 'effect/Effect';
16
+ import { type TrafficMatchingListAttributes, type TrafficMatchingListProps } from './traffic-matching-list-form.ts';
17
+ import type { UnifiRequirements, UnifiSpec } from './resource.ts';
18
+ export type { TrafficMatchingListAttributes, TrafficMatchingListProps, } from './traffic-matching-list-form.ts';
19
+ export { declareTrafficMatchingList } from './traffic-matching-list-form.ts';
20
+ export { driftOf } from './traffic-matching-list-drift.ts';
21
+ export interface UnifiTrafficMatchingList extends Resource<'Unifi.TrafficMatchingList', TrafficMatchingListProps, TrafficMatchingListAttributes, never, UnifiRequirements> {
22
+ }
23
+ export declare const UnifiTrafficMatchingList: import("alchemy").ResourceClass<UnifiTrafficMatchingList>;
24
+ /** `trafficMatchingList('office-subnets', props)` — `adopt(true)` piped on by default (H5); see
25
+ * `network.ts`. */
26
+ export declare const trafficMatchingList: (id: string, props: TrafficMatchingListProps) => Effect.Effect<UnifiTrafficMatchingList, never, import("effect/unstable/http/HttpClient").HttpClient>;
27
+ /** ★ EXPORTED for direct testing against a fake `Credentials` layer — see `network.ts`'s own. */
28
+ export declare const spec: UnifiSpec<TrafficMatchingListProps, trafficMatchingLists.TrafficMatchingList, TrafficMatchingListAttributes, trafficMatchingLists.GetTrafficMatchingListError>;
29
+ export declare const handlers: {
30
+ list: () => Effect.Effect<never[], never, never>;
31
+ read: (args: {
32
+ olds: TrafficMatchingListProps;
33
+ output: TrafficMatchingListAttributes | undefined;
34
+ }) => Effect.Effect<TrafficMatchingListAttributes | undefined, trafficMatchingLists.UnifiNetworkOpError, import("effect/unstable/http/HttpClient").HttpClient>;
35
+ diff: (args: {
36
+ news: import("alchemy").Input<TrafficMatchingListProps>;
37
+ output: TrafficMatchingListAttributes | undefined;
38
+ }) => Effect.Effect<{
39
+ readonly action: 'update';
40
+ } | {
41
+ readonly action: 'noop';
42
+ } | undefined, trafficMatchingLists.UnifiNetworkOpError, import("effect/unstable/http/HttpClient").HttpClient>;
43
+ reconcile: (args: {
44
+ news: TrafficMatchingListProps;
45
+ }) => Effect.Effect<TrafficMatchingListAttributes, import("./policy.ts").UnifiWriteRefused | trafficMatchingLists.UnifiNetworkOpError, import("effect/unstable/http/HttpClient").HttpClient>;
46
+ delete: (args: {
47
+ olds: TrafficMatchingListProps;
48
+ }) => Effect.Effect<never, import("./policy.ts").UnifiWriteRefused, import("effect/unstable/http/HttpClient").HttpClient>;
49
+ };
50
+ export declare const UnifiTrafficMatchingListProvider: () => import("effect/Layer").Layer<Provider.Provider<UnifiTrafficMatchingList>, never, import("effect/unstable/http/HttpClient").HttpClient>;
51
+ //# sourceMappingURL=traffic-matching-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traffic-matching-list.d.ts","sourceRoot":"","sources":["../../src/unifi/traffic-matching-list.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,oBAAoB,MAAM,uDAAuD,CAAC;AAC9F,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAE9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,YAAY,EACV,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAE3D,MAAM,WAAW,wBAAyB,SAAQ,QAAQ,CACxD,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,KAAK,EACL,iBAAiB,CAClB;CAAG;AAEJ,eAAO,MAAM,wBAAwB,2DAGpC,CAAC;AAEF;oBACoB;AACpB,eAAO,MAAM,mBAAmB,OAAQ,MAAM,SAAS,wBAAwB,yGACxB,CAAC;AAExD,iGAAiG;AACjG,eAAO,MAAM,IAAI,EAAE,SAAS,CAC1B,wBAAwB,EACxB,oBAAoB,CAAC,mBAAmB,EACxC,6BAA6B,EAC7B,oBAAoB,CAAC,2BAA2B,CAcjD,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;CAAsB,CAAC;AAE5C,eAAO,MAAM,gCAAgC,8IAI1C,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `Unifi.WifiBroadcast`'s `matches` AND `driftOf` (B6) — built on the ONE field list below, the
3
+ * same `fieldDrift`-is-the-only-comparison shape `dns-policy-drift.ts`'s header explains
4
+ * (MEDIUM-4): `matches(attrs, props) === (driftOf(live, props).length === 0)` is true BY
5
+ * CONSTRUCTION, never two hand-kept-in-sync comparisons.
6
+ *
7
+ * ★ THREE FIELDS REUSE `wifi-broadcast-form.ts`'s OWN NORMALIZERS ON THE `declared` SIDE TOO, not
8
+ * just the `live` side — `firewall-zone-form.ts`'s `networkIds` gives the same reason: comparing
9
+ * a freshly-normalized live value against an un-normalized declared value would report spurious
10
+ * drift the moment a committed declaration's array happens to be in a different (still valid)
11
+ * order than what `declareWifiBroadcast` would itself produce today.
12
+ */
13
+ import type * as wifiBroadcasts from '@distilled.cloud/unifi-network/wifi_broadcasts';
14
+ import { type WifiBroadcastAttributes, type WifiBroadcastProps } from './wifi-broadcast-form.ts';
15
+ export declare const matches: (attributes: WifiBroadcastAttributes, props: WifiBroadcastProps) => boolean;
16
+ /**
17
+ * Per-field live-vs-declared drift straight from one live read — the task's own API
18
+ * (`driftOf(live, props)`), so `homeflare-network`'s pre-import drift check never has to derive
19
+ * `attributesOf` itself just to call this.
20
+ */
21
+ export declare const driftOf: (live: wifiBroadcasts.WifiBroadcastOverview, props: WifiBroadcastProps) => import("./drift.ts").FieldDrift[];
22
+ //# sourceMappingURL=wifi-broadcast-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wifi-broadcast-drift.d.ts","sourceRoot":"","sources":["../../src/unifi/wifi-broadcast-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,KAAK,cAAc,MAAM,gDAAgD,CAAC;AAEtF,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAOxB,MAAM,0BAA0B,CAAC;AAoClC,eAAO,MAAM,OAAO,eAAgB,uBAAuB,SAAS,kBAAkB,KAAG,OAC7C,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,OAAO,SAAU,cAAc,CAAC,qBAAqB,SAAS,kBAAkB,sCAC/C,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `Unifi.WifiBroadcast`'s wire shape — the declarable subset of `WifiBroadcastOverview`, and how
3
+ * a live read becomes both plan attributes and a rendered declaration.
4
+ *
5
+ * ⛔ T23, THE WHOLE REASON THIS SHAPE DIFFERS FROM EVERY OTHER FAMILY HERE. Every other family's
6
+ * `*-form.ts` (`network-form.ts`, `dns-policy-form.ts`, …) types its props against the vendor's
7
+ * CREATE/UPDATE request — the fullest declarable shape, even though this stack never calls it.
8
+ * `WifiBroadcastProps`/`WifiBroadcastAttributes` do NOT: `securityConfiguration` is typed
9
+ * `wifiBroadcasts.WifiSecurityConfigurationOverview` — the PAGE OVERVIEW's own type, `{type,
10
+ * presharedKeyNetworkIds}` — never `WifiSecurityConfigurationDetailObject` (the
11
+ * `getWifiBroadcastDetails`/create/update shape, which carries `passphrase` and
12
+ * `radiusConfiguration`). There is no DECLARED field on `WifiSecurityConfigurationOverview` for
13
+ * `attributesOf`/`declareWifiBroadcast` below to name a passphrase into. See `wifi-broadcast.ts`'s
14
+ * header for why `fetchLive` can only ever produce a `WifiBroadcastOverview` in the first place
15
+ * (no get-by-id call exists for it).
16
+ *
17
+ * ⛔ THE TYPE SYSTEM ALONE DOES NOT ENFORCE THIS (red team, IMPORTANT-1, 2026-09-26). `@distilled
18
+ * .cloud/core`'s wire decode does not strip a key a schema doesn't declare (this file's next
19
+ * header block); the TS types above describe what a CORRECTLY-shaped response looks like, not
20
+ * what the decoder actually returns at runtime, so a stray key nested inside `network`,
21
+ * `hotspotConfiguration`, `broadcastingDeviceFilter`, or an element of `presharedKeyNetworkIds`
22
+ * would ride along through a naive `{...live}`/pass-through copy exactly like the top-level
23
+ * `securityConfiguration` object does. `normalizeRef`/`normalizeHotspot`/`normalizeDeviceFilter`
24
+ * below rebuild EVERY nested object field-by-field for the same reason
25
+ * `normalizeSecurityConfiguration` does — enumeration, not the type annotation, is what actually
26
+ * stops it. `wifi-broadcast-secrets.test.ts` plants a sentinel inside each nested shape
27
+ * (including one `presharedKeyNetworkIds` element) to prove it, not just the top level.
28
+ *
29
+ * ⚠️ EVERY OTHER FIELD REUSES THE SDK'S OWN OVERVIEW TYPES DIRECTLY (`WifiNetworkReference`,
30
+ * `BroadcastingDeviceFilter`, `IntegrationWifiHotspotConfigurationOverviewDto`) rather than
31
+ * redeclaring them — same reasoning `network-form.ts` gives for reusing `NetworkDHCPGuarding`/
32
+ * `NetworkIPv6Configuration` verbatim: one shape to keep in sync with the SDK's own regen.
33
+ *
34
+ * ⛔ THREE FIELDS ARE SETS, NOT SEQUENCES, UNCONFIRMED AGAINST A LIVE CONSOLE (same caveat
35
+ * `network-form.ts`'s header gives for its own three): `broadcastingDeviceFilter.deviceIds`/
36
+ * `.deviceTagIds` and `securityConfiguration.presharedKeyNetworkIds` are membership sets by the
37
+ * vendor description's own wording ("Defines the custom scope of devices…"), not ordered
38
+ * sequences. `normalizeDeviceFilter`/`normalizeSecurityConfiguration`/`normalizeFrequencies`
39
+ * neutralize the same "spurious update, refused by a read-only reconcile" failure mode
40
+ * `network-form.ts`'s header describes, exactly like `firewall-zone-form.ts`'s `networkIds`.
41
+ */
42
+ import type * as wifiBroadcasts from '@distilled.cloud/unifi-network/wifi_broadcasts';
43
+ /**
44
+ * Rebuilds a reference field-by-field — never returns the object as received. IMPORTANT-1: this
45
+ * runs on EVERY reference this file handles (`network`, and each `presharedKeyNetworkIds`
46
+ * element) precisely because a reference is exactly the shape (`{network: WifiNetworkReference,
47
+ * passphrase}`) the details call uses to carry a PPSK passphrase (`IntegrationWifiPresharedKeyDto`,
48
+ * SDK `wifi_broadcasts.ts`); it is the most plausible place for a stray passphrase-shaped key to
49
+ * appear on the wire if the vendor ever leaked one onto the overview response.
50
+ */
51
+ export declare const normalizeRef: (ref: wifiBroadcasts.WifiNetworkReference | undefined) => wifiBroadcasts.WifiNetworkReference | undefined;
52
+ /**
53
+ * Rebuilds the hotspot configuration field-by-field. `IntegrationWifiHotspotConfigurationOverviewDto`
54
+ * declares only `type` (SDK `wifi_broadcasts.ts:743-753`) — a PASSPOINT/RADIUS secret would live on
55
+ * a wire key this type doesn't name, exactly the IMPORTANT-1 risk `normalizeRef` guards against.
56
+ */
57
+ export declare const normalizeHotspot: (value: wifiBroadcasts.IntegrationWifiHotspotConfigurationOverviewDto | undefined) => wifiBroadcasts.IntegrationWifiHotspotConfigurationOverviewDto | undefined;
58
+ /**
59
+ * ★ EXPORTED: `wifi-broadcast-drift.ts` reuses these exact normalizers so `matches`/`driftOf` can
60
+ * never quietly disagree about what counts as a change (MEDIUM-4, `network-drift.ts`'s header).
61
+ *
62
+ * ⛔ NO `{...value}` SPREAD (red team, IMPORTANT-1) — `BroadcastingDeviceFilter` declares exactly
63
+ * `type`/`deviceIds`/`deviceTagIds` (SDK `wifi_broadcasts.ts:125-129`); enumerating exactly those
64
+ * three is what stops a stray wire key here, the same reason `normalizeSecurityConfiguration`
65
+ * (below) never spreads its input.
66
+ */
67
+ export declare const normalizeDeviceFilter: (value: wifiBroadcasts.BroadcastingDeviceFilter | undefined) => wifiBroadcasts.BroadcastingDeviceFilter | undefined;
68
+ export declare const normalizeFrequencies: (value: readonly number[] | undefined) => number[] | undefined;
69
+ /**
70
+ * ⛔ NO `{...value}` SPREAD, UNLIKE EVERY OTHER NORMALIZER IN THIS DIRECTORY (`network-form.ts`'s
71
+ * `normalizeDhcpGuarding`/`normalizeIpv6Configuration` both spread). This is the one field in
72
+ * the whole `Unifi.*` tree with a spec-confirmed passphrase risk (T23): nothing in
73
+ * `@distilled.cloud/core`'s wire key-mapping strips an object key the schema doesn't declare —
74
+ * it only renames declared ones — so a stray extra key on the WIRE `securityConfiguration`
75
+ * object (a vendor bug, or a future console version) survives `getWifiBroadcastPage`'s own
76
+ * decode untyped, and `{...value}` would carry it straight through into `Attributes`/`Props`/the
77
+ * rendered declaration. Enumerating exactly the two fields
78
+ * `WifiSecurityConfigurationOverview` declares is what actually stops that — proved by
79
+ * `wifi-broadcast-secrets.test.ts`'s sentinel test, which injects exactly this kind of stray key.
80
+ */
81
+ export declare const normalizeSecurityConfiguration: (value: wifiBroadcasts.WifiSecurityConfigurationOverview) => wifiBroadcasts.WifiSecurityConfigurationOverview;
82
+ /**
83
+ * ⚠️ EVERY OPTIONAL FIELD SPELLS OUT `| undefined` ON PURPOSE — `exactOptionalPropertyTypes`; see
84
+ * `network-form.ts`'s own header. `attributesOf`/`declareWifiBroadcast` echo a live optional
85
+ * field structurally rather than defaulting it, so the target type must admit an explicit
86
+ * `undefined`.
87
+ */
88
+ export interface WifiBroadcastProps {
89
+ siteId: string;
90
+ wifiBroadcastId: string;
91
+ name: string;
92
+ enabled: boolean;
93
+ type: string;
94
+ network?: wifiBroadcasts.WifiNetworkReference | undefined;
95
+ broadcastingDeviceFilter?: wifiBroadcasts.BroadcastingDeviceFilter | undefined;
96
+ broadcastingFrequenciesGHz?: number[] | undefined;
97
+ hotspotConfiguration?: wifiBroadcasts.IntegrationWifiHotspotConfigurationOverviewDto | undefined;
98
+ /** ⛔ T23: the PAGE OVERVIEW's security shape ONLY — see this file's header. */
99
+ securityConfiguration: wifiBroadcasts.WifiSecurityConfigurationOverview;
100
+ }
101
+ export interface WifiBroadcastAttributes {
102
+ siteId: string;
103
+ wifiBroadcastId: string;
104
+ name: string;
105
+ enabled: boolean;
106
+ type: string;
107
+ network: wifiBroadcasts.WifiNetworkReference | undefined;
108
+ broadcastingDeviceFilter: wifiBroadcasts.BroadcastingDeviceFilter | undefined;
109
+ broadcastingFrequenciesGHz: number[] | undefined;
110
+ hotspotConfiguration: wifiBroadcasts.IntegrationWifiHotspotConfigurationOverviewDto | undefined;
111
+ securityConfiguration: wifiBroadcasts.WifiSecurityConfigurationOverview;
112
+ /** `metadata.origin` — server-derived, never declared; same split as every other family. */
113
+ metadataOrigin: string;
114
+ }
115
+ export declare const attributesOf: (live: wifiBroadcasts.WifiBroadcastOverview, props: WifiBroadcastProps) => WifiBroadcastAttributes;
116
+ /**
117
+ * The declaration renderer (task spec: "given one live object, return the props a declaration
118
+ * needs so its plan is noop"). A later import script feeds `getWifiBroadcastPage`'s own per-row
119
+ * response straight in and writes the result into `alchemy.run.ts` as `wifiBroadcast('<id>',
120
+ * declareWifiBroadcast(live, siteId))` — no field is invented or defaulted here beyond what
121
+ * `attributesOf` already reports, so `matches(attributesOf(live, props), declareWifiBroadcast(live,
122
+ * siteId))` is `true` by construction (`wifi-broadcast.test.ts` proves it) for any live object
123
+ * this SDK can decode. Builds ONLY from fields `WifiBroadcastOverview` has — never a passphrase,
124
+ * which that type cannot express (see this file's header).
125
+ */
126
+ export declare const declareWifiBroadcast: (live: wifiBroadcasts.WifiBroadcastOverview, siteId: string) => WifiBroadcastProps;
127
+ //# sourceMappingURL=wifi-broadcast-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wifi-broadcast-form.d.ts","sourceRoot":"","sources":["../../src/unifi/wifi-broadcast-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,KAAK,KAAK,cAAc,MAAM,gDAAgD,CAAC;AAWtF;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,QAClB,cAAc,CAAC,oBAAoB,GAAG,SAAS,KACnD,cAAc,CAAC,oBAAoB,GAAG,SAGqD,CAAC;AAa/F;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UACpB,cAAc,CAAC,8CAA8C,GAAG,SAAS,KAC/E,cAAc,CAAC,8CAA8C,GAAG,SACX,CAAC;AAEzD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,UACzB,cAAc,CAAC,wBAAwB,GAAG,SAAS,KACzD,cAAc,CAAC,wBAAwB,GAAG,SAStC,CAAC;AAER,eAAO,MAAM,oBAAoB,UAAW,SAAS,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EAAE,GAAG,SAC/B,CAAC;AAEzD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,UAClC,cAAc,CAAC,iCAAiC,KACtD,cAAc,CAAC,iCAKhB,CAAC;AAEH;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,cAAc,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAC1D,wBAAwB,CAAC,EAAE,cAAc,CAAC,wBAAwB,GAAG,SAAS,CAAC;IAC/E,0BAA0B,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAClD,oBAAoB,CAAC,EAAE,cAAc,CAAC,8CAA8C,GAAG,SAAS,CAAC;IACjG,+EAA+E;IAC/E,qBAAqB,EAAE,cAAc,CAAC,iCAAiC,CAAC;CACzE;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC,oBAAoB,GAAG,SAAS,CAAC;IACzD,wBAAwB,EAAE,cAAc,CAAC,wBAAwB,GAAG,SAAS,CAAC;IAC9E,0BAA0B,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjD,oBAAoB,EAAE,cAAc,CAAC,8CAA8C,GAAG,SAAS,CAAC;IAChG,qBAAqB,EAAE,cAAc,CAAC,iCAAiC,CAAC;IACxE,4FAA4F;IAC5F,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,SACjB,cAAc,CAAC,qBAAqB,SACnC,kBAAkB,KACxB,uBAYD,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,SACzB,cAAc,CAAC,qBAAqB,UAClC,MAAM,KACb,kBAWD,CAAC"}