@tikoci/centrs 0.1.3 → 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 +39 -0
- package/GLOSSARY.txt +213 -0
- package/LICENSE +21 -0
- package/README.md +36 -8
- package/commands/AGENTS.md +7 -1
- package/commands/api/README.md +19 -18
- package/commands/api/examples.md +15 -0
- package/commands/btest/README.md +21 -32
- package/commands/check/README.md +6 -1
- package/commands/discover/README.md +5 -11
- package/commands/execute/README.md +41 -29
- package/commands/execute/examples.md +41 -3
- package/commands/explain/README.md +1716 -0
- package/commands/explain/examples.md +606 -0
- package/commands/retrieve/README.md +25 -27
- package/commands/retrieve/examples.md +16 -0
- package/commands/transfer/README.md +28 -20
- package/commands/transfer/examples.md +29 -0
- package/docs/CLI.md +353 -0
- package/docs/CONSTITUTION.md +66 -15
- package/docs/MATRIX.md +38 -1
- package/docs/errors/README.md +3 -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/transport/provider-trust.md +29 -0
- package/docs/errors/usage/stdin-ignored.md +28 -0
- package/docs/errors/validation/unknown-attribute.md +37 -4
- package/package.json +45 -10
- package/src/api-fanout.ts +29 -14
- package/src/api.ts +97 -54
- package/src/cli/api.ts +25 -6
- package/src/cli/btest.ts +18 -2
- package/src/cli/execute.ts +25 -6
- package/src/cli/explain.ts +503 -0
- package/src/cli/retrieve.ts +33 -1
- package/src/cli/selection.ts +71 -11
- package/src/cli/settings.ts +2 -2
- package/src/cli/transfer.ts +23 -6
- package/src/cli.ts +15 -2
- package/src/core/envelope.ts +5 -2
- package/src/core/error-catalog.ts +40 -0
- package/src/core/preflight.ts +306 -0
- package/src/core/routeros-string.ts +24 -0
- package/src/errors.ts +1 -0
- package/src/execute-fanout.ts +29 -14
- package/src/execute.ts +114 -63
- 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 +206 -4
- package/src/protocols/mac-telnet-console.ts +61 -17
- package/src/resolver/facts.ts +1 -1
- package/src/resolver/index.ts +23 -4
- package/src/resolver/quickchr-provider.ts +597 -0
- package/src/resolver/selection.ts +99 -12
- package/src/resolver/service-endpoint.ts +155 -0
- package/src/resolver/target.ts +1 -1
- package/src/retrieve-fanout.ts +26 -12
- package/src/retrieve.ts +81 -18
- package/src/transfer-fanout.ts +42 -25
- package/src/transfer.ts +87 -44
|
@@ -16,11 +16,17 @@ selection**, examples F1–F5). `romon` and `winbox-terminal` remain
|
|
|
16
16
|
- Mirror RouterOS `execute` semantics. Input is a CLI string; output is
|
|
17
17
|
console-shaped text (or structured records for path+verb writes) wrapped in
|
|
18
18
|
the standard envelope. This includes write-shaped add/set/remove.
|
|
19
|
-
- Validation is two-stage (see constitution: validation
|
|
20
|
-
"<cmd>"]`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
- Validation is two-stage (see constitution: validation; grounded on CHR 7.23.3,
|
|
20
|
+
GH#230): a single `:put [:parse "<cmd>"]` covers both the syntax and the
|
|
21
|
+
unknown-attribute (name-level) gate on **every** transport — `:parse` never
|
|
22
|
+
throws; its return value's printed form (`(evl …)` / `(evl bad parameter …)` /
|
|
23
|
+
`(<%% bad command name …)`) is read from the REST/native `ret` *and* the
|
|
24
|
+
console output. That check is necessary, not sufficient: value-type errors pass
|
|
25
|
+
it, and the `/console/inspect` / server re-validation semantic checks are
|
|
26
|
+
separate.
|
|
27
|
+
The outer RouterOS string literal escapes backslash, quote, and dollar so
|
|
28
|
+
validation parses the caller's exact command rather than expanding variables
|
|
29
|
+
in the wrapper.
|
|
24
30
|
- centrs owns the **script-vs-structured gate** (`canonicalizeExecuteCommand` +
|
|
25
31
|
`isWriteShaped` in `src/execute.ts`): it decides which validation runs and
|
|
26
32
|
whether the write-confirm prompt fires. The shared `rosetta`/`lsp-routeros-ts`
|
|
@@ -102,30 +108,31 @@ selection**, examples F1–F5). `romon` and `winbox-terminal` remain
|
|
|
102
108
|
|
|
103
109
|
## Flags
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
Implemented flags are generated from the CLI metadata into
|
|
112
|
+
[`docs/CLI.md` → execute](../../docs/CLI.md#execute); this file does not
|
|
113
|
+
duplicate that table. Behavior notes the generated reference cannot carry:
|
|
114
|
+
|
|
115
|
+
- `--validate` is transport-appropriate but now one gate on every transport —
|
|
116
|
+
a single `:put [:parse ...]` that is read as a value (GH#230): REST/native
|
|
117
|
+
read the `ret` text (HTTP 200 / `as-string`); mac-telnet and ssh read the
|
|
118
|
+
console's printed value.
|
|
119
|
+
- `--format` defaults to `text`; `CENTRS_FORMAT` sets the default.
|
|
120
|
+
- `--quickchr` resolves host/port/auth from the live `@tikoci/quickchr`
|
|
121
|
+
(0.4.5+, optional dependency) descriptor, bypassing CDB/env resolution for
|
|
122
|
+
those fields.
|
|
123
|
+
- `--` — use it when the command contains tokens that would otherwise be
|
|
124
|
+
claimed as centrs flags; otherwise the command must be quoted as a single
|
|
125
|
+
argument. In fan-out, positional targets come BEFORE `--` and the command
|
|
126
|
+
AFTER it (see **Target selection**).
|
|
127
|
+
|
|
128
|
+
### Designed, not implemented
|
|
129
|
+
|
|
130
|
+
Spec-tier flags with no implementation yet — today they fail as unknown flags:
|
|
131
|
+
|
|
132
|
+
| Flag | Designed behavior |
|
|
106
133
|
| ------------------------------- | ------------------------------------------------------------------------------------- |
|
|
107
|
-
| `--via <protocol>` | Pin the transport (`native-api`, `rest-api`, `ssh`, or `mac-telnet`). No silent downgrade. A bare MAC target defaults to `mac-telnet`. |
|
|
108
|
-
| `--host <host\|url>` | Override the resolved host or base URL for the target. |
|
|
109
|
-
| `--port <n>` | Override the resolved management port. |
|
|
110
|
-
| `--username` (alias `--user`, `-u`) / `--password` | RouterOS credentials; fall back to `CENTRS_USERNAME` / `CENTRS_PASSWORD`. |
|
|
111
|
-
| `--ssh-key <path>` | `--via ssh`: explicit private-key path. Falls back to `CENTRS_SSH_KEY` / the ssh-agent. |
|
|
112
|
-
| `--insecure` | Accept a new SSH host key (`--via ssh`) or a self-signed `api-ssl` TLS cert. Default verifies. |
|
|
113
|
-
| `--cdb-file` / `--cdb-password` | Read target credentials from (and decrypt) a WinBox CDB file. |
|
|
114
|
-
| `--resolve <none\|arp>` | Resolve a MAC-address target to an IP via the host ARP cache. Default `none`. |
|
|
115
|
-
| `--timeout <duration>` | Per-request timeout. REST: ≤ 60s; other transports may allow longer. |
|
|
116
|
-
| `--validate[=false]` | Run transport-appropriate preflight validation before execution (default `true`): REST/native use `:parse` + `/console/inspect`; mac-telnet and ssh use a single console `:parse` (covers syntax + unknown-attribute). |
|
|
117
134
|
| `--strict` | Treat any warning on a successful run as an error (`ok: false`, nonzero exit), like `-Werror`. Default is lenient (`ok: true` + `warnings`). |
|
|
118
|
-
| `--
|
|
119
|
-
| `--max-bytes <n>` | Byte budget for the rendered envelope; excess output is truncated with a warning + `meta.truncated` (not an error), matching `retrieve`. (Renamed from `--max-results`.) |
|
|
120
|
-
| `--format <text\|json\|yaml>` | Output format (alias `--json`). Defaults to `text`; `CENTRS_FORMAT` sets the default. |
|
|
121
|
-
| `--group <name>` | Run across every CDB record in WinBox group `<name>`. Repeatable, combinable with `<target>` positionals plus `--where`/`--all`/`--default`; de-duped by record index. See **Target selection**. |
|
|
122
|
-
| `--where <attr>=<value>` | Device-class selector — run across every CDB record whose stored fact/comment-kv matches (e.g. `--where board=RB5009 /system/package/check-for-updates`). Repeatable (AND). See constitution: target selection. |
|
|
123
|
-
| `--all` | Run across every CDB record (excludes the reserved `__default__`). See **Target selection**. |
|
|
124
|
-
| `--default` | Select the reserved `__default__` record. See **Target selection**. |
|
|
125
|
-
| `--near <lat>,<lon>,<radius>` | Geo selector — run across CDB records whose GPS is within the great-circle radius (units `m`/`km`/`mi`/`ft`; bare = km). Lat-first. Union predicate; geo-less devices never match. See **Target selection**. |
|
|
126
|
-
| `--bbox <south>,<west>,<north>,<east>` | Geo selector — run across CDB records whose GPS is inside the lat-first bounding box. Union predicate. See **Target selection**. |
|
|
127
|
-
| `--concurrency <n>` | Max in-flight targets during fan-out (integer ≥ 1). Transport-aware default: `rest-api` 8, others 4. |
|
|
128
|
-
| `--` | End-of-options marker. Every token after `--` is taken as the literal RouterOS command, even flag-shaped ones — e.g. `centrs execute $R -- /interface print where disabled=yes`. In fan-out, positional targets come BEFORE `--` and the command AFTER it (`centrs execute r1 r2 -- /system/reboot`). Use it when the command contains tokens that would otherwise be claimed as centrs flags; otherwise the command must be quoted as a single argument. |
|
|
135
|
+
| `--max-bytes <n>` | Byte budget for the rendered envelope; excess output is truncated with a warning + `meta.truncated` (not an error), matching `retrieve`. (Will replace the implemented `--max-results`, which fails instead of truncating.) |
|
|
129
136
|
|
|
130
137
|
## SSH key selection
|
|
131
138
|
|
|
@@ -174,6 +181,11 @@ many tokens):
|
|
|
174
181
|
- `execute r1 /system/resource/print` — a single positional target with no
|
|
175
182
|
selector stays **single-target** (legacy split: first positional is the target,
|
|
176
183
|
the rest is the command), never `FanoutData`.
|
|
184
|
+
- `execute --quickchr lab /system/resource/print` — the quickchr
|
|
185
|
+
named-live-provider claims the target slots like a selector (positionals are
|
|
186
|
+
the command; no `--` needed). One `--quickchr` stays single-target; repeating
|
|
187
|
+
it fans out; mixing it with positionals or CDB selectors is
|
|
188
|
+
`usage/conflicting-flags` (constitution: resolution providers).
|
|
177
189
|
|
|
178
190
|
Because `execute` is the primary **write** path, a write-shaped fan-out
|
|
179
191
|
(add/set/remove) is gated by **`--yes`**, confirmed **once** up front; without it
|
|
@@ -213,7 +225,7 @@ How it is wired:
|
|
|
213
225
|
`transport/capability-unsupported` (mac-telnet is execute/terminal only).
|
|
214
226
|
- **Validation is one console `:parse`.** Over the console, `:put [:parse "<cmd>"]`
|
|
215
227
|
prints both `syntax error` and `bad parameter <name>`, so a single gate covers
|
|
216
|
-
syntax **and** the unknown-attribute (
|
|
228
|
+
syntax **and** the unknown-attribute (name-level) check — no `/console/inspect`
|
|
217
229
|
table parsing. Maps to `validation/syntax` / `validation/unknown-attribute`,
|
|
218
230
|
same codes as REST/native (see `docs/CONSTITUTION.md`, validation).
|
|
219
231
|
- **Auth (grounded):** MTWEI is required; a stock device offers a 16-byte MD5 salt
|
|
@@ -243,7 +255,7 @@ Protocol selection: an unresolved MAC target auto-selects mac-telnet (covered by
|
|
|
243
255
|
**decided:** `--strict` promotes any warning on an otherwise-successful run to
|
|
244
256
|
`ok: false` (nonzero exit), like `-Werror`; the default stays lenient
|
|
245
257
|
(`ok: true` with the warning in the `warnings` channel). Tracked code
|
|
246
|
-
follow-up; the flag is
|
|
258
|
+
follow-up; the flag is under **Designed, not implemented** above.
|
|
247
259
|
|
|
248
260
|
These are deferred refinements to the already-grounded single-shot envelope,
|
|
249
261
|
not blockers for the `rest-api`/`native-api` cells.
|
|
@@ -62,14 +62,16 @@ The command is a script-shaped console expression, not a slash path plus verb,
|
|
|
62
62
|
so REST must use the `/rest/execute` fallback.
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
centrs execute $R ':put [/system/identity/get name]' --via rest-api --username $U --password $P
|
|
65
|
+
centrs execute $R ':local a true; :if ($a = true) do={:put [/system/identity/get name]}' --via rest-api --username $U --password $P
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
Envelope: `ok: true`, `data` is string-shaped (`data.output` or `data.ret`) and
|
|
69
69
|
contains the CHR identity name, `meta.via=rest-api`, and
|
|
70
70
|
`meta.validation.syntax=true`. `meta.validation.semantic` is absent or marked
|
|
71
71
|
`not-applicable` because `/console/inspect` validates path-shaped commands, not
|
|
72
|
-
arbitrary script expressions.
|
|
72
|
+
arbitrary script expressions. The `$a` variable must survive the validation
|
|
73
|
+
wrapper: if that outer string expands it before `:parse`, this example fails even
|
|
74
|
+
though RouterOS accepts the original command.
|
|
73
75
|
|
|
74
76
|
### 5. Syntax reject from `:put [:parse ...]`
|
|
75
77
|
|
|
@@ -95,7 +97,7 @@ centrs execute $R '/ip/address/add address=198.51.100.11/32 interface=ether1 no-
|
|
|
95
97
|
```
|
|
96
98
|
|
|
97
99
|
Envelope: `ok: false`, `error.code=validation/unknown-attribute`,
|
|
98
|
-
`error.
|
|
100
|
+
`error.context.parameter="no-such-arg"`,
|
|
99
101
|
`meta.validation.syntax=true`, `meta.validation.source=/console/inspect`, and
|
|
100
102
|
no address is added. This example is the product claim: syntax validation and
|
|
101
103
|
semantic validation are separate gates.
|
|
@@ -435,3 +437,39 @@ Envelope: `meta.via=mac-telnet` when `$MAC` is not resolved from CDB and no
|
|
|
435
437
|
`--host`/`--port`). If the caller wants IP-level REST or native API execution,
|
|
436
438
|
they must opt into MAC-to-IP resolution (`--resolve arp` + `--via …`) before
|
|
437
439
|
protocol selection.
|
|
440
|
+
|
|
441
|
+
## quickchr targets (#134)
|
|
442
|
+
|
|
443
|
+
`$NAME` is the machine name of a running quickchr-managed CHR. Host/port/auth
|
|
444
|
+
come from the live descriptor — the CDB, `CENTRS_HOST`-style env, and the
|
|
445
|
+
`__default__` ladder are bypassed for those fields. Covered by
|
|
446
|
+
`test/integration/quickchr-target.test.ts`.
|
|
447
|
+
|
|
448
|
+
### Q1. Run a command on a quickchr target (native API default)
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
centrs execute --quickchr $NAME ':put [/system/identity/get name]' --json
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Envelope: `ok: true`, `meta.via=native-api` (execute's normal default),
|
|
455
|
+
`meta.target.source.kind=provider`, `meta.target.identity=$NAME`.
|
|
456
|
+
|
|
457
|
+
### Q2. A `--via` the descriptor does not forward → `quickchr/unsupported-via`
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
centrs execute --quickchr $NAME ':put 1' --via mac-telnet --json
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Envelope: `ok: false`, `error.code=quickchr/unsupported-via` — quickchr v1
|
|
464
|
+
forwards `rest-api`/`native-api`/`ssh` only; centrs never falls back to another
|
|
465
|
+
transport.
|
|
466
|
+
|
|
467
|
+
### Q3. Repeated `--quickchr` fans out; an unknown machine is an inner failure
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
centrs execute --quickchr $NAME --quickchr no-such-machine -- ':put 1' --json
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Envelope: outer `ok: true`, `data.summary = { total: 2, ok: 1, failed: 1 }`;
|
|
474
|
+
the unknown machine's inner error is `quickchr/machine-not-found`. Exit code 2
|
|
475
|
+
(partial).
|