Act III · Keys

The hub is the only door

Secure multi-host mode: the agent attaches to the hub only. Hub reaches spokes over SSH only. Spokes execute localhost and cannot lateral-move via this fabric.

Agent to hub to spokes over SSH AGENT OpenCode / MCP stdio hub session HUB ctrl-01 inventory SoT SSH SPOKE spoke-01 · localhost SPOKE spoke-02 · localhost SPOKE spoke-03 · localhost EMPTY BAY not enrolled
Enrollment
01
hub init --name ctrl-01
Keys, hub identity, empty inventory
02
hub issue-token --name web-03 --ttl 15m
Signed, TTL, one-time jti replay cache
03
spoke join --token … --hub user@hub:22
Token + SSH identity → inventory bay fills
04
ForceCommand → spoke session
Mesh path is not a login shell
Mesh vs bastion
Full mesh Hub/spoke
Worker compromise MCP-hop fleet No lateral MCP
Inventory Gossip / replicas Hub is SoT
Agent attach Any node Hub only
Ops model Mesh OS Classic bastion
Dual SSH identities — never conflate them. Mesh hop uses the hub client key + ForceCommand user for spoke_call. Ansible runs use a separate identity. Putting interactive Ansible expectations on a ForceCommand-only user deadlocks runs.

Operators

Same surface as the agent

Enroll, group, hand the hub to OpenCode. Day-2 is a TUI, not a second product.

ansible-flow-mcp hub init --name ctrl-01
ansible-flow-mcp hub issue-token --name web-03 --ttl 15m
ansible-flow-mcp spoke join --token "$TOKEN" --hub user@hub:22 --public-addr web-03.example.com
ansible-flow-mcp hub session          # MCP stdio for the agent
ansible-flow-mcp tui                  # servers · groups · invite · OpenCode
ansible-flow-mcp hub spoke-call --node web-03 --tool list_collections