Product history from the public DenyOut repository.
Unreleased
Added
Optional Account + sync (Settings to Advanced): magic-link sign-in / sign out. Sync now pull/push with last-write-wins. Delete cloud data (server account + blob). Local-only when signed out. Protect never requires an account. UX: docs/07-desktop-ux.md, docs/cloud-sync.md.
Cloud sync schema (internal/cloudsync + desktop export/apply map): versioned settings blob for optional signed-in sync. Never includes audit/secrets.
App updates (no account):internal/updates public JSON client + desktop Check for updates (Settings to Diagnostics). Home/Problems tip when newer. Fail-open if offline. Example: docs/updates/desktop.example.json.
Threat lists (Book C): Phishing Army + URLhaus (on after first good fetch) + optional Stronger (HaGeZi TIF medium). Settings Basic toggles, poll interval, Refresh now. Reason threat_list to post-block HITL. Advanced optional OISD / StevenBlack (off). Product unbreak (Book D) + read-only Product exceptions. Plan/QA: docs/ux-iters/threat-lists-plan.md, docs/ux-iters/threat-lists-qa.md.
Agent allow packs:cursor-starter / claude-starter. Ask on new agent. Undo pack in My agents.
denyout-desktop (Wails v2 + React/TS): Activity / My agents / Settings / Problems. Tray Open DenyOut.... Close hides to tray.
Dual artifacts: static denyout (CLI/proxy) + CGO denyout-desktop. Install.sh fetches both when present. Autostart prefers desktop binary.
Your setup dialog after first-run / install (mode, what to expect, Activity / Problems pointers).
Post-block confirm on Safe desktop clear threats: 15s Keep blocked / Allow this site. Keep remembered per host+reason.
Activity: Time / Site / Why. Drawer URL + codes. Always allow / Allow this site.
Post-block / deny toasts include redacted URL when known (secrets to ***).
Changed
Desktop UX backlog: compact tray. Left-click to Activity. Toast Keep blocked / Allow this site. Settings Basic | Advanced.
UX2 polish: nav My agents. Agents only to Advanced. Tips one-at-a-time. Activity Select... + Group by host under Filters. Human reason labels. Your setup Open DenyOut / Got it. Tray My agents opens window. Top bar Needs attention. Empty Activity CTA. Settings find + Jump sections.
> Tray / screen inventory below is historical for 0.2.0. Current UX (compact tray, My agents nav, Agents only in Settings to Advanced): see Unreleased and docs/07-desktop-ux.md.
Changed
Safe desktop default: Protect computer uses the browse policy (web works. Secrets/canaries/SSRF still block). Host Ask is off for Safe desktop. Whole-PC Agents only requires an explicit confirm (default No) with a messengers warning.
No silent Session: admin failure and restore no longer fall back to Session mode (stays Off). Legacy Session preference is cleared on restore with a toast. Session remains an internal/advanced path only - not a tray peer.
First-run / tray: Protect computer - My agents... - Agents only (whole PC)... - Off. Help & logs. Test. DenyOut version footer. Quit leaves Protect-on for next login. Soft Not-now nudge. Upgrade migration dialog for old Agents-only defaults.
Ask UX: urgent toast "DenyOut needs a decision" then dialog. Default button Keep blocked. ~2 min timeout to blocked. Global Ask queue. Pause after Ask storm + Resume asks. Sound on Ask only. Secret toast: "Blocked a link that looked like it contained a secret" (coalesced).
Native Ask / Activity (no web): Ask uses a 3-button OS dialog (Allow once / Always allow / Keep blocked). Concurrent Ask prompts coalesce per host. Short suppress after Keep blocked.
Open activity... opens a native denial list. Tray Always-allow list... + Undo last always-allow. Proxyd loopback JSON IPC unchanged.
IP literals: hard-deny (no Ask). Prefer Safe desktop for messengers that connect by IP.
Agent preset: Cursor allowlist includes *.cursor.sh / *.cursor.com.
Added
Named agent profiles (~/.config/denyout/profiles/*.yaml): My agents wizard. CLI denyout profile create|list|run|pin|discard|delete. Denyout run --profile .
Learning: Once to pending_once. Pin all / Discard. Counter in tray. After Pin, learning defaults off.
Stronger isolation: real --sandbox=srt wrap via Anthropic srt (fail closed if required / missing). Wrap without srt prints an honest residual line.
Docs: docs/qa-desktop-ux.md. README / 06 / 07 updated for Safe desktop vs wrap.
0.1.9 - Agent seatbelt default (breaking)
Breaking
Computer / Session default policy is no longer "allow the web + block secrets". Default is enforce + agent allowlist (models, package registries, git/CDN, Cursor hosts). Unknown hosts deny (or Ask when Ask mode is on).
Legacy "browse the web" behavior moves to the Browse policy profile (denyout.whole_device_browse.yaml, tray/Activity toggle).
New installs default Ask mode on. Existing installs keep saved Ask/AlwaysAllow. Empty policy_profile migrates to agent on load.
Added
Signed-URL / session precision: tiered named query params. Carve-outs for GitHub release-assets and AWS SigV4. Plain session= without token shape allowed.