@tikoci/centrs 0.1.2 → 0.1.3
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 +59 -0
- package/GLOSSARY.txt +71 -0
- package/README.md +24 -8
- package/SECURITY.md +3 -3
- package/commands/api/README.md +27 -9
- package/commands/api/examples.md +109 -6
- package/commands/check/README.md +371 -53
- package/commands/check/examples.md +390 -0
- package/commands/devices/README.md +177 -37
- package/commands/devices/examples.md +148 -0
- package/commands/execute/README.md +39 -4
- package/commands/execute/examples.md +90 -6
- package/commands/retrieve/README.md +36 -50
- package/commands/retrieve/examples.md +40 -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 +32 -2
- package/commands/transfer/examples.md +66 -0
- package/docs/CONSTITUTION.md +36 -11
- package/docs/MATRIX.md +68 -172
- package/docs/errors/README.md +2 -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/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/usage/fanout-not-supported.md +16 -0
- package/package.json +6 -6
- package/src/api-fanout.ts +454 -0
- package/src/api.ts +91 -19
- package/src/cli/api.ts +135 -11
- package/src/cli/btest.ts +20 -2
- 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 +107 -6
- package/src/cli/mcp.ts +8 -1
- package/src/cli/retrieve.ts +135 -90
- package/src/cli/selection.ts +200 -0
- package/src/cli/settings.ts +286 -0
- package/src/cli/terminal.ts +22 -7
- package/src/cli/transfer.ts +171 -47
- package/src/cli.ts +7 -0
- package/src/core/error-catalog.ts +55 -0
- package/src/core/fanout.ts +143 -2
- package/src/devices.ts +212 -20
- package/src/discover.ts +7 -2
- package/src/execute-fanout.ts +438 -0
- package/src/execute.ts +120 -23
- package/src/index.ts +105 -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/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 +46 -0
- package/src/resolver/mac.ts +12 -3
- package/src/resolver/selection.ts +304 -0
- package/src/resolver/settings.ts +54 -5
- package/src/resolver/target.ts +20 -2
- package/src/retrieve-fanout.ts +225 -133
- package/src/retrieve.ts +39 -7
- package/src/settings.ts +1078 -0
- package/src/terminal.ts +11 -1
- package/src/transfer-fanout.ts +527 -0
- package/src/transfer.ts +61 -11
package/docs/MATRIX.md
CHANGED
|
@@ -30,137 +30,62 @@ A cell advances only with the matching evidence in the same change.
|
|
|
30
30
|
| transfer | `CHR-passed` | `CHR-passed` | `CHR-passed` | — | — | — | — | — |
|
|
31
31
|
| devices | — | — | — | — | — | — | — | — |
|
|
32
32
|
| discover | — | — | — | — | — | `CHR-passed` | — | — |
|
|
33
|
-
| check | `
|
|
33
|
+
| check | `designed` | `designed` | `designed` | `designed` | `not-started` | `not-started` | `not-started` | `not-started` |
|
|
34
34
|
| settings | — | — | — | — | — | — | — | — |
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`commands/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
in
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
`transfer` is `CHR-passed` for `rest-api`/`native-api` and for **sftp** (the
|
|
81
|
-
`ssh` column's first method): `src/transfer.ts` + `src/cli/transfer.ts`
|
|
82
|
-
(size/direction-aware method selection, leading-slash normalization, the
|
|
83
|
-
`print`-probe existence guard, `--verify`) over the shared `FileBackend` seam,
|
|
84
|
-
with the SFTP client in `src/protocols/sftp.ts` (host OpenSSH `sftp` subsystem;
|
|
85
|
-
`scp` deferred). `test/integration/transfer.test.ts` is green on real CHR 7.23.1
|
|
86
|
-
(110 assertions): the rest + native round-trip, the native `N1`–`N4` mirror, the
|
|
87
|
-
sftp `S1`–`S5` round-trip, the stdin/stdout forms via the subprocess harness
|
|
88
|
-
(examples 8–10), and example 17 (chunked REST read of an sftp-seeded >60 KB file).
|
|
89
|
-
The method-selection grammar, the SFTP-vs-SCP rationale, the `--verify` behavior
|
|
90
|
-
(sftp trusts the transfer guarantee; rest/native re-read the `/file` size), and the
|
|
91
|
-
deferred `scp`/`fetch`/`ftp` methods are documented in
|
|
92
|
-
`commands/transfer/README.md`.
|
|
93
|
-
|
|
94
|
-
`execute / ssh` is `CHR-passed` (the second SSH consumer): a per-command batch
|
|
95
|
-
client (`SshExecClient` in `src/protocols/ssh.ts` — one `ssh user@host "<cmd>"`
|
|
96
|
-
per command, sharing `sftp.ts`'s host-`ssh` plumbing) behind the `SshExecAdapter`
|
|
97
|
-
console transport (execute-only, like mac-telnet; structured reads/inspect
|
|
98
|
-
unsupported). It reuses the mac-telnet `:put [:parse …]` gate verbatim. Green via
|
|
99
|
-
`test/integration/execute-ssh.test.ts` (S1–S4) + `test/unit/ssh.test.ts`; the
|
|
100
|
-
no-PTY / clean-output / `:parse` wire grounding lives in the `src/protocols/ssh.ts`
|
|
101
|
-
header and `commands/execute/README.md`.
|
|
102
|
-
|
|
103
|
-
`terminal / ssh` is `CHR-passed` (the third and last SSH consumer): it execs the
|
|
104
|
-
host `ssh` with inherited stdio (`buildSshTerminalArgv` in `src/terminal.ts`,
|
|
105
|
-
reusing `sshCommonOptions`) and lets the OS relay RouterOS's already-clean no-PTY
|
|
106
|
-
console — no screen emulation. No `-t` is passed (`-tt` hangs RouterOS);
|
|
107
|
-
`runTerminal` returns `ssh`'s exit code. A host target defaults to ssh, a MAC
|
|
108
|
-
target to mac-telnet. Green via `test/integration/terminal-ssh.test.ts` (TS1/TS2),
|
|
109
|
-
with argv unit-tested in `test/unit/terminal.test.ts`. **All three SSH cells
|
|
110
|
-
(transfer/execute/terminal) are `CHR-passed`.** The no-PTY / exit-code semantics are documented in
|
|
111
|
-
`src/terminal.ts`; the no-multi-line-brace limitation is in
|
|
112
|
-
`commands/terminal/README.md`.
|
|
113
|
-
|
|
114
|
-
`fetch` (centrs-as-HTTP-server + `/tool/fetch`) is a **deferred, explicit-only
|
|
115
|
-
method within the rest-api/native-api cells**, not a grid column — it needs
|
|
116
|
-
inbound reachability (router → centrs) so it is never auto-selected.
|
|
117
|
-
|
|
118
|
-
`settings` is `designed` and transport-less (like `devices`), so its grid row
|
|
119
|
-
stays `—`. `commands/settings/README.md` describes the `centrs.env` + `__default__`
|
|
120
|
-
front-end (interactive first-time setup plus `settings get/set/reset/print`); no
|
|
121
|
-
code yet.
|
|
122
|
-
|
|
123
|
-
### Transport-base readiness (below the command grid)
|
|
36
|
+
## Status pointers
|
|
37
|
+
|
|
38
|
+
Detailed command contracts live in `commands/<name>/README.md`; example evidence
|
|
39
|
+
lives in `commands/<name>/examples.md` and the named integration tests. Keep this
|
|
40
|
+
section short enough that the grid remains the status surface.
|
|
41
|
+
|
|
42
|
+
- `devices` is transport-less, so its row stays `—`; command state is
|
|
43
|
+
`CHR-passed` by fixture-backed integration tests in `test/integration/devices.test.ts`.
|
|
44
|
+
- `settings` is transport-less, so its row stays `—`; command state is
|
|
45
|
+
`CHR-passed` by fixture-backed integration tests in `test/integration/settings.test.ts`.
|
|
46
|
+
- `retrieve`, `api`, `execute`, and `transfer` share the target-selection and
|
|
47
|
+
fan-out contracts from `docs/CONSTITUTION.md`; command-specific boundaries and
|
|
48
|
+
evidence are in their command READMEs and integration tests.
|
|
49
|
+
- There is no `update` command. RouterOS CLI-shaped writes ride `execute`; the
|
|
50
|
+
structured operation surface is `api`.
|
|
51
|
+
- `api --stream` absorbs the former `stream`/`tail` surface; native-api stream
|
|
52
|
+
details are in `commands/api/README.md` and `src/protocols/native-api.ts`.
|
|
53
|
+
- `discover / mndp` is grounded by `commands/discover/README.md`,
|
|
54
|
+
`src/data/mndp.ts`, `src/data/mndp-cache.ts`, and
|
|
55
|
+
`test/integration/discover.test.ts`.
|
|
56
|
+
- `check` is `designed` (`commands/check/README.md`): a reach + health battery
|
|
57
|
+
whose reads ride the execute-capable transports (rest-api/native-api/ssh/
|
|
58
|
+
mac-telnet), so those four cells are `designed`; `snmp` and `romon`/
|
|
59
|
+
`winbox-terminal` stay `not-started`. Its per-host fan-out is the machinery the
|
|
60
|
+
IP-scan discovery (#149) will iterate; the L2-default timing evidence (#136) is
|
|
61
|
+
recorded in the README before the cells advance past `designed`.
|
|
62
|
+
- `transfer / ssh` means the SFTP-backed transfer method. Deferred file-transfer
|
|
63
|
+
methods such as `scp`, `fetch`, and `ftp` are tracked in
|
|
64
|
+
`commands/transfer/README.md`; `fetch` is not a grid column.
|
|
65
|
+
- SSH grounding for `execute` and `terminal` lives in
|
|
66
|
+
`commands/execute/README.md`, `commands/terminal/README.md`,
|
|
67
|
+
`src/protocols/ssh.ts`, `src/protocols/sftp.ts`, and `src/terminal.ts`.
|
|
68
|
+
- MAC-Telnet grounding for `execute` and `terminal` lives in
|
|
69
|
+
`commands/execute/README.md`, `commands/terminal/README.md`, and the
|
|
70
|
+
`src/protocols/mac-telnet*.ts` module headers.
|
|
71
|
+
- Transport wire-format and delivery caveats belong in `src/protocols/*.ts`
|
|
72
|
+
module headers. Do not expand this file with per-packet or per-router findings.
|
|
73
|
+
|
|
74
|
+
Beyond the grid: post-`CHR-passed` hardening, ergonomics, and research work is
|
|
75
|
+
tracked in GitHub issues (`dry-july` and successors). Those issues may point back
|
|
76
|
+
to this matrix for current status, but they are not additional cell states.
|
|
77
|
+
|
|
78
|
+
### Transport-base readiness
|
|
124
79
|
|
|
125
80
|
The grid above tracks command cells. The transports those cells ride are
|
|
126
81
|
implemented and grounded in their `src/protocols/*.ts` **module headers** — the
|
|
127
|
-
single home for wire-format, auth, and delivery facts
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`test/unit/native-api.test.ts`, `test/integration/native-api.test.ts`
|
|
135
|
-
(transport), and `test/integration/native-api-retrieve.test.ts` (command).
|
|
136
|
-
- **mac-telnet** (`src/protocols/mac-telnet.ts` + `mtwei.ts` +
|
|
137
|
-
`mac-telnet-console.ts` + `MacTelnetAdapter` in `adapter.ts`): packet/control
|
|
138
|
-
codec, session state machine, both auth methods (classic MD5 + MTWEI EC-SRP),
|
|
139
|
-
the interactive-console reader, and the UDP datagram transport with route
|
|
140
|
-
discovery. The deep findings — auth (MTWEI-required / MD5-refused /
|
|
141
|
-
`END_AUTH`≠success), console (ANSI terminal-size probe, ~10s prime stall,
|
|
142
|
-
one-time license gate, `:put [:parse]` syntax+semantic gate, silent writes),
|
|
143
|
-
reliability (byte-counter retransmit + empty-ACK keepalive), and the
|
|
144
|
-
real-device UDP-delivery facts (real egress MAC required; broadcast-only reply;
|
|
145
|
-
per-NIC directed-broadcast reach via `discoverMacTelnetRoute`; bind `0.0.0.0`)
|
|
146
|
-
— are documented in those module headers. Two cells are `CHR-passed`:
|
|
147
|
-
- **`execute / mac-telnet`**: `executeEnvelope` (resolver → `MacTelnetAdapter` →
|
|
148
|
-
UDP transport) runs reads, REST-verified writes, and the validation-reject
|
|
149
|
-
path. Green via `test/integration/mac-telnet-console.test.ts` (examples
|
|
150
|
-
19–21); transport/auth alone via `test/integration/mac-telnet.test.ts` (MTWEI
|
|
151
|
-
login + MD5 refusal). Unit: `test/unit/{mtwei,mac-telnet,mac-telnet-console}.test.ts`.
|
|
152
|
-
- **`terminal / mac-telnet`**: the interactive relay over the same console
|
|
153
|
-
reader (`MacTelnetConsole.attachInteractive`), orchestrated in
|
|
154
|
-
`src/terminal.ts` over an injectable `TerminalIo`, reusing the execute
|
|
155
|
-
resolver and the shared `resolveMacTelnetRoute`. Green via
|
|
156
|
-
`test/integration/terminal-mac-telnet.test.ts` (T1–T3) driving the real
|
|
157
|
-
`centrs terminal` binary through the subprocess harness.
|
|
158
|
-
- **Evidence caveat:** the CHR integration runs over the quickchr
|
|
159
|
-
`socket-connect` **L2 bridge** (`test/integration/mactelnet-l2-bridge.ts`), so
|
|
160
|
-
the real `createUdpMacTelnetTransport` egress/broadcast path is *not* exercised
|
|
161
|
-
in CI — the RB1100AHx4 / RouterOS 7.24beta1 real-device run grounded the
|
|
162
|
-
UDP-delivery facts (and caught the synthetic-source-MAC break). A full-TTY
|
|
163
|
-
`terminal` test (real PTY via `script(1)`/node-pty) is likewise deferred.
|
|
82
|
+
single home for wire-format, auth, and delivery facts.
|
|
83
|
+
|
|
84
|
+
| Transport | Status pointer |
|
|
85
|
+
| --------- | -------------- |
|
|
86
|
+
| native-api | Used by `retrieve`, `api`, `execute`, and `transfer`; wire facts in `src/protocols/native-api.ts`. |
|
|
87
|
+
| ssh / sftp | Used by `transfer`, `execute`, and `terminal`; facts in `src/protocols/ssh.ts`, `src/protocols/sftp.ts`, and `src/terminal.ts`. |
|
|
88
|
+
| mac-telnet | Used by `execute` and `terminal`; facts in `src/protocols/mac-telnet.ts`, `src/protocols/mac-telnet-console.ts`, `src/protocols/mtwei.ts`, and `src/protocols/adapter.ts`. |
|
|
164
89
|
|
|
165
90
|
### Frontend surfaces (orthogonal to the command grid)
|
|
166
91
|
|
|
@@ -169,9 +94,9 @@ core and carry their own state, tracked here:
|
|
|
169
94
|
|
|
170
95
|
| Surface | State | Spec | Notes |
|
|
171
96
|
| ------- | ----- | ---- | ----- |
|
|
172
|
-
| ts-api | `CHR-passed` | `src/index.ts` | Root
|
|
97
|
+
| ts-api | `CHR-passed` | `src/index.ts` | Root TypeScript library surface; everything else adapts it. |
|
|
173
98
|
| cli | `coded` | `src/cli/` | `retrieve`/`execute`/`transfer`/`terminal`/`devices`/`discover`/`btest` wired. |
|
|
174
|
-
| mcp | `CHR-passed` | `commands/mcp/` | Scoped-verb stdio MCP server;
|
|
99
|
+
| mcp | `CHR-passed` | `commands/mcp/` | Scoped-verb stdio MCP server; details in `commands/mcp/README.md` and `test/integration/mcp.test.ts`. |
|
|
175
100
|
| tui | `not-started` | `src/tui.ts` | Stub. |
|
|
176
101
|
| proxy | `not-started` | `src/webproxy.ts` | Stub. |
|
|
177
102
|
|
|
@@ -183,46 +108,17 @@ are documented in `commands/mcp/README.md` and `commands/mcp/examples.md`.
|
|
|
183
108
|
|
|
184
109
|
### Peer measurement (`btest`) — orthogonal to the command grid
|
|
185
110
|
|
|
186
|
-
`btest` is the MikroTik
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
from the `:parse` / `/console/inspect` gate. v1 scope (decided with the user):
|
|
190
|
-
**both** client and server, **EC-SRP5 + unauthenticated**, **TCP and UDP** (legacy
|
|
191
|
-
pre-6.43 double-MD5 is out of scope).
|
|
111
|
+
`btest` is the MikroTik bandwidth test (peer measurement, TCP/UDP port 2000),
|
|
112
|
+
not a RouterOS-command transport. It sits outside the command×protocol grid as
|
|
113
|
+
its own capability axis and is exempt from the RouterOS command-validation gate.
|
|
192
114
|
|
|
193
115
|
| Mode | State | Evidence |
|
|
194
116
|
| -------------- | ------------ | -------- |
|
|
195
|
-
| btest / server | `CHR-passed` |
|
|
196
|
-
| btest / client | `CHR-passed` |
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
orchestrator + CLI, and the honest grounding caveat (the server gets direct CHR
|
|
201
|
-
evidence over the QEMU SLIRP gateway `10.0.2.2`; the client gets direct CHR
|
|
202
|
-
evidence over a host→guest `tcp:2000` forward (the forward carries TCP; UDP rides
|
|
203
|
-
the guest→host gateway instead, below); UDP-receive was
|
|
204
|
-
previously a soft smoke test because the SLIRP reverse path was believed to block
|
|
205
|
-
real validation and a `connect()` socket filter was silently dropping all received
|
|
206
|
-
datagrams — RouterOS sends UDP data **from a different source port** than the
|
|
207
|
-
negotiated `serverUdpPort`, so the BSD receive filter rejected every packet;
|
|
208
|
-
fixed by removing `connect()` and addressing sends explicitly, validated against
|
|
209
|
-
a real RouterOS device at 163–203 Mbps receive and 104 Mbps bidirectional, and
|
|
210
|
-
**CI now gates UDP client receive/both** — the server→client return rides the
|
|
211
|
-
guest→host SLIRP gateway (`10.0.2.2:clientUdpPort`), needing no UDP forward and no
|
|
212
|
-
quickchr change (#88 closed; the `connect()` filter fix in #86 is what enabled it);
|
|
213
|
-
TCP
|
|
214
|
-
`connection-count` reaches the server's command packet (#84) and centrs opens the
|
|
215
|
-
negotiated extra TCP data connections — multi-connection **fan-out** (#87),
|
|
216
|
-
grounded byte-for-byte against RouterOS 7.23.1 (secondary join
|
|
217
|
-
`[token:u16 BE][0x02][0 …]`) and CHR-gated for the realized fan-out
|
|
218
|
-
(`activeConnections == count`; no throughput-rise assertion — the SLIRP loopback is
|
|
219
|
-
bandwidth-bound); authenticated sessions stay single-stream (warned); TCP
|
|
220
|
-
`direction=both` demuxes the server's
|
|
221
|
-
interleaved status frames so the client paces its TX from feedback and does not
|
|
222
|
-
starve server→client RX (#85 fixed); the Windows unit tier skips UDP-loopback
|
|
223
|
-
tests (#69); NDJSON is not adopted) are
|
|
224
|
-
documented in `commands/btest/README.md` and the `src/protocols/btest.ts`,
|
|
225
|
-
`src/protocols/btest-session.ts`, and `src/protocols/ec-srp5.ts` module headers.
|
|
117
|
+
| btest / server | `CHR-passed` | `test/integration/btest.test.ts`; details in `commands/btest/README.md`. |
|
|
118
|
+
| btest / client | `CHR-passed` | `test/integration/btest-client.test.ts`; details in `commands/btest/README.md`. |
|
|
119
|
+
|
|
120
|
+
Wire, auth, TCP/UDP, and CI caveats live in `commands/btest/README.md` and the
|
|
121
|
+
`src/protocols/btest*.ts` / `src/protocols/ec-srp5.ts` module headers.
|
|
226
122
|
|
|
227
123
|
## Priority order
|
|
228
124
|
|
|
@@ -230,18 +126,18 @@ Do not start a later item until the earlier cell or dependency checkpoint has
|
|
|
230
126
|
matching evidence. The grid above is the live status; per-item detail lives in
|
|
231
127
|
the linked `commands/<name>/`.
|
|
232
128
|
|
|
233
|
-
1. **retrieve / rest-api** — `CHR-passed
|
|
129
|
+
1. **retrieve / rest-api** — `CHR-passed` (`commands/retrieve/`).
|
|
234
130
|
2. **CDB resolution + metadata overrides** — `CHR-passed` (`commands/devices/`).
|
|
235
|
-
3. **CDB groups +
|
|
236
|
-
4. **execute / native-api + rest-api** — `CHR-passed` (`commands/execute/`).
|
|
131
|
+
3. **CDB groups + fan-out** — `CHR-passed` (`commands/devices/`, fan-out core).
|
|
132
|
+
4. **execute / native-api + rest-api** — `CHR-passed` (`commands/execute/`).
|
|
237
133
|
5. **devices** (CDB mutation + provenance) — `CHR-passed` (`commands/devices/`).
|
|
238
134
|
6. **retrieve / snmp** — `not-started` (future: SNMP OID/MIB reads + MikroTik MIB cache).
|
|
239
|
-
7. **ssh** for transfer/execute/terminal —
|
|
240
|
-
8. **mac-telnet** for execute/terminal — both `CHR-passed
|
|
135
|
+
7. **ssh** for transfer/execute/terminal — all three `CHR-passed`.
|
|
136
|
+
8. **mac-telnet** for execute/terminal — both `CHR-passed`.
|
|
241
137
|
9. **RoMON / WinBox Terminal for execute** — `not-started` (see Open questions).
|
|
242
138
|
10. **discover / mndp** — `CHR-passed` (`commands/discover/`).
|
|
243
|
-
11. **MCP, TUI, proxy** —
|
|
244
|
-
12. **btest (peer measurement)** — server
|
|
139
|
+
11. **MCP, TUI, proxy** — MCP `CHR-passed`; TUI/proxy `not-started`.
|
|
140
|
+
12. **btest (peer measurement)** — server and client both `CHR-passed`.
|
|
245
141
|
|
|
246
142
|
## Open questions (decisions needed before the affected cell can advance)
|
|
247
143
|
|
package/docs/errors/README.md
CHANGED
|
@@ -50,7 +50,8 @@ Codes are slash-namespaced `family/slug`. The families and where they originate:
|
|
|
50
50
|
- `routeros/*` — RouterOS-surfaced faults mapped by the grounded vocabulary in
|
|
51
51
|
`src/core/routeros-errors.ts` (REST `detail` and native-api `!trap`, identical
|
|
52
52
|
on CHR 7.23).
|
|
53
|
-
- `settings/*` — settings/value parsing (`src/resolver/settings.ts`)
|
|
53
|
+
- `settings/*` — settings/value parsing (`src/resolver/settings.ts`) and the
|
|
54
|
+
`centrs settings` command's own registry/refusal rules (`src/settings.ts`).
|
|
54
55
|
- `target/*` — turning a `<router>` into a transport endpoint.
|
|
55
56
|
- `transport/*` — connection, TLS, DNS, and timeout plumbing.
|
|
56
57
|
- `usage/*` — how a command was invoked (arity, conflicting flags, confirmation).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# `cdb/empty-selection`
|
|
2
|
+
|
|
3
|
+
The target selection matched no CDB records.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
A fan-out selection involving `--where` / `--all` / `--default` / positionals (on
|
|
8
|
+
its own or mixed with `--group`) resolved to zero targets. This is reported as a
|
|
9
|
+
warning on an `ok: true` fan-out envelope with `summary { total: 0, ok: 0, failed:
|
|
10
|
+
0 }`, not a hard failure — there was simply nothing to run.
|
|
11
|
+
|
|
12
|
+
A **group-only** empty (bare `--group`, no other selector) is reported as
|
|
13
|
+
[`cdb/empty-group`](empty-group.md) instead, naming the group that matched nothing;
|
|
14
|
+
this page covers every other empty selection.
|
|
15
|
+
|
|
16
|
+
Check the selector: run `centrs devices list` (and `centrs devices groups`) to see
|
|
17
|
+
the registered records, groups, and the facts a `--where <attr>=<value>` can match.
|
|
18
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Target selection) for the
|
|
19
|
+
selector grammar.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `input/incomplete-gps`
|
|
2
|
+
|
|
3
|
+
lat/lon (or a --gps tuple) were not given as a complete pair.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `input/incomplete-gps`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `input/invalid-altitude`
|
|
2
|
+
|
|
3
|
+
The altitude is not a number, or altitude-type is not MSL/AGL.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `input/invalid-altitude`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `input/invalid-bbox`
|
|
2
|
+
|
|
3
|
+
The --bbox is not four lat-first corners with south<=north and west<=east.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `input/invalid-bbox`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `input/invalid-coordinate`
|
|
2
|
+
|
|
3
|
+
The latitude or longitude is not a number in its valid range.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `input/invalid-coordinate`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `input/invalid-radius`
|
|
2
|
+
|
|
3
|
+
The --near radius is not a number with an optional m/km/mi/ft suffix.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `input/invalid-radius`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# `internal/settings-failed`
|
|
2
|
+
|
|
3
|
+
The settings command failed with an unexpected internal error.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
|
|
8
|
+
contract. This stub will be expanded with the typical trigger and remediation
|
|
9
|
+
for `internal/settings-failed`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# `settings/consequential-value`
|
|
2
|
+
|
|
3
|
+
`settings set` accepted a syntactically valid value with a real, non-obvious consequence (e.g. a global --insecure default, or a transfer-via value gated elsewhere).
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
This is a warning, not a failure — the envelope is still `ok: true` and the
|
|
8
|
+
value is written. `centrs settings set` emits it for exactly two keys today
|
|
9
|
+
(the `warn` callback on the matching `SettingsKeyDef` in `src/settings.ts`):
|
|
10
|
+
|
|
11
|
+
- `insecure` set to any truthy spelling (`true`, `yes`, `on`, `1`) makes
|
|
12
|
+
every command run without an explicit `--insecure`/`--no-insecure`
|
|
13
|
+
override trust RouterOS's self-signed TLS certificate or unknown SSH host
|
|
14
|
+
key globally, not just for one invocation. See the `insecure` row in
|
|
15
|
+
`commands/settings/README.md`'s "Known settings keys" table.
|
|
16
|
+
- `transfer-via` set to `ftp` is accepted here — `ftp` is a syntactically
|
|
17
|
+
valid `CENTRS_TRANSFER_VIA` value — but `transfer` still rejects it at
|
|
18
|
+
call time with [`settings/unsafe-protocol-blocked`](unsafe-protocol-blocked.md)
|
|
19
|
+
unless `ALLOW_UNSAFE_PROTOCOLS` also includes `ftp`. The warning exists so
|
|
20
|
+
the write doesn't silently look like it "worked" when the value won't
|
|
21
|
+
actually take effect anywhere else yet.
|
|
22
|
+
|
|
23
|
+
There is nothing to fix in the sense of retrying with different input — the
|
|
24
|
+
value you asked for was written as requested. Run `centrs settings set
|
|
25
|
+
insecure false` or pick a different `transfer-via` value if the consequence
|
|
26
|
+
wasn't intended. See example 24 in `commands/settings/examples.md`.
|
|
@@ -4,6 +4,24 @@ A boolean-like setting received a non-boolean value.
|
|
|
4
4
|
|
|
5
5
|
## Fix
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`centrs settings set <attr> <value>` throws this for the three boolean-typed
|
|
8
|
+
managed keys — `mcp-allow-adhoc`, `validate`, `insecure` — when `<value>`
|
|
9
|
+
isn't one of the spellings the shared parser (`parseBoolean` in
|
|
10
|
+
`src/resolver/settings.ts`) accepts: `true`/`false`, `yes`/`no`, `on`/`off`,
|
|
11
|
+
or `1`/`0`, case-insensitively. Anything else — `maybe`, `2`, an empty
|
|
12
|
+
string — fails with a remediation listing the accepted spellings.
|
|
13
|
+
|
|
14
|
+
This isn't a `settings`-only rule: `parseBoolean` backs every `CENTRS_*`
|
|
15
|
+
boolean setting across the app, so the same error and message shape appears
|
|
16
|
+
whenever any command resolves a boolean env var to an unrecognized value,
|
|
17
|
+
not just through `settings set`.
|
|
18
|
+
|
|
19
|
+
One canonicalization detail worth knowing even though it isn't what triggers
|
|
20
|
+
this error: once a boolean value *does* validate, `settings set` always
|
|
21
|
+
writes the canonical `1` or `0` to `centrs.env`, never `true`/`false` —
|
|
22
|
+
`CENTRS_MCP_ALLOW_ADHOC`'s reader in `src/mcp/config.ts` checks the literal
|
|
23
|
+
string `"1"` rather than reusing `parseBoolean`, so writing `1`/`0`
|
|
24
|
+
uniformly is what satisfies every reader. Retry `set` with one of the
|
|
25
|
+
accepted spellings above; see
|
|
26
|
+
[`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Settings precedence) for how
|
|
27
|
+
this value feeds into the resolver chain.
|
|
@@ -4,6 +4,21 @@ An unsupported output format was requested.
|
|
|
4
4
|
|
|
5
5
|
## Fix
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`centrs settings set format <value>` throws this when `<value>` isn't one of
|
|
8
|
+
`text`, `json`, or `yaml` — the same `{text, json, yaml}` set every
|
|
9
|
+
command's own `--format` flag (and `CENTRS_FORMAT`) validates against
|
|
10
|
+
(`retrieveOutputFormats` and its `execute`/`transfer`/`api` counterparts).
|
|
11
|
+
`centrs settings set format xml` is the canonical trigger; see example 14 in
|
|
12
|
+
`commands/settings/examples.md`. A failed `set` never partially writes — the
|
|
13
|
+
file is unchanged.
|
|
14
|
+
|
|
15
|
+
`format` is the one managed key without a single universal built-in
|
|
16
|
+
default: `retrieve`/`execute`/`transfer` default to `text`, but `api`
|
|
17
|
+
defaults to `json`. Because of that, `centrs settings print`/`get format`
|
|
18
|
+
can't report one scalar default when the key is unset — it reports a
|
|
19
|
+
`perCommandDefault` map (`{ retrieve: "text", execute: "text", transfer:
|
|
20
|
+
"text", api: "json" }`) instead, so this is the one key where "unset" looks
|
|
21
|
+
different in the output shape than every other key.
|
|
22
|
+
|
|
23
|
+
See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Settings precedence) for
|
|
24
|
+
where `format` sits in the resolver chain once a value is set.
|
|
@@ -4,6 +4,21 @@ An integer setting received a non-integer or out-of-range value.
|
|
|
4
4
|
|
|
5
5
|
## Fix
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`centrs settings set max-results <value>` and `centrs settings set port
|
|
8
|
+
<value>` both throw this when `<value>` fails the shared positive-integer
|
|
9
|
+
rule (`resolveOptionalIntegerSetting` in `src/resolver/settings.ts`):
|
|
10
|
+
`Number.isInteger(n) && n > 0`. `0`, negative numbers (`-1`), and
|
|
11
|
+
non-numeric strings (`abc`) are all rejected the same way — `centrs settings
|
|
12
|
+
set max-results 0` is the canonical trigger (example 20 in
|
|
13
|
+
`commands/settings/examples.md`).
|
|
14
|
+
|
|
15
|
+
This validator isn't specific to `settings` — `resolveOptionalIntegerSetting`
|
|
16
|
+
is the shared helper every `CENTRS_*` integer setting resolves through
|
|
17
|
+
(`max-results`, `port`, and any future integer key), so the same code and
|
|
18
|
+
message shape appear whenever an integer env var, CLI flag, or `centrs.env`
|
|
19
|
+
line resolves to a non-positive or non-numeric value anywhere in the app,
|
|
20
|
+
not only through `settings set`.
|
|
21
|
+
|
|
22
|
+
A failed `set` never partially writes; re-run with a positive integer. See
|
|
23
|
+
[`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Settings precedence) for how
|
|
24
|
+
this value feeds into the resolver chain.
|
|
@@ -4,6 +4,23 @@ A timeout setting received an invalid value.
|
|
|
4
4
|
|
|
5
5
|
## Fix
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`centrs settings set timeout <value>` throws this when `<value>` doesn't
|
|
8
|
+
match the shared duration grammar (`parseDuration` in
|
|
9
|
+
`src/resolver/settings.ts`): a bare integer (milliseconds) or an integer
|
|
10
|
+
with a `ms`/`s`/`m` suffix — `500ms`, `5s`, `1m`. Anything else, like
|
|
11
|
+
`not-a-duration` (example 22 in `commands/settings/examples.md`), fails.
|
|
12
|
+
`settings.ts` layers one more rule on top for `timeout` specifically: even a
|
|
13
|
+
syntactically valid duration that parses to `0` is rejected — a zero timeout
|
|
14
|
+
isn't a meaningful value to set.
|
|
15
|
+
|
|
16
|
+
Like the other typed-value codes here, this isn't `settings`-exclusive:
|
|
17
|
+
`parseDuration` backs `CENTRS_TIMEOUT` and every command's own `--timeout`
|
|
18
|
+
flag, so the same failure shape shows up anywhere a duration string is
|
|
19
|
+
resolved, not just through `settings set`.
|
|
20
|
+
|
|
21
|
+
One write detail worth knowing: `settings set timeout` writes the
|
|
22
|
+
**canonical parsed milliseconds**, not the raw suffixed string you typed —
|
|
23
|
+
`centrs settings set timeout 5s` writes `CENTRS_TIMEOUT=5000` to
|
|
24
|
+
`centrs.env`, not `CENTRS_TIMEOUT=5s`. See
|
|
25
|
+
[`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Settings precedence) for how
|
|
26
|
+
this value feeds into the resolver chain.
|
|
@@ -4,6 +4,25 @@ An unsupported protocol identifier was supplied to --via.
|
|
|
4
4
|
|
|
5
5
|
## Fix
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
This one code covers two different value sets, because `settings` reuses it
|
|
8
|
+
for two different keys. `centrs settings set via <value>` requires one of
|
|
9
|
+
the protocol identifiers in `plannedProtocols` (`src/protocols/index.ts`):
|
|
10
|
+
`rest-api`, `native-api`, `ssh`, `snmp`, `mndp`, `mac-telnet`, `romon`,
|
|
11
|
+
`winbox-terminal` — `centrs settings set via carrier-pigeon` is the
|
|
12
|
+
canonical trigger (example 21 in `commands/settings/examples.md`).
|
|
13
|
+
`centrs settings set transfer-via <value>` reuses the same error code but
|
|
14
|
+
validates against a completely different set: `auto`, `rest`/`rest-api`,
|
|
15
|
+
`native`/`native-api`, `sftp`, `scp`, `fetch`, `ftp`. Unlike `CENTRS_VIA`,
|
|
16
|
+
which has a per-device `via=` comment-kv counterpart, `CENTRS_TRANSFER_VIA`
|
|
17
|
+
has none — `transfer` reads only the env var.
|
|
18
|
+
|
|
19
|
+
The same validation backs `retrieve`/`execute`/`api`'s own `--via` flag more
|
|
20
|
+
broadly, so the identical code and message shape appear there too, not only
|
|
21
|
+
through `settings set`.
|
|
22
|
+
|
|
23
|
+
`transfer-via ftp` is syntactically valid against the `transfer-via` set
|
|
24
|
+
above — it does **not** trigger this error — but it does trigger a separate
|
|
25
|
+
warning, [`settings/consequential-value`](consequential-value.md), because
|
|
26
|
+
`transfer` still rejects `ftp` at call time unless `ALLOW_UNSAFE_PROTOCOLS`
|
|
27
|
+
also opts in. See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Protocol
|
|
28
|
+
selection) for the full `via` vocabulary.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# `settings/reserved-key`
|
|
2
|
+
|
|
3
|
+
`settings set`/`reset` refused a credential-shaped or self-referential CENTRS_* key.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
`centrs settings set <attr> <value>` and `centrs settings reset <attr>` refuse
|
|
8
|
+
five keys outright: `password`, `username`, `cdb-password`, `skip-env-file`,
|
|
9
|
+
and `run-fast-integration` (the `settingsRefusedKeys` list in
|
|
10
|
+
`src/settings.ts`). Each is refused for a different reason, not a blanket
|
|
11
|
+
policy: `password`/`username` are credential-shaped and belong on the
|
|
12
|
+
`__default__` CDB record — run `centrs devices add __default__ --user …
|
|
13
|
+
--password …` instead of duplicating a secret into a second, unencrypted
|
|
14
|
+
file. `cdb-password` is the CDB's own decrypt password; writing it beside the
|
|
15
|
+
encrypted CDB it unlocks would defeat the encryption, so pass
|
|
16
|
+
`--cdb-password` per invocation or export `CENTRS_CDB_PASSWORD` in the
|
|
17
|
+
calling shell instead. `skip-env-file` is self-referential — a line in
|
|
18
|
+
`centrs.env` that says "ignore this file" is a no-op by construction, since
|
|
19
|
+
the file has to be read to find it. `run-fast-integration` is a CI/test
|
|
20
|
+
signal `bun run test:integration` sets, never a human preference.
|
|
21
|
+
|
|
22
|
+
`settings get`/`settings print` still work read-only on all five keys — this
|
|
23
|
+
error is specific to the write path (`set`/`reset`). A read of `cdb-password`
|
|
24
|
+
or `password` redacts the value rather than refusing outright; see
|
|
25
|
+
[`settings/unknown-key`](unknown-key.md) for the different case of a token
|
|
26
|
+
that isn't a recognized setting at all. See examples 17 and 29 in
|
|
27
|
+
`commands/settings/examples.md`, and
|
|
28
|
+
[`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Identity and CDB) for why
|
|
29
|
+
credentials route through `devices` rather than `centrs.env`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# `settings/skip-env-file-active`
|
|
2
|
+
|
|
3
|
+
`settings print` ran under --skip-env-file; the shown centrs.env values would not apply to other commands run in the same environment.
|
|
4
|
+
|
|
5
|
+
## Fix
|
|
6
|
+
|
|
7
|
+
This is an informational warning, not a failure — `centrs settings print`
|
|
8
|
+
still returns `ok: true` with the file's real contents. It appears only when
|
|
9
|
+
`--skip-env-file` (or `CENTRS_SKIP_ENV_FILE`) was active on that same
|
|
10
|
+
`print` invocation, as a reminder that the flag doesn't apply to `settings`
|
|
11
|
+
itself: `settings` always reads and writes the real `centrs.env` file
|
|
12
|
+
regardless of `--skip-env-file`, since inspecting/editing the file is this
|
|
13
|
+
command's whole job (see the module doc comment at the top of
|
|
14
|
+
`src/settings.ts`).
|
|
15
|
+
|
|
16
|
+
What the warning is actually flagging is every *other* command: if
|
|
17
|
+
`--skip-env-file`/`CENTRS_SKIP_ENV_FILE` is also active when you run
|
|
18
|
+
`retrieve`/`execute`/`transfer`/`api` in that same shell or environment,
|
|
19
|
+
those commands' resolvers skip loading `centrs.env` as a settings source —
|
|
20
|
+
so the values `print` just showed you would not apply there. There's
|
|
21
|
+
nothing to fix; either drop `--skip-env-file` if you want other commands to
|
|
22
|
+
see these values, or ignore the warning if the isolation is intentional. See
|
|
23
|
+
example 6 in `commands/settings/examples.md`, and
|
|
24
|
+
[`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Settings precedence) for how
|
|
25
|
+
the config tier fits into the precedence ladder.
|