Per-terminal privacy (toggle + wipe) + free-form sessions (create + real close)#34
Open
falkoro wants to merge 1 commit into
Open
Per-terminal privacy (toggle + wipe) + free-form sessions (create + real close)#34falkoro wants to merge 1 commit into
falkoro wants to merge 1 commit into
Conversation
… real close) B2 — privacy: a per-shell private-mode toggle (persisted in private-sessions.json) redacts that session's preview, work-title, and SSE output server-side and excludes it from the summary LLM. A private session also cannot be opened as a live terminal — /api/term returns 403 and the Shell-in control is disabled — so a private session's output never leaves the server. Plus a one-tap wipe (/api/wipe) that runs tmux clear-history + clears the screen, evicts the cached summary, and scrubs the local preview cache. B3 — free-form sessions: a "New session" form creates a real tmux session (name + command + cwd, validated; persisted in dynamic-sessions.json so it survives restarts) and merges into the session list; Close on a dynamic session kills it AND removes it (config slots keep the existing kill-only Stop). Removing a session also clears any stale private flag. New modules src/dynamic_sessions.rs + src/private_sessions.rs (tolerant JSON stores, strict name/cwd validation). All new endpoints gated by require_unlock + the CSRF action header. Reviewed by a 3-lens adversarial pass; the one real leak (live-terminal bypass of privacy) is fixed and verified (WS 403, preview redacted, create/close round-trip). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Implements two new backend+frontend features for ShellDeck session management: per-session privacy (server-side redaction + terminal block + wipe) and persisted “free-form” (dynamic) tmux sessions that can be created and fully removed.
Changes:
- Adds per-session privacy state persisted to
private-sessions.json, redacting preview/title/summary context and blocking/api/termfor private sessions. - Adds dynamic sessions persisted to
dynamic-sessions.json, including create + true close/remove semantics. - Extends UI controls to toggle privacy, wipe a session, and create/close dynamic sessions, including updated styling.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/tmux.rs |
Adds managed session abstraction, dynamic session create/remove, private redaction in shell previews, and wipe support. |
src/term.rs |
Blocks WebSocket terminal access for private sessions. |
src/summary.rs |
Excludes private sessions from summary LLM context. |
src/routes.rs |
Adds /api/private, /api/wipe, and dynamic session create/remove endpoints with unlock + CSRF action gating. |
src/private_sessions.rs |
New module for persisting/loading private session set. |
src/dynamic_sessions.rs |
New module for persisting/loading/validating dynamic session definitions. |
src/main.rs |
Registers new Rust modules. |
src/config.rs |
Adds config paths for private/dynamic session state files. |
public/terminal.js |
Prevents opening terminals for private sessions; exposes close-by-session helper. |
public/render.js |
Adds privacy toggle + wipe UI, and private-mode rendering behavior. |
public/events.js |
Wires click handlers for privacy/wipe/new session and dynamic close behavior. |
public/core.js |
Tracks private sessions client-side; updates UI state and local caches accordingly. |
public/actions.js |
Implements /api/private, /api/wipe, and /api/sessions/* client actions and new-session modal. |
public/app.css |
Styles for private mode and new session modal layout. |
frontend/terminal.ts |
TS source for terminal private-session gating + close helper. |
frontend/render.ts |
TS source for privacy/wipe UI and private-mode rendering behavior. |
frontend/events.ts |
TS source for wiring privacy/wipe/new session and dynamic close behavior. |
frontend/core.ts |
TS source for private session state tracking + UI updates. |
frontend/actions.ts |
TS source for private toggle, wipe, and dynamic session create modal/actions. |
.gitignore |
Ignores runtime JSON state files for dynamic/private sessions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+564
to
+568
| if body.private { | ||
| if let Ok(mut cache) = state.summary_cache.lock() { | ||
| *cache = None; | ||
| } | ||
| } |
Comment on lines
+297
to
+298
| let managed = managed_sessions(config.clone()).await; | ||
| let private = private_sessions::load(config.clone()).await; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds the two approved features. Not merging yet — recommend deploying #33 (stabilization) first and confirming the live instance is happy, then merge + deploy this.
B2 — Per-terminal privacy
private-sessions.json): redacts that session's preview, work-title and SSE output server-side, and excludes it from the summary LLM./api/termreturns 403 and Shell-in is disabled — so its output never leaves the server. (This closed the one real leak the review found.)/api/wipe):tmux clear-history+ clear screen + evict cached summary + scrub local preview cache.B3 — Free-form sessions
dynamic-sessions.json(survives restart), merged into the session list.New modules
src/dynamic_sessions.rs+src/private_sessions.rs. All new endpoints gated byrequire_unlock+ CSRF action header.Verification
3-lens adversarial review (security/correctness/frontend): gating correct on all 5 endpoints, command/cwd handling safe (argv not shell), 31 tests pass, no formatting churn. The HIGH finding (live-terminal privacy bypass) was fixed and I re-verified end-to-end: private → WS 403 +
/api/shellsoutput redacted; Shell-in disabled + "output hidden" placeholder + work-title blank; non-private opens normally; free-form create → real tmux session → close kills + removes. 0 console errors.🤖 Generated with Claude Code