Skip to content

Commit 3238750

Browse files
feat(spec)!: oauth2 and app-credential connector instance auth; the runtime oauth2 variant retired (ADR-0143 S0) (#28213)
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm <!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6Jao4xopuwRpgz7BBJKw6iZpKi)_ Fixes #28137 Clause-②: yes (narrowing) Metadata-protocol: narrowed Skills-docs: follow-up #28226 ## 维护者速读 - 改了什么:连接器实例的 `auth` 新增两种需要换取令牌的类型,`oauth2`(授权码 / 客户端凭证)和 `app-credential`(飞书、钉钉、企业微信),密钥只能写引用;旧的运行时 `oauth2` 写法被移除并给出改写提示。 - 为什么改:以前对接要 OAuth 的系统在开源版里无处声明,旧写法把密钥和刷新令牌明文写进配置,也从来没人执行;ADR-0143 把这类认证纳入开源层,这是第一步(只定形状)。 - 风险与回滚:写了 `authentication: { type: 'oauth2' }` 的连接器会被拒绝(有迁移提示);新类型的实例在服务端真正支持前一律标为"降级、不调用上游",数据源借用返回 422,不会出现未认证调用。回滚即 revert 本 PR。 - 先看:`packages/spec/src/shared/connector-auth.zod.ts`(新形状与拒绝提示)和 `packages/services/service-automation/src/plugin.ts` 里新加的降级分支。 - 两分钟验证:`pnpm --filter @objectstack/spec exec vitest run src/integration/connector-auth-grant-kinds.test.ts src/shared/connector-auth.test.ts`,看到每个拒绝都有错误码和位置、每种类型都有正例通过。 - 需要你做的:无。不属于受管面,契约复审 PASS(评论 6529303069),由席位落地;技能文档与 lint 提示的更新已立卡 #28226,随 S1 落地。 ## What changes **`@objectstack/spec`** - `ConnectorInstanceAuthSchema` gains two members (ADR-0143 D2.1, D2.2). Both are closed (`strictObject`), and both carry their secret only as `credentialRef`. - `oauth2` is a union on `grant`, one strict shape per grant. - `authorization_code` takes `authorizationUrl`, `tokenUrl`, `scopes`, `resource`, `clientId` and an optional `credentialRef` (a public client has no secret). - `client_credentials` has no `authorizationUrl` key, and its `credentialRef` is required. - Both use the projectable `dependentRequired` refinement, so the JSON Schema carries the rule and no dropped-refinements entry is owed. - `app-credential` takes `vendor` (`feishu` | `dingtalk` | `wecom`), `appId` and a required `credentialRef`. - An inline secret or token key is refused by name with the `credentialRef` prescription: `clientSecret`, `secret`, `accessToken`, `refreshToken`, `token` and `pkce` on `oauth2`; `appSecret`, `secret`, `corpSecret`, `accessToken` and `token` on `app-credential`. The aliases `audience` → `resource` and `appKey` / `corpId` / `clientId` → `appId` answer with the right key. - ⛔ There is no `signed` member (#26710, D2.3). - On `DeclarativeConnectorEntrySchema` (both authoring doors), an `oauth2` instance must name `tokenUrl` and `clientId`, plus `authorizationUrl` on `authorization_code`. Each missing key is refused at `auth.<key>`. The one exception is `provider: 'mcp'` over an `http` transport, where the MCP authorization flow discovers the endpoints and can register the client. An mcp instance over stdio gets the same refusals as any other instance. - **D7.** `ConnectorOAuth2Schema` leaves `ConnectorAuthConfigSchema`. - `authentication: { type: 'oauth2' }` is refused at `type` with a prescription that names ADR-0143 D7 and the instance `auth` that replaces it. The union's error map fires only for that literal, the `ViewDataSchema` `provider: 'api'` precedent. - `ResolvedConnectorAuth` stays the four static kinds. - The schema was module-level only and never on a published entry point. The type it narrows, `integration/Connector:authentication`, is authorable, hence the narrowing line. - The ADR-0087 D3 entry `connector-auth-config-oauth2-retired` records the change, with its `STEP18_RATIONALE` fragment (order 115). - **D4.** The per-dispatch handle types move into `packages/spec/src/integration/connector-provider.ts`: `ConnectorCredentialHandle`, `BorrowedConnectorCredential`, `BorrowedConnectorAuth` and `ConnectorCredentialRequest`, structurally identical. `ConnectorProviderContext` gains `readonly credentialHandle?: ConnectorCredentialHandle`. - **Token-endpoint client authentication** (card item 4) has no key. The ADR leaves the method (`client_secret_basic` vs `client_secret_post`) to the runtime that calls the token endpoint, so S1 owns it. The seat accepted this as an S1 choice. - The header text "OAuth2 is intentionally absent" is rewritten to the open-tier reading. The six new isomorphic aliases are pinned in `type-alias-convention.pin.test.ts` (count 795 → 801, with its receipt). **`@objectstack/types`**: `connector-credential-source.ts` re-exports the four handle types from `@objectstack/spec/integration` under the same names. The service-datasource typecheck and its 1069 tests are unchanged and green. **`@objectstack/service-automation`** (seat ruling A). Widening the union made two switches non-exhaustive, so the minimal exhaustive handling is: - `plugin.ts`: an `oauth2` or `app-credential` instance is held **degraded** through the existing `failDegradedConnectorInstance` path, with a reason that names its kind. Its factory is never called, so it never reaches the upstream unauthenticated. - `connector-credential-source.ts`: a datasource borrow of such an instance is refused with `422 VALIDATION_ERROR`, naming the kind and the instance. **Docs and fixtures** - `content/docs/automation/connectors.mdx`: "Where is `oauth2`?" is replaced by "Grant-bearing kinds: `oauth2` and `app-credential`", plus a note on the retired runtime variant and a failure-modes row. - `packages/spec/docs/SYNC_ARCHITECTURE.md`: the L3 example moves off the retired variant. The auth table drops `jwt` and `saml`, which were never variants. - `variant-docs.json`: re-keyed for the three unions. - The frozen fixture `packages/qa/downstream-contract` `DcConnector` changes per its README, because the break is intended and documented here: `authentication` is now `bearer`, with a comment citing the D7 entry. ## S1 replaces these lines These are the stand-in lines S1 (#26702) replaces when per-dispatch resolution lands. Every one of them is in `packages/services/service-automation/src/`: - `plugin.ts`, the `GrantBearingInstanceAuth` type and `grantBearingNotServedReason()` (lines 402–417 at head). - `plugin.ts`, the narrowed `resolveInstanceAuth(auth: Exclude<ConnectorInstanceAuth, GrantBearingInstanceAuth> | undefined, …)` signature and its doc sentence "A grant-bearing kind never reaches here either…" (lines 424–431). - `plugin.ts`, the reconcile branch `if (entry.auth?.type === 'oauth2' || entry.auth?.type === 'app-credential') { this.failDegradedConnectorInstance(…); continue; }` with its three-line comment (lines 2269–2283). - `connector-credential-source.ts`, `Lendable.auth: Exclude<ConnectorInstanceAuth, { type: 'none' | 'oauth2' | 'app-credential' }>` (line 84). - `connector-credential-source.ts`, the `lendRefusal` branch `if (auth.type === 'oauth2' || auth.type === 'app-credential') { return … }` with its comment (lines 118–126). - The tests that pin the stand-in: `connector-materialization.test.ts` describe "ADR-0143 D4 — a grant-bearing instance is held degraded…", and `connector-credential-source.test.ts` describe "[ADR-0143 D4] createConnectorCredentialSource — a grant-bearing kind is refused, not lent". Their CONTROL cases for the four static kinds stay. - `content/docs/automation/connectors.mdx`: the "A server that does not yet run the per-dispatch token resolution…" paragraph and the failure-modes row for a grant-bearing kind. What S1 needs that this slice leaves out: - A provider that reads `ConnectorProviderContext.credentialHandle`. The member is typed here and nothing sets it yet. - The token-endpoint client-auth method choice (basic vs post). - The connection record that holds an `authorization_code` grant. - The mcp `client_credentials` path through dynamic client registration, when `clientId` is omitted. - The skill bullet named under `Skills-docs:` above. ## Deviations from the dispatch order - The order said "Do not touch server packages". Widening `ConnectorInstanceAuth` turned the service-automation typecheck red (6 errors), so I reported it to the seat. The seat ruled **A**: touch only `connector-credential-source.ts` and `plugin.ts`, minimal and exhaustive, as above. - The order's lines were `Clause-②: yes (widening)` and `Metadata-protocol: added`. D7 removes an authorable value (`integration/Connector:authentication` `type: 'oauth2'`), so the seat ruled `yes (narrowing)` / `narrowed`, with a BREAKING changeset and the registered ADR-0087 entry. The lines are corrected here and in the changeset. - Beyond the expected landing, these files changed on the producer side: `integration/connector.zod.ts` (the entry rule and re-exports), `shared/connector-auth.test.ts` and `integration/connector.test.ts` (retired-variant tests), `type-alias-convention.pin.test.ts` (ADR-0122 gate), `variant-docs.json`, `content/docs/automation/connectors.mdx`, `packages/spec/docs/SYNC_ARCHITECTURE.md` (its L3 example is compiled by `connector-author-shape.test.ts`) and the qa fixture. ## Verification Head `4d12a2786bc03dfb6d046d7a31f9761cec235616` (includes a merge of `origin/main`). **Tests** | Command | Result | |:---|:---| | `vitest run src/integration src/shared src/migrations src/type-alias-convention.pin.test.ts` (spec) | 54 files, 1335 tests, green | | `pnpm --filter @objectstack/spec typecheck` (incl. test layer) | exit 0 | | `pnpm --filter @objectstack/types typecheck && test` | exit 0 · 825/825 | | `pnpm --filter @objectstack/service-automation typecheck && test` | exit 0 · 2926/2926 (merged head) | | `pnpm --filter @objectstack/service-datasource typecheck && test` | exit 0 · 1069/1069 | | `pnpm --filter @objectstack/downstream-contract typecheck` + `test/contract.test.ts` | exit 0 · 13/13 | `consumer-specifier-ledger.test.ts` refuses locally because `@objectstack/cli` has no dist in this box. That is a prerequisite refusal, not a finding, and CI builds it. **Gates.** `dispatch-gates.mjs --commands` derived 109 commands. I ran each one with `</dev/null` and recorded `<command> :: exit <code>` on disk. All 109 exit 0. `--ran` reconciliation: "109 derived, 109 run, 0 NOT-MEASURED, 0 UNRUN". Four commands first refused for local reasons and were re-run green: - `check-plugin-teardown-shape --self-test`, on a shallow clone, after fetching its pinned commit. - The `.d.ts`-reading spec gates, against a stale dist after the rebase, after a rebuild. - `check:skill-examples`, with no client-react dist, after building it. - `check:dual-build-cjs-loads`, with no package dists, after a packages build. One real finding, `check:spec-parsed-alias` (ADR-0122, 6 new aliases), is fixed by the pins. `check-platform-checklist --changed-from origin/main`: OK. **Ablations.** I used `scripts/ablation-replace.mjs`. Each mutation landed (anchor 1 → 0) and was restored (blob == HEAD): - A1, the mcp-http exception removed: 3 red in `connector-auth-grant-kinds.test.ts`, the two mcp CONTROLs and the secret-without-client-id case. - A2, the D7 prescription removed: 2 red in `connector-auth.test.ts`. - A3, `client_credentials` no longer requiring `credentialRef`: 1 red. - A4, the `plugin.ts` degrade branch disabled: 2 red in `connector-materialization.test.ts`, one per kind. - A5, the lend refusal disabled: 2 red in `connector-credential-source.test.ts`, one per kind. **Dogfood battery.** Full `@objectstack/dogfood` on the final head `4d12a2786`, run under `os-verify-lock` as 6 vitest shards, each `VERDICT command-exit 0`. Result: Test Files 359 passed, 3 skipped (362). Tests 2891 passed, 20 skipped (2911). No failures. It was also green on the pre-merge head `4609d0cb6`. ## Acceptance notes - **Located errors.** Every refusal is pinned by `code @ path`. Each of the two members has a CONTROL accept, and so does `provider: 'mcp'` on http with the endpoints and `clientId` omitted (`connector-auth-grant-kinds.test.ts`): - a missing endpoint: `custom @ auth.tokenUrl` / `auth.clientId` / `auth.authorizationUrl` - an unknown grant: `invalid_union @ auth.grant` - an inline secret, token or `pkce`: `unrecognized_keys @ auth` with the key named - `credentialRef` without `clientId`, or `client_credentials` without a secret: `custom @ auth.credentialRef` - an unknown vendor: `invalid_value @ auth.vendor` - a missing app secret reference: `invalid_type @ auth.credentialRef` - `signed` / `oauth1`: `invalid_union @ type` - An inline secret is refused on both new members (ADR Acceptance). - `ResolvedConnectorAuth` is unchanged (four static kinds). `@objectstack/types` keeps re-exporting the moved handle types, and the datasource borrow path's importers typecheck and test green. - The changeset is `.changeset/28137-connector-grant-bearing-auth.md`: BREAKING, with `<!-- adr-0087: registered connector-auth-config-oauth2-retired -->`. `check-adr-0087-registration` and `check-changeset-no-major` are green. - A contract review at `CONTRACT_REVIEW_TIER` is owed before the queue. The triage seat runs it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01L9qibvmENgz1tZkajp5SuJ --- _Generated by [Claude Code](https://claude.ai/code/session_01L9qibvmENgz1tZkajp5SuJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7c3cc88 commit 3238750

27 files changed

Lines changed: 1301 additions & 306 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/types': patch
4+
'@objectstack/service-automation': patch
5+
---
6+
7+
feat(spec)!: `oauth2` and `app-credential` join declarative connector-instance auth, and the runtime `oauth2` variant is retired (ADR-0143 S0, #28137)
8+
9+
Clause-②: yes (narrowing)
10+
Metadata-protocol: narrowed
11+
12+
<!-- adr-0087: registered connector-auth-config-oauth2-retired -->
13+
14+
An upstream that takes no static credential (an OAuth 2.0 API, a Feishu, DingTalk or WeCom app) had no open-tier way to be declared: the instance `auth` stopped at four static kinds, and the runtime `authentication` shape had an `oauth2` variant that held a client secret and a refresh token inline and that nothing ran. ADR-0143 opens the grant-bearing kinds on the instance, with the secret as a reference.
15+
16+
- **`@objectstack/spec`**: `ConnectorInstanceAuthSchema` gains `oauth2` (D2.1), one strict shape per `grant` (`authorization_code` with PKCE always on, `client_credentials` for a confidential client), and `app-credential` (D2.2, `vendor` `feishu` / `dingtalk` / `wecom`, `appId`, a required `credentialRef`). The publish door refuses a missing `tokenUrl`, `clientId` or `authorizationUrl` at its key under `auth`, except on `provider: 'mcp'` over `http`, where the MCP authorization flow discovers them. An inline `clientSecret`, `refreshToken`, `accessToken` or `appSecret` is refused by name with the `credentialRef` prescription. `signed` is not a member (#26710). `ConnectorOAuth2Schema` is removed from `ConnectorAuthConfigSchema` (D7), and `ResolvedConnectorAuth` stays the four static kinds. The per-dispatch handle types (`ConnectorCredentialHandle`, `BorrowedConnectorCredential`, `BorrowedConnectorAuth`, `ConnectorCredentialRequest`) move into `@objectstack/spec/integration`, and `ConnectorProviderContext` gains an optional `credentialHandle` (D4). The D3 entry `connector-auth-config-oauth2-retired` names the removal for `os migrate meta`.
17+
- **`@objectstack/types`**: re-exports the four handle types from `@objectstack/spec/integration`; the same names, structurally unchanged.
18+
- **`@objectstack/service-automation`**: this server does not run the per-dispatch token resolution yet (ADR-0143 S1). A grant-bearing instance is held **degraded** with a reason that names its kind, and its upstream is never called without the credential. A datasource that borrows it through `external.connector` is refused with `422`, naming the kind.
19+
20+
**BREAKING** for a connector that writes `authentication: { type: 'oauth2', ... }`.
21+
22+
- **Before.** `authentication: { type: 'oauth2', authorizationUrl, tokenUrl, clientId, clientSecret, refreshToken }` was accepted, with the secret and the refresh token inline, and no runtime obtained or refreshed a token from it.
23+
- **Now.** `ConnectorAuthConfigSchema` refuses it at `type`, with a prescription naming ADR-0143 D7 and the replacement. No first-party source declares it.
24+
- **Fix.** Declare the grant on a declarative instance's `auth`, with the secret as a reference: `auth: { type: 'oauth2', grant: 'authorization_code', authorizationUrl, tokenUrl, scopes, clientId, credentialRef: 'VENDOR_CLIENT_SECRET' }`, or `grant: 'client_credentials'` without `authorizationUrl`. Code that registers a connector with a token it already holds passes `{ type: 'bearer', token }`.

‎content/docs/automation/connectors.mdx‎

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -394,22 +394,67 @@ auth: { type: 'bearer', credentialRef: 'BILLING_API_TOKEN' },
394394
— fails validation, and `auth: { type: 'bearer', token: … }` is not even a
395395
legal shape (the declarative union has no `token` field to put a secret in).
396396

397-
### Where is `oauth2`?
398-
399-
Deliberately absent from declarative instances — **not** an oversight to work
400-
around. The runtime auth shape has five variants (`none`, `bearer`,
401-
`api-key`, `basic`, `oauth2`); the declarative shape stops at four. Static
402-
credentials resolved from env/config are the open tier; the OAuth2
403-
authorization-code/refresh **lifecycle** — token acquisition, rotation,
404-
per-tenant connections — is the enterprise tier (ADR-0015). If your upstream
405-
needs OAuth2, use an enterprise credential resolver or register the connector
406-
from a plugin that manages its own tokens; don't try to emulate it by stuffing
407-
a short-lived access token behind a `bearer` ref.
397+
### Grant-bearing kinds: `oauth2` and `app-credential`
398+
399+
Some upstreams take no static credential: the token is obtained from a token
400+
endpoint and refreshed as it expires. Two more `auth` kinds declare that, in
401+
the open tier (ADR-0143). They are **grant-bearing**: the metadata carries the
402+
endpoints, the client id and a `credentialRef` for the client or app secret,
403+
never a token. Access and refresh tokens are runtime state and have no key here.
404+
405+
```ts
406+
// OAuth 2.0 — a user grants access once (`authorization_code`, PKCE S256 always on):
407+
auth: {
408+
type: 'oauth2',
409+
grant: 'authorization_code',
410+
authorizationUrl: 'https://vendor.example.com/oauth/authorize',
411+
tokenUrl: 'https://vendor.example.com/oauth/token',
412+
scopes: ['crm.read'],
413+
clientId: 'objectstack-prod',
414+
credentialRef: 'VENDOR_CLIENT_SECRET', // omit for a public client
415+
}
416+
417+
// OAuth 2.0 — server to server (`client_credentials`, a confidential client):
418+
auth: {
419+
type: 'oauth2',
420+
grant: 'client_credentials',
421+
tokenUrl: 'https://vendor.example.com/oauth/token',
422+
resource: 'https://api.vendor.example.com',
423+
clientId: 'objectstack-prod',
424+
credentialRef: 'VENDOR_CLIENT_SECRET', // required for this grant
425+
}
426+
427+
// A vendor app credential (Feishu, DingTalk, WeCom): app id + app secret → tenant token
428+
auth: { type: 'app-credential', vendor: 'feishu', appId: 'cli_a1b2', credentialRef: 'FEISHU_APP_SECRET' }
429+
```
430+
431+
What the publish door checks, each refusal located at its key under `auth`:
432+
433+
- **`oauth2`** needs `tokenUrl` and `clientId`, plus `authorizationUrl` on
434+
`authorization_code`. The one exception is `provider: 'mcp'` over an `http`
435+
transport, which may omit the endpoints and the client id: the MCP
436+
authorization flow discovers the server's metadata and can register the
437+
client. `client_credentials` has no authorization step, so
438+
`authorizationUrl` is refused there, and it requires `credentialRef`.
439+
A `credentialRef` without its `clientId` is refused. An inline
440+
`clientSecret`, `refreshToken` or `accessToken` is refused by name, pointing
441+
at `credentialRef`. There is no PKCE switch.
442+
- **`app-credential`** takes `vendor` (`feishu`, `dingtalk` or `wecom`), `appId`
443+
and a required `credentialRef`. An inline `appSecret` is refused by name.
444+
445+
A server that does not yet run the per-dispatch token resolution holds such an
446+
instance **degraded**, with a reason that names the grant-bearing kind, and
447+
never calls the upstream without its credential. A datasource that borrows
448+
from it (`external.connector`) is refused with `422`. Until the server serves
449+
them, declare a static kind (`bearer`, `api-key` or `basic`) to dispatch now;
450+
don't emulate a grant by putting a short-lived access token behind a `bearer`
451+
ref.
408452

409453
### The runtime shape: `authentication`
410454

411-
The `authentication` field is the **runtime** auth config — it carries the
412-
resolved secret *inline* (`{ type: 'bearer', token }`), because it is supplied
455+
The `authentication` field is the **runtime** auth config, with four static
456+
variants (`none`, `bearer`, `api-key`, `basic`). It carries the resolved
457+
secret *inline* (`{ type: 'bearer', token }`), because it is supplied
413458
by **host code** (a plugin calling `engine.registerConnector`, or the
414459
executors' hand-wired instance options reading `process.env`). That is a
415460
different trust anchor than metadata: code review guards what enters it, and
@@ -418,6 +463,11 @@ leave `authentication` alone — provider-bound instances must use `auth`, and
418463
catalog descriptors documenting a planned integration must still never carry a
419464
live secret value.
420465

466+
The runtime shape's `oauth2` variant was removed in `@objectstack/spec` 18
467+
(ADR-0143 D7): it held a client secret and a refresh token inline and nothing
468+
ran its lifecycle. `authentication: { type: 'oauth2' }` is refused with that
469+
prescription; declare the grant on an instance's `auth` instead, as above.
470+
421471
## Dispatching from a flow
422472

423473
A materialized instance is dispatched exactly like any other connector — by
@@ -449,6 +499,7 @@ retry):
449499
|:---|:---|
450500
| `provider` names no installed factory | **Hard boot error** naming the entry, the provider, and the plugin that supplies it — add the executor to `plugins:` |
451501
| Invalid `providerConfig` (missing `baseUrl` / `spec` / `transport`, wrong shape) | **Hard boot error** from the provider factory |
502+
| `auth` is a grant-bearing kind (`oauth2`, `app-credential`) on a server that does not yet run its per-dispatch resolution | **Not fatal**: the instance registers **degraded**, naming the kind, and the upstream is never called without its credential; a datasource borrowing it is refused with `422` |
452503
| `credentialRef` resolves to nothing | **Not fatal**: the instance registers **degraded**, naming the reference — set it (`PUT …/credential-refs/:ref`), and it materializes without a restart |
453504
| The upstream refuses the credential (`401` / `403`) | **Not fatal**: the instance registers **degraded**. A stored credential is marked `rejected` and waits until it is set again (or a restart); an environment or vault credential is retried on the backoff |
454505
| Instance `name` collides with a plugin-registered connector | **Hard boot error** — there is no silent precedence between the two worlds |

‎content/docs/references/index.mdx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Protocol reference — every schema by module
33
navTitle: Protocol Reference
4-
description: Every schema published by @objectstack/spec — 1549 schemas across 14 protocol modules
4+
description: Every schema published by @objectstack/spec — 1555 schemas across 14 protocol modules
55
---
66

77
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -25,7 +25,7 @@ counts are sums of the rows they head. Regenerate with
2525
| [Automation Protocol](/docs/references/automation) | 15 | 77 | Flows and their nodes, approvals, ETL pipelines, webhooks, state machines, execution records. |
2626
| [Data Protocol](/docs/references/data) | 31 | 174 | Objects, fields, queries, filters, datasources and drivers — the ObjectQL layer. |
2727
| [Identity Protocol](/docs/references/identity) | 5 | 27 | Users and accounts, organizations, positions, SCIM provisioning. |
28-
| [Integration Protocol](/docs/references/integration) | 1 | 12 | The single connector protocol (ADR-0097) — catalog descriptors and provider-bound instances. |
28+
| [Integration Protocol](/docs/references/integration) | 1 | 18 | The single connector protocol (ADR-0097) — catalog descriptors and provider-bound instances. |
2929
| [Kernel Protocol](/docs/references/kernel) | 29 | 151 | Plugin lifecycle and manifests, capabilities and security, metadata loading, service registry. |
3030
| [Marketplace Protocol](/docs/references/marketplace) | 4 | 30 | The package & marketplace format — package identity and versions, listing, publish, review, search, install, template manifests. |
3131
| [QA Protocol](/docs/references/qa) | 1 | 8 | Declarative test suites — scenarios, steps, actions and assertions. |
@@ -34,7 +34,7 @@ counts are sums of the rows they head. Regenerate with
3434
| [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. |
3535
| [System Protocol](/docs/references/system) | 37 | 287 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
3636
| [UI Protocol](/docs/references/ui) | 16 | 172 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
37-
| **Total** | **202** | **1549** | 14 protocol modules |
37+
| **Total** | **202** | **1555** | 14 protocol modules |
3838

3939
---
4040

@@ -190,13 +190,13 @@ Users and accounts, organizations, positions, SCIM provisioning.
190190

191191
## Integration Protocol
192192

193-
**Source:** `packages/spec/src/integration/` · **Import:** `@objectstack/spec/integration` · **1 page, 12 schemas**
193+
**Source:** `packages/spec/src/integration/` · **Import:** `@objectstack/spec/integration` · **1 page, 18 schemas**
194194

195195
The single connector protocol (ADR-0097) — catalog descriptors and provider-bound instances.
196196

197197
| File | Schemas |
198198
| :--- | :--- |
199-
| [`connector.zod.ts`](/docs/references/integration/connector) | `Connector`, `ConnectorAction`, `ConnectorActionEffect`, `ConnectorInstanceAPIKeyAuth`, `ConnectorInstanceAuth`, `ConnectorInstanceBasicAuth`, `ConnectorInstanceBearerAuth`, `ConnectorInstanceNoAuth`, `ConnectorRetryStrategy`, `ConnectorType`, `DeclarativeConnectorEntry`, `RetryConfig` |
199+
| [`connector.zod.ts`](/docs/references/integration/connector) | `Connector`, `ConnectorAction`, `ConnectorActionEffect`, `ConnectorAppCredentialVendor`, `ConnectorInstanceAPIKeyAuth`, `ConnectorInstanceAppCredentialAuth`, `ConnectorInstanceAuth`, `ConnectorInstanceBasicAuth`, `ConnectorInstanceBearerAuth`, `ConnectorInstanceNoAuth`, `ConnectorInstanceOAuth2Auth`, `ConnectorInstanceOAuth2AuthorizationCodeAuth`, `ConnectorInstanceOAuth2ClientCredentialsAuth`, `ConnectorOAuth2Grant`, `ConnectorRetryStrategy`, `ConnectorType`, `DeclarativeConnectorEntry`, `RetryConfig` |
200200

201201
---
202202

0 commit comments

Comments
 (0)