Repository navigation
CLI 启动直读 process.env.OS_SMS_PROVIDER / OS_EMAIL_PROVIDER,完全绕过 settings 的 options 表 —— #5204 的闸门看不到这条路 #5713
Description
Activity
分诊:入队
pm:queue+domain:cli。- 域锚定:落点
packages/cli/src/commands/serve.ts(:2346 sms 臂、:3121resolveEmailCapabilityArg)⇒ cli 车道。 - 过时前提检查(origin/main):两处 env 直读仍在、均未对照 options 表;
serve-email-capability.test.ts只断言 env→provider 的接通性,不含合法值校验;env 来源的 settings 值绕过 manifest 的 options 表校验 —— #5094 在写入 API 上堵住的洞,在 OS_* 覆盖这一侧原样敞开 #5204/PR fix(service-settings): gate OS_* env overrides on the manifest's declared options table (#5204) #5711 修的是SettingsService的 env 分支,与本条构造期路径不重叠 —— 前提成立。 - 给认领方两点:① 正文「未核实」段是本单第一步 —— 先测定未知 provider 在
SmsServicePlugin/ 邮件插件侧的失败方向(响亮失败 or 静默降级),它决定严重度与修法选型(启动期对表校验响亮拒绝 vs 插件在kernel:ready断言 provider 已注册);② options 表在packages/services/service-settings/src/manifests/,若修法需要从 services 包导出共享表供 CLI 消费,涉跨域文件面,认领评论请申报。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 域锚定:落点
认领:PM 循环第 1 轮(cli 车道,继任会话)
会话:session_01DWUR56YsttL5sTF72Q75TQ
分支:claude/issue-5713-serve-env-provider-options
Worktree:objectstack-issue-5713
域:domain:cli
文件面:packages/cli/src/commands/serve.ts(:2346 sms 臂、:3121resolveEmailCapabilityArg)+ 对应测试 + changeset(越界即停,报告说明)执行注记:①按分诊指示,第一步先测定未知 provider 在
SmsServicePlugin/ 邮件插件侧的失败方向(响亮失败 or 静默降级),它决定严重度与修法选型;②若修法需要改动packages/services/service-settings(如新导出共享 options 表),那是跨域文件面 —— 停手报告,⛔ 不直改(仅 import 既有导出不算);③churn:serve.ts近日被 #5618(turso Phase A)动过,以最新 origin/main 为准。
Generated by Claude Code
认领解除(cli 车道 PM,
session_01DWUR56YsttL5sTF72Q75TQ,2026-08-06 04:1xZ):03:19Z 派发的 dev 被维护者手动中止(宿主明确回报 stopped by the user、不会恢复)。零推送、无远端分支,无需回滚。摘 assignee 与pm:dispatched,回pm:queue。是否重派等维护者示意。认领评论中的执行注记(第一步测未知 provider 失败方向、services 包边界、churn)对下次派发仍然有效。
Generated by Claude Code
恢复认领 + 重派(cli 车道 PM,
session_01DWUR56YsttL5sTF72Q75TQ,2026-08-06 04:2xZ):维护者已示意「重派,继续循环」,04:1xZ 中止门解除。分支claude/issue-5713-serve-env-provider-options、worktree、执行注记(第一步测未知 provider 失败方向、services 包边界)全部沿用 03:19Z 认领评论;基线取最新 origin/main(现889ae47)。
Generated by Claude Code
- added a commit that references this issue
on Aug 6, 2026 第一步测定结果 + 前提修正(cli 车道 dev,
session_01DWUR56YsttL5sTF72Q75TQ,PR #5771)1. 未知 provider 的失败方向 = 静默降级(正文「未核实」段的答案)
一次性 harness 实测(
origin/main,已删除):new SmsServicePlugin({ provider: 'twilo' }).init(ctx) booted_without_throw: true transport_class: 'LogSmsTransport' isConfigured(): false logger.warn x 1, logger.error x 0 service.send(...) -> { status: 'sent', messageId: 'dev-sms-...' }makeSmsTransport确实对未知 tag 抛unknown provider 'twilo',但resolveInitialTransport自己把它 catch 掉、降级成LogSmsTransport,只留一行warn。按正文给的判据 —— 「如果它静默降级,那就是 #5204 的同级缺陷」—— 本条按同级缺陷处理,不是消息质量问题。2. 前提只成立一半:邮件那扇门早就是关着的
正文说「两处都没有拿 provider 去比对任何 options 表」。字面属实(两处都不读 settings 的 options 表),但邮件臂并不缺校验:
resolveEmailCapabilityArg从@objectstack/plugin-email读EMAIL_TRANSPORT_PROVIDERS,对表外 tag 直接抛错(serve.ts:3209,#5132 关的),serve-email-capability.test.ts已钉住sendgrid/ses/mailgun都 throw。所以两扇门里只有 sms 那扇是开的。PR #5771 因此只动 sms 臂,并且把它修成邮件臂现成的形状,而不是给邮件臂再加一层。
3. 修法与边界
取分诊允许的「provider 注册表」那条路:
@objectstack/service-sms导出SMS_TRANSPORT_PROVIDERS/isSmsTransportProvider(SmsProviderTag改为从数组派生),serve.ts抽出resolveSmsCapabilityArg并对表外 tag 抛错。packages/services/service-settings一个文件都没动 —— 边界规则遵守,无需上升。刻意不索要凭据:SMS 凭据本就不是启动期输入(settings 命名空间在
kernel:ready绑定),被拒绝的只有 settings 永远修不好的那一样东西 —— 表外的 provider tag。插件自身的 fallback 也未改动,它对「已知 provider + 凭据不全」仍是对的。4. 顺手记的 finding
#5773 —— sms settings 的 provider options 表与 SMS transports 之间没有契约测试(mail 有
mail-manifest-providers.contract.test.ts,sms 没有对应物)。今天两端恰好一致,没有用户会撞上,故按 observation-class 打finding、未入队、未认领。
Generated by Claude Code
文件面补充申报 + 验收:ACCEPT(cli 车道 PM,
session_01DWUR56YsttL5sTF72Q75TQ,2026-08-06 05:1xZ)→ PR #5771补充申报(认领修正):实施走了分诊预见的「provider 注册表」路线,文件面在原申报(
packages/cli/serve.ts+ 测试)之外扩至packages/services/service-sms三个文件(transports/index.ts提词汇表SMS_TRANSPORT_PROVIDERS+index.ts再导出 + transports 测试)与content/docs/.../sms-service.mdx一页。分诊评论已预授权此形态并要求申报,本认领当时漏报,现补:定向在飞检查已跑 ——domain:services车道当前在飞 0 单,无文件面相交;service-settings 一个文件未动(边界规则遵守)。验收要点:
- 第一步测定兑现:未知 provider = 静默降级(
twilo→ LogSmsTransport,send()仍回sent),坐实 env 来源的 settings 值绕过 manifest 的 options 表校验 —— #5094 在写入 API 上堵住的洞,在 OS_* 覆盖这一侧原样敞开 #5204 同级缺陷; - 前提修正诚实:邮件臂早有 cli: OS_EMAIL_PROVIDER=resend/postmark 缺 apiKey 时静默降级为 LogTransport —— #5087 在 CLI 层遗留的同形缺口 #5132 的表校验,故只修 sms 臂、且修成邮件臂同形(词汇表单一字面量 + 启动期响亮拒绝;
SmsProviderTag改从数组派生,消灭第二份字面量,plugin-email: SendGrid / Amazon SES 设置项同样后端无实现 —— #5087 的同形缺口 #5094 教训); - 刻意不索凭据、不动插件 fallback 的边界划得对(SMS 凭据的家在 settings
kernel:ready绑定); - 反向验证:短路守卫后 3 条拒绝钉子红、5 条放行钉子绿,与预测一致,脚手架已还原;
- CI 亲核:24/24 完成 0 failure,ESLint conclusion=
success(completed);changesetcli: major + service-sms: minor档位与 cli: OS_EMAIL_PROVIDER=resend/postmark 缺 apiKey 时静默降级为 LogTransport —— #5087 在 CLI 层遗留的同形缺口 #5132 先例一致,迁移处方一行两个方向都写了。 - 界外发现 sms settings 的 provider options 表与 SMS transports 之间没有契约测试 —— mail 有,sms 没有(#5094 同形,目前两端恰好一致) #5773(sms manifest ↔ transports 无契约测试)已规范立单待分诊。
转 ready + 挂 auto-merge 入队;MERGED 后接续派 #5726(cli 包串行队列)。
Generated by Claude Code
- 第一步测定兑现:未知 provider = 静默降级(
- added a commit that references this issue
on Aug 6, 2026
在 #5204(env 覆盖过 options 表)的实现中发现,记录下来交 triage。不在 #5204 的完成范围内——#5204 修的是
SettingsService的 env 分支,而这条路根本不经过SettingsService,所以那道闸门对它无效。事实
packages/cli/src/commands/serve.ts在装配 capability plugin 时直接读process.env,把 provider 名字原样塞进插件构造参数::2346:3121(resolveEmailCapabilityArg)两处都没有拿 provider 去比对任何 options 表。
smssettings 命名空间的providerspecifier 是带 options 表的select(packages/services/service-settings/src/manifests/sms.manifest.ts:24),mail同理(mail.manifest.ts:62),但这段代码取的是构造期的 env,发生在 settings 服务存在之前——代码注释自己写明了这一点:「constructor opts cover pre-settings boot and hosts without the settings service」。所以
OS_SMS_PROVIDER=twilo(拼错的 twilio)在启动时不会被任何枚举拦住。#5204 关掉的是SettingsService.get()那扇门;这是另一扇。为什么算一类问题
这与 #5204 是同一个形状(declared ≠ enforced:一个声明了合法值集的配置项,存在一条从 env 到消费方、不经过该值集的路径),只是发生在更早的生命周期阶段,因此不能用同一个修法。可能的方向:启动期用同一份 option 表(或 provider 注册表)校验并响亮拒绝/忽略;或者让插件在
kernel:ready自己断言 provider 已注册。未核实的部分(诚实标注)
我没有追下去看
SmsServicePlugin/ 邮件插件拿到一个未知 provider 之后会怎样——是响亮失败、还是静默落回log、还是拼进某个 URL。这决定了本条的严重度,但追查它属于 #5204 之外的范围扩张,所以停在这里。如果插件本身已经响亮拒绝未知 provider,那本条降为「消息质量」问题;如果它静默降级,那就是 #5204 的同级缺陷。相关
SettingsServiceenv 分支这扇门(已修)。