Files
peltier.io/agent/hotpath_agent/harness.py
T
Claude e0c5018008 agent: OS-level isolation for the agent tool boundary (SPEC §10)
harnessd gains --socket mode (Unix socket, trusted uid, mutating ops
serialized); the harness client speaks socket when
HOTPATH_HARNESS_SOCKET is set. scripts/agent-isolated.sh launches an
attempt with the agent tree confined — mountns mode (repo bind-mounted
read-only, CAP_SYS_ADMIN/CAP_SYS_PTRACE dropped; no credential copying)
or user mode (unprivileged hpagent, bench-metal shape).
scripts/isolation-check.sh + just isolation-check verify the boundary
from the agent's side: 19 checks, both modes, all passing — repo
writes, forged ledger INSERTs, trust-binary replacement, rw remounts,
and userns re-entry all refused; the harnessd socket door works.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcKPWQ3MQD4NdEHwar96u2
2026-07-10 04:43:08 +00:00

71 lines
2.4 KiB
Python

"""Client for harnessd — the agent's only door to the trust layer.
Two transports:
- Unix socket (production/SPEC §10): if HOTPATH_HARNESS_SOCKET is set,
connect to a daemon owned by the trusted uid. The agent process runs
unprivileged and cannot write the repo except through this door.
- Spawned stdio subprocess (dev fallback): same uid, defense-in-depth
only — the filesystem boundary does not hold in this mode.
The client is deliberately dumb: no retries that could double-apply a
patch, no local fallbacks that could fabricate evidence.
"""
from __future__ import annotations
import json
import os
import socket
import subprocess
from typing import Any
class HarnessError(RuntimeError):
"""The harness refused or failed an operation."""
class HarnessClient:
def __init__(self, repo_root: str, binary: str = "target/debug/harnessd"):
sock_path = os.environ.get("HOTPATH_HARNESS_SOCKET")
self._proc: subprocess.Popen[str] | None = None
self._sock: socket.socket | None = None
if sock_path:
self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._sock.connect(sock_path)
self._io = self._sock.makefile("rw", encoding="utf-8", newline="\n")
else:
self._proc = subprocess.Popen(
[binary],
cwd=repo_root,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True,
)
def call(self, op: str, **kwargs: Any) -> dict[str, Any]:
payload = json.dumps({"op": op, **kwargs}) + "\n"
if self._sock is not None:
self._io.write(payload)
self._io.flush()
line = self._io.readline()
else:
assert self._proc and self._proc.stdin and self._proc.stdout
self._proc.stdin.write(payload)
self._proc.stdin.flush()
line = self._proc.stdout.readline()
if not line:
raise HarnessError("harnessd connection closed")
resp = json.loads(line)
if not resp.get("ok"):
raise HarnessError(resp.get("error", "unknown harness error"))
return resp["result"]
def close(self) -> None:
if self._sock is not None:
self._io.close()
self._sock.close()
if self._proc is not None:
if self._proc.stdin:
self._proc.stdin.close()
self._proc.wait(timeout=10)