chore(plugins,services): declare providesServices on the remaining init-time providers (ADR-0116, #4131) - #4185
Merged
Conversation
…it-time providers (ADR-0116, #4131) ADR-0116 gave the kernel a declared ordering contract, but only ObjectQLPlugin and MetadataPlugin had declared what their init() registers — so the pre-Phase-1 ordering check could only name a provider for two plugins' worth of services. An audit of every plugin's init() body (brace-matched, comments stripped, each call classified by whether it sits inside a try/if) found 20 plugins that register a service on every path without declaring it. All 20 now declare providesServices. Purely additive: no ordering changes and no new failure modes — a providesServices entry only lets the kernel say WHO provides a service when it reports a misordering, and enriches the Phase-1 getService miss diagnostic. cache/queue/job needed a closer read before declaring, because they register the same service from several branches: every early-return branch plus the fallback registers it, so every path does. ADR-0116's rule that a conditionally registered service must never be declared is unchanged and was applied throughout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DQuJBNpwStpJvo3owBw2B
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 7 package(s): 46 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Jul 30, 2026
os-zhuang
marked this pull request as ready for review
July 30, 2026 14:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ADR-0116(#4163)落地后的第一步补齐。ADR 给了内核一套声明式排序契约,但当时只有
ObjectQLPlugin与MetadataPlugin声明了自己init()注册什么——所以 Phase 1 前置校验能"指名 provider"的覆盖面只有两个插件宽。做法:先审计,再声明
写了一个一次性审计脚本,对每个插件大括号配对提取
init()方法体(先剥离注释),再按调用是否位于try/if内分类。两个方法论上的坑值得记下来,因为第一版都踩了:)后直接跟{,漏掉了本仓库主流写法async init(ctx: PluginContext): Promise<void> {(中间隔着返回类型标注)——修正后覆盖从 10 个文件涨到 35 个。ctx.getService('manifest')会被当成真实依赖。A. 20 个 provider 补上声明(本 PR)
审计出 20 个插件在
init()里每条路径都会注册服务却没声明。全部补上providesServices:com.objectstack.authauth,tenancycom.objectstack.securitysecurity.permissions,security.rls,security.fieldMasker,security.bootstrapPermissionSets,security.fallbackPermissionSetcom.objectstack.server.honohttp.server,http-servercom.objectstack.service.messagingmessaging,notificationcom.objectstack.service-datasource-admindatasource-connection,datasource-adminemail/api-registry/file-storage/settings/realtime/mcp/i18n/analytics/cluster/sms/cache/queue/job/external-datasource/automation)纯增量:不改变任何排序,也不引入新的失败模式——
providesServices只让内核在报告顺序错误时能指名是谁提供该服务,并丰富 Phase 1 期间getServicemiss 的诊断信息。cache/queue/job三个下手前逐条读了控制流:它们从多个分支注册同名服务(若干提前 return 分支 + 兜底分支),确认每条路径都会注册,所以声明是诚实的。ADR-0116 那条"条件注册的服务绝不能声明"的规则未变,全程遵守(脚本也会把条件注册单独列出来提示不要声明)。B. 12 个消费方:不是活的暴露,本 PR 不动
同一次审计发现 12 个插件在
init()里同步硬取服务(其中 11 个取manifest)却没声明requiresServices。逐个查证后确认全都已经通过dependencies硬依赖被正确排序,没有一个是活的 #4085 类暴露。这里记一次我自己的误判修正:中途一度判定
plugin-auth与metadata-protocol"无任何依赖声明",是 grep 模式的问题——前者写作dependencies: string[] = [...](带类型标注),后者写作对象字面量的dependencies: [...](冒号非等号),都被漏掉了。这个结论反过来收窄了后续范围:对已声明硬依赖的消费方,
requiresServices价值有限(内核本来就会先报Dependency ... not found)。它真正有价值的地方是软依赖消费方——目前全仓只有AppPlugin一个。所以这批不做批量补,详情与清单见随后的 issue。验证
pnpm build71/71 通过(退出码直接捕获)。pnpm test:除@objectstack/plugin-audit外全部通过。该失败与本 PR 无关,且已定位到机制——audit-writers.test.ts的makeI18n()里有await import('@objectstack/core'),失败的localizes verb + object label to the workspace locale (zh-CN)是全文件第一个触发这次冷加载的用例(耗时 20094ms,撞上 20s testTimeout),紧随其后调用同一 helper 的用例只要 104ms(模块已缓存)。单独跑plugin-audit46/46 稳过。已另开 issue 记录,不在本 PR 处理——本 PR 的 diff 是 20 个其它文件的声明,该用例一个都没 import。🤖 Generated with Claude Code
https://claude.ai/code/session_014DQuJBNpwStpJvo3owBw2B
Generated by Claude Code