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

No one assigned

    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