fix(msteams): bound probe token acquisition to request deadline#106386
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 17, 2026, 8:14 PM ET / July 18, 2026, 00:14 UTC. Summary PR surface: Source +13, Tests +154. Total +167 across 4 files. Reproducibility: yes. source inspection gives a high-confidence path: make the Teams SDK token-provider promise never settle and call the probe or shared Graph resolver; the new focused tests exercise that path with fake timers. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review detailsBest possible solution: Land the exact reviewed head once required checks complete, retaining the existing 30-second MS Teams deadline contract for stalled SDK token acquisition. Do we have a high-confidence way to reproduce the issue? Yes, source inspection gives a high-confidence path: make the Teams SDK token-provider promise never settle and call the probe or shared Graph resolver; the new focused tests exercise that path with fake timers. Is this the best way to solve the issue? Yes. Reusing the existing owner-local request-deadline helper at each previously unbounded token-acquisition await is narrower and safer than adding a new setting, SDK wrapper, or fallback. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 72e4b779215b. Label changesLabel justifications:
Evidence reviewedPR surface: Source +13, Tests +154. Total +167 across 4 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 Updated PR to address both blockers from the prior 🦪 review:
Both new commits are on |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
a844c4f to
512ab8c
Compare
512ab8c to
5da5ee6
Compare
|
Rebased onto current main (patch-identical cherry-pick, verified via The failing |
5da5ee6 to
4588249
Compare
probeMSTeams() at extensions/msteams/src/probe.ts:75 and :89 awaited tokenProvider.getAccessToken(...) for the Bot Framework and Microsoft Graph token endpoints with no surrounding deadline. The Microsoft Teams SDK does not carry an inherent timeout on these calls, so a stalled Azure AD token endpoint pinned the probe indefinitely. Wrap both awaits with withMSTeamsRequestDeadline (default MSTEAMS_REQUEST_TIMEOUT_MS = 30_000), matching the pattern already used by six other MS Teams call sites: attachments/bot-framework.ts:252, attachments/graph.ts:258, monitor-handler/message-handler.ts:594/654/685/692, attachments/download.ts:167, team-identity.ts:37. The probe was the one missing site. No new helper, no SDK change. The existing outer catch at probe.ts:138 and inner catch at probe.ts:110 convert the timeout into a ProbeMSTeamsResult with ok: false and a structured error field. Added probe.timeout.test.ts: real probeMSTeams() with vi.mock injected never-resolving getBotToken/getGraphToken; asserts the call returns within the 30s bound instead of hanging to the proof budget.
The original probe.timeout.test.ts waited 90 seconds of wall-clock per focused run (3 stalled cases racing against a real setTimeout budget). Per ClawSweeper P2 (automation), this material deterministic CI cost can slow or time out test shards. Drive the withTimeout race (from @openclaw/fs-safe/dist/timing.js, uses setTimeout + clearTimeout) via vi.useFakeTimers() so each stalled case resolves in milliseconds. Add one new case that spies on withTimeout's timeoutMs argument to assert the production default deadline is exactly MSTEAMS_REQUEST_TIMEOUT_MS = 30_000, so the production contract is not silently weakened by the fake-timer change. Per-case wall-clock: 25ms / 3ms / 2ms / 1ms / 2ms (was: 30s / 30s / 30s / 2ms / n/a). Co-Authored-By: Claude <[email protected]>
4588249 to
39d9894
Compare
|
Merged via squash.
|
…claw#106386) * fix(msteams): bound probe token acquisition to request deadline probeMSTeams() at extensions/msteams/src/probe.ts:75 and :89 awaited tokenProvider.getAccessToken(...) for the Bot Framework and Microsoft Graph token endpoints with no surrounding deadline. The Microsoft Teams SDK does not carry an inherent timeout on these calls, so a stalled Azure AD token endpoint pinned the probe indefinitely. Wrap both awaits with withMSTeamsRequestDeadline (default MSTEAMS_REQUEST_TIMEOUT_MS = 30_000), matching the pattern already used by six other MS Teams call sites: attachments/bot-framework.ts:252, attachments/graph.ts:258, monitor-handler/message-handler.ts:594/654/685/692, attachments/download.ts:167, team-identity.ts:37. The probe was the one missing site. No new helper, no SDK change. The existing outer catch at probe.ts:138 and inner catch at probe.ts:110 convert the timeout into a ProbeMSTeamsResult with ok: false and a structured error field. Added probe.timeout.test.ts: real probeMSTeams() with vi.mock injected never-resolving getBotToken/getGraphToken; asserts the call returns within the 30s bound instead of hanging to the proof budget. * test(msteams): drive probe timeout test with vi.useFakeTimers The original probe.timeout.test.ts waited 90 seconds of wall-clock per focused run (3 stalled cases racing against a real setTimeout budget). Per ClawSweeper P2 (automation), this material deterministic CI cost can slow or time out test shards. Drive the withTimeout race (from @openclaw/fs-safe/dist/timing.js, uses setTimeout + clearTimeout) via vi.useFakeTimers() so each stalled case resolves in milliseconds. Add one new case that spies on withTimeout's timeoutMs argument to assert the production default deadline is exactly MSTEAMS_REQUEST_TIMEOUT_MS = 30_000, so the production contract is not silently weakened by the fake-timer change. Per-case wall-clock: 25ms / 3ms / 2ms / 1ms / 2ms (was: 30s / 30s / 30s / 2ms / n/a). Co-Authored-By: Claude <[email protected]> * fix(msteams): bound remaining token acquisition * test(msteams): keep credential fixture unchanged --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
MS Teams token acquisition could wait forever when the Teams SDK or its authentication transport stalled. The unbounded calls affected both
probeMSTeams()phases and the sharedresolveGraphToken()path used by Teams Graph actions.Why This Change Was Made
All three missing calls now reuse the plugin's existing
withMSTeamsRequestDeadlinehelper and its established 30-second default:This is the existing owner-local deadline contract already used by Teams attachment, media, identity, and message paths. No new helper, config, environment variable, SDK surface, fallback, or capability is introduced.
The regression coverage drives the real provider functions with never-settling SDK promises under fake timers. The original standalone 168-line test was rewritten into two focused suites covering the probe and shared Graph resolver, reducing the final PR by 13 lines while adding the missed Graph production path.
User Impact
Teams health probes and Graph-backed actions now return a labeled timeout error instead of remaining pending indefinitely when token acquisition stalls. Existing successful, credential-error, delegated-token, and China-cloud behavior is unchanged.
Evidence
Dependency contract:
@microsoft/teams.apps2.0.13TokenManager.getBotToken()andgetGraphToken()call MSAL or managed-identity token acquisition without accepting an abort signal or per-call timeout.Focused tests after the final rewrite:
Result: 5 files passed, 33 tests passed.
Hosted changed gate:
Result: passed on Blacksmith Testbox
tbx_01kxs8nxvngn01fktwyjdmgdjj, including formatting, extension production/test typechecks, lint, Plugin SDK manifest, plugin boundaries, repository guards, and import-cycle checks: https://github.com/openclaw/openclaw/actions/runs/29622311925Fresh autoreview: no findings; patch correct at 0.93 confidence.
The contributor's controlled transport proof also exercised the production Teams SDK and real
@azure/msal-nodepath against a loopback response-body stall. The probe returned at 30,002 ms with the expected timeout and the following Graph acquisition remained usable. No credentials or live Azure traffic were used.Changelog
No
CHANGELOG.mdedit in this contributor PR. Release-note context is preserved here and in the squash message.