技术文档

服务运行、迁移与数据保护

星线 App 的运行涉及静态下载站、Account 身份服务、聊天服务,以及可选的模型、LiveKit 和 APNs。本文介绍源码中可确认的运行机制与维护原则,不提供生产凭据、服务器地址或私有部署目录。本次仅核对代码与历史文档,没有连接生产、读取数据库、执行迁移或演练恢复。

运行拓扑与边界

身份服务使用 Node.js 24、MySQL 8.4 和独立 Account/管理站来源;其代码、命令与迁移以当前维护仓库为准,App 工作树的 identity/ 不能当作现行部署模板。聊天服务使用 Node.js 24 与 SQLite,保存聊天、媒体、新事、设备会话和相关权限。下载介绍与公开技术文档属于静态内容,不需要数据库。App 内的记忆、个人任务和收藏存于设备,不因后端数据库备份而自动备份,也不因账号退出而删除。

组件 实际入口 持久数据或材料
身份服务 当前 Account 的 identity/server/main.ts;构建后 dist/server/main.js MySQL、稳定身份密钥、PII 密钥、私有 OIDC JWKS
聊天服务 chat-service/src/main.mjs SQLite、WAL、资料加密密钥、OIDC 客户端配置
下载与文档 app-download/dist/ 的发布产物 经过核对的静态文件与下载配置
通话与推送 LiveKit、APNs 服务端适配器 各自受保护配置与运行状态

配置变量用途见配置参考。生产身份服务会校验批准的 HTTPS 来源、身份主密钥、PII 密钥和 OIDC 签名材料。当前管理员通行密钥要求由环境开关控制,不能沿用旧副本“生产始终强制 true”的断言;应另核对 admin-policy.ts 与实际角色及认证方法。聊天生产启动要求固定批准的身份 issuer、HTTPS public URL 与 confidential 客户端。合成域名只适合测试构造,不能通过替换示例值绕过这些检查。

构建与持续运行

在当前 Account 仓库的隔离构建环境准备依赖与身份服务产物:

npm --prefix identity ci
npm --prefix identity/client ci
npm --prefix identity/client run build
npm --prefix identity run typecheck
npm --prefix identity run build

身份服务的源码入口 npm start 适合本地运行;生产宿主部署由进程管理器运行构建产物,并注入受保护配置。仓库还提供 identity/Dockerfile、identity/compose.yml、chat-service/Dockerfile 与 chat-service/compose.yml。聊天镜像从同一 Rust 源码构建 Node WASM 校验器,复制固定城市库与贴纸素材,并用非 root 用户运行。Compose 将数据库映射到持久卷,应用端口默认仅绑定宿主回环;容器代理要按实际网络选择可达地址。

构建命令可以在新环境准备镜像。第一条在当前 Account 仓库执行,第二条在 App 仓库执行,不能因相对路径相同而混用历史副本:

docker compose -f identity/compose.yml build
docker compose -f chat-service/compose.yml build

这一步只构建,不等于启动、发布或健康。镜像准备后先核对现有部署基线、配置链、持久卷、回滚产物和目标服务,再按维护窗口切换。共享 Account 有独立维护来源,不能用 App 工作区的旧副本覆盖其最新代码、Compose 或代理配置。进程应持续运行,不设置用于展示的时间上限;退出时优先使用 SIGTERM 或 SIGINT,源码会关闭定时任务和连接。

健康检查与业务探测

本地检查命令是:

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

身份健康接口执行 SELECT 1,因此检查了数据库连接。聊天 /health 只返回进程的 status: ok,没有逐项探测 OIDC、LiveKit、APNs、模型或数据库后续写入。公开入口还要分别验证 DNS、TLS、反向代理、Host、重定向及正确响应。生产身份接口有可信代理和 Host 约束,不应直接照搬开发 curl 判断生产不可用,也不应为了探测关闭约束。

业务探测使用专用合成账号,依次确认授权、换票、/me 恢复、双方收发、媒体权限与重开读取。通话还需两台真实设备跨网络验证,APNs 还需证明通知实际到达。只记录状态和关联请求信息,不保存 token、code、完整回跳 URL、验证码或用户内容。

迁移与版本切换

身份服务启动前自动调用迁移,也提供独立入口:

cd identity
npm run migrate

当前 Account MySqlStore.migrate() 顺序处理 001.sql 至 007.sql,随后执行 PII 与补列逻辑,表前缀取自配置;部分幂等迁移会先检查现有结构。生产要求 64 位十六进制 IDENTITY_PII_KEY。已有明文联系方式、flow 或 challenge 转换前需要验证备份,并明确设置 IDENTITY_PII_MIGRATION_APPROVED=1;数据库密钥标记不匹配时拒绝启动,不能通过审批开关绕过。修改迁移前应审查 SQL、在隔离副本验证,再记录执行结果;不能由命令返回 0 推断所有业务兼容。

聊天没有独立 npm run migrate,ChatDatabase 与各仓储在构造时创建表、补充列或重建特定表,企业、城市贴纸、原生授权等结构也在启动阶段处理。因此新旧进程不能同时对同一份数据库随意切换。

上线顺序应为:冻结当前基线与构建产物,取得一致性备份,在隔离环境验证迁移与读写,确认客户端兼容,停止旧实例后切换,再做健康与业务验收。仓库未提供通用自动降级脚本;数据库结构已变化时,单独退回旧镜像可能不兼容,回滚需要与已演练的数据快照一起设计。

备份与恢复原则

聊天 SQLite 启用 WAL、外键和 5 秒 busy timeout。备份应使用一致性快照机制,或在有序停止写入后保存数据库及其 WAL 所需状态;不能在服务写入时只随手复制主数据库。媒体 BLOB、新事及权限也属于数据集,不能只备份消息表。不要删除 WAL、手工改表或清空数据作为通用修复步骤。

身份 MySQL 与稳定 IDENTITY_SECRET、IDENTITY_PII_KEY、私有 OIDC 签名材料需要按受控流程配套保护。PII 密钥同时影响联系方式解密与查找摘要,缺失或换错会拒绝启动或无法使用旧数据。聊天的 CHAT_PROFILE_ENCRYPTION_KEY 未设置时从客户端密钥派生;更换这些值可能导致已存资料无法解密或手机号查找索引失效。密钥轮换必须先分析受影响数据与会话,实施迁移或撤销,不把“生成新密钥”当作无损恢复。具体隔离演练见故障处理与恢复。

备份应加密、限制访问、设置保留期并定期检查可恢复性。恢复先在隔离环境验证结构、读取、权限和合成写入;正式切换前停止旧实例,避免双写。身份恢复后根据风险撤销旧会话与授权。管理员恢复只能由获授权维护者在受保护环境审计处理,不提供公开提权或绕过验证入口。本机记忆密钥绑定设备安全存储,服务端备份不能重建丢失的设备密钥;换机前应由用户按 App 的授权转出流程处理。

日志、队列和保留

身份日志保留方法、去除查询参数的路径、请求 ID 与响应状态,脱敏 Cookie、Authorization 和 CSRF 头。当前验证码 worker 每 250 毫秒调用 processPendingDeliveries() 处理持久队列,多实例依靠数据库锁分配任务;不能沿用旧方法名当作当前运维接口。生产邮件为腾讯 SES,短信为阿里云,SMTP 仅非生产备用;“请求已受理”“提供商接受”和“用户已收件”是三个不同结果。聊天源码将未处理异常写入标准错误,目前没有完整集中指标面板,应在进程及代理层补充错误率、延迟、重启、磁盘和资源观测,并先过滤敏感信息。

身份维护入口为 npm run cleanup,按过期状态与 IDENTITY_AUDIT_RETENTION_DAYS 清理,审计默认保留 180 天。新事未发布媒体会在启动及每小时检查中清理过期孤立项。不能把这些清理误认为完整备份或容量治理。生产状态、发布与商店进度见版本与分发状态,按症状排查见故障定位。

Markdown 原文完整文档文本