Skip to content

spec/cli: EmailServiceConfig.persist 声明了但没有载体 —— config.email.persist 永远到不了 EmailServicePlugin(#5307 的反向面,ADR-0049) #5447

Description

@os-zhuang

实施 #5307(补齐 EmailServiceConfigSchema 未声明的三个实读键)时,按该 issue「待确认」一节核实了反向的 persist 键。结论:它是 declared-but-unenforced,不是「在别处被消费」。本单只记录,#5307 的 PR 未动它。

实测(origin/main @ ed0d2aa)

config.email 在全仓只有一个读者:

grep -rn "config as any).email\|config\.email\b" --include=*.ts --exclude-dir=node_modules --exclude-dir=dist packages/ examples/ | grep -v "\.test\.ts"
# packages/cli/src/commands/serve.ts:2335:   (config as any).email ?? {},   <-- 唯一读者

packages/cli/src/commands/serve.tsresolveEmailCapabilityArg。它读的键(#5307 的复现命令):

cfgEmail.apiKey / appName / defaultFrom / defaultTemplateContext / options / provider / queueDelivery / retries

没有 cfgEmail.persist 该函数拼出的 options 对象里也没有 persist 字段。

为什么不是「在 plugin 侧被消费」

插件选项 persist 本身是活的:

  • packages/plugins/plugin-email/src/email-plugin.ts:81 声明 persist?: boolean
  • 同文件 482 行按它决定是否构造 EmailPersistence:
    const persistence: EmailPersistence | undefined = this.options.persist === false ? undefined : { ... }
  • 877 行还用它写诊断:sys_email persistence is disabled ('persist: false'), so a queued job would have no row to deliver

活的是插件构造参数。缺的是config.email.persist 到那个构造参数的那一段路——resolveEmailCapabilityArg 是唯一能走这一段的代码,而它不读这个键。settings 侧(Settings → Mail)也没有对应开关(email-plugin.mail-settings.test.tsmail-manifest-providers.contract.test.ts 均无 persist)。

影响

作者在 objectstack.config.ts 写:

email: { provider: 'smtp', persist: false, options: { host: 'smtp.acme.test' } }

EmailServiceConfig 标注 —— 类型通过,schema safeParse 通过,生成的参考文档 content/docs/references/system/email-config.mdx 正面写着「Persist to sys_email (default true)」。运行时依旧把每一封邮件写进 sys_email

这正是 Prime Directive #10 的 declared ≠ enforced:一个 PII 敏感部署以为自己关掉了邮件正文落库,其实没有。方向与 #5307 相反(那边是 spec 落后于运行时,这边是 spec 超前于运行时),所以拆成两单。

待决(ADR-0049 enforce-or-remove,两条路)

  1. enforce —— 在 resolveEmailCapabilityArg 里补 ...(cfgEmail.persist != null ? { persist: !!cfgEmail.persist } : {}),并配一个 OS_EMAIL_PERSIST_ENABLED(Prime Directive [WIP] Create a new release version #9 的布尔开关形状)。成本约一行 + 测试;把已声明的契约兑现。
  2. remove —— 从 EmailServiceConfigSchema 删掉 persist,走 spec-property-retirement 的整套纪律(ADR-0087 转换层 / liveness 台账 / 生成物)。代价高,而且删掉的是一个能力真实存在、只是没接线的键,直觉上不对。

倾向 1(enforce):插件侧已经完整实现并有诊断文案,缺的只是配置通路;删声明等于把一个真能力藏起来,只能通过直接 new EmailServicePlugin({ persist: false }) 触达——而 os serve 路径下作者根本没有这个入口。

关联

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions