@@ -21,11 +21,43 @@ import { retiredKey } from '../shared/retired-key';
2121 * - **Enterprise Connector** (THIS FILE) - System integrators - Full SAP integration; connector-attached sync via `syncConfig`
2222 *
2323 * **SCOPE: Most comprehensive integration layer.**
24- * Includes authentication, webhooks, rate limiting, field mapping, bidirectional sync,
24+ * Includes authentication, webhooks, field mapping, bidirectional sync,
2525 * retry policies, and complete lifecycle management.
26- *
26+ *
2727 * This protocol supports multiple authentication strategies, bidirectional sync,
28- * field mapping, webhooks, and comprehensive rate limiting.
28+ * field mapping, webhooks, and comprehensive retry and resilience policies.
29+ *
30+ * ## What this layer does NOT provide
31+ *
32+ * **There is no outbound rate limiting.** This header used to advertise "rate
33+ * limiting" twice — once in the SCOPE line, once as "comprehensive rate limiting" —
34+ * and no engine ever backed either. `connector.rateLimitConfig`, and the entire
35+ * `ConnectorRateLimitConfig` / `RateLimitStrategy` shape behind it, was removed in
36+ * `@objectstack/spec` 17.0.0 (#4911, ADR-0049 D2), because **no outbound
37+ * rate-limiting engine ever existed**. The platform's only token bucket (runtime
38+ * `security/rate-limit.ts`) throttles **INBOUND** requests *to* us; nothing throttles
39+ * the calls a connector makes *out*. Do **not** substitute `shared`'s
40+ * `RateLimitConfig` — that is the inbound limiter and would cap the wrong direction.
41+ * **Until an outbound throttle exists, rate-limit at the connector provider or
42+ * upstream gateway.** What L3 does declare for a rate-limited upstream is
43+ * `retryConfig` — whose `retryableStatusCodes` default `[408, 429, 500, 502, 503,
44+ * 504]` includes `429` — and `health.circuitBreaker`. The full removal reasoning is
45+ * recorded at the removal site: the "REMOVED: outbound rate limiting" block in
46+ * `integration/connector.zod.ts`, and `packages/spec/docs/SYNC_ARCHITECTURE.md`.
47+ *
48+ * **Field mapping does not transform values.** This header used to offer "field
49+ * mapping and transformations"; only the first half was ever true.
50+ * `ConnectorFieldMappingSchema` extends the base mapping with exactly three keys —
51+ * `dataType`, `required` and `syncMode`. `FieldMapping.transform` was removed in
52+ * `@objectstack/spec` 17.0.0 (#5552, ADR-0049), and the whole `FieldMappingTransform`
53+ * union went with it (`constant` / `cast` / `lookup` / `javascript` / `map`) — **no
54+ * runtime ever executed any of the five**. An L3 connector mapping moves a value from
55+ * `source` to `target`; it does not compute one. **Value conversion belongs on a
56+ * surface that runs it:** the import mapping's own `mapping.fieldMapping[].transform`
57+ * (`data/mapping.zod.ts` — a string enum,
58+ * `none`/`constant`/`map`/`split`/`join`/`lookup`, with its settings in `params`),
59+ * applied row by row by the REST import path — or an ETL transformation step
60+ * (L2 above). Already authored the retired key? `os migrate meta --from 16` rewrites it.
2961 *
3062 * ## Runtime contract — descriptor vs. registered connector (#2612)
3163 *
@@ -55,8 +87,8 @@ import { retiredKey } from '../shared/retired-key';
5587 * **Use Enterprise Connector when:**
5688 * - Building enterprise-grade connectors (e.g., Salesforce, SAP, Oracle)
5789 * - Complex OAuth2/SAML authentication required
58- * - Bidirectional sync with field mapping and transformations
59- * - Webhook management and rate limiting required
90+ * - Bidirectional sync with field mapping (`dataType` / `syncMode` per field — it moves values, it does not transform them)
91+ * - Webhook management required
6092 * - Full CRUD operations and data synchronization
6193 * - Need comprehensive retry strategies and error handling
6294 *
0 commit comments