🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

远程访问入口 why-did/dsh-tailscale-access

DeepSeek 客户端
why-did43 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

用手机浏览器安全访问本机 harness 界面

29.4/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/why-did/dsh-tailscale-access.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 43 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 27 处,展示前 27 条)
  • 写入本地文件
    lib/index.js:198
    appendFile(auditFile, `${JSON.stringify({ at: Date.now(), ...event })}\n`, { mode: 0o600 }).catch(() => {})
  • 发起网络请求
    lib/index.js:411
    const response = await fetch(url, { redirect: 'manual' })
  • 读取本地文件
    lib/index.js:680
    const info = await stat(auditFile)
  • 写入本地文件
    lib/index.js:681
    if (info.size > AUDIT_MAX_BYTES) await rename(auditFile, `${auditFile}.1`)
  • 写入剪贴板
    lib/client/client.js:207
    return Promise.resolve(writeClipboard(text)).then(function (ok) { return ok === true }, function () { return false })
  • 写入剪贴板
    lib/client/client.js:215
    return Promise.resolve(nav.clipboard.writeText(text)).then(function () { return true }, function () { return false })
  • 发起网络请求
    lib/client/client.js:781
    request = fetch(HOST_SETTINGS_PATH, { method: 'GET', headers: { accept: 'application/json' }, cache: 'no-store', credentials: 'same-origin' })
  • 发起网络请求
    lib/client/client.js:915
    request = fetch(STATUS_PATH, options)
  • 发起网络请求
    lib/client/client.js:1012
    request = fetch(ACTION_PATH, options)
  • 发起网络请求
    lib/proxy.js:786
    const upstreamReq = http.request({
  • 读取本地文件
    lib/cloudflared.js:90
    accessSync(candidate, constants.X_OK)
  • 读取本地文件
    lib/cloudflared.js:91
    return statSync(candidate).isFile()
  • 执行外部命令来自配置/变量
    lib/cloudflared.js:115
    execFile(file, args, (error) => { if (error == null) resolve(undefined); else reject(error) })
  • 写入本地文件
    lib/cloudflared.js:170
    await mkdir(cacheDir, { recursive: true })
  • 写入本地文件
    lib/cloudflared.js:179
    await pipeline(source, createWriteStream(temporary, { mode: 0o600 }))
  • 读取本地文件
    lib/cloudflared.js:180
    if (statSync(temporary).size === 0) {
  • 写入本地文件
    lib/cloudflared.js:185
    await chmod(temporary, 0o755)
  • 写入本地文件
    lib/cloudflared.js:186
    await rename(temporary, destination)
  • 删除本地文件
    lib/cloudflared.js:193
    await rm(temporary, { force: true })
  • 写入本地文件
    lib/cloudflared.js:198
    await chmod(extracted, 0o755)
  • 删除本地文件
    lib/cloudflared.js:202
    await rm(temporary, { force: true }).catch(() => {})
  • 读取本地文件
    lib/tailscale.js:225
    accessSync(candidate, constants.X_OK)
  • 写入本地文件
    lib/supervisor.js:97
    await mkdir(directory, { recursive: true })
  • 写入本地文件
    lib/supervisor.js:101
    await writeFile(temporary, body, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/supervisor.js:102
    await chmod(temporary, 0o600)
  • 写入本地文件
    lib/supervisor.js:103
    await rename(temporary, path)
  • 删除本地文件
    lib/supervisor.js:105
    await rm(temporary, { force: true }).catch(() => {})
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 远程访问本机界面
  • 手机浏览器安全访问

通过 Tailscale 或 cloudflared 远程访问 DeepSeek Harness Web GUI——早期阶段,先看注意事项。

README

由 DeepSeek 最新模型翻译生成
dsh-tailscale-access [!IMPORTANT] 早期版本 —— 打开开关前,值得先花两分钟读这一段。 本插件目前是 0.1.x,仍在持续测试中:有自动化测试覆盖,也在作者自己的机器上日常使用,但接口、默认值和行为仍可能在版本之间调整,也没有针对恶意网络或多用户共享主机做加固。 它做的事正如其名:为"能在本机执行命令的 GUI"开一个入口。请把这个入口当作 SSH 端口来对待 —— 只在自己的 tailnet 内使用,先读下面的安全模型,确认这个取舍是你愿意承担的。如果今天还不想承担,把开关留着不动就好,没有任何代价。 欢迎提问、报 bug,也欢迎告诉我"这里的行为出乎意料"。 一个 DeepSeek Harness(dsh)插件:在插件页打开一个开关,就能用手机或任何电脑通过浏览器访问这台机器上跑的 harness —— 不需要公网 IP、不需要端口映射、不改 dsh 的监听地址。dsh 自始至终只监听 127.0.0.1。
展开完整文档(README 剩余 1 节)
dsh-tailscale-access

[!IMPORTANT]
早期版本 —— 打开开关前,值得先花两分钟读这一段。

本插件目前是 0.1.x,仍在持续测试中:有自动化测试覆盖,也在作者自己的机器上日常使用,但接口、默认值和行为仍可能在版本之间调整,也没有针对恶意网络或多用户共享主机做加固。

它做的事正如其名:为"能在本机执行命令的 GUI"开一个入口。请把这个入口当作 SSH 端口来对待 —— 只在自己的 tailnet 内使用,先读下面的安全模型,确认这个取舍是你愿意承担的。如果今天还不想承担,把开关留着不动就好,没有任何代价。

欢迎提问、报 bug,也欢迎告诉我"这里的行为出乎意料"。

一个 DeepSeek Harness(dsh)插件:在插件页打开一个开关,就能用手机或任何电脑通过浏览器访问这台机器上跑的 harness —— 不需要公网 IP、不需要端口映射、不改 dsh 的监听地址。dsh 自始至终只监听 127.0.0.1。

手机 / 任何电脑 │ tailscale serve(tailnet 内,端到端加密) │ 或 cloudflared quick tunnel(公网 HTTPS) ▼ 本地重写代理 127.0.0.1:8787 │ Host → 127.0.0.1:3080;丢弃 Origin/Referer/Sec-Fetch-Site; │ 注入 harness 自己的浏览器 cookie ▼
dsh web 127.0.0.1:3080(不知道外面有人)

npm 包名是 dsh-tailscale-access;插件的 settings section、HTTP 路由与状态文件名仍沿用 remote-access。

环境要求

- DSH 0.1.5-rc.2(next)或 0.1.6-alpha.2+(alpha)。卡片同时注册进两个 slot:0.1.6 的侧边栏「插件」页用 plugins.item,0.1.5-rc.2 的「设置 → 插件」页用按 namespace 作 key 的 settings.plugin.item;两个页面都不会渲染对方的 slot,所以只会出现一张卡。更老的版本(如 npm 上仍标 latest 的 0.0.1-rc.1)没有本插件能用的卡片 slot:此时打开开关会明确报 DSH_VERSION_UNSUPPORTED,而不是跑一个没人看得见的面板。包内已用 engines.dsh 声明。
- Node >= 20(engines.node)。插件自身只用 Node 内置模块。
- tailscale 模式:装好并登录 tailscale,tailnet 打开 HTTPS 证书,且有配置 tailscale serve 的权限(Linux 上即 tailscale operator)。
- quick 模式(实验性,面板暂不提供):cloudflared。allowDownload 为 true 时首次使用会自动下载到 $DSH_HOME/cache/cloudflared,也可以用 cloudflaredPath 指向已有二进制。
- none 模式:不需要额外组件。

安装

用「插件」页安装(推荐)

在 DSH 0.1.6-alpha.2+ 里打开侧边栏的 插件(Plugins) 页,点 添加插件,填入包名并安装(0.1.5-rc.2 走「设置 → 插件」):

dsh-tailscale-access

装完点 立即启用 即可。这一步会同时写好 profile 依赖和 dsh.profile.bundles 条目。

手动安装

把包装进 web profile(profile 位于 ~/.dsh/profiles/web):

cd ~/.dsh/profiles/web
pnpm add dsh-tailscale-access

再把包名加进 profile manifest 的 bundle 列表:

// ~/.dsh/profiles/web/package.json
{
"dependencies": {
"dsh-tailscale-access": "^0.1.0"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-tailscale-access"
]
}
}
}

profile 里 "patchReload": "live" 时改 manifest 会自动重载;否则重启 dsh web。在 profile 目录外也可以用 dsh plugin --profile web add dsh-tailscale-access,它做的是同一个 pnpm 步骤。

打开面板

侧边栏 → 插件 → Remote Access(官方分组)。它是配置页,不在「设置 → 插件」里 —— 后者是只读的插件清单。

三种模式

| 模式 | 入口 | 认证 | 说明 |
| tailscale(默认) | tailscale serve --https=443 + 本地代理 | tailnet 身份(Tailscale-User-Login + 允许名单) | 域名固定 https://..ts.net、端到端加密、第三方看不到明文;不需要口令 |
| quick(实验性) | cloudflared quick tunnel | 口令(+ 可选来源白名单) | 仍在测试中,面板暂不提供 —— 想试就在设置段里写 mode: quick。公网 HTTPS、零安装、域名每次变;必须显式确认风险 |
| none | 只开 loopback 本地代理,不开隧道 | 口令 | 调试用:验证代理链路与登录流程;本身不对外发布任何东西 |

同时只允许一个模式生效;切换模式会先拆掉旧入口再建新入口。tailscale 模式的入口地址来自节点的 MagicDNS 名(https://..ts.net);本地代理默认端口 8787,dsh 默认 3080。

Funnel 与 tagged node 不带身份头,一律拒绝。

安全模型

这个插件是故意提供 dsh 自己拒绝提供的外网入口:上游不允许绑定网络接口,harness 始终只监听 loopback。入口默认关闭,请按需开启 —— 入口对面是一个能执行任意命令的 GUI。

- 身份优先。 tailscale 模式下唯一凭据是 Tailscale-User-Login,且只在请求来自 loopback(tailscaled 代理)且启用代理头时才被采信。客户端伪造的 Tailscale-User- 一律忽略;缺身份头的请求返回 403 并计入 denied。
- 允许名单 fail-closed。 allowedUsers 为空时默认只允许你自己(启用时从 tailscale status --json 的 Self.UserID + User 映射解析 login);解析不出来就拒绝启用。不允许"空 = 放行所有人"。
- 口令模式。 quick 与 none 都要求口令(至少 8 位),quick 还要求 acknowledgeRisk: true。会话是 HMAC 签名的 cookie(HttpOnly、SameSite=Lax、HTTPS 时 Secure),有效期由 sessionHours 控制(默认 72 小时)。登录失败按 IP 限速:5 分钟内 8 次失败封禁 15 分钟。quick 还可以用 allowedCidrs 按隧道传来的 CF-Connecting-IP 限制来源。
- 只绑 loopback。 本地代理只监听 127.0.0.1,dsh 始终只监听 127.0.0.1:3080;不需要 --trusted-host,浏览器全程不接触 harness token。
- 代理层做什么。 把 Host 改写为 127.0.0.1:,丢弃 Origin/Referer/Sec-Fetch-Site,用服务端换来的 harness 浏览器 cookie 替换 Cookie(上游 401 时自动重换一次),响应方向剥掉 Set-Cookie 与逐跳头,HTTP 与 WebSocket 升级都转发,客户端地址由代理自己解析。tailscale 模式下通过白名单校验的身份头会转发给上游;none/quick 模式下一律剥离。
- 代理层不信什么。 客户端自带的 CF-Connecting-IP、X-Forwarded-、Forwarded、True-Client-IP 一律丢弃后重建(只在隧道模式且请求来自 loopback 时才采信);伪造的 Tailscale-User-* 一律忽略;tailscale 模式下本地会话 cookie 永远不作为身份。
- 关闭即收口: tailscale serve reset、关代理、清会话,不留监听。
- 能进这个 GUI 的人 = 能批准 = 能授权命令执行。 所以 allowedUsers 白名单 / 口令就是"谁有权批准"的边界。

配置

Remote Access 卡片是本插件唯一的 UI,没有单独的设置表单,也没有 CLI。卡片每 1.5 秒轮询 GET /remote-access/status.json,状态、入口 URL 与客户端列表无需刷新页面即可更新。

| 字段 | 类型 | 默认 | 作用 |
| enabled | boolean | false | 总开关。为 true 时每次 harness 启动自动恢复这个入口(不是操作系统开机自启)。 |
| mode | tailscale \| quick \| none | tailscale | 入口方式。 |
| port | number | 8787 | 本地代理端口。 |
| sessionHours | number | 72 | 口令模式的会话有效期。 |
| allowedUsers | string[] | [] | tailscale 身份白名单;空 = 只允许本节点自己的 login。 |
| allowedCidrs | string[] | [] | quick / none 的来源地址白名单。 |
| cloudflaredPath | string | "" | 指定 cloudflared 二进制;空则先搜 PATH,再搜缓存目录。 |
| allowDownload | boolean | true | 允许 quick 模式首次使用时自动下载 cloudflared。仅 settings section。 |
| acknowledgeRisk | boolean | false | quick 模式必须为 true 才允许启用。 |
| audit | boolean | true | 写审计日志(登录成功/失败、被拒、被踢)。 |
| statusPage | boolean | true | 提供只读状态页。 |
| password | string(secret) | — | quick / none 必需,至少 8 位。仅 settings section。 |
| bind | string | "" | 高级项:覆盖本地代理监听地址。留空即 loopback;其它取值会扩大监听面、失去 loopback 保证。仅 settings section。 |

password、allowDownload、bind 在卡片里没有控件,需要直接改 settings section。

总开关与模式下拉立即写入;文本、数字、列表字段暂存 + Save(空值 = 回默认值)。卡片会标注用户层是否覆盖了默认值,并显示运行阶段(已停止 / 启动中 / 运行中 / 失败);前置检查失败时直接显示可复制的修复命令。

口令要写进插件的 settings section。卡片里没有口令输入框,也不会读回口令;状态接口只报告是否已设置(passwordSet):

~/.dsh/settings.yaml
remote-access:
mode: quick
password: ""
acknowledgeRisk: true

卡片还会显示机器名、tailnet 名、tailscale 版本与 BackendState,已连接客户端列表(身份或 IP、首次连接、最后活跃、WebSocket 数、请求数)以及每行的踢掉,并保留一份有界的最近事件。重启隧道 不重启 harness 即可重建入口。关闭开关立即生效,不留监听。

远端页面:DSH 的设置限制

DSH 把"页面是否拥有 Host"绑定在页面 authority 上(isLoopback = localhost / [::1] / 127.0.0.0/8)。在非 loopback 页面上设置镜像跑在 memory 模式:不读设置文档,写入被丢弃且静默成功。所以手机经 tailscale / cloudflared 访问时,DSH 自身的语言、主题、各设置页都会显示默认值、改动不生效(这是 DSH 的既有设计,不是本插件的转发问题 —— 转发层已逐项验证:主页注入逐字节相同、SSE/WS/POST 均正常、零失败请求)。

本插件因此自带配置读写接口,这些 host 路由由代理从 loopback 转发,所以在远端页面上同样可用:

- 读:GET /remote-access/status.json 的 config(host 的有效配置,永不含口令,只有 passwordSet 布尔;另给 configOverridden 表示是否偏离默认)。
- 写:POST /remote-access/action 的 {action:"set",patch} / {action:"unset",fields} / {action:"reset"}。校验失败返回 400 + code,不是 500。

settings section 仍是唯一真源,接口只是另一个写入口。结果:Remote Access 卡片在手机上和在本机一样可用(显示真实状态、能真正改配置、刷新不丢)。DSH 其它设置页仍受上面的限制。

远端页面的「读取宿主设置」按钮

非 loopback 页面上,卡片会显示 远端页面:读取宿主设置 一节(本机页面上隐藏 —— 本机页面本来就有设置文档)。点 读取宿主设置并应用 会请求 GET /remote-access/host-settings.json(宿主设置文档,敏感值已脱敏),把宿主的语言、外观与字号应用到当前页面。文档里的其它设置只报告、不应用 —— 那些偏好属于各自的插件。读取失败会显示原因。

远端审批(重要)

需要审批的操作(例如写工作区外的文件)可以在手机上批准:审批走的是同一条被代理的通道(host 侧 approval/request waterfall → 浏览器侧 ui-approval 的 remote event),待审批状态是会话状态,任何跟随该会话的客户端都能看到面板。三条必须知道的规则:

- 至少要有客户端在线:没有任何 answerer 时请求 fail-closed(直接拒绝),不会排队等你回来。本机浏览器开着也算。
- 谁先答谁生效:本机与手机会同时看到同一个请求,晚答被丢弃;请求被 turn 取消后晚答同样作废。
- 手机被挂起/断连就不会等你:要保活(页面留在前台)。tailscale 模式是 HTTPS(secure context),浏览器能力完整;本版本没有明文回退。

推论:能进这个 GUI 的人 = 能批准 = 能授权命令执行。所以 allowedUsers 白名单 / 口令就是"谁有权批准"的边界。

排错

卡片提示 "not operator"

Linux 上默认只有 root 能改 tailscale serve 配置。把当前用户设为 tailscale operator 即可(一次即可,之后无需 sudo)。卡片会显示确切命令:

sudo tailscale set --operator=$USER

tailnet 没开 HTTPS 证书

tailscale 模式始终发布 HTTPS 443,没有明文 tailscale serve --tcp 回退:明文 HTTP 页面不是 secure browser context,DSH 客户端插件里调用 crypto.randomUUID() 的地方会直接坏掉。去 Tailscale admin console → DNS → HTTPS Certificates 打开,等证书签发后重新打开开关。实在开不了就用 quick 模式(cloudflared 自带 HTTPS)。卡片会显示失败原因,提示里指明 admin console 的设置项,并给出可复制的 tailscale serve --bg --https=443 http://127.0.0.1: 命令。

tailscale 未安装 / 未运行 / 未登录

curl -fsSL https://tailscale.com/install.sh | sh # Linux
brew install tailscale # macOS
winget install --exact --id Tailscale.Tailscale # Windows

sudo systemctl enable --now tailscaled # 守护进程没跑(Linux)
brew services start tailscale # 守护进程没跑(macOS,Homebrew)
open -a Tailscale # 守护进程没跑(macOS,应用包) Start-Service Tailscale # 守护进程没跑(Windows)
sudo tailscale up # 没登录
tailscale status # 确认节点状态 tailscale ip -4 # 节点的 tailnet 地址

tailscale 给出登录链接时,卡片显示的提示里会带上该 URL。卡片能区分"未安装 / 未运行 / 未登录 / 不是 operator",前置条件不满足时拒绝启用。每种失败都会带上一句人话结论和一条可复制命令。

cloudflared 找不到或下载失败

allowDownload 为 true 时,quick 模式会把 cloudflared 下载到 $DSH_HOME/cache/cloudflared。下载失败(无网络、没有对应平台的构建、代理问题)时,自己装一个 cloudflared,并把 cloudflaredPath 指向它。

本地端口被占用

配置的 port 报 EADDRINUSE。在卡片里换一个 port,或停掉占用者:

ss -ltn | grep 8787

有残留规则 / 启用后没有发布

上一次运行可能留下 serve 规则。清掉再启用:

tailscale serve status
tailscale serve reset

收集诊断信息

curl -s http://127.0.0.1:8787/remote-access/status.json | head -c 2000
tailscale serve status
cat ~/.dsh/remote-access.json
tail -40 ~/.dsh/remote-access-audit.log
ss -ltn | grep -E '3080|8787'

dsh 控制台里 remote-access: 开头的日志行有完整错误。只读状态页 /remote-access/status 在手机上经隧道也能打开。

文件与接口

| 路径 | 内容 |
| $DSH_HOME/remote-access.json | 运行状态快照(enabled、mode、url、port、客户端数、denied、lastError、updatedAt)。 |
| $DSH_HOME/remote-access-audit.log | 审计日志(JSON 行,权限 0600,超过 5 MB 轮转为 .1),audit 为 true 时写入。 |
| $DSH_HOME/cache/cloudflared/ | quick 模式自动下载的 cloudflared 二进制。 |
| $DSH_HOME/settings.yaml 里的 settings section remote-access | 配置,唯一真源。 |

所有 host 路由都要求 loopback 来源,所以即使 dsh 将来绑得更宽也不会泄漏到网络;代理从 loopback 转发,因此远端页面能用到它们。

| 路由 | 用途 |
| GET /remote-access/status.json | 状态 + 不含口令的有效 config。 |
| POST /remote-access/action | kick、restart、set、unset、reset。需要 content-type: application/json 与 x-remote-access-action: 1 头,随机网页无法驱动它(CSRF)。 |
| GET /remote-access/status | 只读状态页(statusPage: true)。 |
| GET /remote-access/host-settings.json | 宿主设置文档(已脱敏),供远端页面按钮使用。 |

动作请求体:

{"action": "kick", "id": ""}
{"action": "restart"}
{"action": "set", "patch": {"port": 9000}}
{"action": "unset", "fields": ["port"]}
{"action": "reset"}

已知限制

- 本插件提供的是 dsh 自己拒绝提供的外网入口,默认关闭,请有意开启。
- quick 模式的 URL 公网可解析、每次启动都变,扫描器会发现它;唯一防线是口令(外加可选 CIDR),不建议长期开着 quick。固定域名的 named tunnel + Cloudflare Access 未实现。
- 口令在 settings 文档里是明文存储,对外只报告 passwordSet 布尔值;只存 salt + scrypt 哈希未实现。
- none / quick 模式下口令在 loopback 这一段是明文 HTTP;对外一段是 HTTPS(tailscale / cloudflared)。
- 远端页面上 DSH 自身的设置页仍显示默认值;只有语言、外观与字号能通过上面的按钮应用。
- Tailscale Funnel 与 tagged node 不带身份头,一律拒绝。
- 没有账号体系或权限分级:白名单/口令是单一闸门,过了闸门的人就能通过 GUI 执行命令。
- 远端审批要求至少有一个客户端在线,且先答先得;手机被挂起就不会再回答。
- dsh 自身的安全说明依然适用:harness 未做安全审计,沙箱/审批不保证隔离。

开发与测试

npm install # 只依赖 @deepseek-ai/schemastery
npm test # node --test tests/
node --test tests/routes.test.mjs

167 个自动化测试,全部用 node:test,使用假上游/假二进制;需要网络的用例用 DSH_TEST_NETWORK 守卫。

| 测试文件 | 覆盖 |
| tests/config.test.mjs | 配置归一化、绑定解析、口令要求、错误结构 |
| tests/routes.test.mjs | host 路由:loopback 守卫、CSRF 头、动作、状态页、host-settings 路由 |
| tests/proxy.test.mjs | 转发层:头改写、cookie 注入、WS、限速、身份规则 |
| tests/tailscale.test.mjs | tailscale 状态机与 serve 编排 |
| tests/cloudflared.test.mjs、tests/supervisor.test.mjs | 隧道进程、退避、原子写状态 |
| tests/orchestration.test.mjs、tests/integration.test.mjs | 生命周期、模式切换、对假上游的端到端接线 |
| tests/client-bundle.test.mjs | 客户端卡片 bundle 形状与行为 |

仓库里另有 ACCEPTANCE.zh.md(人工验收清单)。

验证状态

- 卡片已在真实 DSH 0.1.6-alpha.2 上用无头浏览器验证:能注册进 plugins.item、能打开完整页面、轮询状态接口且无控制台报错。
- 尚未在真实 GUI 中跑过:写入路径(开关/下拉 + Save 往返)、踢人、切换语言、窄屏/手机布局。
- tailscale serve 实机链路尚未在装好 tailscale 的机器上端到端跑过;状态机由假二进制的单元测试覆盖。
- 经隧道的远端审批目前是文档所述行为,尚未端到端验证。

许可证

MIT,见 LICENSE。
预览分享卡片长什么样 ↓why-did/dsh-tailscale-access
分享 · DeepSeek Harness Hub
why-did/dsh-tailscale-access

用手机浏览器安全访问本机 harness 界面

这是你的仓库?认领条目

回到顶部