@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.
- package/README.md +31 -4
- 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
|
|
727
|
-
`
|
|
728
|
-
|
|
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` |
|
|
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