Skip to content

feat(security): permission mode selector with auto-detection, scope granularity, and single-instance enforcement#85

Merged
siracusa5 merged 4 commits intomainfrom
feat/permission-mode-selector
Apr 7, 2026
Merged

feat(security): permission mode selector with auto-detection, scope granularity, and single-instance enforcement#85
siracusa5 merged 4 commits intomainfrom
feat/permission-mode-selector

Conversation

@siracusa5
Copy link
Copy Markdown
Collaborator

Summary

Adds a fully-featured permission mode selector to the Security → Permissions page, with automatic Claude account detection to gate Auto mode, per-tool scope granularity (e.g. Read(~/repos/**) patterns), a live "Current configuration" summary banner, graceful degradation when running outside the Tauri desktop environment, and single-instance window enforcement.

Changes

  • Permission mode selector: Mode cards (Default, Skip, Auto) rendered from localStorage with first-run modal. Auto mode card only shown when the user's Claude account qualifies (team/enterprise/business/API key — not max/pro).
  • Auto account detection: New detect_claude_account Tauri command runs claude auth status, parses subscription type, and returns auto_mode_available. Frontend calls this on mount and auto-shows/hides the Auto card without a manual disclosure toggle.
  • Tool scope granularity: Allowed tools checklist now supports Tool(pattern) entries (e.g. Read(~/repos/**), Bash(git *), WebFetch(https://api.github.com/*)). Active tools render as rows with a scope input column; inactive tools render as + ToolName chips.
  • Current configuration summary: Live banner above the settings.json section showing active mode, tool list, and override count.
  • Graceful degradation: When window.__TAURI_INTERNALS__ is absent (browser/dev), the settings.json section shows "requires the desktop app" instead of a raw TypeError.
  • Single-instance enforcement: tauri-plugin-single-instance focuses the existing window when a second instance is launched.
  • Test fixes: Added window.__TAURI_INTERNALS__ setup/teardown in beforeEach/afterEach and missing mock entries (detectClaudeAccount, getAutoModeUnlocked, setAutoModeUnlocked) so all 638 tests pass.

Test Plan

  • All 638 tests pass (pnpm test --run in apps/desktop)
  • Permission mode cards render and persist to localStorage
  • Auto card hidden when auto_mode_available: false, shown when true
  • Tool scope inputs accept and persist Tool(pattern) format
  • Settings.json section shows graceful message outside desktop app
  • Second app launch focuses existing window instead of opening new one
  • CI checks pass

Notes

The detect_claude_account command shells out to claude auth status — if the Claude CLI is not installed, it returns { logged_in: false, auto_mode_available: false } gracefully. The Auto mode card is suppressed in that case.

siracusa5 and others added 4 commits April 7, 2026 00:13
… tool approval panel

Replaces the hardcoded --allowedTools flag with a user-configurable
permission mode system. Three modes: Skip All (default, --dangerously-
skip-permissions), Auto (--permission-mode auto, for paid plans), and
Allowed Tools (--allowedTools with per-tool checklist).

Security → Permissions now leads with a mode selector section featuring
icon cards, flag badges, and a clear selected state. An allowed-tools
checklist and per-harness overrides are available below. A one-time
first-run modal surfaces before the first task execution. A slide-in
ToolApprovalPanel lets users manage the allowed tools list mid-session
from within the terminals view.

All preferences persist in localStorage under harness-kit- keys.
resetPermissionDefaults() clears tool list, ack flag, and overrides.

638/638 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…llback

getAllowedTools now filters stored entries against /^[A-Za-z]+(\([^)\]+\))?$/
so arbitrary localStorage strings cannot reach the Claude CLI flag.

Empty allowed-tools list no longer falls back to --dangerously-skip-permissions;
Claude's default prompting behavior (no permission flag) is now used instead,
which matches user expectation that an empty list means "prompt for everything."

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stance

- tauri.ts: export detectClaudeAccount + ClaudeAccountInfo interface
- tool-names.ts: add scopeHint/scopeLabel fields for per-tool scope input hints
- PermissionsPage.test.tsx: add window.__TAURI_INTERNALS__ setup/teardown
- vite.config.ts: ignore .auto-claude/** to prevent Vite watching worktree artifacts
- Cargo.toml + Cargo.lock: add tauri-plugin-single-instance dependency
- settings.rs: detect_claude_account command (parses claude auth status)
- lib.rs: register single-instance plugin and detect_claude_account command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@siracusa5 siracusa5 force-pushed the feat/permission-mode-selector branch from b5f8cd1 to 3f84593 Compare April 7, 2026 04:13
@siracusa5 siracusa5 merged commit 2c38e1e into main Apr 7, 2026
16 checks passed
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