Skip to content

Port upstream 0.65.0: respect read-only claude-swap adapters - #631

Closed
Finesssee wants to merge 1 commit into
port/upstream-0.65.0from
port/micro-0.65.0-claude-swap-read-only
Closed

Finesssee wants to merge 1 commit into
port/upstream-0.65.0from
port/micro-0.65.0-claude-swap-read-only

Conversation

@Finesssee

Copy link
Copy Markdown
Collaborator

Summary

Respect read-only claude-swap account adapters. The cswap --list --json schema-v1 envelope may carry an optional top-level boolean supportsAccountSwitching (absent means true). When it is false, usage, account details and the active marker remain, but no Switch or Reauthenticate action is projected for any row, and the shell rejects switch/reauthenticate for that list. A present non-boolean value (including null, numbers, strings, arrays, objects) fails the whole payload with MalformedShape("supportsAccountSwitching is not a boolean").

Upstream reference

  • Release bullet (v0.65.0): "Claude: respect read-only account adapters, preserving usage and account details while hiding switching and re-authentication actions" (Support read-only Claude account adapters steipete/CodexBar#3658; f21dbeb37 / fix(claude): honor read-only account adapters steipete/CodexBar#3846).
  • Tag-pinned reads (v0.65.0): Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountList.swift (supportsAccountSwitching, default true, exact error text), ClaudeSwapAccountProjection.swift (canActivate: list.supportsAccountSwitching && ...), Tests/CodexBarTests/ClaudeSwapListParserTests.swift, ClaudeSwapAccountProjectionTests.swift, ClaudeSwapSwitchErrorTimingTests.swift, docs/claude-multi-account-and-status-items.md.

Ported / Deferred

Ported: parser field and validation, projection gating (action_for_account now takes the list), shell rejection in validate_claude_swap_operation, tests. The existing UI already renders no button when action is null, so no frontend change; a Vitest test pins it.
Deferred: none. The other hunks of the upstream commit (scoped-window parse refactor, projected-usage snapshot inlining) are behavior-preserving refactors and were not ported.

Validation

  • cargo +1.98.0 fmt --all; cargo +1.98.0 clippy --workspace --all-targets -- -D warnings: clean
  • cargo +1.98.0 test -p codexbar claude_swap: 40 passed, 0 failed
  • cargo +1.98.0 test -p codexbar-desktop-tauri claude_accounts: 7 passed, 0 failed
  • pnpm exec vitest run .../ClaudeSwapAccountsSection.test.tsx: 8 passed; pnpm run build: ok; pnpm run lint: only pre-existing warnings in untouched files

Affected areas

  • Rust backend (claude-swap parser/projection)
  • Tauri shell command validation
  • Settings UI (test only, no component change)

UI proof

Pending: coordinator will capture CUA proof on a fresh build.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Finesssee

Finesssee commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

CUA proof

Build commit: 50dbe7fd07f3d9c42c2ae67ce3302343bdb97aad (equals PR head at capture time). Debug build via tauri:build:debug, not rebuilt for this run.

Proof-only patches (throwaway, never committed): workspace Cargo.toml [patch.crates-io] dirs shim redirecting home/config dirs to the kit's home\ folder, plus the matching Cargo.lock edit (see proof-patch.diff). No source files patched, no usage seed. The real %APPDATA%\CodexBar was not touched.

Commands: bash launch.sh settings:providers (fixture list-readonly.json), then negative control CSWAP_FIXTURE=...\mocks\list-switching.json bash launch.sh settings:providers. Driven with cua-driver call (list_windows, get_window_state, click, set_window_frame to 800x1180 so the list fits without scrolling) plus --screenshot-out-file.

# Assertion Result
1 Only *@example.test data visible, no real account PASS
2 Dark theme under theme: auto PASS
3 claude-swap list shows proof-active, proof-inactive, proof-foreign PASS
4 Active marker + Session 42% / Weekly 17% on active; Session 8% / Weekly 3% on inactive PASS
5 No Switch / Re-authenticate button on any of the three rows (UIA tree has none; the only Switch-like control is the unrelated Claude-wide "Switch account..." button below the list) PASS
6 Negative control (switching enabled): proof-inactive and proof-foreign each show a "Switch via claude-swap" button PASS (note: foreign row shows "Switch via claude-swap", not a "Re-authenticate" button; buttons not clicked)
7 Settings/logs written under kit home\AppData\Roaming\CodexBar, real APPDATA unchanged PASS

Screenshots (local, not committed) in %LOCALAPPDATA%\Win-CodexBar\port-audit\proof\631\shots\:

  • 01-initial.png (dark theme, Codex selected)
  • 02-claude.png (Claude selected, default window size)
  • 03-swap-list.png (read-only fixture: three rows, no buttons)
  • 04-negative-control.png (switching fixture: Switch buttons present)

Both instances and the cua session were stopped afterward.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

Adversarial validation (lane-A) at 50dbe7f

Review verdict: the branch at its published head matches the 0.65.0 audit PR-3 spec; local HEAD equals the remote head (50dbe7fd), so no re-merge or fix commit was needed. The optional top-level supportsAccountSwitching boolean is parsed in the schema-v1 envelope (absent ⇒ true; non-boolean including null/numbers ⇒ ClaudeSwapError::MalformedShape("supportsAccountSwitching is not a boolean")); when false the projection keeps usage/account details/active marker but emits no Switch or Reauthenticate action, and the shell rejects switch/reauthenticate commands for that list. ClaudeSwapAccountsSection.test.tsx covers the no-button rendering.

Checks at 50dbe7f (CARGO_TARGET_DIR=W:\cargo-target\lane-a, jobs=4, RUST_TEST_THREADS=4):

  • cargo fmt --all --check: pass.
  • cargo clippy both manifests --all-targets -- -D warnings: only the 3 documented pre-existing main-drift findings; 0 in this PR's diff.
  • cargo test rust manifest: 2164 passed / 0 failed / 1 ignored (claude focused: 211/0).
  • cargo test desktop manifest: only the documented Isolate bootstrap payload test from real settings #684 bootstrap_payload_exposes_every_provider_variant failure (env-dependent baseline on branches without Make the bootstrap catalog test hermetic (#684) #711; expected, hermetic fix lives on release/v0.70.0).
  • Vitest ClaudeSwapAccountsSection.test.tsx: 8 passed.

No new code was required; validation-only item.

@Finesssee

Copy link
Copy Markdown
Collaborator Author

Shipped in v0.70.0: this PR's head is included in main via #735 (merge commit 9d0a37a). Closing as integrated.

@Finesssee Finesssee closed this Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant