feat(connectors): ADR-0096 — provider-bound declarative connector instances (#2977)#2994
Merged
Merged
Conversation
…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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 99 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
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
This was referenced Jul 16, 2026
Merged
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.
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 aprovider(an installed generic executor) and the automation service materializes it into a live connector at boot, reusing the ADR-0023/0024 generator APIs verbatim.What (per the ADR task breakdown D0–D7)
@objectstack/spec).ConnectorSchemagainsprovider/providerConfig/auth;authenticationnow defaults to{ type: 'none' }(loosening, non-breaking).ConnectorInstanceAuthSchemais thecredentialRef-based instance auth — structurally no inline-secret field.DeclarativeConnectorEntrySchema(used bystack.zod.ts) rejects inline secrets, orphanproviderConfig/auth, and authoredactions/triggerson a provider-bound entry (§5). Newintegration/connector-provider.tsdefines the provider-factory contract as pure types.registerConnectorProvider/getConnectorProvider;registerConnectoris origin-tagged.credentialRef.service-automationresolves each provider-bound entry instart()(a throw there is fatal to bootstrap under bothLiteKernelandObjectKernel, unlike a swallowedkernel:readyhook).credentialRefresolves via a pluggableCredentialResolver; the open-tier default reads env vars.connector-rest/connector-openapi/connector-mcpeach export acreate*ProviderFactoryand register it ininit(). Plugin options are now optional (provider-only vs. also hand-wired). AddsConnectorOpenApiPlugin.StatusApiConnector(provider: 'rest') is materialized at boot and dispatched byShowcaseDeclarativeConnectorPingFlow;coverage.tsrecords it.none/api-key/basic/bearer),credentialReffrom env vars. Enterprise (ADR-0015): managed vaulting + OAuth2 refresh + per-tenant lifecycle (inject a vault-backedCredentialResolver, no change to the materialization path).Boot fails loudly for: unknown provider, invalid
providerConfig, unresolvablecredentialRef, name conflict.Verification
authenticationloosening and new exports break no consumer.connector_actiondispatch + every hard-fail case 12, provider factories 15, real-plugin integration (ConnectorRestPlugin + AutomationServicePlugin → declared instance materialized → dispatched withcredentialRefresolution) 2. Full suites for the 5 touched packages pass (spec 253 files, service-automation 26).validate+typecheck+ coverage test pass (the provider-boundStatusApiConnectorcomposes and validates; 22 flows).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