On Windows, the not(macos/linux) cfg block is the only path, so
clippy flags the return as needless. Use expression form instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gate version detection behind cfg(unix), fix unreachable Ok(()) after
return in trust_ca, use next_back() and is_some_and() per clippy.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cross-platform paths: config_dir() uses %APPDATA%, data_dir() uses
%PROGRAMDATA% on Windows. TLS cert directory uses data_dir() instead
of hardcoded /usr/local/var/numa. Windows DNS discovery via ipconfig.
Fixed cfg gates from not(macos) to explicit linux to prevent Linux
code compiling on Windows. Added Windows target to CI and release
workflows with zip packaging.
System integration (numa install/service) not yet supported on Windows
— users run numa.exe manually.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
security delete-certificate -c fails when multiple certs match.
Now finds all certs by hash and deletes each individually.
Also updated README with HTTPS, service persistence, and TLS mentions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
macOS kills unsigned binaries, so numa service restart failed after
copying a new build. Added ad-hoc codesign to restart flow and a
make deploy target that handles the full build-copy-sign-restart cycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HTTP reverse proxy on port 80 lets developers use clean domain names
(frontend.numa, api.numa) instead of localhost:PORT. Includes WebSocket
upgrade support for HMR, TCP health checks, dashboard UI panel, and
REST API for service management. numa.numa is preconfigured for the
dashboard itself.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Kills the running process and lets launchd/systemd respawn it
with the updated binary. DNS stays configured throughout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Default upstream auto-detected from system resolver (scutil/resolv.conf)
instead of hardcoding Google 8.8.8.8. Falls back to Quad9 (9.9.9.9).
- Single scutil --dns pass for both upstream detection and forwarding rules
- Linux: reads backup resolv.conf if current only has loopback
- Service start/stop now couples DNS config (install on start, uninstall on stop)
- Install script for one-line binary install from GitHub Releases
- GitHub Actions release workflow: builds for macOS/Linux x86_64/aarch64
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect systemd-resolved: use drop-in config instead of overwriting
/etc/resolv.conf (which gets regenerated)
- Warn if /etc/resolv.conf is a symlink (NetworkManager, etc.)
- Fix TOCTOU: attempt copy/remove directly, handle NotFound
- Remove side-effect from backup_path_linux (no eager mkdir)
- Fix macOS $HOME fallback: /var/root instead of /tmp
- Log warnings on launchctl/systemctl failures instead of silencing
- Delete plist before unloading (prevents zombie restarts)
- Extract ensure_binary_installed helper on Linux
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Linux:
- numa install: backs up /etc/resolv.conf, sets nameserver to 127.0.0.1
- numa uninstall: restores original /etc/resolv.conf from backup
- numa service start: installs systemd unit, enables + starts
- numa service stop: stops, disables, removes unit file
- numa service status: shows systemctl status
macOS: launchd plist (already working)
Both platforms: Restart=always / KeepAlive=true for crash recovery.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move HashMap, PathBuf, numa_data_dir, backup_path inside macOS
cfg blocks so Linux builds don't see unused imports/functions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
numa install — saves current DNS, sets all network services to 127.0.0.1
numa uninstall — restores original DNS from ~/.numa/original-dns.json
numa help — shows usage
macOS: uses networksetup to enumerate services and set/restore DNS.
Linux: stubs with instructions for manual setup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DNS-level ad blocking: 385K+ domains via Hagezi Pro blocklist, subdomain
matching, one-click allowlist, pause/toggle, background refresh every 24h
- Live dashboard at :5380 with real-time stats, query log, override
management (create/edit/delete), blocking controls
- System DNS auto-discovery: parses scutil --dns on macOS to find
conditional forwarding rules (Tailscale, VPN split-DNS)
- REST API expanded to 18 endpoints (blocking, overrides, diagnostics)
- Startup banner with colored system info
- Performance benchmarks (bench/dns-bench.sh)
- Landing page updated with new positioning and comparison table
- CI, Dockerfile, LICENSE, development plan docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>