@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.
- package/README.md +32 -8
- package/dist/ceph/auth-entity.d.ts +34 -0
- package/dist/ceph/auth-entity.d.ts.map +1 -0
- package/dist/ceph/ceph-argv-config.d.ts +10 -0
- package/dist/ceph/ceph-argv-config.d.ts.map +1 -0
- package/dist/ceph/ceph-argv.d.ts +19 -0
- package/dist/ceph/ceph-argv.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-form.d.ts +54 -0
- package/dist/ceph/ceph-auth-form.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-parse.d.ts +56 -0
- package/dist/ceph/ceph-auth-parse.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-reconcile.d.ts +35 -0
- package/dist/ceph/ceph-auth-reconcile.d.ts.map +1 -0
- package/dist/ceph/ceph-config-options.d.ts +23 -0
- package/dist/ceph/ceph-config-options.d.ts.map +1 -0
- package/dist/ceph/ceph-key-leak-assert.d.ts +25 -0
- package/dist/ceph/ceph-key-leak-assert.d.ts.map +1 -0
- package/dist/ceph/ceph-transport.d.ts +37 -0
- package/dist/ceph/ceph-transport.d.ts.map +1 -0
- package/dist/ceph/fake-ceph-dial.d.ts +35 -0
- package/dist/ceph/fake-ceph-dial.d.ts.map +1 -0
- package/dist/ceph/index.d.ts +13 -0
- package/dist/ceph/index.d.ts.map +1 -0
- package/dist/ceph/index.js +1609 -0
- package/dist/ceph/index.js.map +38 -0
- package/dist/forgejo/index.js +4 -2
- package/dist/forgejo/index.js.map +3 -3
- package/dist/forgejo/team-member.d.ts +25 -0
- package/dist/forgejo/team-member.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/index.d.ts +1 -1
- package/dist/proxmox/generated/constraints/index.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts +23 -0
- package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts.map +1 -0
- package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
- package/dist/proxmox/index.d.ts +14 -3
- package/dist/proxmox/index.d.ts.map +1 -1
- package/dist/proxmox/index.js +574 -133
- package/dist/proxmox/index.js.map +33 -23
- package/dist/proxmox/qemu-form.d.ts +27 -18
- package/dist/proxmox/qemu-form.d.ts.map +1 -1
- package/dist/proxmox/qemu-judge.d.ts +30 -0
- package/dist/proxmox/qemu-judge.d.ts.map +1 -0
- package/dist/proxmox/qemu-lifecycle.d.ts +16 -2
- package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/qemu-net.d.ts +9 -0
- package/dist/proxmox/qemu-net.d.ts.map +1 -0
- package/dist/proxmox/qemu-props.d.ts +112 -0
- package/dist/proxmox/qemu-props.d.ts.map +1 -0
- package/dist/proxmox/qemu-volume.d.ts +27 -0
- package/dist/proxmox/qemu-volume.d.ts.map +1 -0
- package/dist/proxmox/qemu.d.ts +14 -27
- package/dist/proxmox/qemu.d.ts.map +1 -1
- package/dist/proxmox/storage-download-errors.d.ts +5 -0
- package/dist/proxmox/storage-download-errors.d.ts.map +1 -0
- package/dist/proxmox/storage-download-identity.d.ts +27 -0
- package/dist/proxmox/storage-download-identity.d.ts.map +1 -0
- package/dist/proxmox/storage-download-lifecycle.d.ts +97 -0
- package/dist/proxmox/storage-download-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/storage-download-props.d.ts +36 -0
- package/dist/proxmox/storage-download-props.d.ts.map +1 -0
- package/dist/proxmox/storage-download-task.d.ts +17 -0
- package/dist/proxmox/storage-download-task.d.ts.map +1 -0
- package/dist/proxmox/storage-download.d.ts +44 -0
- package/dist/proxmox/storage-download.d.ts.map +1 -0
- package/dist/talos/credentials-write.d.ts +46 -0
- package/dist/talos/credentials-write.d.ts.map +1 -0
- package/dist/talos/credentials.d.ts +51 -9
- package/dist/talos/credentials.d.ts.map +1 -1
- package/dist/talos/fake-process.d.ts +56 -0
- package/dist/talos/fake-process.d.ts.map +1 -0
- package/dist/talos/index.d.ts +19 -4
- package/dist/talos/index.d.ts.map +1 -1
- package/dist/talos/index.js +357 -173
- package/dist/talos/index.js.map +16 -10
- package/dist/talos/kubeconfig-attrs.d.ts +4 -0
- package/dist/talos/kubeconfig-attrs.d.ts.map +1 -0
- package/dist/talos/kubeconfig.d.ts +41 -23
- package/dist/talos/kubeconfig.d.ts.map +1 -1
- package/dist/talos/machine-config-fixtures.d.ts +60 -0
- package/dist/talos/machine-config-fixtures.d.ts.map +1 -0
- package/dist/talos/machine-config-poll.d.ts +43 -0
- package/dist/talos/machine-config-poll.d.ts.map +1 -0
- package/dist/talos/machine-config-read.d.ts +49 -0
- package/dist/talos/machine-config-read.d.ts.map +1 -0
- package/dist/talos/resource.d.ts +18 -0
- package/dist/talos/resource.d.ts.map +1 -1
- package/dist/talos/talos-bootstrap-etcd.d.ts +38 -0
- package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -0
- package/dist/talos/talos-bootstrap.d.ts +87 -0
- package/dist/talos/talos-bootstrap.d.ts.map +1 -1
- package/dist/talos/talos-cluster-health.d.ts +43 -1
- package/dist/talos/talos-cluster-health.d.ts.map +1 -1
- package/dist/talos/talos-errors.d.ts +68 -0
- package/dist/talos/talos-errors.d.ts.map +1 -0
- package/dist/talos/talos-machine-config.d.ts +51 -15
- package/dist/talos/talos-machine-config.d.ts.map +1 -1
- package/dist/talos/talosctl.d.ts +7 -0
- package/dist/talos/talosctl.d.ts.map +1 -1
- package/dist/talos/values.d.ts +23 -3
- package/dist/talos/values.d.ts.map +1 -1
- package/dist/telemetry/fake-collector.d.ts +36 -0
- package/dist/telemetry/fake-collector.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +11 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +223 -0
- package/dist/telemetry/index.js.map +12 -0
- package/dist/telemetry/layer.d.ts +86 -0
- package/dist/telemetry/layer.d.ts.map +1 -0
- package/dist/telemetry/redact-serialization.d.ts +21 -0
- package/dist/telemetry/redact-serialization.d.ts.map +1 -0
- package/dist/telemetry/redact.d.ts +46 -0
- package/dist/telemetry/redact.d.ts.map +1 -0
- package/dist/unifi/acl-rule-drift.d.ts +22 -0
- package/dist/unifi/acl-rule-drift.d.ts.map +1 -0
- package/dist/unifi/acl-rule-form.d.ts +90 -0
- package/dist/unifi/acl-rule-form.d.ts.map +1 -0
- package/dist/unifi/acl-rule-ordering-form.d.ts +49 -0
- package/dist/unifi/acl-rule-ordering-form.d.ts.map +1 -0
- package/dist/unifi/acl-rule-ordering.d.ts +54 -0
- package/dist/unifi/acl-rule-ordering.d.ts.map +1 -0
- package/dist/unifi/acl-rule.d.ts +49 -0
- package/dist/unifi/acl-rule.d.ts.map +1 -0
- package/dist/unifi/dns-policy-drift.d.ts +21 -0
- package/dist/unifi/dns-policy-drift.d.ts.map +1 -0
- package/dist/unifi/dns-policy-form.d.ts +97 -0
- package/dist/unifi/dns-policy-form.d.ts.map +1 -0
- package/dist/unifi/dns-policy.d.ts +55 -0
- package/dist/unifi/dns-policy.d.ts.map +1 -0
- package/dist/unifi/drift.d.ts +27 -0
- package/dist/unifi/drift.d.ts.map +1 -0
- package/dist/unifi/fake-unifi.d.ts +5 -1
- package/dist/unifi/fake-unifi.d.ts.map +1 -1
- package/dist/unifi/firewall-policy-drift.d.ts +26 -0
- package/dist/unifi/firewall-policy-drift.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-form.d.ts +102 -0
- package/dist/unifi/firewall-policy-form.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-ordering-form.d.ts +66 -0
- package/dist/unifi/firewall-policy-ordering-form.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-ordering.d.ts +57 -0
- package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -0
- package/dist/unifi/firewall-policy.d.ts +57 -0
- package/dist/unifi/firewall-policy.d.ts.map +1 -0
- package/dist/unifi/firewall-zone-form.d.ts +6 -0
- package/dist/unifi/firewall-zone-form.d.ts.map +1 -1
- package/dist/unifi/firewall-zone.d.ts +1 -1
- package/dist/unifi/firewall-zone.d.ts.map +1 -1
- package/dist/unifi/index.d.ts +11 -3
- package/dist/unifi/index.d.ts.map +1 -1
- package/dist/unifi/index.js +725 -60
- package/dist/unifi/index.js.map +31 -9
- package/dist/unifi/network-drift.d.ts +26 -0
- package/dist/unifi/network-drift.d.ts.map +1 -0
- package/dist/unifi/network-form.d.ts +40 -7
- package/dist/unifi/network-form.d.ts.map +1 -1
- package/dist/unifi/network.d.ts +1 -0
- package/dist/unifi/network.d.ts.map +1 -1
- package/dist/unifi/paginate.d.ts +24 -0
- package/dist/unifi/paginate.d.ts.map +1 -0
- package/dist/unifi/providers.d.ts +1 -1
- package/dist/unifi/providers.d.ts.map +1 -1
- package/dist/unifi/resource.d.ts +36 -1
- package/dist/unifi/resource.d.ts.map +1 -1
- package/dist/unifi/scan-source.d.ts +11 -0
- package/dist/unifi/scan-source.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list-drift.d.ts +22 -0
- package/dist/unifi/traffic-matching-list-drift.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list-form.d.ts +56 -0
- package/dist/unifi/traffic-matching-list-form.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list.d.ts +51 -0
- package/dist/unifi/traffic-matching-list.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast-drift.d.ts +22 -0
- package/dist/unifi/wifi-broadcast-drift.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast-form.d.ts +127 -0
- package/dist/unifi/wifi-broadcast-form.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast.d.ts +73 -0
- package/dist/unifi/wifi-broadcast.d.ts.map +1 -0
- package/docs/telemetry-spike.md +94 -0
- package/docs/telemetry.md +109 -0
- package/docs/unifi-acl-rule.md +122 -0
- package/docs/unifi-dns-policy.md +75 -0
- package/docs/unifi-firewall-policy.md +109 -0
- package/docs/unifi-traffic-matching-list.md +82 -0
- package/docs/unifi-wifi.md +120 -0
- package/docs/unifi.md +64 -3
- package/package.json +10 -2
- package/src/ceph/auth-entity.ts +74 -0
- package/src/ceph/ceph-argv-config.ts +78 -0
- package/src/ceph/ceph-argv.test.ts +226 -0
- package/src/ceph/ceph-argv.ts +189 -0
- package/src/ceph/ceph-auth-form.test.ts +103 -0
- package/src/ceph/ceph-auth-form.ts +107 -0
- package/src/ceph/ceph-auth-parse.test.ts +155 -0
- package/src/ceph/ceph-auth-parse.ts +121 -0
- package/src/ceph/ceph-auth-reconcile-secrecy.test.ts +82 -0
- package/src/ceph/ceph-auth-reconcile.test.ts +233 -0
- package/src/ceph/ceph-auth-reconcile.ts +119 -0
- package/src/ceph/ceph-config-options.test.ts +44 -0
- package/src/ceph/ceph-config-options.ts +36 -0
- package/src/ceph/ceph-key-leak-assert.ts +35 -0
- package/src/ceph/ceph-no-output-logging.test.ts +52 -0
- package/src/ceph/ceph-transport.test.ts +125 -0
- package/src/ceph/ceph-transport.ts +117 -0
- package/src/ceph/fake-ceph-dial.ts +55 -0
- package/src/ceph/index.ts +12 -0
- package/src/forgejo/team-member.test.ts +14 -0
- package/src/forgejo/team-member.ts +28 -1
- package/src/index.ts +1 -0
- package/src/proxmox/constraints-required.test.ts +1 -0
- package/src/proxmox/generated/constraints/index.ts +3 -1
- package/src/proxmox/generated/constraints/pve-access.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-storage.ts +30 -0
- package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
- package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
- package/src/proxmox/index.test.ts +11 -6
- package/src/proxmox/index.ts +19 -3
- package/src/proxmox/qemu-form.ts +49 -13
- package/src/proxmox/qemu-identity.test.ts +30 -0
- package/src/proxmox/qemu-judge.test.ts +65 -0
- package/src/proxmox/qemu-judge.ts +84 -0
- package/src/proxmox/qemu-lifecycle.test.ts +78 -19
- package/src/proxmox/qemu-lifecycle.ts +131 -32
- package/src/proxmox/qemu-net.test.ts +48 -0
- package/src/proxmox/qemu-net.ts +78 -0
- package/src/proxmox/qemu-ownership.test.ts +44 -0
- package/src/proxmox/qemu-props.test.ts +87 -0
- package/src/proxmox/qemu-props.ts +157 -0
- package/src/proxmox/qemu-volume.test.ts +229 -0
- package/src/proxmox/qemu-volume.ts +178 -0
- package/src/proxmox/qemu.ts +15 -29
- package/src/proxmox/storage-download-errors.ts +7 -0
- package/src/proxmox/storage-download-identity.test.ts +54 -0
- package/src/proxmox/storage-download-identity.ts +50 -0
- package/src/proxmox/storage-download-lifecycle.ts +226 -0
- package/src/proxmox/storage-download-ownership.test.ts +50 -0
- package/src/proxmox/storage-download-props.ts +38 -0
- package/src/proxmox/storage-download-task.ts +72 -0
- package/src/proxmox/storage-download.test.ts +216 -0
- package/src/proxmox/storage-download.ts +58 -0
- package/src/talos/credentials-write.test.ts +81 -0
- package/src/talos/credentials-write.ts +95 -0
- package/src/talos/credentials.test.ts +157 -0
- package/src/talos/credentials.ts +160 -90
- package/src/talos/fake-process.ts +94 -0
- package/src/talos/index.ts +39 -4
- package/src/talos/kubeconfig-attrs.ts +55 -0
- package/src/talos/kubeconfig.test.ts +256 -0
- package/src/talos/kubeconfig.ts +170 -90
- package/src/talos/machine-config-fixtures.ts +86 -0
- package/src/talos/machine-config-poll.test.ts +57 -0
- package/src/talos/machine-config-poll.ts +82 -0
- package/src/talos/machine-config-read.ts +118 -0
- package/src/talos/resource.ts +19 -0
- package/src/talos/secrets-gate.test.ts +63 -0
- package/src/talos/talos-bootstrap-etcd.ts +71 -0
- package/src/talos/talos-bootstrap.test.ts +218 -0
- package/src/talos/talos-bootstrap.ts +151 -45
- package/src/talos/talos-cluster-health.test.ts +143 -0
- package/src/talos/talos-cluster-health.ts +91 -28
- package/src/talos/talos-errors.ts +85 -0
- package/src/talos/talos-machine-config.test.ts +189 -0
- package/src/talos/talos-machine-config.ts +102 -88
- package/src/talos/talosctl.ts +8 -0
- package/src/talos/values.test.ts +34 -6
- package/src/talos/values.ts +41 -7
- package/src/telemetry/fake-collector.ts +59 -0
- package/src/telemetry/http-client-sealing.test.ts +82 -0
- package/src/telemetry/index.ts +10 -0
- package/src/telemetry/layer.test.ts +204 -0
- package/src/telemetry/layer.ts +152 -0
- package/src/telemetry/redact-serialization.ts +178 -0
- package/src/telemetry/redact.test.ts +124 -0
- package/src/telemetry/redact.ts +147 -0
- package/src/unifi/acl-rule-drift.ts +57 -0
- package/src/unifi/acl-rule-form.ts +135 -0
- package/src/unifi/acl-rule-ordering-form.ts +79 -0
- package/src/unifi/acl-rule-ordering.test.ts +141 -0
- package/src/unifi/acl-rule-ordering.ts +70 -0
- package/src/unifi/acl-rule.test.ts +183 -0
- package/src/unifi/acl-rule.ts +61 -0
- package/src/unifi/discriminated-filter-decode.test.ts +134 -0
- package/src/unifi/dns-policy-drift.ts +48 -0
- package/src/unifi/dns-policy-form.ts +142 -0
- package/src/unifi/dns-policy.test.ts +154 -0
- package/src/unifi/dns-policy.ts +67 -0
- package/src/unifi/drift.test.ts +78 -0
- package/src/unifi/drift.ts +56 -0
- package/src/unifi/errors-and-secrets.test.ts +127 -0
- package/src/unifi/fake-unifi.ts +5 -1
- package/src/unifi/firewall-policy-drift.test.ts +151 -0
- package/src/unifi/firewall-policy-drift.ts +55 -0
- package/src/unifi/firewall-policy-filter-roundtrip.test.ts +143 -0
- package/src/unifi/firewall-policy-form.ts +146 -0
- package/src/unifi/firewall-policy-ordering-form.ts +111 -0
- package/src/unifi/firewall-policy-ordering.test.ts +185 -0
- package/src/unifi/firewall-policy-ordering.ts +87 -0
- package/src/unifi/firewall-policy.test.ts +183 -0
- package/src/unifi/firewall-policy.ts +73 -0
- package/src/unifi/firewall-zone-form.ts +31 -2
- package/src/unifi/firewall-zone.test.ts +21 -1
- package/src/unifi/firewall-zone.ts +1 -1
- package/src/unifi/get-only-guard.test.ts +165 -0
- package/src/unifi/index.ts +78 -1
- package/src/unifi/network-drift.test.ts +207 -0
- package/src/unifi/network-drift.ts +80 -0
- package/src/unifi/network-form.ts +11 -39
- package/src/unifi/network.test.ts +7 -82
- package/src/unifi/network.ts +6 -6
- package/src/unifi/paginate.test.ts +252 -0
- package/src/unifi/paginate.ts +141 -0
- package/src/unifi/providers.ts +19 -1
- package/src/unifi/resource.ts +73 -3
- package/src/unifi/scan-source.ts +64 -0
- package/src/unifi/traffic-matching-list-drift.ts +40 -0
- package/src/unifi/traffic-matching-list-form.ts +77 -0
- package/src/unifi/traffic-matching-list.test.ts +202 -0
- package/src/unifi/traffic-matching-list.ts +78 -0
- package/src/unifi/wifi-broadcast-details-call.test.ts +92 -0
- package/src/unifi/wifi-broadcast-drift.ts +69 -0
- package/src/unifi/wifi-broadcast-form.ts +211 -0
- package/src/unifi/wifi-broadcast-secrets.test.ts +145 -0
- package/src/unifi/wifi-broadcast.test.ts +155 -0
- package/src/unifi/wifi-broadcast.ts +90 -0
- 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
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
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":"
|
|
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"}
|
package/dist/unifi/network.d.ts
CHANGED
|
@@ -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,
|
|
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;
|
|
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"}
|
package/dist/unifi/resource.d.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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"}
|