@atbash/cli 0.5.12 → 0.5.14

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/README.md CHANGED
@@ -305,8 +305,58 @@ The agent is not trusted to know when it should stop. If the agent could loosen
305
305
 
306
306
  `atbash tier --org <name>` shows the current tier for an org.
307
307
 
308
+ ## Verifying this CLI before you run it (humans & AI agents)
309
+
310
+ `atbash connect` reads your local agent / MCP config and relays it to your onboarding session. Being cautious about that is correct — so the command is built to be **verified, not merely trusted**. Before running it you can independently confirm the three things that separate the real tool from a look-alike:
311
+
312
+ 1. **What it will do — without sending anything.** Append `--dry-run`:
313
+ ```bash
314
+ npx --yes @atbash/cli connect <CODE> --host <HOST> --dry-run --json
315
+ ```
316
+ It runs the same read-only scan and prints the exact destination URL and the exact payload it *would* send, then exits. Nothing leaves the machine.
317
+
318
+ 2. **That the package matches the artifact the Atbash deployment attests.** The
319
+ CLI repository is private, so npm provenance is not currently available. Compare
320
+ the exact version's registry integrity with the dashboard's same-origin manifest:
321
+ ```bash
322
+ curl -s https://<HOST>/api/cli-releases
323
+ npm view @atbash/cli@<VERSION> dist.integrity
324
+ ```
325
+ Matching values prove the tarball matches what that deployment vouches for; they
326
+ do not prove it was built from a particular source commit.
327
+
328
+ 3. **Where it sends and what it sends.** Exactly one POST, only to the `--host` you pass (HTTPS required; an unrecognized host is refused unless explicitly allowed). It relays agent / tool / skill **names**, sanitized MCP endpoint URLs and launch-command basenames — never tokens, auth headers, env values, or file contents.
329
+
330
+ If any check fails — an integrity value that does not match the deployment's manifest, an unexpected destination, or a dry-run payload containing anything sensitive — **don't run it.** Those are exactly the signals a malicious clone cannot fake.
331
+
308
332
  ## Command reference
309
333
 
334
+ ### `atbash connect <code>`
335
+
336
+ Link a machine to a hosted Atbash onboarding session. A browser can't read your disk and the Atbash server only sees its own, so this runs on the machine you want to govern, enumerates the agents / MCP tools configured there (read-only), and relays their *surface* to your onboarding session via the one-time pairing code shown in the browser.
337
+
338
+ ```bash
339
+ # Pair this machine (code comes from the "Scan another machine" screen):
340
+ npx --yes @atbash/cli connect G9MB-TS3U --host https://your-atbash-host
341
+
342
+ # Verify first — same scan, prints destination + payload, sends nothing:
343
+ npx --yes @atbash/cli connect G9MB-TS3U --host https://your-atbash-host --dry-run
344
+ ```
345
+
346
+ | Flag | Description |
347
+ |------|-------------|
348
+ | `--host <url>` | Atbash deployment hosting your session (HTTPS required) |
349
+ | `--dry-run` | Do the scan and print exactly what would be sent, then exit WITHOUT sending |
350
+ | `--json` | Machine-readable output (for agents / automation) |
351
+ | `--home <dir>` | Home directory to scan (for testing) |
352
+ | `--introspect` | Opt in to starting configured MCP servers locally and listing their advertised surface; no tools are called |
353
+ | `--allow-unrecognized-host` | Explicitly permit a host outside the built-in Atbash allowlist |
354
+
355
+ Default discovery is read-only and sends one request. `--introspect` starts and stops
356
+ configured MCP server processes, so it is not purely read-only even though Atbash
357
+ never invokes their tools. See [Verifying this CLI](#verifying-this-cli-before-you-run-it-humans--ai-agents)
358
+ and the [release checklist](RELEASE_CHECKLIST.md).
359
+
310
360
  ### `atbash judge <action>`
311
361
 
312
362
  Submit a pending action for judgment. The action string is the exact operation the agent is about to execute — a transfer, a command, a mutation.
File without changes
@@ -2,12 +2,23 @@ import { Command } from "commander";
2
2
  interface DeclaredTool {
3
3
  name: string;
4
4
  description?: string;
5
+ /** Sanitized JSON-Schema shape (from MCP introspection) — structure only. */
6
+ inputSchema?: unknown;
7
+ }
8
+ interface SurfaceEvidence {
9
+ source: "local-declaration" | "mcp-tools-list" | "manifest";
10
+ status: "complete" | "incomplete";
11
+ transport?: "http" | "stdio";
12
+ server?: string;
13
+ observedAt?: string;
14
+ error?: string;
5
15
  }
6
16
  type Agent = {
7
17
  type: "declared";
8
18
  label: string;
9
19
  detail: string;
10
20
  declaredTools: DeclaredTool[];
21
+ surfaceEvidence?: SurfaceEvidence;
11
22
  } | {
12
23
  type: "config";
13
24
  label: string;
@@ -16,11 +27,29 @@ type Agent = {
16
27
  mcpServers: Record<string, unknown>;
17
28
  };
18
29
  };
19
- /** One-line skill description from SKILL.md frontmatter `description:` or first heading. */
30
+ /** One-line skill description from SKILL.md frontmatter `description:` or first heading.
31
+ * Frontmatter is parsed with a real YAML parser (handles quotes, block scalars,
32
+ * folded/multiline values and nested maps that the previous regex mis-read). */
20
33
  declare function describeSkill(text: string | undefined, fallback: string): string;
34
+ /** Descriptions are useful capability evidence, but never worth relaying a
35
+ * credential or binary/control content from an untrusted local skill file. */
36
+ declare function safeDescription(raw: string): string | undefined;
21
37
  /** Walk a skills root (bounded) → declared tools. Mirrors src/lib/scan/adapters/local-skills.ts. */
22
38
  declare function enumerateSkills(root: string, maxDepth?: number, cap?: number): DeclaredTool[];
39
+ /**
40
+ * THE sanitization boundary. Reduce an mcpServers map to the SANITIZED structural
41
+ * signal the hosted scanner needs — server name, host+path of the endpoint, and
42
+ * executable basename — and nothing else. Every value that could carry a live
43
+ * secret or PII (env, headers, token, apiKey, args, url credentials, absolute
44
+ * command paths) is dropped or reduced. The connector relays the tool SURFACE,
45
+ * never secrets. Raw specs from `readAllMcpServers()` MUST pass through here before
46
+ * entering any relayed `Agent`.
47
+ *
48
+ * Caps the map at MAX_RELAY_SERVERS. Callers are expected to compare the returned
49
+ * size against the input size and label the result partial — see `discover()`.
50
+ */
51
+ declare function relaySafeServers(servers: Record<string, unknown>): Record<string, unknown>;
23
52
  /** Enumerate the agents/MCP tools configured on this machine. Read-only. */
24
53
  declare function discover(home: string): Agent[];
25
54
  export declare function registerConnectCommand(program: Command): void;
26
- export { discover, enumerateSkills, describeSkill };
55
+ export { discover, enumerateSkills, describeSkill, relaySafeServers, safeDescription };