feat(agents): add Agent Authority policy + access bootstrap tooling

Add non-negotiable "Agent Authority" section to AGENTS.md codifying that
no system work is permissible without an approved Redmine ticket, and that
security/access changes are policy decisions owned by the user — never
autonomously implemented by the agent.

Also add the access bootstrap toolkit:
- agent-bootstrap.sh: in-guest key + sudo setup (localuser sudo only per policy)
- bootstrap-all.sh: workstation-side push to remaining NO-KEY systems
- access-matrix.sh: full fleet SSH/sudo probe
- probe-ssh.sh, probe-ssh-localuser.sh, probe-ga.sh, pivot-probe.sh,
  ga-push-key.sh: diagnostic scripts used during access audit

Refs [#403]

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
2026-08-10 14:00:38 -05:00
parent c115ea8ea1
commit db6c7829ee
9 changed files with 428 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
#!/bin/sh
# Fleet probe: for each running VM, report guest-agent status + primary IP.
# Run on a Proxmox host. Output: "VMID NAME GA-STATUS IP(s)"
set -u
qm list 2>/dev/null | awk 'NR>1 && $3=="running" {print $1, $2}' | while read -r vmid name; do
[ -n "$vmid" ] || continue
if timeout 10 qm agent "$vmid" ping >/dev/null 2>&1; then
gastatus="GA-OK"
ips=$(timeout 10 qm agent "$vmid" network-get-interfaces 2>/dev/null \
| python3 -c '
import sys, json
try:
data = json.load(sys.stdin)
except Exception:
sys.exit(0)
seen = []
for iface in data:
ifname = iface.get("name","")
if ifname == "lo": continue
for a in iface.get("ip-addresses", []):
ip = a.get("ip-address","")
if ":" in ip: continue
if ip.startswith("127."): continue
seen.append(ip)
print(",".join(seen))
' 2>/dev/null)
else
gastatus="GA-NO"
ips=""
fi
printf '%s\t%s\t%s\t%s\n' "$vmid" "$name" "$gastatus" "$ips"
done