@tikoci/centrs 0.1.3 → 0.1.6
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 +348 -0
- package/GLOSSARY.txt +252 -0
- package/LICENSE +21 -0
- package/README.md +44 -12
- package/commands/AGENTS.md +14 -5
- package/commands/api/AGENTS.md +13 -1
- package/commands/api/README.md +56 -26
- package/commands/api/examples.md +46 -1
- 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 +77 -36
- package/commands/execute/examples.md +120 -10
- package/commands/explain/README.md +2756 -0
- package/commands/explain/examples.md +702 -0
- package/commands/mcp/README.md +7 -4
- package/commands/mcp/examples.md +2 -2
- package/commands/retrieve/README.md +25 -27
- package/commands/retrieve/examples.md +16 -0
- package/commands/terminal/examples.md +7 -1
- package/commands/transfer/README.md +28 -20
- package/commands/transfer/examples.md +29 -0
- package/docs/CLI.md +353 -0
- package/docs/CONSTITUTION.md +138 -30
- package/docs/MATRIX.md +92 -18
- 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/syntax.md +29 -4
- package/docs/errors/validation/unknown-attribute.md +37 -4
- package/package.json +56 -10
- package/src/api-fanout.ts +46 -18
- package/src/api.ts +351 -121
- package/src/cli/api.ts +26 -7
- package/src/cli/btest.ts +19 -3
- 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/terminal.ts +1 -1
- package/src/cli/transfer.ts +23 -6
- package/src/cli.ts +15 -2
- package/src/core/envelope.ts +58 -2
- package/src/core/error-catalog.ts +42 -1
- package/src/core/execute-command.ts +148 -0
- package/src/core/inspect.ts +36 -4
- package/src/core/preflight.ts +306 -0
- package/src/core/routeros-string.ts +24 -0
- package/src/core/version.ts +4 -0
- package/src/core/yaml.ts +86 -0
- package/src/errors.ts +1 -0
- package/src/execute-fanout.ts +47 -18
- package/src/execute.ts +339 -307
- package/src/explain/arg-tokens.ts +151 -0
- package/src/explain/args.ts +1749 -0
- package/src/explain/blocks.ts +175 -0
- package/src/explain/brace-slots.ts +143 -0
- package/src/explain/brace-tokens.ts +39 -0
- package/src/explain/catalog.ts +1343 -0
- package/src/explain/coordinates.ts +488 -0
- package/src/explain/defects.ts +218 -0
- package/src/explain/escape-tokens.ts +77 -0
- package/src/explain/highlight-projection.ts +308 -0
- package/src/explain/is-known-menu.ts +17 -0
- package/src/explain/menus.ts +668 -0
- package/src/explain/operator-tokens.ts +316 -0
- package/src/explain/operators.ts +465 -0
- package/src/explain/path-tokens.ts +150 -0
- package/src/explain/pathresolve.ts +1569 -0
- package/src/explain/quoted-string.ts +331 -0
- package/src/explain/scope-brace.ts +461 -0
- package/src/explain/segment.ts +1165 -0
- package/src/explain/separator.ts +187 -0
- package/src/explain/split-owner.ts +194 -0
- package/src/explain/string-tokens.ts +77 -0
- package/src/explain/symbol-values.ts +556 -0
- package/src/explain/symbols.ts +1617 -0
- package/src/explain/token-ranges.ts +72 -0
- package/src/explain/transport.ts +514 -0
- package/src/explain/value-tokens.ts +83 -0
- package/src/explain/values.ts +357 -0
- package/src/explain/verbs.ts +64 -0
- package/src/explain/verbsplit.ts +955 -0
- package/src/explain/write.ts +856 -0
- package/src/explain.ts +2602 -0
- package/src/index.ts +225 -6
- package/src/mcp/server.ts +2 -1
- package/src/offline-gate.ts +148 -0
- 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 +27 -13
- package/src/retrieve.ts +82 -77
- package/src/settings.ts +2 -1
- package/src/transfer-fanout.ts +43 -26
- package/src/transfer.ts +88 -45
package/GLOSSARY.txt
CHANGED
|
@@ -93,9 +93,12 @@ cwd
|
|
|
93
93
|
datagram
|
|
94
94
|
davidanson
|
|
95
95
|
DDNS
|
|
96
|
+
dialable # an endpoint a client can actually connect to (advertised AND reachable)
|
|
96
97
|
defconf
|
|
97
98
|
demux
|
|
98
99
|
demuxes
|
|
100
|
+
desync # a highlight stream whose token count != input length, so classes line up against the wrong characters
|
|
101
|
+
desynced
|
|
99
102
|
dogtail
|
|
100
103
|
donny
|
|
101
104
|
dotenv
|
|
@@ -125,6 +128,8 @@ keystream
|
|
|
125
128
|
KSA
|
|
126
129
|
KVM
|
|
127
130
|
LDTP
|
|
131
|
+
LFS # Git Large File Storage. The pinned corpus blob is NOT stored through it,
|
|
132
|
+
# which is why a plain raw.githubusercontent GET returns the real bytes.
|
|
128
133
|
librouteros # <https://github.com/haakonnessjoen/librouteros-api>
|
|
129
134
|
LLDP
|
|
130
135
|
lsp-routeros-ts
|
|
@@ -144,10 +149,12 @@ npk # MikroTik package format
|
|
|
144
149
|
nvme-over-tcp # supported by RouterOS **with** rose-storage.npk extra-package
|
|
145
150
|
OID
|
|
146
151
|
PII # Personally Identifiable Information
|
|
152
|
+
PON # passive optical network; RouterOS /interface/ethernet/pon menu
|
|
147
153
|
POV
|
|
148
154
|
PRGA
|
|
149
155
|
proplist
|
|
150
156
|
pywinauto
|
|
157
|
+
QKD # quantum key distribution; RouterOS IPsec/keymat-provider vocabulary
|
|
151
158
|
QML
|
|
152
159
|
qll # CodeQL library file extension (.qll), e.g. CleartextLoggingCustomizations.qll
|
|
153
160
|
qmljsdebugger
|
|
@@ -163,6 +170,7 @@ rosetta
|
|
|
163
170
|
routeros
|
|
164
171
|
routeros-skills
|
|
165
172
|
rsc # RouterOS script / export file extension (.rsc)
|
|
173
|
+
rstp # Rapid Spanning Tree Protocol; a RouterOS `protocol-mode=` value on /interface/bridge
|
|
166
174
|
SARIF # Static Analysis Results Interchange Format; CodeQL's code-scanning analysis download format
|
|
167
175
|
scp
|
|
168
176
|
scriptability
|
|
@@ -206,6 +214,7 @@ webproxy
|
|
|
206
214
|
WinAppDriver
|
|
207
215
|
winbox
|
|
208
216
|
Wireshark
|
|
217
|
+
workstream
|
|
209
218
|
workstreams
|
|
210
219
|
XCUI
|
|
211
220
|
XDG
|
|
@@ -269,6 +278,9 @@ choco
|
|
|
269
278
|
coderabbit
|
|
270
279
|
coderabbitai
|
|
271
280
|
|
|
281
|
+
# GitHub account Codex review threads are authored under (see pr-review-bots).
|
|
282
|
+
mobileskyfi
|
|
283
|
+
|
|
272
284
|
# centrs domain vocabulary
|
|
273
285
|
# %identity: the device /system/identity; a centrs CDB comment *lookup key*
|
|
274
286
|
# (`identity=`) used to resolve `<router>`. Human handle, deliberately may
|
|
@@ -370,6 +382,20 @@ CSI
|
|
|
370
382
|
SIGWINCH
|
|
371
383
|
# evl: RouterOS :parse renders a parsed command as "(evl ...)" on the console.
|
|
372
384
|
evl
|
|
385
|
+
# putmessage/globalname: RouterOS :parse IL statement heads — ":put x" echoes back
|
|
386
|
+
# as "(evl /putmessage=x)", ":global n v" as "(evl /globalname=$n;value=v)" (GH#230).
|
|
387
|
+
putmessage
|
|
388
|
+
globalname
|
|
389
|
+
# localname/setnote/runnumber: more of the same head rendering, quoted verbatim as
|
|
390
|
+
# evidence for the missing-separator rule (GH#311). ":put [:parse …]" joins the IL
|
|
391
|
+
# array with NO separator, so the path and its first argument run together —
|
|
392
|
+
# ":local a v" is "(evl /localname=$a;value=v)", "/system/note set note=hello" is
|
|
393
|
+
# "(evl /system/note/setnote=hello)", "/system/script/run /ip/route" is
|
|
394
|
+
# "(evl /system/script/runnumber=/ip/route)". Artefacts of the rendering, not
|
|
395
|
+
# RouterOS argument names; kept unsplit because the quote must match the bytes.
|
|
396
|
+
localname
|
|
397
|
+
setnote
|
|
398
|
+
runnumber
|
|
373
399
|
# unconfigured: a freshly-flashed RouterOS device with no IP — the mac-telnet use case.
|
|
374
400
|
unconfigured
|
|
375
401
|
unwired
|
|
@@ -397,6 +423,7 @@ Weierstrass
|
|
|
397
423
|
# ndjson: newline-delimited JSON; the stream / btest output contract (one envelope per line).
|
|
398
424
|
ndjson
|
|
399
425
|
# allocate-udp-ports-from: /tool/bandwidth-server base of the UDP data-port range.
|
|
426
|
+
allocate-udp-ports-from
|
|
400
427
|
# srp5: the "5" suffix of EC-SRP5 (the MikroTik EC-SRP variant).
|
|
401
428
|
srp5
|
|
402
429
|
# SRV: the server-endpoint test variable in commands/btest/examples.md.
|
|
@@ -505,3 +532,228 @@ sfo
|
|
|
505
532
|
ele
|
|
506
533
|
GPX
|
|
507
534
|
Geolocation
|
|
535
|
+
unparseable
|
|
536
|
+
Unparseable
|
|
537
|
+
versionless
|
|
538
|
+
|
|
539
|
+
# explain canonicalizer (phase-0 lab #185, commands/explain) vocabulary.
|
|
540
|
+
# SUT: "system under test" — the phase-0 lab's throwaway parser, scored
|
|
541
|
+
# against a `:parse` IL / highlight oracle; the ratified behavior is what the
|
|
542
|
+
# production modules under src/explain promote. CJK: the Chinese/Japanese/
|
|
543
|
+
# Korean Unicode range, used as a non-ASCII coordinate/segmentation fixture.
|
|
544
|
+
# pathresolve / blocktree: the Q3-Q4 / Q2 lab probe names, carried into the
|
|
545
|
+
# src/explain module + fixture names. klass: `class` is reserved, so the
|
|
546
|
+
# resolution feature-class field is `klass`. tostr / tostrvalue: the RouterOS
|
|
547
|
+
# `:tostr` directive and its IL-lowered form `/tostrvalue`. eworm: a corpus
|
|
548
|
+
# script author (eworm/*.rsc) cited as grounding for scope-name findings.
|
|
549
|
+
# rextended: another corpus script author, cited for the Q14 nested-bracket
|
|
550
|
+
# ambient-context case (a user function establishes no menu). ppp: the RouterOS
|
|
551
|
+
# /ppp menu, in the Q14 corner proving a `$` inside a `~` FILTER argument does
|
|
552
|
+
# not make the menu unreadable. strfind: a corpus user function in that corner.
|
|
553
|
+
# verbsplit: the Q6 verb/menu-boundary lab probe name, carried into the
|
|
554
|
+
# src/explain module + fixture names. myvar: the RouterOS example variable in
|
|
555
|
+
# the Q6 `:global myvar` collision corner (a positional operand indistinguishable
|
|
556
|
+
# from a sub-menu offline).
|
|
557
|
+
# failclosed: the ratified Q16 navigation arm name (the two arms that priced it
|
|
558
|
+
# stayed in the lab). notadirective: the Q16 fixture's deliberately unseen root
|
|
559
|
+
# directive, pinning that an unknown directive abstains rather than reading as
|
|
560
|
+
# harmless control flow.
|
|
561
|
+
# RouterOS root cmds (scripting directives) enumerated from /console/inspect and
|
|
562
|
+
# frozen in src/explain/write.ts as the closed ROOT_CMDS vocabulary — jobname,
|
|
563
|
+
# rndnum, rndstr, tobool, tocrlf, toid, toip, tolf, tonsec, tonum, totime.
|
|
564
|
+
# lte: the RouterOS /interface lte menu, cited in the Q16 long-tail-verb corner.
|
|
565
|
+
# dyn: the `$dyn` variable in the Q14 cascade corners — a dynamic-headed
|
|
566
|
+
# statement, which is context-NEUTRAL and must not poison the menu context.
|
|
567
|
+
# symbols (Q13): cls — the resolved variable-class field on a symbol occurrence
|
|
568
|
+
# (`class` is reserved, same reason as klass). sigilled: written with the `$`
|
|
569
|
+
# sigil, the schema-free tell that separates a variable from a directive or a
|
|
570
|
+
# menu-path segment. ERRVAR: the `:onerror NAME` error-variable slot (S18).
|
|
571
|
+
# unmodeled / distinguisher: the closure-scope finding — the lab left the rule
|
|
572
|
+
# unmodeled because a depth counter has no scope identity, and the statement
|
|
573
|
+
# head is the only distinguisher between a function `do={}` and a control-flow
|
|
574
|
+
# one. Corner variable names quoted from the device probes and corpus scripts:
|
|
575
|
+
# vlanid, vlanbytes, ipprefix, octive (the `$octive-1` name-vs-operator case),
|
|
576
|
+
# lppp (the device documentation's own `variable-undefined` example).
|
|
577
|
+
# lookback: the backward scan that decides whether a `{` follows `do=`; it must
|
|
578
|
+
# accept exactly the escapes the forward walker does, or the two disagree about
|
|
579
|
+
# where the argument name ends and a function body stops being a closure.
|
|
580
|
+
# tangentsoft: the maintainer/site (tangentsoft.com/mikrotik) behind the third
|
|
581
|
+
# corpus collection — 35 genuine `/export show-sensitive terse` device captures
|
|
582
|
+
# imported for the #203 genre census, and the corpus's only wholly-terse
|
|
583
|
+
# export stratum.
|
|
584
|
+
SUT
|
|
585
|
+
CJK
|
|
586
|
+
parseil # lsp-routeros-ts corpus table of captured `:parse` IL, per script per RouterOS version
|
|
587
|
+
pathresolve
|
|
588
|
+
blocktree
|
|
589
|
+
klass
|
|
590
|
+
tostr
|
|
591
|
+
tostrvalue
|
|
592
|
+
eworm
|
|
593
|
+
rextended
|
|
594
|
+
tangentsoft
|
|
595
|
+
ppp
|
|
596
|
+
strfind
|
|
597
|
+
verbsplit
|
|
598
|
+
myvar
|
|
599
|
+
failclosed
|
|
600
|
+
notadirective
|
|
601
|
+
jobname
|
|
602
|
+
rndnum
|
|
603
|
+
rndstr
|
|
604
|
+
tobool
|
|
605
|
+
tocrlf
|
|
606
|
+
toid
|
|
607
|
+
toip
|
|
608
|
+
tolf
|
|
609
|
+
tonsec
|
|
610
|
+
tonum
|
|
611
|
+
totime
|
|
612
|
+
lte
|
|
613
|
+
dyn
|
|
614
|
+
cls
|
|
615
|
+
sigilled
|
|
616
|
+
ERRVAR
|
|
617
|
+
unmodeled
|
|
618
|
+
distinguisher
|
|
619
|
+
vlanid
|
|
620
|
+
vlanbytes
|
|
621
|
+
ipprefix
|
|
622
|
+
octive
|
|
623
|
+
lppp
|
|
624
|
+
lookback
|
|
625
|
+
|
|
626
|
+
# RouterOS menu vocabulary reached by the explain menu table (#207).
|
|
627
|
+
# The generated table itself (src/explain/menus.ts) is cspell-ignored; these are
|
|
628
|
+
# the terms that also appear in hand-written prose and tests.
|
|
629
|
+
# %cliref: docs-derived RouterOS command reference in rosetta
|
|
630
|
+
# (experiments/cliref.db). A second opinion on node types, NOT a source for
|
|
631
|
+
# the menu table: its paths interleave the docs slug with the CLI path.
|
|
632
|
+
cliref
|
|
633
|
+
hotspot
|
|
634
|
+
igmp
|
|
635
|
+
ipfix
|
|
636
|
+
keymat
|
|
637
|
+
pmp
|
|
638
|
+
pptp
|
|
639
|
+
sstp
|
|
640
|
+
wlan
|
|
641
|
+
zerotier
|
|
642
|
+
cuu # `/terminal cuu` (cursor up) — a RouterOS command that reads as a bare menu path, so the table refuses it (#210)
|
|
643
|
+
|
|
644
|
+
# Hardware-gated RouterOS surfaces named when explaining why a published path is
|
|
645
|
+
# absent from a CHR-derived inspect tree (#228). No CHR carries these.
|
|
646
|
+
FDB # forwarding database — `/interface/ethernet/switch/{unicast,multicast,reserved}-fdb`, switch-chip only
|
|
647
|
+
MSRP # Stream Reservation Protocol (TSN) — `/interface/bridge/msrp`, gated by `conditions: MSRP_ENABLE`
|
|
648
|
+
PTP # Precision Time Protocol — `/system/ptp`, gated by `syscap: ptp`
|
|
649
|
+
syscap # a CLI-Reference applicability gate naming the hardware/system capability a path requires (`poe`, `lcd`, `multiswitch`, `nochr`)
|
|
650
|
+
|
|
651
|
+
# explain ANALYSIS/ORACLE vocabulary — not RouterOS menu names. These name the
|
|
652
|
+
# lab's measurement machinery and the properties it measures, and belong apart
|
|
653
|
+
# from the menu block above even though both arrived with the explain work.
|
|
654
|
+
importability # whether a document RouterOS emitted can be re-imported (#203 oracle level L2)
|
|
655
|
+
menuctx # the IL (`:parse`) statement type for menu navigation, as against `cmd` — the native nav-vs-command oracle (#210)
|
|
656
|
+
|
|
657
|
+
# #202c-1 argument-lexer vocabulary: one analysis term, plus the RouterOS names
|
|
658
|
+
# that appear verbatim in the corpus lines `test/unit/explain-args.test.ts`
|
|
659
|
+
# fixtures. The corpus lines are real forum scripts and are quoted rather than
|
|
660
|
+
# paraphrased, so their spellings are data, not prose.
|
|
661
|
+
renderable # of a statement: covered by a tested REST mapping rule, so `--curl` may render it (#202c-2)
|
|
662
|
+
wifiwave # `/interface wifiwave2` — the pre-7.13 RouterOS wifi menu, renamed `wifi` (drift the corpus carries)
|
|
663
|
+
nomaster # from a corpus line where two arguments ran together (`disabled=nomaster-interface=wifi1`); pinned as the first-`=`-splits case
|
|
664
|
+
CAINFO # `AT#CAINFO?` — an LTE modem AT command in a corpus `/interface/lte/at-chat` line
|
|
665
|
+
vzwinternet # Verizon LTE APN name, from a corpus `/interface lte apn add` line
|
|
666
|
+
rtr # short device name in an explain test input
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
# #228 path-catalog vocabulary: the CLI-Reference definition-module segments the
|
|
670
|
+
# alias allowlist maps away, the published gate values, and the prose terms used
|
|
671
|
+
# to describe the union. The generated table itself is cspell-ignored.
|
|
672
|
+
chancfg # caps-man definition module for `/caps-man/channel` — a doc spelling, not a CLI path
|
|
673
|
+
dpathcfg # caps-man definition module for `/caps-man/datapath`
|
|
674
|
+
ifaceactual # caps-man definition module for `/caps-man/actual-interface-configuration`
|
|
675
|
+
ratescfg # caps-man definition module for `/caps-man/rates`
|
|
676
|
+
remoteap # caps-man definition module for `/caps-man/remote-cap`
|
|
677
|
+
seccfg # caps-man definition module for `/caps-man/security`
|
|
678
|
+
ifaces # CLI-Reference definition module for `/tool/graphing/interface`
|
|
679
|
+
datapath # `/caps-man/datapath` — the real CLI menu behind `dpathcfg`
|
|
680
|
+
easymesh # `/interface/wifi/easymesh` — the doc spelling of `/interface/wifi/wps-push-button`
|
|
681
|
+
wps # Wi-Fi Protected Setup — `/interface/wifi/wps-push-button`
|
|
682
|
+
qos # switch-chip quality of service — `/interface/ethernet/switch/qos`, a real menu segment R1 must never drop
|
|
683
|
+
qca # Qualcomm Atheros — the `wireless-qca` package gate
|
|
684
|
+
multiswitch # syscap gate: more than one switch chip
|
|
685
|
+
oldswitch # syscap gate: the pre-Prestera switch-chip menu shape
|
|
686
|
+
smips # RouterOS architecture (single-core MIPS), named in `conditions:` gates
|
|
687
|
+
mmips # RouterOS architecture (multi-core MIPS), named in `conditions:` gates
|
|
688
|
+
CRS # MikroTik Cloud Router Switch — carries the switch-chip menus no CHR has
|
|
689
|
+
CCR # MikroTik Cloud Core Router
|
|
690
|
+
superlinear # growth faster than linear, used for resolveDocument wall-clock on separator-free input (#248)
|
|
691
|
+
superlinearity # the property a growth-ratio guard bounds; `superlinear+` is NOT usable here, cspell's compound form forbids the bare word (#313)
|
|
692
|
+
stmts # `explainCommand` corpus measurement: statement count (shorthand for `statements`)
|
|
693
|
+
argCandidates # `explainCommand` corpus measurement: arg-bearing candidates
|
|
694
|
+
argReadable # `explainCommand` corpus measurement: readable statements
|
|
695
|
+
ungated # of a published path: carrying no package/conditions/syscap that would explain its absence from a tree
|
|
696
|
+
unioned # of the two sources: merged with per-entry provenance rather than flattened
|
|
697
|
+
unioning # the act of the above
|
|
698
|
+
greppable # of a generated table: one entry per line, so `grep` finds a path
|
|
699
|
+
apos # the `'` XML entity, decoded by the CLI-Reference parser
|
|
700
|
+
|
|
701
|
+
# #285 CLI-Reference reshape vocabulary: the second published inventory, and the
|
|
702
|
+
# gate values on the paths that publish twice.
|
|
703
|
+
llms # `llms.txt` — MikroTik's published page inventory; the only one listing the `<dir>/<basename>` leaf a branching menu's own entry lives on, so discovery is the union of it and the sitemap
|
|
704
|
+
musicswitch # syscap gate: the Marvell-era switch-chip menu shape — one half of the `/interface/ethernet/switch` pair published under two gates
|
|
705
|
+
rbswitch # syscap gate: the RouterBOARD switch-chip menu shape — the other half of that pair
|
|
706
|
+
prestera # Marvell Prestera switch chip — named in the `crs_prestera` syscap gate on `/interface/ethernet/switch/qos`
|
|
707
|
+
xfrm # `/interface/xfrm` — the IPsec transform interface, device-confirmed by the pinned 7.25beta3 trees and published by the CLI Reference
|
|
708
|
+
btrfs # the Linux B-tree filesystem, a `/disk/btrfs/...` menu on RouterOS 7.20+
|
|
709
|
+
|
|
710
|
+
# #255 operator-axis vocabulary: the device-grounded operator surface.
|
|
711
|
+
arities # plural of arity — the operand counts an operator accepted, which is what separates `(> 1)` (deferred expression) from `(2 > 1)` (comparison)
|
|
712
|
+
typeofvalue # RouterOS IL renders `[:typeof $x]` as `/typeofvalue=$x` — the directive and its argument name run together with no separator
|
|
713
|
+
juxt # short for juxtaposition — the unnamed ` ( a b)` node RouterOS builds for space-separated paren contents; used in ids like `any-juxt`
|
|
714
|
+
punct # short for punctuation — the shape class for a candidate spelling made of symbol bytes, as opposed to a word; used in the `bogus-punct` control id
|
|
715
|
+
gapless # of a token partition: every byte in [0, input.bytes) belongs to exactly one token, sorted by start, no gaps (#289 B1)
|
|
716
|
+
SCIP # Source Code Intelligence Protocol — the symbol-identity axis for `data.tokens[]`'s later vocabulary (#264 B5)
|
|
717
|
+
unclassified # the provisional token class for a byte no analyzer claims; a first-class answer in the gapless partition (#289 B1)
|
|
718
|
+
|
|
719
|
+
# #290 B2 operator-fill test vocabulary
|
|
720
|
+
xand
|
|
721
|
+
andx
|
|
722
|
+
alnum
|
|
723
|
+
wpa # `security.authentication-types=wpa2-psk` — a wifi argument name whose interior dot the operator fill must not read as concatenation
|
|
724
|
+
psk # pre-shared key — the value half of the same grounded `wpa2-psk` example
|
|
725
|
+
|
|
726
|
+
# #293 B2 arg-fill vocabulary
|
|
727
|
+
retag # B5 may retag the `=` separator from the provisional `arg` class without moving byte coverage
|
|
728
|
+
|
|
729
|
+
# #239 S2 flow-sensitive symbol→value
|
|
730
|
+
occ # short for occurrence — local variable in symbol-values flow analysis
|
|
731
|
+
vid # short for valueId — result-local value occurrence identifier (v0, v1)
|
|
732
|
+
idx # short for index — loop/event index in flow merging
|
|
733
|
+
mis # prefix in mis-linking — hyphenated in comments for symbol-values guard
|
|
734
|
+
|
|
735
|
+
# #313 offline performance vocabulary
|
|
736
|
+
JIT # just-in-time compiler — warmed before either half of the growth-ratio timing so the two sizes are compared in the same compilation state
|
|
737
|
+
|
|
738
|
+
# #317 statement-ownership index vocabulary
|
|
739
|
+
laminarity # the property of a set of spans in which every pair is nested or disjoint, never crossing — what makes the shortest containing span reachable by a parent walk
|
|
740
|
+
|
|
741
|
+
# #264 B4 / #263 device-agreement vocabulary
|
|
742
|
+
unprojected # of a byte whose offline/device class PAIR the declared projection does not cover, so it can neither agree nor disagree: an offline class that deliberately maps to no RouterOS `highlight` class, or a device class this build has never seen (#264 B4)
|
|
743
|
+
|
|
744
|
+
# #324 / #325 offline-reading vocabulary. Both words are corpus data: they are
|
|
745
|
+
# quoted from the two slice scripts the device-agreement report names as the
|
|
746
|
+
# exemplars of the cells these fixes empty, so their spellings must match the
|
|
747
|
+
# bytes the device saw.
|
|
748
|
+
ytkids # an address-list name in the corpus line `/ip/firewall/address-list name=ytkids timeout=1h` — the #324 exemplar
|
|
749
|
+
apikey # a local variable in the corpus line `apikey-len=$([:len $apikey])` — the `$(…)` interpolation #325 deliberately leaves unreached
|
|
750
|
+
|
|
751
|
+
# #312 offline-entry boundary vocabulary
|
|
752
|
+
dgram # Node's `node:dgram` UDP socket module — reached by `mac-telnet`, and one of the builtins that made the old `explain` import graph unusable outside Bun; named in the boundary gate's allowlist rationale
|
|
753
|
+
|
|
754
|
+
# #347 / #348 offline false-reject controls. Both words are deliberate
|
|
755
|
+
# NON-words: each is the rejected half of a CHR-confirmed accepted/rejected
|
|
756
|
+
# pair, so its spelling is load-bearing and must not be "corrected".
|
|
757
|
+
elsy # the misspelled `else` in `:if (1=1) do={…} elsy {…}` — rejected as `expected end of command` on CHR 7.21.5/7.23.5/7.24.2/7.25beta3, which is what proves the bare-brace `else {` acceptance is a real device fact and not a probe artifact (#347)
|
|
758
|
+
prnt # a misspelt `print` verb — `/ip/address/prnt` is the offline analyzer's ABSTENTION fixture (`verdict: warn`, not `fail`), which is what proves the two-stage validation gate passes an abstention through to the device rather than refusing it (#354)
|
|
759
|
+
zzznotamenu # a menu name no RouterOS build has — `/ip { zzznotamenu { print } }` is a `syntax error` on device, so menu-scope resolution is schema-dependent and a catalog MISS must abstain rather than accept (#348)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TIKOCI GitHub Organization
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
CLI (with MCP, TUI, and HTTP proxy frontends planned) for talking to MikroTik
|
|
5
5
|
RouterOS devices through a regularized, validated interface.
|
|
6
6
|
|
|
7
|
-
Preview builds are published on npm. To
|
|
7
|
+
Preview builds are published on npm. To try the current offline analyzer without
|
|
8
|
+
installing centrs or connecting to a router:
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
|
-
bunx @tikoci/centrs --
|
|
11
|
+
bunx @tikoci/centrs@next explain '/ip/address print' --json
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
Use `bunx @tikoci/centrs@next --help` to inspect the full preview CLI. The
|
|
15
|
+
explicit `@next` matters: `0.1.x` preview releases do not move npm's `latest`
|
|
16
|
+
tag.
|
|
17
|
+
|
|
18
|
+
The full flag reference for every command is generated from the CLI metadata
|
|
19
|
+
into [`docs/CLI.md`](docs/CLI.md); per-command behavior lives in
|
|
20
|
+
`commands/<name>/README.md`.
|
|
21
|
+
|
|
13
22
|
It is a **friendly conduit**, not a high-level configuration abstraction. It
|
|
14
23
|
helps humans and agents reach RouterOS over the right protocol, with the right
|
|
15
24
|
credentials and ports, and validates RouterOS-shaped commands before running
|
|
@@ -17,9 +26,12 @@ them. It does **not** hide RouterOS behind helpers like `createVlanOnBridge()`
|
|
|
17
26
|
— you still speak RouterOS. Validation and structured diagnostics are the
|
|
18
27
|
product; without them this would just be a worse `curl`.
|
|
19
28
|
|
|
20
|
-
> **Status:** early npm preview
|
|
21
|
-
>
|
|
22
|
-
>
|
|
29
|
+
> **Status:** early npm preview under active development. It is not
|
|
30
|
+
> production-ready: expect bugs and breaking changes before 1.0, and exercise
|
|
31
|
+
> router-writing workflows on lab or disposable targets first. Offline
|
|
32
|
+
> `explain` does not contact a router, but its analysis is intentionally
|
|
33
|
+
> conservative and never proves that RouterOS will accept a command at runtime.
|
|
34
|
+
> Check current dist-tags with
|
|
23
35
|
> `npm view @tikoci/centrs dist-tags --json`. The library, device registry, and
|
|
24
36
|
> first MCP server phases are CHR-verified; the CLI is wired (`coded`);
|
|
25
37
|
> encrypted-CDB writes are still blocked, and the TUI/proxy frontends are planned.
|
|
@@ -35,8 +47,10 @@ product; without them this would just be a worse `curl`.
|
|
|
35
47
|
SSH / MAC-Telnet / RoMON / WinBox Terminal for interactive and L2 execute;
|
|
36
48
|
MNDP for discovery. centrs picks the protocol for you (and lets you pin one
|
|
37
49
|
with `via=` or `--via`).
|
|
38
|
-
- **Commands:** every command resolves a *target* — a router you
|
|
39
|
-
CLI — to a real address, credentials, and a protocol, then runs.
|
|
50
|
+
- **Commands:** every router-facing command resolves a *target* — a router you
|
|
51
|
+
name on the CLI — to a real address, credentials, and a protocol, then runs.
|
|
52
|
+
(Local commands — `devices`, `settings`, `discover`, and `explain`'s offline
|
|
53
|
+
mode — need no router.)
|
|
40
54
|
|
|
41
55
|
| Command | Purpose |
|
|
42
56
|
| ---------- | ------- |
|
|
@@ -45,6 +59,7 @@ product; without them this would just be a worse `curl`.
|
|
|
45
59
|
| `api` | Structured RouterOS API passthrough (gh-api style): one command per operation, structured in/out, can write, over REST or native API. Open-ended follow is `api … --stream` (native API; NDJSON). |
|
|
46
60
|
| `terminal` | Open an interactive console, primarily SSH or MAC-Telnet. |
|
|
47
61
|
| `check` | Probe reachability and management protocol availability. |
|
|
62
|
+
| `explain` | Analyze a RouterOS command before running it: canonical form, syntax diagnostics, and what is valid at a path. Offline analysis runs today; the live-device probes are designed. |
|
|
48
63
|
| `devices` | View and maintain the CDB-backed device registry (the only writer). |
|
|
49
64
|
| `discover` | Discover MNDP neighbors and optionally save them into the CDB. |
|
|
50
65
|
| `settings` | Manage centrs's own settings (`centrs.env`, `__default__`) and run first-time setup. |
|
|
@@ -163,7 +178,9 @@ and the comment grammar — lives in `commands/devices/README.md` and
|
|
|
163
178
|
|
|
164
179
|
The load-bearing contract — envelope shape, error model, protocol selection,
|
|
165
180
|
settings precedence, and the "done" definition — lives in
|
|
166
|
-
`docs/CONSTITUTION.md`.
|
|
181
|
+
`docs/CONSTITUTION.md`. Capability status and the selected work track,
|
|
182
|
+
including the command×protocol grid and offline analysis, live in
|
|
183
|
+
`docs/MATRIX.md`.
|
|
167
184
|
|
|
168
185
|
## Repository layout
|
|
169
186
|
|
|
@@ -172,19 +189,21 @@ code and authority docs live.
|
|
|
172
189
|
|
|
173
190
|
- **`docs/CONSTITUTION.md`** — load-bearing rules (validation, envelope, error
|
|
174
191
|
model, settings precedence, identity/CDB, protocol selection, done).
|
|
175
|
-
- **`docs/MATRIX.md`** —
|
|
192
|
+
- **`docs/MATRIX.md`** — capability status and the selected work track (the
|
|
193
|
+
command×protocol grid plus offline analysis and frontend surfaces); the
|
|
194
|
+
only status surface.
|
|
176
195
|
- **`commands/<name>/`** — per-command README and executable examples.
|
|
177
196
|
- **`src/`** — Bun/TypeScript source.
|
|
178
197
|
- **`test/`** — unit and CHR-backed integration tests.
|
|
179
198
|
|
|
180
|
-
There is no `docs/specs/`, no `work/`, no roadmap doc. The matrix
|
|
181
|
-
roadmap.
|
|
199
|
+
There is no `docs/specs/`, no `work/`, no roadmap doc. The matrix and the
|
|
200
|
+
GitHub issues it links are the roadmap.
|
|
182
201
|
|
|
183
202
|
## Development
|
|
184
203
|
|
|
185
204
|
Requirements:
|
|
186
205
|
|
|
187
|
-
- Bun 1.3.11 or newer (CI pinned to 1.3.
|
|
206
|
+
- Bun 1.3.11 or newer (CI pinned to 1.3.14; Bun 2.x not yet validated).
|
|
188
207
|
- Git.
|
|
189
208
|
- For integration tests: QEMU plus `@tikoci/quickchr` (handles CHR image
|
|
190
209
|
download and boot).
|
|
@@ -204,6 +223,19 @@ Generated API docs through TypeDoc:
|
|
|
204
223
|
bun run build:doc:api
|
|
205
224
|
```
|
|
206
225
|
|
|
226
|
+
The `explain` censuses measure a RouterOS script corpus that lives in
|
|
227
|
+
[`tikoci/lsp-routeros-ts`](https://github.com/tikoci/lsp-routeros-ts), not in
|
|
228
|
+
this repo. `scripts/corpus-pin.json` records which snapshot centrs measures
|
|
229
|
+
against — a commit plus the blob's sha256 — and `corpus:fetch` downloads and
|
|
230
|
+
verifies it. A sibling `lsp-routeros-ts` checkout is used when present, and the
|
|
231
|
+
censuses print the source and hash they used:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
bun run corpus:fetch # download the pinned snapshot, verify its sha256
|
|
235
|
+
bun run explain:corpus-census # genre census (#203)
|
|
236
|
+
bun run explain:value-census # value-surface census (#225)
|
|
237
|
+
```
|
|
238
|
+
|
|
207
239
|
## Done definition (short version)
|
|
208
240
|
|
|
209
241
|
A feature is done when every line in `commands/<name>/examples.md` is green on
|
package/commands/AGENTS.md
CHANGED
|
@@ -3,9 +3,16 @@
|
|
|
3
3
|
Each `commands/<name>/` holds the **executable spec** for one command:
|
|
4
4
|
|
|
5
5
|
- `README.md` — intent, flags, behavior. The "designed" tier.
|
|
6
|
-
- `examples.md` — numbered, runnable examples
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
- `examples.md` — numbered, runnable examples mapped to named tests:
|
|
7
|
+
example N ↔ named test N. Live examples require CHR integration; offline
|
|
8
|
+
examples use the unit/fixture tests named by the command — a named test may
|
|
9
|
+
carry several assertions. Verification follows `docs/CONSTITUTION.md` →
|
|
10
|
+
Done definition.
|
|
11
|
+
|
|
12
|
+
**Implemented** flags are generated from `CliCommandMetadata` into
|
|
13
|
+
`docs/CLI.md` (`bun run docs:cli`; drift-gated in CI) — a command README keeps
|
|
14
|
+
behavior prose plus a "Designed, not implemented" table for spec-only flags,
|
|
15
|
+
never a duplicate table of implemented flags.
|
|
9
16
|
|
|
10
17
|
Do not restate the constitution here or in a command README — link to
|
|
11
18
|
`docs/CONSTITUTION.md` for envelope, errors, settings precedence, target
|
|
@@ -14,12 +21,14 @@ keys, ambiguity, `__default__`, comment-kv allowlist, write strategy) lives in
|
|
|
14
21
|
`commands/devices/README.md` — the registry command owns it; the constitution
|
|
15
22
|
keeps only the identity/CDB principle. A command file covers only what is
|
|
16
23
|
specific to that command. `docs/MATRIX.md` is the only status surface; a
|
|
17
|
-
README's "Status" line must agree with it.
|
|
24
|
+
README's "Status" line must agree with it. GitHub issues track the tasks and
|
|
25
|
+
dependencies within the selected capability; they do not replace its status.
|
|
18
26
|
|
|
19
27
|
## Verb vocabulary
|
|
20
28
|
|
|
21
29
|
Commands are centrs **verbs** (`retrieve`, `execute`, `api`, `devices`,
|
|
22
|
-
`discover`, `check`, `terminal`, `settings`), never one tool per
|
|
30
|
+
`discover`, `check`, `explain`, `terminal`, `settings`), never one tool per
|
|
31
|
+
RouterOS command. Open-ended follow
|
|
23
32
|
is folded into `api --stream` (no separate `stream` verb). Sub-verbs and their
|
|
24
33
|
aliases are canonical across CLI / API / MCP:
|
|
25
34
|
|
package/commands/api/AGENTS.md
CHANGED
|
@@ -183,11 +183,23 @@ green on CHR 7.23.1.
|
|
|
183
183
|
not `print`/`get`), so it is a `POST` and **write-classed** → needs `--yes`.
|
|
184
184
|
- **CONFIRMED — the inspect gate over both transports.** Path existence
|
|
185
185
|
(`request=child` empty ⇒ `validation/unknown-path`) and add/set attribute
|
|
186
|
-
validity (`request=child
|
|
186
|
+
validity (`request=child` ⇒ `validation/unknown-attribute`) fire
|
|
187
187
|
identically over rest-api and native-api, **before** any write — no `:put
|
|
188
188
|
[:parse]` involved (api input is a path, not a CLI string). A `/execute` script
|
|
189
189
|
is a CLI string ⇒ `meta.validation.semantic = "not-applicable"`.
|
|
190
190
|
|
|
191
|
+
## CONFIRMED ON CHR (RouterOS 7.12.2 compatibility — GH#343, 2026-09-14)
|
|
192
|
+
|
|
193
|
+
- **Command-level `request=completion` is unsafe on 7.12.2.** For
|
|
194
|
+
`path=system,identity,print`, REST did not answer before the 10 s client
|
|
195
|
+
timeout and native API closed the connection immediately. Adding
|
|
196
|
+
`.proplist=completion` did not change either result. The preceding `:parse`
|
|
197
|
+
and `request=child` controls returned in 1–8 ms on both transports, and
|
|
198
|
+
`child` contained the complete command argument list. Execute/API attribute
|
|
199
|
+
validation therefore uses command-level `request=child` only. This does not
|
|
200
|
+
prohibit argument-level completion probes such as `print,proplist`, which are
|
|
201
|
+
a separate shape and returned immediately on the same 7.12.2 controls.
|
|
202
|
+
|
|
191
203
|
## CONFIRMED ON CHR (Phase 4 `--stream` follow — CHR 7.23.1, 2026-06-30)
|
|
192
204
|
|
|
193
205
|
Validated by `test/integration/api-listen.test.ts` (L1–L4) on CHR 7.23.1.
|
package/commands/api/README.md
CHANGED
|
@@ -57,24 +57,25 @@ when a bare-collection `POST` carries create-looking fields.
|
|
|
57
57
|
|
|
58
58
|
## Flags
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
60
|
+
Implemented flags are generated from the CLI metadata into
|
|
61
|
+
[`docs/CLI.md` → api](../../docs/CLI.md#api); this file does not duplicate
|
|
62
|
+
that table, and `api` has no designed-but-unimplemented flags. Behavior notes
|
|
63
|
+
the generated reference cannot carry:
|
|
64
|
+
|
|
65
|
+
- `-f` values pass through verbatim (no type-guessing); `-d`/`--input`
|
|
66
|
+
collide with `-f` → `usage/conflicting-flags`.
|
|
67
|
+
- `--query`/`--filter` map to REST `.query` words / native `?` words.
|
|
68
|
+
- `--raw-query` is emitted as-is; the caller owns the stack — e.g.
|
|
69
|
+
`--raw-query type=ether --raw-query type=vlan --raw-query '#|'` (OR).
|
|
70
|
+
- `--via rest-api --stream` errors `transport/capability-unsupported`
|
|
71
|
+
(REST's 60 s cap cannot follow).
|
|
72
|
+
- Under `--stream`, `--format json`/`yaml` emit one compact envelope per
|
|
73
|
+
line (NDJSON); `text` emits a concise row per frame.
|
|
74
|
+
- The target/auth flags (`--host`, `--port`, `--username`, `--password`,
|
|
75
|
+
`--insecure`, `--timeout`, `--cdb-file`, `--cdb-password`, `--resolve`)
|
|
76
|
+
use the same single-target resolver as `retrieve`/`execute`; `--quickchr`
|
|
77
|
+
resolves host/port/auth from the live `@tikoci/quickchr` descriptor
|
|
78
|
+
instead (constitution: resolution providers).
|
|
78
79
|
|
|
79
80
|
## Fan-out (multi-target)
|
|
80
81
|
|
|
@@ -98,19 +99,48 @@ vs `--query` distinction.
|
|
|
98
99
|
|
|
99
100
|
## Validation
|
|
100
101
|
|
|
101
|
-
Default on. Because the input is a structured path (not a CLI string), the
|
|
102
|
-
`/console/inspect` — **not** `:put [:parse]`:
|
|
102
|
+
Default on. Because the input is a structured path (not a CLI string), the device
|
|
103
|
+
gate is `/console/inspect` — **not** `:put [:parse]`:
|
|
103
104
|
|
|
104
105
|
- Path existence + per-verb attribute validity via `request=child`
|
|
105
106
|
(`validation/unknown-path`, `validation/unknown-attribute`).
|
|
106
|
-
-
|
|
107
|
+
- **Designed, not implemented:** value-level advice via `request=completion`
|
|
108
|
+
(+`input=`) feeding `tips`/`warnings`. Whatever implements it must not fall
|
|
109
|
+
back to `request=completion` at a *command* path (`path=` ending at the verb):
|
|
110
|
+
that shape hangs REST and closes native API on RouterOS 7.12.2, and no centrs
|
|
111
|
+
code uses it. Completion at an *argument* path (`print,proplist`, as `retrieve`
|
|
112
|
+
does) answers normally on the same build. See the 7.12.2 finding in
|
|
113
|
+
`AGENTS.md` (GH#343).
|
|
107
114
|
- **Carve-out:** a script-shaped `POST /rest/execute` is a CLI string, not a path,
|
|
108
115
|
so the inspect gate is `not-applicable` (`meta.validation.semantic`); RouterOS
|
|
109
|
-
re-validates on the run.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
re-validates on the run. Until GH#354 that carve-out meant the script was sent
|
|
117
|
+
with *no* preflight at all. It is now gated by the offline stage (constitution:
|
|
118
|
+
validation) — the same analyzer `explain` publishes, run over the `script`
|
|
119
|
+
field with no connection, so a syntax fault is a byte span in
|
|
120
|
+
`error.context.span` instead of a round trip. `meta.validation.stages[]` shows
|
|
121
|
+
the offline stage `passed` and the device stage `skipped` with its reason. A
|
|
122
|
+
missing or blank `script` is still `input/invalid-command`, not a syntax
|
|
123
|
+
rejection.
|
|
124
|
+
- Structured path requests are **not** offline-gated. The input is a path plus a
|
|
125
|
+
body, not a CLI string, and an offline *path* gate collides with GH#211's
|
|
126
|
+
unlisted-path decision. On the success path `meta.validation.stages[]` is
|
|
127
|
+
absent there; on a `validation/*` rejection it is present and reports the
|
|
128
|
+
offline stage `skipped` with that reason, so the breakdown never implies an
|
|
129
|
+
analysis that did not run.
|
|
130
|
+
|
|
131
|
+
`--validate=false` skips **both** stages of the preflight — one flag, one meaning
|
|
132
|
+
(constitution: validation); RouterOS still re-validates writes server-side.
|
|
133
|
+
Disabling validation to make a call pass is forbidden (constitution: validation
|
|
134
|
+
is the product).
|
|
135
|
+
|
|
136
|
+
`--raw` **defaults** `--validate` to false — it does not override it (GH#154).
|
|
137
|
+
The resolution order is the explicit `--validate` flag, then `--raw`, then
|
|
138
|
+
`CENTRS_VALIDATE` / the CDB comment-kv / config, then the `true` default. So
|
|
139
|
+
`--raw` alone behaves as it always has and behaves the same on every machine
|
|
140
|
+
whatever the environment holds, while `--raw --validate=true` runs the gate and
|
|
141
|
+
reports a rejection in the `--raw` error shape (`{code,message}` on stderr,
|
|
142
|
+
nonzero exit, no `data` key) — which is how you debug `api` when centrs itself is
|
|
143
|
+
the suspect.
|
|
114
144
|
|
|
115
145
|
## Write confirmation
|
|
116
146
|
|