Skip to content

Consolidate dev improvements: pane zoom, font sizing, quit confirm, preview cleanup, security hardening#154

Open
alxjrvs wants to merge 5 commits into
mainfrom
dev-consolidation
Open

Consolidate dev improvements: pane zoom, font sizing, quit confirm, preview cleanup, security hardening#154
alxjrvs wants to merge 5 commits into
mainfrom
dev-consolidation

Conversation

@alxjrvs

@alxjrvs alxjrvs commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Consolidates several independent improvements developed on the dev line into main. Each is isolated to its own commit.

What's included

1. Pane zoom (feat(terminal))

  • Cmd/Ctrl+Enter toggles a maximized ("zoomed") pane that fills the workspace, hiding sibling panes and the split divider. Toggling again — or zooming a different surface — restores the split layout. Ephemeral, not persisted.

2. Adjustable terminal font size (feat(terminal))

  • Cmd/Ctrl +/- adjust font size (clamped 8–32px); Cmd/Ctrl 0 resets to 14px. Persisted to config and re-fit across every open terminal, so it survives restart.

3. Quit confirmation (feat(terminal))

  • The window close request is intercepted; when live PTYs exist, an in-app ConfirmPrompt modal asks before tearing them down (WKWebView has no window.confirm). With zero live terminals, quit proceeds with no prompt.

4. Preview resource cleanup (fix(preview))

  • Previewers can return a cleanup function from render(); the PDF previewer now revokes its Blob URL and removes the iframe on dispose. Also fixes a file-changed listener leak (one per preview opened).

5. PTY notification sanitization & humanization (feat(security))

  • Strips C0/C1/DEL control chars and caps notification text at 500 chars. OSC 777 notify;<title>;<body> payloads render as <title>: <body> instead of leaking the raw prefix.

6. Filesystem path hardening (feat(security))

  • validate_read_path fails closed (literal check before canonicalize) and rejects symlinks into blocked dirs. Blocklist extended (.netrc, .git-credentials, .npmrc, .pypirc, shell histories, macOS keychains). file_exists reports blocked paths as non-existent so callers can't probe for sensitive files.

Adds ~69 tests (293 → 362) plus new Rust unit tests for notification sanitization and path validation.

Test plan

Pane zoom

  • Split a workspace into 2+ panes; focus one and press Cmd+Enter (macOS) / Ctrl+Enter (Linux/Win) — focused pane fills the workspace, siblings + divider hidden
  • Press the shortcut again — split layout restores at the prior ratio
  • With a pane zoomed, zoom a different surface — view switches to the new one (no need to un-zoom first)

Font size

  • Cmd/Ctrl + enlarges every open terminal; Cmd/Ctrl - shrinks them
  • Cmd/Ctrl 0 resets to default (14px)
  • Confirm clamping: repeatedly shrink → stops at 8px; enlarge → stops at 32px
  • Change size, quit & relaunch — size persists from config

Quit confirmation

  • With at least one running terminal, close the window — confirmation dialog appears; Cancel keeps the app open
  • Repeat and choose Quit — app closes
  • Close all terminals (no live PTYs), then quit — no prompt, closes immediately

PDF preview

  • Open a .pdf from the file tree — renders in an iframe
  • Close the preview tab, reopen several PDFs in succession — no growth in memory/leaked listeners over repeated open/close

Notifications

  • Trigger a Claude Code (or printf '\e]777;notify;Title;Body\a') notification — workspace row shows Title: Body, not the raw notify; prefix
  • Emit a notification containing escape/control bytes — they're stripped, no garbled output

Path security

  • Attempt to preview/read ~/.ssh/id_rsa (or ~/.netrc) via the app — access denied
  • Confirm normal project files still open and preview as before

🤖 Generated with Claude Code

alxjrvs and others added 3 commits June 12, 2026 23:34
- Cmd/Ctrl+Enter toggles a maximized ("zoomed") pane that fills the
  workspace, hiding sibling panes until toggled off.
- Cmd/Ctrl +/-/0 adjust the terminal font size (clamped 8-32px),
  persisted to config and re-fit across every open terminal.
- Intercept the window close request and confirm when live PTYs exist
  via a new in-app ConfirmPrompt (WKWebView has no window.confirm).

Co-Authored-By: alxjrvs <alxjrvs@gmail.com>
Previewers may now return a cleanup function from render(); openPreview
threads it through and exposes a dispose() on the surface so the
PreviewSurface component can release resources on close.

- PDF previewer revokes its Blob URL and removes the iframe on dispose,
  guarding against a teardown that races the async file read.
- The file-changed listener handle is captured and detached on dispose,
  fixing a listener leak of one per preview opened.

Co-Authored-By: alxjrvs <alxjrvs@gmail.com>
- Strip C0/C1/DEL control characters and cap notification text at 500
  chars so malicious PTY output can't inject control sequences into
  native system notifications.
- Humanize OSC 777 'notify;<title>;<body>' payloads to '<title>: <body>'
  so the raw prefix never reaches the workspace row.
- validate_read_path now fails closed: the literal path is checked before
  canonicalize so a sensitive-but-absent path (e.g. ~/.ssh/id_rsa) is
  still denied, and the canonical path is re-checked to reject symlinks
  into blocked dirs.
- Extend the blocklist (.netrc, .git-credentials, .npmrc, .pypirc, shell
  histories, macOS keychains) and make file_exists report blocked paths
  as non-existent so callers can't probe for sensitive files.

Co-Authored-By: alxjrvs <alxjrvs@gmail.com>
alxjrvs and others added 2 commits June 12, 2026 23:55
The pull_request trigger was filtered to base=main, so stacked PRs (whose
base is a feature branch) got no CI. Drop the base-branch filter so every
PR runs CI regardless of its base.

Co-Authored-By: alxjrvs <alxjrvs@gmail.com>
The prior commit added an explanatory comment but left the
`branches: [main]` line under `pull_request` in place, so stacked PRs
were still filtered out. Remove the filter for real.

Co-Authored-By: alxjrvs <alxjrvs@gmail.com>
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