Files
multi-simadmin/docs/superpowers/specs/2026-09-08-ios-native-ipa-design.md

13 KiB
Raw Permalink Blame History

iOS 原生 IPA 改写设计

日期:2026-09-08

实现修订(2026-09-14,0.2.1 build 6)

本文是改写启动时的设计稿,保留作为历史背景。以下决策在实现过程中被推翻,现行事实以 docs/ios-native.md 为准,正文中的旧描述不再单独改写:

  • 底部导航为节点、消息、设置三个入口,不是本文的五个 Tab。
  • 应用内通知中心整体移除:通知依赖常驻进程转发,应用关闭后无法工作,因此通道、规则、 投递队列、手动投递均不实现。
  • 日志中心不是独立 Tab,收纳在「设置 → 本地数据」内。
  • 不使用 iOS Keychain:TrollStore 环境下 Keychain 读写不稳定,实例密码改存应用沙盒 Documents/credentials.json,仅内存持有会话 Cookie。
  • 不使用 GRDB/SQLite:本地数据改为四个 JSON 文件(instances.json、 instance-groups.json、credentials.json、log-center.json),不引入第三方依赖。
  • 操作目录、任务、审计、维护、备份、恢复未实现:iPhone 前台场景不承载高风险写操作与 调度型能力,本文对应章节按未落地处理。
  • 设备模块落地为 6 个只读分区(设备、SIM、蜂窝网络、系统资源、CPU、连接状态)加短信读写, 本文列出的通话、eSIM、OTA、WiFi Calling、自动化历史未纳入当前版本。
  • 配色从「浅灰画布 + 青绿主按钮」改为深墨蓝与金色的品牌对,浅色用中性冷灰画布,主操作为蓝色。

目标

把 multi-simadmin 的管理能力改写为独立 iPhone 应用,而不是为现有 Web 服务做一个远程客户端或 WebView 壳。应用面向 iOS 16+ 和 TrollStore 安装环境,构建流程产出未签名 IPA;Apple 证书、开发者账号、TestFlight 和上架签名不在本项目范围内。

原生应用直接连接用户配置的各 SimAdmin 实例,本地承担实例注册、连接状态、消息归档、通知队列、任务历史、审计、日志和维护能力。不要求用户先运行 8788 控制台服务。现有 Web 前端与 Node API 保持不变,直到 iOS 版本验证后再另行决定发布关系。

已确认决策

  • 形态:SwiftUI 原生应用。
  • 最低系统:iOS 16.0。
  • 构建产物:MultiSimAdmin.ipa,默认不签名,后续由用户用 TrollStore 或自有证书处理。
  • 功能范围:优先保持现有控制台与 Hub 能力,但移除不适用于 iPhone 前台的定时/常驻能力。
  • 全局访问密码:移除;实例自身的登录凭据仍保留并安全存储。
  • 现有 UI 风格:移植为 iOS 原生组件,不照搬浏览器布局。

架构

新增 apps/ios,包含独立 Swift 应用。结构分为五层:

  1. App 层:SwiftUI 应用入口、导航、生命周期和全局错误提示。
  2. Presentation 层:节点、消息、通知、日志、操作、设置等 SwiftUI 视图与 view model。
  3. Domain 层:实例、连接、消息、通知、操作、审计、维护等领域服务和值类型。
  4. Upstream 层:URLSession 访问 SimAdmin 实例,管理实例会话 Cookie、超时、响应解析和安全路径白名单。
  5. Persistence 层:SQLite 持久化本地控制面数据;实例密码等敏感值使用 iOS Keychain。

数据库采用 GRDB 管理迁移与查询,避免手写 SQLite C API。凭据使用 Keychain 的应用私有可迁移项,不进入数据库明文、日志、备份预览或导出文件。

应用不内嵌 Node.js。iOS 版本的消息、通知、任务和审计语义按现有控制面模型重新实现,保留核心字段和用户可见行为。

导航与界面

iPhone 主导航使用底部 Tab:

  • 节点:总览、筛选、批量选择、添加/编辑实例、实例详情和设备模块。
  • 消息:跨实例短信归档、会话、发送、删除、手动同步和发送队列。
  • 通知:通道、规则、队列、投递日志和手动投递/重试。
  • 日志:运行日志、连接日志、诊断和审计。
  • 设置:实例管理入口、分组/标签、操作目录、维护、备份、应用信息。

界面移植现有设计语言:

  • 画布使用浅灰 #f3f5f8,主要内容使用白色卡片和柔和描边。
  • 顶部使用深色品牌栏,内容区保持浅色高对比。
  • 主操作按钮使用现有青绿色系统,危险操作使用现有红色系统。
  • 统一普通、紧凑、大号控件高度和圆角;同屏并排的主要操作必须尺寸一致。
  • 使用 SF Symbols 表达刷新、筛选、添加、删除、发送、密钥和状态,不使用文字包住所有图标。
  • 卡片、表格、表单和确认弹窗按 iPhone 动态字体、安全区、横竖屏和 Assistive Access 语义适配。

功能映射

实例与节点

  • 添加、编辑、删除实例,支持名称、地址、标签、分组和实例密码。
  • 连接测试、登录、登出、在线/离线/需登录/降级状态和快照新旧程度。
  • 批量选择、批量测试、批量删除、分组筛选、标签筛选、状态筛选和搜索。
  • 节点资源摘要、手机号、温度、版本、新鲜度和最新短信预览。
  • 删除实例前先尝试释放 Hub 绑定;无法访问时按现有规则区分“跳过释放”与“失败”。

设备模块

实例详情保留上游设备能力模块:总览、蜂窝、SIM、通话、eSIM、WiFi Calling、设备网络、OTA、消息、通知、自动化历史、配置和备份。每个模块按现有上游端点读写,使用统一的加载、空态、无权限、超时和确认流程。

高风险动作沿用操作目录中的风险等级和确认文案;系统重启、基带重启、服务重启等动作必须明确显示目标实例。

消息

  • 直接拉取实例短信列表、会话、统计和详情。
  • 发送短信、批量删除、清空、按方向筛选和分页。
  • 本地归档跨实例消息,保留方向、号码、内容、时间、状态、来源实例和同步时间。
  • 发送队列保留离线重试记录,但只在前台刷新、进入消息页或用户点击“发送”时处理。

通知

  • 管理通知通道、规则、队列和投递日志。
  • 支持基于连接状态、短信和操作事件的手动评估。
  • “立即投递”“重试”“重试全部”“清空”只在应用前台执行。
  • 投递成功、失败和重试状态进入本地队列/日志表。

不使用 iOS 远程推送、后台任务调度或常驻网络轮询。

操作、任务与审计

  • 移植操作目录、准备/执行两段式协议、确认令牌、版本检查和风险等级。
  • 操作准备写入本地数据库;应用退出时把未完成任务标记为终止或未知结果。
  • 保留任务列表、任务详情、条目结果、尝试记录、取消、重试和手动 reconcile。
  • 审计事件记录操作者、请求、目标、结果、参数摘要和异常原因。

定时任务创建与自动触发移除。已有调度模型只保留为历史只读视图;新的“手动执行”入口不创建周期任务。

日志与系统

  • 连接日志、运行日志和诊断汇总进入日志中心。
  • 支持筛选、清空、修剪、导出和详情展开。
  • 系统维护显示数据库、组件数量、可回收空间、应用版本和平台信息。
  • 手动清理、VACUUM、校验、备份、恢复、导入、导出和删除备份。
  • 自动备份、自动日志修剪和自动数据保留调度移除;保留策略仅作为手动清理的默认参数。

分组、标签与身份

  • 设备分组和标签完整本地管理,并用于节点筛选、通知规则和批量操作。
  • 设备身份记录用于识别异常换绑和重复身份,前台刷新时更新。
  • 授权模式支持自动与手动;手动模式在检测到身份变化时要求确认。

定时能力的移除边界

以下行为不实现:

  • 应用启动后的周期网络轮询。
  • iOS 后台任务、静默推送唤醒、常驻 Socket 或后台同步。
  • Cron 表达式解析与周期执行。
  • 自动备份、自动队列投递、自动日志清理。
  • 控制台自更新。

以下行为保留:

  • 进入前台、下拉刷新、页面切换或用户点击时执行一次同步。
  • 用户主动触发队列投递、备份、清理和 reconcile。
  • 前台期间页面可见时的按需状态刷新。

上游访问与安全

  • 上游请求只允许显式注册的方法和路径,不提供任意 URL 代理。
  • 响应大小、超时、JSON 结构和敏感字段按现有上游网关边界限制。
  • 实例密码存入 Keychain;会话 Cookie 只保存在内存,不写入 SQLite 或日志。
  • 登录会话按实例隔离;修改实例地址后立即清空旧会话。
  • 日志不输出 Cookie、Authorization、密码、确认令牌、完整短信正文或敏感通知配置。
  • 短信和通知正文在列表中支持脱敏显示,详情页按现有显隐交互显示原文。

iOS 允许访问用户明确输入的 HTTP SimAdmin 实例地址。设置页必须显示“HTTP 明文传输”警告;HTTPS 和受信任内网地址不做额外降级提示。

数据模型与迁移

SQLite 保留以下核心表,字段可按 Swift 领域模型调整,但不得丢失现有用户语义:

  • 实例:instances、instance_tags、tag_registry、device_groups。
  • 状态:status_snapshots、capabilities、connection_logs、device_identities。
  • 消息:sms_messages、sms_outbox。
  • 通知:notification_channels、notification_rules、notification_deliveries、notification_queue。
  • 操作:jobs、job_items、job_attempts、operation_preparations、audit_events。
  • 设置:app_settings、维护保留策略。

首次启动创建 iOS 版本 1 迁移。不导入现有 Node 服务数据库作为第一版要求;后续可在设置页提供数据库导入兼容层。导入时必须拒绝无法识别的 schema 版本,并在写入前创建安全备份。

构建 IPA

新增 Swift Package apps/ios 和构建脚本 scripts/build-ios-ipa.sh。Swift Package 是 iOS 源码与依赖的单一事实来源,不引入 XcodeGen 或检入的 Xcode 工程文件。

  1. 使用 swift build --configuration release --triple arm64-apple-ios16.0 和 iPhoneOS SDK 编译 MultiSimAdmin 可执行文件。
  2. 组装 Payload/MultiSimAdmin.app,包含可执行文件、Info.plist、资源包和应用图标。
  3. Info.plist 声明 iOS 16 最低版本、iPhone 方向、深浅色外观、ATS 例外和启动屏,但不声明后台模式。
  4. 压缩为 build/ipa/MultiSimAdmin.ipa。
  5. 输出 IPA 路径、大小和 SHA-256。

构建脚本不得要求证书或描述文件。如果目标环境需要伪签名,由用户使用 TrollStore 或自有工具处理;仓库脚本不默认修改二进制签名。

错误处理

  • 网络失败显示实例名、可读原因和重试操作,不中断其他实例刷新。
  • 单个实例失败只影响该实例卡片或详情,不使节点总览整页失败。
  • 上游 401 显示“需要登录”,403 显示权限受限,404 显示不支持,超时明确区分网络不可达。
  • 删除、恢复、重启、清空和高风险操作使用统一确认弹窗,显示目标数量与不可恢复提示。
  • 数据库迁移失败时保持只读启动屏,提示备份文件位置,不自动删除旧数据。

测试与验收

XCTest 覆盖:

  • 实例创建、地址校验、版本冲突、密码保存、登录会话隔离和删除补偿。
  • 上游路径白名单、超时、错误状态、Cookie 注入和响应解析。
  • 短信归档、去重、发送、删除、队列前台 flush 和失败重试。
  • 通知规则评估、队列处理、通道投递和日志写入。
  • 操作准备/执行、确认令牌、任务结果、审计和中断任务恢复。
  • 数据库迁移、备份导出、恢复预览和敏感字段排除。
  • UI 层验证核心页面可达、空态/错误态存在、按钮尺寸一致、脱敏状态正确。

构建验收:

  • iOS 16 Simulator 可安装并启动。
  • 390、768 和 1024 点宽度下无横向溢出、文字截断或控件重叠。
  • scripts/build-ios-ipa.sh 在干净构建目录产出未签名 IPA,并输出 SHA-256。
  • 应用不请求定位、相机、麦克风、通讯录或后台刷新权限。

非目标

  • 不实现 App Store 发布、TestFlight、推送证书或开发者签名。
  • 不在 iPhone 上运行 Node.js、Fastify 或现有 SQLite 服务端。
  • 不实现后台常驻、Cron 自动化、自动备份或控制台自更新。
  • 不支持多用户、远程 Web 登录或浏览器访问 iPhone 内的控制面。
  • 不移除实例自身密码能力;只移除 multi-simadmin 的全局访问密码。