feat(mouse): #304 PR 4h — ask_each banner + session-trust (final)#369
Merged
Conversation
…ance Final PR of #304. Adds the interactive trust posture to mouse_urls: click an untrusted URL → status-bar banner open <host>? [y]es / [a]llow / [t]rust / cancel asks the user what to do. | Key | Effect | |---|---| | `y` / `Y` | Open once; nothing persisted | | `a` / `A` | Add host to in-memory session-trust + open | | `t` / `T` | Session-trust + surface `sudo atty-guard urls allow <host>` guidance (NO open — opening would clobber the hint before the user can read it; click again to launch via the session-trust fast-path) | | Esc / Ctrl-C / Ctrl-U / `c` | Cancel; nothing happens | | anything else | swallowed (don't poison the shell prompt while banner is up) | The daemon-side `urls allow` RPC requires EUID 0 (see atty-guard/src/server.rs::handle_urls_allow), so atty can't write permanent trust itself; `[t]` surfaces the sudo command the user would run to persist the host across sessions. `hostTrusted` checks both `url_whitelist` (config-static) and the in-memory `session_hosts` ring before arming. Ring is FIFO-evicted at `session_trust_capacity` (default 64); dedup on add. While `armed=true`, statusText shows the banner and hint TTL is suspended. Subsequent clicks are silently consumed (no second banner). `whitelist_only` mode also gets the session-trust check for free — `[a]` works there too, just without the prompt. 1106/1106 tests pass (+8 new banner / session-trust / FIFO tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nits - FIFO test: expand to 5 adds with cap=3, assert hc/hd/he present AND ha/hb evicted, plus a fast-path proof that surviving entries hostTrust. Was: only checked ha missing — wouldn't have caught a "all entries evicted" regression. - New paired test "'y' on first host, 'a' on second": locks the invariant that 'y' doesn't fall through to 'a'. Previously each branch had its own fresh runtime so cross-arm contamination wouldn't have been caught. - `setPersistHint` long-host fallback now uses `stripPort(host)` instead of raw host — consistent with the normal path. - Module docstring + config.def.zig now spell out the ordering rule: place mouse_urls BEFORE guardrail in the modules tuple so the banner's y/a/t keystrokes win over guardrail's armed prompt. 1107/1107 pass (+1 paired y/a test; FIFO test rewrite is net-zero). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Final PR of #304. Adds the interactive trust posture to `mouse_urls` — click an untrusted URL, get a status-bar banner that asks what to do.
```
open ? [y]es / [a]llow / [t]rust / cancel
```
Key bindings (while armed)
Why `[t]` doesn't call atty-guard
The daemon's `urls allow` RPC requires `peer.is_root` (see `atty-guard/src/server.rs:942-965`). atty runs as the user, so we can't write to the persistent trust file directly. The surfaced sudo command gives the user a one-shot way to escalate when they really want persistence.
Trust resolution
`hostTrusted` checks both `url_whitelist` (config-static) and the in-memory `session_hosts` ring before arming. The ring is FIFO-evicted at `session_trust_capacity` (default 64); add operations dedupe.
While `armed=true`:
`whitelist_only` mode benefits too — once you `[a]` a host in `ask_each`, switching back to `whitelist_only` still honours it for the session.
Roadmap (#304) — complete
#304 closes once this lands.
Test plan
🤖 Generated with Claude Code