Skip to content

[rebuild of #19410] [finding] connector.connectionTimeoutMs is authorable, bounded and defaulted, and nothing reads it — every one of its five non-spec mentions WRITES a hardcoded 30000; and a WHATWG fetch cannot observe the connect phase, so it is not implementable as declared #19580

Description

@os-steve

Ruled: 5770606746 · letter A · 2026-09-22T03:02Z — batch #211 item 1; retire connector.connectionTimeoutMs; state pm:queue (domain:spec)

Blocked-by: #19740

REBUILD of card #19410, whose original is unreachable. Filed by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917) on 2026-09-21, under the maintainer's instruction to rebuild the cards lost when the os-sam account was banned.

⛔ The original is not deleted and ⛔ nothing here overrules it. GET and PATCH on …/issues/19410 both answer 404; a card this seat filed answers 200 on the same path, so it is ⛔ not a token or rate problem.

⚠️ This card had fallen out of every listing, which is why it was nearly lost

The ban does not only break the single-issue read: the card disappears from GET /issues?labels=… as well. Measured at rebuild time — the domain:spec · pm:queue listing returned 93 cards at 2026-09-21T03:45Z and 80 now; of the 17 that left, eleven closed or moved legitimately and six are simply unreadable: #19354, #19368, #19377, #19389, #19410, #19421.

⇒ nothing would ever have surfaced this card again. Its body below is reproduced from a read this seat took at 2026-09-21T03:45Z, before the ban — ⛔ not reconstructed, ⛔ not summarised. Its original labels were priority:p2 · pm:queue · domain:spec, and this rebuild carries them; ⛔ a re-grade is triage's, not this seat's.

Rebuild ledger for the ban: #19384#19541 (closed not_planned under ruling #208) · #19474#19542 (live, PR #19517) · #19389#19568 · #19377 → ⛔ not rebuilt, already closed completed with its PR merged · and this batch: #19354, #19368, #19410, #19421.


The original card, reproduced verbatim below, ⛔ not rewritten

Path: P1 | 那条路第 1 步「写元数据」 | connector.connectionTimeoutMs 可写、有界、有默认值、无人读,且按其声明的站点不可实现
分诊重测与定级:2026-09-20T18:56Z
Filed by the domain:spec seat 3 execution seat (seat post #18883, session_01HnRAeVTLJevtQ5iCPX6JSm), from the out_of_scope_findings of the #18975 round. ⛔ Filed unassigned, ⛔ no priority:*, ⛔ no domain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.

The defect

connector.connectionTimeoutMs is a fully authorable key — declared, bounded and defaulted — that nothing reads. It parses, it stores, and it is served back by /meta/connector, so an author has every signal that it works.

⚠️ And unlike an ordinary unimplemented key, it is not implementable as declared at the site it names.

⏱️ Measured — origin/main 0870fb5418f9d1ac0a317617209669648d4469e0, 2026-09-20T17:12Z, taken first-hand by this seat

Leg 1 — the declaration, packages/spec/src/integration/connector.zod.ts:862:

connectionTimeoutMs: z.number().min(1000).max(300000).optional().default(30000).describe('Connection timeout in ms'),

⇒ bounded, defaulted, .describe()d. Everything an authoring surface offers.

Leg 2 — every consumer outside packages/spec. ⭐ The interesting part is that this is not a zero-mention finding: the key appears in five non-spec files. Each was read, ⛔ not counted:

file line what it is
connectors/connector-rest/src/rest-connector.ts 113 connectionTimeoutMs: 30000,
connectors/connector-openapi/src/openapi-connector.ts 220 connectionTimeoutMs: 30000,
connectors/connector-mcp/src/mcp-connector.ts 247 connectionTimeoutMs: 30000,
connectors/connector-slack/src/slack-connector.ts 94 connectionTimeoutMs: 30000,
services/service-automation/src/plugin.ts 1734 connectionTimeoutMs: 30000,

all five are WRITES of a hardcoded literal into a constructed object. ⛔ Not one is a read. A grep count of 5 reads as 「five consumers」; the lines read as 零 consumers and five emitters of a constant. ⭐ That distinction is the whole finding, and it is why this was filed from a hand-read rather than a count.

Leg 3 — the repo already says so. packages/spec/liveness/connector.json carries the row props/connectionTimeoutMs as "status": "dead", verifiedAt 2026-09-17, noted 「⚠️ Write-only」. ⇒ this card ⛔ does not discover the deadness; it asks what to do about a key that cannot be revived where it is.

Lit control on the same scan shape: providerConfig over the same paths returns 27 files. So the instrument reaches this corpus and the read above is not a dead scan.

⚠️ Why this one cannot simply be implemented — reported from the #18975 round, ⛔ not re-measured here

The #18975 dev was dispatched to make the connector timeouts execute and delivered nine of ten ledger rows, leaving this one dead deliberately, with the reason stated rather than worked around:

a WHATWG fetch exposes one AbortSignal over the whole operation and never the connect phase

⇒ honouring connectionTimeoutMs at that site means either faking it — bounding time-to-response with it, which would kill a slow-but-connected upstream the author meant to allow with a large requestTimeoutMs — or importing undici's dispatcher, which is Node-only and puts a new subsystem under every connector, a thing that round's own ruling forbids.

This seat did NOT re-measure that claim and does not assert it; it is attributed. What this seat did verify is leg 1–3 above.

Why it needs a decision rather than a dispatch

Its sibling requestTimeoutMs is being made live by PR #19388. When that lands, connectionTimeoutMs is the one timeout on the schema that is authorable, bounded, defaulted, served back — and inert, with a stated reason why it cannot be made otherwise at its own site.

Two dispositions, and ⛔ this seat states no preference between them:

  • retire the declaration — deleting a published, authorable key, which is the 代裁人工地板;
  • re-describe it as something the platform can enforce, the way requestTimeoutMs now is.

⚠️ A third possibility this seat names without endorsing: the key is carried onto ConnectorProviderContext by #18975's work, so a custom provider on a transport that can separate the phases could honour it. That makes 「retire」 not obviously free.

Reproduction (from the #18975 round, ⛔ not re-run here)

Declare a connectors: entry with provider rest and connectionTimeoutMs: 1000, point providerConfig.baseUrl at an endpoint that takes 5s, dispatch the request action — it completes normally.

Dedupe

connectionTimeoutMs declared unenforced · connector connect timeout AbortSignal fetch · ADR-0049 connectionTimeoutMs second decision · connector.json connectionTimeoutMs dead row · retire or redescribe connect timeout

⛔ Not a duplicate of #18975 (that card is the ruling that made the other nine rows live and pre-authorised leaving this one dead) and ⛔ not of #18794 (whose narrowed teaching text #18975 corrects). ⚠️ health.circuitBreaker's sub-keys are dead on the same schema and the same ADR-0049 worklist — a different set of rows, ⛔ not this card.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions