Skip to content

feat(connectors): ADR-0096 — provider-bound declarative connector instances (#2977)#2994

Merged
os-zhuang merged 2 commits into
mainfrom
claude/adr-0096-declarative-connectors-gcmemn
Jul 16, 2026
Merged

feat(connectors): ADR-0096 — provider-bound declarative connector instances (#2977)#2994
os-zhuang merged 2 commits into
mainfrom
claude/adr-0096-declarative-connectors-gcmemn

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Implements ADR-0096 — closes the last mile from connectors: stack metadata to a live, dispatchable connector. Tracking: #2977.

Why

Declarative connectors: entries were descriptor-only (#2612): registered as metadata but never reaching the automation connector registry — the platform's one dead metadata surface (plausible, validated, dead). For a platform whose goal is AI-built enterprise systems out of metadata, integrations must be expressible and executable as metadata. This adds only the last mile: an entry may name a provider (an installed generic executor) and the automation service materializes it into a live connector at boot, reusing the ADR-0023/0024 generator APIs verbatim.

connectors: [{
  name: 'billing',
  provider: 'openapi',                                  // ← materialized at boot
  providerConfig: { spec: '…', baseUrl: 'https://…' },
  auth: { type: 'bearer', credentialRef: 'billing_token' },  // reference, never inline
}]

What (per the ADR task breakdown D0–D7)

  • D1 — Schema (@objectstack/spec). ConnectorSchema gains provider / providerConfig / auth; authentication now defaults to { type: 'none' } (loosening, non-breaking). ConnectorInstanceAuthSchema is the credentialRef-based instance auth — structurally no inline-secret field. DeclarativeConnectorEntrySchema (used by stack.zod.ts) rejects inline secrets, orphan providerConfig/auth, and authored actions/triggers on a provider-bound entry (§5). New integration/connector-provider.ts defines the provider-factory contract as pure types.
  • D2 — Provider registry. The engine adds registerConnectorProvider / getConnectorProvider; registerConnector is origin-tagged.
  • D3 — Boot materialization + credentialRef. service-automation resolves each provider-bound entry in start() (a throw there is fatal to bootstrap under both LiteKernel and ObjectKernel, unlike a swallowed kernel:ready hook). credentialRef resolves via a pluggable CredentialResolver; the open-tier default reads env vars.
  • D4 — Conflict rule. A declarative-vs-plugin name collision throws — no silent precedence.
  • D5 — Providers. connector-rest / connector-openapi / connector-mcp each export a create*ProviderFactory and register it in init(). Plugin options are now optional (provider-only vs. also hand-wired). Adds ConnectorOpenApiPlugin.
  • D6 — Showcase. StatusApiConnector (provider: 'rest') is materialized at boot and dispatched by ShowcaseDeclarativeConnectorPingFlow; coverage.ts records it.
  • D7 — ADR + tiering. ADR flipped Proposed → Accepted with an as-built section. Open tier: static auth (none/api-key/basic/bearer), credentialRef from env vars. Enterprise (ADR-0015): managed vaulting + OAuth2 refresh + per-tenant lifecycle (inject a vault-backed CredentialResolver, no change to the materialization path).

Boot fails loudly for: unknown provider, invalid providerConfig, unresolvable credentialRef, name conflict.

Verification

  • Full monorepo build green (70/70 tasks) — the authentication loosening and new exports break no consumer.
  • Tests: schema 13, materialization incl. end-to-end connector_action dispatch + every hard-fail case 12, provider factories 15, real-plugin integration (ConnectorRestPlugin + AutomationServicePlugin → declared instance materialized → dispatched with credentialRef resolution) 2. Full suites for the 5 touched packages pass (spec 253 files, service-automation 26).
  • Showcase validate + typecheck + coverage test pass (the provider-bound StatusApiConnector composes and validates; 22 flows).

Note: the full-app live browser boot was blocked by an environment version-skew in the resolved objectstack CLI shim (an older dev command), not by this change. The identical runtime path — real ConnectorRestPlugin registers the rest provider, the automation service materializes a declared instance, and a flow connector_action dispatches it — is proven by the integration test, and objectstack validate composes the full showcase stack.

Compatibility

Additive/loosening only — no removed or renamed authorable keys, so no migration or tombstone. Existing descriptor-only entries (no provider) are unaffected; the boot audit warning still applies to them. Changeset included.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs


Generated by Claude Code

…tances (#2977)

Declarative `connectors:` stack entries were descriptor-only (#2612): registered
as metadata but never dispatchable — the platform's one dead metadata surface. An
entry may now name a `provider` (an installed generic executor: openapi / mcp /
rest) and the automation service materializes it into a live, dispatchable
connector at boot, indistinguishable from a hand-written one. AI can wire an
integration as pure metadata and a flow `connector_action` calls it end-to-end.

Spec (@objectstack/spec):
- ConnectorSchema gains `provider`, `providerConfig`, `auth`; `authentication`
  now defaults to `{ type: 'none' }` (loosening — existing connectors unaffected).
- ConnectorInstanceAuthSchema: credentialRef-based instance auth (no inline
  secrets); ResolvedConnectorAuth for the resolved static subset.
- DeclarativeConnectorEntrySchema (used by stack.zod) rejects inline secrets,
  orphan providerConfig/auth, and authored actions/triggers on a provider-bound
  entry (§5). New connector-provider.ts defines the provider-factory contract as
  pure types (plugins depend only on the spec).

Engine + boot (@objectstack/service-automation):
- Connector-provider registry (registerConnectorProvider/getConnectorProvider);
  registerConnector is origin-tagged so a declarative/plugin name collision
  throws instead of silently replacing (§4 — no silent precedence).
- materializeDeclaredConnectors() runs in start() (fatal to bootstrap under both
  LiteKernel and ObjectKernel). credentialRef resolves via a pluggable
  CredentialResolver; the open-tier default reads environment variables. Boot
  fails loudly for unknown provider / invalid providerConfig / unresolvable
  credentialRef / name conflict.

Providers (connector-rest / connector-openapi / connector-mcp):
- Each exports a create*ProviderFactory and registers it in the plugin's init().
  Plugin options are now optional: with none the plugin contributes only the
  provider factory; with instance options it also registers a hand-wired
  connector (back-compat). Adds ConnectorOpenApiPlugin.

Showcase: StatusApiConnector (provider: 'rest') is materialized at boot and
dispatched by ShowcaseDeclarativeConnectorPingFlow; coverage.ts records it.

ADR-0096 flipped Proposed → Accepted with an as-built section + open/enterprise
line. Tests: schema (13), materialization incl. end-to-end dispatch + all
hard-fail cases (12), provider factories (15), real-plugin integration (2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 16, 2026 1:55am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/xl labels Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

99 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 @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @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/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/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/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/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/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via 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/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 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/spec)
  • 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/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.

The `check:api-surface` gate (run in the TypeScript Type Check job) flagged the
13 new `@objectstack/spec` exports added by ADR-0096 as an intentional additive
API change (0 breaking, 13 added): the ConnectorInstance* auth schemas,
ResolvedConnectorAuth, the ConnectorProvider* / ConnectorMaterialization*
contract, and DeclarativeConnectorEntry(Schema). Regenerate the committed
snapshot. spec-changes.json and the upgrade guide are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
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/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants