@tikoci/centrs 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/GLOSSARY.txt +284 -0
  3. package/LICENSE +21 -0
  4. package/README.md +55 -11
  5. package/SECURITY.md +3 -3
  6. package/commands/AGENTS.md +7 -1
  7. package/commands/api/README.md +46 -27
  8. package/commands/api/examples.md +124 -6
  9. package/commands/btest/README.md +21 -32
  10. package/commands/check/README.md +376 -53
  11. package/commands/check/examples.md +390 -0
  12. package/commands/devices/README.md +177 -37
  13. package/commands/devices/examples.md +148 -0
  14. package/commands/discover/README.md +5 -11
  15. package/commands/execute/README.md +73 -26
  16. package/commands/execute/examples.md +131 -9
  17. package/commands/explain/README.md +1716 -0
  18. package/commands/explain/examples.md +606 -0
  19. package/commands/retrieve/README.md +55 -71
  20. package/commands/retrieve/examples.md +56 -9
  21. package/commands/settings/README.md +286 -22
  22. package/commands/settings/examples.md +408 -0
  23. package/commands/terminal/README.md +6 -0
  24. package/commands/transfer/README.md +57 -19
  25. package/commands/transfer/examples.md +95 -0
  26. package/docs/CLI.md +353 -0
  27. package/docs/CONSTITUTION.md +102 -26
  28. package/docs/MATRIX.md +106 -173
  29. package/docs/errors/README.md +5 -1
  30. package/docs/errors/cdb/empty-selection.md +19 -0
  31. package/docs/errors/input/incomplete-gps.md +9 -0
  32. package/docs/errors/input/invalid-altitude.md +9 -0
  33. package/docs/errors/input/invalid-bbox.md +9 -0
  34. package/docs/errors/input/invalid-coordinate.md +9 -0
  35. package/docs/errors/input/invalid-radius.md +9 -0
  36. package/docs/errors/internal/settings-failed.md +9 -0
  37. package/docs/errors/quickchr/machine-not-found.md +22 -0
  38. package/docs/errors/quickchr/machine-stopped.md +20 -0
  39. package/docs/errors/quickchr/package-unavailable.md +27 -0
  40. package/docs/errors/quickchr/unsupported-via.md +35 -0
  41. package/docs/errors/quickchr/unsupported.md +35 -0
  42. package/docs/errors/routeros/version-unsupported.md +26 -0
  43. package/docs/errors/settings/consequential-value.md +26 -0
  44. package/docs/errors/settings/invalid-boolean.md +21 -3
  45. package/docs/errors/settings/invalid-format.md +18 -3
  46. package/docs/errors/settings/invalid-integer.md +18 -3
  47. package/docs/errors/settings/invalid-timeout.md +20 -3
  48. package/docs/errors/settings/invalid-via.md +22 -3
  49. package/docs/errors/settings/reserved-key.md +29 -0
  50. package/docs/errors/settings/skip-env-file-active.md +25 -0
  51. package/docs/errors/settings/unknown-key.md +25 -0
  52. package/docs/errors/transport/provider-trust.md +29 -0
  53. package/docs/errors/usage/fanout-not-supported.md +16 -0
  54. package/docs/errors/usage/stdin-ignored.md +28 -0
  55. package/docs/errors/validation/unknown-attribute.md +37 -4
  56. package/package.json +49 -14
  57. package/src/api-fanout.ts +469 -0
  58. package/src/api.ts +171 -56
  59. package/src/cli/api.ts +156 -13
  60. package/src/cli/btest.ts +38 -4
  61. package/src/cli/common.ts +11 -0
  62. package/src/cli/devices.ts +235 -6
  63. package/src/cli/discover.ts +3 -1
  64. package/src/cli/execute.ts +129 -9
  65. package/src/cli/explain.ts +503 -0
  66. package/src/cli/mcp.ts +8 -1
  67. package/src/cli/retrieve.ts +167 -90
  68. package/src/cli/selection.ts +260 -0
  69. package/src/cli/settings.ts +286 -0
  70. package/src/cli/terminal.ts +22 -7
  71. package/src/cli/transfer.ts +192 -51
  72. package/src/cli.ts +22 -2
  73. package/src/core/envelope.ts +5 -2
  74. package/src/core/error-catalog.ts +95 -0
  75. package/src/core/fanout.ts +143 -2
  76. package/src/core/preflight.ts +306 -0
  77. package/src/core/routeros-string.ts +24 -0
  78. package/src/devices.ts +212 -20
  79. package/src/discover.ts +7 -2
  80. package/src/errors.ts +1 -0
  81. package/src/execute-fanout.ts +453 -0
  82. package/src/execute.ts +216 -68
  83. package/src/explain/arg-tokens.ts +114 -0
  84. package/src/explain/args.ts +1403 -0
  85. package/src/explain/blocks.ts +132 -0
  86. package/src/explain/brace-slots.ts +143 -0
  87. package/src/explain/brace-tokens.ts +38 -0
  88. package/src/explain/catalog.ts +1345 -0
  89. package/src/explain/coordinates.ts +329 -0
  90. package/src/explain/defects.ts +217 -0
  91. package/src/explain/is-known-menu.ts +17 -0
  92. package/src/explain/menus.ts +664 -0
  93. package/src/explain/operator-tokens.ts +310 -0
  94. package/src/explain/operators.ts +458 -0
  95. package/src/explain/path-tokens.ts +150 -0
  96. package/src/explain/pathresolve.ts +1324 -0
  97. package/src/explain/quoted-string.ts +241 -0
  98. package/src/explain/scope-brace.ts +308 -0
  99. package/src/explain/segment.ts +757 -0
  100. package/src/explain/string-tokens.ts +67 -0
  101. package/src/explain/symbol-values.ts +520 -0
  102. package/src/explain/symbols.ts +1597 -0
  103. package/src/explain/token-ranges.ts +72 -0
  104. package/src/explain/transport.ts +497 -0
  105. package/src/explain/value-tokens.ts +80 -0
  106. package/src/explain/values.ts +357 -0
  107. package/src/explain/verbs.ts +64 -0
  108. package/src/explain/verbsplit.ts +813 -0
  109. package/src/explain/write.ts +815 -0
  110. package/src/explain.ts +2152 -0
  111. package/src/index.ts +307 -1
  112. package/src/mcp/config.ts +12 -2
  113. package/src/mcp/tools.ts +137 -2
  114. package/src/protocols/adapter.ts +38 -18
  115. package/src/protocols/index.ts +11 -5
  116. package/src/protocols/mac-telnet-console.ts +61 -17
  117. package/src/resolver/cdb.ts +10 -2
  118. package/src/resolver/comment-kv.ts +58 -4
  119. package/src/resolver/config-file.ts +136 -0
  120. package/src/resolver/facts.ts +78 -0
  121. package/src/resolver/geo.ts +453 -0
  122. package/src/resolver/index.ts +65 -0
  123. package/src/resolver/mac.ts +12 -3
  124. package/src/resolver/quickchr-provider.ts +597 -0
  125. package/src/resolver/selection.ts +391 -0
  126. package/src/resolver/service-endpoint.ts +155 -0
  127. package/src/resolver/settings.ts +54 -5
  128. package/src/resolver/target.ts +21 -3
  129. package/src/retrieve-fanout.ts +239 -133
  130. package/src/retrieve.ts +120 -25
  131. package/src/settings.ts +1078 -0
  132. package/src/terminal.ts +11 -1
  133. package/src/transfer-fanout.ts +544 -0
  134. package/src/transfer.ts +133 -40
package/src/retrieve.ts CHANGED
@@ -26,10 +26,14 @@ import {
26
26
  type RouterOsProtocol,
27
27
  } from "./protocols/index.ts";
28
28
  import {
29
+ assertNoQuickchrOverrideConflict,
29
30
  type CdbResolution,
30
31
  isIpTransport,
32
+ loadEnvFileDefaults,
31
33
  parseDuration,
32
34
  parseResolvePolicy,
35
+ type QuickchrResolution,
36
+ quickchrConnection,
33
37
  type ResolvedAuth,
34
38
  type ResolvedSetting,
35
39
  type ResolvedTarget,
@@ -38,6 +42,7 @@ import {
38
42
  resolveCdb,
39
43
  resolveMacTarget,
40
44
  resolveOptionalIntegerSetting,
45
+ resolveQuickchrTarget,
41
46
  resolveStringSetting,
42
47
  resolveTarget,
43
48
  toCoreSource,
@@ -48,6 +53,12 @@ export type RetrieveOutputFormat = (typeof retrieveOutputFormats)[number];
48
53
 
49
54
  export interface RetrieveRequest {
50
55
  targetInput?: string;
56
+ /**
57
+ * quickchr machine name (`--quickchr <name>`): resolve host/port/auth from
58
+ * the live VM descriptor instead of CDB/env (`docs/CONSTITUTION.md` →
59
+ * Resolution providers). Conflicts with host/port/username/password.
60
+ */
61
+ quickchr?: string;
51
62
  path: string;
52
63
  via?: string;
53
64
  host?: string;
@@ -122,6 +133,14 @@ export interface ResolvedRetrieveRequest {
122
133
  timeoutMs: ResolvedSetting<number>;
123
134
  format: ResolvedSetting<RetrieveOutputFormat>;
124
135
  validate: ResolvedSetting<boolean>;
136
+ /**
137
+ * Relax TLS peer verification. retrieve has no `--insecure` flag; this is set
138
+ * only by the quickchr provider (trust-by-provenance for the VM's self-signed
139
+ * TLS forward — see `src/resolver/quickchr-provider.ts`), so when present its
140
+ * source is always `provider` and it is surfaced as `meta.settings.insecure`
141
+ * for auditability.
142
+ */
143
+ insecure?: ResolvedSetting<boolean>;
125
144
  maxResultsBytes?: ResolvedSetting<number>;
126
145
  attributes: readonly string[];
127
146
  allAttributes: boolean;
@@ -160,6 +179,7 @@ export async function runResolvedRetrieve(
160
179
  username: resolved.auth.username,
161
180
  password: resolved.auth.password,
162
181
  timeoutMs: resolved.timeoutMs.value,
182
+ insecure: resolved.insecure?.value,
163
183
  });
164
184
 
165
185
  try {
@@ -211,7 +231,8 @@ export async function runResolvedRetrieve(
211
231
  "Check the attribute name, or use `--list-attributes` to inspect the available properties first.",
212
232
  context: {
213
233
  path: resolved.path,
214
- requested: resolved.attributes,
234
+ parameter: missing[0],
235
+ requestedAttributes: resolved.attributes,
215
236
  availableAttributes,
216
237
  },
217
238
  });
@@ -461,6 +482,9 @@ function metaFromResolved(
461
482
  timeoutMs: toCoreSource(resolved.timeoutMs.source),
462
483
  format: toCoreSource(resolved.format.source),
463
484
  validate: toCoreSource(resolved.validate.source),
485
+ insecure: resolved.insecure
486
+ ? toCoreSource(resolved.insecure.source)
487
+ : undefined,
464
488
  maxResultsBytes: resolved.maxResultsBytes
465
489
  ? toCoreSource(resolved.maxResultsBytes.source)
466
490
  : undefined,
@@ -618,9 +642,11 @@ export function buildResolvedRetrieve(
618
642
  cdbResolution: CdbResolution | undefined,
619
643
  attributeSelections: readonly string[],
620
644
  macResolution?: { mac: string; ip: string },
645
+ config: Record<string, string | undefined> = {},
646
+ quickchrResolution?: QuickchrResolution,
621
647
  ): ResolvedRetrieveRequest {
622
- const via = resolveProtocol(request, env, cdbResolution);
623
- const format = resolveFormat(request, env);
648
+ const via = resolveProtocol(request, env, cdbResolution, config);
649
+ const format = resolveFormat(request, env, config);
624
650
  const validate = resolveBooleanSetting(
625
651
  request.validate,
626
652
  env,
@@ -628,35 +654,50 @@ export function buildResolvedRetrieve(
628
654
  true,
629
655
  "validate",
630
656
  cdbResolution?.overrides.validate,
657
+ config,
631
658
  );
632
659
  const timeoutMs = resolveTimeoutSetting(
633
660
  request.timeout,
634
661
  env,
635
662
  via.value,
636
663
  cdbResolution?.overrides.timeoutMs,
664
+ config,
637
665
  );
638
666
  const maxResultsBytes = resolveOptionalIntegerSetting(
639
667
  request.maxResultsBytes,
640
668
  env,
641
669
  "CENTRS_MAX_RESULTS",
642
670
  "max-results",
671
+ undefined,
672
+ config,
643
673
  );
644
- const target = resolveTarget(
645
- {
646
- targetInput: request.targetInput,
647
- host: request.host,
648
- port: request.port,
649
- macResolution,
650
- },
651
- env,
652
- via.value,
653
- cdbResolution,
654
- );
655
- const auth = resolveAuth(
656
- { username: request.username, password: request.password },
657
- env,
658
- cdbResolution,
659
- );
674
+ // A quickchr member substitutes the live descriptor's per-`--via` endpoint
675
+ // for the CDB/env target+auth path (`docs/CONSTITUTION.md` → Resolution
676
+ // providers); everything else (via/format/validate/timeout) resolved above
677
+ // stays on the normal ladder.
678
+ const connection = quickchrResolution
679
+ ? quickchrConnection(quickchrResolution, via.value)
680
+ : null;
681
+ const target = connection
682
+ ? connection.target
683
+ : resolveTarget(
684
+ {
685
+ targetInput: request.targetInput,
686
+ host: request.host,
687
+ port: request.port,
688
+ macResolution,
689
+ },
690
+ env,
691
+ via.value,
692
+ cdbResolution,
693
+ );
694
+ const auth = connection
695
+ ? connection.auth
696
+ : resolveAuth(
697
+ { username: request.username, password: request.password },
698
+ env,
699
+ cdbResolution,
700
+ );
660
701
 
661
702
  return {
662
703
  path: request.path,
@@ -666,12 +707,24 @@ export function buildResolvedRetrieve(
666
707
  timeoutMs,
667
708
  format,
668
709
  validate,
710
+ insecure:
711
+ connection?.insecure === true && quickchrResolution
712
+ ? {
713
+ value: true,
714
+ source: {
715
+ kind: "provider" as const,
716
+ key: `quickchr:${quickchrResolution.name}`,
717
+ },
718
+ }
719
+ : undefined,
669
720
  maxResultsBytes,
670
721
  attributes: attributeSelections,
671
722
  allAttributes: request.allAttributes ?? false,
672
723
  listAttributes: request.listAttributes ?? false,
673
724
  verbose: request.verbose ?? false,
674
- warnings: cdbResolution?.warnings ?? [],
725
+ warnings: connection
726
+ ? [...connection.warnings]
727
+ : (cdbResolution?.warnings ?? []),
675
728
  };
676
729
  }
677
730
 
@@ -691,22 +744,33 @@ export function resolveRetrieveGlobalContext(
691
744
  request: RetrieveRequest,
692
745
  env: Record<string, string | undefined>,
693
746
  attributeSelections: readonly string[],
747
+ config: Record<string, string | undefined> = {},
694
748
  ): RetrieveGlobalContext {
695
- const via = resolveProtocol(request, env);
696
- const format = resolveFormat(request, env);
749
+ const via = resolveProtocol(request, env, undefined, config);
750
+ const format = resolveFormat(request, env, config);
697
751
  const validate = resolveBooleanSetting(
698
752
  request.validate,
699
753
  env,
700
754
  "CENTRS_VALIDATE",
701
755
  true,
702
756
  "validate",
757
+ undefined,
758
+ config,
759
+ );
760
+ const timeoutMs = resolveTimeoutSetting(
761
+ request.timeout,
762
+ env,
763
+ via.value,
764
+ undefined,
765
+ config,
703
766
  );
704
- const timeoutMs = resolveTimeoutSetting(request.timeout, env, via.value);
705
767
  const maxResultsBytes = resolveOptionalIntegerSetting(
706
768
  request.maxResultsBytes,
707
769
  env,
708
770
  "CENTRS_MAX_RESULTS",
709
771
  "max-results",
772
+ undefined,
773
+ config,
710
774
  );
711
775
 
712
776
  return {
@@ -739,6 +803,23 @@ export async function resolveRetrieveRequest(
739
803
  env: Record<string, string | undefined>,
740
804
  ): Promise<ResolvedRetrieveRequest> {
741
805
  const attributeSelections = validateRetrieveRequestShape(request);
806
+ const config = await loadEnvFileDefaults(env);
807
+
808
+ // A quickchr target bypasses CDB and MAC resolution entirely — the live
809
+ // descriptor is the only connection-fact source for those fields.
810
+ if (request.quickchr !== undefined) {
811
+ assertNoQuickchrOverrideConflict(request, request.quickchr);
812
+ const quickchrResolution = await resolveQuickchrTarget(request.quickchr);
813
+ return buildResolvedRetrieve(
814
+ request,
815
+ env,
816
+ undefined,
817
+ attributeSelections,
818
+ undefined,
819
+ config,
820
+ quickchrResolution,
821
+ );
822
+ }
742
823
 
743
824
  const cdbResolution = await resolveCdb(
744
825
  {
@@ -747,12 +828,14 @@ export async function resolveRetrieveRequest(
747
828
  cdbPassword: request.cdbPassword,
748
829
  },
749
830
  env,
831
+ config,
750
832
  );
751
833
 
752
834
  const macResolution = await resolveMacForRetrieve(
753
835
  request,
754
836
  env,
755
837
  cdbResolution,
838
+ config,
756
839
  );
757
840
 
758
841
  return buildResolvedRetrieve(
@@ -761,6 +844,7 @@ export async function resolveRetrieveRequest(
761
844
  cdbResolution,
762
845
  attributeSelections,
763
846
  macResolution,
847
+ config,
764
848
  );
765
849
  }
766
850
 
@@ -774,8 +858,9 @@ export async function resolveMacForRetrieve(
774
858
  request: RetrieveRequest,
775
859
  env: Record<string, string | undefined>,
776
860
  cdb?: CdbResolution,
861
+ config: Record<string, string | undefined> = {},
777
862
  ): Promise<{ mac: string; ip: string } | undefined> {
778
- if (!isIpTransport(resolveProtocol(request, env, cdb).value)) {
863
+ if (!isIpTransport(resolveProtocol(request, env, cdb, config).value)) {
779
864
  return undefined;
780
865
  }
781
866
  return resolveMacTarget({
@@ -783,7 +868,10 @@ export async function resolveMacForRetrieve(
783
868
  targetInput: request.targetInput,
784
869
  cdbTarget: cdb?.target,
785
870
  env,
786
- policy: parseResolvePolicy(request.resolve ?? env["CENTRS_RESOLVE"]),
871
+ config,
872
+ policy: parseResolvePolicy(
873
+ request.resolve ?? env["CENTRS_RESOLVE"] ?? config["CENTRS_RESOLVE"],
874
+ ),
787
875
  operation: "retrieve",
788
876
  });
789
877
  }
@@ -792,6 +880,7 @@ function resolveProtocol(
792
880
  request: RetrieveRequest,
793
881
  env: Record<string, string | undefined>,
794
882
  cdb?: CdbResolution,
883
+ config: Record<string, string | undefined> = {},
795
884
  ): ResolvedSetting<RouterOsProtocol> {
796
885
  const via = resolveStringSetting(
797
886
  request.via,
@@ -801,6 +890,7 @@ function resolveProtocol(
801
890
  "via",
802
891
  undefined,
803
892
  cdb?.overrides.via,
893
+ config,
804
894
  );
805
895
  if (!via) {
806
896
  throw new CentrsError({
@@ -859,6 +949,7 @@ function resolveProtocol(
859
949
  function resolveFormat(
860
950
  request: RetrieveRequest,
861
951
  env: Record<string, string | undefined>,
952
+ config: Record<string, string | undefined> = {},
862
953
  ): ResolvedSetting<RetrieveOutputFormat> {
863
954
  return resolveStringSetting(
864
955
  request.format,
@@ -867,6 +958,8 @@ function resolveFormat(
867
958
  "text",
868
959
  "format",
869
960
  parseOutputFormat,
961
+ undefined,
962
+ config,
870
963
  ) as ResolvedSetting<RetrieveOutputFormat>;
871
964
  }
872
965
 
@@ -990,6 +1083,7 @@ function resolveTimeoutSetting(
990
1083
  env: Record<string, string | undefined>,
991
1084
  via: RouterOsProtocol,
992
1085
  commentKv?: ResolvedSetting<number>,
1086
+ config: Record<string, string | undefined> = {},
993
1087
  ): ResolvedSetting<number> {
994
1088
  const resolved = resolveStringSetting(
995
1089
  timeout === undefined ? undefined : String(timeout),
@@ -1010,6 +1104,7 @@ function resolveTimeoutSetting(
1010
1104
  return parsed;
1011
1105
  },
1012
1106
  commentKv,
1107
+ config,
1013
1108
  );
1014
1109
  if (!resolved) {
1015
1110
  throw new Error("timeout resolution produced no value");