ADR-0006: INFRA-1 constrained local infrastructure execution broker¶
Status¶
Accepted as the provisional design for the POWER 3.8 INFRA-1 candidate. The broker is opt-in, remains unmerged until protected admission, does not change the public version, and does not authorize Phase 5C.
Context¶
Direct SSH/SCP from an AI agent is denied by policy, but the absence of an
approved capability previously collapsed into a misleading input-required
request. POWER needs a safe, bounded path for a small class of local
infrastructure operations without turning the agent into a shell client.
Decision¶
Provide a typed client and an opt-in non-root broker over one Unix-domain
socket. The client accepts only the closed operation set status, probe,
rsync-dry-run, replicate, and verify, plus target/profile identifiers and
bounded idempotency/approval references.
The broker derives the caller principal from Unix peer credentials. It resolves
host, port, user, source roots, remote root, pinned known-hosts file,
credential ID, resource limits, approval policy, and receiver mode from an
operator-owned strict profile. It builds fixed SSH/rsync arguments with
BatchMode, password and keyboard-interactive authentication disabled,
IdentitiesOnly, IdentityAgent=none, strict host-key checking, and no
caller-controlled remote command.
The private key is delivered through systemd LoadCredential= into the broker
boundary. An explicitly enabled root/operator-owned plaintext fallback is a
lower-assurance deployment mode; it is disabled by default. In either mode the
key never enters a request, Task, receipt, MCP response, CLI output, prompt, or
vault note. Replication is immutable-run/staging oriented, requires an
idempotency key, uses a broker-owned snapshot plus bounded manifests and
output/time limits, requires a dry-run unless standing profile policy says
otherwise, and never performs remote deletion/pruning. A partial remote run is
not trusted until the separate verify operation succeeds; the broker never
silently retries an unknown write.
Task and handoff semantics¶
No new top-level Task state is introduced. Capability absence is blocked with
MISSING_EXECUTION_CAPABILITY; disabled profiles, missing pins, changed pins,
network failure, and unavailable credentials remain blocked. Missing approval is
auth-required; a genuinely missing target/profile input is input-required.
The broker block receipt is referenced through existing receipt_ids,
error_ref, and open_gates; it is not a canonical Task completion receipt.
Handoff packets remain declarative data and never execute next_action.
Alternatives rejected¶
- direct agent SSH/SCP: violates the security boundary and exposes arbitrary host/path/command selection;
- HTTP/TCP broker: expands the local trust boundary and is unnecessary;
sshpass, environment/private-key arguments, or inheritedSSH_AUTH_SOCK: leaks credentials or permits password/agent fallback;- TOFU or automatic
ssh-keyscantrust: permits host-key substitution; - a homemade
SSH_ORIGINAL_COMMANDparser: use currentrrsynccontrols; - privileged/root daemon: solve source ACLs with bounded staging and operator permissions instead of granting an agent-triggered root filesystem view.
Consequences¶
The framework can report a truthful blocked capability instead of requesting a password. A real profile and receiver remain explicit deployment evidence, not framework CI prerequisites. General automation, restore, deletion, sudo, package management, lifecycle, and firewall operations remain outside INFRA-1 and require separate gates.