Client 是用户与 NSIO Next 交互的产品层,包含桌面/移动 NS App、ns CLI、租户管理控制台和成员应用门户。Client 负责收集意图、展示事实和引导恢复,不拥有网络授权或路由算法。
每项能力的用户入口、状态组合和角色预演见产品能力目录与实现闭环;AccessRequest、角色、Capability、Share、Posture 等管理流程以控制资源生命周期为权威,逐功能实现证据以功能闭环总账为权威。Client 必须消费这些结构化事实,不能复制下层求值或状态机。
| 表面 | 目标用户 | 主要任务 |
|---|---|---|
| NS App | 日常员工/个人 | 登录、连接、节点/服务访问、发布、出口、诊断 |
ns CLI | 开发者/运维/无头 Linux | enroll、up/down、status、service、route、doctor |
| Member Portal | 无 App 或需要 Web 目录的成员 | 查看并打开已授权应用、管理自己身份安全 |
| Tenant Console | Owner/Admin/Security/Network/Edge Admin | 成员、设备、Network、Access、Capabilities、Public Applications、Route、Gateway、审计 |
| Platform Admin | NSIO 运营 | 部署、计费、PoP、支持;不越权进入租户数据 |
ns runtime;版本不兼容时只提供诊断和签名升级,不启动第二个引擎。首页只回答:是否连接、当前连接范围/质量、可以访问什么。
纵向结构:
首页不放独立 Gateway 功能卡、不展示装饰性指标、不把读取失败画成空列表。
列表显示节点名称、owner/assigned principal(有权限时)、系统、在线、路径和可用动作。详情显示 Node FQDN/IP、最近连接、被授权端口/协议摘要和诊断。点击 SSH/RDP/Ping 是明确命令,不把 Node 当 Service 自动打开浏览器。
紧凑列表保持统一高度,标题行可带清晰类型标识:Service、Gateway Egress、内部/公开。域名过长中间省略并可复制完整值。筛选使用单选菜单或 segmented control,当前值始终显示;协议与服务类型是两个独立筛选维度。
详情/弹层显示协议、域名、状态、标签和主动作。成员看不到 backend、完整策略或无权资源。
发布向导步骤:选择后端类型 → 输入地址/端口或发现本机服务 → 健康测试 → 名称/协议 → 可见性和本地授权上限 → 影响预览 → 提交。
结果区分本地保存、等待 NSD、等待管理员、在线、后端失败和本地拒绝。取消远端审批不删除本地草稿;停止发布要求选择仅停 Endpoint 或删除 Service 声明。
分组:Account/Profile、Connection、Internet Exit、DNS/Proxy、Service Host、Privacy/Diagnostics、Advanced。高级平台选项不在普通流程中展开;存在 CLI 非默认配置时显示只读摘要,写入前必须 read-modify-write,读取不完整则禁止覆盖。
Account 同时提供个人数据导出、登录方式/会话和账号注销;Organization 删除只在租户控制台提供并展示 ownership、Billing、Device、Service、审计和 Legal Hold 影响。Billing、发票、SLA、状态页和支持入口按角色显示,不能让普通成员看到财务资料。
浏览器返回只建立用户会话;Device 注册仍需 Device Key + Enrollment Grant。登录成功但审批未完成时显示“账号已登录,设备等待批准”,不能显示“已连接”。
取消后保留账号会话,撤销本次 Enrollment Request,清理对应 staging key。重启 App 可凭 request ID 和 staging key 恢复。
点击连接的状态机:
| 阶段 | UI | 取消行为 |
|---|---|---|
| validating local state | 正在检查设备配置 | 立即取消 |
| authenticating control | 正在连接控制服务 | 保留 Enrollment |
| receiving projection | 私网服务准备中 | 停止 runtime |
| installing network | 正在启用安全网络 | 执行平台 rollback |
| establishing paths | 正在建立加密连接 | 可进入 connected degraded |
| ready | 已连接 | 断开 |
App 使用 operation stream,不用假进度条。标准连接建立但出口候选尚未到达时,应显示“已连接,私网服务可用;正在获取互联网出口”,不隐藏真实连接。
出口是连接设置,不是首页模块。设置中一个“互联网出口”开关表达用户意图;打开会将数据面要求设为 TUN/VPN。未选择出口也允许点击连接:先建立标准连接、获取授权候选,再弹出选择。
候选弹窗:单选列表,显示 gateway name(缺失回退 ID)、范围和 availability;失效当前项不预选。提交直接调用 runtime configure,由权威校验,不能先本地比对制造 TOCTOU。
| 情况 | 行为 |
|---|---|
| 首次、多个候选 | 选择后配置并按需要重启 Exit |
| 首次、一个候选 | 仍明确确认,不静默选择企业出口 |
| 无授权 | 关闭用户开关、恢复原数据面并明确告知 |
| candidates not ready/read failed | 保持开关与标准连接,重试 |
| 已运行后 selection/projection 失效 | 保持 capture 安全状态,给“重新选择”和“关闭出口” |
| 更换 Gateway | 设置中点击当前网关;先取得新选择,成功写入后重启 |
| 关闭出口 | 不删除保存选择;以标准连接重启 |
流量文案必须依据 capture 与 scope:ready 才说“出口范围内流量已阻断/已转发”;inactive/not_ready 只说“未经过公司出口”。external_unmanaged 明确显示“IPv6 由其他 VPN 管理,未经过公司出口”。
登录后只有一个空间时直接进入;多个空间显示名称与角色。当前 Profile 持久化为用户偏好,但 daemon 仍验证其存在和权限。
切换前 App 请求影响预览:将断开的 Node/Service、DNS/route 冲突、正在运行的 Exit 和未保存发布草稿。用户确认后 runtime 完成停止、切 Profile、启动;失败时恢复原 Profile 或进入明确 blocked,不形成 UI 与 runtime 分叉。
多 Organization/Profile 是同一 OS principal 的产品能力,不等于多个 OS 用户可以共用一个系统级隧道。桌面首版遵守发行生命周期的 single-active-OS-user 规则:
| 场景 | Client 行为 |
|---|---|
| 当前 OS 用户是 runtime owner | 正常显示账号、Profile、目录、连接与设置 |
| 当前 OS 用户不是 owner | 只显示“NSIO 正由本机另一用户使用”;不显示姓名、账号、Organization、Network、连接范围或服务数量 |
| owner 锁屏、无人切换 | 保持既有连接;UI 解锁后继续读取权威状态 |
| 机器重启、owner 尚未登录 | daemon 可以运行,但 App 状态为 owner_inactive 且没有数据面;不把后台服务自启显示为已连接 |
| owner 重启后登录 | 默认显示未连接;用户可启用“登录后自动连接”,企业策略也只能在本地 owner 验证完成后触发 |
| 快速切换到另一 OS 用户 | daemon 先撤 user-owned 网络投影;新用户 App 显示占用状态,不能复用原隧道 |
| 原 owner 返回 | 显示“网络已因本机用户切换暂停”,提供明确重连 |
| owner 显式释放 | 清除 local owner claim 前先断开并完成 journal;新用户随后可登录/enroll |
| OS 管理员强制 reset | 显示将清除本地 identity、可能留下远端 Device 待撤销;不能称为接管 |
| managed-device 服务器/专机 | 显示受组织管理;交互用户不能切换为自己的 Profile |
非 owner 不显示 Connect、Disconnect、Profile switch、Publish、Exit、诊断导出或完整卸载动作。可以显示版本、更新和“联系本机管理员/等待另一用户退出”的恢复说明。客户端不能通过缓存重现 owner 的最后目录或名称。
| 场景 | 命令体验 |
|---|---|
| 有浏览器电脑 | ns login 打开浏览器并 loopback callback |
| 无头、人操作 | ns login --device-code 显示 URL、短码、指纹和校验短语 |
| 无人值守 | ns enroll --key-env NS_ENROLLMENT_KEY,key 不进 argv/history |
| 连接 | ns up [--network name],多目标时列候选并明确退出 |
| 状态 | ns status [--json],JSON 使用稳定 schema |
| 发布 | ns service add/list/disable/remove |
| 诊断 | ns doctor、ns diagnostics export |
CLI 文本适合人读,--json 只输出结构化 payload 到 stdout,日志到 stderr。非交互环境不弹浏览器、不自动选择第一个 Network、不把暂时不可用返回成功。
租户控制台导航:Overview、Members、Devices、Networks、Services、Access、Capabilities、Public Applications、Routes、Gateways、Roles、Audit、Settings/Billing。角色控制导航和 API,隐藏菜单不等于授权。
控制台直接渲染服务端权威对象及 allowed actions:Access 分别展示 AccessGrant 与 AccessRequest/TemporaryAccessGrant;Capabilities 展示 Policy eligibility、逐实例 Activation、Availability、projection 和 quota allocation;Roles 编辑 AdminRoleBinding 的明确 action/resource scope;Share 展示 Offer/Federation/Binding 三段状态;Devices 分开显示 ownership、Membership、Posture 和 key rotation。页面不得把这些轴压成一个 active 开关。
关键交互:
administer 开关;Portal 只返回成员自己需要的最小数据:已授权 Service、由这些 Service 推导的站点/节点摘要、自己的 Device 和身份安全设置。不得返回完整 policies、全量机器、无归属节点或管理员对象。
打开 Service 时优先使用 NS App/deep link;Web 应用可复制 FQDN 或打开浏览器。MFA、Passkey、恢复码和 API Token(若产品开放)必须有真实操作入口,按钮不能只渲染文案。
Controller/ViewModel 保存结构化模型:local runtime ownership、session、profile、daemon lifecycle、membership、directory freshness、connection readiness、exit intent/readiness、operations 和 errors。派生 UI 状态必须是纯函数,禁止在 build/render 中执行网络副作用。
每个异步操作有 operation ID、phase、cancelability 和 retry policy。互斥操作期间禁用连接/设置按钮;失败后偏好与 runtime 必须一起回滚或明确标记 pending repair。
可缓存:上次显示名称、最近目录、筛选偏好、窗口布局、非敏感 onboarding 进度。不可作为权威:授权、Gateway 候选、当前 runtime、有效 Membership、Entitlement。
缓存项携带 source/profile、revision 和 observed_at。source 不匹配时不展示可能误导的资源名;连接后立即以权威结果覆盖。
Client 穷尽匹配已知 error code;未知 code 显示“组件版本不兼容或发生未知错误”并附 request ID,不回落成网络失败。
文案规则:
no_authorized_candidates:管理员尚未分配;temporarily_unavailable:已授权资源当前不可用,不猜离线还是停用;read_failed:暂时无法获取,可重试;source_mismatch:保存配置属于另一个连接;route_conflict:显示冲突 CIDR/软件,不建议强制覆盖;projection_outdated:展示已应用 revision、待应用 revision,以及旧投影仍有效/已过期事实。runtime_owned_by_another_local_user:只说明本机另一用户正在使用,不泄露对方身份或网络;runtime_owner_inactive:说明因本机用户切换已暂停,原 owner 可明确重连;runtime_owner_release_required:要求原 owner 释放,或由管理员确认破坏性 reset;concurrent_interactive_sessions_unsupported:保持断开,说明首版不支持多交互用户共享系统隧道。App 在真正需要 TUN/VPN、helper 或防火墙能力时才请求系统权限,并提前说明系统将显示什么原生提示。权限拒绝不影响登录、目录和 Proxy-only 能力。Windows 输入法、窗口 focus 和 UAC 必须通过原生 runner 生命周期测试,避免连接时整窗闪烁或第三方 IME 崩溃。
Windows session change、macOS console user change 和 Linux logind 事件是安全输入,不是普通 UI hint。Client 只展示 daemon 的结构化 owner state,不自行猜测当前用户是否可以接管。平台没有可靠的 session-change hook 或不能证明网络先撤后切时,user-owned 连接入口保持禁用。
移动端使用平台 VPN API;后台限制、Always-On、休眠和网络切换状态必须映射到 runtime,而不是由 UI 定时器猜测。
所有状态不能只靠颜色;图标有语义标签和 tooltip;键盘可完成登录后所有桌面操作;动态文本不改变固定工具栏/列表尺寸。中英文 key 同步由测试检查,删除功能同时删除孤儿文案。
遥测默认不含访问的业务域名、完整 Node/Service 名称、IP、用户目录或错误 payload。崩溃报告需要用户/组织策略同意并脱敏。诊断导出前显示包含内容,生成后可本地检查。
产品分析只使用服务运营规格定义的 allowlist 和激活状态转移。App Store/Play 披露、用户同意和实际 payload 必须一致。更新、企业托管和卸载交互以发行生命周期为权威。
Client 完成的标准不是页面能点击,而是每次操作都能追踪到权威命令、runtime 结果、失败恢复和审计证据。