Skip to content

feat(mouse): #304 PR 4h — ask_each banner + session-trust (final)#369

Merged
fentas merged 2 commits into
masterfrom
feat/304-pr4h-url-banner-trust
May 29, 2026
Merged

feat(mouse): #304 PR 4h — ask_each banner + session-trust (final)#369
fentas merged 2 commits into
masterfrom
feat/304-pr4h-url-banner-trust

Conversation

@fentas
Copy link
Copy Markdown
Owner

@fentas fentas commented May 29, 2026

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)

Key Effect
`y` / `Y` Open once; nothing persisted
`a` / `A` Add host to in-memory session-trust + open. Subsequent clicks on the same host fast-path
`t` / `T` Session-trust + surface `sudo atty-guard urls allow ` guidance. Does NOT open — would clobber the guidance hint before the user reads 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)

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`:

  • statusText shows the banner
  • hint TTL is suspended
  • Subsequent clicks are silently consumed (no second banner)

`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

  • `zig build test` — 1106/1106 (+8 new: banner arming, [y]/[a]/[t]/cancel, swallow-on-unrelated-key, whitelist fast-path, FIFO eviction)
  • `zig fmt --check`
  • `zig build -Doptimize=ReleaseSafe` — 10.7 MB binary
  • Manual end-to-end smoke (deferred — needs Ghostty session)

🤖 Generated with Claude Code

…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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

…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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@fentas fentas merged commit f5c72eb into master May 29, 2026
4 of 5 checks passed
@fentas fentas deleted the feat/304-pr4h-url-banner-trust branch May 29, 2026 23:36
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.

2 participants