Added a new workflow step that, before opencode run, sets up a read-only ssh node1 client so agents can run ssh node1 <cmd> (matching the homelab opencode.json allowlist patterns). It writes SSH_PRIV_KEY to ~/.ssh/agent_node1 (600) and adds a Host node1 SSH config alias using SWARM_HOST/SWARM_USER (config 600, ~/.ssh 700). The step no-ops cleanly when the swarm secrets are absent, so this shared workflow still works for repos that don't define them.
Changes
.gitea/workflows/agent.yml: new step "Set up read-only SSH alias node1 (swarm diagnostics)" placed between "Install opencode + provider config" and "Inspect / fetch image attachments", so the alias is ready before any agent (including comment-mode agents that may invoke bash via opencode) runs.
Secrets (SWARM_HOST/SWARM_USER/SSH_PRIV_KEY) are passed via env: and never inlined in shell; the key is never printed.
Graceful no-op when any swarm secret is empty — non-swarm repos are unaffected.
Safety confirmation (per issue)
The provider-level ~/.config/opencode/opencode.json written in the "Install opencode + provider config" step contains onlyprovider and mcp keys — no permission block. It therefore does not override the target repo's project-level opencode.json, does not blanket-approve bash, and does not re-allow ssh *. The read-only boundary enforced by the homelab opencode.json (deny ssh * + specific allow ssh node1 …, last-match-wins, compatible with --auto) remains the real safety boundary, now backed by a working ssh node1 command.
Verification
Real verification is post-merge in a repo with the swarm secrets: ssh node1 docker service ls should return swarm state, and ssh node1 docker service rm <x> should be denied by the opencode permission layer. That's a manual check for @ffaerber (or a follow-up comment) — not something @qa's browser flow can validate.
## Summary
Added a new workflow step that, before `opencode run`, sets up a read-only `ssh node1` client so agents can run `ssh node1 <cmd>` (matching the homelab `opencode.json` allowlist patterns). It writes `SSH_PRIV_KEY` to `~/.ssh/agent_node1` (600) and adds a `Host node1` SSH config alias using `SWARM_HOST`/`SWARM_USER` (config 600, `~/.ssh` 700). The step no-ops cleanly when the swarm secrets are absent, so this shared workflow still works for repos that don't define them.
## Changes
- `.gitea/workflows/agent.yml`: new step "Set up read-only SSH alias `node1` (swarm diagnostics)" placed between "Install opencode + provider config" and "Inspect / fetch image attachments", so the alias is ready before any agent (including comment-mode agents that may invoke `bash` via opencode) runs.
- Secrets (`SWARM_HOST`/`SWARM_USER`/`SSH_PRIV_KEY`) are passed via `env:` and never inlined in shell; the key is never printed.
- Graceful no-op when any swarm secret is empty — non-swarm repos are unaffected.
## Safety confirmation (per issue)
The provider-level `~/.config/opencode/opencode.json` written in the "Install opencode + provider config" step contains **only** `provider` and `mcp` keys — no `permission` block. It therefore does not override the target repo's project-level `opencode.json`, does not blanket-approve `bash`, and does not re-allow `ssh *`. The read-only boundary enforced by the homelab `opencode.json` (`deny ssh *` + specific `allow ssh node1 …`, last-match-wins, compatible with `--auto`) remains the real safety boundary, now backed by a working `ssh node1` command.
## Verification
Real verification is post-merge in a repo with the swarm secrets: `ssh node1 docker service ls` should return swarm state, and `ssh node1 docker service rm <x>` should be denied by the opencode permission layer. That's a manual check for @ffaerber (or a follow-up comment) — not something @qa's browser flow can validate.
---
Resolves #10 · 🤖 @senior
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Added a new workflow step that, before
opencode run, sets up a read-onlyssh node1client so agents can runssh node1 <cmd>(matching the homelabopencode.jsonallowlist patterns). It writesSSH_PRIV_KEYto~/.ssh/agent_node1(600) and adds aHost node1SSH config alias usingSWARM_HOST/SWARM_USER(config 600,~/.ssh700). The step no-ops cleanly when the swarm secrets are absent, so this shared workflow still works for repos that don't define them.Changes
.gitea/workflows/agent.yml: new step "Set up read-only SSH aliasnode1(swarm diagnostics)" placed between "Install opencode + provider config" and "Inspect / fetch image attachments", so the alias is ready before any agent (including comment-mode agents that may invokebashvia opencode) runs.SWARM_HOST/SWARM_USER/SSH_PRIV_KEY) are passed viaenv:and never inlined in shell; the key is never printed.Safety confirmation (per issue)
The provider-level
~/.config/opencode/opencode.jsonwritten in the "Install opencode + provider config" step contains onlyproviderandmcpkeys — nopermissionblock. It therefore does not override the target repo's project-levelopencode.json, does not blanket-approvebash, and does not re-allowssh *. The read-only boundary enforced by the homelabopencode.json(deny ssh *+ specificallow ssh node1 …, last-match-wins, compatible with--auto) remains the real safety boundary, now backed by a workingssh node1command.Verification
Real verification is post-merge in a repo with the swarm secrets:
ssh node1 docker service lsshould return swarm state, andssh node1 docker service rm <x>should be denied by the opencode permission layer. That's a manual check for @ffaerber (or a follow-up comment) — not something @qa's browser flow can validate.Resolves #10 · 🤖 @senior