fix(extension): use the guarded caps local for the cookie heading - #217
Conversation
Reported as a consistency nit on #215; it is a crash. `caps` is the defensively-guarded form — it falls back to ['fetch'] because callers may omit `capabilities` — and the cookie heading read `pending.capabilities` directly, so an omitted field throws: TypeError: Cannot read properties of undefined (reading 'includes') That throws inside `renderPopup`, so the pair popup renders NOTHING. The one UI the user depends on to see what they are approving fails closed into a blank panel, which is a worse outcome than the wrong heading this line was added to fix. Covered by a test that renders a pending-pair state with `capabilities` omitted and asserts no throw, plus that the names still appear under the read heading — the fallback is ['fetch'], which grants no cookie access, so "Read cookies" is the correct label in that state. Closes #216 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012o2nXwu7tov6j7ciBEpigo
|
Claude finished @chrischall's task in 39s —— View job PR Review: fix(extension): use the guarded caps local for the cookie headingStatus: ✅ Complete SummaryThis PR fixes a critical crash in the pair-approval popup. The bug occurs when an MCP omits the The fix correctly switches to the defensively-guarded Findings✅ No issues found. The change is minimal, correct, and well-aligned with project conventions:
Verdict: pass |
|
✅ Auto-review verdict: pass — The PR correctly fixes a critical crash in the pair-approval popup by using the defensively-guarded |
🤖 I have created a release *beep* *boop* --- ## [2.0.0](v1.11.0...v2.0.0) (2026-08-06) ### ⚠ BREAKING CHANGES * **protocol:** bind the ephemeral key into the ready signature ([#222](#222)) ### Features * **protocol:** add write_cookies, the one verb that can repair a rotated session ([#211](#211)) ([b2557c2](b2557c2)) * **protocol:** bind the ephemeral key into the ready signature ([#222](#222)) ([c13aeed](c13aeed)) * **server:** let a request name the tab that relays it ([#207](#207)) ([c5d3f4d](c5d3f4d)) * **server:** pin the extension's identity, and verify it on the peer path ([#213](#213)) ([0eeced7](0eeced7)) ### Bug Fixes * **cli:** let a real filesystem error be itself, not "no extension pin" ([#221](#221)) ([c87a864](c87a864)), closes [#220](#220) * **cli:** validate --via-tab before connecting, like the request URL ([#210](#210)) ([959fcc5](959fcc5)) * **extension:** reattach the write_cookies doc block, and name the writable cookies as writable ([#215](#215)) ([2730c4a](2730c4a)) * **extension:** use the guarded caps local for the cookie heading ([#217](#217)) ([f95c832](f95c832)) * **server:** release only our own extension claim, and stop guessing scoped names ([#219](#219)) ([3d90a64](3d90a64)), closes [#218](#218) * **server:** type no-tab rejections so they stop reading as version mismatches ([#205](#205)) ([dc30bd9](dc30bd9)) ### Refactor * **server:** drop the concatBytes imports the signature change orphaned ([#224](#224)) ([4985ba7](4985ba7)), closes [#223](#223) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Closes #216.
It's a crash, not a consistency nit
capsis the defensively-guarded form — it falls back to['fetch']because callers may omitcapabilities. My cookie heading readpending.capabilitiesdirectly, so an omitted field throws:That throw is inside
renderPopup, so the pair popup renders nothing. The one UI a user depends on to see what they're approving fails closed into a blank panel — a worse outcome than the wrong heading that line was added to fix.Filed as "inconsistent with the established defensive pattern", which is accurate but undersells it. Verified with a test before fixing: renders a pending-pair state with
capabilitiesomitted, asserts no throw, and asserts the names still appear under "Read cookies" — the fallback is['fetch'], which grants no cookie access at all, so the read heading is correct in that state.The pattern in these three findings
All three review rounds since
write_cookiesmerged found the same class of mistake: code that was right for the case I had in mind and wrong for the case the surrounding code had already handled. The guard was six lines above the line I added. So was the doc block I displaced, and the siblingpending*maps before that.The correction isn't "be more careful" — it's to read the enclosing function for existing conventions before adding a call, rather than after a reviewer points at one.
1195 tests pass.
🤖 Generated with Claude Code
https://claude.ai/code/session_012o2nXwu7tov6j7ciBEpigo