@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.
Files changed (134) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/GLOSSARY.txt +284 -0
  3. package/LICENSE +21 -0
  4. package/README.md +55 -11
  5. package/SECURITY.md +3 -3
  6. package/commands/AGENTS.md +7 -1
  7. package/commands/api/README.md +46 -27
  8. package/commands/api/examples.md +124 -6
  9. package/commands/btest/README.md +21 -32
  10. package/commands/check/README.md +376 -53
  11. package/commands/check/examples.md +390 -0
  12. package/commands/devices/README.md +177 -37
  13. package/commands/devices/examples.md +148 -0
  14. package/commands/discover/README.md +5 -11
  15. package/commands/execute/README.md +73 -26
  16. package/commands/execute/examples.md +131 -9
  17. package/commands/explain/README.md +1716 -0
  18. package/commands/explain/examples.md +606 -0
  19. package/commands/retrieve/README.md +55 -71
  20. package/commands/retrieve/examples.md +56 -9
  21. package/commands/settings/README.md +286 -22
  22. package/commands/settings/examples.md +408 -0
  23. package/commands/terminal/README.md +6 -0
  24. package/commands/transfer/README.md +57 -19
  25. package/commands/transfer/examples.md +95 -0
  26. package/docs/CLI.md +353 -0
  27. package/docs/CONSTITUTION.md +102 -26
  28. package/docs/MATRIX.md +106 -173
  29. package/docs/errors/README.md +5 -1
  30. package/docs/errors/cdb/empty-selection.md +19 -0
  31. package/docs/errors/input/incomplete-gps.md +9 -0
  32. package/docs/errors/input/invalid-altitude.md +9 -0
  33. package/docs/errors/input/invalid-bbox.md +9 -0
  34. package/docs/errors/input/invalid-coordinate.md +9 -0
  35. package/docs/errors/input/invalid-radius.md +9 -0
  36. package/docs/errors/internal/settings-failed.md +9 -0
  37. package/docs/errors/quickchr/machine-not-found.md +22 -0
  38. package/docs/errors/quickchr/machine-stopped.md +20 -0
  39. package/docs/errors/quickchr/package-unavailable.md +27 -0
  40. package/docs/errors/quickchr/unsupported-via.md +35 -0
  41. package/docs/errors/quickchr/unsupported.md +35 -0
  42. package/docs/errors/routeros/version-unsupported.md +26 -0
  43. package/docs/errors/settings/consequential-value.md +26 -0
  44. package/docs/errors/settings/invalid-boolean.md +21 -3
  45. package/docs/errors/settings/invalid-format.md +18 -3
  46. package/docs/errors/settings/invalid-integer.md +18 -3
  47. package/docs/errors/settings/invalid-timeout.md +20 -3
  48. package/docs/errors/settings/invalid-via.md +22 -3
  49. package/docs/errors/settings/reserved-key.md +29 -0
  50. package/docs/errors/settings/skip-env-file-active.md +25 -0
  51. package/docs/errors/settings/unknown-key.md +25 -0
  52. package/docs/errors/transport/provider-trust.md +29 -0
  53. package/docs/errors/usage/fanout-not-supported.md +16 -0
  54. package/docs/errors/usage/stdin-ignored.md +28 -0
  55. package/docs/errors/validation/unknown-attribute.md +37 -4
  56. package/package.json +49 -14
  57. package/src/api-fanout.ts +469 -0
  58. package/src/api.ts +171 -56
  59. package/src/cli/api.ts +156 -13
  60. package/src/cli/btest.ts +38 -4
  61. package/src/cli/common.ts +11 -0
  62. package/src/cli/devices.ts +235 -6
  63. package/src/cli/discover.ts +3 -1
  64. package/src/cli/execute.ts +129 -9
  65. package/src/cli/explain.ts +503 -0
  66. package/src/cli/mcp.ts +8 -1
  67. package/src/cli/retrieve.ts +167 -90
  68. package/src/cli/selection.ts +260 -0
  69. package/src/cli/settings.ts +286 -0
  70. package/src/cli/terminal.ts +22 -7
  71. package/src/cli/transfer.ts +192 -51
  72. package/src/cli.ts +22 -2
  73. package/src/core/envelope.ts +5 -2
  74. package/src/core/error-catalog.ts +95 -0
  75. package/src/core/fanout.ts +143 -2
  76. package/src/core/preflight.ts +306 -0
  77. package/src/core/routeros-string.ts +24 -0
  78. package/src/devices.ts +212 -20
  79. package/src/discover.ts +7 -2
  80. package/src/errors.ts +1 -0
  81. package/src/execute-fanout.ts +453 -0
  82. package/src/execute.ts +216 -68
  83. package/src/explain/arg-tokens.ts +114 -0
  84. package/src/explain/args.ts +1403 -0
  85. package/src/explain/blocks.ts +132 -0
  86. package/src/explain/brace-slots.ts +143 -0
  87. package/src/explain/brace-tokens.ts +38 -0
  88. package/src/explain/catalog.ts +1345 -0
  89. package/src/explain/coordinates.ts +329 -0
  90. package/src/explain/defects.ts +217 -0
  91. package/src/explain/is-known-menu.ts +17 -0
  92. package/src/explain/menus.ts +664 -0
  93. package/src/explain/operator-tokens.ts +310 -0
  94. package/src/explain/operators.ts +458 -0
  95. package/src/explain/path-tokens.ts +150 -0
  96. package/src/explain/pathresolve.ts +1324 -0
  97. package/src/explain/quoted-string.ts +241 -0
  98. package/src/explain/scope-brace.ts +308 -0
  99. package/src/explain/segment.ts +757 -0
  100. package/src/explain/string-tokens.ts +67 -0
  101. package/src/explain/symbol-values.ts +520 -0
  102. package/src/explain/symbols.ts +1597 -0
  103. package/src/explain/token-ranges.ts +72 -0
  104. package/src/explain/transport.ts +497 -0
  105. package/src/explain/value-tokens.ts +80 -0
  106. package/src/explain/values.ts +357 -0
  107. package/src/explain/verbs.ts +64 -0
  108. package/src/explain/verbsplit.ts +813 -0
  109. package/src/explain/write.ts +815 -0
  110. package/src/explain.ts +2152 -0
  111. package/src/index.ts +307 -1
  112. package/src/mcp/config.ts +12 -2
  113. package/src/mcp/tools.ts +137 -2
  114. package/src/protocols/adapter.ts +38 -18
  115. package/src/protocols/index.ts +11 -5
  116. package/src/protocols/mac-telnet-console.ts +61 -17
  117. package/src/resolver/cdb.ts +10 -2
  118. package/src/resolver/comment-kv.ts +58 -4
  119. package/src/resolver/config-file.ts +136 -0
  120. package/src/resolver/facts.ts +78 -0
  121. package/src/resolver/geo.ts +453 -0
  122. package/src/resolver/index.ts +65 -0
  123. package/src/resolver/mac.ts +12 -3
  124. package/src/resolver/quickchr-provider.ts +597 -0
  125. package/src/resolver/selection.ts +391 -0
  126. package/src/resolver/service-endpoint.ts +155 -0
  127. package/src/resolver/settings.ts +54 -5
  128. package/src/resolver/target.ts +21 -3
  129. package/src/retrieve-fanout.ts +239 -133
  130. package/src/retrieve.ts +120 -25
  131. package/src/settings.ts +1078 -0
  132. package/src/terminal.ts +11 -1
  133. package/src/transfer-fanout.ts +544 -0
  134. package/src/transfer.ts +133 -40
@@ -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
- 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 `settings/invalid-boolean`.
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
- 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 `settings/invalid-format`.
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
- 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 `settings/invalid-integer`.
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
- 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 `settings/invalid-timeout`.
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
- 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 `settings/invalid-via`.
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.
@@ -0,0 +1,25 @@
1
+ # `settings/unknown-key`
2
+
3
+ `settings get`/`set`/`reset` received a token that is not a recognized CENTRS_*-shaped setting.
4
+
5
+ ## Fix
6
+
7
+ `centrs settings get <attr>`, `set <attr> <value>`, and `reset <attr>` all
8
+ normalize the token first — with or without the `CENTRS_` prefix, in
9
+ kebab-case or SCREAMING_SNAKE (`format`, `FORMAT`, `centrs_format`, and
10
+ `CENTRS_FORMAT` all resolve to the same key) — then look it up against the 13
11
+ keys `settings` manages plus the 5 refused keys. This error fires when the
12
+ normalized token matches neither list: a typo, a made-up name, or a
13
+ `CENTRS_*` var no shipped command actually reads (see
14
+ `commands/settings/README.md`, "Not yet wired — exclude from v1", for three
15
+ such names that are deliberately unsupported today).
16
+
17
+ Run `centrs settings print --all` to see every key `settings` recognizes,
18
+ plus any unrecognized `CENTRS_*` lines already present in the file, tagged
19
+ `(unrecognized)` — that second list is the fastest way to spot a typo you
20
+ already wrote into `centrs.env` by hand.
21
+
22
+ This is a different failure from [`settings/reserved-key`](reserved-key.md):
23
+ that error means "this is a real setting, but writing it is off-limits";
24
+ `settings/unknown-key` means the token isn't a setting `centrs` knows about
25
+ at all. See examples 9 and 19 in `commands/settings/examples.md`.
@@ -0,0 +1,29 @@
1
+ # `transport/provider-trust`
2
+
3
+ A warning (not an error): the target came from a named-live-provider
4
+ (`--quickchr <name>`), and centrs relaxed peer verification to use its
5
+ endpoint.
6
+
7
+ ## Why this happens
8
+
9
+ quickchr's descriptor prefers the VM's TLS forwards (`https` / `api-ssl`),
10
+ whose certificate is the CHR's own self-signed one, and its SSH endpoint's
11
+ host key is regenerated per VM. The descriptor carries no trust material, so
12
+ strict verification would reject every quickchr target and force `--insecure`
13
+ ceremony onto every lab call.
14
+
15
+ Instead, centrs treats the endpoint as **trusted by provenance**: quickchr
16
+ vouches for a loopback-forwarded port (`127.0.0.1:<port>`) of a VM the user
17
+ owns, so peer verification is relaxed for exactly that connection — with
18
+ `provider` provenance on `meta.settings.insecure` and this warning on the
19
+ envelope, never silently.
20
+
21
+ ## When to care
22
+
23
+ - If this warning appears on a target you did **not** select with
24
+ `--quickchr`, that is a bug — report it.
25
+ - The relaxation never applies to CDB, literal, or env-resolved targets;
26
+ those still require an explicit `--insecure` (which raises
27
+ [`transport/insecure-trust`](./insecure-trust.md) instead).
28
+
29
+ See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) → Resolution providers.
@@ -0,0 +1,16 @@
1
+ # `usage/fanout-not-supported`
2
+
3
+ The command or mode cannot fan out across multiple targets.
4
+
5
+ ## Fix
6
+
7
+ Some surfaces are single-session by nature and reject a multi-target selection:
8
+
9
+ - `terminal` — an interactive console relay to one device.
10
+ - `api --stream` / `api --listen` — an open-ended native-api follow is a single
11
+ long-lived subscription.
12
+
13
+ Run the command against a single target (one positional, no `--group` / `--where` /
14
+ `--all` / `--default`). To act on a fleet, use a fan-out-capable verb instead
15
+ (`retrieve`, `execute`, `api` without `--stream`, `transfer`). See
16
+ [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) (Target selection).
@@ -0,0 +1,28 @@
1
+ # `usage/stdin-ignored`
2
+
3
+ stdin was redirected but the input came from the positional argument, so
4
+ anything piped in was not analyzed.
5
+
6
+ This is a **warning**, not an error: the analysis ran and its result is exactly
7
+ what the arguments asked for. What the warning reports is that a second possible
8
+ input source was present and lost.
9
+
10
+ ## Fix
11
+
12
+ Name the source you meant:
13
+
14
+ ```bash
15
+ cat script.rsc | centrs explain --file - # analyze stdin
16
+ centrs explain '/ip/route print' # analyze the positional
17
+ ```
18
+
19
+ The live form spells the same thing (`… | centrs explain edge1 --file -`) and is
20
+ already parsed, but it is refused with
21
+ [`usage/not-implemented`](not-implemented.md) until the phase-2 live probes
22
+ land — so it is not a fix you can apply today.
23
+
24
+ `explain` reads ambient stdin only when no positional could be the input, so a
25
+ positional always wins. It cannot check whether the pipe actually carries bytes
26
+ without consuming fd 0, which is why the collision is reported rather than
27
+ resolved. See [`commands/explain/README.md`](https://github.com/tikoci/centrs/blob/main/commands/explain/README.md)
28
+ for the positional grammar.
@@ -1,9 +1,42 @@
1
1
  # `validation/unknown-attribute`
2
2
 
3
- An attribute is not valid for the path/verb per /console/inspect.
3
+ An attribute or argument is not valid for the requested RouterOS operation.
4
+ The validator rejects the request before RouterOS executes it.
5
+
6
+ ## Context keys
7
+
8
+ Context keys vary by validation mechanism. Callers must not assume every key
9
+ below is present on every `validation/unknown-attribute` rejection.
10
+
11
+ | Key | Type | Notes |
12
+ | --- | ---- | ----- |
13
+ | `parameter` | `string` | First offending name. Present on retrieve and inspect-gated rejections, and on console `:parse` when RouterOS reports `bad parameter <name>`. |
14
+ | `requestedAttributes` | `string[]` | Full requested name list. Retrieve and inspect-gated API/execute validation only. |
15
+ | `availableAttributes` | `string[]` | Names exposed for the path/verb. Retrieve and inspect-gated API/execute validation only. |
16
+ | `path` | `string` | Slash-prefixed RouterOS path (for example `/ip/address`). Retrieve and inspect-gated API/execute validation only. |
17
+ | `verb` | `string` | Verb when applicable (`print`, `add`, `set`, …). Inspect-gated API/execute validation only; retrieve is path-only. |
18
+ | `validationSource` | `string` | Validation provenance. Inspect-gated API/execute and console `:parse` only; retrieve does not currently emit it. |
19
+ | `command` | `string` | Original CLI command. Console `:parse` only. |
20
+ | `detail` | `string` | Raw RouterOS parse diagnostic. Console `:parse` only. |
21
+
22
+ Console `:parse` may also put RouterOS' byte location in the top-level
23
+ `error.position` field. On older RouterOS versions, an unknown name can produce
24
+ only a generic syntax diagnostic; that is reported as `validation/syntax`
25
+ because no parameter identity is available.
26
+
27
+ Provenance:
28
+
29
+ - `src/api.ts:988,1033` — REST/native `validateApiRequest` (print vs add/set branches)
30
+ - `src/execute.ts:742` — REST `validateRestExecute`
31
+ - `src/retrieve.ts:233` — REST `retrieve` attribute projection
32
+ - `src/protocols/mac-telnet-console.ts:674` — console `:parse` (`bad parameter <name>`) over mac-telnet/ssh
33
+ - `src/core/routeros-errors.ts:128` — `!trap`/`detail` `unknown parameter <name>` (routeros/unknown-attribute sibling)
4
34
 
5
35
  ## Fix
6
36
 
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 `validation/unknown-attribute`.
37
+ For `retrieve` and inspect-gated API/execute validation, check the name against
38
+ `/console/inspect`; `retrieve --list-attributes` lists the available properties.
39
+ For console `:parse`, compare `context.parameter` with the RouterOS parameters
40
+ for `context.command`; `context.detail` preserves the device's raw diagnostic.
41
+ Use `--validate=false` only when intentionally probing an undocumented RouterOS
42
+ edge.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tikoci/centrs",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "main": "src/index.ts",
5
5
  "module": "src/index.ts",
6
6
  "repository": {
@@ -9,21 +9,22 @@
9
9
  },
10
10
  "homepage": "https://github.com/tikoci/centrs#readme",
11
11
  "bugs": "https://github.com/tikoci/centrs/issues",
12
- "packageManager": "bun@1.3.13",
12
+ "packageManager": "bun@1.3.14",
13
+ "license": "MIT",
13
14
  "devDependencies": {
14
- "@agent-lint/cli": "^0.8.1",
15
- "@biomejs/biome": "2.5.1",
15
+ "@biomejs/biome": "2.5.7",
16
16
  "@secretlint/secretlint-rule-preset-recommend": "^13.0.2",
17
- "@tikoci/quickchr": "^0.4.2",
18
17
  "@types/bun": "^1.3.13",
19
18
  "cloc": "^2.6.0-cloc",
20
19
  "cspell": "^10.0.0",
21
20
  "has-flag": "4.0.0",
22
- "markdownlint-cli2": "^0.22.1",
21
+ "markdownlint-cli2": "^0.23.0",
23
22
  "secretlint": "^13.0.2",
24
23
  "typedoc": "^0.28.19"
25
24
  },
26
- "optionalDependencies": {},
25
+ "optionalDependencies": {
26
+ "@tikoci/quickchr": "^0.4.7"
27
+ },
27
28
  "peerDependencies": {
28
29
  "typescript": "^6.0.3"
29
30
  },
@@ -46,22 +47,24 @@
46
47
  "files": [
47
48
  "src/",
48
49
  "commands/",
50
+ "docs/CLI.md",
49
51
  "docs/CONSTITUTION.md",
50
52
  "docs/MATRIX.md",
51
53
  "docs/errors/",
52
54
  "README.md",
53
55
  "CHANGELOG.md",
54
56
  "SECURITY.md",
57
+ "LICENSE",
55
58
  "GLOSSARY.txt"
56
59
  ],
57
60
  "scripts": {
58
- "ci": "bun run lint && bun run test && bun run build",
59
- "git:pre-commit": "bun run lint",
61
+ "ci": "bun run lint:ci && bun run test && bun run build",
62
+ "git:pre-commit": "bun run lint:git:commit",
60
63
  "git:pre-push": "bun run lint:git:push",
61
64
  "lint": "bun run lint:biome && bun run lint:typecheck",
62
- "lint:git:commit": "bun run lint",
63
- "lint:git:push": "bun run lint:ci && bun run test && bun run build",
64
- "lint:ci": "bun run lint && bun run lint:markdownlint && bun run lint:cspell && bun run lint:secretlint",
65
+ "lint:git:commit": "bun run lint:biome",
66
+ "lint:git:push": "bun run lint:ci",
67
+ "lint:ci": "bun run lint && bun run docs:cli:check && bun run explain:value-census:readme:check && bun run explain:token-census:readme:check && bun run explain:operator-readme:check && bun run lint:markdownlint && bun run lint:cspell && bun run lint:secretlint",
65
68
  "lint:cspell": "cspell lint . --gitignore",
66
69
  "lint:cspell:all": "cspell lint . --no-gitignore",
67
70
  "lint:markdownlint": "markdownlint-cli2 \"**/*.md\" \"!.scratch/**\"",
@@ -70,10 +73,10 @@
70
73
  "lint:biome": "biome check .",
71
74
  "lint:fix": "biome check --write .",
72
75
  "lint:secretlint": "secretlint \"**/*\"",
73
- "lint:agents": "agent-lint scan --stdout",
74
76
  "test": "bun test",
75
77
  "test:smoke": "bun test test/integration/cli-smoke.test.ts",
76
- "test:integration:fast": "bun test test/integration/devices.test.ts",
78
+ "test:integration:fast": "bun test test/integration/devices.test.ts test/integration/settings.test.ts",
79
+ "test:integration:settings": "bun test test/integration/settings.test.ts",
77
80
  "test:integration:smoke": "CENTRS_RUN_FAST_INTEGRATION=1 bun test test/integration/chr-smoke.test.ts",
78
81
  "test:integration": "CENTRS_RUN_FAST_INTEGRATION=1 bun test test/integration/",
79
82
  "test:integration:stable": "CENTRS_CHR_CHANNEL=stable bun run test:integration",
@@ -82,9 +85,41 @@
82
85
  "test:integration:development": "CENTRS_CHR_CHANNEL=development bun run test:integration",
83
86
  "test:ci": "bun test --coverage",
84
87
  "test:all": "bun run test:ci",
88
+ "check:agent": "bun run scripts/agent-check.ts",
89
+ "corpus:fetch": "bun run scripts/corpus-fetch.ts",
85
90
  "build": "bun build src/index.ts src/cli.ts src/mcp.ts src/tui.ts src/webproxy.ts src/protocols/index.ts --outdir dist --target bun",
86
91
  "build:doc:api": "typedoc --out docs/api src/index.ts",
92
+ "docs:cli": "bun run scripts/gen-cli-docs.ts",
93
+ "docs:cli:check": "bun run scripts/gen-cli-docs.ts --check",
87
94
  "docs:errors": "bun run scripts/gen-error-pages.ts",
95
+ "explain:catalog": "bun run scripts/gen-explain-catalog.ts",
96
+ "explain:catalog:check": "bun run scripts/gen-explain-catalog.ts --check",
97
+ "explain:corpus-census": "bun run scripts/explain-corpus-census.ts",
98
+ "explain:highlight-slice": "bun run scripts/explain-highlight-slice.ts",
99
+ "explain:menus": "bun run scripts/gen-explain-menus.ts",
100
+ "explain:operator-census": "bun run scripts/explain-operator-census.ts",
101
+ "explain:operator-census:check": "bun run scripts/explain-operator-census.ts --check",
102
+ "explain:operator-readme": "bun run scripts/explain-operator-slice.ts --readme",
103
+ "explain:operator-readme:check": "bun run scripts/explain-operator-slice.ts --readme --check",
104
+ "explain:operator-slice": "bun run scripts/explain-operator-slice.ts",
105
+ "explain:probe:brace-slots": "bun run scripts/probes/explain-brace-slot-sweep.ts",
106
+ "explain:probe:escapes": "bun run scripts/probes/explain-escape-sweep.ts",
107
+ "explain:probe:highlight-recapture": "bun run scripts/probes/explain-highlight-recapture.ts",
108
+ "explain:probe:operators": "bun run scripts/probes/explain-operator-sweep.ts",
109
+ "explain:probe:symbol-anchors": "bun run scripts/probes/explain-symbol-anchors.ts",
110
+ "explain:probe:symbol-arms-score": "bun run scripts/probes/explain-symbol-arms-score.ts",
111
+ "explain:probe:symbol-bad-sigil-replay": "bun run scripts/probes/explain-symbol-bad-sigil-replay.ts",
112
+ "explain:probe:symbol-classes-replay": "bun run scripts/probes/explain-symbol-classes-replay.ts",
113
+ "explain:probe:version-floors": "bun run scripts/probes/explain-version-floors.ts",
114
+ "explain:menus:check": "bun run scripts/gen-explain-menus.ts --check",
115
+ "explain:value-census": "bun run scripts/explain-value-census.ts",
116
+ "explain:value-census:check": "bun run scripts/explain-value-census.ts --check",
117
+ "explain:value-census:readme": "bun run scripts/explain-value-census.ts --readme",
118
+ "explain:value-census:readme:check": "bun run scripts/explain-value-census.ts --readme --check",
119
+ "explain:token-census": "bun run scripts/explain-token-census.ts",
120
+ "explain:token-census:check": "bun run scripts/explain-token-census.ts --check",
121
+ "explain:token-census:readme": "bun run scripts/explain-token-census.ts --readme",
122
+ "explain:token-census:readme:check": "bun run scripts/explain-token-census.ts --readme --check",
88
123
  "security": "bun run lint:secretlint && bun run lint:markdownlint"
89
124
  },
90
125
  "type": "module",