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.auth auth, tenancy
com.objectstack.security security.permissions, security.rls, security.fieldMasker, security.bootstrapPermissionSets, security.fallbackPermissionSet
com.objectstack.server.hono http.server, http-server
com.objectstack.service.messaging messaging, notification
com.objectstack.service-datasource-admin datasource-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

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 30, 2026 2:27pm

Request Review

@github-actions github-actions Bot 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 free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants