@tikoci/centrs 0.1.2 → 0.1.4
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/CHANGELOG.md +98 -0
- package/GLOSSARY.txt +284 -0
- package/LICENSE +21 -0
- package/README.md +55 -11
- package/SECURITY.md +3 -3
- package/commands/AGENTS.md +7 -1
- package/commands/api/README.md +46 -27
- package/commands/api/examples.md +124 -6
- package/commands/btest/README.md +21 -32
- package/commands/check/README.md +376 -53
- package/commands/check/examples.md +390 -0
- package/commands/devices/README.md +177 -37
- package/commands/devices/examples.md +148 -0
- package/commands/discover/README.md +5 -11
- package/commands/execute/README.md +73 -26
- package/commands/execute/examples.md +131 -9
- package/commands/explain/README.md +1716 -0
- package/commands/explain/examples.md +606 -0
- package/commands/retrieve/README.md +55 -71
- package/commands/retrieve/examples.md +56 -9
- package/commands/settings/README.md +286 -22
- package/commands/settings/examples.md +408 -0
- package/commands/terminal/README.md +6 -0
- package/commands/transfer/README.md +57 -19
- package/commands/transfer/examples.md +95 -0
- package/docs/CLI.md +353 -0
- package/docs/CONSTITUTION.md +102 -26
- package/docs/MATRIX.md +106 -173
- package/docs/errors/README.md +5 -1
- package/docs/errors/cdb/empty-selection.md +19 -0
- package/docs/errors/input/incomplete-gps.md +9 -0
- package/docs/errors/input/invalid-altitude.md +9 -0
- package/docs/errors/input/invalid-bbox.md +9 -0
- package/docs/errors/input/invalid-coordinate.md +9 -0
- package/docs/errors/input/invalid-radius.md +9 -0
- package/docs/errors/internal/settings-failed.md +9 -0
- package/docs/errors/quickchr/machine-not-found.md +22 -0
- package/docs/errors/quickchr/machine-stopped.md +20 -0
- package/docs/errors/quickchr/package-unavailable.md +27 -0
- package/docs/errors/quickchr/unsupported-via.md +35 -0
- package/docs/errors/quickchr/unsupported.md +35 -0
- package/docs/errors/routeros/version-unsupported.md +26 -0
- package/docs/errors/settings/consequential-value.md +26 -0
- package/docs/errors/settings/invalid-boolean.md +21 -3
- package/docs/errors/settings/invalid-format.md +18 -3
- package/docs/errors/settings/invalid-integer.md +18 -3
- package/docs/errors/settings/invalid-timeout.md +20 -3
- package/docs/errors/settings/invalid-via.md +22 -3
- package/docs/errors/settings/reserved-key.md +29 -0
- package/docs/errors/settings/skip-env-file-active.md +25 -0
- package/docs/errors/settings/unknown-key.md +25 -0
- package/docs/errors/transport/provider-trust.md +29 -0
- package/docs/errors/usage/fanout-not-supported.md +16 -0
- package/docs/errors/usage/stdin-ignored.md +28 -0
- package/docs/errors/validation/unknown-attribute.md +37 -4
- package/package.json +49 -14
- package/src/api-fanout.ts +469 -0
- package/src/api.ts +171 -56
- package/src/cli/api.ts +156 -13
- package/src/cli/btest.ts +38 -4
- package/src/cli/common.ts +11 -0
- package/src/cli/devices.ts +235 -6
- package/src/cli/discover.ts +3 -1
- package/src/cli/execute.ts +129 -9
- package/src/cli/explain.ts +503 -0
- package/src/cli/mcp.ts +8 -1
- package/src/cli/retrieve.ts +167 -90
- package/src/cli/selection.ts +260 -0
- package/src/cli/settings.ts +286 -0
- package/src/cli/terminal.ts +22 -7
- package/src/cli/transfer.ts +192 -51
- package/src/cli.ts +22 -2
- package/src/core/envelope.ts +5 -2
- package/src/core/error-catalog.ts +95 -0
- package/src/core/fanout.ts +143 -2
- package/src/core/preflight.ts +306 -0
- package/src/core/routeros-string.ts +24 -0
- package/src/devices.ts +212 -20
- package/src/discover.ts +7 -2
- package/src/errors.ts +1 -0
- package/src/execute-fanout.ts +453 -0
- package/src/execute.ts +216 -68
- package/src/explain/arg-tokens.ts +114 -0
- package/src/explain/args.ts +1403 -0
- package/src/explain/blocks.ts +132 -0
- package/src/explain/brace-slots.ts +143 -0
- package/src/explain/brace-tokens.ts +38 -0
- package/src/explain/catalog.ts +1345 -0
- package/src/explain/coordinates.ts +329 -0
- package/src/explain/defects.ts +217 -0
- package/src/explain/is-known-menu.ts +17 -0
- package/src/explain/menus.ts +664 -0
- package/src/explain/operator-tokens.ts +310 -0
- package/src/explain/operators.ts +458 -0
- package/src/explain/path-tokens.ts +150 -0
- package/src/explain/pathresolve.ts +1324 -0
- package/src/explain/quoted-string.ts +241 -0
- package/src/explain/scope-brace.ts +308 -0
- package/src/explain/segment.ts +757 -0
- package/src/explain/string-tokens.ts +67 -0
- package/src/explain/symbol-values.ts +520 -0
- package/src/explain/symbols.ts +1597 -0
- package/src/explain/token-ranges.ts +72 -0
- package/src/explain/transport.ts +497 -0
- package/src/explain/value-tokens.ts +80 -0
- package/src/explain/values.ts +357 -0
- package/src/explain/verbs.ts +64 -0
- package/src/explain/verbsplit.ts +813 -0
- package/src/explain/write.ts +815 -0
- package/src/explain.ts +2152 -0
- package/src/index.ts +307 -1
- package/src/mcp/config.ts +12 -2
- package/src/mcp/tools.ts +137 -2
- package/src/protocols/adapter.ts +38 -18
- package/src/protocols/index.ts +11 -5
- package/src/protocols/mac-telnet-console.ts +61 -17
- package/src/resolver/cdb.ts +10 -2
- package/src/resolver/comment-kv.ts +58 -4
- package/src/resolver/config-file.ts +136 -0
- package/src/resolver/facts.ts +78 -0
- package/src/resolver/geo.ts +453 -0
- package/src/resolver/index.ts +65 -0
- package/src/resolver/mac.ts +12 -3
- package/src/resolver/quickchr-provider.ts +597 -0
- package/src/resolver/selection.ts +391 -0
- package/src/resolver/service-endpoint.ts +155 -0
- package/src/resolver/settings.ts +54 -5
- package/src/resolver/target.ts +21 -3
- package/src/retrieve-fanout.ts +239 -133
- package/src/retrieve.ts +120 -25
- package/src/settings.ts +1078 -0
- package/src/terminal.ts +11 -1
- package/src/transfer-fanout.ts +544 -0
- package/src/transfer.ts +133 -40
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# centrs CLI reference
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED FILE — do not edit. Regenerate with `bun run docs:cli`. -->
|
|
4
|
+
<!-- Source of truth: the CliCommandMetadata objects in src/cli/*.ts -->
|
|
5
|
+
|
|
6
|
+
Every flag below is generated from the same metadata that renders
|
|
7
|
+
`centrs <command> --help`; CI fails when this file and the metadata drift
|
|
8
|
+
(`bun run docs:cli --check`). Behavior, examples, and designed-but-not-yet
|
|
9
|
+
implemented flags live in each command's `commands/<name>/README.md`.
|
|
10
|
+
|
|
11
|
+
| Command | Summary |
|
|
12
|
+
| ------- | ------- |
|
|
13
|
+
| [`retrieve`](#retrieve) | Read RouterOS values through the shared core using the selected protocol. |
|
|
14
|
+
| [`execute`](#execute) | Run a RouterOS read or write command via native API, REST, or mac-telnet. |
|
|
15
|
+
| [`api`](#api) | Structured RouterOS API passthrough (gh-api style) over REST or native API. |
|
|
16
|
+
| [`transfer`](#transfer) | Copy files to/from a RouterOS device and manage device files (rest/native/sftp). |
|
|
17
|
+
| [`terminal`](#terminal) | Open an interactive RouterOS console (ssh or mac-telnet). |
|
|
18
|
+
| [`explain`](#explain) | Analyze a RouterOS command offline: canonical form, structure, and syntax diagnostics. |
|
|
19
|
+
| [`devices`](#devices) | Inspect and mutate the CDB-backed device registry. `devices` is the only command that writes the CDB. |
|
|
20
|
+
| [`discover`](#discover) | Discover RouterOS neighbors over MNDP and optionally save them into the CDB. |
|
|
21
|
+
| [`btest`](#btest) | Run MikroTik's bandwidth test as a client or server (peer measurement). |
|
|
22
|
+
| [`mcp`](#mcp) | Start the centrs MCP server (stdio) — scoped RouterOS tools gated by the CDB allowlist. |
|
|
23
|
+
| [`settings`](#settings) | Manage centrs's own global preferences (`centrs.env`) and inspect the `__default__` CDB record. |
|
|
24
|
+
|
|
25
|
+
## retrieve
|
|
26
|
+
|
|
27
|
+
Read RouterOS values through the shared core using the selected protocol.
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
Usage: centrs retrieve <target> <routeros-path> [flags] | centrs retrieve <target...> <routeros-path> [flags] | centrs retrieve --group <name> <routeros-path> [flags]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
| Flag | Value | Description |
|
|
34
|
+
| ---- | ----- | ----------- |
|
|
35
|
+
| `--via` | `<protocol>` | Pin the protocol selector. Defaults to `rest-api` for retrieve. |
|
|
36
|
+
| `--group` | `<name>` | Fan out across every CDB record in the group (repeatable; de-duped by record index). |
|
|
37
|
+
| `--where` | `<attr>`=`<value>` | Device-class selector over CDB facts + core fields (repeatable, AND-combined). |
|
|
38
|
+
| `--near` | `<lat>`,`<lon>`,`<radius>` | Geo selector: devices whose GPS is within radius (m/km/mi/ft; bare number = km). Lat-first. |
|
|
39
|
+
| `--bbox` | `<south>`,`<west>`,`<north>`,`<east>` | Geo selector: devices whose GPS is inside the lat-first bounding box. |
|
|
40
|
+
| `--all` | | Fan out across every CDB record (excludes `__default__`). |
|
|
41
|
+
| `--default` | | Select the reserved `__default__` record. |
|
|
42
|
+
| `--quickchr` | `<name>` | Target a running quickchr-managed CHR VM by name (repeatable; fans out when repeated). Exclusive of positional targets and CDB selectors; conflicts with direct connection overrides (--host/--port/--username/--password, and --ssh-key where the command has it). |
|
|
43
|
+
| `--concurrency` | `<n>` | Max in-flight targets during fan-out (transport-aware default: rest-api 8, native-api 4). |
|
|
44
|
+
| `--host` | <host\|url> | Override the resolved host or base URL for the target. |
|
|
45
|
+
| `--port` | `<port>` | Override the resolved management port. |
|
|
46
|
+
| `--username / --user / -u` | `<name>` | RouterOS username (aliases `--user`, `-u`). Falls back to `CENTRS_USERNAME`. |
|
|
47
|
+
| `--password` | `<secret>` | RouterOS password. Falls back to `CENTRS_PASSWORD`. |
|
|
48
|
+
| `--timeout` | <ms\|5s> | Operation timeout. REST currently rejects values above 60s. |
|
|
49
|
+
| `--attribute` | `<name>` | Project one attribute. May be repeated. |
|
|
50
|
+
| `--attributes` | `<a,b>` | Project a comma-separated attribute list. |
|
|
51
|
+
| `--all-attributes` | | Request the RouterOS detail/all-attributes shape. |
|
|
52
|
+
| `--list-attributes / --list` | | List inspect-derived attributes without running the data call. |
|
|
53
|
+
| `--query / --filter` | `<expr>` | RouterOS-side row filter (maps to `.query`). Not implemented yet — returns `validation/not-implemented`. |
|
|
54
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. Defaults to text; use --json or --format json for the structured envelope. |
|
|
55
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
56
|
+
| `--max-results` | `<bytes>` | Fail instead of printing output larger than the given byte budget. |
|
|
57
|
+
| `--cdb-file` | `<path>` | Read target credentials from a WinBox CDB file. |
|
|
58
|
+
| `--cdb-password` | `<password>` | Decrypt an encrypted WinBox CDB file. |
|
|
59
|
+
| `--resolve` | <none\|arp> | Resolve a MAC-address target to an IP via the host ARP cache (default none). |
|
|
60
|
+
| `--validate / --no-validate` | | Enable or disable inspect-backed preflight validation. |
|
|
61
|
+
| `--verbose` | | Show resolved setting sources in text output. |
|
|
62
|
+
|
|
63
|
+
## execute
|
|
64
|
+
|
|
65
|
+
Run a RouterOS read or write command via native API, REST, or mac-telnet.
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
Usage: centrs execute <target> <command> [flags] | centrs execute <target...> -- <command> [flags] | centrs execute --group <name> <command> [flags]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
| Flag | Value | Description |
|
|
72
|
+
| ---- | ----- | ----------- |
|
|
73
|
+
| `--via` | <native-api\|rest-api\|mac-telnet> | Pin the protocol selector; no silent downgrade when set. A bare MAC target defaults to mac-telnet. |
|
|
74
|
+
| `--group` | `<name>` | Fan out across every CDB record in the group (repeatable; de-duped by record index). |
|
|
75
|
+
| `--where` | `<attr>`=`<value>` | Device-class selector over CDB facts + core fields (repeatable, AND-combined). |
|
|
76
|
+
| `--near` | `<lat>`,`<lon>`,`<radius>` | Geo selector: devices whose GPS is within radius (m/km/mi/ft; bare number = km). Lat-first. |
|
|
77
|
+
| `--bbox` | `<south>`,`<west>`,`<north>`,`<east>` | Geo selector: devices whose GPS is inside the lat-first bounding box. |
|
|
78
|
+
| `--all` | | Fan out across every CDB record (excludes `__default__`). |
|
|
79
|
+
| `--default` | | Select the reserved `__default__` record. |
|
|
80
|
+
| `--quickchr` | `<name>` | Target a running quickchr-managed CHR VM by name (repeatable; fans out when repeated). Exclusive of positional targets and CDB selectors; conflicts with direct connection overrides (--host/--port/--username/--password, and --ssh-key where the command has it). |
|
|
81
|
+
| `--concurrency` | `<n>` | Max in-flight targets during fan-out (transport-aware default: rest-api 8, native-api 4). |
|
|
82
|
+
| `--host` | <host\|url> | Override the resolved host or base URL for the target. |
|
|
83
|
+
| `--port` | `<port>` | Override the resolved management port. |
|
|
84
|
+
| `--username / --user / -u` | `<name>` | RouterOS username (aliases `--user`, `-u`). Falls back to `CENTRS_USERNAME`. |
|
|
85
|
+
| `--password` | `<secret>` | RouterOS password. Falls back to `CENTRS_PASSWORD`. |
|
|
86
|
+
| `--ssh-key` | `<path>` | `--via ssh`: explicit private-key path. Falls back to `CENTRS_SSH_KEY` / the `ssh-agent`. |
|
|
87
|
+
| `--insecure` | | Disable SSH host-key verification (`--via ssh`: accepts changed/impersonated keys, not just new) or accept a self-signed `api-ssl` TLS cert. Default verifies. |
|
|
88
|
+
| `--cdb-file` | `<path>` | Read target credentials from a WinBox CDB file. |
|
|
89
|
+
| `--cdb-password` | `<password>` | Decrypt an encrypted WinBox CDB file. |
|
|
90
|
+
| `--resolve` | <none\|arp> | Resolve a MAC-address target to an IP via the host ARP cache (default none). |
|
|
91
|
+
| `--timeout` | `<duration>` | Per-request timeout (for REST, max 60s). |
|
|
92
|
+
| `--validate / --no-validate` | | Run RouterOS :parse and /console/inspect validation before execution (default true; `--validate=false` also accepted). |
|
|
93
|
+
| `--yes` | | Confirm write-shaped add/set/remove commands in non-interactive runs. |
|
|
94
|
+
| `--max-results` | `<bytes>` | Fail if the rendered envelope exceeds this byte budget. |
|
|
95
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. Defaults to text; use --json or --format json for the structured envelope. |
|
|
96
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
97
|
+
| `--verbose` | | Include additional context in text output. |
|
|
98
|
+
| `--` | | End centrs option parsing: every following token is the literal RouterOS command, even flag-shaped ones (e.g. `-- /interface print where disabled=yes`). |
|
|
99
|
+
|
|
100
|
+
## api
|
|
101
|
+
|
|
102
|
+
Structured RouterOS API passthrough (gh-api style) over REST or native API.
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
Usage: centrs api <router> <endpoint> [flags]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
| Flag | Value | Description |
|
|
109
|
+
| ---- | ----- | ----------- |
|
|
110
|
+
| `-X / --method` | `<verb>` | HTTP method, default GET (case-insensitive). GET→print, PUT→add, PATCH→set, DELETE→remove, POST→run. |
|
|
111
|
+
| `-f / --field` | `<key=value>` | Body field, repeatable; assembled into the JSON body (verbatim string values). |
|
|
112
|
+
| `-d / --data` | `<json>` | Raw JSON request body. Conflicts with `-f` / `--input`. |
|
|
113
|
+
| `--input` | <file\|-> | Read the raw JSON body from a file or stdin (`-`). |
|
|
114
|
+
| `--query / --filter` | `<expr>` | RouterOS-side row filter, AND-combined, repeatable: name=value, name!=value, name>value, name<value, name. |
|
|
115
|
+
| `--raw-query` | `<word>` | Verbatim RouterOS query word (repeatable) for OR / absence / stack expressions. |
|
|
116
|
+
| `--attribute / --proplist` | `<a,b>` | Property projection → `.proplist`. |
|
|
117
|
+
| `--raw` | | Strip the envelope; emit bare RouterOS JSON. Implies `--validate=false`; does not imply `--yes`. |
|
|
118
|
+
| `--yes` | | Confirm a mutating (non-read) request in non-interactive runs. |
|
|
119
|
+
| `--stream / --listen` | | Follow changes as an NDJSON envelope stream (native-api only; the `/listen` endpoint infers it). Ends with a summary envelope. |
|
|
120
|
+
| `--count` | `<n>` | Stop a `--stream` after N change frames. |
|
|
121
|
+
| `--duration` | `<dur>` | Stop a `--stream` after this wall-clock window (e.g. `5s`). |
|
|
122
|
+
| `--via` | <rest-api\|native-api> | Pin the transport; no silent downgrade. Default rest-api. |
|
|
123
|
+
| `--group` | `<name>` | Fan out across every CDB record in the group (repeatable; de-duped by record index). |
|
|
124
|
+
| `--where` | `<attr>`=`<value>` | Device-class selector over CDB facts + core fields (repeatable, AND-combined). |
|
|
125
|
+
| `--near` | `<lat>`,`<lon>`,`<radius>` | Geo selector: devices whose GPS is within radius (m/km/mi/ft; bare number = km). Lat-first. |
|
|
126
|
+
| `--bbox` | `<south>`,`<west>`,`<north>`,`<east>` | Geo selector: devices whose GPS is inside the lat-first bounding box. |
|
|
127
|
+
| `--all` | | Fan out across every CDB record (excludes `__default__`). |
|
|
128
|
+
| `--default` | | Select the reserved `__default__` record. |
|
|
129
|
+
| `--quickchr` | `<name>` | Target a running quickchr-managed CHR VM by name (repeatable; fans out when repeated). Exclusive of positional targets and CDB selectors; conflicts with direct connection overrides (--host/--port/--username/--password, and --ssh-key where the command has it). |
|
|
130
|
+
| `--concurrency` | `<n>` | Max in-flight targets during fan-out (transport-aware default: rest-api 8, native-api 4). |
|
|
131
|
+
| `--host` | <host\|url> | Override the resolved host or base URL for the target. |
|
|
132
|
+
| `--port` | `<port>` | Override the resolved management port. |
|
|
133
|
+
| `--username / --user / -u` | `<name>` | RouterOS username. Falls back to `CENTRS_USERNAME`. |
|
|
134
|
+
| `--password` | `<secret>` | RouterOS password. Falls back to `CENTRS_PASSWORD`. |
|
|
135
|
+
| `--insecure` | | Accept a self-signed `api-ssl`/REST TLS cert. Default verifies. |
|
|
136
|
+
| `--cdb-file` | `<path>` | Read target credentials from a WinBox CDB file. |
|
|
137
|
+
| `--cdb-password` | `<password>` | Decrypt an encrypted WinBox CDB file. |
|
|
138
|
+
| `--resolve` | <none\|arp> | Resolve a MAC-address target to an IP via the host ARP cache (default none). |
|
|
139
|
+
| `--timeout` | `<duration>` | Per-request timeout (for REST, max 60s). |
|
|
140
|
+
| `--validate / --no-validate` | | Run `/console/inspect` validation before the request (default true; `--validate=false` also accepted). |
|
|
141
|
+
| `--format` | <json\|yaml\|text> | Output format. Defaults to json for api; `CENTRS_FORMAT` overrides. |
|
|
142
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
143
|
+
| `--verbose` | | Include additional context in text output. |
|
|
144
|
+
|
|
145
|
+
## transfer
|
|
146
|
+
|
|
147
|
+
Copy files to/from a RouterOS device and manage device files (rest/native/sftp).
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
Usage: centrs transfer <router> upload <local> [remote] | download <remote> [local] | list [path] | remove <remote> | mkdir <remote> | copy <src> <dst> [flags]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
| Flag | Value | Description |
|
|
154
|
+
| ---- | ----- | ----------- |
|
|
155
|
+
| `--via` | `<method>` | Pin the method: rest, native, or sftp (large transfers); scp/fetch/ftp are not built yet. Auto picks the cheapest by size/direction. |
|
|
156
|
+
| `--ssh-key` | `<path>` | sftp only: explicit private-key path. Falls back to CENTRS_SSH_KEY / the ssh-agent. |
|
|
157
|
+
| `--insecure` | | Accept a self-signed TLS cert (https/api-ssl) or a new SSH host key. Default verifies. |
|
|
158
|
+
| `--force / --overwrite` | | Replace an existing destination. Default refuses it. |
|
|
159
|
+
| `--group` | `<name>` | Fan out across every CDB record in the group (repeatable; de-duped by record index). |
|
|
160
|
+
| `--where` | `<attr>`=`<value>` | Device-class selector over CDB facts + core fields (repeatable, AND-combined). |
|
|
161
|
+
| `--near` | `<lat>`,`<lon>`,`<radius>` | Geo selector: devices whose GPS is within radius (m/km/mi/ft; bare number = km). Lat-first. |
|
|
162
|
+
| `--bbox` | `<south>`,`<west>`,`<north>`,`<east>` | Geo selector: devices whose GPS is inside the lat-first bounding box. |
|
|
163
|
+
| `--all` | | Fan out across every CDB record (excludes `__default__`). |
|
|
164
|
+
| `--default` | | Select the reserved `__default__` record. |
|
|
165
|
+
| `--quickchr` | `<name>` | Target a running quickchr-managed CHR VM by name (repeatable; fans out when repeated). Exclusive of positional targets and CDB selectors; conflicts with direct connection overrides (--host/--port/--username/--password, and --ssh-key where the command has it). |
|
|
166
|
+
| `--concurrency` | `<n>` | Max in-flight targets during fan-out (transport-aware default: rest-api 8, native-api 4). |
|
|
167
|
+
| `--out-dir` | `<dir>` | `download` fan-out only: write one file per target into `<dir>`, named by CDB identity. Required when downloading across a selection. |
|
|
168
|
+
| `--yes` | | Confirm a mutating fan-out (upload/remove/mkdir/copy) across multiple routers in non-interactive runs. |
|
|
169
|
+
| `--verify / --no-verify` | <size\|checksum\|off> | Post-transfer integrity check. Default size; `--no-verify` skips. |
|
|
170
|
+
| `--type` | <file\|directory\|disk\|package> | list filter: RouterOS /file row type. |
|
|
171
|
+
| `--name` | `<glob>` | list filter: file-name glob. |
|
|
172
|
+
| `--host` | <host\|url> | Override the resolved host or base URL. |
|
|
173
|
+
| `--port` | `<port>` | Override the resolved management port. |
|
|
174
|
+
| `--username / --user / -u` | `<name>` | RouterOS username (aliases --user, -u). Falls back to CENTRS_USERNAME. |
|
|
175
|
+
| `--password` | `<secret>` | RouterOS password. Falls back to CENTRS_PASSWORD. |
|
|
176
|
+
| `--timeout` | <ms\|5s> | Operation timeout. REST rejects values above 60s. |
|
|
177
|
+
| `--format` | <text\|json\|yaml> | Output format. Defaults to text; --json / --yaml shortcuts. |
|
|
178
|
+
| `--json` | | Shortcut for --format json. |
|
|
179
|
+
| `--yaml` | | Shortcut for --format yaml. |
|
|
180
|
+
| `--cdb-file` | `<path>` | Read target credentials from a WinBox CDB file. |
|
|
181
|
+
| `--cdb-password` | `<password>` | Decrypt an encrypted WinBox CDB file. |
|
|
182
|
+
| `--validate / --no-validate` | | Enable or disable the existence-probe preflight. |
|
|
183
|
+
| `--verbose` | | Show the resolved transport in text output. |
|
|
184
|
+
|
|
185
|
+
## terminal
|
|
186
|
+
|
|
187
|
+
Open an interactive RouterOS console (ssh or mac-telnet).
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
Usage: centrs terminal <router> [flags]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
| Flag | Value | Description |
|
|
194
|
+
| ---- | ----- | ----------- |
|
|
195
|
+
| `--via` | `<method>` | Transport: `ssh` (host target, default) or `mac-telnet` (MAC target, default for a MAC). rest/native have no terminal capability. |
|
|
196
|
+
| `--host` | `<host>` | Override the target host (ssh) / UDP delivery host (mac-telnet, default L2 broadcast). |
|
|
197
|
+
| `--port` | `<port>` | Override the port: ssh default 22, mac-telnet default 20561. |
|
|
198
|
+
| `--username / --user / -u` | `<name>` | RouterOS username (aliases --user, -u). Falls back to CENTRS_USERNAME. |
|
|
199
|
+
| `--password` | `<secret>` | RouterOS password. Falls back to CENTRS_PASSWORD. |
|
|
200
|
+
| `--source-mac` | `<mac>` | mac-telnet: explicit in-packet source MAC (overrides egress resolution). |
|
|
201
|
+
| `--ssh-key` | `<path>` | `--via ssh`: explicit private-key path. Falls back to `CENTRS_SSH_KEY` / the `ssh-agent`. |
|
|
202
|
+
| `--insecure` | | `--via ssh`: disable host-key verification (accepts changed/impersonated keys). Default verifies. |
|
|
203
|
+
| `--cdb-file` | `<path>` | Read target credentials from a WinBox CDB file. |
|
|
204
|
+
| `--cdb-password` | `<password>` | Decrypt an encrypted WinBox CDB file. |
|
|
205
|
+
| `--resolve` | <none\|arp> | `--via ssh` only: turn a MAC target into an IP. CDB-first; `arp` opts into the host ARP cache (default none). The mac-telnet default ignores it. |
|
|
206
|
+
| `--format` | <text\|json\|yaml> | Error-envelope format on failure. --json / --yaml shortcuts. |
|
|
207
|
+
| `--json` | | Shortcut for --format json. |
|
|
208
|
+
| `--yaml` | | Shortcut for --format yaml. |
|
|
209
|
+
| `--verbose` | | Verbose error output. |
|
|
210
|
+
|
|
211
|
+
## explain
|
|
212
|
+
|
|
213
|
+
Analyze a RouterOS command offline: canonical form, structure, and syntax diagnostics.
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
Usage: centrs explain '<input>' [flags]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Flag | Value | Description |
|
|
220
|
+
| ---- | ----- | ----------- |
|
|
221
|
+
| `--file` | `<path>` | Read the input from a file instead of the positional (`-` reads stdin). Piped stdin is used automatically when no input positional is given. |
|
|
222
|
+
| `--fail-on` | <error\|warning\|never> | Exit 2 when the verdict reaches this severity. Default `error`; an ambiguous or unknown statement is a warning, never an error. |
|
|
223
|
+
| `--complete` | | Continuation candidates at the cursor. Live evidence — offline emits a tip and enumerates nothing. |
|
|
224
|
+
| `--schema` | | Path enumeration (verbs, args, types, enums). Live evidence — offline emits a tip and enumerates nothing. |
|
|
225
|
+
| `--curl` | | Render a ready-to-edit REST curl for statements covered by a runtime-tested mapping rule. |
|
|
226
|
+
| `--tokens` | | Emit the total, gapless token partition behind `data.tokens[]` (provisional `class` until #264 B5: every byte not claimed by an analyzer is `unclassified`). |
|
|
227
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. |
|
|
228
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
229
|
+
| `--yaml` | | Shortcut for `--format yaml`. |
|
|
230
|
+
| `--verbose` | | Verbose error output. |
|
|
231
|
+
|
|
232
|
+
## devices
|
|
233
|
+
|
|
234
|
+
Inspect and mutate the CDB-backed device registry. `devices` is the only command that writes the CDB.
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
Usage: centrs devices <list|show|groups|add|edit|set|remove> [args] [flags]
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
| Flag | Value | Description |
|
|
241
|
+
| ---- | ----- | ----------- |
|
|
242
|
+
| `--cdb-file` | `<path>` | Override the resolved CDB path (default `~/.config/tikoci/winbox.cdb`). |
|
|
243
|
+
| `--cdb-password` | `<secret>` | Decrypt an encrypted CDB. Falls back to `CENTRS_CDB_PASSWORD`. Also used to re-encrypt on writes. |
|
|
244
|
+
| `--via` | `<protocol>` | Resolve and report the protocol source for provenance examples; no network IO is performed. |
|
|
245
|
+
| `--group` | `<name>` | `list` filter / `add`,`edit` first-class group field for the target entry. |
|
|
246
|
+
| `--where` | `<attr=value>` | `list` only — repeatable device-class filter over CDB facts (AND-combined), e.g. `--where lat=37.7749`. |
|
|
247
|
+
| `--near` | `<lat>`,`<lon>`,`<radius>` | `list` only — GPS filter: devices within radius (m/km/mi/ft; bare number = km). Lat-first. |
|
|
248
|
+
| `--bbox` | `<south>`,`<west>`,`<north>`,`<east>` | `list` only — GPS filter: devices inside the lat-first bounding box. |
|
|
249
|
+
| `--members` | | `groups` only — expand each group's membership. |
|
|
250
|
+
| `--explain` | | `show` only — include the raw `WinBoxCdbRecord` in `data.record`. |
|
|
251
|
+
| `--match` | <user=…\|target=…\|record-type> | `show` — disambiguate when `<router>` matches several records: `user=<name>`, `target=<addr>`, or a record-type token. |
|
|
252
|
+
| `--user` | `<name>` | `add`,`set` — first-class CDB user field. |
|
|
253
|
+
| `--password` | `<secret>` | `add`,`set` — first-class CDB password field. |
|
|
254
|
+
| `--profile` | `<name>` | `add`,`set` — named WinBox profile (Workspace). |
|
|
255
|
+
| `--profile-none` | | `add`,`set` — write the WinBox `<none>` profile sentinel. |
|
|
256
|
+
| `--profile-own` | | `add`,`set` — write the WinBox `<own>` profile sentinel. |
|
|
257
|
+
| `--session` | `<name>` | `add`,`set` — first-class CDB session field. |
|
|
258
|
+
| `--comment` | `<text>` | `add` only — base free-form comment (may include kv-soup). |
|
|
259
|
+
| `--record-type` | <macTarget\|ipAdmin\|ipUser\|romonNeighbor\|romonTarget> | `add` only — record type (default `ipAdmin`). |
|
|
260
|
+
| `--lat / --latitude` | `<deg>` | `add`,`set` — latitude in decimal degrees (-90..90); a comment-kv fact, paired with --lon. |
|
|
261
|
+
| `--lon / --lng / --longitude / --long` | `<deg>` | `add`,`set` — longitude in decimal degrees (-180..180); a comment-kv fact, paired with --lat. |
|
|
262
|
+
| `--altitude / --alt / --ele / --elevation` | `<meters>` | `add`,`set` — altitude in meters (may be negative); a comment-kv fact. |
|
|
263
|
+
| `--altitude-type / --alt-type` | <MSL\|AGL> | `add`,`set` — vertical datum for --altitude (default MSL); case-insensitive. |
|
|
264
|
+
| `--gps` | `<lat>`,`<lon>`[,`<altitude>`[,`<altitude-type>`]] | `add`,`set` — combined lat,lon[,altitude[,altitude-type]] convenience (lat-first; missing altitude-type defaults MSL). |
|
|
265
|
+
| `--force` | | `add` only — overwrite the existing (target, user) entry. |
|
|
266
|
+
| `--strict` | | `add`,`set` — reject unknown comment kv keys instead of warning. |
|
|
267
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. |
|
|
268
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
269
|
+
|
|
270
|
+
## discover
|
|
271
|
+
|
|
272
|
+
Discover RouterOS neighbors over MNDP and optionally save them into the CDB.
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
Usage: centrs discover [--timeout 15s] [--save] [flags]
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
| Flag | Value | Description |
|
|
279
|
+
| ---- | ----- | ----------- |
|
|
280
|
+
| `--timeout` | <ms\|15s> | Listen window before results are returned. Default 15s. |
|
|
281
|
+
| `--save` | | Persist discovered neighbors into the CDB (`group=discovered`, `source=mndp`). |
|
|
282
|
+
| `--group` | `<name>` | `--save` group for new entries. Default `discovered`. |
|
|
283
|
+
| `--port` | `<port>` | UDP port to bind for MNDP. Default 5678. |
|
|
284
|
+
| `--cdb-file` | `<path>` | `--save` CDB path override (default `~/.config/tikoci/winbox.cdb`). |
|
|
285
|
+
| `--cdb-password` | `<secret>` | `--save` password for an encrypted CDB. Used to decrypt the existing CDB and re-encrypt on write. |
|
|
286
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. |
|
|
287
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
288
|
+
|
|
289
|
+
## btest
|
|
290
|
+
|
|
291
|
+
Run MikroTik's bandwidth test as a client or server (peer measurement).
|
|
292
|
+
|
|
293
|
+
```text
|
|
294
|
+
Usage: centrs btest <client <router>|server> [flags]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
| Flag | Value | Description |
|
|
298
|
+
| ---- | ----- | ----------- |
|
|
299
|
+
| `--protocol` | <udp\|tcp> | (client) Transport. Default udp. |
|
|
300
|
+
| `--direction` | <receive\|transmit\|both> | (client) Test direction. Default receive. |
|
|
301
|
+
| `--duration` | `<dur>` | Bound the run (e.g. 15s). Omit for open-ended (Ctrl-C). |
|
|
302
|
+
| `--interval` | `<dur>` | Report cadence (20ms..5s). Default 1s. |
|
|
303
|
+
| `--connection-count` | `<n>` | (client, TCP only) Parallel TCP data connections (1..255). |
|
|
304
|
+
| `--local-udp-tx-size` | `<n>` | (client, UDP only) Client→server packet size (28..64000). |
|
|
305
|
+
| `--remote-udp-tx-size` | `<n>` | (client, UDP only) Server→client packet size (28..64000). |
|
|
306
|
+
| `--local-tx-speed` | `<bps>` | (client) Cap on client→server rate (e.g. 100M). |
|
|
307
|
+
| `--remote-tx-speed` | `<bps>` | (client) Cap on server→client rate (e.g. 100M). |
|
|
308
|
+
| `--random-data` | | (client) Incompressible payload. |
|
|
309
|
+
| `--nat-mode` | | (client, UDP only) Originate an outbound datagram first so server→client data can traverse NAT. Automatic when the test receives. |
|
|
310
|
+
| `--authenticate / --no-authenticate` | | (server) Require EC-SRP5 auth. Default true; `--authenticate=false` also accepted. |
|
|
311
|
+
| `--bind` | `<addr>` | (server) Listen address. Default 127.0.0.1. |
|
|
312
|
+
| `--allocate-udp-ports-from` | `<n>` | (server) Base of the UDP data-port range. Default 2001. |
|
|
313
|
+
| `--max-sessions` | `<n>` | (server) Concurrent test cap (1..1000). Default 100. |
|
|
314
|
+
| `--user / --username / -u` | `<name>` | Credential (aliases --username, -u; falls back to CDB / CENTRS_USERNAME). |
|
|
315
|
+
| `--password` | `<secret>` | Credential (falls back to CDB / CENTRS_PASSWORD). |
|
|
316
|
+
| `--port` | `<port>` | Control port. Default 2000. |
|
|
317
|
+
| `--cdb-file` | `<path>` | (client) Read target credentials from a WinBox CDB file. |
|
|
318
|
+
| `--cdb-password` | `<password>` | (client) Decrypt an encrypted WinBox CDB file. |
|
|
319
|
+
| `--format` | <text\|csv\|json\|yaml> | Output format. Default text. |
|
|
320
|
+
| `--csv` | | Shortcut for `--format csv`. |
|
|
321
|
+
|
|
322
|
+
## mcp
|
|
323
|
+
|
|
324
|
+
Start the centrs MCP server (stdio) — scoped RouterOS tools gated by the CDB allowlist.
|
|
325
|
+
|
|
326
|
+
```text
|
|
327
|
+
Usage: centrs mcp [start] [--cdb-file <path>] [--allow-adhoc-targets]
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
| Flag | Value | Description |
|
|
331
|
+
| ---- | ----- | ----------- |
|
|
332
|
+
| `--cdb-file` | `<path>` | CDB allowlist path (default `~/.config/tikoci/winbox.cdb`, or CENTRS_CDB_FILE). |
|
|
333
|
+
| `--cdb-password` | `<password>` | Decrypt password for an encrypted CDB (or CENTRS_CDB_PASSWORD). |
|
|
334
|
+
| `--allow-adhoc-targets` | | Reserved unsafe escape hatch for future inline targets; current tools still use CDB-only targets. |
|
|
335
|
+
| `--help` | | Show this help. |
|
|
336
|
+
|
|
337
|
+
## settings
|
|
338
|
+
|
|
339
|
+
Manage centrs's own global preferences (`centrs.env`) and inspect the `__default__` CDB record.
|
|
340
|
+
|
|
341
|
+
```text
|
|
342
|
+
Usage: centrs settings [print|get|set|reset] [args] [flags]
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
| Flag | Value | Description |
|
|
346
|
+
| ---- | ----- | ----------- |
|
|
347
|
+
| `--all` | | `print` only — also list unrecognized CENTRS_* lines found in the file. |
|
|
348
|
+
| `--cdb-file` | `<path>` | `print` only — CDB to probe for the `__default__` record summary (falls back to normal CDB resolution; never centrs.env). |
|
|
349
|
+
| `--cdb-password` | `<secret>` | `print` only — decrypt password for the probed CDB. |
|
|
350
|
+
| `--skip-env-file` | | `print` only — note that other commands in this environment would not see centrs.env (settings itself always reads the real file). |
|
|
351
|
+
| `--format` | <text\|json\|yaml> | Output format for the CLI response. |
|
|
352
|
+
| `--json` | | Shortcut for `--format json`. |
|
|
353
|
+
| `--help` | | Show this help. |
|
package/docs/CONSTITUTION.md
CHANGED
|
@@ -37,21 +37,29 @@ re-validate-server-side. Validation is not optional polish.
|
|
|
37
37
|
attribute inspection. The path syntax (commas, no leading slash, last token
|
|
38
38
|
is the verb) is part of the validator contract.
|
|
39
39
|
- `execute` and other CLI-shaped calls validate with `:put [:parse "..."]` plus
|
|
40
|
-
a semantic gate.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`:parse` covers both syntax and the
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
40
|
+
a semantic gate. Grounded on CHR 7.23.3 (GH#230), **`:parse` never throws** —
|
|
41
|
+
it returns a script value whose printed form carries the verdict. For a bare
|
|
42
|
+
menu path a clean parse prints `(evl /canonical/path)` with abbreviations
|
|
43
|
+
expanded; for script-shaped input (e.g. `:put …`, `:global …`, `where …`) the
|
|
44
|
+
accepted return echoes the script body and may contain arbitrary text such as
|
|
45
|
+
`expected`. Rejection forms are `(evl bad parameter <name> (line N column M)
|
|
46
|
+
/path)`, `(<%% bad command name <name> (line N column M) …)`, and the
|
|
47
|
+
line-anchored `expected … (line N column M)` (spellings: `expected end of
|
|
48
|
+
command`, `expected command name`, `expected input value`) / `syntax error
|
|
49
|
+
(line N column M)`. That text rides the **HTTP-200 `ret` value** (REST,
|
|
50
|
+
`as-string`), the native `as-string` `ret`, and the console's printed output
|
|
51
|
+
alike — so a single `:put [:parse ...]` covers both the syntax and the
|
|
52
|
+
**unknown-attribute** gate on every transport. centrs sends `as-string` and now
|
|
53
|
+
reads the `ret`/printed value (the previous gate ignored it, so it rejected
|
|
54
|
+
nothing). Because the accepted return echoes the body, the matcher must anchor
|
|
55
|
+
on the diagnostic shape (the `(<%%` wrapper, or a trailing `(line N column M)`)
|
|
56
|
+
and never on a bare English word — `expected` is also a real
|
|
57
|
+
`/ip/firewall/connection` field name.
|
|
58
|
+
That unknown-attribute check is **name-level only**: `:parse` does not validate
|
|
59
|
+
parameter *values* (`/ip/address/add address=not-an-ip` parses clean). So a
|
|
60
|
+
clean parse is necessary, not sufficient, and value-type plus the remaining
|
|
61
|
+
semantic validation stay distinct steps — `/console/inspect` or the server's
|
|
62
|
+
own re-validation on the write round-trip.
|
|
55
63
|
- **Peer-measurement commands (`btest`) are exempt from this gate** — they issue
|
|
56
64
|
no RouterOS command, so they validate *option-grammar* + the **EC-SRP5** auth
|
|
57
65
|
exchange instead (the envelope, identity-resolution, and friendly-error
|
|
@@ -221,24 +229,82 @@ must round-trip through the same envelope.
|
|
|
221
229
|
|
|
222
230
|
One grammar across every non-terminal command. A call selects targets from any
|
|
223
231
|
mix of: `<router>` positionals (one or more), repeatable `--group <name>`,
|
|
224
|
-
`--all` (every CDB record
|
|
225
|
-
repeatable `--where <attr>=<value>` —
|
|
226
|
-
CDB-stored facts/comment-kv
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
232
|
+
`--all` (every CDB record, **excluding** the reserved `__default__` record),
|
|
233
|
+
`--default` (the `__default__` record), and repeatable `--where <attr>=<value>` —
|
|
234
|
+
a **device-class** selector that matches CDB-stored facts/comment-kv **plus core
|
|
235
|
+
record fields** (`target`/`identity`/`group`/`mac`; core fields win so a comment
|
|
236
|
+
token cannot spoof them), AND-combined across repeats. A call is in **fan-out
|
|
237
|
+
mode** when any selector flag is present **or** more than one positional target is
|
|
238
|
+
given; a plain single-positional call stays single-target. The union is
|
|
239
|
+
**de-duped by CDB record index** (ad-hoc literal targets by host) and run through
|
|
240
|
+
the same per-target pipeline.
|
|
241
|
+
|
|
242
|
+
Fan-out output is the locked **`FanoutData`** envelope: `data = { summary, targets[]
|
|
243
|
+
}`, where the outer `ok` reports **orchestration** success and a per-target failure
|
|
244
|
+
is an inner `ok:false` envelope (output, not metadata). `targets[]` is reassembled
|
|
245
|
+
in resolved record order, not completion order, so repeated runs diff cleanly. The
|
|
246
|
+
**process exit code** is granular and uniform across fan-out commands: `0` every
|
|
247
|
+
target ok (or an empty selection), `2` partial (some ok, some failed), `1`
|
|
248
|
+
orchestration error or every target failed.
|
|
249
|
+
|
|
250
|
+
A multi-target **RouterOS write** (e.g. `execute` / `api` add/set/remove across a
|
|
251
|
+
selection) is gated by **`--yes`**, confirmed **once** up front; when it is missing
|
|
252
|
+
the error names the blast radius (how many routers). The separate **`--force`**
|
|
253
|
+
gate is scoped to destructive **`devices` CDB mutations** (e.g. `devices remove`
|
|
254
|
+
across a group), not RouterOS writes. `terminal` and single-session `stream` /
|
|
255
|
+
`api --stream` are not fan-out surfaces and reject N>1 with
|
|
256
|
+
`usage/fanout-not-supported`; `api --raw` is rejected in fan-out mode with
|
|
257
|
+
`usage/conflicting-flags` (it strips the per-target envelope).
|
|
233
258
|
|
|
234
259
|
`--where` filters *which devices* by CDB-stored facts; keep it distinct from
|
|
235
260
|
`retrieve`/`execute`'s `--query`/`--filter`, which filter *RouterOS rows* in the
|
|
236
|
-
response. Two layers, two flag families.
|
|
261
|
+
response. Two layers, two flag families. `--near <lat>,<lon>,<radius>` and
|
|
262
|
+
`--bbox <south>,<west>,<north>,<east>` are geo union predicates over device GPS
|
|
263
|
+
(**lat-first, decimal degrees**; radius units `m`/`km`/`mi`/`ft`, bare = km);
|
|
264
|
+
geo-less devices never match. They join the same union — a device matches when it
|
|
265
|
+
falls in `--near`'s radius **or** `--bbox`.
|
|
237
266
|
|
|
238
267
|
`--group` is purely a **selector** in this grammar; the group *field* is written
|
|
239
268
|
by a distinct `--new-group` flag on `devices add`/`set`, so record selection and
|
|
240
269
|
field-setting never collide on one flag.
|
|
241
270
|
|
|
271
|
+
#### Resolution providers
|
|
272
|
+
|
|
273
|
+
Target resolution has **two independent axes**, and centrs keeps them separate so
|
|
274
|
+
the resolver is generalized **once**, not per source (the umbrella plan is #174):
|
|
275
|
+
|
|
276
|
+
- **Axis A — selection** ("which devices"): the target-selection grammar above.
|
|
277
|
+
- **Axis B — connection-fact origin** ("where host/port/auth for a member come
|
|
278
|
+
from"): what a resolved member yields. Today: a **CDB record** or an ad-hoc
|
|
279
|
+
**literal** (+ the `__default__` ladder). Tomorrow: a live descriptor or an
|
|
280
|
+
inventory entry.
|
|
281
|
+
|
|
282
|
+
Sources fall into two kinds, and the distinction is normative:
|
|
283
|
+
|
|
284
|
+
- **Selector-source** — participates in the Axis-A grammar. **CDB** (now), and
|
|
285
|
+
**TikTOML** next (#137). Multiple selector-sources union into one selection;
|
|
286
|
+
the split-brain precedence between them is #137's problem, not resolved here.
|
|
287
|
+
- **Named-live-provider** — addressed *only* by an explicit named flag, **never**
|
|
288
|
+
matched by a selector; fanned out by repeating the flag. Because it owns an
|
|
289
|
+
**ephemeral** endpoint it also **bypasses** the settings/`__default__` ladder and
|
|
290
|
+
**conflicts** with `--host`/`--port`/`--username`/`--password`/`--ssh-key`. These
|
|
291
|
+
are properties of *live/ephemeral* providers, not of any one provider. **quickchr**
|
|
292
|
+
(`--quickchr <name>`, #134) is the first. A named-live-provider selection is
|
|
293
|
+
**exclusive** (v1): mixing it with `<router>` positionals or selector flags is
|
|
294
|
+
`usage/conflicting-flags` — one flag stays single-target, repeating it fans
|
|
295
|
+
out. Relaxing exclusivity later is additive.
|
|
296
|
+
|
|
297
|
+
Connection facts resolve into one neutral **per-service endpoint map**
|
|
298
|
+
(`src/resolver/service-endpoint.ts`: `via → ServiceEndpoint`, each carrying
|
|
299
|
+
availability, host, port, TLS, auth, and provenance). A **selector-source** is the
|
|
300
|
+
*degenerate single-endpoint* case — one record materialized lazily once `--via` is
|
|
301
|
+
known. A **named-live-provider** populates the map directly, since it genuinely
|
|
302
|
+
exposes different facts per transport. Providers must **not** be flattened to a
|
|
303
|
+
single host/port: that shape is the contract quickchr's descriptor and TikTOML's
|
|
304
|
+
`services` block both map onto, and flattening it forces exactly the re-plumb #174
|
|
305
|
+
exists to prevent. A `--via` whose service key a provider does not supply is a
|
|
306
|
+
typed unsupported-provider error, never a silent fallback.
|
|
307
|
+
|
|
242
308
|
### MCP surface: the CDB is the allowlist
|
|
243
309
|
|
|
244
310
|
The MCP frontend (`commands/mcp/`) is an adapter over this core, not a new set of
|
|
@@ -281,7 +347,11 @@ Rules:
|
|
|
281
347
|
- **Never silently downgrade across `--via`.** If the caller pinned a transport
|
|
282
348
|
that cannot do the operation, error out with a `transport/*` code.
|
|
283
349
|
Auto-selection (no `--via`) may downgrade *within* the table, but every hop is
|
|
284
|
-
reported in `meta.warnings` with its reason.
|
|
350
|
+
reported in `meta.warnings` with its reason. For `api`'s fan-out path, this
|
|
351
|
+
and "Validation is the product" above are also checked structurally by
|
|
352
|
+
CodeQL (`.github/codeql-house-rules/missing-required-gate.ql` —
|
|
353
|
+
`apiFanout` must call `assertApiProtocolSupported`/`validateApiRequestShape`;
|
|
354
|
+
scoped to `apiFanout` only today).
|
|
285
355
|
- **Execute vs retrieve surfaces:** native-api, rest-api, ssh, mac-telnet (and
|
|
286
356
|
later RoMON / WinBox Terminal) are execute surfaces; SNMP is **retrieve-only**.
|
|
287
357
|
mac-telnet is the default execute path for an unresolved-MAC target — IP-level
|
|
@@ -415,3 +485,9 @@ canonicalization only, never the structured-mode predicate. The gate contract,
|
|
|
415
485
|
its pinning test, and the parser-vendoring preconditions are documented in
|
|
416
486
|
`commands/execute/README.md` and the `canonicalizeExecuteCommand` doc-comment
|
|
417
487
|
(`src/execute.ts`).
|
|
488
|
+
|
|
489
|
+
Richer schema-free analysis must distinguish **ambiguous** (multiple plausible
|
|
490
|
+
readings) from **unknown** (no safe reading) and abstain in both cases rather than
|
|
491
|
+
inventing a command, path, symbol class, or transport mapping. These explain-only
|
|
492
|
+
verdicts never widen or reinterpret the execution gate's `mode` or `writeShaped`
|
|
493
|
+
decision.
|