Skip to content
dsh.fish
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

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source