Files
multi-simadmin/docs/product/information-architecture.md

249 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API-first Multi SimAdmin 信息架构
> Operation 的精确页面归属、surface、风险、确认、执行模式及 Fleet/资源批量语义见 [117 项验收账本](./operation-acceptance-matrix.md)Registry 是风险事实源。
> 本文定义 V1 路由、导航、页面职责、上游模块映射、状态呈现与验收矩阵。路由与 OperationRegistry 是实现边界,不允许再建立“任意 endpoint 工作台”。
> Phase 0.1 文档导航:[返回项目章程](./project-charter.md)[现状审计](./current-system-audit.md)[角色与流程](./personas-and-workflows.md)**信息架构**(本文)
## 1. 导航模型
### 1.1 全局导航
1. **Fleet**:所有实例的异常定位、筛选、比较、多选入口。
2. **Jobs**:异步/批量操作的状态、逐项结果、取消和重试。
3. **Audit**:操作证据与故障复盘。
4. **Settings**:实例、凭据状态和系统采集参数。
实例被选中后出现二级模块导航:Overview、Cellular、Device Network、Messages、Calls、eSIM、Notifications、Automation、OTA。导航由 capability 驱动,而非固定展示一组空页面。
### 1.2 URL 规则
- 实例使用不可变内部 `:id`;名称变化不改变 URL。
- 列表 filter/sort/page 可序列化到 query,便于分享和返回。
- dialog 不替代主要业务路由;新增实例使用独立路由。
- Job/Audit 详情有可深链 URL。
- 原站不设 iframe 路由,仅在实例头部提供外链,使用新窗口和 `rel="noopener noreferrer"`
- 不提供 `/api-workbench``/rawpage` 或接受任意 path 的 UI。
## 2. 路由清单
| 路由 | 页面职责 | 主操作 | 权限/风险边界 |
|---|---|---|---|
| `/` | 规范重定向 | 重定向 `/fleet` | 无业务内容 |
| `/fleet` | 高密度实例表格、搜索、筛选、排序、列、分页、多选、异常入口 | 刷新、批量动作 prepare | R0;批量动作按 registry 风险升级 |
| `/instances/new` | 添加实例、连接/认证/capability 初探 | R0 health/auth-statusR1-S credential verify/login;保存 | 仅登记并校验 canonical originR1-S 限速、脱敏元数据审计、禁止重放;secret 不回显 |
| `/instances/:id/overview` | 设备、SIM、网络、系统、关键异常摘要 | 刷新;服务/系统重启 | 查询 R0;重启 R3 Job |
| `/instances/:id/cellular` | 蜂窝、信号、小区、运营商、射频、锁频/锁小区、数据/APN | register、lock、data 等 | R0/R1/R2;影响服务项 Job 化 |
| `/instances/:id/device-network` | 接口、地址、DDNS、WLAN | DDNS sync、WLAN connect/forget | 查询 R0WLAN connect R1WLAN forget R2 JobDDNS config R2 Job,断连影响需预检 |
| `/instances/:id/messages` | 统计、列表、会话、发送、删除 | send、delete、clear | 查询 R0;发送按 registry;删除/清空 R3 |
| `/instances/:id/calls` | 实时通话、拨号、设置、历史、IMS、voicemail | dial/answer/hangup/settings;删除通话记录 | 查询 R0;通话控制/设置按 R1/R2;通话记录删除 R3 Job |
| `/instances/:id/esim` | work mode、config、lpac、eUICC、profiles | download/enable/rename/delete | eSIM download/enable R1 directconfig/work mode R2 Jobprofile delete R3 |
| `/instances/:id/notifications` | config、channel test、logs、queue | test/retry/clear/delete | notifications config R2 Job;清理类 R3 |
| `/instances/:id/automation` | 配置、task test、logs | save/test/clear | automation config R2 Jobtask test R2 Jobclear R3 |
| `/instances/:id/ota` | 当前/最新版本、上传、prepare、apply、cancel | upload/prepare/apply/cancel | prepare R2apply R3 Job;专用流上传 |
| `/jobs` | Job 表格与筛选 | 取消/重试入口 | cancel 默认 R1retry 继承原 operation 风险且最低 R2,均由 registry 可提高 |
| `/jobs/:jobId` | 阶段、items、attempt、事件、retry lineage 和关联 audit | cancel/retry items | cancel 默认 R1retry 创建新 Job 且继承原风险(最低 R2);不复制/重放成功 item,非幂等先核实 |
| `/audit` | 审计列表、筛选、导出 | 查询/导出脱敏摘要 | R0;导出遵循 redaction |
| `/audit/:eventId` | 单事件详情和关联链路 | 跳转 Job/实例 | 不展示 sensitiveFields |
| `/settings/instances` | 实例 CRUD、标签、凭据状态、旧配置导入导出 | create/edit/delete/import | create/update R1;批量 import R2 Jobdelete R3 Job;不导出 secret |
| `/settings/instances/:id` | 实例编辑、连接测试、会话与本地 secret reference、设备密码专用流程 | health/auth-status R0credential verify/login/logout R1-Ssavedelete | 本地 reference set/preserve/clear 为 R1;设备 setup/password 为 R3 专用 Jobdelete R3 Jobrevision 并发控制 |
| `/settings/system` | 轮询、缓存、并发、诊断、版本和数据目录 | 保存设置、诊断 | 设置 R1;限制安全范围 |
| `*` | Not found | 返回 Fleet/上一页 | API 404 与 Web fallback 分离 |
## 3. 页面内部结构
### 3.1 AppShell
- 顶栏:页面标题、全局连接/SSE 状态、全局搜索入口、当前版本。
- 全局侧栏/窄屏菜单:Fleet、Jobs、Audit、Settings。
- 实例上下文栏:实例名称/ID、origin、总状态、认证、新鲜度、实例切换、原站外链。
- 模块导航:由 capability 生成;degraded 有徽标;unsupported 在能力详情可查。
- 主内容:页面标题/说明、状态 banner、工具栏、数据区、持久错误区。
### 3.2 Fleet 表格默认列
| 列 | 值与行为 |
|---|---|
| 选择 | 多选;跨页选择必须显示选择范围 |
| 实例 | 名称、稳定 ID、标签;点击 overview |
| 状态 | online/offline/auth-required/degraded/unknown;点击状态详情 |
| 认证 | authenticated/auth-required/unknown |
| 运营商/制式 | 最后成功值 + freshness |
| 信号 | 规范化等级/原始关键值;可排序,未知不按 0 处理 |
| 版本 | 上游版本/commit 与兼容提示 |
| 异常 | 关键失败采集项数量及最高优先级 |
| 延迟 | health 延迟和 checkedAt |
| 最后成功 | 绝对时间 + 相对时间;stale 明显 |
| 操作 | 查看、刷新;写动作进入选择/专用流程 |
默认排序:异常优先级降序 → stale 年龄降序 → 名称升序。列偏好可本地保存,但状态、实例、异常不可全部隐藏。
### 3.3 实例模块公共布局
1. **摘要条:** capability、采集时间、freshness、requestId/错误入口。
2. **读数据区:** 结构化表格/定义列表/时间序列,不直接 dump raw JSON。
3. **动作区:** 只显示 registry 中该 capability 可用的结构化动作。
4. **确认抽屉/页:** 目标、diff、风险、预检和确认。
5. **关联活动:** 最近 Job 和 audit 摘要。
6. **状态覆盖:** loading/empty/stale/error/unsupported/auth-required/degraded 采用统一组件。
## 4. 上游 API 模块到页面映射
| 上游模块 | 能力范围 | 主页面 | 次入口/备注 |
|---|---|---|---|
| 实例与认证 | health、auth status、setup、login、logout、password、settings | `/instances/new``/settings/instances/:id` | health/auth-status 严格 R0verify/login/logout 为 R1-S 专用会话 BFFsetup/password 为 R3 专用 Job;均禁止通用代理 |
| 设备与系统 | device、stats、CPU、connectivity、service restart、system reboot | `overview` | restart/reboot 为 R3 Job |
| SIM | SIM 信息、详情刷新、缓存更新 | `overview` | 与 cellular 交叉字段只引用同一 resource/query,不重复 endpoint 定义 |
| 蜂窝网络 | network、cells、monitor、signal、location、operators、register | `cellular` | overview 仅摘要和深链 |
| 射频与锁定 | radio mode、band lock、cell lock、unlock all | `cellular` | lock/unlock 预检并按 R2/R3 registry 执行 |
| 数据连接 | data、roaming、airplane、APN、baseband | `cellular` | R1 开关;baseband restart R3 Jobbaseband restart status R0 read,必须分开呈现 |
| 设备网络 | interfaces、addresses、DDNS、WLAN 全生命周期 | `device-network` | connect/disconnect 后需验证 connectivity |
| 工作模式与 eSIM | work mode、config、lpac、eUICC、profiles | `esim` | profile delete R3;工作模式影响说明 |
| 短信 | stats、list、conversation、send、delete、clear | `messages` | 删除/清空 R3;短信正文不进入 audit |
| 通话 | calls、dial、answer、hangup、volume、forwarding、history、IMS、voicemail、history delete | `calls` | 实时状态与历史分区;通话记录单条/批量删除 R3 Job,结果进入 Job 并关联脱敏 audit |
| 通知 | config、test、logs、queue、retry、clear、delete | `notifications` | 日志/队列删除按 R3 |
| 自动化 | config、logs、clear、task test | `automation` | config schema 表单,禁用任意 JSON |
| OTA | status、upload、latest、online prepare、apply、cancel | `ota` | upload 专用流;apply R3 Job |
### 映射约束
- 每个 operation 只有一个主页面 owner;其他页面只能引用摘要或深链。
- 页面不得手写上游 method/path;通过 operationId 调用生成客户端。
- 同一 resource 的缓存 key 包含 instanceId、resource/operation 和参数;不可跨实例共享数据。
- capability 不等于导航可见性:危险操作还需风险政策、认证和前置状态共同满足。
## 5. 状态呈现模型
### 5.1 三个正交维度
| 维度 | 值 | UI 责任 |
|---|---|---|
| 请求执行 | idle/loading/success/error | 控制加载、重试和持久错误 |
| 数据新鲜度 | fresh/stale/expired/unknown | 决定是否保留旧值、是否要求刷新/确认 |
| 能力支持 | supported/unsupported/auth-required/degraded/unknown | 决定模块/动作可用性及解释 |
不得压缩为单个 `status` 后丢失信息。例如:页面可以同时是 `request=error``freshness=stale``support=supported`,表示刷新失败但仍展示上次有效值。
本三维模型受[项目章程 7.6](./project-charter.md#76-三个正交页面状态)约束;领域/API 只允许 `fresh`,其中文显示为“最新”,不得定义 `latest` 枚举(OTA 的“latest release”是资源名称,不是新鲜度枚举)。
### 5.2 页面状态行为
| 页面状态 | 数据区 | 动作区 | 反馈 |
|---|---|---|---|
| loading | skeleton,保留布局 | 禁用依赖当前值的动作 | 超过阈值显示仍在加载与取消/重试 |
| empty | 明确“成功查询但为空” | 提供创建/扫描等适用动作 | 显示 fetchedAt |
| stale | 保留最后成功值 | R0 可刷新;写操作提示或阻断 | banner 显示最后成功和本次错误 |
| error 无缓存 | 错误状态卡 | 只保留安全的重试/登录/诊断 | errorCode、requestId、HTTP status |
| unsupported | 不展示伪空表格 | 隐藏写动作 | 说明版本/404 探测证据 |
| auth-required | 保留可用旧值并 stale | 禁用写;显示登录 | 登录成功仅自动重试 R0 |
| degraded/partial | 成功子区正常,失败子区局部错误 | 仅开放不依赖失败前置项的动作 | 明确失败数量和逐项原因 |
## 6. 风险操作的信息架构
| 风险 | 页面形态 | 结果落点 |
|---|---|---|
| R0 | 页面加载、刷新、筛选 | 原页面数据区;错误持久显示 |
| R1 | 页面内结构化表单 → diff 确认 | 原页面刷新 + audit 侧链 |
| R2 | 专用表单 → preflight → 确认 | 默认 Job 详情/侧面进度 + audit`syncSafe` 单目标例外在原页显示结构化结果 + audit |
| R3 | 专用危险区 → 强确认/复述目标 → Job | `/jobs/:id` 为主,原页面只显示状态与深链 |
R3 全部 Job 化。R2 默认 Job 化;仅单目标 operation 可在 OperationRegistry 中以 `syncSafe=true` 明确例外,并必须登记理由及覆盖同步安全、超时、结果落点和误重放的测试;批量 R2 即使单项可同步也仍 Job 化。任何 R2/R3 不得仅用通用 `confirm()`、toast 或“发送 JSON”完成。确认关闭、目标切换或 revision 变化必须清除 token。
确认令牌不在本文重复定义,以[项目章程 7.3](./project-charter.md#73-确认令牌唯一规范)为唯一规范;Preparation/Job/Attempt/JobItem 与 SSE/audit 关联以[项目章程 7.4](./project-charter.md#74-preparationjob-与-attempt-固定模型)为准。`prepare` 不创建 Job,确认消费 token 后才创建;用户 retry 必须创建新 `jobId`,并用 `retryOfJobId`/`rootJobId` 保留 lineage,来源终态 Job 不变。
### 6.2 实例删除信息架构
删除遵循 `active|disabled → deleting → tombstoned → purged`。确认后创建 R3 Job 并进入 `deleting`,立即从默认 Fleet/导航隐藏且停止轮询、会话和新写;删除详情仍可从 Job/audit 深链访问。不可取消点、snapshot/secret ref、失败恢复和“purge 不删除 audit”的完整流程以[WF-13](./personas-and-workflows.md#wf-13-两阶段删除实例)为准。
### 6.3 出站目标边界
所有实例页只能使用管理员已登记 canonical origin,不接受动作参数指定 host/port。允许地址、DNS 固定/复验、redirect、代理环境变量及 Host/SNI 的实现与攻击测试以[项目章程 7.5](./project-charter.md#75-已登记实例-origin-与-ssrflan-授权)为唯一政策;特别是 loopback/RFC1918 仅允许已登记精确 authority,不是端口扫描授权。
### 6.4 复审关注动作的默认风险
下表默认值必须进入 OperationRegistry;逐项研究可提高风险,不得降低到表中等级以下。若拆分出多个 operation,每项分别登记。
| 动作 | 默认风险与执行 | 确认/结果落点 |
|---|---|---|
| Messages send | R2,默认 Job;仅 registry `syncSafe` 理由与测试齐全时允许单目标同步 | 显示实例、号码、内容摘要;Job 详情或同步原页结果 + audit |
| Notifications channel test / queue retry | R2,默认 Job;单目标 `syncSafe` 例外规则同上 | 显示 channel/queue item 与外发影响;Job 或同步原页结果 + audit |
| Automation task test | R2,默认 Job;单目标 `syncSafe` 例外规则同上 | 显示 task、参数和可能副作用;Job 或同步原页结果 + audit |
| Settings instance read | R0 | 设置列表/详情;错误持久显示 |
| Settings instance create/update(含凭据 set/preserve/clear | R1 | diff、revision;原设置页结果 + audit |
| Settings health/auth-status | 严格 R0,不提交 secret、不改变会话 | 原设置页分阶段结果 |
| Credential verify / login / logout | R1-SR1 子类,不是新等级) | 专用会话 BFF;按 actor+session+instance 限速;audit 仅无 secret 元数据;禁止自动重放 |
| Device setup/password change | R3,全部专用 Job 化 | 强确认、Job+audit;不得通用代理;Phase 0.2 仅可细化上游形态 |
| Settings instance import | R2,批量所以全部 Job 化 | 预览 diff/冲突/数量;Job items + audit |
| Settings instance delete | R3,全部 Job 化 | 复述实例 ID 与关联清理影响;Job + audit |
| Jobs cancel | R1 默认;若取消会触发补偿或中断设备操作则 registry 提高到原 operation 风险 | Job 详情显示可取消阶段;结果仍在该 Job 事件与 audit |
| Jobs retry | 继承原 operation 风险且最低 R2;创建具有独立 Attempt 的新 Job | 重显失败 items/参数摘要并重新确认;新 `jobId` + audit,通过 `retryOfJobId`/`rootJobId` 关联不可变来源;批量仅复制明确选择且可重试的失败 items,并记录 `sourceJobItemId`,成功项绝不复制/重放 |
| Calls history delete(单条/批量) | R3,全部 Job 化 | 展示记录身份与数量并复述实例 ID(批量再复述数量);`/jobs/:jobId` items + 历史刷新 + 脱敏 audit |
## 7. 页面 × 模块 × 状态 × 风险验收矩阵
缩写:`L` loading、`E` empty、`S` stale、`X` error、`U` unsupported、`A` auth-required、`P` degraded/partial。
| 页面 | API 模块 | 必验收状态 | 写风险/关键动作 | 可验收结果 |
|---|---|---|---|---|
| Fleet | health/auth/device/SIM/network/stats/OTA 摘要 | L,E,S,X,A,P,unknown | 批量 R1R3(仅 batchable) | 筛选/排序/多选;逐实例预检和 partial Job |
| New instance | 实例与认证 | L,X,A,U/unknown capability | 配置专用保存/secret set | 连接与认证分阶段;失败可存 disabled 草稿;无 secret 回显 |
| Overview | 设备系统、SIM、摘要 | L,E,S,X,U,A,P | restart service/system R3 | 摘要深链;重启进入 Job,不在断连时假报成功 |
| Cellular | 蜂窝、射频、数据连接 | L,E,S,X,U,A,P | data/roaming R1register/lock/baseband R2/3 | 当前值→目标值;断连影响;验证后状态 |
| Device Network | interfaces/DDNS/WLAN | L,E,S,X,U,A,P | DDNS config R2 JobWLAN connect R1WLAN forget R2 Job | 扫描空与 unsupported 区分;变更后 connectivity 验证 |
| Messages | SMS | L,E,S,X,U,A,P | send R2(默认 Job`syncSafe` 例外);delete/clear R3 Job | 分页/会话;号码校验;删除数量强确认 |
| Calls | Calls/IMS/voicemail | L,E,S,X,U,A,P | dial/answer/hangup/settings R1/2history delete R3 Job | 实时与历史分离;拨号超时不重放;记录删除复述目标/数量并落 Job、刷新历史及脱敏 audit |
| eSIM | work mode/eSIM/lpac/eUICC/profile | L,E,S,X,U,A,P | eSIM download/enable R1 directconfig/work mode R2 Jobdelete R3 | profile 身份可见;删除复述;完成后列表与连接核实 |
| Notifications | config/test/logs/queue | L,E,S,X,U,A,P | notifications config R2 Jobtest/retry R2 Jobclear/delete R3 Job | channel 级反馈;队列逐项;清理确认数量 |
| Automation | config/test/logs | L,E,S,X,U,A,P | automation config R2 Jobtest R2 Jobclear R3 Job | schema 表单;测试与正式任务明确区分 |
| OTA | status/release/upload/prepare/apply/cancel | L,E,S,X,U,A,P | prepare R2apply R3 | 流式进度/校验;版本重现判完成;可取消性明确 |
| Jobs | jobs/items/attempts | L,E,S,X,P | cancel 默认 R1(可提高);retry 继承原风险且最低 R2、创建新 Job | 重启恢复;终态不可变;失败项选择重试;新 jobId+attemptId 与 retry/root/source lineage 关联 |
| Job Detail `/jobs/:jobId` | jobs/items/events/audit links | L,E,S,X,P | cancel 默认 R1retry 最低 R2 | 阶段、逐项、attempt 与关联 audit;不可取消/重试原因可见 |
| Audit | audit | L,E,S,X | R0 查询/脱敏导出 | 过滤、详情、requestId/job 链路;敏感 canary 为零 |
| Audit Detail `/audit/:eventId` | audit event/job/instance links | L,E,S,X | R0 | 参数脱敏摘要、阶段与上游错误;可往返 Job/实例且不展示 sensitiveFields |
| Settings Instances | 实例/认证/导入 | L,E,S,X,A,P | read/health/auth-status R0R1-S 会话;create/update R1import R2 Jobdelete R3 Job | revision、预览 diff、幂等导入、原文件不改;删除 deleting/tombstone 可追踪 |
| Settings Instance Detail `/settings/instances/:id` | 实例/认证/secret reference | L,E,S,X,A,P | health/auth-status R0verify/login/logout R1-Ssave/reference 变更 R1setup/password/delete R3 Job | preserve/set/clear 明确;revision 冲突;删除不可取消点与 Job/audit 可追踪 |
| Settings System | settings/diagnostics | L,E,S,X | R1 | 范围校验;变更 revision;诊断结果可复制且脱敏 |
## 8. 内容与命名规范
- 对用户使用“实例”,不用“设备”代替配置实体;硬件信息仍称“设备”。
- operation 显示业务名称,技术详情可附 `operationId`,不以 path 作为主标签。
- 错误包含可行动说明、`errorCode``requestId`;原始上游正文默认不直接展示。
- 时间同时提供绝对时间和相对时间;所有新鲜度以服务端时间为准。
- destructive button 只用于真正 R3,不以颜色代替风险说明。
- 空值显示“未知/未提供”,不使用同一个 `-` 混合 unknown、unsupported 和 empty。
## 9. 响应式与可访问性验收
| 宽度 | 主要策略 |
|---|---|
| 1440 | 完整全局侧栏 + 实例模块栏;Fleet 多列高密度 |
| 1024 | 可折叠模块栏;非关键 Fleet 列按优先级隐藏 |
| 768 | 全局导航抽屉;表格保留实例/状态/异常/操作,支持列面板 |
| 390/320 | 不把完整表格强塞横向页面;采用行详情/关键字段堆叠,页面本身无横向溢出 |
所有宽度必须满足:焦点可见、dialog 焦点圈定并可返回触发器、错误与字段通过语义关联、图标有名称、状态不只依赖颜色、主要流程可键盘完成。
## 10. IA 阶段门禁
### Phase 0 → Phase 1 workspace/contract bootstrap gate
进入 Phase 1 workspace/contract bootstrap 前只要求规格、结构化证据与复审门禁;不以尚未进入实现阶段的 Fleet 组件或 E2E 产物阻断 workspace bootstrap
- [x] 全部 117 个上游 operation 由显式 operation ID exact partition 映射到唯一主路由与可实施 section/surface;测试验证 exact cover、无重叠、无未知 ID,且 route owner 一致。
- [x] loading/empty/stale/error/unsupported/auth/partial、policy-forbidden、unknown-result 与 owner-switch 由显式 operation ID scenario profile exact partition 决定,并保留逐 profile 不适用理由。
- [x] policy 与 availability 均由显式 operation ID exact partition 决定;每个写动作具有 Registry 风险等级、确认形态、结构化政策和结果落点,缺失映射立即失败。
- [x] 规格与测试不存在 iframe、任意 path、任意 JSON 或第二份 endpoint catalog 的产品入口。
- [x] 1440–320 的导航与数据降级策略已形成可执行规格。
- [x] 最终独立规格与质量/安全复审均已通过;防假绿 mutation、独立 Phase 0.2 Git-object 安全基线和 metadata-only fixture 扫描均获批准。
### Phase 5 implementation gate
以下实现证据不能删除或伪造为已完成,但 deferred 到 Phase 5;它们不是 Phase 1 workspace/contract bootstrap blocker
- [ ] Fleet 默认列、排序、筛选和批量选择规则已形成组件/E2E 验收用例。
- [ ] E2E 当前为 N/A;进入 Phase 5 Fleet 页面实现前,必须将上述规格落为可执行组件/E2E 验收并通过。
Phase 0 release gate 已通过;Phase 5 实现与 E2E 仍是各自阶段的独立门禁,不能由本次规格复审替代。