- 拓扑:每节点一个 agent,只出站连中继,出口硬编码回环,把 SSRF 爆炸半径从整个内网收缩到单节点 - 信封:Ed25519 签名覆盖 nodeID/reqID/ek 防改投与错配,临时-静态 DH 加密,并写准前向安全的实际边界 - 授权:中继不得授权任何事,危险写确认改由手机产生、agent 校验,说明服务端签发令牌为何不可搬用 - iOS:引入 InstanceEndpoint 与 NodeTransport,origin 同时承担目标/去重键/Cookie 绑定三职的迁移路径 - 复用既有 ProblemDetails、FRESHNESS_STATUSES 与 server/proxy 策略,并要求策略抽为共享 JSON 防漂移
207 lines
12 KiB
Markdown
207 lines
12 KiB
Markdown
# iOS 原生应用说明(当前实现)
|
||
|
||
本文是 iPhone 应用的唯一现行说明,内容与仓库代码一致。历史设计稿和执行计划保留在
|
||
`docs/superpowers/` 下,其中已被实现推翻的决策在本文第 9 节逐条列出。
|
||
|
||
- 当前版本:`0.2.2`,构建号 10
|
||
- 承载分支:`ios-native-ipa`
|
||
- 运行要求:iOS 16.0 及以上,`arm64`,Bundle ID `fun.chick.multi-simadmin`
|
||
- 产物:未签名 `MultiSimAdmin.ipa`,由 TrollStore 或用户自有签名流程安装
|
||
|
||
## 1. 形态
|
||
|
||
独立 iPhone 应用。应用直接以 HTTP/HTTPS 访问用户添加的每个 SimAdmin 节点,不经过
|
||
8788 控制台,不含 WebView,不内嵌 Node.js,也不与 Web 端共享数据库或进程。Web 前端和
|
||
Node 控制面仍然独立存在,两者只共享上游接口契约。
|
||
|
||
## 2. 导航
|
||
|
||
底部固定三个入口,高度 62pt(`AITabBar`):
|
||
|
||
| 入口 | 页面 | 内容 |
|
||
| --- | --- | --- |
|
||
| 节点 | `FleetView` | 节点总览、运行概览、标签筛选与批量归类、批量选择、添加与编辑实例 |
|
||
| 消息 | `MessagesView` | 跨实例短信读取、按实例与方向筛选、搜索、发送、删除 |
|
||
| 设置 | `SettingsView` | 主题外观、应用信息、本地数据(进入日志中心)、隐私与数据、数据清理 |
|
||
|
||
实例详情 `InstanceDetailView` 由节点卡片进入;日志中心 `LogsView` 只出现在
|
||
「设置 → 本地数据」里,不占用底部入口。启动参数 `--tab-messages`、`--tab-settings`
|
||
可直达对应 Tab,`--tab-detail`、`--tab-logs` 只在 Debug 构建生效,供逐页截图验证使用。
|
||
|
||
## 3. 页面能力
|
||
|
||
### 节点总览
|
||
|
||
- 运行概览:在线率与异常节点两枚大字结论、状态分布条与图例、八格两行的群集读数(信号、延迟、
|
||
存储、流量、CPU、内存、温度、电量),可折叠,折叠时保留前四格。检测进度与更新时间写在卡片
|
||
副标题里(`刚刚更新 · 已检测 6/6 台`),不占读数格;整群节点没有上报的读数保留占位,统一写成
|
||
一根短横 `—`,避免在四列窄格里被读成故障结论;栅格不会在七格与九格之间跳动。
|
||
- 标签归类:标签是唯一归类手段,分组概念已在 0.2.2 移除。标签条支持多选叠加,胶囊上直接显示
|
||
命中台数,可单个取消或全部清除;卡片内的标签同样可点,点一下即加入筛选。
|
||
- 批量标签:批量选择后一次给多台节点贴同一个标签,每个标签显示「未贴 / N/M / 全部」三态覆盖度,
|
||
点击即在整批上加减;可在同一张表里新建标签。
|
||
- 搜索:匹配名称、地址、运营商与标签。
|
||
- 节点卡片:顶部四条量表(信号、延迟、CPU、内存)配发丝进度,下面是号码、运营商、设备、存储、
|
||
温度、电量、运行时间等指标,超出一屏时折叠为「另有 N 项指标」。健康读数不着色,只有越过阈值
|
||
才出现告警或危险色。
|
||
- 批量选择:工具栏为 34pt 图标按钮(全选、删除、退出等高),勾选列独立于名称区域,
|
||
选中态不遮挡文字。
|
||
- 实例增删改:地址、名称、标签、访问凭据;删除前确认,并一并清除本地登录信息。
|
||
|
||
### 实例详情
|
||
|
||
- 头部卡片:地址与连接状态、四项仪表(信号、延迟、CPU、内存)、身份摘要(号码、运营商、网络、
|
||
IP)、模块可用度读数、标签。四项仪表排成两列发丝线栅格,读数在上、进度在下,缺数据时保留
|
||
空轨道,数据到位后卡片高度不变。
|
||
- 数据模块:设备、SIM、蜂窝网络、系统资源、CPU、连接状态共 6 个分区,逐模块独立加载,
|
||
单模块失败只标记该模块,不影响其余分区。
|
||
- 敏感值(IMEI、ICCID 等)默认隐藏,需要显式开启显示,离开页面后自动恢复隐藏。
|
||
- 本机保存的配置:地址、凭据状态、标签,以及登录、登出、重新检测。
|
||
|
||
### 消息中心
|
||
|
||
逐实例读取 `/api/sms/list` 后在本地合并,不做跨设备中转:
|
||
|
||
- 列表按时间排序,显示来源实例、方向、号码、正文与相对时间。
|
||
- 支持按实例筛选、按上行/下行筛选、按号码或内容搜索。
|
||
- 发送与刷新一起放在导航栏右侧,页脚不再另挂操作条;发送写入目标实例,失败可重试;
|
||
单条删除走该实例的上游接口,行内只留一枚红色线性图标。
|
||
|
||
### 日志中心与设置
|
||
|
||
- 日志中心:运行日志统一时间线、连接探测记录(结果、错误码、耗时)、设备诊断快照;
|
||
支持按级别、来源、实例、结果筛选与关键字搜索,支持清理过期连接日志。
|
||
- 设置:主题外观(跟随系统、浅色、深色,即时作用于全部页面)、应用信息与系统版本、
|
||
本地数据统计、隐私与数据说明、清除运行日志(不可恢复确认)。
|
||
|
||
## 4. 上游访问
|
||
|
||
只允许固定白名单,不存在任意 URL 代理:
|
||
|
||
| 方法 | 路径 | 用途 |
|
||
| --- | --- | --- |
|
||
| GET | `/api/health` | 可达性与版本 |
|
||
| GET | `/api/device` | 设备信息 |
|
||
| GET | `/api/sim` | SIM 与号码 |
|
||
| GET | `/api/network` | 蜂窝网络与信号 |
|
||
| GET | `/api/network/signal-strength` | 信号强度明细 |
|
||
| GET | `/api/stats` | 系统资源 |
|
||
| GET | `/api/stats/cpu` | CPU 明细 |
|
||
| GET | `/api/connectivity` | 连接状态 |
|
||
| GET | `/api/sms/list` | 短信列表(limit、offset、direction) |
|
||
| POST | `/api/sms/send` | 发送短信 |
|
||
| POST | `/api/sms/batch-delete` | 批量删除短信 |
|
||
| POST | `/api/auth/login` | 使用实例密码换取会话 |
|
||
| POST | `/api/auth/logout` | 注销会话 |
|
||
|
||
请求超时 30 秒,单响应体上限 262144 字节,错误统一映射为请求非法、需要登录、权限受限、不支持、
|
||
超时、传输失败、响应非法七类可读文案。会话 Cookie 按实例隔离保存在内存中,并绑定创建时
|
||
的节点地址,地址改变后旧 Cookie 立即失效。应用不请求定位、相机、麦克风、通讯录或后台
|
||
刷新权限,不声明任何后台模式。
|
||
|
||
## 5. 本地数据与安全
|
||
|
||
全部数据落在应用沙盒 `Documents` 目录,无 Keychain、无 SQLite、无服务端上传:
|
||
|
||
| 文件 | 内容 |
|
||
| --- | --- |
|
||
| `instances.json` | 实例名称、地址、标签、修订号 |
|
||
| `credentials.json` | 实例访问密码 |
|
||
| `log-center.json` | 运行日志、连接探测记录、诊断快照缓存 |
|
||
|
||
0.2.1 及更早版本写过的 `instance-groups.json` 与偏好键 `fleet.groupMode` 在升级后的首次启动
|
||
一次性删除。主题偏好存在 `UserDefaults`(键 `aiThemeMode`)。登录会话只存在于进程内存,应用退出即消失。
|
||
密码与 Cookie 不写日志、不进导出内容。删除应用即彻底清除本机数据。允许 HTTP 明文访问是
|
||
为了兼容局域网 SimAdmin,公网节点应由用户自行通过 HTTPS 反代暴露。
|
||
|
||
## 6. 设计语言
|
||
|
||
界面不含蓝色。品牌色是石墨与黄铜:浅色画布中性冷灰 `#F4F5F5`、纯白卡片、墨黑主操作
|
||
`#151819`;深色画布 `#080909`、低明度石墨分层 `#131515` / `#1B1D1E`、近白主操作 `#EEF1F1`。
|
||
颜色只保留给状态语义——危险 `#C12E28` / `#F77169`、告警 `#AA5C0F` / `#E9A63C`、成功
|
||
`#107A56` / `#42C784`,健康读数一律用墨色,避免整屏泛绿或整屏泛红。选中态用实心主色加
|
||
`onPrimary` 文字,不使用低透明度色雾,浅色深色两套主题下都必须一眼可读。
|
||
|
||
控件令牌集中在 `AITheme`:主按钮高 48pt(紧凑 44pt、大号 56pt)、工具栏按钮高 44pt(宽 104pt)、
|
||
导航栏图标按钮 34pt 方形(圆角 11pt)、输入框高 52pt、卡片圆角 22pt、按钮圆角 16pt、标签为
|
||
28pt 胶囊。同屏并排控件必须等高,选中态不得改变控件尺寸,卡片内部不再嵌套卡片——并列读数改用
|
||
发丝线分隔的栅格,正文与标题不使用负字距,字距为 0。
|
||
|
||
## 7. 构建与产物
|
||
|
||
```bash
|
||
./scripts/build-ios-ipa.sh
|
||
```
|
||
|
||
流程:`xcodebuild -scheme MultiSimAdmin -configuration Release`(`generic/platform=iOS`)编译
|
||
可执行文件 → 手工组装 `Payload/MultiSimAdmin.app` → 用 `xcrun actool` 编译 `Assets.xcassets`
|
||
得到 `Assets.car` 并合并图标元数据到 `Info.plist` → `zip` 打包 → 生成 `.sha256`。产物:
|
||
|
||
- `build/ipa/MultiSimAdmin.ipa`
|
||
- `build/ipa/MultiSimAdmin.ipa.sha256`
|
||
|
||
脚本不需要证书与描述文件,不做任何签名改动;`Assets.car` 缺失时直接失败退出,避免发布没有
|
||
图标的包。
|
||
|
||
应用图标由脚本光栅化生成,不使用手工位图:
|
||
|
||
```bash
|
||
cd apps/ios && swift Design/generate_app_icon.swift \
|
||
Sources/MultiSimAdmin/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon1024.png
|
||
```
|
||
|
||
图标为扁平构图,不用立体卡与投影:石墨底、黄铜 SIM 面板(切角在左上)、三根底部对齐的递增
|
||
信号条,29pt 尺寸下轮廓仍然可读。`apps/ios/Design/AppIcon.svg` 是同构图参考稿,实际构建使用
|
||
由 `Design/generate_app_icon.swift` 光栅化出的 PNG,面板边长、圆角、切角与信号条间距都可用
|
||
环境变量调整。
|
||
|
||
## 8. 验证方式
|
||
|
||
```bash
|
||
cd apps/ios
|
||
swift build
|
||
swift test # 48 个用例
|
||
xcodebuild -scheme MultiSimAdmin \
|
||
-destination 'platform=iOS Simulator,id=<UDID>' \
|
||
-configuration Debug build
|
||
```
|
||
|
||
单元测试覆盖实例仓储与修订冲突、地址规范化与去重、标签归一化、上游路由白名单、会话隔离、
|
||
连接探测分类、短信解析与分页、设备快照解析、日志仓储与清理、主题模式持久化、时间相对显示、
|
||
版本号契约。界面改动在 iPhone 17 Pro 模拟器上以截图逐页核对浅色与深色两套主题,重点检查控件
|
||
等高、文字不溢出、按钮在深色下不消失。
|
||
|
||
## 9. 与设计稿的偏离
|
||
|
||
`docs/superpowers/specs/2026-09-08-ios-native-ipa-design.md` 的以下决策已被实现推翻,该文档
|
||
只作为历史背景保留:
|
||
|
||
| 原设计 | 当前实现 | 原因 |
|
||
| --- | --- | --- |
|
||
| 底部五 Tab:节点/消息/通知/日志/设置 | 三 Tab:节点/消息/设置 | 应用内通知中心依赖进程常驻,关闭后不可用;日志属于低频排查,收进设置 |
|
||
| 通知通道、规则、投递队列、立即投递 | 未实现 | 同上,移除后不再保留只读残壳 |
|
||
| 实例密码存 iOS Keychain | 沙盒内 `credentials.json` | Keychain 在 TrollStore 环境下读写不稳定 |
|
||
| GRDB + SQLite 控制面库 | 沙盒内 JSON 文件 | 去掉第三方依赖,数据结构与备份语义更直观 |
|
||
| 操作目录、任务、审计、维护、备份 | 未实现 | 高风险写操作与常驻调度不在 iPhone 前台场景内 |
|
||
| 设备模块 13 项(含通话、eSIM、OTA、WiFi Calling、自动化) | 6 个只读模块 + 短信读写 | 上游只保留有稳定读取价值的接口,其余按需在后续版本评估 |
|
||
| 浅灰画布、青绿主按钮 | 深浅双主题、石墨墨色主操作、黄铜点缀 | 0.2.x 视觉重构结论,用户明确排除蓝色 |
|
||
| 实例分组(分组视图、分组编辑器、分组仓储) | 标签归类 + 批量标签 | 分组与标签职责重复,分组作为实体在 0.2.2 移除 |
|
||
|
||
## 10. 已确认的移除边界
|
||
|
||
不实现:应用启动后的周期轮询、后台任务与静默推送、Cron 与自动投递、自动备份与自动日志修剪、
|
||
控制台自更新、多用户与远程访问、全局访问密码。
|
||
|
||
保留:进入前台与下拉刷新触发的一次同步、页面可见时的按需刷新、用户主动发起的登录、检测、
|
||
发送、删除与日志清理。
|
||
|
||
## 11. 文档索引
|
||
|
||
- [docs/ios-native.md](ios-native.md):本文,现行说明
|
||
- [docs/ios-relay-architecture.md](ios-relay-architecture.md):双通道(内网直通 + 公网中继)设计稿,未实施
|
||
- [docs/ios-native-0.2.2.md](ios-native-0.2.2.md):0.2.2 构建 10 发布说明与校验值
|
||
- [docs/ios-native-0.2.1.md](ios-native-0.2.1.md):0.2.1 构建 6 发布说明与校验值
|
||
- [docs/ios-native-0.2.0.md](ios-native-0.2.0.md):0.2.0 发布说明
|
||
- [docs/superpowers/specs/2026-09-08-ios-native-ipa-design.md](superpowers/specs/2026-09-08-ios-native-ipa-design.md):历史设计稿
|
||
- [docs/superpowers/plans/2026-09-08-ios-native-ipa-foundation.md](superpowers/plans/2026-09-08-ios-native-ipa-foundation.md):地基执行计划(已完成)
|