@tikoci/centrs 0.1.0

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 (182) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/GLOSSARY.txt +420 -0
  3. package/README.md +196 -0
  4. package/SECURITY.md +30 -0
  5. package/commands/AGENTS.md +50 -0
  6. package/commands/btest/README.md +257 -0
  7. package/commands/btest/examples.md +190 -0
  8. package/commands/check/README.md +59 -0
  9. package/commands/devices/README.md +405 -0
  10. package/commands/devices/examples.md +488 -0
  11. package/commands/discover/README.md +170 -0
  12. package/commands/discover/examples.md +98 -0
  13. package/commands/execute/README.md +208 -0
  14. package/commands/execute/examples.md +353 -0
  15. package/commands/mcp/README.md +260 -0
  16. package/commands/mcp/examples.md +158 -0
  17. package/commands/retrieve/README.md +209 -0
  18. package/commands/retrieve/examples.md +306 -0
  19. package/commands/settings/README.md +69 -0
  20. package/commands/stream/README.md +70 -0
  21. package/commands/terminal/README.md +177 -0
  22. package/commands/terminal/examples.md +144 -0
  23. package/commands/transfer/README.md +315 -0
  24. package/commands/transfer/examples.md +368 -0
  25. package/docs/CONSTITUTION.md +417 -0
  26. package/docs/MATRIX.md +224 -0
  27. package/docs/errors/README.md +74 -0
  28. package/docs/errors/auth/failed.md +9 -0
  29. package/docs/errors/cdb/already-exists.md +9 -0
  30. package/docs/errors/cdb/created.md +9 -0
  31. package/docs/errors/cdb/decrypt-failed.md +9 -0
  32. package/docs/errors/cdb/empty-group.md +9 -0
  33. package/docs/errors/cdb/invalid-option.md +9 -0
  34. package/docs/errors/cdb/invalid-record.md +9 -0
  35. package/docs/errors/cdb/not-found-target.md +9 -0
  36. package/docs/errors/cdb/not-found.md +9 -0
  37. package/docs/errors/cdb/override-applied.md +9 -0
  38. package/docs/errors/cdb/parse-failed.md +9 -0
  39. package/docs/errors/cdb/password-not-needed.md +9 -0
  40. package/docs/errors/cdb/password-required.md +9 -0
  41. package/docs/errors/cdb/reserved-key.md +9 -0
  42. package/docs/errors/cdb/reserved-option.md +9 -0
  43. package/docs/errors/cdb/target-not-registered.md +9 -0
  44. package/docs/errors/cdb/unknown-field.md +9 -0
  45. package/docs/errors/cdb/unknown-option.md +9 -0
  46. package/docs/errors/cdb/write-not-permitted.md +9 -0
  47. package/docs/errors/discover/broadcast-unavailable.md +9 -0
  48. package/docs/errors/discover/failed.md +9 -0
  49. package/docs/errors/identity/ambiguous.md +9 -0
  50. package/docs/errors/identity/no-match.md +9 -0
  51. package/docs/errors/input/invalid-command.md +9 -0
  52. package/docs/errors/input/invalid-match.md +9 -0
  53. package/docs/errors/input/invalid-path.md +9 -0
  54. package/docs/errors/input/invalid-routeros-path.md +9 -0
  55. package/docs/errors/input/invalid-target.md +9 -0
  56. package/docs/errors/input/local-file-not-found.md +9 -0
  57. package/docs/errors/input/mac-address.md +9 -0
  58. package/docs/errors/input/max-results-exceeded.md +9 -0
  59. package/docs/errors/internal/devices-failed.md +9 -0
  60. package/docs/errors/internal/mcp-start.md +9 -0
  61. package/docs/errors/internal/mcp-tool.md +9 -0
  62. package/docs/errors/internal/native-api-length.md +9 -0
  63. package/docs/errors/internal/unhandled.md +9 -0
  64. package/docs/errors/internal/unreachable.md +9 -0
  65. package/docs/errors/mndp/encode-failed.md +9 -0
  66. package/docs/errors/mndp/listen-failed.md +9 -0
  67. package/docs/errors/mndp/malformed.md +9 -0
  68. package/docs/errors/routeros/api-fatal.md +9 -0
  69. package/docs/errors/routeros/api-protocol.md +9 -0
  70. package/docs/errors/routeros/api-trap.md +9 -0
  71. package/docs/errors/routeros/btest-protocol.md +12 -0
  72. package/docs/errors/routeros/btest-too-many-sessions.md +9 -0
  73. package/docs/errors/routeros/command-failed.md +14 -0
  74. package/docs/errors/routeros/ec-srp5-protocol.md +11 -0
  75. package/docs/errors/routeros/error.md +9 -0
  76. package/docs/errors/routeros/invalid-value.md +14 -0
  77. package/docs/errors/routeros/mac-telnet-error.md +9 -0
  78. package/docs/errors/routeros/mac-telnet-not-ready.md +9 -0
  79. package/docs/errors/routeros/mac-telnet-protocol.md +9 -0
  80. package/docs/errors/routeros/mac-telnet-unsupported-auth.md +9 -0
  81. package/docs/errors/routeros/protocol-not-implemented.md +9 -0
  82. package/docs/errors/routeros/request-failed.md +9 -0
  83. package/docs/errors/routeros/session-closed.md +13 -0
  84. package/docs/errors/routeros/unknown-attribute.md +13 -0
  85. package/docs/errors/routeros/unknown-path.md +15 -0
  86. package/docs/errors/routeros/unsupported-capability.md +9 -0
  87. package/docs/errors/settings/invalid-boolean.md +9 -0
  88. package/docs/errors/settings/invalid-format.md +9 -0
  89. package/docs/errors/settings/invalid-integer.md +9 -0
  90. package/docs/errors/settings/invalid-timeout.md +9 -0
  91. package/docs/errors/settings/invalid-via.md +9 -0
  92. package/docs/errors/settings/unsafe-protocol-blocked.md +9 -0
  93. package/docs/errors/target/mac-not-in-arp.md +14 -0
  94. package/docs/errors/target/mac-required.md +23 -0
  95. package/docs/errors/target/mac-unresolved.md +17 -0
  96. package/docs/errors/target/unresolved.md +9 -0
  97. package/docs/errors/transport/auth-failed.md +9 -0
  98. package/docs/errors/transport/auto-method.md +9 -0
  99. package/docs/errors/transport/capability-unsupported.md +22 -0
  100. package/docs/errors/transport/checksum-unavailable.md +9 -0
  101. package/docs/errors/transport/connection-closed.md +9 -0
  102. package/docs/errors/transport/connection-refused.md +9 -0
  103. package/docs/errors/transport/dns.md +9 -0
  104. package/docs/errors/transport/host-key-mismatch.md +9 -0
  105. package/docs/errors/transport/incomplete-transfer.md +9 -0
  106. package/docs/errors/transport/insecure-trust.md +9 -0
  107. package/docs/errors/transport/local-tool-missing.md +11 -0
  108. package/docs/errors/transport/network.md +9 -0
  109. package/docs/errors/transport/timeout.md +9 -0
  110. package/docs/errors/transport/tls-certificate.md +9 -0
  111. package/docs/errors/transport/unreachable.md +9 -0
  112. package/docs/errors/transport/unsupported-operation.md +9 -0
  113. package/docs/errors/usage/confirmation-required.md +9 -0
  114. package/docs/errors/usage/conflicting-flags.md +9 -0
  115. package/docs/errors/usage/invalid-concurrency.md +9 -0
  116. package/docs/errors/usage/missing-group.md +9 -0
  117. package/docs/errors/usage/not-implemented.md +9 -0
  118. package/docs/errors/usage/target-exists.md +9 -0
  119. package/docs/errors/usage/timeout-out-of-range.md +9 -0
  120. package/docs/errors/validation/not-implemented.md +9 -0
  121. package/docs/errors/validation/option.md +9 -0
  122. package/docs/errors/validation/syntax.md +9 -0
  123. package/docs/errors/validation/unknown-attribute.md +9 -0
  124. package/docs/errors/validation/unknown-path.md +9 -0
  125. package/package.json +96 -0
  126. package/src/AGENTS.md +7 -0
  127. package/src/btest.ts +906 -0
  128. package/src/cli/btest.ts +455 -0
  129. package/src/cli/common.ts +53 -0
  130. package/src/cli/devices.ts +527 -0
  131. package/src/cli/discover.ts +186 -0
  132. package/src/cli/execute.ts +333 -0
  133. package/src/cli/mcp.ts +109 -0
  134. package/src/cli/retrieve.ts +383 -0
  135. package/src/cli/terminal.ts +303 -0
  136. package/src/cli/transfer.ts +471 -0
  137. package/src/cli.ts +115 -0
  138. package/src/core/envelope.ts +221 -0
  139. package/src/core/error-catalog.ts +469 -0
  140. package/src/core/routeros-errors.ts +268 -0
  141. package/src/data/AGENTS.md +11 -0
  142. package/src/data/dude-db.ts +0 -0
  143. package/src/data/mndp-cache.ts +132 -0
  144. package/src/data/mndp.ts +405 -0
  145. package/src/data/winbox-cdb-write.ts +200 -0
  146. package/src/data/winbox-cdb.ts +913 -0
  147. package/src/devices-schema.ts +107 -0
  148. package/src/devices.ts +1717 -0
  149. package/src/discover.ts +802 -0
  150. package/src/errors.ts +189 -0
  151. package/src/execute.ts +1350 -0
  152. package/src/index.ts +353 -0
  153. package/src/mcp/config.ts +66 -0
  154. package/src/mcp/resources.ts +98 -0
  155. package/src/mcp/safety.ts +119 -0
  156. package/src/mcp/server.ts +225 -0
  157. package/src/mcp/tools.ts +657 -0
  158. package/src/mcp.ts +33 -0
  159. package/src/protocols/AGENTS.md +14 -0
  160. package/src/protocols/adapter.ts +866 -0
  161. package/src/protocols/btest-session.ts +1493 -0
  162. package/src/protocols/btest.ts +447 -0
  163. package/src/protocols/ec-srp5.ts +466 -0
  164. package/src/protocols/index.ts +118 -0
  165. package/src/protocols/mac-telnet-console.ts +655 -0
  166. package/src/protocols/mac-telnet.ts +1299 -0
  167. package/src/protocols/mtwei.ts +47 -0
  168. package/src/protocols/native-api.ts +796 -0
  169. package/src/protocols/sftp.ts +427 -0
  170. package/src/protocols/ssh.ts +297 -0
  171. package/src/resolver/cdb.ts +580 -0
  172. package/src/resolver/comment-kv.ts +360 -0
  173. package/src/resolver/index.ts +74 -0
  174. package/src/resolver/mac.ts +227 -0
  175. package/src/resolver/settings.ts +228 -0
  176. package/src/resolver/target.ts +442 -0
  177. package/src/retrieve-fanout.ts +533 -0
  178. package/src/retrieve.ts +1215 -0
  179. package/src/terminal.ts +444 -0
  180. package/src/transfer.ts +1554 -0
  181. package/src/tui.ts +22 -0
  182. package/src/webproxy.ts +16 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,207 @@
1
+ # Changelog
2
+
3
+ All notable changes to this repository should be recorded here.
4
+
5
+ The product evolves as a stream of changes; there are no alpha gates.
6
+ Per-feature status is tracked in `docs/MATRIX.md`. Use this file for
7
+ documenting cross-cutting shifts that affect contributors and consumers.
8
+
9
+ ## Unreleased
10
+
11
+ ## 0.1.0 — 2026-06-22
12
+
13
+ First published pre-release (odd minor → npm `next`). `@tikoci/centrs@0.1.0`.
14
+
15
+ ### Added
16
+
17
+ - **`btest / client` is now `CHR-passed`.** A direct centrs-client → CHR
18
+ `/tool/bandwidth-server` gated test (`test/integration/btest-client.test.ts`)
19
+ boots a CHR with a host→guest `tcp:2000` forward and runs the centrs client
20
+ against real RouterOS: unauthenticated TCP receive, an **EC-SRP5 client proof
21
+ verified by RouterOS's own server verifier**, and a wrong-password reject (CHR
22
+ 7.23.1). This closes the last open product-grid cell — the client cell was
23
+ previously grounded only transitively (loopback + the server test). The
24
+ integration harness (`test/integration/chr.ts`) gains an `extraPorts` option for
25
+ arbitrary host→guest forwards. UDP client→server and TCP `connection-count > 1`
26
+ fan-out remain loopback/transitive (README, Open questions).
27
+ - **CI/release rework — staged gate, definitive QA matrix, NPM publish, extended
28
+ sweep.** The CI surface is reconciled with the tier/versioning doctrine
29
+ (quickchr's `ci`/`publish`/`verify-extended` scheme as the reference).
30
+ `ci.yaml` is a staged push/PR gate (lint ‖ unit+coverage → **stable CHR smoke**
31
+ → cross-platform unit) with coverage + failing tests surfaced to job summaries
32
+ and artifacts. `qa.yaml` is the definitive RouterOS channel matrix (push +
33
+ weekly + dispatch + `workflow_call`) with **event-aware concurrency** (a new
34
+ main push cancels the old run; dispatches never cancel one another — including
35
+ an `all`-channels dispatch in a single run) and a `bun:sqlite` results store.
36
+ `codeql.yaml` carries security/quality scanning on its own cadence.
37
+ `release.yaml` publishes to npm on a `v*` tag (even/odd minor → `next`/`latest`,
38
+ `--provenance`, dry-run) — **requires the `NPM_TOKEN` repo secret**.
39
+ `verify-extended.yaml` adds a dispatch-only macOS-x86 / Windows-x86 sweep. New
40
+ `chr-smoke` integration test + `test:integration:smoke` script; `.coderabbit.yaml`
41
+ stages bot review to conserve credits.
42
+ - **QA recency-aware channel matrix + cross-run history + must-pass gate.**
43
+ `qa.yaml`'s channel axis is now resolved per run by a `resolve-matrix` pre-flight
44
+ job (`scripts/qa-active-channels.ts`) instead of a hard-coded list: it asks
45
+ quickchr 0.4.2's public version/channel API (`resolveAllVersions` /
46
+ `selectActiveChannels`, with the suffix-aware `compareRouterOsVersion` that
47
+ finally orders `7.24beta2 < 7.24rc1 < 7.24`) for the channels *worth booting* —
48
+ the released channels (stable, long-term) always, plus any pre-release (testing,
49
+ development) at or ahead of stable. This closes the `testing` blind spot and
50
+ auto-adapts as MikroTik promotes builds, because the four channels are not
51
+ monotonically ordered (a stale `testing` rc is skipped; it is picked up
52
+ automatically once it leapfrogs stable). A new `accumulate-and-gate` job appends
53
+ each CHR run to a durable append-log on the `qa-history` branch (per-run
54
+ artifacts have finite retention, and the channel→version drift over time is
55
+ what a long history captures) and fails the run **only when a released
56
+ channel (stable, long-term) regresses** — pre-release legs are best-effort, so a
57
+ beta btest/EC-SRP5 flake (JG-31) is recorded but never reds main. Boundary:
58
+ quickchr owns recency ("what's worth booting"); centrs owns the gate ("what must
59
+ pass") — the must-pass policy lives once in `scripts/qa-results-db.ts`
60
+ (`channelPolicy` / `evaluateMustPassGate`, mirrored by the matrix
61
+ `continue-on-error`), with the cross-run accumulator in `scripts/qa-history.ts`.
62
+ - **`transfer / ssh` (sftp) — SSH lands transfer-first.** SSH joins centrs as a
63
+ self-contained **SFTP transfer client** (`src/protocols/sftp.ts`) over the host
64
+ OpenSSH `sftp` subsystem — the only reliable SSH file path, since RouterOS's SSH
65
+ server has no exec channel / no pseudo-tty (so `execute`/`terminal` over SSH,
66
+ which need an interactive-shell reader, are a deliberate later pass). This
67
+ re-scopes the earlier "SSH lands as one unit" plan. `transfer` now routes
68
+ `--via sftp` (and auto-selects it for >60 KB uploads, the gap the REST `/file`
69
+ 60 KB write cap leaves) through a new backend-agnostic `FileBackend` seam
70
+ (`AdapterFileBackend` for rest/native, `SftpFileBackend` for sftp). The
71
+ `ssh-key` (`--ssh-key` / `CENTRS_SSH_KEY` / CDB `ssh-key=`) and `insecure`
72
+ settings land with the transport. **Green against real CHR 7.23.1** (98
73
+ assertions, `test/integration/transfer.test.ts`): a key-auth sftp round-trip,
74
+ the >60 KB upload, list/mkdir/remove, and example 17 (chunked REST read of an
75
+ sftp-seeded file — the old fetch hack is gone). **CHR finding:** RouterOS's sftp
76
+ `ls -l` does not report a reliable byte size, so the sftp `--verify size` trusts
77
+ the SFTP transfer guarantee rather than re-reading a size. New error codes:
78
+ `transport/host-key-mismatch`, `transport/insecure-trust`,
79
+ `transport/auto-method`, `input/invalid-path`. On-device `copy` has no SFTP
80
+ primitive and stays on rest/native.
81
+ - **Unified TLS / SSH host-key trust across every transport.** One opt-out —
82
+ `--insecure` (`CENTRS_INSECURE`, CDB `insecure=`) — with verify-by-default and a
83
+ `transport/insecure-trust` warning when it is set. REST (`fetch`) and native-api
84
+ (`api-ssl`) now both **verify** TLS by default (native-api previously accepted
85
+ any cert silently); a self-signed cert fails with `transport/tls-certificate`
86
+ whose remediation names `--insecure`. SSH host keys default to
87
+ `accept-new` trust-on-first-use; a changed key fails with
88
+ `transport/host-key-mismatch`. See `docs/CONSTITUTION.md`, Transport trust.
89
+
90
+ - **`transfer` is `coded` for `rest-api` / `native-api`.** `src/transfer.ts` +
91
+ `src/cli/transfer.ts` implement the file verb — `upload`/`download`/`list`/
92
+ `remove`/`mkdir`/`copy` (plus top-level `upload`/`download` aliases) — over the
93
+ RouterOS `/file` menu, driven through the shared `ProtocolAdapter`
94
+ `execute`/`list` seam so REST and native share one path. Size/direction-aware
95
+ method selection encodes the asymmetric `/file` plumbing (writes capped at
96
+ 60 KB via `/file/set contents`; reads scale via chunked `/file/read`), a
97
+ `print`-probe enforces validate-before-write (refuse-overwrite unless
98
+ `--force`), a leading `/` in a remote path is normalized away, and
99
+ `sftp`/`scp`/`fetch`/`ftp` report a defined not-implemented / gated error.
100
+ Unit-green via mocked `fetch` (`test/unit/transfer.test.ts`).
101
+ `test/integration/transfer.test.ts` is green against a real CHR 7.23.1 (98
102
+ assertions, after the sftp commit below also seeds example 17) — confirming the
103
+ `/file` `get`/`set`/`add`/`copy`/`remove` wire shapes over both REST and native
104
+ — covering all examples except the three deferred for harness reasons (8–10
105
+ stdin/stdout/default-local), so the cells stay `coded` shy of the strict
106
+ every-example `CHR-passed` bar. New error codes: `usage/target-exists`,
107
+ `transport/incomplete-transfer`, `transport/checksum-unavailable`,
108
+ `input/local-file-not-found`, `settings/unsafe-protocol-blocked`.
109
+ - **`discover / mndp` is `CHR-passed`.** A real layer-2 integration test
110
+ (`test/integration/discover.test.ts`) boots a CHR with a second
111
+ `socket-connect` NIC and a host bridge (`test/integration/mndp-l2-bridge.ts`)
112
+ that lifts each frame's UDP/5678 payload into centrs's unmodified `discover()`
113
+ listener and injects MNDP refresh frames back over the link. It captures and
114
+ decodes a genuine RouterOS MNDP announcement (CHR 7.23.1), cross-checks
115
+ `identity`/`platform`/`board`/`version`/`mac` against REST, and `--save`s a
116
+ `macTarget`/`group=discovered` record. The `socket-connect` approach was first
117
+ proven against quickchr's own `examples/mndp/` guinea-pig run. The same bridge
118
+ (frame-injection write-back) is the L2 harness mac-telnet will reuse.
119
+ - **Integration CHR can now boot a chosen arch + extra packages.**
120
+ `startIntegrationChr` reads `CENTRS_CHR_ARCH` (`arm64`/`x86`) and
121
+ `CENTRS_CHR_PACKAGES` (comma/space list) and threads them through quickchr
122
+ 0.4.2's `StartOptions`; `verify-extended.yaml` gains a `packages` input that
123
+ installs them into the CHR (e.g. `container`) for a fuller-RouterOS sweep. The
124
+ arm64 path is wired on the centrs side but no arm64 job is added yet: quickchr
125
+ 0.4.2 has an arm64 REST-POST bug (returns the prior GET's body) that breaks the
126
+ execute path every integration test uses, so an arm64 job would be known-red
127
+ until that upstream fix lands.
128
+
129
+ ### Fixed
130
+
131
+ - **`package.json` declares its `repository` (and `homepage`/`bugs`).** Without it,
132
+ `npm publish --provenance` failed validation (`E422`: empty `repository.url` vs
133
+ the GitHub-Actions provenance source). The package now points at
134
+ `github.com/tikoci/centrs`, matching the signed provenance.
135
+ - **Flaky must-pass CHR cells no longer red the release gate.** The first
136
+ `v0.1.0` release sweep was blocked by transient long-term failures (native-api
137
+ `ECONNREFUSED`, mac-telnet L2 prime-latency) — the same cells pass locally and
138
+ the reds hop channels run-to-run, i.e. CI timing flake, not regressions. Two
139
+ fixes: (1) the native-api integration test now `waitForBoot`s and retries the
140
+ cold connect past the boot-readiness race (the api service can lag the REST
141
+ endpoint), via a `withBootReadyRetry` harness helper that retries **only**
142
+ transient connect errors — `auth-failed` still propagates, so assertions are
143
+ unweakened; (2) the qa.yaml CHR sweep runs integration **per-file with one
144
+ retry** — a real regression fails both attempts and still gates, but a single
145
+ transient flake is absorbed, and per-file isolation avoids the resource
146
+ contention that fast-fails a later file.
147
+ - **`windows-latest` unit tier is green.** It was perpetually red on two causes,
148
+ now both addressed without losing coverage: (1) Windows has no `SO_REUSEPORT`,
149
+ so the MNDP/btest UDP loopback binds (`reusePort: true`) threw `ENOTSUP` — a
150
+ capability probe (`test/unit/udp-loopback.ts`) now skips just those UDP tests on
151
+ such a runner (TCP + CHR integration keep the coverage), gating only on the
152
+ known-unsupported bind codes so real regressions still surface; (2) the
153
+ `ssh`/`sftp` argv tests asserted `/dev/null` where the src correctly emits `NUL`
154
+ on Windows, and `transfer.basename()` split on `/` only so an omitted upload
155
+ remote defaulted to the full `C:\…` path — it now splits on `\` too.
156
+
157
+ - **`btest` bidirectional TCP server tx is now accounted.** A `direction=both`
158
+ TCP session reported `totalTxBytes=0` / `txAvgBps=0` on the server side even
159
+ though it transmitted the client's receive half (hundreds of MB): the server's
160
+ bulk-TX loop flushed only its rx into each interval, never its own tx. The
161
+ server now records both halves, so a `both` session's `data.sessions[]` and the
162
+ CSV/text renders carry a non-zero tx rate. Loopback-grounded
163
+ (`test/unit/btest-{session,command}.test.ts`); UDP `both` and single-direction
164
+ TCP were already correct.
165
+ - **`btest` totals now flush the final partial interval.** The per-interval
166
+ accounting loops recorded totals on a tick cadence and exited without folding in
167
+ bytes that arrived after the last tick (or before the first, on a slow host), so
168
+ a short run under-reported the final fraction of a second of each direction.
169
+ `driveSession` now folds the remaining counter bytes into the totals on stop,
170
+ keeping `data.reports[]` lossless against them.
171
+ - **`discover` default listen window is now `15s`** (was `60s` in code).
172
+ Lowering the window relied on the up-front refresh broadcast (sent immediately,
173
+ then every 5s) so responders reply within a round-trip; the per-command docs
174
+ already documented `15s`, but `DISCOVER_DEFAULT_TIMEOUT_MS`, the CLI help, and
175
+ the MCP `centrs_discover` tool description still said `60s`. They now agree.
176
+
177
+ ### Changed
178
+
179
+ - **`release.yaml` fails closed when `NPM_TOKEN` is missing.** A guard step in the
180
+ publish job errors with an actionable message if `secrets.NPM_TOKEN` does not
181
+ reach the runner (whether a repo secret or a tikoci org secret with centrs in
182
+ its repository access) — so a dry-run dispatch proves it before any real
183
+ publish, instead of failing opaquely inside `npm publish`. The value stays
184
+ masked; only its presence is logged.
185
+ - **Workflow restructure.** Replaced `docs/specs/`, `docs/WORKFLOW.md`,
186
+ `docs/ROADMAP.md`, `docs/ARCHITECTURE.md`, and `work/` with three durable
187
+ surfaces:
188
+ - `docs/CONSTITUTION.md` — the load-bearing rules (validation as product,
189
+ result envelope, error model + URL scheme, settings precedence, identity,
190
+ protocol selection, done = CHR-passed).
191
+ - `docs/MATRIX.md` — command×protocol grid; the only status surface.
192
+ - `commands/<name>/{README,examples}.md` — per-command design and
193
+ executable example list that gates "done."
194
+ - Done definition codified in
195
+ `.github/instructions/done-definition.instructions.md`: a feature is done
196
+ when its examples are green on real CHR via `bun run test:integration`.
197
+ Disabling validation to make a test pass is forbidden; validation is the
198
+ product.
199
+
200
+ ### Removed
201
+
202
+ - `docs/specs/S001`–`S008`, `docs/WORKFLOW.md`, `docs/ROADMAP.md`,
203
+ `docs/ARCHITECTURE.md`, all of `work/`, and the
204
+ `docs-specs-lifecycle` / `work-directory` / `integration-testing`
205
+ instruction files. Their durable content folded into the constitution and
206
+ per-command files; the rest was scaffolding for a workflow that did not
207
+ pay off.
package/GLOSSARY.txt ADDED
@@ -0,0 +1,420 @@
1
+ # Project glossary and cspell dictionary
2
+ #
3
+ # This file is the shared source of truth for project vocabulary, short term
4
+ # definitions, and cspell dictionary entries.
5
+ #
6
+ # `%term` in prompts or notes means "look up the matching entry or comment here."
7
+ #
8
+ # CSpell dictionary syntax supported here:
9
+ # - `~word` => use the word only when case sensitivity is off
10
+ # - `+word` or `word+` => allow optional compounds
11
+ # - `-word` or `word-` => require the word to appear in a compound
12
+ # - `!word` => explicitly forbid the word
13
+ #
14
+ # Correctly spelled words may still belong here when the attached comment is the
15
+ # canonical repo-specific definition or reference for the term.
16
+ #
17
+ # Core tikoci references
18
+ # %centrs: this repository and RouterOS interaction hub.
19
+ # https://github.com/tikoci/centrs
20
+ # %quickchr: CHR automation and test helpers used by tikoci projects.
21
+ # https://github.com/tikoci/quickchr
22
+ # %rosetta: RouterOS docs/search grounding and knowledge-base tooling.
23
+ # https://github.com/tikoci/rosetta
24
+ # %restraml: RouterOS REST schema and explorer tooling.
25
+ # https://github.com/tikoci/restraml
26
+ # %lsp-routeros-ts: RouterOS parser and language-server utilities.
27
+ # https://github.com/tikoci/lsp-routeros-ts
28
+ # %donny: Dude/discovery grounding for RouterOS device inventories.
29
+ # https://github.com/tikoci/donny
30
+ # %m2ir: protocol IR (WinBox, nova messages) + the declarative schema-as-data
31
+ # approach to protocol internals; consulted for heavy protocol work.
32
+ # https://github.com/tikoci/m2ir
33
+ # %tikbook: RouterOS notebook/documentation vocabulary used across tikoci.
34
+ # See also https://github.com/tikoci/vscode-tikbook
35
+ # %routeros-skills: reusable RouterOS agent skills.
36
+ # https://github.com/tikoci/routeros-skills
37
+ # %fat-chr: larger CHR image experiments and packaging.
38
+ # https://github.com/tikoci/fat-chr
39
+ # %mikropkl: MikroTik-oriented PKL experiments and schemas.
40
+ # https://github.com/tikoci/mikropkl
41
+ # %tikdns: tikoci DNS tooling.
42
+ # https://github.com/tikoci/tikdns
43
+ #
44
+ # External references
45
+ # %mac-telnet: MikroTik MAC Telnet tooling by haakonnessjoen.
46
+ # https://github.com/haakonnessjoen/mac-telnet
47
+ # %netmiko: multi-vendor SSH abstraction; reference for SSH transport patterns.
48
+ # https://github.com/ktbyers/netmiko
49
+ # %terraform-provider-routeros: widely-used Go RouterOS provider; reference for
50
+ # native-API behavior and provisioning idioms.
51
+ # https://github.com/terraform-routeros/terraform-provider-routeros
52
+ # %librouteros-api: haakonnessjoen's C native-API client; cross-check for our
53
+ # native-api codec.
54
+ # https://github.com/haakonnessjoen/librouteros-api
55
+ # %RouterOS_Tools: third-party WinBox CDB format implementation; cross-check for
56
+ # our CDB codec.
57
+ # https://github.com/jabb3rd/RouterOS_Tools
58
+ # %Winbox_Protocol_Dissector: Wireshark dissector for the WinBox protocol
59
+ # (incl. RoMON proxy); grounding for future WinBox-terminal/RoMON work.
60
+ # https://github.com/Cisco-Talos/Winbox_Protocol_Dissector
61
+ # %btest-opensource: open btest.exe (bandwidth-test) client; possible `check`
62
+ # feature grounding. https://github.com/samm-git/btest-opensource
63
+ Addrs
64
+ ajv
65
+ amazonq
66
+ amm
67
+ AT-SPI
68
+ awk
69
+ axuielement
70
+ backpressure
71
+ bak
72
+ bjjj
73
+ btest.exe # Mikrotik /tool/bandwidth-test client for windows
74
+ bunfig
75
+ bunx
76
+ canonicalizer
77
+ CDB
78
+ CDP
79
+ centrs
80
+ ciphertext
81
+ cli
82
+ cloc
83
+ cmp
84
+ connectionrefused
85
+ cpus
86
+ crossref
87
+ cwd
88
+ datagram
89
+ davidanson
90
+ DDNS
91
+ defconf
92
+ dogtail
93
+ donny
94
+ dotenv
95
+ DSL # domain specific language
96
+ eai
97
+ env
98
+ esbuild
99
+ ETL
100
+ eventtap
101
+ EVP
102
+ execa
103
+ fanout
104
+ fat-chr
105
+ figcaption
106
+ FlaUI
107
+ frontends
108
+ haakonnessjoen
109
+ Hammerspoon
110
+ HMAC
111
+ hostfwd
112
+ IPC # inter-process communications
113
+ iscsi
114
+ jabb3rd
115
+ kbd
116
+ KDF
117
+ keystream
118
+ KSA
119
+ KVM
120
+ LDTP
121
+ librouteros # <https://github.com/haakonnessjoen/librouteros-api>
122
+ LLDP
123
+ lsp-routeros-ts
124
+ macping
125
+ mactelnet
126
+ mactelnetd
127
+ MCP
128
+ MIB
129
+ mikropkl
130
+ MikroTik
131
+ MNDP
132
+ NAND # NAND flash memory; write-back caches file writes up to ~40s on some MikroTik boards
133
+ netmiko # [Multi-vendor library to simplify Paramiko SSH connections to network devices](https://github.com/ktbyers/netmiko)
134
+ netwatch
135
+ npk # MikroTik package format
136
+ nvme-over-tcp # supported by RouterOS **with** rose-storage.npk extra-package
137
+ OID
138
+ PII # Personally Identifiable Information
139
+ POV
140
+ PRGA
141
+ proplist
142
+ pywinauto
143
+ QML
144
+ qmljsdebugger
145
+ quickchr
146
+ RAML
147
+ readcdb
148
+ remotehub
149
+ restraml
150
+ romon
151
+ ros
152
+ rosetta
153
+ routeros
154
+ routeros-skills
155
+ rsc # RouterOS script / export file extension (.rsc)
156
+ scp
157
+ scriptability
158
+ scriptable
159
+ Sikuli
160
+ SikuliX
161
+ skillcheck
162
+ SNMP
163
+ SPI
164
+ SRP
165
+ strawman
166
+ subarray
167
+ tcode
168
+ tcodes
169
+ TCG # QEMU Tiny Code Generator software emulation backend.
170
+ terminal-over-winbox # [Pure Python implementation of the MikroTik WinBox terminal protocol — encrypted CLI access to RouterOS devices over TCP port 8291](https://github.com/subixonfire/winbox-terminal-protocol)
171
+ tgz
172
+ tikbook
173
+ tikdns
174
+ tikoci
175
+ TIKOCI
176
+ tiktui
177
+ TLV
178
+ traceroute
179
+ tsc
180
+ tzsp
181
+ TZSP
182
+ UDP
183
+ UIA
184
+ uvx
185
+ vcs
186
+ venv
187
+ vite
188
+ vitest
189
+ viw2
190
+ vrf
191
+ webproxy
192
+ WinAppDriver
193
+ winbox
194
+ Wireshark
195
+ workstreams
196
+ XCUI
197
+ XDG
198
+ YYYYMMDDX
199
+ zod
200
+
201
+ redactable
202
+ specced
203
+ TTL
204
+
205
+ # MAC-Telnet and native-api protocol vocabulary
206
+ # Wire-format terms from MikroTik MAC-Telnet (Håkon Nessjøen's reference
207
+ # implementation) and the RouterOS binary API.
208
+ ack
209
+ acks
210
+ beginauth
211
+ clienttype
212
+ cptype
213
+ datagrams
214
+ fromserver
215
+ Håkon
216
+ mtwei
217
+ Nessjøen
218
+ passsalt
219
+ plaindata
220
+ ptype
221
+ seskey
222
+ sessionstart
223
+
224
+ # QEMU/host networking vocabulary (mac-telnet L2 investigation)
225
+ BPF
226
+ libpcap
227
+ mcast
228
+ netdev
229
+ netdevs
230
+ NIC
231
+ SLIRP
232
+ vmnet
233
+ # feth: macOS fake-ethernet interface; sysfs: Linux /sys pseudo-filesystem —
234
+ # both read by resolveEgressMac's virtual-NIC MAC fallback (src/protocols/mac-telnet.ts).
235
+ feth
236
+ sysfs
237
+
238
+ # CI workflow shell vocabulary (.github/workflows/*.yaml step scripts)
239
+ # pipefail: `set -eo pipefail` so a tee'd `bun test` failure isn't masked;
240
+ # endgroup: GitHub `::endgroup::` log fold; funcs/gsub/img: coverage-parse and
241
+ # CHR-image terms in the gate's summary + coverage-threshold steps;
242
+ # worktree: the git worktree the qa.yaml accumulate-and-gate job uses for the
243
+ # durable qa-history append-log branch.
244
+ endgroup
245
+ funcs
246
+ gsub
247
+ img
248
+ pipefail
249
+ worktree
250
+ # HVF: macOS Hypervisor.framework (x86 CHR acceleration on Intel Macs in
251
+ # verify-extended); choco: Chocolatey, the Windows package manager (QEMU install).
252
+ HVF
253
+ choco
254
+ # CodeRabbit review bot (.coderabbit.yaml); @coderabbitai is the on-demand handle.
255
+ coderabbit
256
+ coderabbitai
257
+
258
+ # centrs domain vocabulary
259
+ # %identity: the device /system/identity; a centrs CDB comment *lookup key*
260
+ # (`identity=`) used to resolve `<router>`. Human handle, deliberately may
261
+ # repeat across records; collisions resolve via `identity/ambiguous` + --match.
262
+ # %tips: top-level envelope channel `tips[]` for advice that is explicitly not an
263
+ # error or warning (no username set, no CDB found). Shape `{ code, message,
264
+ # fix? }` with `tip/*` codes. See docs/CONSTITUTION.md (Result envelope).
265
+ # %__default__: reserved CDB record (`target=__default__`) supplying fallback
266
+ # creds/metadata. Precedence args → env → device record → __default__ →
267
+ # built-in. Core (CLI/API/MCP); never widens the MCP allowlist.
268
+ neteng
269
+ upsert
270
+ upserts
271
+ upserted
272
+ duplicative
273
+ passwordless
274
+
275
+ # MNDP discovery vocabulary (WP-2b)
276
+ tlvs
277
+ noaddr
278
+ Hac
279
+ HnD
280
+ EADDRINUSE
281
+ EACCES
282
+ ENOTSUP
283
+ EAFNOSUPPORT
284
+ ECONNREFUSED
285
+ ECONNRESET
286
+ REUSEPORT
287
+ REUSEADDR
288
+ # L2 bridge frame-parsing terms (test/integration/mndp-l2-bridge.ts):
289
+ # ethertype: 16-bit EtherType field in an Ethernet frame (0x0800 = IPv4).
290
+ ethertype
291
+ # ihl: IPv4 Internet Header Length (low nibble of the first byte, in 32-bit words).
292
+ ihl
293
+ # PIIX: Intel PCI-ISA bridge chipset QEMU emulates; shows up in CHR's REST board-name.
294
+ PIIX
295
+
296
+ # Test-router and host-ARP vocabulary (centrs CLI fixes)
297
+ # bigdude: a live test router (MAC 96:5D:80:7D:BF:59) used to ground fixes.
298
+ bigdude
299
+ ifscope
300
+ macvlan
301
+ unpadded
302
+
303
+ # RouterOS CLI canonicalization vocabulary
304
+ subshell
305
+ disambiguator
306
+
307
+ # centrs MCP surface vocabulary
308
+ # blackhole: a RouterOS route type / bare flag used as the bench parser-truth example.
309
+ blackhole
310
+ readback
311
+ creds
312
+ # Streamable: the MCP Streamable HTTP transport.
313
+ Streamable
314
+ # modelcontextprotocol: npm scope of the MCP SDK (@modelcontextprotocol/sdk).
315
+ modelcontextprotocol
316
+ # WIP: work in progress (used for the upstream MikroTik Docusaurus docs site).
317
+ WIP
318
+ # adhoc: future inline host+credential targets; Phase 1 MCP uses CDB-only targets.
319
+ adhoc
320
+ # nonexistentattr: a deliberately invalid RouterOS attribute used to exercise the validate dual-gate.
321
+ nonexistentattr
322
+ # underflow: reading past the end of a buffer; the WinBox CDB codec reports it as a structured parse fault.
323
+ underflow
324
+ underflows
325
+
326
+ # Werror: the gcc/clang -Werror "treat warnings as errors" flag, referenced by execute --strict.
327
+ Werror
328
+
329
+ # MTWEI / EC-SRP vocabulary (src/protocols/mtwei.ts, mac-telnet auth)
330
+ # docrypto: mtwei.c's client EC-SRP proof function (mtwei_docrypto), ported to TS.
331
+ docrypto
332
+ # redp: REDP1 (IEEE P1363.2) random-point derivation used in the MTWEI tangle.
333
+ redp
334
+ keypair
335
+ # mul: camelCase fragment from scalarMul (EC scalar multiplication).
336
+ mul
337
+ # weier: camelCase fragment from xWeier (a Weierstrass-form X coordinate).
338
+ weier
339
+ # LSB: least-significant bit (Y-parity in compressed EC point encoding).
340
+ lsb
341
+ # NUL: the 0x00 byte separating username and pubkey in the MTWEI offer.
342
+ nul
343
+ # keepalive: empty-ACK idle keepalive for a held-open MAC-Telnet session.
344
+ keepalive
345
+ # eths: local var for the /interface/ethernet record list in the CHR test.
346
+ eths
347
+
348
+ # MAC-Telnet interactive-console vocabulary (src/protocols/mac-telnet-console.ts)
349
+ # DSR: ANSI Device Status Report (ESC[6n cursor-position query) the console sends.
350
+ DSR
351
+ # DECID: ANSI "identify terminal" escape (ESC Z) the console also sends.
352
+ DECID
353
+ # CSI: ANSI Control Sequence Introducer (ESC[) — the escape family we strip.
354
+ CSI
355
+ # SIGWINCH: terminal-resize signal; an interactive terminal re-reports its size on it.
356
+ SIGWINCH
357
+ # evl: RouterOS :parse renders a parsed command as "(evl ...)" on the console.
358
+ evl
359
+ # unconfigured: a freshly-flashed RouterOS device with no IP — the mac-telnet use case.
360
+ unconfigured
361
+ unwired
362
+
363
+ # MAC-Telnet reliability vocabulary (MacTelnetSession.tick: retransmit + keepalive)
364
+ # unacked: an outbound frame not yet acknowledged by the peer's byte-counter ACK.
365
+ unacked
366
+ # retransmittable: a frame (SESSIONSTART/DATA) the session resends until acked.
367
+ retransmittable
368
+ # clockless: the session keeps no real timer; tick(now) supplies time deltas.
369
+ clockless
370
+ # keepalives: plural of keepalive (empty-ACK idle frames).
371
+ keepalives
372
+
373
+ # btest / bandwidth-test vocabulary (commands/btest, src/protocols/btest.ts)
374
+ # btest: MikroTik bandwidth test peer protocol (TCP/UDP 2000); /tool/bandwidth-test
375
+ # + /tool/bandwidth-server. centrs's "measure" capability axis.
376
+ btest
377
+ # goodput: application-level TCP throughput (excludes TCP/IP headers + retransmits),
378
+ # how RouterOS accounts the TCP bandwidth test.
379
+ goodput
380
+ # Weierstrass: the short-Weierstrass curve form of Curve25519 used by MikroTik
381
+ # EC-SRP5 (shared with mac-telnet MTWEI; see src/protocols/mtwei.ts / ec-srp5.ts).
382
+ Weierstrass
383
+ # ndjson: newline-delimited JSON; the stream / btest output contract (one envelope per line).
384
+ ndjson
385
+ # allocate-udp-ports-from: /tool/bandwidth-server base of the UDP data-port range.
386
+ # srp5: the "5" suffix of EC-SRP5 (the MikroTik EC-SRP variant).
387
+ srp5
388
+ # SRV: the server-endpoint test variable in commands/btest/examples.md.
389
+ srv
390
+ # firewalled: blocked by a firewall (a btest connection-refused remediation).
391
+ firewalled
392
+ # btest reference implementations + EC-SRP5 protocol vocabulary:
393
+ # manawenuz/btest-rs (Rust; both modes + EC-SRP5) and samm-git/btest-opensource
394
+ # (C; no EC-SRP5) are the wire-format references; ECPESVDP-SRP-A/B name the
395
+ # client/server EC-SRP shared-secret roles; docryptos = mtwei.c's server proof fn.
396
+ manawenuz
397
+ samm
398
+ opensource
399
+ ecsrp
400
+ ECPESVDP
401
+ docryptos
402
+ keypairs
403
+ # btest test fixtures (credentials + the "antar" username from the MITM capture).
404
+ testuser
405
+ testpass
406
+ wrongpass
407
+ antar
408
+ swordfish
409
+
410
+ # btest session layer.
411
+ pselect
412
+ interoperation
413
+ Mbps
414
+ Gbps
415
+ Kbps
416
+ trippable
417
+
418
+ # btest integration-test fixtures.
419
+ btestuser
420
+ btestpass