API key 读取容忍首尾引号与空白 - #20
Conversation
efbb006 to
03254d1
Compare
There was a problem hiding this comment.
感谢跟进,并按上次建议把 API-key 容错拆成了独立 PR。复核当前 head 03254d1 后,方向没有问题,但修复边界仍需调整:
- 清洗只发生在 settings facade:
_secret()仅位于config/settings.py。Browser Provider 仍通过EnvironmentReader.string()直接读取原始环境值,命令式 Provider auth 也没有复用该逻辑。 - 同一个 key 在不同消费者中结果不一致:我在当前 head 复现到
config.settings返回sk-test,而 Browser 返回sk-test"。这意味着 Main Chat/TTS 等路径可能恢复,但 Browser 或其他 Provider 仍会携带畸形 key 请求并继续得到 401。 - 测试没有覆盖真实故障边界:现有测试只向进程环境注入一个带引号的值,并断言单个 settings 字段;没有使用真实畸形
.env,也没有验证 Browser/Provider auth 与 settings 得到相同结果。
建议在 config.environment 建立明确的 secret/token 读取合同,让 settings、Browser 和 Provider auth 共用,同时保持“进程环境优先于 .env”的现有 authority 顺序。请补充实际 .env 与跨消费者一致性测试;完成后重新请求 review 即可。
1. 拆出 API key 容错改动(revert 60164e1,见 f6d0e06,移交 Code-Amadeus#20) 2. test_profile_contract 读取 pyproject 显式 encoding="utf-8"(CP936 兼容) 3. CI 安装 uv==0.12.8,resolver smoke 不再被静默跳过;补输出目录 mkdir 4. verify_python_environment 提取 PROFILE_TIER_IMPORTS 阶梯映射, 新增 vad profile(L1+L2+L3);--profile choices 由映射生成防漂移; 阶梯契约测试冻结严格前缀链 5. asr/manager 新增公开 vad_status()(ready/fallback/degraded 三态), runtime_status 投影 snapshot["vad"]/["vad_degraded"], readiness 在 vad=="degraded" 时判 False(L2 fallback 保持 ready) 文档同步:README 梯级验证命令、locks README 验证阶梯说明。
1. 拆出 API key 容错改动(revert 60164e1,见 f6d0e06,移交 Code-Amadeus#20) 2. test_profile_contract 读取 pyproject 显式 encoding="utf-8"(CP936 兼容) 3. CI 安装 uv==0.12.8,resolver smoke 不再被静默跳过;补输出目录 mkdir 4. verify_python_environment 提取 PROFILE_TIER_IMPORTS 阶梯映射, 新增 vad profile(L1+L2+L3);--profile choices 由映射生成防漂移; 阶梯契约测试冻结严格前缀链 5. asr/manager 新增公开 vad_status()(ready/fallback/degraded 三态), runtime_status 投影 snapshot["vad"]/["vad_degraded"], readiness 在 vad=="degraded" 时判 False(L2 fallback 保持 ready) 文档同步:README 梯级验证命令、locks README 验证阶梯说明。
1. 拆出 API key 容错改动(revert 60164e1,见 f6d0e06,移交 Code-Amadeus#20) 2. test_profile_contract 读取 pyproject 显式 encoding="utf-8"(CP936 兼容) 3. CI 安装 uv==0.12.8,resolver smoke 不再被静默跳过;补输出目录 mkdir 4. verify_python_environment 提取 PROFILE_TIER_IMPORTS 阶梯映射, 新增 vad profile(L1+L2+L3);--profile choices 由映射生成防漂移; 阶梯契约测试冻结严格前缀链 5. asr/manager 新增公开 vad_status()(ready/fallback/degraded 三态), runtime_status 投影 snapshot["vad"]/["vad_degraded"], readiness 在 vad=="degraded" 时判 False(L2 fallback 保持 ready) 文档同步:README 梯级验证命令、locks README 验证阶梯说明。
Lucas1479
left a comment
There was a problem hiding this comment.
复核当前 head 03254d1。这个分支在上一轮 review 后没有新提交,统一 secret 读取边界仍未闭合。
我再次复现了跨消费者不一致:给 DEEPSEEK_API_KEY 注入带首尾空白/引号的值后,config.settings.DEEPSEEK_API_KEY 得到清洗后的 sk-test123,而 server.browser_branch_planner._env("DEEPSEEK_API_KEY") 仍返回原始的带引号值。Codex command auth 的 tools/codex_provider_auth.py::provider_token() 也维护着另一套独立读取/strip 逻辑,没有复用本 PR 的合同。因此 settings 路径可能恢复,但 Browser 或 Provider auth 仍会发送畸形 token 并继续得到 401。
请将 secret/token 解析下沉到 config.environment 的单一读取合同,并让 settings、Browser 与 Provider command auth 共享它,同时保持“进程环境优先于项目 .env”的既有 authority 顺序。测试需要覆盖:
- 真实畸形 .env,而不只是向进程环境注入值;
- 进程环境覆盖 .env 的优先级;
- settings、Browser、Provider auth 对同一个 key 得到完全相同的值;
- 明确定义成对引号与孤立引号的处理规则,避免当前连续 strip() 意外改写合法 token。
完成后请 rebase 当前 main、重跑 CI,再请求 review。
.env 中 key 末尾多一个引号会导致 401 鉴权失败且难以定位。 新增 _secret() 读取器:DEEPSEEK/OPENAI/GEMINI/TTS/MIMO/ASR 六个 key 统一去除首尾空白与成对引号。
回应 PR Code-Amadeus#20 两轮评审:清洗此前只存在于 settings._secret() 一个 facade,Browser(browser_branch_planner._env)与 Codex provider auth (provider_token)各自裸读原始环境值,同一 key 三方结果不一致, 畸形 key 在 Browser/Provider 路径继续 401。 - config.environment 新增 secret_value()(纯函数,单一规范化点)与 EnvironmentReader.secret()(走既有 _register/_raw 链,继承进程环境 优先于 .env 的 authority 顺序与 alias 处理) - 规则:剥首尾空白 → 首尾引号字符各剥一层(成对或孤立,孤立引号是 常见 .env 手滑)→ 再剥空白;内部引号永不触碰(my"pass"word 原样)。 与旧 chained strip 的差异:每侧最多一层,保留内层结构。已接受的 trade-off:真以引号结尾的合法 token 会被改写(真实 key 不以引号 开头/结尾,而畸形 key 的代价是不透明 401) - settings._secret 委托 _ENV.secret;browser 新增 _secret 并替换 6 处 key 读取点(共享同一单例 reader);provider_token 清洗段委托 secret_value,--env-file 参数化读取链有意保留(Codex bridge 显式 输入,非项目 .env),空/空白进程值回退 env_file 的边界写入 docstring - 测试重写:规则 9 例表驱动;真实畸形 .env 三方一致;进程值覆盖三方 一致;provider_token authority 顺序与空白回退边界
03254d1 to
f23af52
Compare
|
两轮评审的统一读取合同已闭合(commit 修复:
引号规则(docstring + 测试钉死):剥首尾空白 → 首尾引号字符各剥一层(成对或孤立——孤立引号正是常见 .env 手滑,如评审复现的 测试(评审 4 条全覆盖):
本地:secret 相关 4 + codex provider 既有 6 passed,browser 相关 18 passed,ruff 通过。已全局核查无其他 API key 直接读取点。 |
问题
.env中 API key 末尾多一个引号(例如复制粘贴时带上的)会让鉴权串变成畸形值,表现为 401 Unauthorized,报错完全不会指向引号这个原因,
排查成本很高。
修复
config/settings.py新增_secret()读取器,六个 key(DEEPSEEK / OPENAI / GEMINI / TTS / MIMO / ASR)统一去除首尾空白与
成对引号后使用。
测试
tests/test_secret_parsing.py:带引号+空白的 key 经 settings 读取后等于干净值。
说明
该改动原在 #16 中,按评审意见拆出为独立 PR(与依赖分层无共同根因)。