Outcall
SpecificationsS013 · Agent-Name Rule Context

S013 · Agent-Name Rule Context

Specification module 013-agent-name-context

S013: Agent-Name Rule Context

FieldValue
SpecS013
FeatureAgent-Name CEL Context
Date2026-05-08
StatusImplemented
Author@marktopper

Overview

The CEL evaluation context exposes agent.name so operators can gate policy by the daemon-managed container that originated a request. The container-facing Unix API resolves Linux SO_PEERCRED PID to an immutable Docker container ID. The HTTP proxy and DNS filter resolve the source IP through a lifecycle-managed Docker identity index. All three enforcement paths reject requests when a managed identity cannot be proven.

Background

The agent naming convention strips the trailing -N from container names:

  • Container foobar-1 → agent name foobar
  • Container foobar-2 → agent name foobar
  • Container my-agent-12 → agent name my-agent

The SO_PEERCRED socket option provides the caller's host-namespace PID. Proxy and DNS traffic instead carries a bridge source IP. DockerManager validates both forms against the managed-by=outcalld label and maintains an IP identity index from Docker lifecycle events.

User Scenarios

S013-US-001 [P1] As a host operator, I want to write rules that allow specific agents by name so that I can enforce per-agent access policies.

S013-US-002 [P1] As a host operator, I want agent.name exposed in the CEL context so that existing rule authors can use it immediately.

S013-US-003 [P2] As a host operator, I want to debug which agent made a request by inspecting the agent.name field in evaluation logs.

Requirements Summary

IDTypePriorityTitleStatus
S013-FR-001FunctionalP1AgentContext type in outcall-apiImplemented (outcall-api/src/lib.rs:158)
S013-FR-002FunctionalP1agent field in EvalContextImplemented (outcall-api/src/lib.rs:163)
S013-FR-003FunctionalP1SO_PEERCRED to immutable container identityImplemented
S013-FR-004FunctionalP1Agent name derived from container nameImplemented (agent_api/mod.rs:derive_agent_name)
S013-FR-005FunctionalP1agent.name exposed in CELImplemented for proxy + agent_api paths
S013-FR-006FunctionalP1DockerContext.image remains unchangedImplemented
S013-IF-001InterfaceP1AgentContext struct in outcall-apiImplemented
S013-FR-007FunctionalP1Network enforcement rejects unidentified peersImplemented
S013-IF-002InterfaceP2DockerManager identity lookup interfacesImplemented
S013-IF-003InterfaceP1Document agent.name in docs/rules.mdImplemented
S013-AS-001AcceptanceP1Agent name matches all replicasImplemented
S013-AS-002AcceptanceP1Different agent does not matchImplemented
S013-AS-003AcceptanceP1Missing peer credentials rejectedImplemented
S013-AS-004AcceptanceP1Unknown container identity rejectedImplemented
S013-AS-005AcceptanceP1Existing EvalContext consumers unchangedImplemented
S013-AS-006AcceptanceP2Agent name combines with other contextImplemented
S013-AS-007AcceptanceP2Name without replica suffix preservedImplemented
S013-EC-001Edge CaseP1SO_PEERCRED unavailableImplemented (agent API rejects request)
S013-EC-002Edge CaseP1Container identity not foundImplemented (enforcement path rejects request)
S013-EC-003Edge CaseP2Agent name with no trailing -NImplemented (regex -[0-9]+$ only; tested)
S013-EC-004Edge CaseP1Async resolution does not block rule evaluationImplemented (event-maintained cache with authoritative fallback)
S013-EC-005Edge CaseP2Very long container nameImplemented
S013-EC-006Edge CaseP1Concurrent identities remain isolatedImplemented
S013-EC-007Edge CaseP1Identity lookup is boundedImplemented
S013-EC-008Edge CaseP1Peer PID exits during lookupImplemented
S013-EC-009Edge CaseP1Docker manager not initializedImplemented
S013-SC-001SuccessP1agent.name accessible in CEL rulesImplemented
S013-SC-002SuccessP1Rule agent.name == "foobar" matches foobar-1 and foobar-2Implemented (covered by derive_agent_name unit tests + full-test.sh 5.8/5.9)
S013-SC-003SuccessP1AgentContext does not break existing EvalContext consumersImplemented (Default-derived Optional; existing tests green)
S013-SC-004SuccessP1SO_PEERCRED resolution pathImplemented
S013-SC-005SuccessP2Rule docs include agent namespaceImplemented
S013-SC-006SuccessP1Replica suffix derivationImplemented

The Unix API and network services use different transport identities but converge on the same validated Docker container name and derive_agent_name helper. A synthetic host-side rule evaluation may omit agent; a request on a container-facing enforcement path may not.

Cross-Spec Dependencies

  • Depends on: S003 (CEL context structure, evaluation path)
  • Depends on: S008 (lookup_container_name_by_ip exists)
  • Required by: Operator rules that need per-agent gating (no downstream specs currently reference this)

Shared Types (outcall-api)

/// Agent identity resolved from a daemon-validated managed container.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AgentContext {
    pub name: String,  // e.g. "foobar" from "foobar-1"
}
/// Full CEL evaluation context (S003, extended with agent).
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct EvalContext {
    pub network: Option<NetworkContext>,
    pub http: Option<HttpContext>,
    pub dns: Option<DnsContext>,
    pub docker: Option<DockerContext>,
    pub run: Option<RunContext>,
    pub agent: Option<AgentContext>,  // S013-FR-002
}

CEL Usage

Once implemented, operators can write:

rules:
  - id: "allow-foobar-db"
    condition: |
      agent.name == "foobar" &&
      network.port == 5432
    action: allow

  - id: "block-bar-agents-ssh"
    condition: agent.name == "bar" && network.port == 22
    action: block

On this page