diff --git a/.changeset/18983-connector-header-rate-limit-remedy.md b/.changeset/18983-connector-header-rate-limit-remedy.md new file mode 100644 index 00000000000..3a929a8fd6d --- /dev/null +++ b/.changeset/18983-connector-header-rate-limit-remedy.md @@ -0,0 +1,36 @@ +--- +'@objectstack/spec': patch +--- + +docs(spec): the connector header no longer teaches `retryConfig` as the remedy for a rate-limited upstream (#18983) + +`packages/spec/src/integration/connector.zod.ts` ships inside this package — +`files[]` carries `src/**/*.zod.ts`, and the file is present in the published +tarball — so its header TSDoc is text consumers read, and the generated +reference page is rendered from it. That header ended its "no outbound rate +limiting" paragraph with "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`", which reads as a remedy. + +It is not one. `packages/spec/liveness/connector.json` records all eight +`retryConfig` sub-keys and every `health.circuitBreaker` sub-key as `dead` +(verifiedAt 2026-09-17), and outside `packages/spec` nothing reads either: no +retry loop consumes the strategy, the backoff, the jitter or that status-code +list, so the `429` in it never causes a retry, and no breaker ever opens. An +author who followed that sentence wrote configuration that parses, stores, and +is then silently ignored. + +The sentence now carries the wording PR #18979 landed for the same claim in +`packages/spec/docs/SYNC_ARCHITECTURE.md`: both keys are **declared but +currently unimplemented**, with a pointer to the liveness ledger, and they are +explicitly neither retired — both are still declared and still parse, so an +author writing them sees no error — nor left to the host, since +`ConnectorProviderContext` carries exactly `name`, `label`, `description`, +`icon`, `type`, `providerConfig`, `auth` and `loadPackageFile`, and a provider +factory is therefore never handed either key. + +**Prose only — zero behaviour change.** No schema, declaration, default or +accept set moves, and the keys' fate stays ADR-0049's to rule on rather than +being prejudged here. The generated reference page +`content/docs/references/integration/connector.mdx` follows from `gen:docs`; it +is not published by any package in this workspace. diff --git a/content/docs/references/integration/connector.mdx b/content/docs/references/integration/connector.mdx index 23370d3bdc4..9e3029ab94b 100644 --- a/content/docs/references/integration/connector.mdx +++ b/content/docs/references/integration/connector.mdx @@ -38,9 +38,25 @@ rate-limiting engine ever existed**. The platform's only token bucket (runtime 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 +upstream gateway.** **And do not reach for `retryConfig` instead.** This +paragraph used to end "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`", which reads as a +remedy. It is not one: both keys are **declared but currently +unimplemented**. `packages/spec/liveness/connector.json` records every +`retryConfig` sub-key and every `health.circuitBreaker` sub-key as `dead`, +and outside `packages/spec` nothing reads either — no retry loop consumes a +strategy, a backoff, a jitter or that status-code list, so the `429` in it +never causes a retry, and no breaker ever opens. They are **not retired**: +both are still declared and still parse, so an author can write them and see +no error. They are **not left to the host** either — +`ConnectorProviderContext` (`integration/connector-provider.ts`) carries +exactly `name`, `label`, `description`, `icon`, `type`, `providerConfig`, +`auth` and `loadPackageFile`, so a provider factory is never handed either +key and has no way to honour it. ADR-0049 owes these keys a decision +(retire / implement / declare as a host contract); until it rules, the +advice above is the whole advice — retry and throttle **at the connector +provider or upstream gateway**. 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`. diff --git a/packages/spec/src/integration/connector.zod.ts b/packages/spec/src/integration/connector.zod.ts index c0e6eb6ccbe..1ff7f697507 100644 --- a/packages/spec/src/integration/connector.zod.ts +++ b/packages/spec/src/integration/connector.zod.ts @@ -41,9 +41,25 @@ import { retiredKey } from '../shared/retired-key'; * 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 + * upstream gateway.** **And do not reach for `retryConfig` instead.** This + * paragraph used to end "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`", which reads as a + * remedy. It is not one: both keys are **declared but currently + * unimplemented**. `packages/spec/liveness/connector.json` records every + * `retryConfig` sub-key and every `health.circuitBreaker` sub-key as `dead`, + * and outside `packages/spec` nothing reads either — no retry loop consumes a + * strategy, a backoff, a jitter or that status-code list, so the `429` in it + * never causes a retry, and no breaker ever opens. They are **not retired**: + * both are still declared and still parse, so an author can write them and see + * no error. They are **not left to the host** either — + * `ConnectorProviderContext` (`integration/connector-provider.ts`) carries + * exactly `name`, `label`, `description`, `icon`, `type`, `providerConfig`, + * `auth` and `loadPackageFile`, so a provider factory is never handed either + * key and has no way to honour it. ADR-0049 owes these keys a decision + * (retire / implement / declare as a host contract); until it rules, the + * advice above is the whole advice — retry and throttle **at the connector + * provider or upstream gateway**. 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`. *