Skip to content

spec: EmailProviderSchema 缺 'smtp',TSDoc 仍称 SMTP 不随 plugin-email 发布(#5087 落地后为假) #5104

Closed

Description

@os-zhuang

Blocked-by: #5087

由 #5087 的实现派生。修复落在 packages/spec,而 #5087 的 PR 被派发约束明确禁止碰 spec(同批 #5080 / #4001 正在 spec 内作业,避免撞车),故单独立单。

PM 分诊(勿在解除前派发):除上面的 Blocked-by 外,还需等 spec 车道空出 —— #5080 / #4001 在飞期间本单不可进,因为本单要动的生成物 content/docs/references/system/email-config.mdx 走 merge=os-regen,会静默吞掉一侧改动。详见本单评论。

现状

packages/spec/src/system/email-config.zod.ts:

  • EmailProviderSchema = z.enum(['log', 'resend', 'postmark']) —— 不含 'smtp'。
  • 同文件该 schema 的 TSDoc 明写:「Self-hosted SMTP is intentionally NOT shipped in plugin-email; apps that need SMTP register a custom IEmailTransport themselves and pass it via EmailServicePluginOptions.transport.」

#5087 落地后这两句都不再成立:@objectstack/plugin-email 已内置 SmtpTransport(ADR-0012,nodemailer 惰性加载),EmailServicePluginOptions.provider 与 CLI OS_EMAIL_PROVIDER 都接受 'smtp',并新增了 OS_EMAIL_SMTP_HOST / _PORT / _SECURE / _USER / _PASSWORD。

影响

  • 用 EmailServiceConfig 类型标注 objectstack.config.ts 的作者写 provider: 'smtp' 会拿到类型错误(运行时其实可用 —— CLI 直接读 config.email,不过这个 schema)。
  • 生成文档 content/docs/references/system/email-config.mdx 的 Allowed Values 仍只列三个值,注释也仍在劝人自带 transport。AI 作者读到的就是「SMTP 不受支持」—— 与运行时实际能力相反的 declared ≠ implemented。

建议改动

  1. EmailProviderSchema 增加 'smtp'(纯加值,非破坏性,不需要 ADR-0087 conversion/migration)。
  2. 重写该段 TSDoc:SMTP 由 plugin-email 内置(ADR-0012),nodemailer 为惰性 import。
  3. 顺带说明 EmailServiceConfig.options 对 provider: 'smtp' 承载连接参数(host / port / secure / user / password),与 OS_EMAIL_SMTP_* 一一对应。
  4. 按 AGENTS.md:pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated --fix,提交被证明过期的生成物(至少 email-config.mdx)。

验收

  • EmailServiceConfig 类型接受 provider: 'smtp';
  • 生成的 email-config 参考文档列出 smtp 并且不再宣称 SMTP 需要自带 transport;
  • spec 的生成物门禁全绿。

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 4, 2026
  2. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    分诊(PM 循环,邮件线):接下,但本轮不派发 —— 两条阻塞都还没解除。

    1. 等 plugin-email: 实现 SMTP transport —— 设置页可选 SMTP 但后端无实现 #5087 落地。现在就把 'smtp' 加进 EmailProviderSchema,会造成反方向的 declared ≠ implemented:spec 声明了一个 main 上还没有实现的 provider(SmtpTransport 目前只存在于 PR feat(plugin-email): SmtpTransport —— 真实 SMTP 投递、设置热替换、不再说谎的 mail/test (#5087) #5106 的分支上)。等 feat(plugin-email): SmtpTransport —— 真实 SMTP 投递、设置热替换、不再说谎的 mail/test (#5087) #5106 合入 main 之后再动,这一单就只是把契约追平既成事实。
    2. spec 车道当前不可进。E1(#5040 执行器契约面):IMetadataService.matchEndpoint? / generateOpenApi? + IHttpServer.setFallbackHandler? 可选契约方法与契约测试 #5080 与 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 两单正在 packages/spec 内作业(均 pm:dispatched),而本单要碰 email-config.zod.ts 加上生成物 content/docs/references/system/email-config.mdx。生成物走 .gitattributes 的 merge=os-regen 驱动——它会让 merge exit 0、零冲突标记,却静默丢掉一侧的改动,只有整体重新生成才暴露。三单同时在飞正是踩这个坑的标准姿势,所以严格串行。

    派发时会在派发词里带上:合并 origin/main 后整体重新生成(⛔ 绝不做文本合并),并断言兄弟单的条目与实现体都还在。

    维护者若认为这条可以先行,随时否决——但请注意上面第 1 条,提前落地会让 spec 短暂地承诺一个 main 上不存在的能力。


    Generated by Claude Code

  3. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    释放认领(PM 循环收口):会话 session_017MCKJaEomEqg4tvz4SzdNd 的邮件线已全部闭环,本单是唯一未派出的存量 —— 一直被 spec 车道串行压着:#4001(全仓 strict 收紧)仍在飞且活跃,与本单的 packages/spec 类型改动冲突面最大。我的会话即将结束循环,把认领放回,免得压死这单。

    给下一个认领者的现成派发包(#4001 闭环后即可用):


    Generated by Claude Code

  4. added
    priority:p1High: required for production / M2
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 4, 2026
  5. self-assigned this
    on Aug 4, 2026
  6. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    认领:PM 循环第 2 批补位(spec 车道,batch:5;维护者列为 v17 高价值 p1)
    会话:session_01ErbEDVAg1No9gdg1pgDAGB
    分支:claude/issue-5104-email-provider-types
    Worktree:objectstack-issue-5104
    域:domain:spec
    文件面:packages/spec/src/system/email-config.zod.ts(+ 测试)、生成物 content/docs/references/system/email-config.mdx(os-regen 路径)、spec 生成基线、.changeset/*.md

    派发注记(必须先厘清再动手):本单正文(缺 smtp,2026-08-04 04:39)与 12:31Z 释放认领评论的派发包(「transport 判别联合加 ses 分支」)互相矛盾 —— dev 第一步是在 origin/main 上实测 plugin-email 实际发布了哪些 transport(#5087 实落了什么、EmailProviderSchema 与 EmailConfigSchema 现状各缺什么),以实测为准对齐 spec 类型面,两边描述都不照抄;若实测发现 spec 需要承诺 main 上不存在的能力,按 premise_still_valid: false 停下回报。前任 PM 的串行顾虑(#4001/#5080 在飞)已解除 —— 两单均已闭环。

    早前分诊评论(05:00Z)的第 1 条阻塞(#5087 未落地)按 12:31Z 评论所述视为已解除,dev 复核为准。


    Generated by Claude Code

  7. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    验收:ACCEPT(PM 复核毕,PR #5308)

    复核依据(GitHub 实据):

    • 矛盾按实测裁决,正文胜出:origin/main 上 EMAIL_TRANSPORT_PROVIDERS = ['log','resend','postmark','smtp'],SesTransport 不存在且 ses 是带迁移处方的显式退役 tag、OS_EMAIL_PROVIDER=ses 实测抛错 —— 12:31Z 释放认领评论的「SES 支持已在 / EmailConfigSchema 判别联合」两条描述均与 main 相反,依「spec 不承诺 main 没有的能力」硬规则弃用。此更正在此公开记录,后续读该评论者请以本条为准;
    • 改动贴合正文范围:枚举加值(纯加性,免 conversion)、假 TSDoc 重写、provider/options 补 .describe()(顺带修了生成文档两格为空的问题)、mdx 窄重生成;运行时零改动(plugin-email 只新增测试文件);
    • 词表三边钉死:spec 侧 safeParse(避开 @ts-expect-error 退役 pin 在 packages/spec 里是幽灵检查:tsconfig 把 **/*.test.ts 排除出唯一的 tsc --noEmit #5286 幻检查陷阱)+ plugin-email 侧跨包契约测试(该包 tsconfig 不排除测试,编译期见证为真 —— 反向验证 A 项的 TS2322 即证)+ 既有 manifest 下拉框契约;三处反向验证全部按预判红;
    • 5 文件对账吻合;无新增可授权键,台账纪律不触发判断正确;mid-work 合并 fix(auth,verify)!: organization/create 判实际生效的 posture,降级部署不再产出无墙的组织 (#5261) #5294 零重叠已复跑全门。

    后续:PR #5308 进落地串行链第 6 位;#5307(同文件缺 queueDelivery/appName/defaultTemplateContext 三键 + persist 声明未读的镜像问题)已分诊入队,与本单串行(同文件 + 同生成物)。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch looppriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions