mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-06 08:24:17 +00:00
docs(design): publish terminal command address design for #72
grill-with-docs 会话产物:交互设计与测试边界定稿,spec 已发布为 issue #72;CONTEXT.md 增加 Terminal command address 词条。
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
- **Listener mode**: The user-facing choice that determines which address families the local proxy listeners accept: this Mac only (IPv4 loopback), all IPv4 interfaces, all IPv4 and IPv6 interfaces, or all IPv6 interfaces only. One mode applies to both the local SOCKS and HTTP proxy inbounds. _Avoid_: Listen scope.
|
||||
- **HTTP proxy environment command**: An HTTP-only terminal command that sets lowercase `http_proxy` and `https_proxy` for this Mac's local HTTP proxy inbound. It always targets a loopback address for the selected listener mode.
|
||||
- **Terminal proxy environment commands**: Shell-specific commands for zsh/bash and fish that set lowercase `http_proxy` and `https_proxy` through the local HTTP inbound, `all_proxy` through the local SOCKS inbound, and `no_proxy` for `localhost`, `127.0.0.1`, `::1`, and `.local` hostnames. The proxy endpoints use loopback addresses selected by listener mode, and the commands affect child processes that honor these variables.
|
||||
- **Terminal command address**: The user-selected IP address used by both HTTP and SOCKS endpoints in copied terminal proxy environment commands. It defaults to a compatible loopback address; non-local listener modes also offer addresses of enabled Wi-Fi and Ethernet interfaces in the accepted address families, and the selection lasts only for the current app session without changing listener or system-proxy settings.
|
||||
- **Proxy runtime**: The per-user background host process, independent of the GUI's lifetime, that runs the external tunnel service and loads the optional generated ACL sidecar.
|
||||
- **Legacy configuration**: The server list and preferences persisted by the frozen implementation in `Legacy/`.
|
||||
- **Legacy import**: The user-confirmed, read-only translation of a Legacy configuration's server records into a separate manual group in 2.0. It migrates no preferences, activates no target, and neither starts proxying nor alters the Legacy source.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
## Problem Statement
|
||||
|
||||
首页“复制代理环境变量设置命令”目前只能生成指向回环地址的命令。用户已经选择允许其他设备访问的监听方式时,仍需手动修改命令中的 HTTP、HTTPS 和 SOCKS 地址,也无法从首页辨认本机可用的 Wi-Fi 或 Ethernet 地址。
|
||||
|
||||
## Solution
|
||||
|
||||
在非“仅本机”监听方式下,为首页命令卡片增加一个单选 IP 下拉框,默认选中兼容的回环地址。候选仅来自 loopback 和当前启用的 Wi-Fi、Ethernet 接口,并按监听地址族过滤。候选显示为 `{IP} - {name}`,名称采用系统接口本地化名称,缺失时使用 BSD 名称。两种 shell 的所有代理端点共用该选择,选择失效时自动回退到回环地址。
|
||||
|
||||
## User Stories
|
||||
|
||||
1. 作为应用用户,我希望非本机监听时能在首页选择命令地址,以便直接复制包含所需 IP 的命令。
|
||||
2. 作为应用用户,我希望仅本机监听时隐藏地址下拉框,以便只看到适用于当前监听方式的操作。
|
||||
3. 作为应用用户,我希望默认使用回环地址,以便继续使用现有本机终端操作习惯。
|
||||
4. 作为 IPv4 用户,我希望候选仅包含 IPv4 地址,以便避免复制监听器不接受的端点。
|
||||
5. 作为双栈用户,我希望同时选择 IPv4 和 IPv6 地址,以便适应目标设备使用的地址族。
|
||||
6. 作为双栈用户,我希望两个回环地址都可选且默认使用 127.0.0.1,以便保留熟悉的默认值。
|
||||
7. 作为仅 IPv6 用户,我希望默认地址为 ::1 且候选只有 IPv6,以便得到兼容的命令。
|
||||
8. 作为 Wi-Fi 用户,我希望候选包含当前启用 Wi-Fi 接口的单播地址,以便通过无线网络使用代理。
|
||||
9. 作为 Ethernet 用户,我希望候选包含当前启用 Ethernet 接口的单播地址,以便通过有线网络使用代理。
|
||||
10. 作为应用用户,我希望排除 VPN 和其他接口类型,以便候选只包含明确支持的三类接口。
|
||||
11. 作为应用用户,我希望每项同时显示 IP 和接口名称,以便辨认地址属于哪个网络接口。
|
||||
12. 作为应用用户,我希望接口名称采用系统本地化名称,以便与系统中的接口称呼对应。
|
||||
13. 作为应用用户,我希望名称缺失时显示 BSD 接口名,以便仍能辨认候选。
|
||||
14. 作为应用用户,我希望回环项置顶、其他项稳定排序并合并同一接口的重复地址,以便快速查找候选。
|
||||
15. 作为应用用户,我希望不出现 IPv6 链路本地地址和通配绑定地址,以便避免复制需要额外接口作用域或不能用作目标的地址。
|
||||
16. 作为 zsh/bash 用户,我希望复制的 HTTP、HTTPS 和 SOCKS 端点都使用选中地址,以便一次设置全部代理变量。
|
||||
17. 作为 fish 用户,我希望复制命令使用同一地址并保持 fish 语法,以便直接在 fish 中执行。
|
||||
18. 作为 IPv6 用户,我希望生成的 URL 正确包含地址方括号和端口,以便应用能解析代理端点。
|
||||
19. 作为应用用户,我希望选择命令地址不改变监听方式或系统代理,以便该操作仅用于生成命令。
|
||||
20. 作为应用用户,我希望离开首页再返回时保留本次选择,以便减少重复操作。
|
||||
21. 作为应用用户,我希望应用重启后恢复默认回环地址,以便不沿用先前网络环境的选择。
|
||||
22. 作为切换网络的用户,我希望候选随网络变化刷新,以便选择当前接口地址。
|
||||
23. 作为切换监听方式的用户,我希望不兼容的选择自动回退,以便界面始终符合已保存的监听配置。
|
||||
24. 作为应用用户,我希望复制前重新检查地址并在失效时复制回环命令,以便不复制已消失的地址。
|
||||
25. 作为应用用户,我希望无法枚举接口时仍能选择回环并复制,以便基础本机功能保持可用。
|
||||
26. 作为应用用户,我希望代理未运行时仍能复制命令,以便预先准备终端配置。
|
||||
27. 作为应用用户,我希望复制按钮的提示命令与实际剪贴板内容采用相同选择,以便理解即将复制的内容。
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
- 扩展 ProxyControlWorkflow 的 UI-facing 投影与用户操作:提供候选地址、选中地址、选择器可见性,以及基于同一选择生成的两种 shell 命令。呈现层负责下拉框和现有剪贴板副作用,不自行访问底层控制器或拼接命令。
|
||||
- 应用会话持有选择,生命周期长于首页视图;不写入持久化设置。地址身份包含 BSD 接口身份与规范化 IP,不以本地化名称作为身份。
|
||||
- 一个下拉框放在两个复制按钮上方,仅“仅本机”监听方式隐藏。监听方式与端口取已保存的设置;命令选择不改变代理运行状态、监听设置或系统代理。
|
||||
- 默认地址前三种监听方式为 127.0.0.1,仅所有 IPv6 接口为 ::1。双栈提供两个回环地址。IPv4-only、双栈和 IPv6-only 分别过滤对应地址族。
|
||||
- 候选仅包含 loopback,以及当前启用 Wi-Fi、Ethernet 接口的单播地址。排除 VPN、其他虚拟接口和其他接口类型,不以接口名前缀或通用链路类型代替严格类型判断。
|
||||
- 系统适配器以 SCNetworkInterfaceGetInterfaceType 的 IEEE80211、Ethernet 类型识别非回环接口,以 IFF_LOOPBACK 识别回环。无法确认属于允许类型的非回环接口排除。
|
||||
- 本地化接口名称使用 SCNetworkInterfaceGetLocalizedDisplayName,通过 BSD 接口名关联地址事实。缺失时回退 BSD 名;回环默认显示 lo0。名称缺失不会放宽类型过滤。
|
||||
- 标签统一采用 `{IP} - {name}`。回环项置顶,双栈时 IPv4 回环先于 IPv6 回环;其他项按接口名称排序,同一接口先 IPv4 后 IPv6,然后按地址稳定排序。同一接口重复 IP 合并,不同接口同 IP 保留接口身份。
|
||||
- 不提供手动地址输入,排除 IPv6 链路本地地址和通配地址。允许已通过接口类型过滤的 IPv4 链路本地单播地址。列出地址不代表已验证其他设备到该端点的连通性。
|
||||
- 进入首页、网络变化以及复制前刷新;监听方式变化时重新过滤。仍有效的选择保留,否则回退到当前监听方式的默认回环地址。复制前发现失效时,本次复制采用回退后的命令,并更新界面选择。
|
||||
- 枚举失败时仅提供兼容回环候选。即使代理未运行也允许复制。提示命令与实际复制内容使用相同的地址选择和生成逻辑;复制前刷新产生的变化同步至提示投影。
|
||||
- HTTP、HTTPS 使用已保存的 HTTP 端口,SOCKS 使用已保存的 SOCKS 端口。保持现有变量集合、小写变量名、shell 转义、socks5 协议和 no_proxy 内容;IPv6 URL 使用方括号。
|
||||
- 复用现有运行时适配缝提供已保存监听事实。仅新增一个工作流层可注入的本机接口事实来源,统一提供接口地址、类型、名称及变化通知;系统 API 查询细节封装于生产适配器,不再为每个底层 API 增加独立 mock 协议。
|
||||
- 无配置迁移或持久化 schema 变更。同步修订现有四种监听方式 ADR 和领域文档中“终端命令始终面向回环”的旧约定;健康检查、系统代理目标继续依据监听方式,不受复制地址影响。
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
- 主测试入口为 ProxyControlWorkflow 的可观察投影和用户操作。复用现有 FakeProxyRuntime、确定性变化通知与工作流 contract 测试方式,新增一个可编程接口事实替身。替身提供原始接口事实,让生产策略实际完成过滤、排序、名称回退与地址选择;不直接注入已经过滤好的候选。
|
||||
- 好的测试断言用户可见候选、选中值、选择器可见性和最终 shell 命令,不断言底层系统 API 调用顺序、内部容器或私有辅助方法。
|
||||
- 用四种监听方式验证地址族过滤、默认值、双栈回环项及监听方式切换后的回退。提供 Wi-Fi、Ethernet、loopback、VPN、其他虚拟接口及未知类型事实,验证严格白名单。
|
||||
- 验证本地化名称、名称缺失的 BSD 回退、同一接口重复 IP 合并、不同接口同 IP 保留、稳定排序、IPv6 链路本地排除与 IPv4 链路本地允许。
|
||||
- 通过选址后执行两种 shell 的命令准备操作,断言 HTTP、HTTPS、SOCKS 共用地址、端口来自已保存值、IPv6 URL 正确且 no_proxy 保持不变。
|
||||
- 以同一会话离开再进入首页验证保留;以新会话验证默认值。通过可编程网络变化和复制前刷新覆盖地址消失、地址族不兼容及枚举失败的回环回退。
|
||||
- 复用已有运行时命令记录,断言选择和刷新不会启动代理、修改监听设置或修改系统代理;代理未运行时命令仍可准备。
|
||||
- 延续现有 workflow 不直接访问剪贴板的边界。工作流测试验证“刷新后准备的复制内容”,以及提示命令与命令准备结果在刷新后的投影一致性。不为纯视图布局引入额外领域测试缝,不进行视觉验收。
|
||||
- 在真实 macOS 上通过非视觉验证核实系统接口名称与类型映射、Wi-Fi/Ethernet 候选以及 IPv6 地址事实。替身测试证明策略行为,真实主机的非视觉验证证明系统适配器整合;候选枚举本身不证明跨设备网络可达。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 运行时监听绑定修改、系统代理地址修改或自动启用代理。
|
||||
- VPN、其他虚拟接口和其他接口类型的候选支持。
|
||||
- IPv6 链路本地地址作用域、手动地址输入、域名或外部公网 IP 发现。
|
||||
- 跨应用重启记忆选择、设置迁移、恢复旧的手动 advertised address 配置。
|
||||
- 网络可达性检测、认证机制、防火墙配置和复制命令后在目标终端的执行。
|
||||
- 额外 shell、代理协议或环境变量语义变更。
|
||||
- 视觉验收、截图检查与人工界面布局验收。
|
||||
|
||||
## Further Notes
|
||||
|
||||
- 设计来自 2026-10-01 的 grill-with-docs 会话。用户已确定交互与边界,最终将候选限制为 Wi-Fi、Ethernet、loopback,覆盖第一轮包含 VPN/虚拟接口的建议。
|
||||
- 系统接口名称 API 可返回空值;loopback 无对应的 SystemConfiguration 类型常量,必须单独识别。严格类型白名单与名称回退分别处理。
|
||||
- 用户已明确不做视觉验收。测试边界采用工作流外部行为测试和一个接口事实注入缝,系统适配器采用非视觉验证。
|
||||
- 作为单一 feature spec issue 发布,标记 ready-for-agent,不创建拆分实施票据。
|
||||
@@ -0,0 +1,45 @@
|
||||
# 首页代理环境变量命令地址选择
|
||||
|
||||
日期:2026-10-01。
|
||||
状态:交互设计与测试边界已确定,spec 已发布为 [Issue #72](https://github.com/qiuyuzhou/ShadowsocksX-NG/issues/72),标记 ready-for-agent;尚未实现。
|
||||
|
||||
## 功能范围
|
||||
|
||||
首页“复制代理环境变量设置命令”卡片在非“仅本机”监听方式下,在 zsh / bash 和 fish 两个复制按钮上方显示一个单选下拉框。仅本机模式隐藏下拉框并使用 IPv4 回环地址。
|
||||
|
||||
所选地址同时用于两种 shell 命令的 HTTP、HTTPS 和 SOCKS 端点。端口取已保存的监听设置,现有 shell 语法、变量集合和 no_proxy 内容保持不变。IPv6 在 URL 中使用方括号。选择只改变生成的命令,不改变监听配置或系统代理。
|
||||
|
||||
## 候选地址
|
||||
|
||||
仅包含 loopback,以及本机当前启用的 Wi-Fi、Ethernet 接口的单播 IP。VPN、其他虚拟接口和其他接口类型排除;不能仅依据 BSD 接口前缀或通用 Ethernet 链路类型来接受虚拟接口。无法确认是允许类型的非回环接口不纳入列表。
|
||||
|
||||
不提供手动输入,不提供通配绑定地址,IPv6 链路本地地址排除。IPv4 链路本地地址属于允许接口的单播地址时可以列出。候选列表不表示网络连通性已验证。
|
||||
|
||||
| 已保存的监听方式 | 地址族 | 默认地址 |
|
||||
| --- | --- | --- |
|
||||
| 仅本机 | IPv4 回环;隐藏下拉框 | 127.0.0.1 |
|
||||
| 所有 IPv4 接口 | IPv4 | 127.0.0.1 |
|
||||
| 所有 IPv4 与 IPv6 接口 | IPv4、IPv6,包含两个回环地址 | 127.0.0.1 |
|
||||
| 仅所有 IPv6 接口 | IPv6 | ::1 |
|
||||
|
||||
每项显示 `{IP} - {name}`。接口名称优先取 `SCNetworkInterfaceGetLocalizedDisplayName(interface)`;名称缺失或无法映射到 SystemConfiguration 接口时,回退到 BSD 接口名,但不会因此放宽接口类型过滤。回环项回退名称为 lo0。
|
||||
|
||||
回环项置顶,双栈时 127.0.0.1 在 ::1 前。其余按接口名称排序,同一接口先 IPv4 后 IPv6,再按地址稳定排序。同一接口的重复 IP 合并;不同接口即使 IP 相同也保留接口身份。
|
||||
|
||||
## 选择生命周期与刷新
|
||||
|
||||
选择在本次应用运行期间保留,包括离开首页后返回;不跨应用重启持久化。进入首页、网络变化以及复制前刷新候选地址。监听方式变化时立即重新过滤候选。
|
||||
|
||||
所选地址消失,或监听方式不再支持该地址时,回退到对应监听方式的默认回环地址。复制前刷新发现地址失效时,本次复制使用回退后的地址,界面与命令一致。
|
||||
|
||||
地址枚举失败时仅保留兼容的回环项,继续允许复制。代理未运行时也允许复制;生成命令不承诺端点当前可连接。
|
||||
|
||||
## 实现与验证边界
|
||||
|
||||
地址枚举、接口名称及类型识别通过可注入的事实来源提供,UI 不自行访问底层控制器拼接命令。应用会话状态持有选中地址的接口身份和地址值,不使用界面显示名称作为身份。
|
||||
|
||||
需要验证四种监听方式的候选过滤和默认地址、Wi-Fi/Ethernet/loopback 类型过滤、VPN/虚拟接口排除、名称回退、IPv6 URL、两种 shell 的共享选中地址、离开首页后保留、应用重启后重置、网络变化和复制前失效回退,以及枚举失败时的回环退化行为。用户明确不做视觉验收;系统接口映射通过非视觉验证核实。
|
||||
|
||||
## 现有决策调整
|
||||
|
||||
此设计扩展 ADR-0015 中“命令始终面向本机回环”的旧约定。实现时同步更新该 ADR 的命令地址段落以及 CONTEXT.md 中对应定义和约束;健康检查和系统代理目标仍由监听方式确定,不受命令地址选择影响。此项是可逆的首页交互调整,不新增 ADR。
|
||||
Reference in New Issue
Block a user