diff --git a/.changeset/connector-jsdoc-retirement-drift.md b/.changeset/connector-jsdoc-retirement-drift.md new file mode 100644 index 0000000000..4506e88942 --- /dev/null +++ b/.changeset/connector-jsdoc-retirement-drift.md @@ -0,0 +1,20 @@ +--- +'@objectstack/spec': patch +--- + +connector.zod.ts 的模块 JSDoc 不再宣传已退役的出站限流与字段映射转换 + +`packages/spec/src/integration/connector.zod.ts` 的模块级 JSDoc 有四处措辞比它描述的 schema 晚了两次退役,而这段 JSDoc 被 `gen:docs` 逐字生成进 `content/docs/references/integration/connector.mdx`——同一页的属性表已经写着「已移除」,散文却还在承诺「comprehensive rate limiting」。读者相信哪一个,取决于他先读到哪一段。 + +收敛的四处: + +- 「Includes authentication, webhooks, **rate limiting**, field mapping, …」 +- 「… and comprehensive **rate limiting**.」 +- 「- Bidirectional sync with field mapping **and transformations**」 +- 「- Webhook management **and rate limiting** required」 + +出站限流从来没有引擎:平台唯一的令牌桶(`packages/runtime/src/security/rate-limit.ts`)是**入站**的,`connector.rateLimitConfig` 连同 `ConnectorRateLimitConfig` / `RateLimitStrategy` 整个形状已在 `@objectstack/spec` 17.0.0 移除(#4911, ADR-0049 D2)。字段映射同理:`FieldMapping.transform` 与整个 `FieldMappingTransform` 联合已在 17.0.0 移除(#5552, ADR-0049),没有任何 runtime 执行过其中五个成员。 + +JSDoc 因此新增一节「What this layer does NOT provide」,把两条否定连同处方写明——出站限流请在 connector provider 或上游网关做;取值转换请用会真正执行它的面(import mapping 的 `mapping.fieldMapping[].transform`,或 L2 的 ETL 转换步骤)。措辞直接复用 #4911 / #5552 墓碑与 `SYNC_ARCHITECTURE.md`(#5554)的现成句,一次退役只保留一种说法。 + +参考文档 `content/docs/references/integration/connector.mdx` 由 `gen:docs` 随动重生成(未手改)。仅注释与生成文档变化,schema 形状与运行时行为不变。 diff --git a/content/docs/references/integration/connector.mdx b/content/docs/references/integration/connector.mdx index 665856b7f7..23f28ce36b 100644 --- a/content/docs/references/integration/connector.mdx +++ b/content/docs/references/integration/connector.mdx @@ -18,11 +18,43 @@ retired in #4738 — narrative-only, zero consumers; see - **Enterprise Connector** (THIS FILE) - System integrators - Full SAP integration; connector-attached sync via `syncConfig` **SCOPE: Most comprehensive integration layer.** -Includes authentication, webhooks, rate limiting, field mapping, bidirectional sync, +Includes authentication, webhooks, field mapping, bidirectional sync, retry policies, and complete lifecycle management. This protocol supports multiple authentication strategies, bidirectional sync, -field mapping, webhooks, and comprehensive rate limiting. +field mapping, webhooks, and comprehensive retry and resilience policies. + +## What this layer does NOT provide + +**There is no outbound rate limiting.** This header used to advertise "rate +limiting" twice — once in the SCOPE line, once as "comprehensive rate limiting" — +and no engine ever backed either. `connector.rateLimitConfig`, and the entire +`ConnectorRateLimitConfig` / `RateLimitStrategy` shape behind it, was removed in +`@objectstack/spec` 17.0.0 (#4911, ADR-0049 D2), because **no outbound +rate-limiting engine ever existed**. The platform's only token bucket (runtime +`security/rate-limit.ts`) throttles **INBOUND** requests *to* us; nothing throttles +the calls a connector makes *out*. Do **not** substitute `shared`'s +`RateLimitConfig` — that is the inbound limiter and would cap the wrong direction. +**Until an outbound throttle exists, rate-limit at the connector provider or +upstream gateway.** What L3 does declare for a rate-limited upstream is +`retryConfig` — whose `retryableStatusCodes` default `[408, 429, 500, 502, 503, +504]` includes `429` — and `health.circuitBreaker`. The full removal reasoning is +recorded at the removal site: the "REMOVED: outbound rate limiting" block in +`integration/connector.zod.ts`, and `packages/spec/docs/SYNC_ARCHITECTURE.md`. + +**Field mapping does not transform values.** This header used to offer "field +mapping and transformations"; only the first half was ever true. +`ConnectorFieldMappingSchema` extends the base mapping with exactly three keys — +`dataType`, `required` and `syncMode`. `FieldMapping.transform` was removed in +`@objectstack/spec` 17.0.0 (#5552, ADR-0049), and the whole `FieldMappingTransform` +union went with it (`constant` / `cast` / `lookup` / `javascript` / `map`) — **no +runtime ever executed any of the five**. An L3 connector mapping moves a value from +`source` to `target`; it does not compute one. **Value conversion belongs on a +surface that runs it:** the import mapping's own `mapping.fieldMapping[].transform` +(`data/mapping.zod.ts` — a string enum, +`none`/`constant`/`map`/`split`/`join`/`lookup`, with its settings in `params`), +applied row by row by the REST import path — or an ETL transformation step +(L2 above). Already authored the retired key? `os migrate meta --from 16` rewrites it. ## Runtime contract — descriptor vs. registered connector (#2612) @@ -52,8 +84,8 @@ Authentication is now imported from the canonical `auth/config.zod.ts`. **Use Enterprise Connector when:** - Building enterprise-grade connectors (e.g., Salesforce, SAP, Oracle) - Complex OAuth2/SAML authentication required -- Bidirectional sync with field mapping and transformations -- Webhook management and rate limiting required +- Bidirectional sync with field mapping (`dataType` / `syncMode` per field — it moves values, it does not transform them) +- Webhook management required - Full CRUD operations and data synchronization - Need comprehensive retry strategies and error handling diff --git a/packages/spec/src/integration/connector.zod.ts b/packages/spec/src/integration/connector.zod.ts index 449abf8743..9c3f7a49e6 100644 --- a/packages/spec/src/integration/connector.zod.ts +++ b/packages/spec/src/integration/connector.zod.ts @@ -21,11 +21,43 @@ import { retiredKey } from '../shared/retired-key'; * - **Enterprise Connector** (THIS FILE) - System integrators - Full SAP integration; connector-attached sync via `syncConfig` * * **SCOPE: Most comprehensive integration layer.** - * Includes authentication, webhooks, rate limiting, field mapping, bidirectional sync, + * Includes authentication, webhooks, field mapping, bidirectional sync, * retry policies, and complete lifecycle management. - * + * * This protocol supports multiple authentication strategies, bidirectional sync, - * field mapping, webhooks, and comprehensive rate limiting. + * field mapping, webhooks, and comprehensive retry and resilience policies. + * + * ## What this layer does NOT provide + * + * **There is no outbound rate limiting.** This header used to advertise "rate + * limiting" twice — once in the SCOPE line, once as "comprehensive rate limiting" — + * and no engine ever backed either. `connector.rateLimitConfig`, and the entire + * `ConnectorRateLimitConfig` / `RateLimitStrategy` shape behind it, was removed in + * `@objectstack/spec` 17.0.0 (#4911, ADR-0049 D2), because **no outbound + * rate-limiting engine ever existed**. The platform's only token bucket (runtime + * `security/rate-limit.ts`) throttles **INBOUND** requests *to* us; nothing throttles + * the calls a connector makes *out*. Do **not** substitute `shared`'s + * `RateLimitConfig` — that is the inbound limiter and would cap the wrong direction. + * **Until an outbound throttle exists, rate-limit at the connector provider or + * upstream gateway.** What L3 does declare for a rate-limited upstream is + * `retryConfig` — whose `retryableStatusCodes` default `[408, 429, 500, 502, 503, + * 504]` includes `429` — and `health.circuitBreaker`. The full removal reasoning is + * recorded at the removal site: the "REMOVED: outbound rate limiting" block in + * `integration/connector.zod.ts`, and `packages/spec/docs/SYNC_ARCHITECTURE.md`. + * + * **Field mapping does not transform values.** This header used to offer "field + * mapping and transformations"; only the first half was ever true. + * `ConnectorFieldMappingSchema` extends the base mapping with exactly three keys — + * `dataType`, `required` and `syncMode`. `FieldMapping.transform` was removed in + * `@objectstack/spec` 17.0.0 (#5552, ADR-0049), and the whole `FieldMappingTransform` + * union went with it (`constant` / `cast` / `lookup` / `javascript` / `map`) — **no + * runtime ever executed any of the five**. An L3 connector mapping moves a value from + * `source` to `target`; it does not compute one. **Value conversion belongs on a + * surface that runs it:** the import mapping's own `mapping.fieldMapping[].transform` + * (`data/mapping.zod.ts` — a string enum, + * `none`/`constant`/`map`/`split`/`join`/`lookup`, with its settings in `params`), + * applied row by row by the REST import path — or an ETL transformation step + * (L2 above). Already authored the retired key? `os migrate meta --from 16` rewrites it. * * ## Runtime contract — descriptor vs. registered connector (#2612) * @@ -55,8 +87,8 @@ import { retiredKey } from '../shared/retired-key'; * **Use Enterprise Connector when:** * - Building enterprise-grade connectors (e.g., Salesforce, SAP, Oracle) * - Complex OAuth2/SAML authentication required - * - Bidirectional sync with field mapping and transformations - * - Webhook management and rate limiting required + * - Bidirectional sync with field mapping (`dataType` / `syncMode` per field — it moves values, it does not transform them) + * - Webhook management required * - Full CRUD operations and data synchronization * - Need comprehensive retry strategies and error handling *