fix(feishu): pass timeoutMs through app-registration guarded fetch#105549
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 14, 2026, 2:42 PM ET / 18:42 UTC. Summary PR surface: Source +7, Tests +35. Total +42 across 2 files. Reproducibility: no. full failing current-main runtime reproduction is shown, but the source path is high-confidence reproducible: app registration omits the guarded-fetch timeout while sibling guarded calls use that contract. The supplied live run convincingly proves the corrected production path. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Keep one canonical 10-second budget at the guarded-fetch boundary, refresh the branch onto current main, rerun the focused registration timeout proof, and merge if the refreshed diff remains behaviorally unchanged. Do we have a high-confidence way to reproduce the issue? No full failing current-main runtime reproduction is shown, but the source path is high-confidence reproducible: app registration omits the guarded-fetch timeout while sibling guarded calls use that contract. The supplied live run convincingly proves the corrected production path. Is this the best way to solve the issue? Yes. Moving the existing 10-second budget to fetchWithSsrFGuard is narrower and more maintainable than retaining parallel RequestInit and dispatcher timeout mechanisms, and it matches the sibling guarded-fetch pattern. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against af3d796e199f. Label changesLabel justifications:
Evidence reviewedPR surface: Source +7, Tests +35. Total +42 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles) |
|
@clawsweeper re-review Added non-Vitest standalone runtime proof on the production caller
Also re-ran Vitest ( |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
4ae9692 to
2e52be1
Compare
|
@clawsweeper re-review New head after rebase + stronger proof:
PR body Real behavior proof updated with verbatim transcripts. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper status |
2e52be1 to
9238e5b
Compare
|
@clawsweeper re-review Fresh review for current head Real behavior proof re-verified on this head: Vitest ( Standalone non-Vitest short ( Standalone non-Vitest production floor ( PR body already contains the full verbatim transcripts. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
0a849c1 to
0203a25
Compare
7639e86 to
50cf7a2
Compare
50cf7a2 to
3ec4fce
Compare
|
Land-ready maintainer pass complete on exact head
Known gap: no credentialed QR scan/app creation. The live smoke deliberately stopped before authentication or mutation. The final head contains one merge-only sync to resolve the real |
|
Merged via squash.
|
…penclaw#105549) * fix(feishu): pass timeoutMs through app-registration guarded fetch * refactor(feishu): keep registration timeout internal * docs(changelog): credit Feishu timeout fix --------- Co-authored-by: Peter Steinberger <[email protected]>
Rebuild on current main. Current registration still passes timeoutMs into fetchWithSsrFGuard (openclaw#105549); assert TimeoutError + request timed out with fetchImpl never called.
Rebuild on current main. Registration still passes timeoutMs into fetchWithSsrFGuard (openclaw#105549); do not rewrite to AbortSignal.timeout(). Assert TimeoutError + request timed out with fetchImpl never called.
What Problem This Solves
Feishu/Lark scan-to-create app registration used the guarded SSRF fetch without its transport-level
timeoutMs. A peer that accepted a connection but never returned response headers could therefore outlive the onboarding request budget.This is the HTTP path behind the documented one-click app creation flow.
Why This Change Was Made
fetchFeishuJsonnow passes one private 10-second app-registration deadline intofetchWithSsrFGuard. That shared boundary already owns DNS preflight, the pinned Undici dispatcher, redirects, body limits, and cleanup, so a secondAbortSignal.timeoutpath was redundant.The test-only override stays on the internal registration fetch options. Poll expiry and poll sleep fallbacks now use their own named registration constants instead of borrowing the request timeout.
No new config, environment variable, or public SDK surface.
User Impact
Before: a stalled accounts endpoint could leave app registration or owner lookup waiting beyond the intended onboarding budget.
After: every registration JSON request has the guarded 10-second deadline, including connect and response-header waits. Timeout failures surface as
TimeoutError: request timed out.Evidence
50c08330fca02042d52f222b21d224e621c4f328beginAppRegistration→postRegistration→fetchFeishuJson→fetchWithSsrFGuardtbx_01kxm1sm2m7r2s8emr4hww28z4: 10/10 tests passed; a real TCP peer that withheld headers timed out in 83 ms under the shortened test deadlineinitAppRegistrationcalls reached Feishu in 743 ms and Lark in 1,209 ms without credentials or app creationoxfmt --check,pnpm check:test-types, andgit diff --check: passedWhat was not tested: a credentialed QR scan that creates an app. The live smoke deliberately stopped before authentication or app creation.
The final head contains one merge-only sync to resolve the real
CHANGELOG.mdconflict with currentmain; the reviewed Feishu code is unchanged.