Bundle
dsh-trusted-page
DSH Web 远程受信访问插件:在设置面板可视化配置受信域名(联动 /api 放行与页面受信判定),修复远程打开 Models/设置页报 settings are unavailable in this browser
- Source
- liujuntao123
- License
- MIT
- Updated
- Updated 4 days ago
Readme
# dsh-trusted-page
DSH(DeepSeek Harness)Web 远程受信访问插件:把「远程域名信任」做成
**设置面板里的可视化配置**,修复经反向隧道 / 自定义域名远程访问 DSH Web 时
Models / 设置页报错:
> 加载提供方目录失败: settings are unavailable in this browser
## 它解决什么问题
DSH Web 客户端按「页面 hostname 是否回环(localhost / 127.x)」决定是否启用
Host settings 持久化。远程域名不是回环名,设置镜像降级为 `memory`
(不读不写 Host 设置),于是 Models 页把提供方目录与 settings 快照联表时
直接报上错 —— 尽管服务端的 `--trusted-host` 早已放行你的域名。
## 功能
- **设置面板 → 通用 → 「远程受信域名」**:以标签列表可视化增删受信域名
(`host` 或 `host:port`),带「当前页面:已受信 / 未受信」徽标;
- **一处配置,两处联动**(写入即生效,无需重启):
1. `/api` 的 Host/Origin fence —— 列表并入 `connection.trustedHosts`
(静态基线 `--trusted-host` 只增不减);
2. 页面受信判定 —— 每次渲染 index 注入一段先于插件执行的内联脚本,
`location` 命中列表才声明 `window.__DSH_TRANSPORT__ = { ownsHost: true }`
(`dsh-client-connection` 预留扩展点),使该页面的设置持久化可用;
- 匹配语义与服务端 fence 一致:无端口条目匹配任意端口,带端口条目
要求端口精确匹配;支持 IPv6 字面量(`[::1]:8080`);
- 输入容错:自动剥离 `https://` 前缀、路径、查询,统一小写;
拒绝 userinfo(`user@host`)、非法字符与非数字端口。
## 安全模型(不变的部分)
- 受信域名**之外**的 `/api` 请求仍被 Host/Origin fence 403;
- 页面本身仍需浏览器会话 Cookie(或启动 token 交换),未授权来源 index 401;
- 本插件只放宽「操作者自己在已认证的设置面板里声明的域名」。
前置条件:该域名必须已经路由到你的 DSH 服务(如 Cloudflare Tunnel、
nginx 反代、LAN 直连)—— 插件不负责路由。
## 安装
```bash
dsh plugin --profile web add git+https://github.com/liujuntao123/dsh-trusted-page.git
```
或手动:
```bash
cd ~/.dsh/profiles/web
pnpm add git+https://github.com/liujuntao123/dsh-trusted-page.git
```
然后把 `"dsh-trusted-page"` 加进该目录 `package.json` 的
`dsh.profile.bundles` 数组,重启 `dsh web`。
详见 [AI_INSTALL.md](./AI_INSTALL.md)(含验证与卸载步骤)。
## 使用
1. 本机打开 DSH Web(`http://127.0.0.1:<port>`)→ 设置 → 通用 →
「远程受信域名」;
2. 输入你的远程域名(如 `dsh.example.com`)回车或点「添加」;
3. 用该域名打开 DSH Web(需已路由到本服务),强刷一次页面(Ctrl+F5);
4. 进入 设置 → 模型:提供方目录正常加载,不再报
`settings are unavailable in this browser`。
> 远程页面上也能看到该设置行(只读提示或可编辑,取决于该页面当前是否受信)。
## 原理
```
设置面板 UI(lib/client.js)
│ settingsScope.bind({ namespace: 'trusted-page' })
▼
Host 设置命名空间 trusted-page.hosts(~/.dsh/settings.yaml)
│ scope.watch
├──────────────────────────────┐
▼ ▼
connection.trustedHosts 并入 index-inject 内联脚本
(/api fence,即时生效) (页面命中才 ownsHost:true,
下次刷新生效)
```
- 宿主侧 [lib/index.js](./lib/index.js):注册设置命名空间(手写最小
schemastery 兼容 schema,零依赖)、fence 联动、页面判定脚本注入;
- 纯逻辑 [lib/authority.js](./lib/authority.js):域名规范化 + 判定脚本生成
(有单测覆盖,含「已存在 `__DSH_TRANSPORT__` 时不覆盖」「不命中不声明」
等安全边界);
- 浏览器侧 [lib/client.js](./lib/client.js):设置面板行(纯
`React.createElement`,无构建步骤)。
## 开发
```bash
git clone https://github.com/liujuntao123/dsh-trusted-page.git
cd dsh-trusted-page
npm test # node --test tests/*.test.mjs
```
## 兼容性
在 `@deepseek-ai/dsh` 0.1.5-rc.1 上开发验证。依赖两个稳定的公开扩展点:
`webserver/index-inject` 注入事件与 `__DSH_TRANSPORT__.ownsHost` 读取约定;
若上游改变语义,插件会安全退化(页面不声明受信,fence 不变)。
## License
[MIT](./LICENSE)
Install
dsh plugin --profile web add github:liujuntao123/dsh-trusted-page
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-trusted-page from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.