# 故障定位与恢复边界

排查星线 App 时，先确定故障发生在本机界面、网络、聊天服务、Account、第三方授权还是商店。本文根据源码中的实际错误与运行机制整理处理顺序。示例仅使用本机地址和合成数据；本次没有访问生产、读取用户内容或实施恢复操作。服务机制见[运行维护](https://document.thestarline.cn/app/operations.md)，验收命令见[测试与验收](https://document.thestarline.cn/app/testing.md)。

## 先收集最少必要信息

记录平台、App 版本、系统、网络、时间、入口、可重复步骤、HTTP 状态或错误代码，以及是否刚更新版本。把“按钮没反应”“网页报错”“网页成功但未回 App”“回 App 后账号为空”分开；它们位于不同边界。日志只截取必要部分，移除 Authorization、Cookie、验证码、state、ticket、完整回跳 URL、手机号和记忆正文。

优先做只读检查，保留原进程和数据。不要一开始卸载 App、清空 Keychain／Keystore、删除 SQLite、清空记忆或重置模拟器。构建成功不能解释真实路径失败，截图出现某一页面也不能证明用户已完成授权。

## 页面打不开或连接被拒绝

本地 `ERR_CONNECTION_REFUSED` 通常先确认目标端口确有服务，而不是反复刷新页面：

```sh
curl --fail --silent --show-error http://127.0.0.1:9100/api/health
curl --fail --silent --show-error http://127.0.0.1:4210/health
```

身份健康检查会访问数据库；聊天健康仅证明 HTTP 进程响应。若前端开发页能打开而 API 不可用，分别检查 `identity/client` 的 Vite 与身份后端，不把一个端口的 200 当成整套服务可用。静态下载页可独立预览：

```sh
python3 -m http.server 8868 --bind 127.0.0.1 --directory app-download/dist
```

该预览持续运行，不自动按时间退出。端口冲突时先识别已有服务，不随意结束用户进程。公开入口还需分层核对 DNS、证书、HTTPS、代理和上游，502 与 DNS 解析失败属于不同阶段；不通过关闭 TLS 验证或修改系统网络来掩盖原因。

## 登录、回跳与冷启动

当前原生流程是 `POST /auth/native/start` 获取授权地址，系统浏览器进入 Account，网页返回聊天服务 `/auth/callback`，再以 `starlineworkbench://chat-auth` 回到 App，最后 `POST /auth/exchange` 换取设备会话。客户端保存 verifier 与 state，服务端票据为单次且有效一分钟；访问 token 不放在回跳 URL。

| 现象 | 优先定位 | 处理边界 |
| --- | --- | --- |
| `LOGIN_UNAVAILABLE` 或启动登录 503 | 聊天 OIDC 配置、discovery、上游可达性 | 不在客户端补写 secret 或伪造成功 |
| 打开了错误环境 | App base URL、issuer、public URL、构建参数 | Account 与聊天必须来自同一联调环境 |
| 网页完成但未回 App | scheme 注册、目标 app、系统授权会话、回调阶段 | 先确认回调到达位置，不重复消费 ticket |
| state 错误、过期或 ticket 401 | 是否原设备发起、是否重放、是否过期、是否取消 | 发起新的完整授权；保留原有有效会话 |
| 冷启动临时离线 | `/me` 网络错误或服务 503 | 客户端应保留凭据并允许恢复 |
| `/me` 返回 401 | 会话到期、退出或无效 | 重新登录，不把 token 复制到其他设备 |

设备会话有效期为 24 小时，没有永久登录或 refresh token。iOS 的 Debug 仅通过 `STARLINE_CHAT_BASE_URL` 显式覆盖，Release 使用正式地址；Android 通过 `-PstarlineChatBaseUrl` 编译，默认也是正式服务。本地 ticket 不能提交正式服务换票。iOS 系统“继续”提示是授权会话的一部分，应检查提示与实际表单，不能把它当作 App 登录失败后直接删掉。

Android 保存过真实授权和 force-stop 冷启动成功的历史证据；iOS 真实账号完整闭环及审核 iPad 仍待验收。定位问题时应针对失败平台重现，不能用另一平台的成功结果代替。对已有账号执行恢复测试须保留记忆与原会话数据，不把重新安装作为默认步骤。

## 验证码未到或第三方暂不可用

匿名邮箱码接口返回 `request_accepted` 表示受理，发送在持久验证码队列中执行；提供商接受与实际收件仍需分别确认。`DELIVERY_UNAVAILABLE` 先检查当前主源码的投递适配器：生产邮件为腾讯 SES，短信为阿里云；SMTP 只用于非生产备用，配置 SMTP 不能恢复生产邮件。旧副本的腾讯短信变量也不能用于当前服务。TLS 验证保持严格，等待重发冷却，避免重复请求导致难以判断当前有效验证码。

若注册先返回 CAPTCHA_REQUIRED／CAPTCHA_UNAVAILABLE，优先检查当前验证码门禁及四项 captcha 配置，不把它归为邮件失败。开发注册同样需要证明；旧 fixture 没有提交 captcha，不能据此认定后端注册损坏。若启动报 PII 密钥缺失、不匹配或旧数据迁移未批准，保留库与稳定密钥，先验证隔离备份和迁移方案，不通过删除标记、重置密钥或盲开审批修复。当前 Account 迁移已为 001–007，排查必须使用其当前维护仓库，见[完整配置参考](https://document.thestarline.cn/app/configuration-reference.md)与[故障处理手册](https://document.thestarline.cn/app/incident-runbooks.md)。

微信、QQ、支付宝配置存在不等于平台已启用或真实回调通过。星线智联 `0.1.0` 只有开发上传历史，尚未提审、发布，并按用户要求暂停。手机“暂时无法核对”可能包含 `wx.login`、网络或 inspect 错误，需恢复后检查分段日志；不能仅凭统一提示断言 AppSecret 或合法域名错误，也不能自动恢复暂停任务。

## 消息、贴纸与模型

401 先处理登录，403／404 核对成员和资源权限；已解除好友、屏蔽、离群或删除记录会改变可见范围。失败消息应通过原重试入口发送，避免新建另一条造成重复。只在已加载聊天摘要中搜索的结果不能代表完整历史不存在。

城市贴纸未知 `cityId` 或额外字段返回 400，缺少／损坏素材返回 503。城市目录来自内置 catalog，客户端不能提交文件路径。IP 城市为空可能是私网地址、代理未在精确 allowlist、离线库缺失或无法识别；先核对输入边界、素材版本与哈希，不扩大为信任所有代理。设备城市优先、IP 只是粗略兜底，空值时保留选择城市，不伪造位置。

实时位置的本机停采集与远端停止必须分别核对。当前 iOS 退出不会逐范围删除共享，session 注销或到期也不清理服务端最后位置；Android bestEffort 删除失败同样可能残留。不能以退出、通知消失或坐标不再变化证明其他成员已不可读；使用明确停止入口并确认远端状态，详见[故障处置](https://document.thestarline.cn/app/incident-runbooks.md)。

未配置 `CHAT_CRYPTO_NODE_BUNDLE` 时加密接口返回 503；加密核心测试或 WASM 构建成功不能证明聊天 UI 已全量采用 MLS，也不能声明旧消息、附件或新事均为端到端加密。记忆模型未就绪可返回 503，但本机自由记录和固定模板仍可使用；不要把模型不可用修成上传用户记忆到未知外部服务。

## 通话与通知

`CALL_MEDIA_UNAVAILABLE` 先核对 LiveKit 地址、密钥、媒体房间与网络连通。HTTP 业务接口响应正常不代表 WebRTC／TURN 端口可达；同房间连接测试也不代表双向声音和画面正常。排查时分别确认发起、振铃、接听、媒体、挂断与多设备竞争，保留双方时间线。

APNs 请求构造成功或提供商接受不等于设备收到来电。核对 Bundle／VoIP topic、开发或生产环境、签名能力、会话期限、锁屏与后台状态；不要记录推送 token 或私钥。watchOS 尚无独立版交付，现有通话 SDK 不支持手表，不能用手机接通结果声称手表可接听。

## 本机记忆、升级与资源异常

记忆索引和附件分别加密，密钥在设备安全存储。升级或迁移失败应保留原文件，不用空数据覆盖；卸载会丢失 App 私有数据，服务端备份不能恢复设备密钥。用户换机或卸载前，应按现有账号多因素授权流程主动转出；公开报告只描述结果，不收集导出正文。医疗健康模板只记录信息，没有自动复诊提醒、系统健康接入或跨设备同步。

模拟器内存异常先观察进程、物理内存、swap、日志和是否存在重复实例，不擅自关闭程序或修改系统配置。Android 预览启动器复用既有 AVD，保护阈值是资源异常条件，不是展示时限。界面截图停在旧帧时先区分绘制与业务状态，不清空数据强行“修复”。问题修复后只重跑相关验证并记录剩余边界；发布与审核状态依据新的正式回执更新，见[版本与分发状态](https://document.thestarline.cn/app/releases.md)。
