0.26.0 — transport-aware classifier escalation + standalone-server monitoring override
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

- classifyAndGate: escalate read-only commands on lxc: targets that
  touch /opt/, /etc/, /var/lib/ to config_mutation. The classifier
  scores command text only, not the SSH transport layer — SSH-ing into
  a container to read config is riskier than pct exec from the host.
- ontology: standalone-server monitoring override from inherited
  [ping, resource, updates] to [http]. VPS-like machines may not be
  SSH/ICMP-reachable from the scheduler; HTTP is the LCD liveness
  signal. Entities with full SSH can override per-entity.
This commit is contained in:
2026-08-05 16:31:41 +02:00
parent 1d0197da69
commit 38c472a118
3 changed files with 20 additions and 1 deletions

View File

@@ -826,6 +826,20 @@ var (
func classifyAndGate(ctx context.Context, pool *db.Pool, agentID, targetID uuid.UUID, targetSlug, command, purpose, declaredRisk, sessionID string) *mcp.CallToolResult {
riskClass := policy.ClassifyCommand(command, declaredRisk)
// Transport-aware escalation: read-only commands on LXC targets that
// touch config paths (/opt/, /etc/) escalate to config_mutation.
// The classifier only scores the command text, not the transport layer
// — SSH-ing into a container to read /opt/ is riskier than running
// the same command locally on the Proxmox host via pct exec.
// Caught live: "cat /etc/hostname" on lxc:dns queued as config_mutation
// while "pct exec 107 -- cat /etc/hostname" on host:hubris auto-ran.
if riskClass == policy.RiskReadOnly && strings.HasPrefix(targetSlug, "lxc:") {
if strings.Contains(command, "/opt/") || strings.Contains(command, "/etc/") || strings.Contains(command, "/var/lib/") {
riskClass = policy.RiskConfigMutation
}
}
runParams, _ := json.Marshal(map[string]string{"command": command, "purpose": purpose})
actionCol := "run:" + string(runParams)