capability: agent privileged-capability self-probe (manifest + build-test + runtime snapshot) v0.44.0

New internal/capability: Manifest of required sudo -n grants + Prober that LISTS each
via 'sudo -n -l' (never executes) + binary-exists check → ok/degraded snapshot on the hub
report. Build-time test asserts manifest⊆sudoers (red-proof: dropping lxc-info FAILs the
gate). Startup logs N/N ok + ERROR per degraded. Serve-degraded; no allowlist change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPZ4GJ8L5Jqf8UiPwbn1kt
This commit is contained in:
2026-06-29 18:43:49 +02:00
parent 19582046ba
commit 25024d9dda
10 changed files with 584 additions and 11 deletions
+4
View File
@@ -4,6 +4,8 @@ import (
"encoding/json"
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-agent/internal/capability"
)
func TestHostReport_FieldNamesAndEmptyCollections(t *testing.T) {
@@ -28,6 +30,7 @@ func TestHostReport_FieldNamesAndEmptyCollections(t *testing.T) {
PBSSnapshots: []PBSSnapshot{},
AuditTail: []AuditEntry{},
Cloudflared: Cloudflared{Status: "active"},
Capabilities: []capability.Status{},
}
// dr_recipe is always set on the real path (Collect); set it here too so the "no null" invariant
// covers it (empty pbs is omitempty → omitted, never null).
@@ -46,6 +49,7 @@ func TestHostReport_FieldNamesAndEmptyCollections(t *testing.T) {
`"cloudflared":{"status":"active"}`,
// empty collections must be [] not null
`"storage_targets":[]`, `"backups":[]`, `"restore_tests":[]`, `"pbs_snapshots":[]`, `"audit_tail":[]`,
`"capabilities":[]`,
} {
if !strings.Contains(got, field) {
t.Errorf("report JSON missing %s\n got: %s", field, got)