Skip to content

Releases

v1.2.0 (Tailscale remote access)

Choose a tag to compare

@YE-ZINAN YE-ZINAN released this 08 Oct 02:39

Remote access over Tailscale, a host-side preflight script, and a written post-mortem.

What's new

  • Tailscale remote access. The network guard now also allows 100.64.0.0/10, so the gateway is reachable from a phone on mobile data through your tailnet — no port forwarding, no public exposure. REMOTE-ACCESS.md covers the whole setup, the two gotchas we hit, and the isolation rules that keep the gateway away from the rest of the LAN.
  • tools/check-tailscale.ps1 — host-side preflight for the remote path: Tailscale state, the address the guard will match, the listening port, and whether the reachability rules can actually work. Exit code 0 means good to go.
  • The sidebar button now shows the reach scope — LAN only, or LAN + remote — so you can tell at a glance whether the gateway is currently reachable from outside the house.

What's fixed

  • tools/check-tailscale.ps1 check #5 had its criterion inverted and reported the opposite of the truth.

Docs

  • docs/issue-remote-mux-reset-2026-10-08.md — post-mortem of a "workspace looks stuck / can't pick a workspace / can't create a session" report that looked exactly like WebSocket resets inside this gateway. It wasn't. Worth reading for the falsified hypotheses (two of them, disproved by source reading plus a real ws client harness), the logging gap that made the wrong story convincing, and the actual cause: the client plugin had been fixed on disk while the running DSH host still had the old code loaded. Restart the DSH host after changing a client plugin.
  • IP addresses, device names and user names in the new documents are placeholders, matching what .gitignore already keeps out of this repo.

Upgrading

Update the checkout and restart the gateway (.\lan-gate.ps1 restart). Approved devices, the approval list and settings are untouched.

v1.1.0 (DSH button + self-healing)

Choose a tag to compare

@YE-ZINAN YE-ZINAN released this 04 Oct 04:01

The gateway now has a button inside DSH, and it comes back by itself.

What's new

  • A "phone access" button in the DSH sidebar, next to Settings. It shows how many devices are waiting for approval, and one click opens the approval page in your default browser. No more typing the admin URL by hand.
  • It follows the gateway state: running, N waiting, or not running. When the gateway is down, clicking it starts the gateway first and then opens the page.
  • It hides itself on phones and iPads. Those screens come through the gateway, where the approval page correctly answers 403 (loopback only), so the button would only be a trap there.
  • New endpoint GET /__langate/admin/summary, loopback only, under the same guard as the admin page. It returns waiting/approved counts and who is waiting.
  • Self-healing scheduled task. It used to fire once, 30 seconds after logon. It now also repeats every 5 minutes and restarts the gateway if it is gone.

Why the self-healing matters

The gateway can be killed hard, not merely crash. On 2026-10-04 it died at 09:11 and stayed down for 22 hours, leaving no trace: the SIGINT handler's exit line never reached run.log, and run.err.log was 0 bytes. That combination means TerminateProcess — no signal handler ever gets to run. With a logon trigger as the only trigger, nothing was going to bring it back.

The easiest way to hit this: starting the gateway from inside a DSH command. Processes spawned there belong to that command's process tree and die with it. Start it from the scheduled task instead.

Logs now rotate (run.log to run.log.prev) instead of being deleted on every start, so the previous run's log survives the next time this happens.

Upgrading

  • Re-run .\tools\install-autostart.ps1 to pick up the 5-minute self-healing trigger; the old task only had the logon trigger.
  • The DSH button is a separate, optional plugin in plugin/. Install it with dsh plugin --profile desktop add link:<path-to>/plugin. The gateway works without it.

Verified

  • Six test suites pass; three new assertions cover the summary endpoint.
  • Self-healing was tested by hard-killing the gateway: the task brought it back at the next 5-minute mark.
  • The button was confirmed end to end on the real desktop app — it renders, and clicking it opens the admin page in the system browser.

Not verified yet: the collapsed 56px sidebar rail (the code renders a dot only; no screenshot taken), and clicking the button while the gateway is stopped.


中文

给网关加了一个装在 DSH 里的按钮,并让它在被杀掉之后能自己回来。

本次新增

  • 左栏底部、设置图标旁边的「手机接入」按钮。 显示有几台设备在等批准,点一下用系统默认浏览器打开批准页,不用再手敲管理台地址。
  • 按钮跟着网关状态变:运行中 / 待批准 N / 没在跑。网关没在跑时,点击会先把它拉起来再打开页面。
  • 手机和 iPad 上不显示这个按钮。 那些界面是经网关代理过去的,批准页在那边会正确返回 403(只认回环地址),显示出来只会是个陷阱。
  • 新增接口 GET /__langate/admin/summary,只允许回环访问,与批准页同一道守卫。返回待批准 / 已批准计数和待批准设备。
  • 计划任务改为自愈。 原来只在登录后 30 秒触发一次,现在额外每 5 分钟重复一次,进程不在了就补起来。

为什么必须自愈

网关可能是被硬杀的,而不只是崩溃。2026-10-04 它 09:11 停了,之后 22 小时没恢复,且没留下任何痕迹:SIGINT 处理函数里那句「退出。运行 Ns …」没有进 run.log,run.err.log 是 0 字节。这个组合指向 TerminateProcess —— 信号处理函数根本没机会执行。而当时唯一的触发条件是登录,所以没有任何机制会把它带回来。

最容易踩的触发方式:从 DSH 的命令里启动网关。那里 spawn 的进程属于该命令的进程树,命令被清理时一起死。请交给计划任务启动。

日志也改为轮转(run.log → run.log.prev),不再每次启动都删,下次再出这种事上一次的日志还在。

升级须知

  • 重新跑一次 .\tools\install-autostart.ps1 才会有 5 分钟自愈触发条件;旧任务只有登录触发。
  • DSH 那个按钮是独立可选的插件,在 plugin/。装法:dsh plugin --profile desktop add link:<路径>/plugin。不装它网关照常工作。

已核验

  • 六个测试套件全部通过;新增三条断言覆盖状态接口。
  • 自愈经过实测:硬杀网关后,任务在下一个 5 分钟整点把它拉了回来。
  • 按钮在真实桌面端跑通:能看到,「点击 → 系统默认浏览器打开管理台」也已确认。

尚未核验:侧栏折叠成 56px 轨道时的观感(代码只留状态点,未截图),以及网关处于停止状态时点击按钮那条路径。

v1.0.0 (first release)

Choose a tag to compare

@YE-ZINAN YE-ZINAN released this 03 Oct 09:03

First release. A LAN gateway that lets your phone or iPad use the DeepSeek Harness desktop over Wi-Fi, without exposing DSH to the network.

What it does

  • Proxies DSH Web while it stays bound to 127.0.0.1. The gateway is the only entry point.
  • Device approval. A new device sees a "waiting for approval" page until you click Allow on the computer.
  • Mobile layout injection for phones and iPads, plus home-screen icons.
  • Network guard. Refuses to start when the machine is not on an allowed subnet.

Requirements

  • Node.js 18 or newer, with no third-party dependencies
  • DeepSeek Harness desktop running on the same machine

Before you use it

Plain HTTP, no TLS. LAN use only. The gateway reads the local DSH credential file to mint a session cookie, so it has to run on the same machine as DSH. Read NOTICE.md and the Security boundary section of the README first.

Verified

Six test suites pass: gate, mobile layout, PWA, end-to-end, WebSocket, API routes.


中文

让手机和 iPad 在同一个 WiFi 下使用电脑上的 DeepSeek Harness。DSH 本体仍然只监听 127.0.0.1,新设备需要在电脑上亲手批准一次。

零运行时依赖,只用 Node 内置模块。明文 HTTP、没有 TLS,只建议在可信局域网使用。