# 配置变量与启动校验参考

本页从配置加载器、服务入口、构建文件和适配器提取变量名、默认行为与失败条件，不使用环境文件中的实际值。Account 以其当前维护的主源码为准；App 独立工作树中的 `identity/` 是历史副本，不能作为现行生产配置模板。以下描述是源码契约，不是运行配置或业务可用性的回读结果。环境选择见[开发配置](https://document.thestarline.cn/app/development.md)，维护流程见[故障处理手册](https://document.thestarline.cn/app/incident-runbooks.md)。

## 配置的读取顺序与分类

Account 的 `npm start`、`dev`、`migrate` 会通过 Node 的环境文件参数加载配置；生产构建入口直接读取进程环境，Compose 还会增加容器环境和变量插值。聊天 `npm start` 本身不会自动加载本地配置文件，需由启动器或 Node 参数注入。对同名值应核对最终进程环境的来源，不能只看到某份文件就认定容器已使用它。检查时报告变量是否存在、格式是否合法、来源与版本，避免回显实际值。

| 分类 | 例子 | 处理方式 |
| --- | --- | --- |
| 服务端秘密 | 身份主密钥、PII 密钥、客户端 secret、云服务 secret、签名私钥 | 受保护系统注入；不进入仓库、App 包、日志或文档 |
| 稳定加密依赖 | `IDENTITY_SECRET`、`IDENTITY_PII_KEY`、`CHAT_PROFILE_ENCRYPTION_KEY` | 与数据版本一起备份；轮换前设计迁移，不能随意重建 |
| 标识与策略 | issuer、origin、client ID、topic、模板 ID、开关 | 不一定是秘密，仍需核对环境与变更影响 |
| 本机开发配置 | API 端口、Debug 地址、测试命名空间 | 仅用于隔离环境，不能冒充生产回执 |

本页用“未设置”描述没有默认值；不是建议将变量设置为空字符串。Account 多数变量用 `||` 取默认值，聊天多数使用 `??`，因此聊天的空字符串通常不会回退到默认值。所有布尔开关只有源码指定的精确字符串才启用，`1`、`TRUE` 与 `true` 不能随意互换。

## Account 基础与持久化

| 变量 | 默认或格式 | 必填条件与影响 |
| --- | --- | --- |
| `NODE_ENV` | 仅精确 `production` 进入生产分支，其他为 development | 必须显式核对模式，不能靠目录名称判断 |
| `IDENTITY_HOST` / `IDENTITY_PORT` | 本机 IPv4 回环 / `9100` | 容器通常由运行配置覆盖；端口转为 Number |
| `IDENTITY_DATABASE_URL` | 未设置 | 所有正常服务入口必需；指向 MySQL |
| `IDENTITY_DB_PREFIX` | 空前缀 | 仅字母、数字、下划线；改变它会切换表命名空间 |
| `IDENTITY_SECRET` | 空值，启动校验要求至少 32 字符 | 生产拒绝公开示例标记；保护协议材料与 HMAC |
| `IDENTITY_PII_KEY` | 64 位十六进制，解码后 32 字节 | 生产必需；已加密数据库在任何模式下均需匹配原密钥 |
| `IDENTITY_PII_MIGRATION_APPROVED` | 仅精确 `1` 表示已批准 | 有旧联系方式、flow 或 challenge 数据时，迁移前需验证备份并明确批准 |
| `IDENTITY_AUDIT_RETENTION_DAYS` | `180` | 供清理策略读取；修改前核对保留要求与实际清理任务 |
| `IDENTITY_RATE_LIMIT` | `20`，正安全整数 | 与固定 600 秒窗口配合；不是各业务独立限额的统一替代 |
| `IDENTITY_BOOTSTRAP_EMAIL` | 未设置 | 仅首次管理员初始化脚本读取；不是持续服务的登录凭据 |
| `IDENTITY_DB_PASSWORD` / `IDENTITY_DB_ROOT_PASSWORD` | 当前 Compose 必需的插值变量 | 分别用于应用数据库用户和数据库 root 初始化；属于秘密，不能以示例口令部署 |
| `IDENTITY_BIND_PORT` | 当前 Compose 默认 `9100` | 只改宿主映射，不改变容器内服务端口；不是 `IDENTITY_PORT` 的同义项 |

`PiiProtector.fromHex` 拒绝错误长度或非十六进制密钥。数据库保存密钥检查标记，缺密钥、错误密钥或迁移后残留不一致都会拒绝继续。当前迁移顺序为 `001.sql` 至 `007.sql`，随后执行 PII 与补列处理。迁移审批开关只表示维护流程已满足前置条件，不会替维护者自动备份，也不是修复错误密钥的方法。

## 来源、管理与协议

| 变量 | 默认行为 | 启动或运行约束 |
| --- | --- | --- |
| `IDENTITY_ORIGINS` | 开发允许本机 9100、9101 的两种回环来源；生产无默认列表 | 至少一个精确 origin；不得带路径；生产只允许批准的 Account 与管理站 HTTPS 主机 |
| `IDENTITY_ACCOUNT_ORIGIN` / `IDENTITY_OPEN_ORIGIN` | 开发为 localhost 的 9100 / 9101；生产为各自正式 HTTPS 来源 | 决定页面、协议及来源判断，需与代理和客户端一致 |
| `IDENTITY_WEBAUTHN_RP_ID` | 开发 `localhost`，生产为正式 Account 主机 | RP 与 origin 是不同字段，已有通行密钥不能任意迁移到其他 RP |
| `IDENTITY_TRUST_PROXY` | `false` | 逗号分隔的明确可信代理；拒绝 `*`，不能复制其他网络的配置 |
| `IDENTITY_OIDC_JWKS_FILE` | 开发可生成并加密持久化签名材料 | 生产必需稳定私有 JWKS；RSA、RS256、use=sig、kid，私钥至少 2048 位 |
| `IDENTITY_ADMIN_PASSKEY_REQUIRED` | 仅精确 `true` 启用 | 当前主源码不再硬编码生产必为 true；管理授权仍需按当前策略与服务端角色检查 |
| `IDENTITY_REAL_NAME_ENABLED` | 仅精确 `true` 启用 | 启用时要求可用 PII 保护器；开关不代表外部实名能力已验收 |
| `IDENTITY_DEV_API_PORT` | `9100` | 仅 Vite 开发代理使用，不改变生产服务监听端口 |
| `IDENTITY_PREVIEW_URL` | fixture 脚本默认本机 9100 HTTP | 仅该旧预览脚本读取；限制本机、非生产，不解决当前 captcha 契约差异 |

Account 会话 28800 秒、OTP 300 秒、验证事务 1800 秒、OTP 尝试 5 次、重发间隔 60 秒是当前加载器中的固定配置值，不能凭这些字段名推导存在对应环境变量。公开资料中的角色与通行密钥建议属于运维要求，实际可接受的认证方法需依据现行 `admin-policy.ts` 和目标会话验证。

## 验证码、人机验证与第三方身份

| 变量 | 默认及启用条件 | 缺失时的行为 |
| --- | --- | --- |
| `IDENTITY_DELIVERY` | 精确 `development` 选择开发投递，其余选择真实适配器 | 生产禁止开发适配器；真实配置缺失不模拟投递成功 |
| `TENCENT_SES_SECRET_ID` / `TENCENT_SES_SECRET_KEY` / `TENCENT_SES_TEMPLATE_ID` | 三项齐全，模板 ID 为正安全整数 | 当前生产邮件只接受此 SES 路径；SMTP 不作为生产回退 |
| `ALIBABA_CLOUD_ACCESS_KEY_ID` / `ALIBABA_CLOUD_ACCESS_KEY_SECRET` / `ALIYUN_SMS_SIGN_NAME` / `ALIYUN_SMS_TEMPLATE_CODE` | 四项齐全启用阿里云短信 | 无可用适配器时返回投递不可用；当前发送校验中国大陆手机号与六位验证码 |
| `SMTP_HOST` / `SMTP_FROM` / `SMTP_USER` / `SMTP_PASSWORD` | 常规 SMTP 要求四项；仅供非生产备用 | 即使四项齐全，生产邮件也不会使用 SMTP |
| `SMTP_PORT` / `SMTP_SECURE` | 普通端口默认 465；非精确 `false` 时 secure=true | 保持 TLS 验证；选择其他端口时要同时核对 TLS 模式 |
| `SMTP_LOCAL_SINK` | 精确 `true`；端口默认 9125，无认证和 TLS | 仅非生产回环；生产或外部主机直接拒绝 |
| `TENCENT_CAPTCHA_APP_ID` | 正整数形式、5–16 位十进制且为安全整数 | 公开配置返回 null 或验证不可用 |
| `TENCENT_CAPTCHA_APP_SECRET` / `TENCENT_CAPTCHA_SECRET_ID` / `TENCENT_CAPTCHA_SECRET_KEY` | 与有效 App ID 四项齐全 | 注册等受保护入口返回 CAPTCHA_UNAVAILABLE；不能靠开发投递绕过 |
| `WECHAT_APP_ID` / `WECHAT_APP_SECRET`、`QQ_APP_ID` / `QQ_APP_SECRET` | 各提供商成对配置 | configured 与后台启用、平台开通、真实回调是不同状态 |
| `ALIPAY_APP_ID` / `ALIPAY_PRIVATE_KEY` / `ALIPAY_PUBLIC_KEY` | 应用 ID、RSA2 私钥与平台公钥 | 不完整时不能据此启用支付宝身份验证 |

当前 SES 模板参数为带三位分组显示的验证码，发件地址由适配器代码固定，不由 `SMTP_FROM` 控制。旧副本中的 `TENCENT_SMS_*` 不是现行主源码的短信配置。当前开发注册同样有人机验证门禁；仅 `env=test` 的测试构造允许专用注入或隔离跳过，正常服务没有通用免验证开关。

微信小程序还有 `WECHAT_MINI_APP_ID`、`WECHAT_MINI_APP_SECRET`，以及 `IDENTITY_WECHAT_MINI_ENABLED`、`IDENTITY_WECHAT_MINI_PUBLISHED`、`IDENTITY_WECHAT_MINI_LAUNCH_ENABLED`、`IDENTITY_WECHAT_MINI_VERIFICATION_ENABLED` 四个精确 `true` 开关。配置完成、预览验证、正式 URL Link 与公开入口分别检查；小程序 ID 还不能与网页微信提供商 ID 混用。配置中的 published 不等于官方发布回执，当前暂停要求不因改配置而自动解除。

## 聊天、媒体与可选依赖

| 变量 | 默认与校验 | 所属能力 |
| --- | --- | --- |
| `CHAT_HOST` / `CHAT_PORT` / `CHAT_DATABASE_PATH` | 本机回环 / 4210 / `./data/chat.sqlite` | 路径相对工作目录；确认持久卷映射，避免误建空库 |
| `CHAT_ISSUER_URL` / `CHAT_PUBLIC_URL` | 未设置；生产要求批准的正式 issuer 与 HTTPS public URL | OIDC discovery、授权回调与站点身份 |
| `CHAT_CLIENT_ID` / `CHAT_CLIENT_SECRET` | 未设置；生产要求存在，secret 至少 24 字符 | confidential 客户端；不放入原生 App |
| `CHAT_PROFILE_ENCRYPTION_KEY` | 未设置则使用客户端 secret 作为派生输入 | 资料联系电话加密；轮换可能影响旧数据解密 |
| `CHAT_CRYPTO_NODE_BUNDLE` | 未设置则校验器为 null | 设置时要求导出两个 MLS 校验函数，错误文件会导致启动异常 |
| `CHAT_TRUST_PROXY_ALLOWLIST` | 无可信代理；逗号分隔并去空白 | 仅合法地址或 CIDR；IP 城市不信任任意转发头 |
| `CHAT_IP_CITY_DATABASE_DIR` | 仓库固定城市库目录 | 需匹配版本与摘要；缺库、坏库返回空城市，不制造位置 |
| `CHAT_MEMORY_MODEL_URL` / `CHAT_MEMORY_MODEL` | 非生产默认本机 11434 HTTP 与 `qwen2.5vl:7b`；生产未设置 | 识别接口；请求文字发送给配置模型，不形成云同步 |
| `LIVEKIT_URL` / `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET` | 未设置 | 通话媒体必需；健康接口不验证这三项是否真实可用 |
| `APNS_TEAM_ID` / `APNS_KEY_ID` / `APNS_KEY_PATH` / `APNS_VOIP_TOPIC` | 未设置；四项齐全才可发送 | 配置路径读取失败或私钥格式错误可在启动时报错 |
| `APNS_ENVIRONMENT` | 精确 `sandbox` 才走测试 APNs，其余走生产 | 与 App 签名环境匹配，不能以默认值推断配置正确 |

`cityStickerDirectory`、媒体房间清理间隔和 APNs 测试 origin 是测试构造参数，并没有同名环境变量入口。聊天设备 session 默认 24 小时也没有公开环境变量或 refresh 路由。完整约束见[限制与错误](https://document.thestarline.cn/app/limits-and-errors.md)。

## 原生构建差异与核对方法

iOS `STARLINE_CHAT_BASE_URL` 仅 Debug 读取，接受 HTTPS 或 HTTP 回环，拒绝用户名密码、查询与 fragment；Release 忽略覆盖。iOS 工程的 `APNS_ENVIRONMENT` 在 Debug 为 development、Release 为 production，服务端测试环境字符串却是 sandbox，二者不得直接照抄。Android `starlineChatBaseUrl` 编译为 `BuildConfig.CHAT_BASE_URL`，Debug 允许本地明文 API，Release 清单禁止；`NativeAuth.kt` 两种构建均只信任正式 Account HTTPS，没有本地授权例外。`ANDROID_HOME`、`JAVA_HOME`、`ANDROID_NDK_HOME`、`CARGO` 是工具链定位配置，不能当作产品服务变量。文档生成器的 `STARLINE_DOCS_NODE_MODULES` 仅增加 Markdown 构建依赖的查找位置，不影响 App、Account 或聊天运行配置。

只查代码中的声明可使用：

```sh
rg -n 'env\.[A-Z_]+|process\.env' identity/server identity/client/vite.config.ts
rg -n 'environment\.[A-Z_]+|production' chat-service/src/main.mjs
rg -n 'STARLINE_CHAT_BASE_URL|#if DEBUG' ios-app/Sources/Features/Chat/ChatAPI.swift
rg -n 'gradleProperty|versionName|versionCode' android-app/app/build.gradle.kts
```

第一条应在 Account 当前源码仓库执行，其余在 App 仓库执行。不要把搜索范围扩展到环境文件、运行目录或秘密材料。变更结果按[测试矩阵](https://document.thestarline.cn/app/qa-matrix.md)验证，再按[发行清单](https://document.thestarline.cn/app/release-checklist.md)记录实际交付阶段。
