@hyzyn/dsh-tty 0.21.0 → 0.22.0-rc.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.en.md +48 -3
- package/README.md +63 -3
- package/client.js +135 -36
- package/lib/index.d.ts +51 -0
- package/lib/index.js +501 -98
- package/lib/index.js.map +1 -1
- package/lib/probe.d.ts +29 -1
- package/lib/probe.js +98 -19
- package/lib/probe.js.map +1 -1
- package/lib/sftp.js +37 -9
- package/lib/sftp.js.map +1 -1
- package/lib/ssh-config.d.ts +34 -2
- package/lib/ssh-config.js +150 -32
- package/lib/ssh-config.js.map +1 -1
- package/lib/ssh.d.ts +256 -2
- package/lib/ssh.js +637 -6
- package/lib/ssh.js.map +1 -1
- package/lib/tunnels.js +47 -5
- package/lib/tunnels.js.map +1 -1
- package/package.json +4 -2
- package/scripts/integration.mjs +51 -19
- package/scripts/jump-smoke.mjs +175 -0
- package/scripts/lib/proxy-bridge.mjs +30 -0
- package/scripts/preview/harness.js +74 -26
- package/scripts/probe-route-smoke.mjs +10 -1
- package/scripts/proxycommand-smoke.mjs +267 -0
- package/scripts/windows-smoke.mjs +23 -0
package/README.en.md
CHANGED
|
@@ -109,7 +109,7 @@ The plugin injects sixteen tools into the agent (with the same power as the bash
|
|
|
109
109
|
| `tty_stats` | Read live host metrics for a session’s machine (0.20.0): CPU / memory / disk / TCP connections / network rates / temperature / uptime. Local sessions report the host; SSH sessions report that remote host over a separate non-PTY channel that never touches the terminal. Check it before deploying or load-testing |
|
|
110
110
|
| `tty_capture` | Read recent output (last N lines, ANSI stripped by default, `raw:true` for the raw stream); **`last:true` returns only the output + exit code of the previous completed command** (shell integration markers, see the next section); when a command is **in flight** (just sent, completion marker not in yet) it returns `inProgress:true` without the stale result, so the previous command is never mistaken for this one (0.19.0) |
|
|
111
111
|
| `tty_screen` | Read the **currently visible screen** as rendered (xterm-headless virtual screen, plain text) — it can genuinely read TUI interfaces such as vim / htop / menus |
|
|
112
|
-
| `tty_expect` | Wait with a regex for a readiness signal
|
|
112
|
+
| `tty_expect` | Wait with a regex for a readiness signal (dev server URL, build finished, …). It **looks back first** at output that has not been read yet (including the full output of “the previous command”, so a command that finished instantly no longer burns the whole timeout) and then waits for subsequent output; on a hit it returns `matched:true` plus `matchedFrom` (`live` produced during this wait / `last` the previous command’s output / `buffered` buffered output that had already arrived). A timeout does not throw (`matched:false` + tail output, and it **does not consume the unread region**, so a different pattern can still look back at the same output), and a command that ends early also returns early with its exit code; the echo never counts as a hit (via the OSC 133 A..B boundary — see the next section for environments without markers); at most 5 in-flight calls per session, and the accumulated window keeps only the last 64KB (0.19.0; look-back matching, see D72) |
|
|
113
113
|
| `tty_send` | Send keys/text to a given session (such as `q` to a dev server, or a menu selection) |
|
|
114
114
|
| `sftp_list` | List a remote SSH directory (name/type/size/mtime, directories first); `book` is the connection-book entry name and `path` defaults to the login home; at most 500 entries by default (`truncated:true` beyond that), and `isSymlink` distinguishes a symlink from a real directory (0.19.0) |
|
|
115
115
|
| `sftp_read` | Read a remote **text** file (≤256KB by default, adjustable to 1MB, truncated beyond that); `offset` pages from a given byte (handy for log tails), an invalid `maxBytes` errors out instead of silently falling back, and binary detection is a double test (NUL + illegal-UTF-8 ratio) (0.19.0) |
|
|
@@ -152,6 +152,30 @@ At spawn time hooks are injected through the existing `-c` wrapper layer accordi
|
|
|
152
152
|
code / `OSC 7 file://…` cwd reporting (`tty_list.cwd` follows `cd`, and SSH sessions report the remote path);
|
|
153
153
|
- Other shells are silently disabled; `shellIntegration: false` turns the whole thing off (escape hatch).
|
|
154
154
|
|
|
155
|
+
**Look-back matching and the read watermark (D72)**: `tty_expect` first looks back at output that has
|
|
156
|
+
**not been read yet** (when a command finishes instantly, the marker you are waiting for is already in the
|
|
157
|
+
buffer). The look-back lower bound is raised to “just after the last `B` marker” inside the unread region —
|
|
158
|
+
the echo sits between `A` and `B`, so text in the echo never counts as a hit (deliberately no text
|
|
159
|
+
comparison here: line wrapping / ANSI / multi-line paste would break it).
|
|
160
|
+
|
|
161
|
+
- **Environments without `B` markers** (integration off / local Windows tabs / a remote host without the
|
|
162
|
+
hooks) cannot tell the echo apart and degrade to “scan from the watermark, possibly matching the echo
|
|
163
|
+
itself” — a known limitation;
|
|
164
|
+
- **The tradeoff in that look-back range**: raising the lower bound to “just after the last `B` marker”
|
|
165
|
+
costs you the unread output that precedes the newest command’s start. It deliberately prefers a miss
|
|
166
|
+
over a false hit — treating the echo as a match would make the agent believe the event just happened.
|
|
167
|
+
Use `tty_capture` for that text. The mirror-image corner exists too: right after `tty_send`, before the
|
|
168
|
+
new command’s `B` marker arrives, the unread region still holds the previous command’s output, so a
|
|
169
|
+
pattern in it matches at once (the agent’s next call almost always lands after that `B`, where this
|
|
170
|
+
text has already been cut off by it);
|
|
171
|
+
- **Read watermark**: whatever `tty_capture` / `tty_expect` returns counts as read, and later
|
|
172
|
+
`tty_expect` calls will not look back at it (use `tty_capture` to re-read older output). `tty_screen`
|
|
173
|
+
deliberately does **not** advance it (the screen is a different representation, not a text stream);
|
|
174
|
+
`tty_send` only initialises it (the output of the command just sent has not been seen yet); **a timeout
|
|
175
|
+
does not consume the unread region** either (another pattern can still look back at the same output).
|
|
176
|
+
A tab the user opened gets its watermark placed at the moment the agent first touches it — history
|
|
177
|
+
before that does not count as unread.
|
|
178
|
+
|
|
155
179
|
SSH sessions are scheduled on the same table: entries with `kind: 'ssh'` in `tty_list` are identified by
|
|
156
180
|
`target` (user@host[:port]), and `tty_capture` / `tty_expect` / `tty_send` are used exactly as for local
|
|
157
181
|
sessions — dev server logs and key interactions on the remote machine remain available as usual.
|
|
@@ -460,7 +484,22 @@ and the agent tools all reuse the same scheduling.
|
|
|
460
484
|
`agentForward` and show `· fwd` in the list;
|
|
461
485
|
- **`~/.ssh/config` import (0.4.0)**: “Import from ~/.ssh/config” in the connection-book area of the settings
|
|
462
486
|
card — parses `HostName/User/Port/IdentityFile` into candidate entries (skipping wildcard blocks and
|
|
463
|
-
entries without a User; `Include` is not expanded), skips same names, and writes them on “save
|
|
487
|
+
entries without a User; `Include` is not expanded), skips same names, and writes them on “save”.
|
|
488
|
+
**Every skip is now reported** (this round): blocks that depend on a jump host (`ProxyJump` /
|
|
489
|
+
`ProxyCommand`) are **not imported and are named** — this version does not support jump hosts, and
|
|
490
|
+
importing one would only produce an entry that cannot connect and reports a generic timeout; the
|
|
491
|
+
over-limit count and the “not a concrete host” count are reported too. `ProxyJump none` /
|
|
492
|
+
`ProxyCommand none` mean an explicit direct connection and are imported as usual.
|
|
493
|
+
**`ProxyJump` is resolved into the entry's jump host (single hop) and imported with it**: the
|
|
494
|
+
value may be `user@host:port` (IPv6 as `[::1]:22`) or another concrete Host in the same config
|
|
495
|
+
(resolved by block name, in any order); the jump host **inherits the target hop's credentials**
|
|
496
|
+
by default, so set `jump.keyPath` / `jump.password` on the entry when it needs its own.
|
|
497
|
+
Unresolvable ones (missing alias, or an alias that itself needs a jump) are still skipped and
|
|
498
|
+
named; `ProxyCommand` is not supported (it would let a settings field drive arbitrary local
|
|
499
|
+
command execution — a different trust tier, see project ROADMAP item 2). **The dialog also has a “Jump host” section**: one
|
|
500
|
+
`[user@]host[:port]` input (matching OpenSSH), with user / auth / key / passphrase overrides
|
|
501
|
+
revealed only after ticking “use separate credentials”; entry rows show “⇢ via X”, and the
|
|
502
|
+
“Test” button reports the jump hop on its own line;
|
|
464
503
|
- **Credential-reference picker (0.4.0; decoupled from the env plugin since 0.17)**: next to the password /
|
|
465
504
|
passphrase fields in the SSH dialog there is a filter box plus a height-limited list whose candidates are
|
|
466
505
|
**the reference names the credential store already knows** (the host reads the `refs:` keys of
|
|
@@ -991,7 +1030,13 @@ Host half (src/index.ts)
|
|
|
991
1030
|
│ /api/dsh-tty/credential-refs (reference names known to the credential store — names only, see
|
|
992
1031
|
│ “Credential storage”), /api/dsh-tty/env-vars (variable names managed by the env plugin), /api/dsh-tty/known-hosts
|
|
993
1032
|
│ (TOFU fingerprint prefill, src/known-hosts.ts parses hashed entries too),
|
|
994
|
-
│ /api/dsh-tty/shells (shell path candidates) — all behind the loopback fence
|
|
1033
|
+
│ /api/dsh-tty/shells (shell path candidates) — all behind the loopback fence (hardened
|
|
1034
|
+
│ tier: the whole 127/8 range + DNS confirmation for alias hostnames + source checks before
|
|
1035
|
+
│ DNS; one implementation only, in @hyzyn/dsh-kit); **state-changing endpoints additionally
|
|
1036
|
+
│ require a same-origin proof** (POST /probe, sftp mkdir/rename/remove/upload, local-fs
|
|
1037
|
+
│ mkdir/rename/remove/transfer); read-only endpoints (including sftp /list and /download)
|
|
1038
|
+
│ need no proof, so bare curl still works. POST /config is deliberately exempt — it is the
|
|
1039
|
+
│ only recovery entry once the plugin is disabled
|
|
995
1040
|
├─ SFTP (src/sftp.ts, 0.7.0): lazy connection pool (reclaimed after 120s idle, reconnected on
|
|
996
1041
|
│ demand when dropped, TOFU shared) → POST /api/dsh-tty/sftp/list|mkdir|rename|remove|download|
|
|
997
1042
|
│ upload (spec in body/headers, credentials never in the URL; uploads/downloads streamed via pipe) +
|
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ dsh plugin --profile web add link:$(pwd)/packages/tty # 仓库开发调试
|
|
|
103
103
|
| `tty_stats` | 读会话所在机器的实时指标(0.20.0):CPU / 内存 / 磁盘 / TCP 连接数 / 网速 / 温度 / 在线时长。本地会话取宿主机;SSH 会话取那台远程主机(另开一段非 PTY 通道,不影响终端)。部署、压测前先看它 |
|
|
104
104
|
| `tty_capture` | 读取近期输出(尾部 N 行,默认清洗 ANSI,`raw:true` 取原始流);**`last:true` 只返回上一条已完成命令的输出 + 退出码**(shell 集成标记,见下节);命令**在途**时(刚发送、完成标记未到)返回 `inProgress:true` 且不带旧结果——避免把上一条的输出当成这一条(0.19.0) |
|
|
105
105
|
| `tty_screen` | 读取**当前可见屏幕**的渲染结果(xterm-headless 虚拟屏,纯文本)——能真正读懂 vim / htop / 菜单等 TUI 界面 |
|
|
106
|
-
| `tty_expect` |
|
|
106
|
+
| `tty_expect` | 用正则等一个就绪信号(dev server URL、构建完成等)。**先回溯**还没被读过的输出(含「上一条命令」的完整输出,故命令瞬间跑完也不会白等),再等后续输出;命中即返回 `matched:true` + `matchedFrom`(`live` 本次等待期间新产生 / `last` 上一条命令的输出 / `buffered` 此前已到达的缓冲输出)。超时不抛错(`matched:false` + 尾部输出,且**不消耗未读区**——换个 pattern 还能回溯到同一段),命令提前结束也会带退出码早停;回显不算命中(靠 OSC 133 的 A..B 边界,无标记环境见下节);同一会话在途调用最多 5 个,累积窗口只保留尾部 64KB(0.19.0;回溯匹配见 D72) |
|
|
107
107
|
| `tty_send` | 向指定会话发送按键/文本(如 dev server 的 q 键、菜单选择) |
|
|
108
108
|
| `sftp_list` | 列出 SSH 远程目录内容(名称/类型/大小/修改时间,目录在前);`book` 为连接簿条目名,`path` 缺省为登录 home;默认最多 500 项(超限 `truncated:true`),`isSymlink` 区分软链与真目录(0.19.0) |
|
|
109
109
|
| `sftp_read` | 读取远程**文本**文件(默认 ≤256KB 可调至 1MB,超出截断);`offset` 可从指定字节分页(适合读日志尾部),非法 `maxBytes` 直接报错,二进制判定 = NUL + 非法 UTF-8 占比双判据(0.19.0) |
|
|
@@ -144,6 +144,24 @@ spawn 时经既有的 `-c` 包装层按 shell 类型注入钩子(对用户透
|
|
|
144
144
|
SSH 会话则上报远程路径);
|
|
145
145
|
- 其他 shell 静默关闭;配置 `shellIntegration: false` 可整体关掉(逃生门)。
|
|
146
146
|
|
|
147
|
+
**回溯匹配与已读水位线(D72)**:`tty_expect` 会先回看**还没被读过**的输出(命令瞬间跑完时
|
|
148
|
+
要等的标记早就在缓冲区里了),回看的起点抬到「未读区内最后一个 `B` 标记之后」——回显落在 `A`
|
|
149
|
+
与 `B` 之间,所以回显里的字样不会被当成命中(这里刻意不做文本比对:折行 / ANSI / 多行粘贴
|
|
150
|
+
都会把它打碎)。
|
|
151
|
+
|
|
152
|
+
- **没有 `B` 标记的环境**(未开集成 / Windows 本地标签 / 远端未装集成)分不出回显,退化为
|
|
153
|
+
「从水位线起扫,可能匹配到回显本身」——这是已知限制;
|
|
154
|
+
- **回看范围的取舍**:起点抬到「未读区内最后一个 `B` 标记之后」,代价是最后一条命令**开始
|
|
155
|
+
之前**的那段未读输出不在回看范围内。刻意选「宁可漏、不可误报」——把回显当成命中会让 AI
|
|
156
|
+
以为事件刚刚发生。要那段内容用 `tty_capture`。反过来的窄窗口也有一个:`tty_send` 之后、
|
|
157
|
+
新命令的 `B` 标记到达之前,未读区里仍然是上一条命令的输出,里面有要等的 pattern 就会立即
|
|
158
|
+
命中(AI 的下一次调用几乎总在新 `B` 之后,那种情况下这段已被新 `B` 切掉);
|
|
159
|
+
- **已读水位线**:`tty_capture` / `tty_expect` 返回的内容算「已读」,之后的 `tty_expect` 不再
|
|
160
|
+
回扫它们(要回看更早的内容用 `tty_capture`)。`tty_screen` 刻意**不**推进(屏幕是另一种
|
|
161
|
+
表示,不是文本流);`tty_send` 只初始化不推进(刚发出去的命令输出还没被看见);**超时也不
|
|
162
|
+
消耗未读区**(换一个 pattern 还能回溯到同一段)。用户自己开的标签在 agent 第一次触达时
|
|
163
|
+
才把水位线落在当下——那之前的历史输出不算「未读」。
|
|
164
|
+
|
|
147
165
|
SSH 会话同表调度:`tty_list` 里 `kind: 'ssh'` 的条目按 `target`
|
|
148
166
|
(user@host[:port])识别,`tty_capture` / `tty_expect` / `tty_send` 用法与
|
|
149
167
|
本地会话完全一致——远程机器上的 dev server 日志与按键交互照常可用。
|
|
@@ -409,7 +427,44 @@ tmux server(专用 socket `dsh-tty`,与用户自己的 tmux 完全隔离)
|
|
|
409
427
|
失效。连接簿条目随 `agentForward` 保存,列表里显示 `· fwd`;
|
|
410
428
|
- **`~/.ssh/config` 导入(0.4.0)**:设置卡片连接簿区「从 ~/.ssh/config
|
|
411
429
|
导入」——解析 `HostName/User/Port/IdentityFile` 生成候选条目(跳过通配符
|
|
412
|
-
块与无 User 条目,`Include`
|
|
430
|
+
块与无 User 条目,`Include` 不展开),同名跳过,随「保存」写入。
|
|
431
|
+
**每一种跳过都会当场说明**(本轮起):依赖跳板机的块(`ProxyJump` / `ProxyCommand`)
|
|
432
|
+
**不导入并点名**——本版本不支持跳板机,导进来只会得到一条连不上、且只报通用超时的条目;
|
|
433
|
+
超过导入上限的条数与「非具体主机」的条数也各自报数。`ProxyJump none` /
|
|
434
|
+
`ProxyCommand none` 是显式直连,照常导入。
|
|
435
|
+
**`ProxyJump` 会解析成连接条目的跳板机(单跳)一起导入**:值可以是 `user@host:port`
|
|
436
|
+
(IPv6 写 `[::1]:22`),也可以是同一份 config 里的另一个具体 Host(按块名解析,块序任意);
|
|
437
|
+
跳板机缺省**继承目标那一跳的凭据**,要不同的钥匙就在条目里填 `jump` 的 `keyPath`/`password`。
|
|
438
|
+
解析不出来的(别名缺失、别名自己又依赖跳板机)仍会跳过并点名。
|
|
439
|
+
**`ProxyCommand` 永不自动导入**(单独报数并说明为什么):它等于让设置字段驱动本地任意
|
|
440
|
+
命令执行,所以只在**手动填写 + 打开开关**之后才会跑(见下一段)。
|
|
441
|
+
**对话框里也有「跳板机」一段**:一个 `[用户@]主机[:端口]` 输入框(与 OpenSSH 写法一致),
|
|
442
|
+
勾「使用独立凭据」才展开用户名 / 认证方式 / 私钥 / 口令;条目行显示「⇢ 经 X」,「试连」
|
|
443
|
+
会把跳板机那一跳单列出来;
|
|
444
|
+
- **代理命令 / ProxyCommand(0.21.0,默认关)**:连接簿条目(或连接对话框)里可填一条
|
|
445
|
+
**本机命令**,它的 stdin/stdout 就是到目标的 SSH 传输——等价于 OpenSSH 的 `ProxyCommand`
|
|
446
|
+
(典型写法 `ssh -W %h:%p bastion`)。支持 `%h` 目标主机、`%p` 端口、`%r` 用户名、`%n` 主机、
|
|
447
|
+
`%%` 字面 `%`,其余 `%X` 原样保留;**代入值只允许字母数字与 `._@:[]-`,含 shell 特殊字符
|
|
448
|
+
直接拒绝执行**(不做「按平台各写一套转义」:命令最终交给 `sh -c` / `cmd /c`,两边规则不同)。
|
|
449
|
+
**闸门**:设置卡片「允许 ProxyCommand(本机执行命令)」**默认关**,它的**提权有两条通道**:
|
|
450
|
+
① **启动环境变量** `DSH_TTY_ALLOW_PROXY_COMMAND=1`(最严档,进程启动时采样,只认继承来的
|
|
451
|
+
`process` 层——写项目 `.env` 或 `~/.dsh/env.yml` **不算**授权);② **就地提权**(免重启):
|
|
452
|
+
卡片上点那个开关 → 面板给出一条「在宿主终端执行」的命令 → 执行后十秒内解锁并替你打开开关。
|
|
453
|
+
HTTP / 界面**不能凭空打开**它(给 `true` 而无授权会被 400 拒绝并说清两条路),但**关掉**永远
|
|
454
|
+
可用(紧急刹车不能依赖重启)。授权是**持久**的(落在 `<DSH home>/dsh-kit/capability-grants.json`,
|
|
455
|
+
0600):宿主重启后直接生效、不再确认,所以每次启动会打一行
|
|
456
|
+
`[dsh-tty] elevation: load capability=… via=file grantedAt=…`,卡片上也显示「已授权 · 时刻」并给
|
|
457
|
+
「撤销宿主授权」入口。**升级影响**:升级前靠界面打开的这个开关会变成关。为什么这么设计:
|
|
458
|
+
回环围栏与同源证明都拦不住跨站页面与页内脚本,而这一档是「配置里写一行就在本机跑命令」——
|
|
459
|
+
配置界面若能凭空提权,这道闸门等于没有(细节见
|
|
460
|
+
[architecture.md § 7](../../docs/architecture.md#7-一条请求经过什么))。关着时携带代理命令的连接
|
|
461
|
+
**明确失败、不退回直连**(直连多半也连不上,还会把配置问题伪装成网络问题),「试连」在
|
|
462
|
+
阶段 0 就返回并点名这个开关。与跳板机同时填时按 OpenSSH 语义**跳板机优先**,并记一条 warn。
|
|
463
|
+
闸门只有一处(本插件 settings):docker 容器面板读同一个开关——连接簿配一次、两处生效;
|
|
464
|
+
代价是代理命令是**本机**执行的,docker 目标也会用这条命令(详见
|
|
465
|
+
[docs/proxyjump-plan.md](../../docs/proxyjump-plan.md) §6.1 的闸门定案表);
|
|
466
|
+
与跳板机一样,**它是另一条独立传输,收尾必须成对**(终端 / SFTP / 隧道 / 探针四条路都在
|
|
467
|
+
同一个收尾入口里 `dispose()`:关传输 + 杀进程组,子进程不会变成常驻孤儿);
|
|
413
468
|
- **凭据引用选择器(0.4.0,0.17 起与 env 插件解耦)**:SSH 对话框的密码/口令字段旁有筛选框 +
|
|
414
469
|
限高列表,候选 = **凭据存储里已有的引用名**(宿主读 `.credentials.yaml` 的 `refs:` 键,
|
|
415
470
|
**只回名字、绝不含值**)∪ **本机连接簿里已经在用的引用名**;点击即填 `env:NAME`,也可手输
|
|
@@ -510,6 +565,7 @@ tmux server(专用 socket `dsh-tty`,与用户自己的 tmux 完全隔离)
|
|
|
510
565
|
| `persistence` | `off` | 会话持久化:`off` 会话随宿主生死(默认);`tmux` 开启后**所有新开的标签默认由 tmux server 托管**、可跨宿主重启恢复(需本机/远程安装 tmux);SSH 对话框可对单次连接取消 |
|
|
511
566
|
| `endOnPageClose` | `false` | 页面(最后一个连接)断开且保活期结束时,是否连 tmux 持久会话一起结束。默认 `false` = 留存可恢复;`true` = 页面关了就不保活(保活期内刷新仍可无缝接回) |
|
|
512
567
|
| `sftpLimits` | `{maxDownloadMb: 1024, maxUploadMb: 2048, maxUploadFiles: 1000}` | SFTP 传输限制(浏览器侧保护,均为 **0 = 不限**):`maxDownloadMb` 单文件下载上限(超限中止并提示用双栏 `⇦`/终端 scp)、`maxUploadMb` 单文件上传上限、`maxUploadFiles` 一次批量/拖拽上传的文件数上限;大文件请走双栏 `⇨/⇦` 服务端直传(字节不经过浏览器,不占内存) |
|
|
568
|
+
| `allowProxyCommand` | `false` | 允许连接簿条目里的**代理命令(ProxyCommand)在本机执行**。默认关:关着时携带代理命令的连接**明确失败**(不退回直连),`~/.ssh/config` 导入**永不**自动带入该字段。docker 容器面板读同一个开关(连接簿只有一处)。支持 `%h/%p/%r/%n/%%` 展开,代入值走白名单;命令的子进程不会残留(四条连接路径共用同一收尾)。**两条提权通道**:① 启动环境变量 `DSH_TTY_ALLOW_PROXY_COMMAND=1`(判定源是宿主的**启动环境快照**,只认继承来的 `process` 层:写项目 `.env` 或 `~/.dsh/env.yml` **不算**授权);② **就地提权**(免重启):设置卡片点那个开关 → 面板给出「在宿主终端执行」的命令 → 十秒内解锁。HTTP / 界面**不能凭空打开**它(给 `true` 而无授权 400 并说清两条路),但**关掉**永远可用;配置里的 `true` 不算授权。授权持久(`<DSH home>/dsh-kit/capability-grants.json`),重启后直接生效并在卡片上显示时刻与「撤销宿主授权」(见 [architecture.md § 7](../../docs/architecture.md#7-一条请求经过什么)) |
|
|
513
569
|
| `statsEnabled` | true | 服务器状态条(0.17.0):按标签可见性采集并推送 CPU / 内存 / 磁盘 / 在线时长 / TCP 连接数 / 网速 / CPU 温度;关闭即停表(远端 exec channel 一并关闭),保存即热生效 |
|
|
514
570
|
|
|
515
571
|
## 连接栏扩展点(客户端服务 `ttyConnbar`,0.13.0)
|
|
@@ -866,7 +922,11 @@ node scripts/preview.mjs --theme=light # 浅色主题
|
|
|
866
922
|
│ /api/dsh-tty/credential-refs(凭据存储里已知的引用名 —— 只要名字,见「凭据存储」)、
|
|
867
923
|
│ /api/dsh-tty/env-vars(env 插件托管变量名)、/api/dsh-tty/known-hosts
|
|
868
924
|
│ (TOFU 指纹预填充,src/known-hosts.ts 解析含 hashed 条目)、
|
|
869
|
-
│ /api/dsh-tty/shells(Shell 路径候选)——均 loopback
|
|
925
|
+
│ /api/dsh-tty/shells(Shell 路径候选)——均 loopback 围栏(加固档:127/8 全段 +
|
|
926
|
+
│ 别名主机名的 DNS 确认 + 来源检查在 DNS 之前,实现只有一份在 @hyzyn/dsh-kit);
|
|
927
|
+
│ **改状态的端点另需同源证明**(POST /probe、sftp 的 mkdir/rename/remove/upload、
|
|
928
|
+
│ local-fs 的 mkdir/rename/remove/transfer);只读端点(含 sftp /list 与 /download)
|
|
929
|
+
│ 不要求证明,裸 curl 也能读。POST /config 刻意豁免——它是插件被禁用后唯一的恢复入口
|
|
870
930
|
├─ SFTP(src/sftp.ts,0.7.0):懒连接池(空闲 120s 回收、断开按需重连、
|
|
871
931
|
│ TOFU 共用)→ POST /api/dsh-tty/sftp/list|mkdir|rename|remove|download|
|
|
872
932
|
│ upload(spec 走体/头,凭证不进 URL;上传下载流式 pipe)+
|