@tikoci/centrs 0.1.1 → 0.1.2

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/docs/MATRIX.md CHANGED
@@ -24,7 +24,7 @@ A cell advances only with the matching evidence in the same change.
24
24
  | Command | rest-api | native-api | ssh | mac-telnet | snmp | mndp | romon | winbox-terminal |
25
25
  | -------- | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- | ---------------- |
26
26
  | retrieve | `CHR-passed` | `CHR-passed` | — | — | `not-started` | — | — | — |
27
- | stream | — | `designed` | `designed` | — | — | — | — | — |
27
+ | api | `CHR-passed` | `CHR-passed` | — | — | — | — | — | — |
28
28
  | execute | `CHR-passed` | `CHR-passed` | `CHR-passed` | `CHR-passed` | — | — | `not-started` | `not-started` |
29
29
  | terminal | — | — | `CHR-passed` | `CHR-passed` | — | — | — | — |
30
30
  | transfer | `CHR-passed` | `CHR-passed` | `CHR-passed` | — | — | — | — | — |
@@ -56,13 +56,26 @@ verbose REST `board-name`), and the L2 validation policy are documented in
56
56
  `commands/discover/README.md`.
57
57
 
58
58
  There is no `update` command: `execute` is the single read/write surface for
59
- RouterOS add/set/remove, and `retrieve` stays read-only. See
60
- `docs/CONSTITUTION.md` (protocol selection).
61
-
62
- `stream` is `designed` (no code yet): the read-only follow surface (NDJSON
63
- stream-of-envelopes; native-api/ssh only — REST's 60s cap cannot follow) is
64
- specified in `commands/stream/README.md`. The native-api streaming reader it will
65
- consume already exists (`src/protocols/native-api.ts`).
59
+ RouterOS *CLI-shaped* add/set/remove, and `retrieve` stays read-only. The `api`
60
+ command is the structured one-command-per-operation surface (the verb trichotomy
61
+ in `commands/api/README.md`); it can also write. See `docs/CONSTITUTION.md`
62
+ (protocol selection).
63
+
64
+ `api` is `CHR-passed` for `rest-api` and `native-api` (single-target): endpoint
65
+ normalization, the method→verb map, the `/console/inspect` gate, write
66
+ confirmation, `.query`/`.proplist`, `-f`/`-d`/`--input` bodies, `--raw`,
67
+ `/execute` script-run (`=as-string=` for sync output on both transports), and
68
+ open-ended `--stream` follow (native-api only — `NativeApiSession.listen()` +
69
+ `/cancel`, NDJSON envelope frames with a terminating summary; `--via rest-api
70
+ --stream` errors `transport/capability-unsupported`), green on CHR 7.23.1 via
71
+ `test/integration/api.test.ts` + `api-native.test.ts` + `api-listen.test.ts`.
72
+ Still deferred (own phase): multi-target fan-out (`--stream` is single-session).
73
+
74
+ `api` **absorbs** the former `stream` command (folded — no separate row): the
75
+ read-only follow surface is `api <router> <endpoint> --stream` (alias `--listen`;
76
+ the `/listen` endpoint form infers it), native-api only, since REST's 60s cap
77
+ cannot follow. `centrs stream`/`centrs tail` now error with a pointer to
78
+ `api --stream`.
66
79
 
67
80
  `transfer` is `CHR-passed` for `rest-api`/`native-api` and for **sftp** (the
68
81
  `ssh` column's first method): `src/transfer.ts` + `src/cli/transfer.ts`
@@ -156,7 +169,7 @@ core and carry their own state, tracked here:
156
169
 
157
170
  | Surface | State | Spec | Notes |
158
171
  | ------- | ----- | ---- | ----- |
159
- | api (TS) | `CHR-passed` | `src/index.ts` | Root surface; everything else adapts it. |
172
+ | ts-api | `CHR-passed` | `src/index.ts` | Root **TypeScript library** surface; everything else adapts it. (Renamed from `api (TS)` to avoid colliding with the `api` **command** row in the grid above — the command is a verb, this is the library.) |
160
173
  | cli | `coded` | `src/cli/` | `retrieve`/`execute`/`transfer`/`terminal`/`devices`/`discover`/`btest` wired. |
161
174
  | mcp | `CHR-passed` | `commands/mcp/` | Scoped-verb stdio MCP server; CDB-as-allowlist safety model. Phase 1 (explain/validate/retrieve/execute, resources) plus first Phase 2 CDB mutation (`centrs_devices add`) green on CHR 7.23 via `test/integration/mcp.test.ts`, including gated write execution. |
162
175
  | tui | `not-started` | `src/tui.ts` | Stub. |
@@ -186,12 +199,30 @@ The wire codec, the EC-SRP5 session/handshake (shared core byte-identical with
186
199
  mac-telnet's MTWEI, plus the net-new server role), the TCP/UDP data engines, the
187
200
  orchestrator + CLI, and the honest grounding caveat (the server gets direct CHR
188
201
  evidence over the QEMU SLIRP gateway `10.0.2.2`; the client gets direct CHR
189
- evidence over a host→guest `tcp:2000` forward — TCP only; UDP-receive is a soft
190
- smoke test and UDP client→CHR-server stays loopback/transitive over the SLIRP
191
- reverse path; TCP `connection-count > 1` fan-out is deferred; NDJSON is not
192
- adopted) are documented in `commands/btest/README.md` and the
193
- `src/protocols/btest.ts`, `src/protocols/btest-session.ts`, and
194
- `src/protocols/ec-srp5.ts` module headers.
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.
195
226
 
196
227
  ## Priority order
197
228
 
@@ -0,0 +1,22 @@
1
+ # `routeros/btest-connection-count-single-stream`
2
+
3
+ A **warning** (not a failure): `centrs btest client --protocol tcp
4
+ --connection-count <n>` opened **fewer** TCP data connections than `n`. centrs
5
+ does implement the multi-connection fan-out — it opens the extra connections that
6
+ join the test with the server-negotiated session token — but it falls back to a
7
+ single stream when the server negotiates **no** token. The common case is an
8
+ **authenticated (EC-SRP5)** session: centrs does not yet capture the post-auth
9
+ session token, so authenticated tests stay single-stream. A secondary connection
10
+ that fails mid-handshake also reduces the realized count.
11
+
12
+ The warning reports both the requested and the actually-active connection count.
13
+
14
+ ## Workaround
15
+
16
+ - For full multi-stream throughput, run the test **unauthenticated**
17
+ (`/tool/bandwidth-server` with `authenticate=no`), where centrs negotiates the
18
+ token and opens all `n` connections.
19
+ - Or run several `centrs btest client` processes in parallel and sum their
20
+ throughput.
21
+
22
+ See `docs/CONSTITUTION.md` for the centrs error/warning contract.
@@ -0,0 +1,15 @@
1
+ # `routeros/btest-udp-tx-size-ignored`
2
+
3
+ A non-fatal warning. For UDP `--direction both`, the btest wire protocol carries
4
+ a **single** `tx-size` field, so the client and the server transmit with the
5
+ same packet size. centrs maps `--local-udp-tx-size` to that field and discards
6
+ `--remote-udp-tx-size`. This warning fires only when both flags are set to
7
+ different values, so you know which size the session actually used.
8
+
9
+ ## Fix
10
+
11
+ Drop `--remote-udp-tx-size` for `--direction both`, or set both flags to the
12
+ same value. To size each direction independently, run two sessions:
13
+ `--direction transmit` (uses `--local-udp-tx-size`) and `--direction receive`
14
+ (uses `--remote-udp-tx-size`). See `commands/btest/README.md` and
15
+ [`docs/CONSTITUTION.md`](../../CONSTITUTION.md).
@@ -0,0 +1,23 @@
1
+ # `usage/invalid-method`
2
+
3
+ The -X/--method value is not a supported HTTP method.
4
+
5
+ ## Fix
6
+
7
+ `centrs api` honors the HTTP method (`-X` / `--method`) literally against
8
+ RouterOS's REST verb map. The accepted methods are `GET`, `PUT`, `PATCH`,
9
+ `DELETE`, and `POST` (case-insensitive):
10
+
11
+ | Method | RouterOS verb |
12
+ | ------ | -------------------- |
13
+ | `GET` | print / get |
14
+ | `PUT` | add (RouterOS create) |
15
+ | `PATCH`| set |
16
+ | `DELETE`| remove |
17
+ | `POST` | run a command |
18
+
19
+ Pass one of those with `-X`, or omit the flag to use the default `GET`. Note the
20
+ trap: **`PUT` is RouterOS's create**, not `POST`.
21
+
22
+ See [`docs/CONSTITUTION.md`](../../CONSTITUTION.md) for the centrs error
23
+ contract.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tikoci/centrs",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "main": "src/index.ts",
5
5
  "module": "src/index.ts",
6
6
  "repository": {
@@ -12,7 +12,7 @@
12
12
  "packageManager": "bun@1.3.13",
13
13
  "devDependencies": {
14
14
  "@agent-lint/cli": "^0.8.1",
15
- "@biomejs/biome": "2.5.0",
15
+ "@biomejs/biome": "2.5.1",
16
16
  "@secretlint/secretlint-rule-preset-recommend": "^13.0.2",
17
17
  "@tikoci/quickchr": "^0.4.2",
18
18
  "@types/bun": "^1.3.13",
@@ -57,11 +57,11 @@
57
57
  "scripts": {
58
58
  "ci": "bun run lint && bun run test && bun run build",
59
59
  "git:pre-commit": "bun run lint",
60
- "git:pre-push": "bun run ci",
60
+ "git:pre-push": "bun run lint:git:push",
61
61
  "lint": "bun run lint:biome && bun run lint:typecheck",
62
62
  "lint:git:commit": "bun run lint",
63
- "lint:git:push": "bun run ci",
64
- "lint:ci": "bun run lint && bun run lint:markdownlint && bun run lint:cspell && bun run lint:secretlint && bun run lint:agents",
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
65
  "lint:cspell": "cspell lint . --gitignore",
66
66
  "lint:cspell:all": "cspell lint . --no-gitignore",
67
67
  "lint:markdownlint": "markdownlint-cli2 \"**/*.md\" \"!.scratch/**\"",