finch-remote-host 0.0.0-stage → 1.0.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/README.md CHANGED
@@ -1,3 +1,176 @@
1
- # Temporary Holding Version
1
+ # 远程主机
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 在 Finch 里管理远程 Linux 主机,让 Agent 通过 SSH 执行命令,危险操作先经用户确认,全部动作留审计。
4
+
5
+ 对话里永远不出现账号和密码:主机由你在面板里添加,密码存进系统安全存储,Agent 拿到的是主机 id。
6
+
7
+ 运行 Finch 的宿主系统不限:Windows 用系统自带的 OpenSSH,macOS 与 Linux 用 PATH 里的 `ssh`。目标机需要 POSIX shell。
8
+
9
+ ## 动作
10
+
11
+ | action | 用途 |
12
+ | ------- | ------------------------------------------------------ |
13
+ | `hosts` | 列已配置的主机、策略模式、最近一次执行结果,只读 |
14
+ | `exec` | 在指定主机上执行一条命令,按策略决定放行、确认还是拒绝 |
15
+ | `audit` | 查最近的执行记录:命令、判定、退出码、耗时 |
16
+
17
+ `exec` 会先说清目标机和整条命令,需要确认时弹一张卡片,你点亮「我已看清命令与目标机」才算通过。
18
+
19
+ 执行期间卡片上的进度会每 1.2 秒刷新一次:已跑秒数、输出行数、最新一行。所以长命令能看出还在动,而不是干等。
20
+
21
+ 正文仍是跑完一次性返回——工具结果只支持整段落盘,没有逐行推送的通道。
22
+
23
+ 单条命令最长 10 分钟,到点本地中断;真要跑更久,用下面的后台任务。
24
+
25
+ ## 后台任务
26
+
27
+ `start` / `status` / `stop` 三个动作专治跑不完的命令,进程有主,不会变成孤儿。
28
+
29
+ | action | 干什么 |
30
+ | -------- | --------------------------------------------------------------- |
31
+ | `start` | 远端 `setsid` 脱离会话启动,立刻返回任务 id、pid 与日志路径 |
32
+ | `status` | 探活、输出行数、日志尾巴、退出码;不带 taskId 就列最近任务 |
33
+ | `stop` | 先 TERM 整个进程组,1 秒后按 PGID 逐个 KILL;`clean` 顺手删日志 |
34
+
35
+ 列表只做索引,不给存活结论;要存活就带 taskId 真探一次。
36
+
37
+ 远端写三份伴生文件:`/tmp/finch-<id>.log` 存输出,`.exit` 存退出码,`.pid` 存真正干活的 worker 进程号。
38
+
39
+ 退出码让任务结束后仍能查到真实成败;`.pid` 是关键——`setsid` 会再分叉一层,`$!` 拿到的不是 worker,只有 worker 自己写的 pid 才能把整组收干净。
40
+
41
+ 组长先退出时按负 pid kill 会报 ESRCH 而漏掉子进程,所以 `stop` 会再按 PGID 把剩下的成员逐个收一遍。
42
+
43
+ `start` 和 `exec` 走同一套策略与确认卡片:危险命令照样要你点头,硬拒清单照样不放行。
44
+
45
+ 任务记录存在小程序本地,最多留 50 条,最早的自动挤掉。
46
+
47
+ ## 面板
48
+
49
+ 右侧面板里的「远程主机」就是主机管理处,设置菜单里点「打开主机面板」也能进。
50
+
51
+ 面板提供三件事:主机列表与详情、新增与编辑弹框、每台主机的最近审计。
52
+
53
+ 布局是手风琴:一行一台主机,点一下展开,详情与该机的审计就在同一条目里,再点收起。窄侧栏也放得下,不需要左右分栏。
54
+
55
+ 展开后的三个按钮都带鼠标悬停提示:编辑改配置,测试连一次,删除会先问一句。
56
+
57
+ 新增时选择认证方式:密钥填绝对路径,密码填一次就好。
58
+
59
+ 表单里的「测试连接」会当场直连一次,只看能不能回显,不装进主机列表。
60
+
61
+ 策略下拉每档都跟一句说明,选完就知道这档能干什么。
62
+
63
+ 规则与策略下方有「试运行」框:粘一条命令点「判定」,用表单里还没保存的配置直接问分类器,结果分直接执行 / 需要确认 / 拒绝三色,并附逐段理由。
64
+
65
+ 弹框底部可展开「内置强制规则」,列出全部硬拒项、保护路径与会被检查目标的命令。内容由后端分类器下发,不是另写的一份文案,规则改了面板跟着变。
66
+
67
+ ## 选主机
68
+
69
+ 输入框下方有「远程主机」这颗按钮,点开的菜单里选一台,它就是这台会话默认操作的机器。
70
+
71
+ 选中后按钮直接显示主机名,再点可以换或清除。每个会话各记各的,互不影响。
72
+
73
+ 选定之后 Agent 执行命令不用再指定主机,模型每一轮都会被告知「这台机器」指的是谁。
74
+
75
+ 按钮菜单最后一行是「打开主机面板」,没配主机时也会给你这个入口。
76
+
77
+ ## 策略
78
+
79
+ 每台主机独立配一个模式,随时可改。四档从严到松,放宽只会让更多命令通过,不会反着来。
80
+
81
+ | 模式 | 只读命令 | 写操作 | 读凭据文件 |
82
+ | ---------- | -------- | ------ | ------------ |
83
+ | `query` | 直接跑 | 拒绝 | 拒绝 |
84
+ | `readonly` | 直接跑 | 拒绝 | 确认 |
85
+ | `confirm` | 直接跑 | 确认 | 确认(默认) |
86
+ | `trusted` | 直接跑 | 直接跑 | 直接跑 |
87
+
88
+ 硬拒不看模式、也不给确认按钮:删根目录、删任何一级目录(`/var`、`/wwwroot`、`/var/*` 这类清空也算)、不带路径的通配删除(`rm -rf *`)、`mkfs`、`dd` 写裸盘、重定向写块设备、fork 炸弹、关机重启、`chmod 777 /`。
89
+
90
+ 判硬拒前先去掉引号再按段扫描,所以 `sudo rm -rf /var`、`sh -c "rm -rf /var"`、`/bin/rm -rf /var` 都拦得住。
91
+
92
+ 二级以下路径(`rm -rf /var/log/nginx`)不进一级硬拒,归模式管。
93
+
94
+ ### 保护路径
95
+
96
+ 下面这些位置,删除、清空、截断、重定向写入都直接拒绝,不看模式:
97
+
98
+ | 范围 | 路径 | 粒度 |
99
+ | ------------------ | ---------------------------------------------------------- | -------------- |
100
+ | 系统与启动 | `/etc`、`/boot`、`/bin`、`/sbin`、`/lib*`、`/usr`、`/root` | 整棵子树 |
101
+ | 站点与定时任务 | `/var/www`、`/var/spool` | 整棵子树 |
102
+ | 服务数据与用户目录 | `/home`、`/opt`、`/srv`、`/var/lib` | 只到直属子目录 |
103
+ | 密钥目录 | 任何位置下名为 `.ssh` 的目录 | 整棵子树 |
104
+
105
+ 拦截的命令:`rm`、`rmdir`、`unlink`、`shred`、`truncate`、`dd of=`、`>`/`>>` 重定向、`find -delete`。
106
+
107
+ 不拦 `cp`、`mv`、`sed -i`、`tee`:这些是改配置与部署的正常手段,它们依旧走模式判定。
108
+
109
+ 只保护直属子目录的那档,是给缓存与日志留路:`rm -rf /var/lib/mysql` 拒绝,`rm -rf /var/lib/apt/lists/*` 只要求确认。
110
+
111
+ 名单只收 Linux 通用路径。业务目录(如 `/wwwroot`)的子树不进保护名单,删里面的东西只要求确认;但 `/wwwroot` 自身是一级目录,`rm -rf /wwwroot` 与 `rm -rf /wwwroot/*` 照样硬拒。
112
+
113
+ ### 规则
114
+
115
+ 规则是 glob,一行一条,匹配单位是命令拆开后的每一段(`;` `&&` `||` `|` `&` 换行都是分隔符)。
116
+
117
+ 整段匹配,不做子串:规则 `systemctl restart nginx` 不放过 `systemctl restart nginx-backup`。
118
+
119
+ `*` 不跨 `/`,跨层级用 `**`,`?` 匹配单个字符。
120
+
121
+ 优先级:硬拒 > 拒绝规则 > 放行规则 > 模式。一段命中拒绝规则就整条拒绝;只有等所有段都过了才放行。
122
+
123
+ 规则会逐段判断,所以拼接骗不过去:「放行 `systemctl restart nginx`」不会让 `systemctl restart nginx && rm -rf /tmp/x` 免确认。
124
+
125
+ ### 只读判定
126
+
127
+ 只读看的是整条命令,任何一处可疑就按写操作处理:
128
+
129
+ - 不在白名单里的命令一律不算只读
130
+ - 命令替换 `$(…)`、反引号、`${…}`、重定向、heredoc 都不算只读
131
+ - 白名单命令带上写参数也不算:`sort -o`、`uniq 输入 输出`、`date -s`、`hostname 新名`、`find -delete`/`-exec`、`ping -f`
132
+ - 交互式程序(`less`/`vim`/`man`)不在白名单里,没有 tty 也用不上
133
+
134
+ ## 凭据
135
+
136
+ 两种认证都支持,按机器自选。
137
+
138
+ - **密钥**:ed25519 私钥的绝对路径,口令版先 `ssh-add` 到 Windows 的 OpenSSH 认证代理
139
+ - **密码**:存进系统安全存储(DPAPI),`permissions.secrets` 只声明 `host.*` 前缀
140
+
141
+ 密码不进配置文件、不进面板数据、不进审计,也不会回给模型。
142
+
143
+ 密码认证靠 `SSH_ASKPASS` 非交互地交给 ssh:助手脚本只回显环境变量,密码随进程结束消失。
144
+
145
+ 注意:`SSH_ASKPASS_REQUIRE` 需要 OpenSSH 8.4 以上,Windows 10 1809 之后自带版本都满足。
146
+
147
+ ## 审计
148
+
149
+ 每次判定与执行都写一条 JSONL,落在小程序的私有目录 `audit/<日期>.jsonl`。
150
+
151
+ 记录含时间、主机、会话 id、工具调用 id、完整命令、判定结果与逐段理由、退出码、耗时和输出前 4 KB。
152
+
153
+ 日志只追加,工具本身没有任何删除或改写记录的入口。
154
+
155
+ ## 安装与联调
156
+
157
+ ```bash
158
+ bun run fafinch dev remote-host # 构建 + 软链安装 + 监听
159
+ bun run fafinch build remote-host # 只构建
160
+ bun run fafinch doctor remote-host # 构建 + 官方体检
161
+ bun run synctpl finchapp # 契约校验
162
+ ```
163
+
164
+ `bun run fafinch install remote-host` 是复制安装,改代码后要重新执行。
165
+
166
+ ## 文件
167
+
168
+ - `src/index.js` —— 注册工具与设置菜单,串起判定、确认、执行、审计,并接面板消息
169
+ - `src/hosts.js` —— 主机清单、执行状态与密码的持久化与校验
170
+ - `src/policy.js` —— 命令分级:拆段、glob 规则、只读判定、四档模式
171
+ - `tests/policy.test.js` —— 命令分级的回归用例(vitest)
172
+ - `src/ssh.js` —— 调系统 OpenSSH 客户端,密钥与密码两种认证,按主机串行,输出截断
173
+ - `src/audit.js` —— 审计日志的追加与读取
174
+ - `ui/panel.html` —— 面板页面:列表、表单弹框、审计视图
175
+ - `dist/index.js` —— rolldown 产物(target node24),勿手改
176
+ - `icon.png` —— 由 `bun run fafinch icon remote-host` 从图案源 `scripts/genLogo/output/remote-host/icon.svg` 生成