
## The rule that shapes identity

Daevix runs arbitrary, untrusted customer code. An agent can read its own
filesystem and environment, inspect its own memory, and try to reach the
network. The platform observes and governs that code, so whoever controls the
code benefits from escaping that observation.

That threat model leads to one rule: the agent does not hold a credential. If
it did, an attacker who owned the agent could exfiltrate and replay it. Authentication requires the caller to present something. An
attacker who owns the agent can also present anything that the agent can
present.

So the enclave does not authenticate agents. It **attributes** every action to
an agent using properties of where the agent runs, enforced by layers below the
agent's code: the per-agent socket mount, the Cilium datapath, and the
provisioning-time hardware measurement. The agent presents nothing. Three
enforcement planes carry this out.

## Plane 1: the mount names the agent

The broker creates one IMDS unix socket per agent and mounts only
that socket into that agent's pod, at the well-known path
`/run/dvx/imds.sock`. The broker owns the socket-to-agent mapping. Pod and VM
isolation keep the agent from reaching any other agent's socket.

When the agent asks its IMDS "who am I?", the service answers from the mapping
of the socket that the question arrived on. The identity signal is which listener the
connection used. The socket mount carries the identity. Peer credentials on the socket are
kept only as an optional sanity check, because peer pids and uids across the
Kata VM boundary are virtualized and not meaningful.

The IMDS socket is local IPC inside the namespace. It is not network egress, so
the egress policy of Plane 2 does not apply to it.

## Plane 2: the datapath names the agent

Every agent runs in its own namespace with Cilium default-deny egress. The only
permitted route out is through the enclave gateways. An agent's code cannot
route a packet anywhere else; the eBPF datapath drops it.

East-west traffic is not masqueraded, so the gateway sees each connection's real
pod IP as the TCP source. A pod IP alone is not an identity, so the gateway
joins the source IP to an attribution index. The index is built from
CiliumEndpoint objects, which carry the pod's IPs, its Daevix labels, and its
numeric Cilium security identity. Cilium validates that identity in the kernel,
and the workload cannot forge it.

The join determines how the gateway audits the flow. A named connection is audited
with `actor: "agent:<uid>"` plus the org and the numeric `security_id`. When
attribution is in force and no agent endpoint claims the source IP, the gateway
denies the flow with reason `no_identity` and audits the denial. The platform
does not govern a flow that it cannot name, so an unnameable flow is denied rather
than forwarded by source IP alone.

Mediation and attribution use the same mechanism. The same layer forces the
path and names the agent.

## Plane 3: the measurement anchors both planes

Planes 1 and 2 both rest on a mapping: this socket, or this Cilium identity,
belongs to this agent. The broker establishes that mapping at provisioning,
after it verifies a Kata TEE remote-attestation report against expected
reference values. Only a pod whose measured guest matches gets a socket and a
mapping. The agent never participates in its own enrollment, so there is no
bootstrap secret to steal.

## What attribution does not give you

Attribution establishes who did this for the enclave datapath. It does not give
the agent a credential that it can present anywhere else. The distinction shows up
whenever the platform itself needs a bearer token:

- An external service that authenticates callers (a cloud API, the
  controlplane's operator API) needs something to present. The trusted plane
  mints that credential (for the operator API, the controlplane mints it and
  the gateway fetches and presents it), so the agent still holds nothing. See
  [Agent as operator](/concepts/agent-as-operator/) for the operator API case.
- The controlplane records the actor kind from the credential, not from client
  input. An agent-operator token authenticates as kind `agent-operator`, and the
  audit actor renders as `agent:<uid>`; a human token renders as `user:<uid>`.
  A caller cannot choose its own kind.
- Attribution ends at pod teardown. The identity is the socket, the Cilium
  identity, and the measured guest, so removing the pod removes all three in the
  same operation. There is no secret to rotate and none to revoke.

Authentication proves a claim that a caller carries. Attribution observes where the
action physically came from. Daevix relies on attribution for the datapath and
mints authentication, briefly, only inside the trusted plane when an external
boundary requires it.
