c50e72e17b
- Close Agent-Sudo (infra id=176) design grill-me; gap #5 cross-cutting locked - Add P0-P5 phased background-agent build prompts (Opus 4.8 upgrades applied) - Add agent_sudo_vs_sudo_bridge.md comparison doc - Update context.md: sprint day 11 session 4, Coolify/N8N/port-8084 corrections Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54 lines
6.5 KiB
Markdown
54 lines
6.5 KiB
Markdown
# Agent-Sudo vs. the old sudo-bridge — what actually got better
|
||
|
||
Written 2026-07-08. Companion to `agent_sudo_design_decisions.md` (design, D1–D10) and the P0–P5 build prompts in `agent_prompts.md`.
|
||
|
||
Your instinct — *"more elaborate and complicated, but more eloquent and better-suited"* — is right, and here's the precise reason: **the extra machinery all buys back a single thing the old bridge could never have — safety WITHOUT a human in the loop.** The old bridge tried to be safe by *asking you*. Agent-Sudo is safe by *construction*. That's not a bigger version of the same idea; it's a different idea.
|
||
|
||
---
|
||
|
||
## The one-sentence difference
|
||
- **sudo-bridge:** "Run it if it's on a list; for anything risky, ping Kaleb and wait." → safety depends on you being awake, reachable, and able to judge the command.
|
||
- **Agent-Sudo:** "Run it if it's provably safe/reversible; test it if it's unknown; snapshot it if it's live; refuse it if it's catastrophic — and never ask a human to rubber-stamp what they can't evaluate." → safety depends on nothing human at runtime.
|
||
|
||
---
|
||
|
||
## Side-by-side
|
||
|
||
| Dimension | Old sudo-bridge | Agent-Sudo | Why it matters |
|
||
|---|---|---|---|
|
||
| **Risk model** | 3 states: refuse / auto / **ask-human** | 5 tiers: auto-safe / auto-reversible / **sandbox-first** / **snapshot+execute** / hard-refuse | The middle of the old model was "interrupt Kaleb." The middle of the new model is "prove it's safe by testing or snapshotting." Judgment moved from you to evidence. |
|
||
| **The human gate** | Tier-2 = NTFY approve/deny, 900s timeout | **Eliminated.** Only residual human touch = a rare Tier-4 hard-refuse | The gate was *broken* (you missed NTFYs → timeouts, ×5 agents) AND *theatrical* (you approved commands you couldn't vet). Removing it is the whole point. |
|
||
| **Unknown command** | Not on list → refuse (dead end) | Reproducible → **test in an Incus mirror**, read the audit, self-classify; if the sandbox lacks a dep, **add it to the rebuild script and retry** | The old bridge never learned. Agent-Sudo's allowlist self-completes from evidence. |
|
||
| **Autonomy when you're away** | Stalls on anything tier-2 | Runs every Tier 0–3 unattended; only *expanding* what's allowed waits for you | Automations don't freeze at 3am because you're asleep. |
|
||
| **Live-service ops** (docker/systemctl/DB) | auto or ask — no safety net | **Timeshift snapshot + scoped-undo captured BEFORE execute + auto-verify after** | A bad restart is recoverable by construction, not by luck. |
|
||
| **Rollback** | none (a tier-1 command just ran) | **scoped command-specific undo** captured pre-execution (file backup / package record / Jenkins redeploy) | Blast radius = only what the command touched. |
|
||
| **Host awareness** | one flat list, same on both | **per-host tiering** — primary is stricter; a command that's Tier-3 on server-01 can be Tier-4 (refuse) on primary | Production (Vault/Authelia/media/DB) gets a bigger no-go set than the test box. |
|
||
| **Security philosophy** | gate access (ask a human) | **constrain capability** (least-priv allowlist it *cannot widen itself*) + execute-vs-expand split | Compromising the smart brain inherits only "do already-safe things" — it can't reach arbitrary commands or Tier-4. |
|
||
| **Config integrity** | allowlist.json, root-owned file | **SUDO.md signed via Vault transit**, daemon verifies before load | The ruleset can't be silently widened; tamper = refuse + alert. |
|
||
| **Credentials** | daemon runs as root, no auth on the exec path | dumb root executor **+ scoped short-TTL Vault AppRole** (reads exactly one secret path) + AppArmor/seccomp/egress-lockdown | Auth-agnostic and least-privilege; survives your fingerprint→privacyIDEA→YubiKey roadmap without redesign. |
|
||
| **Anomaly response** | none | **self-disarming circuit-breaker** (abnormal rate/mix/failure → auto-stop Tier-3 + alert) + **dual-service concurrence** on Tier-3 | The autonomous replacement for a human panic button. |
|
||
| **Watchdog** | none | **Hermes** (separate process, no exec power) as independent monitor/second-opinion/tamper-detector — later layer | Separation of duties: Agent-Sudo has hands + no judgment, Hermes has judgment + no hands; they check each other. |
|
||
| **Training data** | executions logged, never used | every classify/test/execute/review → labeled row in `command_audit`; **AI-proposal → your review verdict = gold label** for the local model | The system gets smarter over time and feeds the local brain. |
|
||
| **Audit** | JSONL→Postgres, fail-soft (good) | same resilience **+ append-only, shipped off-box** | Even a full host compromise can't erase the trail. |
|
||
| **Deploy/lifecycle** | Coolify-managed | plain docker-compose via **Jenkins/Gitea** (Coolify retired) | No dependency on retired infra; fits the current stack. |
|
||
| **API contract** | `POST /exec` etc. | **identical** (drop-in) — `/approve` `/deny` removed | Zero caller changes; T2/T3 just add latency transparently. |
|
||
|
||
---
|
||
|
||
## What the old bridge did well (and Agent-Sudo keeps)
|
||
Not everything was wrong — these carry over unchanged:
|
||
- **Dumb root daemon + unprivileged brain** (separation of privilege) — kept and hardened.
|
||
- **Independent re-validation in the daemon** (defense in depth — the executor doesn't trust the brain) — kept.
|
||
- **Danger-pattern regex veto** — kept, now auto-routes to Tier-4.
|
||
- **fnmatch first-match-wins ordered list** — kept as the engine core, extended with per-host overrides + verb heuristic.
|
||
- **JSONL-first→Postgres fail-soft audit** — kept, extended to append-only/off-box + training fields.
|
||
|
||
So it's an **evolution of a known-good core**, not a rewrite — which is exactly why the build (P2) refactors the existing `app.py`/`daemon` rather than greenfielding.
|
||
|
||
---
|
||
|
||
## The honest cost of "more elaborate"
|
||
Agent-Sudo is genuinely more to build and run: an Incus sandbox substrate, a signed ruleset, a scoped-undo library, snapshot automation, an AI evaluator, a circuit-breaker, dual-concurrence. That complexity is real. But every piece exists to remove a human from the runtime path while *raising* safety — and the design deliberately **added no new external tool** (Incus, Vault, AppArmor, Timeshift, Jenkins already exist; Falco/OPA are parked as future options). The complexity lives in *our* code and config, not in new attack surface.
|
||
|
||
**Bottom line:** the old bridge's ceiling was "a human bottleneck that half-works." Agent-Sudo's floor is "safe, autonomous, self-improving, and it can't widen its own powers." It's not that sudo-bridge was bad — it's that it was solving the problem with the one ingredient (you, at runtime) we most need to remove.
|