5 Commits
Author SHA1 Message Date
tke 25780cd6e8 fix(proxy): unit file carries DISPLAY + DBUS_SESSION_BUS_ADDRESS
Lockout notifications need a session path; systemd user services start with an
empty Environment, which made notify-send silently unreachable. Installer now
writes the current DISPLAY and the user-bus address (XDG runtime dir) into the
unit; deploy + daemon-reload + restart applied live and verified (7 listeners,
routed profiles answer 200).
2026-09-24 13:12:18 +02:00
tke be0e2d84cc feat(proxy): desktop lockout notification + 'proxy-bridge reauth' command
Notification path (bridge.js): entering auth lockout fires ONE desktop
notification per episode (notify-send, critical urgency), only when a session
is detectable (DBUS_SESSION_BUS_ADDRESS or DISPLAY) — headless stays silent.
Message explains the 407 cause and points at 'proxy-bridge reauth'.

Recovery path (proxyctl.js): 'proxy-bridge reauth' prompts masked, verifies the
new password with a SINGLE upstream CONNECT (407 -> NOT stored), stores via
secret-tool on success, then writes a reauth-stamp.json the bridge watches
(1s poll): clears in-memory authState and reloads keyring creds — no restart.

Shared one-shot verifier extracted to verify-creds.js (install.js + proxyctl.js
use the same code; also fixes proxyctl 'setup' shelling to the retired
/opt/setup.js — 'reauth' is its replacement for the password-expiry flow).

Tests: +3 bridge (notify once-per-episode incl. remediation hint; headless
silent; stamp clears lockout without restart) +2 proxyctl (verified stored +
stamped; rejected never stored/stamped). Suite: 28/28.
2026-09-24 13:10:42 +02:00
tke a23fa00dfb feat(proxy): apt proxy audit + doctor mode; reinstall-from-clone = update
apt-audit.js scans EVERY file in apt.conf.d for Acquire::*::Proxy, classifying:
- creds: embedded userinfo (plaintext leak + stale-cred hammering risk)
- overrides: sorts after 80proxy-bridge so apt last-wins REPLACES the bridge URL
- external: points at a non-bridge proxy
Installer Legacy section alerts + fixes (backup kept: *.disabled-by-proxy-bridge).
New 'install.js doctor [--fix]': audits apt, bashrc, snap, service drop-ins,
service state, keyring presence; exit 1 when issues found.

Update semantics: deploy writes .installed-from (git commit + file hashes);
runtime JSONs are never created if present and never overwritten; tests prove
3 consecutive installs leave runtime state byte-identical. Downgrade protection
comes from the visible marker + diff reporting, never silent clobbering.

Tests: 6 audit + 2 installer (update-semantics, doctor) — suite now 23/23.
2026-09-23 16:07:53 +02:00
tke 753fac9fe9 fix(proxy): installer — no prompts during dry-run; never pin service to agent-bundled node
- askConfirm short-circuits non-interactively in --dry-run (prints what would be asked)
- systemd node resolution order: existing unit's pinned binary > newest nvm node >
  PATH lookup excluding hermes-agent runtimes > process.execPath. On the live box
  this keeps the unit byte-identical (true idempotency for the service section).
2026-09-23 15:15:33 +02:00
tke 3f9be30784 feat(proxy): idempotent interactive installer; retire credential-embedding legacy scripts
install.js (node, replaces install_proxy.sh + setup.js + update_*.sh + get_proxy.sh):
- sections: preflight, deploy, config import/create, credentials, legacy migration,
  systemd unit, system-wide proxy (bashrc/apt/docker/snapd/ollama), verify
- idempotent: re-run converges; tests prove a second non-interactive run shows
  zero CHANGED
- imports existing /opt configs non-destructively; asks before changing
- credentials: prompted when keyring entry missing; verified with ONE CONNECT
  round-trip before storing; 407 responses are never stored (anti-lockout);
  unreachable upstream stores nothing
- legacy migration: removes bashrc #PROXY_A93JK2 line + plaintext-cred files,
  rewrites cred-embedding apt/snap/service drop-ins to the bridge URL
- flags: --dry-run, --non-interactive (fails listing missing info), --no-systemd

Tests cover dry-run-no-op, idempotency, verify-store-on-200, refuse-on-407.
2026-09-23 15:14:19 +02:00