The zero-trust model

ZTD’s name is its thesis: the host never implicitly trusts the guest. The guest is treated as compromised-by-default, and ZTD’s job is to guarantee the blast radius of anything that happens inside ends at the VM.

This is what makes it safe to run an agent in “YOLO” mode — no per-action approval prompts. The guardrail is a machine boundary, not a dialog box you’d eventually click through anyway.

What is and isn’t in scope

In scope for v1: protecting the host from the guest.

Out of scope for v1 (by design):

  • Protecting the guest from the host.
  • Isolating multiple guests from each other (multi-tenant).
  • Egress allowlisting — guests get open internet for now (see below).

Host-protection guarantees

  • The host’s Docker socket is never exposed to the guest; the guest runs its own Docker daemon. A runaway agent cannot reach your host containers.
  • No host filesystem access beyond the explicitly synced repo path.
  • The guest holds only ephemeral, narrowly-scoped credentials — nothing that grants host-wide or org-wide access.
  • The VM is destroyed after use (see Cattle, not pets), leaving no persistent foothold.

Credentials

The guest holds only two credentials, and neither grants anything on your forge:

  • VM access (SSH): a per-instance keypair generated at up, stored host-side in .ztd/keys/, injected via cloud-init, used only for ztd ssh, and destroyed with the VM. Never your personal key.
  • Agent LLM login: ztd auth syncs your existing Claude Code credential (~/.claude/.credentials.json) into the guest — the agent can’t reach the model without it, so this is the one credential that legitimately lives in the VM. It dies with the VM; scope/limit it if that matters.

Forge git stays on the host. The guest never clones from or pushes to a forge and holds no forge token — a scoped token in an assumed-compromised box is still a credential to leak. Instead the agent commits locally, ztd fetch pulls those commits back to your host checkout, and you push from the host with your own credentials. See Publish the agent’s results. No forge tokens, SSH deploy keys, or PATs in the VM.

Egress (open now, gated later)

v1 guests get open outbound internet — the simplest thing that works. The architecture reserves a network-policy hook so an allowlist can drop in later without a redesign: the intended mechanism is a local DNS resolver (Technitium) that permits only known destinations (the model API, package mirrors, git remotes), with its query log doubling as a network audit trail.

Audit

For now, the audit trail is the result branch / MR diff (what changed) plus, on teardown, an export of the agent transcript, a shell command log, and a run manifest to .ztd/runs/<run_id>/. A pluggable “audit sink” — shipping events to S3 / Loki, with Falco or Wazuh for runtime events — is a later enhancement.