@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.
- package/CHANGELOG.md +207 -0
- package/GLOSSARY.txt +420 -0
- package/README.md +196 -0
- package/SECURITY.md +30 -0
- package/commands/AGENTS.md +50 -0
- package/commands/btest/README.md +257 -0
- package/commands/btest/examples.md +190 -0
- package/commands/check/README.md +59 -0
- package/commands/devices/README.md +405 -0
- package/commands/devices/examples.md +488 -0
- package/commands/discover/README.md +170 -0
- package/commands/discover/examples.md +98 -0
- package/commands/execute/README.md +208 -0
- package/commands/execute/examples.md +353 -0
- package/commands/mcp/README.md +260 -0
- package/commands/mcp/examples.md +158 -0
- package/commands/retrieve/README.md +209 -0
- package/commands/retrieve/examples.md +306 -0
- package/commands/settings/README.md +69 -0
- package/commands/stream/README.md +70 -0
- package/commands/terminal/README.md +177 -0
- package/commands/terminal/examples.md +144 -0
- package/commands/transfer/README.md +315 -0
- package/commands/transfer/examples.md +368 -0
- package/docs/CONSTITUTION.md +417 -0
- package/docs/MATRIX.md +224 -0
- package/docs/errors/README.md +74 -0
- package/docs/errors/auth/failed.md +9 -0
- package/docs/errors/cdb/already-exists.md +9 -0
- package/docs/errors/cdb/created.md +9 -0
- package/docs/errors/cdb/decrypt-failed.md +9 -0
- package/docs/errors/cdb/empty-group.md +9 -0
- package/docs/errors/cdb/invalid-option.md +9 -0
- package/docs/errors/cdb/invalid-record.md +9 -0
- package/docs/errors/cdb/not-found-target.md +9 -0
- package/docs/errors/cdb/not-found.md +9 -0
- package/docs/errors/cdb/override-applied.md +9 -0
- package/docs/errors/cdb/parse-failed.md +9 -0
- package/docs/errors/cdb/password-not-needed.md +9 -0
- package/docs/errors/cdb/password-required.md +9 -0
- package/docs/errors/cdb/reserved-key.md +9 -0
- package/docs/errors/cdb/reserved-option.md +9 -0
- package/docs/errors/cdb/target-not-registered.md +9 -0
- package/docs/errors/cdb/unknown-field.md +9 -0
- package/docs/errors/cdb/unknown-option.md +9 -0
- package/docs/errors/cdb/write-not-permitted.md +9 -0
- package/docs/errors/discover/broadcast-unavailable.md +9 -0
- package/docs/errors/discover/failed.md +9 -0
- package/docs/errors/identity/ambiguous.md +9 -0
- package/docs/errors/identity/no-match.md +9 -0
- package/docs/errors/input/invalid-command.md +9 -0
- package/docs/errors/input/invalid-match.md +9 -0
- package/docs/errors/input/invalid-path.md +9 -0
- package/docs/errors/input/invalid-routeros-path.md +9 -0
- package/docs/errors/input/invalid-target.md +9 -0
- package/docs/errors/input/local-file-not-found.md +9 -0
- package/docs/errors/input/mac-address.md +9 -0
- package/docs/errors/input/max-results-exceeded.md +9 -0
- package/docs/errors/internal/devices-failed.md +9 -0
- package/docs/errors/internal/mcp-start.md +9 -0
- package/docs/errors/internal/mcp-tool.md +9 -0
- package/docs/errors/internal/native-api-length.md +9 -0
- package/docs/errors/internal/unhandled.md +9 -0
- package/docs/errors/internal/unreachable.md +9 -0
- package/docs/errors/mndp/encode-failed.md +9 -0
- package/docs/errors/mndp/listen-failed.md +9 -0
- package/docs/errors/mndp/malformed.md +9 -0
- package/docs/errors/routeros/api-fatal.md +9 -0
- package/docs/errors/routeros/api-protocol.md +9 -0
- package/docs/errors/routeros/api-trap.md +9 -0
- package/docs/errors/routeros/btest-protocol.md +12 -0
- package/docs/errors/routeros/btest-too-many-sessions.md +9 -0
- package/docs/errors/routeros/command-failed.md +14 -0
- package/docs/errors/routeros/ec-srp5-protocol.md +11 -0
- package/docs/errors/routeros/error.md +9 -0
- package/docs/errors/routeros/invalid-value.md +14 -0
- package/docs/errors/routeros/mac-telnet-error.md +9 -0
- package/docs/errors/routeros/mac-telnet-not-ready.md +9 -0
- package/docs/errors/routeros/mac-telnet-protocol.md +9 -0
- package/docs/errors/routeros/mac-telnet-unsupported-auth.md +9 -0
- package/docs/errors/routeros/protocol-not-implemented.md +9 -0
- package/docs/errors/routeros/request-failed.md +9 -0
- package/docs/errors/routeros/session-closed.md +13 -0
- package/docs/errors/routeros/unknown-attribute.md +13 -0
- package/docs/errors/routeros/unknown-path.md +15 -0
- package/docs/errors/routeros/unsupported-capability.md +9 -0
- package/docs/errors/settings/invalid-boolean.md +9 -0
- package/docs/errors/settings/invalid-format.md +9 -0
- package/docs/errors/settings/invalid-integer.md +9 -0
- package/docs/errors/settings/invalid-timeout.md +9 -0
- package/docs/errors/settings/invalid-via.md +9 -0
- package/docs/errors/settings/unsafe-protocol-blocked.md +9 -0
- package/docs/errors/target/mac-not-in-arp.md +14 -0
- package/docs/errors/target/mac-required.md +23 -0
- package/docs/errors/target/mac-unresolved.md +17 -0
- package/docs/errors/target/unresolved.md +9 -0
- package/docs/errors/transport/auth-failed.md +9 -0
- package/docs/errors/transport/auto-method.md +9 -0
- package/docs/errors/transport/capability-unsupported.md +22 -0
- package/docs/errors/transport/checksum-unavailable.md +9 -0
- package/docs/errors/transport/connection-closed.md +9 -0
- package/docs/errors/transport/connection-refused.md +9 -0
- package/docs/errors/transport/dns.md +9 -0
- package/docs/errors/transport/host-key-mismatch.md +9 -0
- package/docs/errors/transport/incomplete-transfer.md +9 -0
- package/docs/errors/transport/insecure-trust.md +9 -0
- package/docs/errors/transport/local-tool-missing.md +11 -0
- package/docs/errors/transport/network.md +9 -0
- package/docs/errors/transport/timeout.md +9 -0
- package/docs/errors/transport/tls-certificate.md +9 -0
- package/docs/errors/transport/unreachable.md +9 -0
- package/docs/errors/transport/unsupported-operation.md +9 -0
- package/docs/errors/usage/confirmation-required.md +9 -0
- package/docs/errors/usage/conflicting-flags.md +9 -0
- package/docs/errors/usage/invalid-concurrency.md +9 -0
- package/docs/errors/usage/missing-group.md +9 -0
- package/docs/errors/usage/not-implemented.md +9 -0
- package/docs/errors/usage/target-exists.md +9 -0
- package/docs/errors/usage/timeout-out-of-range.md +9 -0
- package/docs/errors/validation/not-implemented.md +9 -0
- package/docs/errors/validation/option.md +9 -0
- package/docs/errors/validation/syntax.md +9 -0
- package/docs/errors/validation/unknown-attribute.md +9 -0
- package/docs/errors/validation/unknown-path.md +9 -0
- package/package.json +96 -0
- package/src/AGENTS.md +7 -0
- package/src/btest.ts +906 -0
- package/src/cli/btest.ts +455 -0
- package/src/cli/common.ts +53 -0
- package/src/cli/devices.ts +527 -0
- package/src/cli/discover.ts +186 -0
- package/src/cli/execute.ts +333 -0
- package/src/cli/mcp.ts +109 -0
- package/src/cli/retrieve.ts +383 -0
- package/src/cli/terminal.ts +303 -0
- package/src/cli/transfer.ts +471 -0
- package/src/cli.ts +115 -0
- package/src/core/envelope.ts +221 -0
- package/src/core/error-catalog.ts +469 -0
- package/src/core/routeros-errors.ts +268 -0
- package/src/data/AGENTS.md +11 -0
- package/src/data/dude-db.ts +0 -0
- package/src/data/mndp-cache.ts +132 -0
- package/src/data/mndp.ts +405 -0
- package/src/data/winbox-cdb-write.ts +200 -0
- package/src/data/winbox-cdb.ts +913 -0
- package/src/devices-schema.ts +107 -0
- package/src/devices.ts +1717 -0
- package/src/discover.ts +802 -0
- package/src/errors.ts +189 -0
- package/src/execute.ts +1350 -0
- package/src/index.ts +353 -0
- package/src/mcp/config.ts +66 -0
- package/src/mcp/resources.ts +98 -0
- package/src/mcp/safety.ts +119 -0
- package/src/mcp/server.ts +225 -0
- package/src/mcp/tools.ts +657 -0
- package/src/mcp.ts +33 -0
- package/src/protocols/AGENTS.md +14 -0
- package/src/protocols/adapter.ts +866 -0
- package/src/protocols/btest-session.ts +1493 -0
- package/src/protocols/btest.ts +447 -0
- package/src/protocols/ec-srp5.ts +466 -0
- package/src/protocols/index.ts +118 -0
- package/src/protocols/mac-telnet-console.ts +655 -0
- package/src/protocols/mac-telnet.ts +1299 -0
- package/src/protocols/mtwei.ts +47 -0
- package/src/protocols/native-api.ts +796 -0
- package/src/protocols/sftp.ts +427 -0
- package/src/protocols/ssh.ts +297 -0
- package/src/resolver/cdb.ts +580 -0
- package/src/resolver/comment-kv.ts +360 -0
- package/src/resolver/index.ts +74 -0
- package/src/resolver/mac.ts +227 -0
- package/src/resolver/settings.ts +228 -0
- package/src/resolver/target.ts +442 -0
- package/src/retrieve-fanout.ts +533 -0
- package/src/retrieve.ts +1215 -0
- package/src/terminal.ts +444 -0
- package/src/transfer.ts +1554 -0
- package/src/tui.ts +22 -0
- package/src/webproxy.ts +16 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical Zod model for a WinBox-CDB **device record**.
|
|
3
|
+
*
|
|
4
|
+
* This is the typed source of truth for a device record — the logical shape that
|
|
5
|
+
* `devices add`/`set` accept and that `buildWinBoxCdbEntryRecord` renders into
|
|
6
|
+
* CDB bytes. The CDB is *one rendering* of this model, not the model itself.
|
|
7
|
+
* Keeping it here — outside prose and the CDB key/value codec — is what lets a
|
|
8
|
+
* future JSON/YAML device representation (JG-19) and the interactive
|
|
9
|
+
* devices-edit TUI (JG-22) share one validated contract.
|
|
10
|
+
*
|
|
11
|
+
* Scope is deliberately **device-records-first** (per the plan): it validates
|
|
12
|
+
* mutation input, stays permissive about target/profile *formats* (a target may
|
|
13
|
+
* be IPv4/IPv6/MAC, optionally `host:port`; a profile may be a `<none>`/own
|
|
14
|
+
* sentinel), and is **lenient about `recordType`** — the CDB decoder preserves
|
|
15
|
+
* record types centrs does not name yet ({@link recordTypeName} → `unknown(N)`),
|
|
16
|
+
* so the model must round-trip them. The strict record-type *name* check stays
|
|
17
|
+
* at the `add` CLI boundary, where a human types a name. Settings and the read
|
|
18
|
+
* (decode) path are out of scope until this layer stays clean.
|
|
19
|
+
*/
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import { winBoxCdbRecordType } from "./data/winbox-cdb.ts";
|
|
22
|
+
import { CentrsError } from "./errors.ts";
|
|
23
|
+
|
|
24
|
+
/** Record-type names a human can supply (the strict, user-facing set). */
|
|
25
|
+
export const recordTypeNames: readonly string[] =
|
|
26
|
+
Object.keys(winBoxCdbRecordType);
|
|
27
|
+
|
|
28
|
+
/** True when `value` is a record type centrs names (vs. a preserved unknown). */
|
|
29
|
+
export function isKnownRecordType(value: number): boolean {
|
|
30
|
+
return (Object.values(winBoxCdbRecordType) as number[]).includes(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The logical device record. Field semantics mirror `commands/devices/README.md`
|
|
35
|
+
* and the WinBox CDB field tags (`src/data/winbox-cdb.ts`).
|
|
36
|
+
*/
|
|
37
|
+
export const deviceRecordSchema = z.object({
|
|
38
|
+
/**
|
|
39
|
+
* WinBox CDB record-type tag. Lenient (non-negative int) so a decoded record
|
|
40
|
+
* with a not-yet-named type round-trips; {@link isKnownRecordType} is the
|
|
41
|
+
* strict check for user-supplied types.
|
|
42
|
+
*/
|
|
43
|
+
recordType: z.number().int().nonnegative(),
|
|
44
|
+
/**
|
|
45
|
+
* Address or MAC (optionally `host:port`); the record's natural identity with
|
|
46
|
+
* `user`. Must be non-blank.
|
|
47
|
+
*/
|
|
48
|
+
target: z
|
|
49
|
+
.string()
|
|
50
|
+
.refine(
|
|
51
|
+
(s) => s.trim().length > 0,
|
|
52
|
+
"a device record needs a non-blank target",
|
|
53
|
+
),
|
|
54
|
+
user: z.string().optional(),
|
|
55
|
+
password: z.string().optional(),
|
|
56
|
+
session: z.string().optional(),
|
|
57
|
+
comment: z.string().optional(),
|
|
58
|
+
group: z.string().optional(),
|
|
59
|
+
profile: z.string().optional(),
|
|
60
|
+
savedPassword: z.boolean().optional(),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export type DeviceRecord = z.infer<typeof deviceRecordSchema>;
|
|
64
|
+
|
|
65
|
+
function remediationFor(field: string): string {
|
|
66
|
+
switch (field) {
|
|
67
|
+
case "(record)":
|
|
68
|
+
return "Pass a device record object with at least `recordType` (a non-negative integer) and a non-blank `target`.";
|
|
69
|
+
case "target":
|
|
70
|
+
return "Pass a non-blank address or MAC (optionally host:port) as the target.";
|
|
71
|
+
case "recordType":
|
|
72
|
+
return `Record type must be a non-negative integer; the named types are ${recordTypeNames.join(", ")}.`;
|
|
73
|
+
default:
|
|
74
|
+
return "Check the device-record field types: strings for user/password/session/comment/group/profile, a boolean for savedPassword.";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Validate a logical device record, returning the typed value or throwing a
|
|
80
|
+
* `cdb/invalid-record` {@link CentrsError}. The mutation path (`addDevice`,
|
|
81
|
+
* `setDevice`) runs this before rendering to CDB, so a malformed record (blank
|
|
82
|
+
* target, wrong field type) fails with an actionable error for *every* caller —
|
|
83
|
+
* CLI, MCP, and a future JSON/YAML import — not just the CLI's own guards.
|
|
84
|
+
*/
|
|
85
|
+
export function parseDeviceRecord(input: unknown): DeviceRecord {
|
|
86
|
+
const result = deviceRecordSchema.safeParse(input);
|
|
87
|
+
if (result.success) {
|
|
88
|
+
return result.data;
|
|
89
|
+
}
|
|
90
|
+
// An empty issue path means the input was not a record object at all
|
|
91
|
+
// (e.g. a string/null), so blame the record rather than a named field.
|
|
92
|
+
const issue = result.error.issues[0];
|
|
93
|
+
const field =
|
|
94
|
+
issue && issue.path.length > 0 ? issue.path.join(".") : "(record)";
|
|
95
|
+
throw new CentrsError({
|
|
96
|
+
code: "cdb/invalid-record",
|
|
97
|
+
summary: `Invalid device record: ${field} — ${issue?.message ?? "failed validation"}.`,
|
|
98
|
+
remediation: remediationFor(field),
|
|
99
|
+
context: { field },
|
|
100
|
+
// Flattened Zod issues for debugging — summarized, not the raw error.
|
|
101
|
+
causeData: result.error.issues.map((i) => ({
|
|
102
|
+
path: i.path.join("."),
|
|
103
|
+
code: i.code,
|
|
104
|
+
message: i.message,
|
|
105
|
+
})),
|
|
106
|
+
});
|
|
107
|
+
}
|