Skip to content

feat(connector-openapi): resolve providerConfig.spec from a package-relative file path (#3016) - #3024

Merged
os-zhuang merged 2 commits into
mainfrom
claude/loving-sagan-wxr59d
Jul 16, 2026
Merged

feat(connector-openapi): resolve providerConfig.spec from a package-relative file path (#3016)#3024
os-zhuang merged 2 commits into
mainfrom
claude/loving-sagan-wxr59d

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Closes#3016(ADR-0096 后续项,承接 #2977 / #2994 / #3001)

背景

ADR-0096 的典型示例把 OpenAPI 实例写成 providerConfig: { spec: './billing-openapi.json' },但已落地的 openapi provider 工厂只接受内联文档对象或 http(s) URL,文件路径会被直接拒绝。本 PR 补全 spec 联合形态:内联对象 | 文件路径 | 远程 URL

设计

文件系统访问不放进 connector 包,而是由宿主注入能力(与 ADR-0096「provider 工厂只依赖 @objectstack/spec 纯类型」的结构保持一致):

  • @objectstack/specConnectorProviderContext 新增可选的 loadPackageFile(relativePath) 能力(纯类型,Prime Directive ✨ Set up Copilot instructions #2):按声明该 connector 的 stack/package 根目录解析相对路径并读取 UTF-8 文本;无文件系统的宿主(edge/browser)为 undefined。另更新 providerConfig 的 describe/TSDoc,自动生成的 references 文档会带上 spec 三种形态。
  • @objectstack/service-automation — 新增 packageRoot 插件选项(相对文件引用的解析基准,默认 process.cwd())与导出的 createPackageFileLoader(packageRoot):实现根目录约束(拒绝绝对路径与 .. 逃逸路径,含 Windows 盘符形式);node:fs/node:path 在闭包内懒加载,非 Node 宿主只有真正解引用文件时才会失败。materializeDeclaredConnectors 将该能力注入每个 provider 工厂的 ctx。读取/解析失败沿用既有 reconcile 策略:启动时 fatal,reload 时跳过该条目(旧连接器继续服务)。
  • @objectstack/connector-openapi — 非 URL 的字符串 spec 现在经 ctx.loadPackageFile 读取并按 OpenAPI JSON 解析;文件缺失/不可读、JSON 不可解析、宿主无文件访问能力各有清晰报错。
  • @objectstack/cliserve/dev 把项目目录(objectstack.config.ts 所在目录)作为 automation 服务的 packageRoot 传入,与 standalone sqlite 默认库的锚定方式一致。

Showcase 示例(第二个提交)

新增 StatusOpenApiConnector:provider: 'openapi' 声明式实例,OpenAPI 文档以包相对路径引用(src/system/connectors/status-openapi.json),由无参 ConnectorOpenApiPlugin(只贡献 provider 工厂)在启动时物化;getHealth 指向运行中的服务器自身 GET /api/v1/health,零外部依赖。与既有 rest 内联实例(StatusApiConnector)互补,并同步修正了 connectors: 集合还是「纯 descriptor」时代的过期注释与 coverage 说明。

实机验证:--fresh 随机端口启动 showcase,GET /api/v1/automation/connectors 列出 showcase_status_openapi(origin: declarative,action getHealth)。

测试

  • connector-openapi/openapi-provider.test.ts:文件路径 happy path(经注入的 loader)、loader 失败透传、JSON 不可解析、宿主无文件访问;既有内联/URL 用例不变。
  • service-automation/connector-materialization.test.ts:createPackageFileLoader 单测(happy path、绝对路径拒绝、.. 逃逸拒绝、缺失文件报错含解析后路径);物化策略集成测试(工厂收到可用的 loadPackageFile、缺失文件启动 fatal、逃逸路径启动 fatal、reload 软失败且旧连接器继续服务)。
  • pnpm turbo test(spec / service-automation / connector-openapi / example-showcase)全绿;@objectstack/cli build 通过。

其他

  • 更新 ADR-0096「Deliberate scope boundaries」中原先声明的 non-goal,记录本次交付方式。
  • 已按要求添加 changeset(4 个包 minor)。
  • 已知边界:file-path spec 的文件内容变化不会触发 reload 重物化(签名只覆盖条目本身,与 URL spec 行为一致)。

🤖 Generated with Claude Code

https://claude.ai/code/session_016eY7byWABTUPtJG7R2AEFU

…elative file path (#3016)
ADR-0096 follow-up: complete the spec union (inline object | file path |
remote URL) for the declarative openapi provider.
- spec: ConnectorProviderContext gains an optional host-injected
loadPackageFile capability (pure type)
- service-automation: packageRoot option + createPackageFileLoader with a
root-confinement guard (rejects absolute and ..-escaping paths; lazy
node:fs/node:path imports); capability injected into every provider ctx;
failures follow the reconcile policy (fatal at boot, soft on reload)
- connector-openapi: non-URL string specs are read via ctx.loadPackageFile
and parsed as OpenAPI JSON with clear errors
- cli: serve/dev anchor packageRoot to the objectstack.config.ts directory
- tests: file-path happy path, missing file (fatal at boot / skipped on
reload), traversal rejection; ADR-0096 scope-boundary note updated
Closes#3016
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016eY7byWABTUPtJG7R2AEFU
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specCanceledCanceledJul 16, 2026 6:13am

Request Review

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/cli, packages/connectors, packages/services, @objectstack/spec.

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

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/data-flow.mdx(via @objectstack/cli)
  • content/docs/api/environment-routing.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/cli, packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via packages/services, @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/backup-restore.mdx(via @objectstack/cli)
  • content/docs/deployment/self-hosting.mdx(via @objectstack/cli)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/cli, packages/services, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/permissions/authentication.mdx(via @objectstack/cli)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/cli, packages/services, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/kernel/realtime-protocol.mdx(via @objectstack/cli)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)

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.

- spec: providerConfig describe/TSDoc now documents the spec union
(inline object | package-relative file path | http(s) URL) so the
auto-generated references pick it up
- showcase: StatusOpenApiConnector — a provider: 'openapi' declarative
instance whose OpenAPI document is referenced as a package-relative
file path (src/system/connectors/status-openapi.json), materialized at
boot by an option-less ConnectorOpenApiPlugin; getHealth dispatches
GET /api/v1/health against the running server itself
- coverage notes + stale connectors: comment updated (the collection has
held provider-bound instances since ADR-0096, not only descriptors)
Verified: booted the showcase (--fresh, random port); GET
/api/v1/automation/connectors lists showcase_status_openapi
(origin: declarative) with the getHealth action.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016eY7byWABTUPtJG7R2AEFU
@github-actionsgithub-actionsBot added the dependencies Pull requests that update a dependency file label Jul 16, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 07:48
@os-zhuang
os-zhuang merged commit 10a570a into mainJul 16, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/loving-sagan-wxr59d branch July 16, 2026 07:48
baozhoutao pushed a commit that referenced this pull request Aug 7, 2026
Closes the two coverage holes the seed import left: nothing covered the AI
metadata kinds (agent/tool/skill, MCP surfaces) or the integration/system
services (declarative connectors, webhooks, jobs, email templates).
- areas/ai.json — agent/tool/skill metadata round-trip (variants matrix),
MCP HTTP transport both-sides (enabled 501/off + /mcp/skill public),
stdio fail-closed + RLS/FLS parity (from #3358 §9), run_action
ai.exposed gate + audit (15.1 §A9), validate_expression. Showcase ships
no AI seeds (ADR-0063) — fixture requirements declared explicitly.
- areas/integration-system.json — declarative connector lifecycle from the
15.1 §B rows (#2994/#3062 boot materialization, #3049 degraded husk +
atomic recovery, #3059 stdio default-deny allowlist, #3024 spec-path
escape rejection, #2985 descriptor-only boot audit, objectui#2563
designer picker), webhook live-fire + retired-trigger build gate, job
scheduled run, email-template variable rendering.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YD9f6FYyMraUWYeJf53V43
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(connector-openapi): declarative provider — resolve providerConfig.spec from a file path (ADR-0096 follow-up)

2 participants

@os-zhuang@claude