@johnhenry/wsh 0.27.0 → 0.27.1

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 (2) hide show
  1. package/README.md +31 -4
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -723,9 +723,9 @@ whoever supplies the `Server`/`Client`, and the package root stays
723
723
  dependency-free and browser-safe.
724
724
 
725
725
  **Compatibility.** Purely additive. Old clients never open `rpc` sessions; an old
726
- host (or the Rust `wsh-server`, which has no `rpc` kind yet) does not advertise
727
- `rpc`, so a new client fails fast with `UNSUPPORTED_PROTOCOL` instead of waiting
728
- on an `OpenFail`. Only `@johnhenry/wsh/server` serves `rpc` today. Not goals: a
726
+ host does not advertise `rpc`, so a new client fails fast with
727
+ `UNSUPPORTED_PROTOCOL` instead of waiting on an `OpenFail`. `@johnhenry/wsh/server`
728
+ and the Rust `wsh-server` (see below) serve `rpc` today. Not goals: a
729
729
  replacement for byte streams (exec/pty are unchanged), a new transport (`rpc`
730
730
  rides WebSocket/QMux and WebTransport streams), or an auth change -- an `rpc`
731
731
  session is opened on an authenticated connection and per-method authorization is
@@ -733,6 +733,33 @@ the handler's job (`-32003`; `ctx.user` / `ctx.fingerprint` identify the caller)
733
733
  Handlers run per channel, so register methods synchronously (or before the
734
734
  returned promise settles: inbound messages are held until it does).
735
735
 
736
+ **The Rust `wsh-server`** (since `rust-v0.4.0`) serves `wsh-host` and `wsh-fs`
737
+ exactly as the JS server does -- same features, methods, parameters, results,
738
+ error codes and messages, same CBOR-sequence decoder and size bound, same
739
+ `$/cancel` / `$/progress` -- over a WebSocket (QMux) connection. It does not
740
+ serve `mcp` (hosting an MCP server is an embedding concern) and does not offer
741
+ `rpc` on the native WebTransport listener, whose single control stream has no
742
+ client-opened data streams to carry a channel. `wsh-host` is on by default;
743
+ `wsh-fs` is **off until you give it a root** (file access is opt-in), and is
744
+ confined to it the way the JS `fs` option is. In `~/.wsh/config.toml`:
745
+
746
+ ```toml
747
+ [rpc]
748
+ enabled = true # default; false turns rpc off entirely
749
+ max_message_bytes = 1048576 # advertised as rpc-max-message:<n>; at least 256
750
+ max_inflight = 64 # concurrent requests per channel before -32002
751
+ fs_root = "/srv/files" # unset (the default): wsh-fs is not offered
752
+ fs_read_only = false
753
+ fs_max_file_bytes = 67108864
754
+ ```
755
+
756
+ Key options apply as they do to other channels: a key restricted to a forced
757
+ command opens no rpc channel, and `wsh-fs` needs the `file-transfer` scope
758
+ (`permit-file-transfer` under `restrict`). `host.info` reports the crate version
759
+ and `hostFingerprint: null` (the Rust server has no host key). The JS client
760
+ needs nothing new: it reads `rpc` from `ServerHello`, and its file helpers prefer
761
+ `wsh-fs` automatically once the server offers it.
762
+
736
763
  ## Attach and Resume
737
764
 
738
765
  Opening a PTY/exec session returns a session-scoped credential alongside the channel:
@@ -912,7 +939,7 @@ than left to be found.
912
939
  | Remove a remote file | `WshClient.fileRemove()` | `file_transfer::remove()`, `wsh sftp`'s `rm` | **Wire-unified**: `FileOp`/`FileResult` (`op: "remove"`) -- refused today by every `wsh-server` release ("not yet implemented"), the same refusal on both sides |
913
940
  | Install an authorized key | `WshClient.addAuthorizedKey()` | `wsh_client::WshClient::add_authorized_key()`, `wsh copy-id` | **Wire-unified** (wsh #59): `AuthorizedKeyAdd`/`AuthorizedKeyResult`, replacing a Rust-CLI-only shell command with a message every implementation can send |
914
941
  | Host identity / TOFU | `WshKnownHosts` (localStorage-backed) | `KnownHosts`/`HostStatus` (`~/.wsh/known_hosts`-backed) | **Record unified, policy is not** (wsh #59): both pin `ServerHello.host_fingerprint`, which `@johnhenry/wsh/server` populates (with a proof of possession, [Host key](#host-key-fingerprint--tofu)) but no Rust `wsh-server` release does yet (see [Security](#security-model)). *When* to trust, prompt, or persist is deliberately left per-implementation -- a browser and a CLI have different UX for "first time seeing this host" |
915
- | Typed RPC channels (`openRpc`, `rpc` sessions; `wsh-host`, `wsh-fs`, `mcp`) | `WshClient.openRpc()`, `RpcChannel` | none yet (a Rust `wsh-server` does not advertise `rpc`; a JS client falls back to `FileOp` for files) | **JS server only, no wire change**: `Open { kind: 'rpc', command: <protocol> }` plus `rpc*` `ServerHello` features, negotiated so it fails fast elsewhere |
942
+ | Typed RPC channels (`openRpc`, `rpc` sessions; `wsh-host`, `wsh-fs`, `mcp`) | `WshClient.openRpc()`, `RpcChannel` | Rust `wsh-server` (`rust-v0.4.0`+): `wsh-host`, and `wsh-fs` when `[rpc] fs_root` is set; no client yet in `wsh-client` | **No wire change**: `Open { kind: 'rpc', command: <protocol> }` plus `rpc*` `ServerHello` features, negotiated so it fails fast elsewhere; the Rust server serves it on WebSocket/QMux only |
916
943
  | Interactive shell UI | none -- this SDK is a protocol client, not a terminal emulator; pair with xterm.js/ghostty-web | `wsh connect`, `wsh sftp` (line-oriented REPL) | **Deliberately not unified** -- a browser embeds a terminal widget the host page owns; a CLI process owns its own TTY |
917
944
  | Attach / resume | `attachSession()`, `resumeSession()`, `WshSession.seq` | `attach_session()`, `resume_session()` | **Wire-unified** (`Attach`/`Resume`/`Presence`); `seq` = cumulative output bytes. `@johnhenry/wsh/server` honours `last_seq` (bounded ring, gap errors) and answers Presence with `channel_id`/`seq`; the Rust `wsh-server` does the same (`rust-v0.2.0`+; fixed 256 KiB ring) |
918
945
  | Reverse-connect / relay peer | `connectReverse()`, `trustRelayPeer()`; `@johnhenry/wsh/server`: `relay` option and `createReverseHost()` | `wsh reverse`, `wsh agent` (persistent, with startup-unit install) | **Wire-unified** (registration, discovery, signed peer records); **daemonization is CLI-only** -- a browser tab cannot be a background OS service. The Node relay is default-deny and bridges one operator per peer (`busy:` reasons say so); E2E and bridged feature gates need `rust-v0.3.0`+ on the Rust side |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnhenry/wsh",
3
- "version": "0.27.0",
3
+ "version": "0.27.1",
4
4
  "description": "Web Shell \u2014 browser-native remote command execution over WebTransport and WebSocket with Ed25519 authentication",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",