@takodotid/circuit 0.43.1 → 1.0.0-rc.2

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 (256) hide show
  1. package/README.md +115 -37
  2. package/package.json +21 -58
  3. package/src/checks/across.ts +402 -0
  4. package/src/checks/built-in.ts +256 -0
  5. package/src/checks/device.ts +436 -0
  6. package/src/checks/index.ts +53 -0
  7. package/src/cli/advisories.ts +108 -0
  8. package/src/cli/app.ts +71 -0
  9. package/src/cli/editor-types.generated.ts +30 -0
  10. package/src/cli/editor-types.ts +69 -0
  11. package/src/cli/format.ts +124 -0
  12. package/src/cli/git-hooks.ts +79 -0
  13. package/src/cli/index.ts +350 -1170
  14. package/src/cli/migrate.ts +554 -0
  15. package/src/cli/project-commands.ts +656 -0
  16. package/src/cli/releases.ts +374 -0
  17. package/src/cli/remember.ts +339 -0
  18. package/src/cli/rename.ts +27 -33
  19. package/src/cli/secrets-password.ts +60 -0
  20. package/src/cli/secrets.ts +258 -0
  21. package/src/cli/setup.ts +300 -0
  22. package/src/cli/signing.ts +23 -0
  23. package/src/cli/text-editor.ts +268 -0
  24. package/src/cli/ui.ts +298 -0
  25. package/src/cli/version.ts +2 -0
  26. package/src/cli/versions.ts +158 -0
  27. package/src/config/address.ts +102 -0
  28. package/src/config/circuit.d.ts +30 -0
  29. package/src/config/common.ts +65 -0
  30. package/src/config/communities.ts +479 -0
  31. package/src/config/define.ts +684 -0
  32. package/src/config/device.ts +164 -0
  33. package/src/config/firewall.ts +150 -0
  34. package/src/config/index.ts +22 -0
  35. package/src/{schema → config}/interfaces.ts +121 -85
  36. package/src/config/keys.ts +434 -0
  37. package/src/config/management.ts +61 -0
  38. package/src/config/merge.ts +335 -0
  39. package/src/config/models.ts +70 -0
  40. package/src/config/monitoring.ts +64 -0
  41. package/src/config/network.ts +180 -0
  42. package/src/config/presets.ts +149 -0
  43. package/src/config/routing.ts +401 -0
  44. package/src/config/services.ts +51 -0
  45. package/src/config/switching.ts +84 -0
  46. package/src/config/system.ts +103 -0
  47. package/src/{schema → config}/time-zones.ts +1 -1
  48. package/src/core/address.ts +1 -1
  49. package/src/core/cabling.ts +8 -43
  50. package/src/core/graph.ts +40 -0
  51. package/src/{integrations → core}/registries.ts +5 -3
  52. package/src/core/secrets-file.ts +539 -0
  53. package/src/core/secrets.ts +83 -64
  54. package/src/core/topology.ts +103 -146
  55. package/src/core/utils.ts +12 -1
  56. package/src/model.ts +83 -0
  57. package/src/platforms/derive.ts +64 -37
  58. package/src/platforms/finding.ts +9 -0
  59. package/src/platforms/fortios/firewall.ts +76 -64
  60. package/src/platforms/fortios/index.ts +189 -125
  61. package/src/platforms/fortios/names.ts +51 -18
  62. package/src/platforms/fortios/render.ts +69 -62
  63. package/src/platforms/fortios/routing.ts +89 -58
  64. package/src/platforms/fortios/vdoms.ts +47 -16
  65. package/src/platforms/junos/TRAPS.md +2 -2
  66. package/src/platforms/junos/bgp.ts +63 -42
  67. package/src/platforms/junos/index.ts +122 -89
  68. package/src/platforms/junos/render.ts +139 -104
  69. package/src/platforms/platform.ts +10 -8
  70. package/src/platforms/raisecom-ros/TRAPS.md +1 -1
  71. package/src/platforms/raisecom-ros/index.ts +89 -70
  72. package/src/platforms/raisecom-ros/render.ts +49 -45
  73. package/src/platforms/routeros/TRAPS.md +3 -3
  74. package/src/platforms/routeros/index.ts +121 -60
  75. package/src/platforms/routeros/render.ts +214 -195
  76. package/src/platforms/vrp/TRAPS.md +1 -1
  77. package/src/platforms/vrp/index.ts +74 -50
  78. package/src/platforms/vrp/render.ts +67 -56
  79. package/src/project/project.ts +725 -0
  80. package/src/studio/app/env.d.ts +9 -0
  81. package/src/studio/app/index.html +18 -0
  82. package/src/studio/app/src/App.vue +95 -0
  83. package/src/studio/app/src/components/AddressesView.vue +38 -0
  84. package/src/studio/app/src/components/CablesView.vue +29 -0
  85. package/src/studio/app/src/components/CompareView.vue +160 -0
  86. package/src/studio/app/src/components/DataTable.vue +49 -0
  87. package/src/studio/app/src/components/DeviceView.vue +237 -0
  88. package/src/studio/app/src/components/DevicesView.vue +32 -0
  89. package/src/studio/app/src/components/Faceplate.vue +75 -0
  90. package/src/studio/app/src/components/GraphView.vue +282 -0
  91. package/src/studio/app/src/components/LineDiff.vue +24 -0
  92. package/src/studio/app/src/components/ProblemsView.vue +42 -0
  93. package/src/studio/app/src/components/SearchView.vue +72 -0
  94. package/src/studio/app/src/components/SecretsView.vue +112 -0
  95. package/src/studio/app/src/components/SessionsView.vue +35 -0
  96. package/src/studio/app/src/components/Settings.vue +95 -0
  97. package/src/studio/app/src/components/ToolsView.vue +118 -0
  98. package/src/studio/app/src/components/VlansView.vue +50 -0
  99. package/src/studio/app/src/lib/csv.ts +19 -0
  100. package/src/studio/{public/diff.js → app/src/lib/diff.ts} +40 -35
  101. package/src/studio/app/src/lib/format.ts +38 -0
  102. package/src/studio/app/src/lib/net.ts +68 -0
  103. package/src/studio/app/src/lib/secrets-crypto.ts +35 -0
  104. package/src/studio/app/src/lib/store.ts +71 -0
  105. package/src/studio/app/src/lib/tools.ts +217 -0
  106. package/src/studio/app/src/main.ts +9 -0
  107. package/src/studio/{public → app/src}/style.css +14 -4
  108. package/src/studio/app/tsconfig.json +17 -0
  109. package/src/studio/app/vite.config.ts +16 -0
  110. package/src/studio/assets.generated.ts +3 -0
  111. package/src/studio/data.ts +96 -188
  112. package/src/studio/git.ts +27 -43
  113. package/src/studio/server.ts +196 -107
  114. package/src/studio/types.ts +141 -0
  115. package/src/transport/console.ts +3 -3
  116. package/src/transport/ssh.ts +1 -1
  117. package/dist/chunks/index-3b343xva.js +0 -177
  118. package/dist/chunks/index-6wb41q67.js +0 -62
  119. package/dist/chunks/index-n7w3tg5y.js +0 -149
  120. package/dist/chunks/index-yzw86rc8.js +0 -921
  121. package/dist/chunks/new-w3zys5y4.js +0 -172
  122. package/dist/chunks/server-cxr9ynxc.js +0 -259
  123. package/dist/cli/index.js +0 -12922
  124. package/dist/helpers/index.js +0 -881
  125. package/dist/index.js +0 -28
  126. package/dist/types/core/address-space.d.ts +0 -62
  127. package/dist/types/core/address.d.ts +0 -44
  128. package/dist/types/core/cabling.d.ts +0 -41
  129. package/dist/types/core/cross-checks.d.ts +0 -28
  130. package/dist/types/core/define.d.ts +0 -79
  131. package/dist/types/core/project-files.d.ts +0 -12
  132. package/dist/types/core/schema-docs.d.ts +0 -25
  133. package/dist/types/core/secrets.d.ts +0 -62
  134. package/dist/types/core/topology.d.ts +0 -96
  135. package/dist/types/core/utils.d.ts +0 -10
  136. package/dist/types/core/validator.d.ts +0 -23
  137. package/dist/types/helpers/bgp.d.ts +0 -195
  138. package/dist/types/helpers/cables.d.ts +0 -69
  139. package/dist/types/helpers/checks.d.ts +0 -36
  140. package/dist/types/helpers/exchange.d.ts +0 -55
  141. package/dist/types/helpers/filters.d.ts +0 -51
  142. package/dist/types/helpers/index.d.ts +0 -14
  143. package/dist/types/helpers/route-server.d.ts +0 -52
  144. package/dist/types/helpers/upstreams.d.ts +0 -192
  145. package/dist/types/index.d.ts +0 -10
  146. package/dist/types/integrations/librenms.d.ts +0 -60
  147. package/dist/types/integrations/netbox.d.ts +0 -89
  148. package/dist/types/integrations/peeringdb.d.ts +0 -24
  149. package/dist/types/integrations/prometheus.d.ts +0 -24
  150. package/dist/types/integrations/registries.d.ts +0 -8
  151. package/dist/types/platforms/bgp-wait.d.ts +0 -24
  152. package/dist/types/platforms/catalog.d.ts +0 -109
  153. package/dist/types/platforms/derive.d.ts +0 -17
  154. package/dist/types/platforms/fortios/firewall.d.ts +0 -47
  155. package/dist/types/platforms/fortios/index.d.ts +0 -140
  156. package/dist/types/platforms/fortios/models.d.ts +0 -14
  157. package/dist/types/platforms/fortios/names.d.ts +0 -52
  158. package/dist/types/platforms/fortios/plan.d.ts +0 -114
  159. package/dist/types/platforms/fortios/render.d.ts +0 -77
  160. package/dist/types/platforms/fortios/routing.d.ts +0 -56
  161. package/dist/types/platforms/fortios/tree.d.ts +0 -37
  162. package/dist/types/platforms/fortios/vdoms.d.ts +0 -50
  163. package/dist/types/platforms/index.d.ts +0 -13
  164. package/dist/types/platforms/junos/bgp.d.ts +0 -44
  165. package/dist/types/platforms/junos/index.d.ts +0 -114
  166. package/dist/types/platforms/junos/models.d.ts +0 -14
  167. package/dist/types/platforms/junos/render.d.ts +0 -154
  168. package/dist/types/platforms/line-diff.d.ts +0 -67
  169. package/dist/types/platforms/platform.d.ts +0 -135
  170. package/dist/types/platforms/raisecom-ros/index.d.ts +0 -71
  171. package/dist/types/platforms/raisecom-ros/models.d.ts +0 -14
  172. package/dist/types/platforms/raisecom-ros/render.d.ts +0 -41
  173. package/dist/types/platforms/routeros/export.d.ts +0 -59
  174. package/dist/types/platforms/routeros/index.d.ts +0 -116
  175. package/dist/types/platforms/routeros/models.d.ts +0 -18
  176. package/dist/types/platforms/routeros/plan.d.ts +0 -58
  177. package/dist/types/platforms/routeros/render.d.ts +0 -250
  178. package/dist/types/platforms/vrp/index.d.ts +0 -83
  179. package/dist/types/platforms/vrp/models.d.ts +0 -12
  180. package/dist/types/platforms/vrp/render.d.ts +0 -96
  181. package/dist/types/schema/common.d.ts +0 -30
  182. package/dist/types/schema/device.d.ts +0 -126
  183. package/dist/types/schema/firewall.d.ts +0 -131
  184. package/dist/types/schema/index.d.ts +0 -8
  185. package/dist/types/schema/interfaces.d.ts +0 -205
  186. package/dist/types/schema/policy.d.ts +0 -107
  187. package/dist/types/schema/routing.d.ts +0 -161
  188. package/dist/types/schema/system.d.ts +0 -198
  189. package/dist/types/schema/time-zones.d.ts +0 -2
  190. package/dist/types/transport/console.d.ts +0 -115
  191. package/dist/types/transport/path-check.d.ts +0 -32
  192. package/dist/types/transport/ssh.d.ts +0 -27
  193. package/src/cli/graph-format.ts +0 -91
  194. package/src/cli/new.ts +0 -234
  195. package/src/core/address-space.ts +0 -320
  196. package/src/core/cross-checks.ts +0 -369
  197. package/src/core/define.ts +0 -124
  198. package/src/core/project-files.ts +0 -35
  199. package/src/core/schema-docs.ts +0 -174
  200. package/src/core/validator.ts +0 -508
  201. package/src/helpers/bgp.ts +0 -473
  202. package/src/helpers/cables.ts +0 -74
  203. package/src/helpers/checks.ts +0 -201
  204. package/src/helpers/exchange.ts +0 -123
  205. package/src/helpers/filters.ts +0 -107
  206. package/src/helpers/index.ts +0 -25
  207. package/src/helpers/route-server.ts +0 -212
  208. package/src/helpers/upstreams.ts +0 -369
  209. package/src/index.ts +0 -13
  210. package/src/integrations/librenms.ts +0 -291
  211. package/src/integrations/netbox.ts +0 -620
  212. package/src/integrations/peeringdb.ts +0 -173
  213. package/src/integrations/prometheus.ts +0 -90
  214. package/src/schema/common.ts +0 -41
  215. package/src/schema/device.ts +0 -145
  216. package/src/schema/firewall.ts +0 -140
  217. package/src/schema/index.ts +0 -8
  218. package/src/schema/policy.ts +0 -115
  219. package/src/schema/routing.ts +0 -173
  220. package/src/schema/system.ts +0 -203
  221. package/src/studio/public/app.js +0 -186
  222. package/src/studio/public/compare.js +0 -250
  223. package/src/studio/public/dom.js +0 -138
  224. package/src/studio/public/evaluate.js +0 -687
  225. package/src/studio/public/export.js +0 -130
  226. package/src/studio/public/graph.js +0 -1541
  227. package/src/studio/public/index.html +0 -83
  228. package/src/studio/public/net.js +0 -134
  229. package/src/studio/public/tables.js +0 -1289
  230. package/src/studio/public/tools.js +0 -610
  231. package/templates/colocation/checks.ts +0 -53
  232. package/templates/colocation/circuit.config.ts +0 -9
  233. package/templates/colocation/edge-01.ts +0 -133
  234. package/templates/colocation/routing.ts +0 -13
  235. package/templates/colocation/tenancy.ts +0 -76
  236. package/templates/colocation/tenants/acme.ts +0 -19
  237. package/templates/colocation/tenants/index.ts +0 -6
  238. package/templates/colocation/tor-01.ts +0 -33
  239. package/templates/edge-router/checks.ts +0 -20
  240. package/templates/edge-router/circuit.config.ts +0 -8
  241. package/templates/edge-router/edge-01.ts +0 -110
  242. package/templates/edge-router/routing.ts +0 -13
  243. package/templates/project/AGENTS.md +0 -51
  244. package/templates/project/CLAUDE.md +0 -1
  245. package/templates/project/README.md +0 -16
  246. package/templates/project/gitignore +0 -5
  247. package/templates/project/tsconfig.json +0 -13
  248. package/templates/single-site/checks.ts +0 -26
  249. package/templates/single-site/circuit.config.ts +0 -8
  250. package/templates/single-site/router.ts +0 -86
  251. package/templates/single-site/site.ts +0 -18
  252. package/templates/single-site/switch.ts +0 -34
  253. /package/src/studio/{public → app/public}/favicon.svg +0 -0
  254. /package/src/studio/{public → app/public}/special-gothic-latin-ext.woff2 +0 -0
  255. /package/src/studio/{public → app/public}/special-gothic-latin.woff2 +0 -0
  256. /package/src/studio/{public → app/public}/special-gothic-license.txt +0 -0
@@ -0,0 +1,164 @@
1
+ // One device: its name, where it is, what it is, how Circuit logs in, and its groups. A part of a device, written in another file and given to it by a source.
2
+
3
+ import type { IP, Secret } from "./common";
4
+ import type { Firewall } from "./firewall";
5
+ import type { Interfaces, Port } from "./interfaces";
6
+ import type { Management } from "./management";
7
+ import type { Monitoring } from "./monitoring";
8
+ import type { AnyFacts, NetworkFacts } from "./network";
9
+ import type { Routing } from "./routing";
10
+ import type { Services } from "./services";
11
+ import type { Switching } from "./switching";
12
+ import type { System } from "./system";
13
+
14
+ /** A computer with SSH that holds the serial consoles of devices, such as a laptop beside the rack. It runs Python 3. */
15
+ export type Jump = {
16
+ /** Its address or name. */
17
+ host: string;
18
+ /** The user Circuit logs in as. It must be allowed to open the serial ports. */
19
+ user: string;
20
+ /** The user's password. */
21
+ password: Secret;
22
+ /** SSH port. 22 when absent. */
23
+ port?: number;
24
+ /** The jump host is reached through a Cloudflare Tunnel, so Circuit connects with `cloudflared access ssh`, which must be installed. */
25
+ cloudflared?: true;
26
+ };
27
+
28
+ /** A serial console, on a jump host or on the computer Circuit runs on. */
29
+ export type Console = {
30
+ /** The jump host the console cable is plugged into. When absent, the cable is plugged into the computer Circuit runs on. */
31
+ jump?: Jump;
32
+ /** The serial port: on Linux or macOS a path under `/dev`, where a path under `/dev/serial/by-path/` stays the same when two adapters swap names; on Windows a COM port, such as `COM3`. */
33
+ port: string;
34
+ /** Line speed in bits per second, such as 9600 or 115200. */
35
+ baud: number;
36
+ /** The console asks only for a password, with no name first. Circuit then types no name; `connection.user` still picks the password. */
37
+ password_only?: true;
38
+ };
39
+
40
+ /** How Circuit itself logs in. `U` is the device's user names. */
41
+ export type Connection<U extends string> = {
42
+ /** Management address. Absent for a device reached only through its console. Its own value, apart from any interface's address. */
43
+ host?: IP;
44
+ /** One of `system.users`. Its password is the login. */
45
+ user: U;
46
+ /** SSH port. 22 when absent. */
47
+ port?: number;
48
+ /** The device's serial console, for `--console`: the way in before the device has a management address, or when its management network is down. */
49
+ console?: Console;
50
+ };
51
+
52
+ /** The names a device declares, by kind. A field that refers to a name takes only one of these. */
53
+ export type Names = {
54
+ /** Keys of `interfaces.ethernet`. */
55
+ port: string;
56
+ /** Keys of `interfaces.lag`. */
57
+ lag: string;
58
+ /** Keys of `interfaces.vlan_interface`. */
59
+ vlanInterface: string;
60
+ /** Keys of `interfaces.bridge`, `.loopback`, `.gre`, `.vxlan` and `.wireguard`. */
61
+ interface: string;
62
+ /** Keys of `switching.vlans`. */
63
+ vlan: string;
64
+ /** Keys of `switching.acls`. */
65
+ acl: string;
66
+ /** Keys of `routing.policies`. */
67
+ policy: string;
68
+ /** Keys of `routing.prefix_sets`. */
69
+ prefixSet: string;
70
+ /** Keys of `routing.bgp.neighbor_groups`. */
71
+ neighborGroup: string;
72
+ /** Keys of `routing.tables`. */
73
+ table: string;
74
+ /** Keys of `routing.vrfs`. */
75
+ vrf: string;
76
+ /** Keys of `firewall.address_sets`. */
77
+ addressSet: string;
78
+ /** Keys of `firewall.interface_sets`. */
79
+ interfaceSet: string;
80
+ /** Keys of `system.users`. */
81
+ user: string;
82
+ /** Keys of `system.certificates`. */
83
+ certificate: string;
84
+ /** Every port and interface: `port`, `lag`, `vlanInterface` and `interface` together. */
85
+ anyInterface: string;
86
+ };
87
+
88
+ /**
89
+ * The groups of a device, what a part may add to as well. `N` holds the names the device declares, `Ethernet` its ports. `Part` is true in a part, where BGP holds only what the part adds.
90
+ * `Net` is what the network writes: whether it turns on the check `untrusted_vlans`, and its `communities`.
91
+ */
92
+ export type Groups<N extends Names, Ethernet, Part extends boolean = false, Net extends NetworkFacts = AnyFacts> = {
93
+ /** The box itself: banner, time, DNS it uses, users, certificates, logs kept on it, software, hardware. */
94
+ system?: System<N["user"], N["certificate"], NoInfer<N["anyInterface"]>>;
95
+ /** How people and tools log in: ssh, https, api, native protocol, console. */
96
+ management?: Management<NoInfer<N["anyInterface"]>, NoInfer<N["certificate"]>, NoInfer<N["addressSet"]>>;
97
+ /** What the box reports to collectors: snmp, syslog, flow export, optics. */
98
+ monitoring?: Monitoring<NoInfer<N["anyInterface"]>>;
99
+ /** Every port and interface, by kind: ethernet, lag, vlan_interface, bridge, loopback, gre, vxlan, wireguard. */
100
+ interfaces?: Interfaces<Ethernet, N["lag"], N["vlanInterface"], N["interface"], NoInfer<N["vlan"]>, NoInfer<N["vrf"]>>;
101
+ /** Layer 2 shared by ports: vlans, stp, lldp, acls. */
102
+ switching?: Switching<N["vlan"], N["acl"], NoInfer<N["anyInterface"]>, Net["untrusted"]>;
103
+ /** What the box serves to hosts: dhcp server, dhcp relay, dns server, ntp server. */
104
+ services?: Services<NoInfer<N["anyInterface"]>>;
105
+ /** Where packets go: tables, vrfs, policy routing, static routes, bgp, ospf, bfd, rpki, policies, prefix sets. */
106
+ routing?: Routing<N["policy"], N["prefixSet"], N["neighborGroup"], N["table"], N["vrf"], NoInfer<N["anyInterface"]>, Part, Net>;
107
+ /** Which packets pass and how they are rewritten: address sets, interface sets, filter, nat, untracked, conntrack helpers. */
108
+ firewall?: Firewall<N["addressSet"], NoInfer<N["anyInterface"]>, N["interfaceSet"]>;
109
+ };
110
+
111
+ /**
112
+ * Everything one device runs. What is not written here is removed from the device or returned to its default.
113
+ *
114
+ * `N` holds the names it declares, so a reference to a name it does not declare is an error. `Ethernet` is its ports, checked against the model.
115
+ * `Site` is the network's sites. `Net` is what the network writes: whether it turns on the check `untrusted_vlans`, and its `communities`.
116
+ */
117
+ export type Device<
118
+ Platform extends string,
119
+ Model extends string,
120
+ Site extends string,
121
+ N extends Names,
122
+ Ethernet,
123
+ Name extends string = string,
124
+ Net extends NetworkFacts = AnyFacts,
125
+ > = {
126
+ /** Its hostname: its name in the network, and the key under which each source gives it a part. */
127
+ name: Name;
128
+ /** The site it is at, one of the network's `sites`. The NetBox site and LibreNMS group of that name. */
129
+ site: Site;
130
+ /** Its role in NetBox, such as `Core switch`. Circuit makes the role when NetBox has none of that name. */
131
+ role?: string;
132
+ /** Operating system. It decides which adapter renders and applies the device. */
133
+ platform: Platform;
134
+ /** Hardware model, one of the platform's. It decides which port names exist. */
135
+ model: Model;
136
+ /** How Circuit itself logs in. */
137
+ connection: Connection<NoInfer<N["user"]>>;
138
+ } & Groups<N, Ethernet, false, Net>;
139
+
140
+ /**
141
+ * A part of a device, which a source gives it under its hostname: what an upstream, a tenant or a monitoring host adds to it. The names it refers to must be declared by the device or by one of its parts.
142
+ */
143
+ export type Part<N extends Names, Ethernet, Net extends NetworkFacts = AnyFacts> = {
144
+ /** How Circuit itself logs in. In a part, only what the part adds, such as the console. */
145
+ connection?: Partial<Connection<NoInfer<N["user"]>>>;
146
+ } & Groups<N, Ethernet, true, Net>;
147
+
148
+ /** Any name: what a part, or a device seen from the network, holds. */
149
+ type AnyNames = { [K in keyof Names]: string };
150
+
151
+ /** A port as a part writes it, before the device it goes to checks its names. */
152
+ export type AnyPort = Port<string, string, string, string>;
153
+
154
+ /** Any device, as the network holds it. */
155
+ export type AnyDevice = Device<string, string, string, AnyNames, Record<string, AnyPort>>;
156
+
157
+ /**
158
+ * A part of one or more devices, written apart from them and given to each device that carries it, under its hostname in a source: an upstream's VLAN, sessions and policies on the router, a tenant's ports on a switch, what every device sends to the monitoring hosts.
159
+ *
160
+ * It has a device's shape and docs. What only a whole device has (its site, platform, model) is not here, and what a part writes alone stays optional: a part can add BGP neighbors without the AS, or a console without the user.
161
+ *
162
+ * Names a part refers to (a VLAN, an interface, a policy) are checked once the part reaches a device: there they must be declared.
163
+ */
164
+ export type DevicePart = Part<AnyNames, Record<string, AnyPort>>;
@@ -0,0 +1,150 @@
1
+ // Which packets pass and how they are rewritten: `firewall.address_sets`, `.interface_sets`, `.filter`, `.nat`, `.untracked`, `.conntrack_helpers`.
2
+
3
+ import type { Family, HostAddress, IP, Named, OneOrMore, Ordered, Prefix } from "./common";
4
+
5
+ /** An IP protocol. `icmp` means ICMPv6 in an IPv6 rule. */
6
+ export type Protocol = "tcp" | "udp" | "icmp" | "gre" | "esp" | "ah" | "ospf" | "vrrp";
7
+
8
+ /** The state connection tracking gives a packet. */
9
+ export type ConnectionState = "new" | "established" | "related" | "untracked" | "invalid";
10
+
11
+ /** Ports from `min` to `max`, both included. */
12
+ export type PortRange = {
13
+ /** The first port, 0 to 65535. */
14
+ min: number;
15
+ /** The last port, 0 to 65535, not below `min`. */
16
+ max: number;
17
+ };
18
+
19
+ /** A port, a range of ports, or any of several. */
20
+ export type Ports = number | PortRange | readonly (number | PortRange)[];
21
+
22
+ /** A TCP header flag. */
23
+ export type TcpFlag = "fin" | "syn" | "rst" | "psh" | "ack" | "urg";
24
+
25
+ /**
26
+ * Conditions on a packet. All must be true. A rule with addresses of one family applies to that family only. `I` is the device's
27
+ * ports and interfaces, `AS` its address sets, `IS` its interface sets.
28
+ *
29
+ * `src`, `dst`, `in_interface` and `out_interface` each take a list, and an interface set stands for its interfaces. Where the
30
+ * platform has no list, Circuit writes one rule per combination: the interface outermost (`in` before `out`), then `src`, then `dst`.
31
+ */
32
+ export type FilterMatch<I extends string, AS extends string, IS extends string> = {
33
+ /** Only packets of this family. */
34
+ family?: Family;
35
+ /** IP protocol. */
36
+ protocol?: Protocol;
37
+ /** Source address or prefix, or any of several. */
38
+ src?: OneOrMore<Prefix>;
39
+ /** Destination address or prefix, or any of several. */
40
+ dst?: OneOrMore<Prefix>;
41
+ /** One of `firewall.address_sets`: the source is in it. */
42
+ src_address_set?: AS;
43
+ /** One of `firewall.address_sets`: the destination is in it. */
44
+ dst_address_set?: AS;
45
+ /** Source port, or any of several. TCP and UDP only. */
46
+ src_port?: Ports;
47
+ /** Destination port, or any of several. TCP and UDP only. */
48
+ dst_port?: Ports;
49
+ /** One of the device's ports or interfaces, or any of several: the packet arrived on it. */
50
+ in_interface?: OneOrMore<I>;
51
+ /** One of the device's ports or interfaces, or any of several: the packet leaves through it. */
52
+ out_interface?: OneOrMore<I>;
53
+ /** One of `firewall.interface_sets`: the packet arrived on one of its interfaces. Not with `in_interface`. */
54
+ in_interface_set?: IS;
55
+ /** One of `firewall.interface_sets`: the packet leaves through one of its interfaces. Not with `out_interface`. */
56
+ out_interface_set?: IS;
57
+ /** Connection tracking state, any of these. */
58
+ connection_state?: readonly ConnectionState[];
59
+ /** TCP flags that must be set, and flags that must not be. */
60
+ tcp_flags?: {
61
+ /** Flags that must be set. */
62
+ set?: readonly TcpFlag[];
63
+ /** Flags that must not be set. */
64
+ unset?: readonly TcpFlag[];
65
+ };
66
+ };
67
+
68
+ /**
69
+ * One firewall rule, the condition first: `{ if: { protocol: "icmp" }, then: "accept" }`. No `if`: every packet.
70
+ */
71
+ export type FilterRule<I extends string, AS extends string, IS extends string> = {
72
+ /** Shown beside the rule on the device. */
73
+ description?: string;
74
+ /** Which packets the rule applies to. Every packet when absent. */
75
+ if?: FilterMatch<I, AS, IS>;
76
+ /** What happens to a matching packet. `reject` answers the sender, `drop` does not. */
77
+ then: "accept" | "drop" | "reject";
78
+ /** Send the rest of an accepted flow through the fast path, skipping the remaining rules. */
79
+ fast_path?: true;
80
+ };
81
+
82
+ /** Rules in order, the first match wins, then `default_action`. */
83
+ export type Chain<I extends string, AS extends string, IS extends string> = {
84
+ /** What happens to a packet no rule matched. Accept when absent. */
85
+ default_action?: "accept" | "drop";
86
+ /** Rules in order: the first runs first. Written whole in one place; `merge` places rules from other files in it. */
87
+ rules?: Ordered<FilterRule<I, AS, IS>>;
88
+ };
89
+
90
+ /**
91
+ * One address translation, the condition first: `{ if: { src: "10.0.0.0/24", out_interface_set: "uplinks" }, then: "snat", to_address: "192.0.2.1" }`.
92
+ * No `if`: every packet.
93
+ */
94
+ export type NatRule<I extends string, AS extends string, IS extends string> = {
95
+ /** Shown beside the rule on the device. */
96
+ description?: string;
97
+ /** Which packets are translated. Every packet when absent. */
98
+ if?: FilterMatch<I, AS, IS>;
99
+ } & (
100
+ | {
101
+ /** `masquerade` uses the address of the outgoing interface. */
102
+ then: "masquerade";
103
+ }
104
+ | {
105
+ /** `snat` rewrites the source, `dnat` the destination. */
106
+ then: "snat" | "dnat";
107
+ /** The address to rewrite to, alone or with its length. */
108
+ to_address: HostAddress;
109
+ /** The port to rewrite to. Unchanged when absent. */
110
+ to_port?: number;
111
+ }
112
+ );
113
+
114
+ /** Connection-tracking helpers that rewrite application payloads. None run unless listed. */
115
+ export type Helper = "ftp" | "tftp" | "sip" | "h323" | "pptp" | "rtsp" | "irc";
116
+
117
+ /** What the device filters and translates. `AS` is the device's address set names, `I` its ports and interfaces, `IS` its interface set names. */
118
+ export type Firewall<AS extends string, I extends string, IS extends string> = {
119
+ /** Named groups of addresses and prefixes, of either family, that rules match on with `src_address_set` and `dst_address_set`. */
120
+ address_sets?: Named<AS, readonly (IP | Prefix)[]>;
121
+ /**
122
+ * Named groups of the device's ports and interfaces, that rules match on with `in_interface_set` and `out_interface_set`, like a
123
+ * RouterOS interface list or a FortiOS zone. A list: each part adds its own, such as each upstream its interface to `uplinks`.
124
+ */
125
+ interface_sets?: Named<IS, readonly I[]>;
126
+ /** Traffic to the device (`input`), through it (`forward`), and from it (`output`). */
127
+ filter?: {
128
+ /** Traffic to the device itself. */
129
+ input?: Chain<I, NoInfer<AS>, NoInfer<IS>>;
130
+ /** Traffic the device routes. */
131
+ forward?: Chain<I, NoInfer<AS>, NoInfer<IS>>;
132
+ /** Traffic the device itself sends. */
133
+ output?: Chain<I, NoInfer<AS>, NoInfer<IS>>;
134
+ };
135
+ /** Source translation on the way out, destination translation on the way in. Each is rules in order: the first runs first. */
136
+ nat?: {
137
+ /** Rewrites the source of traffic on the way out. */
138
+ source?: Ordered<NatRule<I, NoInfer<AS>, NoInfer<IS>>>;
139
+ /** Rewrites the destination of traffic on the way in. */
140
+ destination?: Ordered<NatRule<I, NoInfer<AS>, NoInfer<IS>>>;
141
+ };
142
+ /** Connection-tracking helpers that run. None when absent. */
143
+ conntrack_helpers?: readonly Helper[];
144
+ /**
145
+ * Traffic to and from these prefixes passes without connection tracking. A flood toward them cannot fill the connection table, and rules see its packets in the state `untracked`. Everything is tracked when absent.
146
+ *
147
+ * Each address NAT uses inside one of these prefixes (a source translation's `to_address`, a destination translation's `to_address` or matched `dst`) stays tracked: Circuit writes two accept rules for it, one for traffic to it and one for traffic from it, before the untracked rules. Without them, a reply to that address would skip tracking and never be translated back.
148
+ */
149
+ untracked?: readonly Prefix[];
150
+ };
@@ -0,0 +1,22 @@
1
+ // Circuit v1 for a TypeScript project. Its values (functions, `presets` and `address`) are globals: circuit.d.ts declares them for the editor, and
2
+ // Circuit puts them on `globalThis` before it reads the project. A project never imports them. `lib/` may import the types:
3
+ // `import type { Prefix } from "circuit"`.
4
+
5
+ export { bgpNeighbors, circuit, literal, merge, part, secret, secretFile } from "./define";
6
+ export { presets } from "./presets";
7
+ export { address } from "./address";
8
+ export type * from "./address";
9
+ export type * from "./common";
10
+ export type * from "./communities";
11
+ export type * from "./device";
12
+ export type * from "./firewall";
13
+ export type * from "./interfaces";
14
+ export type * from "./management";
15
+ export type * from "./models";
16
+ export type * from "./monitoring";
17
+ export type * from "./network";
18
+ export type * from "./routing";
19
+ export type * from "./services";
20
+ export type * from "./switching";
21
+ export type * from "./system";
22
+ export type * from "./time-zones";
@@ -1,20 +1,22 @@
1
- import type { InterfaceAddress, IP, MacAddress, Prefix, Secret } from "./common";
1
+ // Every port and interface, by kind: `interfaces.ethernet`, `.lag`, `.vlan_interface`, `.bridge`, `.loopback`, `.gre`, `.vxlan`, `.wireguard`.
2
2
 
3
- /** A VLAN. Its key in `vlans` is its name. */
4
- export type Vlan = {
5
- /** The VLAN's number on the wire, 1 to 4094. */
6
- id: number;
7
- /** What the VLAN is for. */
8
- description?: string;
9
- };
3
+ import type { HostAddress, IP, InterfaceAddress, MacAddress, Named, Prefix, Secret } from "./common";
10
4
 
11
5
  /** A storm-control threshold: packets per second, or percent of the link's speed. */
12
- export type Threshold = { pps: number } | { percent: number };
6
+ export type Threshold =
7
+ | {
8
+ /** Packets per second. */
9
+ pps: number;
10
+ }
11
+ | {
12
+ /** Percent of the link's speed, above 0 and up to 100. */
13
+ percent: number;
14
+ };
13
15
 
14
16
  /** A kind of frame, by the ethertype in its header: `ipv4` is 0x0800, `ipv6` 0x86DD, `arp` 0x0806. */
15
17
  export type Ethertype = "ipv4" | "ipv6" | "arp";
16
18
 
17
- /** A virtual router address shared with other devices on the same segment, RFC 5798. */
19
+ /** A virtual router address shared with other devices on the same segment, RFC 9568 (VRRPv3). */
18
20
  export type Vrrp = {
19
21
  /** Virtual router number, 1 to 255. The same on every device sharing the address. */
20
22
  id: number;
@@ -28,22 +30,6 @@ export type Vrrp = {
28
30
  interval?: number;
29
31
  };
30
32
 
31
- /** Layer 3 settings shared by every interface that can have an address. */
32
- export type Routed<F extends string> = {
33
- /** Addresses with their length. Use `{ address, peer }` for a point-to-point address whose far end is outside its own prefix. */
34
- addresses?: readonly (InterfaceAddress | { address: InterfaceAddress; peer: IP })[];
35
- /** Send IPv6 router advertisements on this interface. Off when absent. */
36
- ipv6_ra?: boolean;
37
- /** Overrides the device's `hardware_offload` for traffic routed through this interface. Software forwarding is what makes the firewall apply. */
38
- hardware_offload?: boolean;
39
- /** Virtual router addresses on this interface. */
40
- vrrp?: readonly Vrrp[];
41
- /** The VRF this interface routes in. The default table when absent. */
42
- vrf?: F;
43
- /** This interface is the network's presence at an internet exchange. Devices ignore it; `circuit peeringdb` publishes it. */
44
- exchange?: Exchange;
45
- };
46
-
47
33
  /** Presence at an internet exchange, as a registry lists it. The addresses are the interface's own. */
48
34
  export type Exchange = {
49
35
  /** The exchange's name, for output. */
@@ -54,6 +40,32 @@ export type Exchange = {
54
40
  peeringdb_ixlan?: number;
55
41
  };
56
42
 
43
+ /** An address with its length, or `{ address, peer_address }` for a point-to-point address whose far end is outside its own prefix. */
44
+ export type Address =
45
+ | InterfaceAddress
46
+ | {
47
+ /** Our address, with its length. */
48
+ address: InterfaceAddress;
49
+ /** The far end's address. */
50
+ peer_address: IP;
51
+ };
52
+
53
+ /** Layer 3 settings shared by every interface that can have an address. `Vrf` is the device's VRF names. */
54
+ export type Routed<Vrf extends string> = {
55
+ /** Addresses with their length. Use `{ address, peer_address }` for a point-to-point address whose far end is outside its own prefix. */
56
+ addresses?: readonly Address[];
57
+ /** Send IPv6 router advertisements on this interface. Off when absent. */
58
+ ipv6_ra?: boolean;
59
+ /** Overrides `system.hardware_offload` for traffic routed through this interface. Software forwarding is what makes the firewall apply. */
60
+ hardware_offload?: boolean;
61
+ /** Virtual router addresses on this interface. */
62
+ vrrp?: readonly Vrrp[];
63
+ /** One of `routing.vrfs`: the VRF this interface routes in. The main table when absent. */
64
+ vrf?: Vrf;
65
+ /** This interface is the network's presence at an internet exchange. Devices ignore it; `circuit peeringdb` publishes it. */
66
+ exchange?: Exchange;
67
+ };
68
+
57
69
  /** Spanning tree settings for one port. */
58
70
  export type PortStp = {
59
71
  /** The port faces a host, never a switch, so it forwards at once. */
@@ -64,33 +76,43 @@ export type PortStp = {
64
76
  priority?: number;
65
77
  };
66
78
 
67
- /** Layer 2 membership. A port or LAG with none of these is routed. */
68
- export type Switched<V extends string> = {
69
- /** The one VLAN this port or LAG is in, untagged. */
70
- access_vlan?: V;
71
- /** The VLANs this port or LAG carries, tagged. */
72
- trunk_vlans?: readonly V[];
73
- /** Untagged frames on a trunk are in this VLAN. Only with `trunk_vlans`. */
74
- native_vlan?: V;
75
- /** Overrides the device's `stp` for this port. `false` stops it sending or acting on BPDUs. */
79
+ /** Drop flooded traffic above these thresholds. */
80
+ export type StormControl = {
81
+ /** Frames to every host. */
82
+ broadcast?: Threshold;
83
+ /** Frames to a group. */
84
+ multicast?: Threshold;
85
+ /** Frames to a MAC address the switch has not learned. */
86
+ unknown_unicast?: Threshold;
87
+ };
88
+
89
+ /** Layer 2 membership. A port or LAG with none of these is routed. `Vlan` is the device's VLAN names. */
90
+ export type Switched<Vlan extends string> = {
91
+ /** One of `switching.vlans`: the one VLAN this port or LAG is in, untagged. */
92
+ access_vlan?: Vlan;
93
+ /** Some of `switching.vlans`: the VLANs this port or LAG carries, tagged. */
94
+ trunk_vlans?: readonly Vlan[];
95
+ /** One of `switching.vlans`: untagged frames on a trunk are in this VLAN. Only with `trunk_vlans`. */
96
+ native_vlan?: Vlan;
97
+ /** Overrides `switching.stp` for this port. `false` stops it sending or acting on BPDUs. */
76
98
  stp?: boolean | PortStp;
77
99
  /** Drop flooded traffic above these thresholds. */
78
- storm_control?: {
79
- broadcast?: Threshold;
80
- multicast?: Threshold;
81
- unknown_unicast?: Threshold;
82
- };
100
+ storm_control?: StormControl;
83
101
  /** The most MAC addresses this port or LAG learns, 1 or more. Frames from any other source address are dropped. An exchange sets 1 on a member port, so each member sends from one router only. No limit when absent. */
84
102
  mac_limit?: number;
85
103
  /** The only kinds of frame this port or LAG takes in; any other kind is dropped. An exchange takes `ipv4`, `ipv6` and `arp` on a member port. Every kind when absent. */
86
104
  ethertypes?: readonly Ethertype[];
87
105
  };
88
106
 
89
- /** The other end of a cable: another device and its port. Both ends must agree on how they are switched. */
107
+ /**
108
+ * The other end of a cable: another of our devices and its port. Both ends must agree on how they are switched, and the far end must
109
+ * link back. The port's own `description` names that end, `<far device> <far port as printed there>`, such as `fw-01 port6`:
110
+ * Circuit warns when it doesn't, and never writes it.
111
+ */
90
112
  export type Link = {
91
- /** Name of the device at the other end. */
113
+ /** The device at the other end, by its key in `devices`. */
92
114
  device: string;
93
- /** The port on that device. */
115
+ /** The port on that device, such as `10g-2`. */
94
116
  port: string;
95
117
  /**
96
118
  * What is between the two ends when the cable is not direct, such as a carrier's local loop or L2 transport: `"Carrier A local loop"`. LLDP then sees the carrier's switches, not the far end, so `validate` does not compare LLDP on this port. Both ends name the same carrier.
@@ -98,27 +120,27 @@ export type Link = {
98
120
  through?: string;
99
121
  };
100
122
 
101
- /** A physical port. Ports a device does not declare are shut down. */
102
- export type Port<V extends string, A extends string, L extends string, F extends string> = Routed<F> &
103
- Switched<V> & {
104
- /** What is plugged in. */
123
+ /** A physical port, by its key `<speed>-<position>`, such as `10g-4`. Ports a device does not declare are shut down. */
124
+ export type Port<Vlan extends string, Acl extends string, Lag extends string, Vrf extends string> = Routed<Vrf> &
125
+ Switched<Vlan> & {
126
+ /** What is plugged in. On a port with a `link`, the far end: `<far device> <far port as printed there>`. */
105
127
  description?: string;
106
128
  /** Largest IP packet, in bytes. 1500 when absent. */
107
129
  mtu?: number;
108
130
  /** Fixed speed, for an optic slower than the cage. Negotiated when absent. */
109
131
  speed?: "100m" | "1g" | "10g" | "25g" | "40g" | "50g" | "100g";
110
- /** Overrides the device's `lldp` for this port. */
132
+ /** Overrides `switching.lldp` for this port. */
111
133
  lldp?: boolean;
112
- /** Hardware ACL applied to traffic arriving on this port. */
113
- acl?: A;
114
- /** The LAG this port is in. Every other setting goes on the LAG. */
115
- lag?: L;
116
- /** Another of our devices at the other end of the cable. */
134
+ /** One of `switching.acls`: the hardware ACL applied to traffic arriving on this port. */
135
+ ingress_acl?: Acl;
136
+ /** One of `interfaces.lag`: the LAG this port is in. Every other setting goes on the LAG. */
137
+ in_lag?: Lag;
138
+ /** Another of our devices at the other end of the cable. Circuit checks that it links back, and warns when `description` doesn't name it. */
117
139
  link?: Link;
118
140
  };
119
141
 
120
142
  /** Settings every interface that is not a physical port shares. */
121
- type Base<F extends string> = Routed<F> & {
143
+ export type Base<Vrf extends string> = Routed<Vrf> & {
122
144
  /** What the interface is for. */
123
145
  description?: string;
124
146
  /** Largest IP packet, in bytes. */
@@ -126,10 +148,9 @@ type Base<F extends string> = Routed<F> & {
126
148
  };
127
149
 
128
150
  /** A layer 3 interface on a VLAN. */
129
- export type VlanInterface<V extends string, F extends string> = Base<F> & {
130
- type: "vlan";
131
- /** The VLAN it is on. */
132
- vlan: V;
151
+ export type VlanInterface<Vlan extends string, Vrf extends string> = Base<Vrf> & {
152
+ /** One of `switching.vlans`: the VLAN it is on. */
153
+ vlan: Vlan;
133
154
  /**
134
155
  * A MAC address of its own, instead of the one it shares with the device's other VLAN interfaces. A gateway in front of a transparent firewall needs one: frames to it come back on another VLAN, where the bridge would otherwise take a shared MAC for its own and keep them.
135
156
  */
@@ -137,12 +158,11 @@ export type VlanInterface<V extends string, F extends string> = Base<F> & {
137
158
  };
138
159
 
139
160
  /** An interface that is always up and is on no link, for addresses that must not depend on one. */
140
- export type Loopback<F extends string> = Base<F> & { type: "loopback" };
161
+ export type Loopback<Vrf extends string> = Base<Vrf>;
141
162
 
142
- /** A link aggregation. Each member port points to it with `lag`. */
143
- export type Lag<V extends string, F extends string> = Base<F> &
144
- Switched<V> & {
145
- type: "lag";
163
+ /** A link aggregation. Each member port points to it with `in_lag`. */
164
+ export type Lag<Vlan extends string, Vrf extends string> = Base<Vrf> &
165
+ Switched<Vlan> & {
146
166
  /** LACP negotiates membership with the far end; `static` joins the ports without asking. LACP when absent. */
147
167
  mode?: "lacp" | "static";
148
168
  /** Number, on platforms where a LAG has a number instead of a name. Its position among the device's LAGs when absent. */
@@ -150,23 +170,21 @@ export type Lag<V extends string, F extends string> = Base<F> &
150
170
  };
151
171
 
152
172
  /** A GRE tunnel. */
153
- export type Gre<F extends string> = Base<F> & {
154
- type: "gre";
155
- /** Our tunnel endpoint. */
156
- local: IP;
173
+ export type Gre<Vrf extends string> = Base<Vrf> & {
174
+ /** Our tunnel endpoint, alone or with its length. */
175
+ local_address: HostAddress;
157
176
  /** The far tunnel endpoint. */
158
- remote: IP;
177
+ remote_address: IP;
159
178
  };
160
179
 
161
180
  /** A point-to-point VXLAN tunnel. */
162
- export type Vxlan<F extends string> = Base<F> & {
163
- type: "vxlan";
164
- /** Segment identifier, the same on both ends. */
181
+ export type Vxlan<Vrf extends string> = Base<Vrf> & {
182
+ /** Segment identifier, the same on both ends, 1 to 16777215. */
165
183
  vni: number;
166
- /** Our tunnel endpoint. */
167
- local: IP;
184
+ /** Our tunnel endpoint, alone or with its length. */
185
+ local_address: HostAddress;
168
186
  /** The far tunnel endpoint. */
169
- remote: IP;
187
+ remote_address: IP;
170
188
  /** UDP port. 4789 when absent. */
171
189
  port?: number;
172
190
  /** Fixed MAC address, so a rebuild keeps the one the far side learned. */
@@ -193,12 +211,11 @@ export type WireGuardPeer = {
193
211
  };
194
212
 
195
213
  /** A WireGuard interface. */
196
- export type WireGuard<F extends string> = Base<F> & {
197
- type: "wireguard";
214
+ export type WireGuard<Vrf extends string> = Base<Vrf> & {
198
215
  /** UDP port peers connect to. */
199
216
  listen_port: number;
200
- /** The address clients connect to, for generated client configs. */
201
- endpoint?: IP;
217
+ /** The address clients connect to, for generated client configs, alone or with its length. */
218
+ endpoint?: HostAddress;
202
219
  /** This interface's private key. Its public key is derived from it. */
203
220
  private_key: Secret;
204
221
  /** Who may connect. */
@@ -208,12 +225,31 @@ export type WireGuard<F extends string> = Base<F> & {
208
225
  /**
209
226
  * A layer 2 bridge between VLAN interfaces, each keeping its own VLAN: a frame that comes in on one member leaves another with that member's tag. A firewall filters what crosses it, by the rules of its forward chain between the members, without routing it.
210
227
  */
211
- export type Bridge<F extends string> = Base<F> & {
212
- type: "bridge";
213
- /** The VLAN interfaces it joins, by name. Each has no address of its own. */
214
- members: readonly string[];
228
+ export type Bridge<VlanInterface extends string, Vrf extends string> = Base<Vrf> & {
229
+ /** Some of `interfaces.vlan_interface`: the VLAN interfaces it joins. Each has no address of its own. */
230
+ member_interfaces: readonly VlanInterface[];
215
231
  };
216
232
 
217
- /** Any interface that is not a physical port. */
218
- export type Interface<V extends string, F extends string> =
219
- VlanInterface<V, F> | Loopback<F> | Lag<V, F> | Gre<F> | Vxlan<F> | WireGuard<F> | Bridge<F>;
233
+ /**
234
+ * Every port and interface, by kind, each keyed by its name. A port's key is `<speed>-<position>` from the model.
235
+ *
236
+ * The type parameters are the names the device declares: `Ethernet` the ports, `L` LAGs, `VI` VLAN interfaces, `T` the other interfaces, `V` VLANs, `A` ACLs, `F` VRFs.
237
+ */
238
+ export type Interfaces<Ethernet, L extends string, VI extends string, T extends string, V extends string, F extends string> = {
239
+ /** Physical ports, keyed by `<speed>-<position>` from the model, such as `10g-4`. Ports not listed are shut down. */
240
+ ethernet?: Ethernet;
241
+ /** Link aggregations, keyed by name. Each member port names one with `in_lag`. */
242
+ lag?: Named<L, Lag<V, F>>;
243
+ /** Layer 3 interfaces on a VLAN, keyed by name. Each names its VLAN in `vlan`. */
244
+ vlan_interface?: Named<VI, VlanInterface<V, F>>;
245
+ /** Layer 2 bridges between VLAN interfaces, keyed by name. */
246
+ bridge?: Named<T, Bridge<NoInfer<VI>, F>>;
247
+ /** Interfaces on no link, keyed by name. */
248
+ loopback?: Named<T, Loopback<F>>;
249
+ /** GRE tunnels, keyed by name. */
250
+ gre?: Named<T, Gre<F>>;
251
+ /** Point-to-point VXLAN tunnels, keyed by name. */
252
+ vxlan?: Named<T, Vxlan<F>>;
253
+ /** WireGuard interfaces, keyed by name. */
254
+ wireguard?: Named<T, WireGuard<F>>;
255
+ };