dsh-mobile 0.6.0 → 0.6.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.6.1 - 2026-10-08
6
+
7
+ - Reorganize the remote HTTPS origin, external proxy and managed Caddy forms with native radio groups, responsive fields, separate actions and matching Chinese, English and Italian labels. Thanks @abworks-dev for [#184](https://github.com/saya-ch/dsh-mobile/pull/184).
8
+ - Add pinned, reproducible Caddy review builds: Go 1.26.6, xcaddy 0.4.7, Caddy 2.11.6 and Tencent Cloud DNS 0.4.3, with locked source/dependency inputs, fresh private caches, two-build byte comparison and complete artifact checks. Isolated native Windows/Linux tests cover installation, restart, rollback, TLS, pairing, API, WebSocket and cleanup. Thanks @abworks-dev for [#185](https://github.com/saya-ch/dsh-mobile/pull/185); original author commits are retained alongside maintainer fixes.
9
+ - Find Windows Git Bash from the active Git installation rather than a fixed path. Keep missing-shell, timeout and signal failures distinct from expected nonzero command exits, and prevent shell startup environment variables from changing test behavior.
10
+ - Keep official managed Caddy installation disabled. Review builds and optional TEST prereleases do not enable the production component table or establish public DNS-01/ACME issuance and public-route readiness. Existing external proxies and remote providers are unchanged. See [Caddy status](docs/CADDY_MANAGED.en.md).
11
+ - Synchronize Android release metadata to 0.6.1 (build 77). Native features and the pairing/renewal protocol are unchanged from 0.6.0; the official APK uses the established package and signer, preserving pairings on same-signer upgrades.
12
+
5
13
  ## 0.6.0 - 2026-10-07
6
14
 
7
15
  Add mobile page module management, Android launcher choices, fixed device ordering and improved scanning, alongside connection, layout and WebView compatibility fixes. Update the plugin and Android app together. Original community commits are preserved alongside maintainer fixes; see [Contributors](CONTRIBUTORS.md).
package/CONTRIBUTORS.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # 贡献者 / Contributors
2
2
 
3
- GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-07 的实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
3
+ GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-08 的实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
4
4
 
5
- GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-07. The repository maintainer and automated dependency updates remain visible in GitHub's history.
5
+ GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-08. The repository maintainer and automated dependency updates remain visible in GitHub's history.
6
6
 
7
7
  ## 已合并 PR / Merged PRs
8
8
 
9
9
  | 社区成员 / Community member | 已合并 PR / Merged PRs |
10
10
  | --- | --- |
11
11
  | [@1624318455](https://github.com/1624318455) | [#93](https://github.com/saya-ch/dsh-mobile/pull/93) |
12
- | [@abworks-dev](https://github.com/abworks-dev) | [#91](https://github.com/saya-ch/dsh-mobile/pull/91), [#98](https://github.com/saya-ch/dsh-mobile/pull/98), [#99](https://github.com/saya-ch/dsh-mobile/pull/99), [#152](https://github.com/saya-ch/dsh-mobile/pull/152) |
12
+ | [@abworks-dev](https://github.com/abworks-dev) | [#91](https://github.com/saya-ch/dsh-mobile/pull/91), [#98](https://github.com/saya-ch/dsh-mobile/pull/98), [#99](https://github.com/saya-ch/dsh-mobile/pull/99), [#152](https://github.com/saya-ch/dsh-mobile/pull/152), [#184](https://github.com/saya-ch/dsh-mobile/pull/184), [#185](https://github.com/saya-ch/dsh-mobile/pull/185) |
13
13
  | [@ayiejosh](https://github.com/ayiejosh) | [#109](https://github.com/saya-ch/dsh-mobile/pull/109), [#110](https://github.com/saya-ch/dsh-mobile/pull/110), [#116](https://github.com/saya-ch/dsh-mobile/pull/116), [#117](https://github.com/saya-ch/dsh-mobile/pull/117), [#119](https://github.com/saya-ch/dsh-mobile/pull/119), [#124](https://github.com/saya-ch/dsh-mobile/pull/124), [#125](https://github.com/saya-ch/dsh-mobile/pull/125), [#133](https://github.com/saya-ch/dsh-mobile/pull/133), [#136](https://github.com/saya-ch/dsh-mobile/pull/136) |
14
14
  | [@chintoleung](https://github.com/chintoleung) | [#104](https://github.com/saya-ch/dsh-mobile/pull/104), [#147](https://github.com/saya-ch/dsh-mobile/pull/147), [#148](https://github.com/saya-ch/dsh-mobile/pull/148), [#158](https://github.com/saya-ch/dsh-mobile/pull/158), [#161](https://github.com/saya-ch/dsh-mobile/pull/161), [#162](https://github.com/saya-ch/dsh-mobile/pull/162), [#167](https://github.com/saya-ch/dsh-mobile/pull/167) |
15
15
  | [@cjxh21](https://github.com/cjxh21) | [#154](https://github.com/saya-ch/dsh-mobile/pull/154), [#155](https://github.com/saya-ch/dsh-mobile/pull/155) |
package/README.en.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/repository-hero.png" alt="Use DeepSeek Harness from a phone" width="100%">
2
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/repository-hero.png?v=0bfc8f909993" alt="Use DeepSeek Harness from a phone" width="100%">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">DSH Mobile</h1>
@@ -31,14 +31,14 @@
31
31
 
32
32
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
33
33
  >
34
- > **Current stable release: 0.6.0**. Add mobile page module management, app icon choices and device ordering; improve scanning, mobile layout, remote loading and older WebView compatibility. [Release notes](CHANGELOG.md#060---2026-10-07).
34
+ > **Current stable release: 0.6.1**. Improve remote HTTPS settings and pinned Caddy builds with cross-platform checks. The Android app receives a matching version, retaining 0.6.0's module management, icon choices, device ordering and scanning improvements. [Release notes](CHANGELOG.md#061---2026-10-08).
35
35
  >
36
- > **Upgrade reminder**: update the plugin and Android app together to 0.6.0 for all features and fixes. Older official apps with the same signer can be upgraded in place while keeping pairings. [Compatibility notes](#compatibility).
36
+ > **Upgrade reminder**: update the plugin and Android app together to 0.6.1. Older official apps with the same signer can be upgraded in place while keeping pairings. [Compatibility notes](#compatibility).
37
37
 
38
38
  <p align="center">
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.0/dsh-mobile-android-v0.6.0.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.0/dsh-mobile-android-v0.6.0.apk"><strong>Download Android app 0.6.0</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.0">Release notes and checksums</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.1/dsh-mobile-android-v0.6.1.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.1/dsh-mobile-android-v0.6.1.apk"><strong>Download Android app 0.6.1</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.1">Release notes and checksums</a></sub>
42
42
  </p>
43
43
 
44
44
  DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. Both routes reach the same sessions, Workspaces, messages, and tools. The computer manages their switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.
@@ -71,6 +71,14 @@ Model-search and pairing-page input sizes are corrected, and Android Back naviga
71
71
 
72
72
  </details>
73
73
 
74
+ ## 0.6.1 update
75
+
76
+ - **Remote settings**: clearer HTTPS origin, external-proxy and managed-Caddy form groups, fields and actions, including narrow-window layouts.
77
+ - **Builds and checks**: pinned Caddy inputs, Windows/Linux double-build comparison and isolated TLS, pairing, API, WebSocket and cleanup tests; corrected Windows Git Bash discovery and test-failure classification. [Caddy status](docs/CADDY_MANAGED.en.md)
78
+ - **Android app**: version-aligned 0.6.1 (build 77) with unchanged native features and pairing protocol, using the established release signer. Existing pairings do not need to be recreated.
79
+
80
+ Thanks [@abworks-dev](https://github.com/abworks-dev) for [#184](https://github.com/saya-ch/dsh-mobile/pull/184) and [#185](https://github.com/saya-ch/dsh-mobile/pull/185). Official managed Caddy installation remains unavailable. See the complete [changelog](CHANGELOG.md#061---2026-10-08).
81
+
74
82
  ## 0.6.0 update
75
83
 
76
84
  This update focuses on module management, app personalization and mobile access. See the complete [changelog](CHANGELOG.md#060---2026-10-07).
@@ -438,7 +446,7 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
438
446
 
439
447
  Existing apps (0.3.3 and later) do not need re-pairing. cpolar users should use app 0.3.15 or later because earlier apps may time out before a slow first load over the free route finishes; earlier apps also use a different status-bar strategy. The 0.4.0 app adds the multi-device list, startup behavior, and computer-side revocation status; older apps continue to connect to their saved single device. App 0.1.3 or earlier requires reinstalling and pairing again.
440
448
 
441
- Version 0.6.0 keeps the native pairing and renewal protocol compatible, so normally working older apps can continue connecting. Update to app 0.6.0 (build 76) for icon choices, scanning improvements, device ordering and the switching shortcut, while retaining earlier connection, rotation and authentication fixes.
449
+ App 0.6.1 (build 77) retains 0.6.0's native features and pairing/renewal protocol; existing pairings do not need to be recreated, and normally working older apps can continue connecting. Update the plugin and app together to retain 0.6.0's icon choices, scanning improvements, device ordering, switching shortcut and earlier fixes.
442
450
 
443
451
  GitHub Release APKs use a stable signing certificate, so an older official APK with the same signer can be upgraded in place while retaining pairings. A locally built Debug APK with a different signer cannot be overwritten by the official APK; plan to pair again when switching between them.
444
452
 
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/repository-hero.png" alt="用手机使用电脑中的 DeepSeek Harness" width="100%">
2
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/repository-hero.png?v=0bfc8f909993" alt="用手机使用电脑中的 DeepSeek Harness" width="100%">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">DSH Mobile</h1>
@@ -31,14 +31,14 @@
31
31
 
32
32
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
33
33
  >
34
- > **当前正式版本:0.6.0**。新增移动页面模块管理、App 图标选择与设备排序,升级扫码体验,改善移动布局、远程加载和旧 WebView 兼容。[更新记录](CHANGELOG.md#060---2026-10-07)。
34
+ > **当前正式版本:0.6.1**。优化远程 HTTPS 配置表单,完善 Caddy 固定构建与跨平台验证;Android App 同步版本,保留 0.6.0 的模块管理、图标选择、设备排序与扫码改进。[更新记录](CHANGELOG.md#061---2026-10-08)。
35
35
  >
36
- > **升级提醒**:请同步更新插件与 Android App 至 0.6.0,以获得完整功能与修复;同一正式签名的旧 App 可原位升级并保留配对。[兼容说明](#兼容性)。
36
+ > **升级提醒**:请同步更新插件与 Android App 至 0.6.1;同一正式签名的旧 App 可原位升级并保留配对。[兼容说明](#兼容性)。
37
37
 
38
38
  <p align="center">
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.0/dsh-mobile-android-v0.6.0.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.0/dsh-mobile-android-v0.6.0.apk"><strong>下载 Android App 0.6.0</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.0">版本说明与校验文件</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.1/dsh-mobile-android-v0.6.1.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.6.1/dsh-mobile-android-v0.6.1.apk"><strong>下载 Android App 0.6.1</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.1">版本说明与校验文件</a></sub>
42
42
  </p>
43
43
 
44
44
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
@@ -71,6 +71,14 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
71
71
 
72
72
  </details>
73
73
 
74
+ ## 0.6.1 更新
75
+
76
+ - **远程配置**:重新整理 HTTPS 地址、自备代理与托管 Caddy 的表单分组、字段和操作按钮,小窗口下也能清楚区分配置方式。
77
+ - **构建与验证**:固定 Caddy 构建输入,增加 Windows/Linux 双构建一致性及隔离 TLS、配对、API、WebSocket 和清理检查,修正 Windows Git Bash 路径与测试失败分类。[Caddy 状态](docs/CADDY_MANAGED.md)
78
+ - **Android App**:同步为 0.6.1(build 77),原生功能与配对协议不变,沿用正式签名;已有配对无需重建。
79
+
80
+ 感谢 [@abworks-dev](https://github.com/abworks-dev) 的 [#184](https://github.com/saya-ch/dsh-mobile/pull/184) 与 [#185](https://github.com/saya-ch/dsh-mobile/pull/185)。托管 Caddy 仍未开放正式安装;完整记录见 [CHANGELOG](CHANGELOG.md#061---2026-10-08)。
81
+
74
82
  ## 0.6.0 更新
75
83
 
76
84
  本次更新聚焦模块管理、App 个性化与移动访问体验;完整记录见 [CHANGELOG](CHANGELOG.md#060---2026-10-07)。
@@ -439,7 +447,7 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
439
447
 
440
448
  现有 App(0.3.3 及更新)无需重新配对;cpolar 用户应使用 0.3.15 或更新 App,较早版本可能在免费线路的慢速首次加载完成前超时;更早的 App 还使用不同的状态栏策略。App 0.4.0 才支持多设备列表、启动行为设置和电脑端撤销状态同步;旧版 App 仍可连接已保存的单台设备。App 0.1.3 及更早版本需卸载重装并重新配对。
441
449
 
442
- 0.6.0 保持原生配对与续期协议兼容,旧 App 的正常连接可继续使用;建议同步升级至 0.6.0(build 76),以获得图标选择、扫码改进、设备排序和切换快捷方式,并保留此前的连接、旋转及认证修复。
450
+ 0.6.1(build 77)的原生功能与配对、续期协议延续 0.6.0,已有配对无需重建;旧 App 的正常连接可继续使用。建议同步升级插件与 App,以保留 0.6.0 的图标选择、扫码改进、设备排序、切换快捷方式及此前修复。
443
451
 
444
452
  GitHub Release 的正式 APK 使用固定签名,可从同一签名的旧正式版原位升级并保留配对。自行构建的 Debug APK 若使用不同签名,不能直接覆盖安装正式版;切换前请准备重新配对。
445
453
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [中文](CADDY_MANAGED.md)
4
4
 
5
- > Managed mode and its isolated tests are integrated, but no pinned component has been published. Installation and connection remain disabled. Existing external HTTPS proxy mode is unaffected.
5
+ > Managed mode and its isolated tests are integrated, but no official pinned component is available. Installation and connection remain disabled. Existing external HTTPS proxy mode is unaffected.
6
6
 
7
7
  ## Requirements
8
8
 
@@ -34,6 +34,28 @@ Stopping access or changing provider waits for Caddy and Gateway termination, re
34
34
 
35
35
  ## Maintainer build and validation
36
36
 
37
- `scripts/build-caddy-component.mjs` fixes Go 1.26.6, xcaddy v0.4.7, Caddy v2.11.6, and the Tencent Cloud DNS module v0.4.3. It generates the executable, exact size and SHA-256, version/module records, and licenses for embedded dependencies. `caddy-component.yml` produces review artifacts only: no Release creation, production pin changes, or automatic publication.
37
+ Run these build and validation tools from a source checkout of this repository. The npm plugin package does not include these maintenance scripts; ordinary users do not need to compile Caddy.
38
38
 
39
- The public custom-download endpoint returned v2.11.7 when v2.11.6 was requested; a dynamic latest endpoint cannot serve as a fixed-version artifact. Before enabling production installation, publish reviewed builds at immutable versioned URLs and populate the production verification table. All platforms remain disabled until then. Isolated tests use ephemeral loopback listeners and a test CA that is not installed in the system trust store to verify TLS, pairing authentication, raw API bytes, and WebSockets. They do not establish real DNS-01 issuance or public-route readiness.
39
+ The [builder](<../scripts/build-caddy-component.mjs>) fixes Go 1.26.6, xcaddy v0.4.7, Caddy v2.11.6 and Tencent Cloud DNS v0.4.3. The [input lock](<../scripts/caddy-component-lock.json>) freezes source revisions and compiled dependency versions/checksums. Each build uses fresh private compiler AND module caches, normal Go checksum verification, source-origin checks and retained-module verification. Unknown dependencies, replacements, wrong native settings or compiler versions fail closed before executing the generated Caddy.
40
+
41
+ Use the exact Go compiler (optionally through `GO_BINARY`); output directories must be new and absolute:
42
+
43
+ ```sh
44
+ node scripts/build-caddy-component.mjs --output-dir /absolute/new/first
45
+ node scripts/build-caddy-component.mjs --output-dir /absolute/new/second
46
+ node scripts/compare-caddy-builds.mjs --first /absolute/new/first --second /absolute/new/second --target linux-x64
47
+ ```
48
+
49
+ Windows uses native absolute paths and `--target win32-x64`. Reproducibility means identical executable bytes/size/SHA-256, not identical OS images or every rendered metadata/license file. The [workflow](<../.github/workflows/caddy-component.yml>) natively builds twice on Windows/Linux x64, validates complete evidence and tests the actually installed binary with an independent manifest. Tests cover real default inspection/promotion, no-redownload restart, corrupt-download rollback, TLS/pairing/API/WSS, durable device credentials and stopped-process owned cleanup while neighboring/pairing data survives. Other targets remain unreviewed.
50
+
51
+ PR and normal dispatch runs are read-only review-artifact builds. Only an explicit manual opt-in on an existing `caddy-component-2.11.6-tencentcloud-0.4.3-review.N` tag in the authorized `abworks-dev/dsh-mobile` fork can publish a **TEST prerelease**, after both native jobs pass:
52
+
53
+ ```sh
54
+ gh workflow run caddy-component.yml --repo abworks-dev/dsh-mobile --ref caddy-component-2.11.6-tencentcloud-0.4.3-review.1 -f publish_review_prerelease=true
55
+ ```
56
+
57
+ Component tags never start with `v`, avoiding the plugin release trigger. The separate write-permission job refuses occupied releases, creates a non-latest draft prerelease without asset clobbering, verifies an authenticated download of every draft asset against prepared bytes, then publishes. Assets include platform-distinct raw executables, manifests, build/module/version/license records, double-build proof, source-commit/run identity and SHA256SUMS. The [verifier](<../scripts/verify-caddy-release.mjs>) checks **every published asset** through GitHub metadata and the actual installer's HTTPS/validated-redirect downloader before emitting a review-only catalog. A failed post-publication check leaves the labelled prerelease public, fails the job and emits no catalog; it does not silently delete or roll back a release. Artifact retention is 14 days; release assets are separate.
58
+
59
+ The public custom-download endpoint returned v2.11.7 when v2.11.6 was requested; dynamic latest downloads are not a trust source. Versioned GitHub URLs can still be replaced by repository owners: exact reviewed byte/hash pins, not URL spelling or a remotely supplied checksum alone, define the content boundary. A fork catalog is only a review candidate; it never automatically populates the [production table](<../src/caddy-component.ts>). Official production installation stays disabled until maintainers publish and review their own distribution.
60
+
61
+ Isolated tests use ephemeral loopback listeners and a private internal CA with `skip_install_trust`; no system trust, production DNS or existing proxy is changed. They **do not establish public DNS-01/ACME issuance or public-route readiness**. Those need a separately authorized dedicated test hostname, least-privilege DNS credentials and actual reachable ingress.
@@ -34,6 +34,28 @@ Android App / 浏览器 → 公网 HTTPS 域名(Caddy 终止 TLS)
34
34
 
35
35
  ## 维护者构建与验证
36
36
 
37
- `scripts/build-caddy-component.mjs` 使用 Go 1.26.6、xcaddy v0.4.7、Caddy v2.11.6 和腾讯云 DNS 模块 v0.4.3,生成二进制、完整大小与 SHA-256、版本/模块记录和嵌入依赖许可证清单。`caddy-component.yml` 仅产生 CI 审查产物,不创建 Release、不修改生产组件表、不自动发布。
37
+ 以下构建和验证工具需在本仓库源码 checkout 中运行;npm 插件包不包含这些维护脚本,也不需要普通用户自行编译 Caddy。
38
38
 
39
- 公开定制下载端点曾在请求 v2.11.6 时返回 v2.11.7,所以不能将动态「最新版」端点当作固定版本资产。正式开放前必须将审核通过的构建放到不可变版本化分发地址,并补齐生产校验数据;目前所有平台都保持禁用。隔离测试使用回环随机端口和不导入系统信任库的测试 CA,验证 TLS、配对认证、API 原始数据与 WebSocket,不等同于真实 DNS-01 或公网路由验收。
39
+ [构建脚本](<../scripts/build-caddy-component.mjs>) 固定 Go 1.26.6、xcaddy v0.4.7、Caddy v2.11.6 和腾讯云 DNS v0.4.3。[输入锁](<../scripts/caddy-component-lock.json>) 固定源码提交和编译依赖版本/校验和。每次构建使用全新的私有编译缓存及模块缓存,执行 Go 校验和、源码来源与保留模块校验;未知依赖、替换模块、编译器或原生设置漂移会在运行生成的 Caddy 前拒绝。
40
+
41
+ 选择精确 Go 编译器(可用 `GO_BINARY`),输出目录必须是全新绝对路径:
42
+
43
+ ```sh
44
+ node scripts/build-caddy-component.mjs --output-dir /absolute/new/first
45
+ node scripts/build-caddy-component.mjs --output-dir /absolute/new/second
46
+ node scripts/compare-caddy-builds.mjs --first /absolute/new/first --second /absolute/new/second --target linux-x64
47
+ ```
48
+
49
+ Windows 使用原生绝对路径和 `--target win32-x64`。可复现指二进制字节、大小、SHA-256 一致,不保证操作系统镜像或所有元数据/许可证文本逐字一致。[工作流](<../.github/workflows/caddy-component.yml>) 在 Windows/Linux x64 分别独立构建两次,审核完整产物,并使用独立 manifest 测试真正安装后的二进制:默认版本/模块检查、目录提升、无重复下载的重启、损坏下载回滚、TLS/配对/API/WSS、持久设备凭据与停止后清理,保留邻近文件及配对数据。其他架构仍未审核。
50
+
51
+ PR 和普通手动运行只产生只读审查产物。只有授权的 `abworks-dev/dsh-mobile` fork 上已有 `caddy-component-2.11.6-tencentcloud-0.4.3-review.N` 标签,经明确手动启用且两个原生任务均通过,才发布 **TEST 预发布版**:
52
+
53
+ ```sh
54
+ gh workflow run caddy-component.yml --repo abworks-dev/dsh-mobile --ref caddy-component-2.11.6-tencentcloud-0.4.3-review.1 -f publish_review_prerelease=true
55
+ ```
56
+
57
+ 组件标签不以 `v` 开头,避免触发插件正式发布。独立写权限任务拒绝已有 Release,创建非 latest 的预发布草稿,不覆盖资产;下载所有草稿资产与准备字节逐一对比后才公开。产物包括区分平台的原始二进制、manifest、编译/模块/版本/许可证证据、双构建证明、源码提交/运行标识和 SHA256SUMS。[发布后验证器](<../scripts/verify-caddy-release.mjs>) 用 GitHub 元数据及安装器实际 HTTPS/受限重定向下载链路复核 **所有公开资产**,成功后才输出仅供审核的目录。公开后验证失败会保留已公开的标记预发布版、使任务失败且不输出校验目录,不擅自删除或回滚 Release。CI 产物保留 14 天,Release 资产另行保存。
58
+
59
+ 公开定制下载端点曾在请求 v2.11.6 时返回 v2.11.7,动态最新版不能成为信任来源。版本化 GitHub URL 仍可被仓库所有者替换;信任边界是审核过的精确大小/哈希,而非 URL 名称或远端自报校验和。fork 的目录只是审核候选,不会自动写入[生产组件表](<../src/caddy-component.ts>);正式安装仍等待维护者发布并审核官方分发。
60
+
61
+ 隔离测试仅用回环随机端口、私有内部 CA 和 `skip_install_trust`,不修改系统信任、生产 DNS 或现有代理。**不等于真实公网 DNS-01/ACME 签发或公网路由验收**;后者需要另行授权专用测试域名、最小权限 DNS 凭据和可达入口。
package/lib/client.js CHANGED
@@ -1150,6 +1150,8 @@ window.__ModuleLoader__.load({
1150
1150
  originCopyBackend: "Copy backend address",
1151
1151
  originBackendCopied: "HTTP backend address copied.",
1152
1152
  originPurge: "Clear proxy settings",
1153
+ originHttpsTitle: "HTTPS remote access",
1154
+ originHttpsMode: "HTTPS handling",
1153
1155
  caddyModeManaged: "Managed Caddy (plugin handles HTTPS and certificates)",
1154
1156
  caddyModeExternal: "I already run my own reverse proxy",
1155
1157
  caddySectionTitle: "Managed Caddy upstream",
@@ -1205,6 +1207,8 @@ window.__ModuleLoader__.load({
1205
1207
  originCopyBackend: "Copia indirizzo backend",
1206
1208
  originBackendCopied: "Indirizzo backend HTTP copiato.",
1207
1209
  originPurge: "Cancella impostazioni proxy",
1210
+ originHttpsTitle: "Accesso remoto HTTPS",
1211
+ originHttpsMode: "Gestione HTTPS",
1208
1212
  caddyModeManaged: "Caddy gestito (il plugin gestisce HTTPS e certificati)",
1209
1213
  caddyModeExternal: "Uso già il mio reverse proxy",
1210
1214
  caddySectionTitle: "Upstream Caddy gestito",
@@ -1260,6 +1264,8 @@ window.__ModuleLoader__.load({
1260
1264
  originCopyBackend: "复制后端地址",
1261
1265
  originBackendCopied: "已复制 HTTP 后端地址。",
1262
1266
  originPurge: "清除代理配置",
1267
+ originHttpsTitle: "HTTPS 远程接入",
1268
+ originHttpsMode: "HTTPS 接入方式",
1263
1269
  caddyModeManaged: "托管 Caddy(插件负责 HTTPS 与证书)",
1264
1270
  caddyModeExternal: "我已自行配置反向代理",
1265
1271
  caddySectionTitle: "托管 Caddy 上游",
@@ -6176,14 +6182,14 @@ window.__ModuleLoader__.load({
6176
6182
  const originSetup = element("section", "dsh-mobile-control__origin-setup");
6177
6183
  originSetup.hidden = true;
6178
6184
  const originSetupTitle = element("h3", "dsh-mobile-control__section-title");
6179
- originSetupTitle.textContent = t("prepareOrigin");
6185
+ originSetupTitle.textContent = t("originHttpsTitle");
6180
6186
  const originHelp = element("p", "dsh-mobile-control__component-note");
6181
6187
  originHelp.id = "dsh-mobile-origin-help";
6182
6188
  originHelp.textContent = t("originHelp");
6183
6189
  const originWarning = element("p", "dsh-mobile-control__origin-warning");
6184
6190
  originWarning.textContent = t("originWarning");
6185
6191
  const originFields = element("div", "dsh-mobile-control__origin-fields");
6186
- const originPublicLabel = element("label", "dsh-mobile-control__field");
6192
+ const originPublicLabel = element("label", "dsh-mobile-control__field dsh-mobile-control__field--full");
6187
6193
  originPublicLabel.textContent = t("originPublicOrigin");
6188
6194
  const originPublic = element("input");
6189
6195
  originPublic.type = "url";
@@ -6204,7 +6210,7 @@ window.__ModuleLoader__.load({
6204
6210
  originPort.max = "65535";
6205
6211
  originPort.step = "1";
6206
6212
  originPort.value = "3444";
6207
- const originCidrsLabel = element("label", "dsh-mobile-control__field");
6213
+ const originCidrsLabel = element("label", "dsh-mobile-control__field dsh-mobile-control__field--full");
6208
6214
  originCidrsLabel.textContent = t("originAllowedCidrs");
6209
6215
  const originCidrs = element("input");
6210
6216
  originCidrs.type = "text";
@@ -6248,14 +6254,15 @@ window.__ModuleLoader__.load({
6248
6254
  originCopyBackend.type = "button";
6249
6255
  originCopyBackend.textContent = t("originCopyBackend");
6250
6256
  originBackend.append(originBackendLabel, originBackendAddress, originCopyBackend);
6251
- originSetup.append(originSetupTitle, originHelp, originWarning, originFields, originFeedback, originFormActions, originBackend);
6252
- const caddyModeRow = element("div", "dsh-mobile-control__origin-fields");
6253
- const caddyModeManagedLabel = element("label", "dsh-mobile-control__field");
6257
+ const caddyModeRow = element("fieldset", "dsh-mobile-control__origin-modes");
6258
+ const caddyModeLegend = element("legend");
6259
+ caddyModeLegend.textContent = t("originHttpsMode");
6260
+ const caddyModeManagedLabel = element("label", "dsh-mobile-control__origin-mode");
6254
6261
  const caddyModeManaged = element("input");
6255
6262
  caddyModeManaged.type = "radio";
6256
6263
  caddyModeManaged.name = "caddy-mode";
6257
6264
  caddyModeManaged.value = "managed";
6258
- const caddyModeExternalLabel = element("label", "dsh-mobile-control__field");
6265
+ const caddyModeExternalLabel = element("label", "dsh-mobile-control__origin-mode");
6259
6266
  const caddyModeExternal = element("input");
6260
6267
  caddyModeExternal.type = "radio";
6261
6268
  caddyModeExternal.name = "caddy-mode";
@@ -6266,10 +6273,11 @@ window.__ModuleLoader__.load({
6266
6273
  caddyExternalText.textContent = t("caddyModeExternal");
6267
6274
  caddyModeManagedLabel.append(caddyModeManaged, caddyManagedText);
6268
6275
  caddyModeExternalLabel.append(caddyModeExternal, caddyExternalText);
6269
- caddyModeRow.append(caddyModeManagedLabel, caddyModeExternalLabel);
6270
- const caddyForm = element("div", "dsh-mobile-control__origin-fields");
6276
+ caddyModeRow.append(caddyModeLegend, caddyModeExternalLabel, caddyModeManagedLabel);
6277
+ const caddyForm = element("div", "dsh-mobile-control__caddy-form");
6271
6278
  caddyForm.hidden = true;
6272
- const caddyDomainLabel = element("label", "dsh-mobile-control__field");
6279
+ const caddyFields = element("div", "dsh-mobile-control__origin-fields");
6280
+ const caddyDomainLabel = element("label", "dsh-mobile-control__field dsh-mobile-control__field--full");
6273
6281
  caddyDomainLabel.textContent = t("caddyDomain");
6274
6282
  const caddyDomain = element("input");
6275
6283
  caddyDomain.type = "url";
@@ -6277,7 +6285,7 @@ window.__ModuleLoader__.load({
6277
6285
  caddyDomain.maxLength = 512;
6278
6286
  caddyDomain.autocomplete = "off";
6279
6287
  caddyDomain.spellcheck = false;
6280
- const caddyProviderLabel = element("label", "dsh-mobile-control__field");
6288
+ const caddyProviderLabel = element("label", "dsh-mobile-control__field dsh-mobile-control__field--full");
6281
6289
  caddyProviderLabel.textContent = t("caddyDnsProvider");
6282
6290
  const caddyProvider = element("select");
6283
6291
  const caddyProviderOption = document.createElement("option");
@@ -6296,7 +6304,7 @@ window.__ModuleLoader__.load({
6296
6304
  caddySecretKey.type = "password";
6297
6305
  caddySecretKey.autocomplete = "off";
6298
6306
  caddySecretKey.spellcheck = false;
6299
- const caddyPortLabel = element("label", "dsh-mobile-control__field");
6307
+ const caddyPortLabel = element("label", "dsh-mobile-control__field dsh-mobile-control__field--full");
6300
6308
  caddyPortLabel.textContent = t("caddyListenPort");
6301
6309
  const caddyPort = element("input");
6302
6310
  caddyPort.type = "number";
@@ -6310,7 +6318,7 @@ window.__ModuleLoader__.load({
6310
6318
  caddySecretIdLabel.append(caddySecretId);
6311
6319
  caddySecretKeyLabel.append(caddySecretKey);
6312
6320
  caddyPortLabel.append(caddyPort);
6313
- caddyForm.append(caddyDomainLabel, caddyProviderLabel, caddySecretIdLabel, caddySecretKeyLabel, caddyPortLabel);
6321
+ caddyFields.append(caddyDomainLabel, caddyProviderLabel, caddySecretIdLabel, caddySecretKeyLabel, caddyPortLabel);
6314
6322
  const caddyInstall = element("button", "dsh-mobile-control__primary");
6315
6323
  caddyInstall.type = "button";
6316
6324
  caddyInstall.textContent = t("caddyInstall");
@@ -6330,8 +6338,10 @@ window.__ModuleLoader__.load({
6330
6338
  caddyFeedback.setAttribute("role", "status");
6331
6339
  caddyFeedback.setAttribute("aria-live", "polite");
6332
6340
  caddyFeedback.hidden = true;
6333
- caddyForm.append(caddyInstallNote, caddyInstall, caddyStatus, caddySave, caddyPurgeButton, caddyFeedback);
6334
- originSetup.append(caddyModeRow, caddyForm);
6341
+ const caddyActions = element("div", "dsh-mobile-control__actions dsh-mobile-control__caddy-actions");
6342
+ caddyActions.append(caddyInstall, caddySave, caddyPurgeButton);
6343
+ caddyForm.append(caddyFields, caddyInstallNote, caddyStatus, caddyActions, caddyFeedback);
6344
+ originSetup.append(originSetupTitle, caddyModeRow, originHelp, originWarning, originFields, originFeedback, originFormActions, caddyForm, originBackend);
6335
6345
  const tailscaleInfo = element("details", "dsh-mobile-control__details");
6336
6346
  const tailscaleInfoSummary = element("summary");
6337
6347
  tailscaleInfoSummary.textContent = t("tailscaleHelp");
@@ -10036,7 +10046,11 @@ window.__ModuleLoader__.load({
10036
10046
  .dsh-mobile-control__manage-row{display:flex;justify-content:space-between;gap:8px;margin-top:10px}.dsh-mobile-control__manage{flex:1 1 0;min-width:0;min-height:36px;padding:6px 8px;border:1px solid var(--dsw-alias-border-l3,#cfd5dd);border-radius:10px;background:transparent;color:inherit;font:12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__devices{margin-top:10px;border:1px solid var(--dsw-alias-border-l2,#e1e5eb);border-radius:10px;padding:8px;max-height:220px;overflow-y:auto}.dsh-mobile-control__device-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px;margin:0}.dsh-mobile-control__device{display:flex;align-items:center;gap:8px;padding:6px 2px}.dsh-mobile-control__device + .dsh-mobile-control__device{border-top:1px solid var(--dsw-alias-border-l2,#e1e5eb)}.dsh-mobile-control__device-label{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.dsh-mobile-control__device-meta{flex:none;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;white-space:nowrap}.dsh-mobile-control__device-revoke{flex:none;min-height:36px;padding:4px 8px;border:1px solid var(--dsw-alias-state-error-primary,#dc2626);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary,#dc2626);font:12px/1.2 system-ui;cursor:pointer}.dsh-mobile-control__ws-paths{margin:10px 0 0;padding:12px;border:1px solid var(--dsw-alias-border-l2,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff)}.dsh-mobile-control__ws-paths-list{margin:0 0 8px;padding:0;list-style:none}.dsh-mobile-control__ws-paths-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px}.dsh-mobile-control__ws-paths-item{display:flex;align-items:center;gap:8px;padding:6px 0}.dsh-mobile-control__ws-paths-item + .dsh-mobile-control__ws-paths-item{border-top:1px solid var(--dsw-alias-border-l2,#e1e5eb)}.dsh-mobile-control__ws-paths-item code{flex:1 1 0;min-width:0;overflow:hidden;font:11px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__ws-paths-remove{flex:none;min-height:36px;padding:4px 8px;border:1px solid var(--dsw-alias-border-l3,#cfd5dd);border-radius:8px;background:transparent;color:inherit;font:12px/1.2 system-ui;cursor:pointer}.dsh-mobile-control__trigger,.dsh-mobile-control__diagnostic-entry{position:relative}.dsh-mobile-control__ws-dot{position:absolute;top:2px;right:2px;z-index:1;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff;font:650 11px/16px system-ui;text-align:center;cursor:pointer}.dsh-mobile-control__ws-dot::after{content:'';position:absolute;inset:-5px}.dsh-mobile-control__ws-sr-status{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.dsh-mobile-control__ws-paths-row{display:flex;gap:8px}.dsh-mobile-control__ws-paths-row .dsh-mobile-control__primary{width:auto;flex:none;padding:9px 14px;border-radius:10px}.dsh-mobile-control__ws-paths-group{padding:6px 0}.dsh-mobile-control__ws-paths-group + .dsh-mobile-control__ws-paths-group{border-top:1px solid var(--dsw-alias-border-l2,#e1e5eb)}.dsh-mobile-control__ws-paths-group-head{display:flex;align-items:center;gap:8px}.dsh-mobile-control__ws-count{flex:none;padding:1px 7px;border-radius:999px;background:var(--dsw-alias-state-business-tertiary,#e8f0ff);color:var(--dsw-alias-label-primary,#1d4ed8);font:650 11px/1.6 system-ui}.dsh-mobile-control__ws-paths-item.is-child{padding-left:12px}.dsh-mobile-control__ws-paths-group-head .dsh-mobile-control__primary,.dsh-mobile-control__ws-paths-item .dsh-mobile-control__primary{width:auto;flex:none;min-height:36px;padding:6px 12px;border-radius:10px}.dsh-mobile-control__ws-paths-row input{flex:1 1 0;min-width:0;box-sizing:border-box;min-height:44px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l3,#cfd5dd);border-radius:10px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);font:16px/1.4 system-ui}.dsh-mobile-control__ws-paths-row button{flex:none}.dsh-mobile-control__ws-paths-detected-title{margin:0 0 2px;font:600 12px/1.4 system-ui}.dsh-mobile-control__ws-paths-advanced{margin-top:8px}.dsh-mobile-control__ws-paths-advanced summary{cursor:pointer;color:var(--dsw-alias-label-secondary,#606873);font:12px/1.4 system-ui;user-select:none}.dsh-mobile-control__ws-paths-advanced summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,currentColor);outline-offset:2px;border-radius:4px}.dsh-mobile-control__ws-paths-advanced[open] summary{margin-bottom:6px}.dsh-mobile-control__ws-paths-advanced .dsh-mobile-control__status{margin:6px 0 0}
10037
10047
  @media (max-width:359px){.dsh-mobile-control__provider{min-height:68px}}@media (prefers-reduced-motion:reduce){.dsh-mobile-control__provider,.dsh-mobile-control__cpolar-connect{transition:none}.dsh-mobile-control__diagnostic-summary.is-running .dsh-mobile-control__diagnostic-summary-icon::before,.dsh-mobile-control__diagnostic-checks{animation:none}}
10038
10048
 
10039
- .dsh-mobile-control__origin-setup{margin:0;padding:12px;border:1px solid var(--dsw-alias-border-l2,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff)}.dsh-mobile-control__origin-setup[hidden],.dsh-mobile-control__origin-backend[hidden],.dsh-mobile-control__origin-feedback[hidden]{display:none}.dsh-mobile-control__origin-fields{display:grid;grid-template-columns:minmax(0,1fr) 110px;gap:12px}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field{font-size:12px}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field:nth-child(1),.dsh-mobile-control__origin-fields>.dsh-mobile-control__field:nth-child(4){grid-column:1/-1}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field:nth-child(2){grid-column:1}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field:nth-child(3){grid-column:2}.dsh-mobile-control__origin-warning{margin:12px 0;padding:10px 12px;border-left:3px solid var(--dsw-alias-state-warn-primary,#a56810);border-radius:4px;background:var(--dsw-alias-bg-layer-1,#f3f5f8);color:var(--dsw-alias-label-primary,#384152);font-size:12px;line-height:1.6}.dsh-mobile-control__origin-feedback{font-size:12px;line-height:1.6;overflow-wrap:anywhere}.dsh-mobile-control__origin-feedback.is-error{color:var(--dsw-alias-state-error-primary,#bc3030)}.dsh-mobile-control__origin-fields input[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary,#bc3030)}.dsh-mobile-control__origin-backend{display:flex;min-width:0;flex-direction:column;align-items:stretch;gap:8px;margin-top:12px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#dbe1e8)}.dsh-mobile-control__origin-backend button{align-self:flex-start;min-height:44px}.dsh-mobile-control__self-hosted-body .is-origin{margin-top:8px}
10049
+ .dsh-mobile-control__origin-setup{margin:0;padding:12px;border:1px solid var(--dsw-alias-border-l2,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff)}.dsh-mobile-control__origin-setup[hidden],.dsh-mobile-control__origin-setup [hidden]{display:none}
10050
+ /* Mode choices are not text fields; preserve native radio sizing and keyboard behavior. */
10051
+ .dsh-mobile-control__origin-modes{min-width:0;margin:0 0 14px;padding:0;border:0}.dsh-mobile-control__origin-modes legend{margin:0 0 8px;padding:0;color:var(--dsw-alias-label-secondary,#606873);font:600 12px/1.4 system-ui}.dsh-mobile-control__origin-mode{display:flex;box-sizing:border-box;min-height:44px;align-items:center;gap:10px;padding:10px;border:1px solid var(--dsw-alias-border-l2,#dbe1e8);border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f3f5f8);font:12px/1.5 system-ui;cursor:pointer}.dsh-mobile-control__origin-mode+.dsh-mobile-control__origin-mode{margin-top:8px}.dsh-mobile-control__origin-mode:has(input:checked){border-color:var(--dsw-alias-label-primary-bluish,#2563eb)}.dsh-mobile-control__origin-mode:focus-within{outline:2px solid var(--dsw-alias-state-business-primary,#2563eb);outline-offset:2px}.dsh-mobile-control__origin-mode:has(input:disabled){cursor:wait;opacity:.55}.dsh-mobile-control__origin-mode input[type=radio]{flex:0 0 18px;box-sizing:border-box;width:18px;height:18px;min-height:18px;margin:0;padding:0;accent-color:var(--dsw-alias-label-primary-bluish,#2563eb)}.dsh-mobile-control__origin-mode span{min-width:0;overflow-wrap:anywhere}
10052
+ /* Base the columns on the card width, not the desktop viewport behind the popup. */
10053
+ .dsh-mobile-control__origin-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,140px),1fr));gap:12px}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field{min-width:0;grid-column:auto;font-size:12px}.dsh-mobile-control__origin-fields>.dsh-mobile-control__field--full{grid-column:1/-1}.dsh-mobile-control__origin-fields select{box-sizing:border-box;width:100%;min-height:44px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l3,#cfd5dd);border-radius:10px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);font:16px/1.4 system-ui}.dsh-mobile-control__origin-fields select:disabled{cursor:not-allowed;opacity:.55}.dsh-mobile-control__caddy-form{display:grid;gap:12px}.dsh-mobile-control__caddy-form>.dsh-mobile-control__component-note,.dsh-mobile-control__caddy-form>.dsh-mobile-control__component-status,.dsh-mobile-control__caddy-form>.dsh-mobile-control__origin-feedback{margin:0;overflow-wrap:anywhere}.dsh-mobile-control__origin-setup .dsh-mobile-control__actions.dsh-mobile-control__caddy-actions{grid-template-columns:minmax(0,1fr);margin:0}.dsh-mobile-control__caddy-actions button{box-sizing:border-box;min-width:0;min-height:44px;padding:10px 12px;border-radius:10px;font:600 12px/1.4 system-ui;cursor:pointer}.dsh-mobile-control__origin-warning{margin:12px 0;padding:10px 12px;border-left:3px solid var(--dsw-alias-state-warn-primary,#a56810);border-radius:4px;background:var(--dsw-alias-bg-layer-1,#f3f5f8);color:var(--dsw-alias-label-primary,#384152);font-size:12px;line-height:1.6}.dsh-mobile-control__origin-feedback{font-size:12px;line-height:1.6;overflow-wrap:anywhere}.dsh-mobile-control__origin-feedback.is-error{color:var(--dsw-alias-state-error-primary,#bc3030)}.dsh-mobile-control__origin-fields input[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary,#bc3030)}.dsh-mobile-control__origin-backend{display:flex;min-width:0;flex-direction:column;align-items:stretch;gap:8px;margin-top:12px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#dbe1e8)}.dsh-mobile-control__origin-backend button{align-self:flex-start;min-height:44px}.dsh-mobile-control__self-hosted-body .is-origin{margin-top:8px}
10040
10054
  `;
10041
10055
  /** Mount the desktop control or mobile feature enhancements. */
10042
10056
  function apply(ctx) {