delego 0.3.4 — single-writer daemon - #18
Merged
Merged
Conversation
One long-running process owns the Firewall and exposes it over a Unix domain socket (line-delimited JSON, stdlib socketserver — no new dependency), serializing every operation under a single lock. So every client routes through one writer and a rate_limit is exact ACROSS ALL CLIENTS (the spec's serialized single-writer ledger, §5/§11), not just one host's file lock. - delego/daemon.py: serve() + the UDS server. Windows-guarded (needs AF_UNIX), main-thread-guarded signal handlers, deep listen backlog, chmod 0600, probe-before-unlink so a second daemon refuses to start. - delego/client.py: DaemonClient (propose/resolve/decide/pending/policy/ audit_tail/verify/ping) + daemon_running(). - Paths.socket lives in the per-user runtime dir keyed by a hash of the home (Unix socket paths are length-limited; a deep home would overflow). - CLI: 'delego daemon' to run it; approve/deny/pending auto-route to a live daemon (the sole writer) so a human decision can't fork state behind it. - Off by default: no daemon -> file-backed, unchanged. Protocol still 0.3; package 0.3.4. 7 new tests incl. 16 concurrent clients vs rate_limit max:3 -> exactly 3 allows; 72 total green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the single-writer daemon — the spec's serialized single-writer ledger, made real. Protocol unchanged (0.3); the daemon is optional (no daemon → file-backed, exactly as before). Package → 0.3.4.
Why
Without it, a
rate_limitis exact only among processes sharing one home on one host (the file lock).delego daemonmakes one process the sole owner of theFirewall; every client routes through it, so the cap is exact across all clients — and the ledger has one writer by construction.What
delego/daemon.py—serve()+ aThreadingUnixStreamServerwith a single lock around every op (line-delimited JSON over a UDS, stdlib only, no new dependency). Hardened: Windows-guarded (needsAF_UNIX), main-thread-only signal handlers, deep listen backlog,chmod 0600, and a probe-before-unlink so a second daemon refuses to start (two writers is the one thing this prevents).delego/client.py—DaemonClient(propose/resolve/decide/pending/policy/audit_tail/verify/ping) +daemon_running().Paths.socketin the per-user runtime dir keyed by a hash of the home (Unix socket paths are length-limited; a deep.claude/.delegowould overflow).delego daemonruns it;approve/deny/pendingauto-route to a live daemon (the sole writer) so a human decision can't fork state behind it.Verification
72 tests (7 new): the headline — 16 concurrent
DaemonClient.proposeagainstrate_limit max:3→ exactly 3 allows (cross-client exactness the file lock alone can't give) — plus full approval loop over the socket, second-daemon-refuses, bad-request-doesn't-kill-connection, ping/round-trips.examples/demo.pygreen; existing 65 unchanged (opt-in).Scoped out (follow-ups, noted in ROADMAP)
Routing the MCP agent surface to the daemon (next — realizes exact cross-client limits for agents in prod, not just CLI/tests); a TCP/cross-host transport; and a reserve-then-execute path (broker call outside the lock). Docs: README/ROADMAP/SECURITY updated; the landing /docs site is a separate follow-up PR.