@linxin666/dsh-remote-web-ui 0.3.13 → 0.3.14
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.i18n.yaml +2 -2
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/lib/client.js +1 -5
- package/lib/client.js.map +1 -1
- package/lib/index.js +3 -8
- package/lib/types/client/remote-channel.d.ts +0 -2
- package/lib/types/client/remote-channel.d.ts.map +1 -1
- package/lib/types/client/remote-channel.js +0 -4
- package/lib/types/remote-api.d.ts +1 -1
- package/lib/types/remote-api.d.ts.map +1 -1
- package/lib/types/remote-api.js +1 -1
- package/lib/types/remote-channel-boot.d.ts.map +1 -1
- package/lib/types/remote-channel-boot.js +0 -1
- package/lib/types/remote-channel-rules.d.ts +0 -1
- package/lib/types/remote-channel-rules.d.ts.map +1 -1
- package/lib/types/remote-channel-rules.js +0 -1
- package/lib/types/remote-methods.d.ts +1 -4
- package/lib/types/remote-methods.d.ts.map +1 -1
- package/lib/types/remote-methods.js +1 -5
- package/package.json +18 -18
- package/src/client/remote-channel.ts +0 -3
- package/src/remote-api.ts +0 -1
- package/src/remote-channel-boot.ts +0 -1
- package/src/remote-channel-rules.ts +0 -2
- package/src/remote-methods.ts +1 -6
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 62dd01494df6877b90725715495c39f115dd1e5a
|
|
6
|
+
README.zh.md: 0e1ce635be94a16bfe14bd2ced9a26c8df140e21
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ The official desktop layout already auto-collapses the sidebar below 1024px. On
|
|
|
27
27
|
- **mobile plugin scope**: while the layer is active, the right-hand details column and the desktop-oriented tool surfaces (SSH terminal, skill explorer, task board, git graph, pet, perf, usage) are hidden - keyed on the L2 semantic roots (`data-dsh-plugin`), so ownership stays with the declaring plugin and class churn cannot resurrect them. These are render suppressions; the client bundles still load. Activation also closes the details panel through the official `ctx.layout.closeDetails()`.
|
|
28
28
|
- a **manual opt-out**: `sessionStorage.dsh-remote-force-desktop = 1` disables the whole layer; landscape, desktop, and wide viewports are never touched.
|
|
29
29
|
|
|
30
|
-
The paired remote desktop also runs in **host mode**: on this harness line the "configuration plane is local" behavior is a client-side branch on `connection.isLoopback`, and the channel boot script installs the transport hook (`__DSH_TRANSPORT__.ownsHost = true`) on non-loopback origins before any boot entry. Settings, credentials, agent presets, and deliverables therefore work on the phone exactly as on the desktop — every call still rides the gated `/remote` channel.
|
|
30
|
+
The paired remote desktop also runs in **host mode**: on this harness line the "configuration plane is local" behavior is a client-side branch on `connection.isLoopback`, and the channel boot script installs the transport hook (`__DSH_TRANSPORT__.ownsHost = true`) on non-loopback origins before any boot entry. Settings, credentials, agent presets, and deliverables therefore work on the phone exactly as on the desktop — every call still rides the gated `/remote` channel. Three control planes stay physically local: `/api/pair/*`, `/api/update/*`, and `/api/plugin-manager/*`.
|
|
31
31
|
|
|
32
32
|
## Requirements
|
|
33
33
|
|
|
@@ -156,7 +156,7 @@ The public path is the same round trip through a tunnel (see "Remote access over
|
|
|
156
156
|
- **Pairing is the access control for the `/remote` channel**: while `requirePairingForLan` is on (default), every request must carry a live paired-device cookie, enforced before any bytes are forwarded. A missing or revoked session receives HTTP 403 with a JSON rejection carrying `error.code: "unpaired"`; the browser's `EventSource` API exposes only the stream failure, not that response body.
|
|
157
157
|
- **The channel carries the process's own inner credential.** The harness browser-auth cookie is authority-bound (minted for the exact `host:port` a browser visited) and has no loopback exemption, so a proxied re-issue to `127.0.0.1` cannot reuse a device's cookie. The plugin therefore redeems its own launch token once — the same exchange a first browser visit performs — and attaches that cookie to re-issued requests. The credential is only ever exercised behind the pairing gate above; 停止/取消配对 immediately stop exercising it.
|
|
158
158
|
- **Cohort reality: pairing does not gate direct `/api`.** On the pinned 0.1.2-alpha.2 line nothing emits the `api/gate` seam, so a direct `/api` call from a LAN origin is governed solely by the harness fence (which auto-trusts LAN literals under a `0.0.0.0` bind) plus the harness browser-auth cookie. A browser credential a device has already redeemed therefore survives 停止/取消配对 until its natural expiry (30 days) — revocation binds the `/remote` channel and the pairing cookie, not that credential. The plugin probes the `/api` posture and warns loudly; treat a LAN-exposed bind as a deliberate decision, and prefer loopback plus tunnels when the machine is shared.
|
|
159
|
-
- **A paired device is a full-control credential.** With host mode active it reaches the complete host API — chat, sessions, settings, credentials, agent presets, deliverables — mirroring the SDK's own stance that a loopback desktop is trusted. Only the
|
|
159
|
+
- **A paired device is a full-control credential.** With host mode active it reaches the complete host API — chat, sessions, settings, credentials, agent presets, deliverables — mirroring the SDK's own stance that a loopback desktop is trusted. Only the three control planes (pairing, self-update, plugin install/remove) stay physically local. Only pair devices you control; 停止 or per-device 取消配对 revokes immediately.
|
|
160
160
|
- **Control endpoints stay loopback-only**: mint/stop/revoke, the device roster, the lan-bind status, and the update endpoints answer only to loopback. A LAN-origin browser sees the "配对面板仅限本机使用" banner.
|
|
161
161
|
- **The app landing is cookieless-optional.** After pairing, the QR lands the device on `/pair-app`, served by this plugin: the official shell is delivered without passing the harness index gate, and the device credential rides a `x-dsh-remote-device` header (fetch) / `device` query (WebSocket upgrades) that the boot patch attaches from sessionStorage. The flow therefore works when the device browser blocks all cookies; the pairing cookie remains the primary credential where the browser stores it, and the harness browser-auth cookie is no longer required on the phone path at all.
|
|
162
162
|
- **Reopens are owned by a service worker (https origins).** A paired phone returning from history, a bookmark, or tab restore navigates to bare `/` — a path the plugin does not own, where the harness fallback seat answers with its browser-auth 401 (the cookieless flow never holds that credential). The app shell therefore registers `/pair-app.sw.js` (fenced like `/pair-app`; the script is inert logic with no secrets): it intercepts navigations to `/` only, re-serves the shell network-first through `/pair-app` — which re-validates the device cookie and refreshes its presence, so every reopen also keeps the session alive — falls back to the cached shell offline, and passes the navigation through when the plugin no longer answers (a revoked device then sees the harness response or the bilingual re-scan page). Plain-HTTP LAN origins are not secure contexts and never register the worker; there a reopen means scanning a fresh QR.
|
package/README.zh.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
- **移动端插件范围**:适配层激活时,右侧详情列与面向桌面的工具界面(SSH 终端、技能中心、任务看板、git graph、宠物、性能引擎、使用统计)一律隐藏——以 L2 语义根(`data-dsh-plugin`)为键,归属由声明方插件负责,官方类名变动也不会复活它们。这些是渲染抑制;客户端 bundle 仍会加载。激活时还会经官方 `ctx.layout.closeDetails()` 真正关闭详情面板。
|
|
28
28
|
- **手动退出**:`sessionStorage.dsh-remote-force-desktop = 1` 关闭整个适配层;横屏、桌面与宽视口永不触碰。
|
|
29
29
|
|
|
30
|
-
配对远程桌面同时运行在 **host 模式**:在本 harness 线上,「配置面仅限本机」的行为是客户端分支(`connection.isLoopback`),通道 boot 脚本在一切 boot entry 之前对非回环源安装传输钩子(`__DSH_TRANSPORT__.ownsHost = true`)。设置、凭据、Agent 预设与产出物在手机上与桌面完全一致——所有调用仍走门控 `/remote`
|
|
30
|
+
配对远程桌面同时运行在 **host 模式**:在本 harness 线上,「配置面仅限本机」的行为是客户端分支(`connection.isLoopback`),通道 boot 脚本在一切 boot entry 之前对非回环源安装传输钩子(`__DSH_TRANSPORT__.ownsHost = true`)。设置、凭据、Agent 预设与产出物在手机上与桌面完全一致——所有调用仍走门控 `/remote` 通道。三个控制面保持物理本地:`/api/pair/*`、`/api/update/*` 与 `/api/plugin-manager/*`。
|
|
31
31
|
|
|
32
32
|
## 环境要求
|
|
33
33
|
|
|
@@ -156,7 +156,7 @@ pnpm run build
|
|
|
156
156
|
- **配对是 `/remote` 通道的访问控制**:`requirePairingForLan` 开启(默认)时,每个请求必须携带有效配对设备 cookie,在任何字节转发之前强制。缺失或被撤销的会话收到 HTTP 403,JSON 拒绝携带 `error.code: "unpaired"`;浏览器 `EventSource` API 只暴露流失败,不暴露响应体。
|
|
157
157
|
- **通道携带进程自己的内部凭据。** harness 浏览器认证 cookie 与 authority 绑定(为浏览器访问过的确切 `host:port` 签发)且没有回环豁免,因此转发到 `127.0.0.1` 的再发起请求无法复用设备的 cookie。插件因此自行兑换一次自己的启动令牌——与浏览器首次访问执行的是同一次交换——并把所得 cookie 附到再发起请求上。该凭据只在上面的配对门之后被使用;停止/取消配对会立即停止对它的使用。
|
|
158
158
|
- **本 cohort 的现实:配对不门控直连 `/api`。** 在锚定的 0.1.2-alpha.2 线上,没有任何组件发出 `api/gate` seam,因此来自局域网源头的直连 `/api` 仅由 harness 围栏(`0.0.0.0` 绑定下自动信任局域网字面量)加 harness 浏览器认证 cookie 约束。设备已经兑换过的浏览器凭据在停止/取消配对后仍然有效,直到其自然过期(30 天)——撤销约束的是 `/remote` 通道与配对 cookie,而不是那个凭据。插件会对 `/api` 姿态做探测并大声告警;请把局域网绑定当作深思熟虑的决定,在共享机器上优先回环加隧道。
|
|
159
|
-
- **配对设备是完全控制凭据。** host 模式下它可达完整 host API——聊天、会话、设置、凭据、Agent 预设、产出物——与 SDK
|
|
159
|
+
- **配对设备是完全控制凭据。** host 模式下它可达完整 host API——聊天、会话、设置、凭据、Agent 预设、产出物——与 SDK 对回环桌面的信任一致。只有三个控制面(配对、自更新、插件安装/卸载)保持物理本地。只配对你控制的设备;停止或逐设备取消配对立即撤销。
|
|
160
160
|
- **控制端点仅限回环**:铸造/停止/撤销、设备列表、lan-bind 状态与更新端点只应答回环。局域网源浏览器看到「配对面板仅限本机使用」横幅。
|
|
161
161
|
- **应用落地页不依赖 cookie。** 配对后二维码把设备带到 `/pair-app`——由本插件直接交付官方应用壳,不经过 harness 索引认证门;设备凭据经 `x-dsh-remote-device` 请求头(fetch)与 `device` 查询参数(WebSocket 升级)由引导补丁从 sessionStorage 挂载。因此手机浏览器完全禁用 cookie 时链路依然成立;有 cookie 时配对 cookie 仍是主凭据,手机路径不再需要 harness 浏览器认证 cookie。
|
|
162
162
|
- **重开由 service worker 接管(仅 https 源)。** 配对过的手机从历史、书签或标签恢复回来时导航到裸 `/`——插件不拥有的路径,harness 兜底座会用浏览器认证 401 应答(不依赖 cookie 的流程永远拿不到那份凭据)。应用壳因此注册 `/pair-app.sw.js`(与 `/pair-app` 同一栅栏;脚本是不含任何秘密的惰性逻辑):只拦截对 `/` 的导航,经 `/pair-app` 网络优先地重发应用壳——同时校验设备 cookie 并刷新其活跃时间,每次重开也在为会话续期——离线时回退缓存的壳,插件不再应答时把导航原样放行(被撤销的设备随后看到 harness 应答或双语重扫页)。纯 HTTP 的局域网源不是安全上下文,永远不会注册该 worker;那里的重开意味着重新扫码。
|
package/lib/client.js
CHANGED
|
@@ -4015,7 +4015,6 @@ window.__ModuleLoader__.load({
|
|
|
4015
4015
|
apiPrefix: "/api/",
|
|
4016
4016
|
pairPrefix: "/api/pair/",
|
|
4017
4017
|
updatePrefix: "/api/update/",
|
|
4018
|
-
desktopLauncherPrefix: "/api/dsh-desktop-launcher",
|
|
4019
4018
|
settingsBridgePrefix: "/api/dsh-web-ui-settings",
|
|
4020
4019
|
sidebarPrefix: "/sidebar/",
|
|
4021
4020
|
gitPrefix: "/git/",
|
|
@@ -4047,8 +4046,6 @@ window.__ModuleLoader__.load({
|
|
|
4047
4046
|
* - the pairing routes (`/api/pair/*`) stay where they are — accept must
|
|
4048
4047
|
* work BEFORE a device is paired;
|
|
4049
4048
|
* - the update endpoints (`/api/update/*`) stay loopback-only;
|
|
4050
|
-
* - desktop-launcher create/shutdown (`/api/dsh-desktop-launcher/*`) stay
|
|
4051
|
-
* loopback-only (host-local files and process exit);
|
|
4052
4049
|
* - the family settings bridge (`/api/dsh-web-ui-settings/*`) stays
|
|
4053
4050
|
* loopback-only (same plane as SDK settings.*);
|
|
4054
4051
|
* - `/api/*` (SDK methods and `/api/<plugin>/...` plugin namespaces),
|
|
@@ -4085,7 +4082,6 @@ window.__ModuleLoader__.load({
|
|
|
4085
4082
|
function shouldRewriteFetchPath(pathname) {
|
|
4086
4083
|
if (pathname.startsWith(RULES.pairPrefix)) return false;
|
|
4087
4084
|
if (pathname.startsWith(RULES.updatePrefix)) return false;
|
|
4088
|
-
if (pathname === RULES.desktopLauncherPrefix || pathname.startsWith(`${RULES.desktopLauncherPrefix}/`)) return false;
|
|
4089
4085
|
if (pathname === RULES.settingsBridgePrefix || pathname.startsWith(`${RULES.settingsBridgePrefix}/`)) return false;
|
|
4090
4086
|
if (pathname.startsWith(RULES.apiPrefix)) return true;
|
|
4091
4087
|
if (pathname.startsWith(RULES.sidebarPrefix) || pathname === "/sidebar") return true;
|
|
@@ -4414,7 +4410,7 @@ window.__ModuleLoader__.load({
|
|
|
4414
4410
|
/** The building package's version, when the bundle carries it. */
|
|
4415
4411
|
function bakedVersion() {
|
|
4416
4412
|
try {
|
|
4417
|
-
return "0.3.
|
|
4413
|
+
return "0.3.14";
|
|
4418
4414
|
} catch {
|
|
4419
4415
|
return;
|
|
4420
4416
|
}
|