Skip to content

ADR-0076 D12 诚实能力层的三个洞:_fallback 标记不被识别、data 槽位不传实例、metadata 硬编码 degraded #3898

Description

@os-zhuang

ADR-0076 D12 / #2462 立的规矩是:自认是 stub / dev fake / degraded 的服务,discovery 必须照实报,永远不报 available,免得 AI agent 和 Console 把假能力当真能力。这个机制本身是对的(#3878 里的 analytics shim 就是靠它自报 degraded 的),但它目前有三个洞。

洞 1 —— 标记有三种,诚实层只认两种

packages/spec/src/api/discovery.zod.ts:129readServiceSelfInfo 识别:

  • svc[SERVICE_SELF_INFO_KEY]__serviceInfo
  • svc[SERVICE_DEV_MARKER_KEY](plugin-dev 的 _dev: true

packages/core/src/fallbacks/* 的内存兜底用的是第三种_fallback: true
memory-cache.ts:15memory-i18n.ts:126memory-job.ts:13memory-metadata.ts:24memory-queue.ts:14)。

readServiceSelfInfo 不认识它 → 返回 undefinedhttp-dispatcher.ts:888svcAvailable 落到默认分支 { status: 'available', handlerReady: true }

目前真正上线的是 i18npackages/runtime/src/app-plugin.ts:1173 在 stack 声明了 translations 但没装 I18nServicePlugin 时自动 registerService('i18n', createMemoryI18n())。于是 discovery 对外说"i18n 完全可用",实际是个进程内存实现。
(cache / queue / job 的 _fallback 版本目前只被 plugin-dev 消费,且它在外面套了 _dev: true,所以那三个槽位没有暴露;createMemoryMetadata 我没找到运行时注册点。)

全仓唯一消费 _fallback 的地方是一行日志:app-plugin.ts:1227

洞 2 —— data 槽位根本没把实例传进去

packages/runtime/src/http-dispatcher.ts:943

data: svcAvailable(routes.data, 'kernel'),

svcAvailable(route?, provider?, svc?) 的第三参是被检查的对象。这里省略了 → readServiceSelfInfo 从不被调用 → 无论槽里装的是谁(包括 plugin-dev 的 data stub)永远报 available / handlerReady: true

对比同一段里其它槽位都规规矩矩传了实例(auth/analytics/i18n/cache/...),这看起来是漏了一个参数,不是有意的。

洞 3 —— metadata 硬编码 degraded,方向反了

http-dispatcher.ts:942

metadata: { enabled: true, status: 'degraded' as const, handlerReady: true,
            route: routes.metadata, provider: 'kernel',
            message: 'In-memory registry; DB persistence pending' },

不看实例、恒为 degraded。所以装了真正的 MetadataManager(有 DB 持久化)的部署,discovery 依然对外说"内存注册表,DB 持久化待办"。前两个洞是"假的报成真的",这个是"真的报成假的" —— 同一张表里两个方向都不可信。

packages/metadata-protocol/src/protocol.ts:1393-1394 有一处对称问题:metadata / data 被硬编码成 status: 'available', provider: 'objectql'

为什么值得修

这张表不是装饰:

  • objectui/packages/react/src/hooks/useDiscovery.ts:190status === 'available' || 'degraded' 决定一个能力是否可用(它正确地拒绝了 stub,是唯一做了区分的消费者);
  • objectui/.../ConditionalAuthWrapper.tsx:114 直接读 services.auth.status === 'degraded' 改变渲染;
  • D12 的原始动机就是 AI agent 会读这张表来决定"我能不能用这个能力"。

一个报 available 的内存 i18n,和 #3878 里那个报 degraded 的 analytics shim 是同一类东西 —— 区别只是前者连自报都没做到

建议

  1. readServiceSelfInfo 增加对 _fallback: true 的归一化(→ status: 'degraded',配一句 message 指向对应的 ServicePlugin),与现有 _dev 分支同构;
  2. data: 补上第三参;
  3. metadata: 改为读实例(真 manager → available,内存兜底 → degraded),protocol.ts:1393 同步;
  4. 补一条门:遍历所有已知 fake(3 种标记)逐一注册进槽位,断言 discovery 不把任何一个报成 available —— 这类洞会随着新增兜底不断复发,靠人肉 review 拦不住。

关联:#3878#3891、ADR-0076 D12、#2462

核对于 origin/main @ 93f267f

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions