Repository navigation
fix(api): bound the positional workspace id fallback to the live list - #81
Conversation
`parse_workspace_id` accepts `w_N` and a bare `N` as a documented positional convenience, but returned the parsed index without checking it against the live workspace list, so `"999999"` resolved to `Some(999998)`. Callers that index `self.state.workspaces` directly through `public_workspace_id` then panicked the whole server from one socket request, reachable through `pane.move` with a `new_tab` destination and through `Method::WorkspaceFocus` in the headless client-view path. The parser now bounds the fallback to the live list, so an out-of-range positional id yields `None` and every caller maps it to the `workspace_not_found` error it already returns for an unknown id; the positional convenience itself is unchanged. refs #77
cameronsjo
left a comment
There was a problem hiding this comment.
Code review and an independent security review ran against the diff at c83d4754. Both clean: no Critical, no Important. The delta to this head is one line in docs/fork/CHANGES.md (the PR link); source is identical, so the review binds here.
Security review traced all call sites: the .filter closes the panic on both unguarded surfaces (pane.move and WorkspaceFocus), parse_tab_id/parse_pane_id already re-bound via .get(), no targeting or authorization outcome changes, and checked_sub(1) is safe on 0 and usize::MAX-shaped input. Nits, not actioned: public_workspace_id remains an unchecked index at the sink (herdr#80); the new test does not pin 0/w_0/usize::MAX.
Not run locally (vendored Zig build does not link here); CI is the proving run.
|
Warning Review limit reached
On-demand reviews are free for the next 28 days. After that, they cost $0.25 per reviewed file. Or wait 13 minutes for your next included review. View limit detailsLimit details: You’ve used all 2 included reviews currently available. Your 55 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (6)
Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. 📝 WalkthroughWalkthrough
ChangesWorkspace ID bounds
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Low Suggested reviewers: Merge Risk: ⚪ Minimal · up to Out-of-range workspace IDs now return a not-found response rather than reaching invalid indexing paths. No remaining merge-blocking risk was identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 5 files. (1 skipped: 1 unsupported.) ✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
A rabbit checks each bound, Comment |
The fixture leaves the active workspace unset, and the state invariant check at the end of the test requires one on a non-empty app. CI caught it; the vendored Zig build does not link locally. refs #77
cameronsjo
left a comment
There was a problem hiding this comment.
Rebinds the review at c83d4754. Two commits since: the ledger PR link, and a test-only fix (the pane-move bound test now sets an active workspace so the state invariant check at its end holds; CI caught it, the local build cannot link). Production source is identical to the reviewed head. CI green on macOS and ubuntu at this head.
…workspace-id docs/fork/CHANGES.md conflict only: this branch and master (#115, #116, #117, #118, #119) each added a new section at the same spot. Kept all of them whole, this branch's section first because the ledger is newest first. The retired note on the #81 entry merged without a conflict. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016MXBYW3meTL95gcAeo2HFm
refs #77
What
parse_workspace_idaccepts a positional convenience (w_Nor bareN, the Nth workspace in display order, documented in the socket API) and returned that index unbounded.public_workspace_idindexes the workspace list bare, sopane.movewithdestination.type = "new_tab"andworkspace_id: "999999"panicked the server from one socket request. TheWorkspaceFocusshell navigation path had the same exposure. The guard some callers carry sits in a different arm and never covered the panic path.The fix is one
.filterat the source bounding the index to the live list. The positional convenience survives; an out-of-range id now yields the sameworkspace_not_foundevery caller already returns for an unknown id. Four comments that said the function does not bounds-check are corrected; the three hand-rolled guards stay as defense in depth and the fork ledger says so, so an upstream sync does not read them as stale.What the issue got wrong
Stale ids already failed closed: live ids are
w<base32>with an alphabet that has no underscore, so a stalew5never matched the positional shapes.plugin_context_for_workspace_idnever calls this function. The real defect was the panic.Tests
Two: the bound itself over in-range, out-of-range, exact-match, and stale-shaped ids; and
pane.moveto a new tab with an out-of-range workspace id returningworkspace_not_foundwith the source pane still attached. Theclient_views.rspath is safe by construction and has no test harness of its own. Not run locally (the vendored Zig build does not link on this Mac); CI is the proving run.Review
Code review and an independent security review ran against the diff at
c83d4754, both clean. The follow-up commit fills thePR:line in the changes ledger.Summary by CodeRabbit
Bug Fixes
Tests
Documentation