Skip to content

chore(plugins,services): declare providesServices on the remaining init-time providers (ADR-0116, #4131) - #4185

Merged
os-zhuang merged 1 commit into
mainfrom
claude/plugin-ordering-convention-t9ylrz
Jul 30, 2026
Merged

chore(plugins,services): declare providesServices on the remaining init-time providers (ADR-0116, #4131)#4185
os-zhuang merged 1 commit into
mainfrom
claude/plugin-ordering-convention-t9ylrz

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

ADR-0116(#4163)落地后的第一步补齐。ADR 给了内核一套声明式排序契约,但当时只有 ObjectQLPluginMetadataPlugin 声明了自己 init() 注册什么——所以 Phase 1 前置校验能"指名 provider"的覆盖面只有两个插件宽。

做法:先审计,再声明

写了一个一次性审计脚本,对每个插件大括号配对提取 init() 方法体(先剥离注释),再按调用是否位于 try/if 内分类。两个方法论上的坑值得记下来,因为第一版都踩了:

  • 正则要求 ) 后直接跟 {,漏掉了本仓库主流写法 async init(ctx: PluginContext): Promise<void> {(中间隔着返回类型标注)——修正后覆盖从 10 个文件涨到 35 个。
  • 不剥离注释时,TSDoc 里的 ctx.getService('manifest') 会被当成真实依赖。

A. 20 个 provider 补上声明(本 PR)

审计出 20 个插件在 init()每条路径都会注册服务却没声明。全部补上 providesServices

插件声明
com.objectstack.authauth, tenancy
com.objectstack.securitysecurity.permissions, security.rls, security.fieldMasker, security.bootstrapPermissionSets, security.fallbackPermissionSet
com.objectstack.server.honohttp.server, http-server
com.objectstack.service.messagingmessaging, notification
com.objectstack.service-datasource-admindatasource-connection, datasource-admin
其余 15 个各自单一槽位(email / api-registry / file-storage / settings / realtime / mcp / i18n / analytics / cluster / sms / cache / queue / job / external-datasource / automation

纯增量:不改变任何排序,也不引入新的失败模式——providesServices 只让内核在报告顺序错误时能指名是谁提供该服务,并丰富 Phase 1 期间 getService miss 的诊断信息。

cache / queue / job 三个下手前逐条读了控制流:它们从多个分支注册同名服务(若干提前 return 分支 + 兜底分支),确认每条路径都会注册,所以声明是诚实的。ADR-0116 那条"条件注册的服务绝不能声明"的规则未变,全程遵守(脚本也会把条件注册单独列出来提示不要声明)。

B. 12 个消费方:不是活的暴露,本 PR 不动

同一次审计发现 12 个插件在 init() 里同步硬取服务(其中 11 个取 manifest)却没声明 requiresServices逐个查证后确认全都已经通过 dependencies 硬依赖被正确排序,没有一个是活的 #4085 类暴露。

这里记一次我自己的误判修正:中途一度判定 plugin-authmetadata-protocol "无任何依赖声明",是 grep 模式的问题——前者写作 dependencies: string[] = [...](带类型标注),后者写作对象字面量的 dependencies: [...](冒号非等号),都被漏掉了。

这个结论反过来收窄了后续范围:对已声明硬依赖的消费方,requiresServices 价值有限(内核本来就会先报 Dependency ... not found)。它真正有价值的地方是软依赖消费方——目前全仓只有 AppPlugin 一个。所以这批不做批量补,详情与清单见随后的 issue。

验证

  • 全仓 pnpm build 71/71 通过(退出码直接捕获)。
  • 全仓 pnpm test:除 @objectstack/plugin-audit 外全部通过。该失败与本 PR 无关,且已定位到机制——audit-writers.test.tsmakeI18n() 里有 await import('@objectstack/core'),失败的 localizes verb + object label to the workspace locale (zh-CN) 是全文件第一个触发这次冷加载的用例(耗时 20094ms,撞上 20s testTimeout),紧随其后调用同一 helper 的用例只要 104ms(模块已缓存)。单独跑 plugin-audit 46/46 稳过。已另开 issue 记录,不在本 PR 处理——本 PR 的 diff 是 20 个其它文件的声明,该用例一个都没 import。

🤖 Generated with Claude Code

https://claude.ai/code/session_014DQuJBNpwStpJvo3owBw2B


Generated by Claude Code

…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
@vercel

vercelBot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 30, 2026 2:27pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling size/m labels Jul 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 7 package(s): @objectstack/core, @objectstack/mcp, @objectstack/plugin-auth, @objectstack/plugin-email, @objectstack/plugin-hono-server, @objectstack/plugin-security, packages/services.

46 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx(via @objectstack/core, @objectstack/mcp)
  • content/docs/ai/agents.mdx(via @objectstack/mcp)
  • content/docs/ai/connect-mcp.mdx(via @objectstack/mcp)
  • content/docs/ai/index.mdx(via @objectstack/mcp)
  • content/docs/ai/knowledge-rag.mdx(via @objectstack/core)
  • content/docs/ai/natural-language-queries.mdx(via @objectstack/core, @objectstack/mcp)
  • content/docs/api/index.mdx(via @objectstack/mcp)
  • content/docs/automation/webhooks.mdx(via @objectstack/core, packages/services)
  • content/docs/concepts/north-star.mdx(via packages/core)
  • content/docs/deployment/cli.mdx(via @objectstack/plugin-auth, @objectstack/plugin-security)
  • content/docs/deployment/environment-variables.mdx(via @objectstack/mcp)
  • content/docs/deployment/migration-from-objectql.mdx(via @objectstack/core)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/plugin-auth)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/plugin-hono-server)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/core)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/examples.mdx(via @objectstack/core)
  • content/docs/kernel/runtime-services/index.mdx(via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via @objectstack/plugin-security)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/core, @objectstack/plugin-auth)
  • content/docs/kernel/services.mdx(via @objectstack/core)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authentication.mdx(via @objectstack/core, @objectstack/plugin-auth, @objectstack/plugin-hono-server)
  • content/docs/permissions/authorization.mdx(via packages/core, @objectstack/mcp, @objectstack/plugin-security)
  • content/docs/permissions/explain.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/sso.mdx(via @objectstack/plugin-auth)
  • content/docs/plugins/anatomy.mdx(via @objectstack/core)
  • content/docs/plugins/development.mdx(via @objectstack/core)
  • content/docs/plugins/index.mdx(via @objectstack/core, @objectstack/plugin-auth, @objectstack/plugin-hono-server, @objectstack/plugin-security)
  • content/docs/plugins/packages.mdx(via @objectstack/core, @objectstack/mcp, @objectstack/plugin-auth, @objectstack/plugin-email, @objectstack/plugin-hono-server, @objectstack/plugin-security, packages/services)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/core)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/core)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/core)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/core)
  • content/docs/protocol/knowledge.mdx(via @objectstack/mcp)
  • content/docs/releases/implementation-status.mdx(via @objectstack/core, @objectstack/mcp, @objectstack/plugin-auth, @objectstack/plugin-hono-server, @objectstack/plugin-security)
  • content/docs/releases/v12.mdx(via @objectstack/core)
  • content/docs/releases/v15.mdx(via @objectstack/core)
  • content/docs/releases/v16.mdx(via @objectstack/plugin-hono-server)
  • content/docs/releases/v9.mdx(via @objectstack/plugin-auth)
  • content/docs/ui/audience-based-interfaces.mdx(via packages/plugins/plugin-security)
  • content/docs/ui/dashboards.mdx(via @objectstack/plugin-security)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Labels

documentationImprovements or additions to documentationsize/mtooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude