End-user identity

Understand how DefenseClaw attributes telemetry to endpoint users and agents, which identity facts are verified or claimed, how to join records, and how to opt in to the principal and connector email.

DefenseClaw attributes hook activity and per-profile AI inventory to the endpoint account that produced it. This matters on shared endpoints, where the gateway's service account is not the person running the agent.

An absent field means DefenseClaw could not establish it safely. Do not infer id_kind from an identifier's shape, and do not build an email from an account name.

AttributeMeaning
user.idPOSIX effective uid or Windows token SID.
defenseclaw.user.id_kindposix_uid or windows_sid, set only when the id came from the matching trusted OS source.
defenseclaw.user.nameOS account name without its domain: alice for the SSSD account alice@corp.example.com or for CORP\alice. The qualified form is the principal. Every record of the account carries the same spelling. A local and a directory account with the same bare name differ by user.id, defenseclaw.user.directory and defenseclaw.user.domain. Names in any script are kept.
defenseclaw.user.emailOptional connector-account email. Off by default.
defenseclaw.user.principalDirectory principal (UPN, Kerberos principal or DOMAIN\user), for example alice@CORP.EXAMPLE.COM. Sent only with ai_discovery.include_user_principal.
defenseclaw.user.domainDirectory domain or Kerberos realm.
defenseclaw.user.directorylocal, ldap, active_directory, entra_id, okta or other.
defenseclaw.user.tenant_idCloud directory tenant, for an Entra-joined Windows account.
defenseclaw.user.identity.sourceThe OS facility that resolved the directory facts.
defenseclaw.user.principal.assuranceverified when the gateway or the root guardian resolved the facts. claimed when only the hook reported them (defenseclaw.user.identity.source is then hook_reported).
defenseclaw.session.kindlocal, ssh, rdp or console. Reported only when it has the same assurance as the directory facts. Only Linux verifies a session, so Windows and macOS records omit it.
client.addressClient address of an SSH or remote session, reported with the session kind.
defenseclaw.session.kerberos_principalPrincipal of the session's Kerberos ticket cache. Always claimed. Sent only with ai_discovery.include_user_principal.
defenseclaw.agent.identity.idThe agent's stable identity (agt-), one per connector install, user and machine.
defenseclaw.guardrail.profile.name, .digest, .match, .matched_groupThe guardrail profile that decided the request, its policy digest, why it was chosen, and the matching group.
defenseclaw.user.group_countOn the identity.observed record only: how many groups the user has, never their names.

The directory fields come only from the operating system; DefenseClaw never calls an identity provider. See How DefenseClaw knows who a user is and Identity and authentication. The Secure Client profile emits none of the directory, session, agent identity or profile attributes.

Attribution, not authorization

Hooks run in the interactive user's session, read the account from the operating system, and send it to the loopback gateway as X-DefenseClaw-User-Id and X-DefenseClaw-User-Name. Those headers, and a user named in a hook payload, are claims. On the routes below the gateway ignores the claim and names the user it authenticated, so a forged header cannot re-attribute a record.

RoutePer-user installStandalone enterprise
Hook and inspectThe gateway's own accountThe peer uid of the hook socket, or the uid or SID of the per-user credential. A request whose headers name another user is refused with 403.
ACPThe gateway's own account, for signed requests and bearer tokensThe user bound to the ACP enrollment credential, one per user, editor and agent (preview).
LLM proxyThe gateway's own account when the request presents the gateway token or master key. The X-DefenseClaw-User-* pair is removed from every request.No user is bound. The pair is removed.
Sandbox ingressThe host user on the sandbox binding, recorded for attribution without verified facts. Identity headers from the sandbox are ignored.Same.
Other routes that take the gateway tokenThe gateway's own accountNo user is bound.

A request that proves nothing has no verified user. Application fields such as an X-User-Id header or a body user are recorded as a label, without id_kind, and only when no user was verified. They never choose a guardrail profile.

Do not authorize from telemetry identity

The hook identity is a join key, not an authenticated principal. A local process with a connector hook token may be able to supply a hook request. Never grant access from these fields.

Join hook activity to inventory

Hook lifecycle records carry identity in the agent.lifecycle, tool.activity and guardrail.evaluation buckets. Findings and scan verdicts of an inspected request carry it in security.finding and asset.scan. Per-profile MCP inventory carries it in ai.discovery.

RecordWhat it adds
hook.decision, guardrail.evaluation, tool.activity, and agent, model, tool and guardrail spansThe account, directory, session and agent identity attributes, and the guardrail profile on decisions.
identity.observedOnce per user per identity cache lifetime (15 minutes): directory, source, assurance and group count.
ai_component.* and the endpoint inventoryThe owning user's principal, domain, directory, assurance and agent identity.
ide.plugin.discovered, changed, removedOne IDE plugin and its enabled state, for the user who owns it.

To follow one agent across sessions, join on defenseclaw.agent.identity.id. Join on user.id only after checking defenseclaw.user.id_kind; never join a POSIX uid to a Windows SID. In managed enterprise mode the gateway runs as a service identity, so inventory takes the owner from each profile directory's file ownership or token-bound Windows Known Folders.

Optional connector email

Email is off by default and has no CLI or TUI switch. After you review the privacy impact, add this to ~/.defenseclaw/config.yaml and run defenseclaw config validate:

config_version: 9
ai_discovery:
  include_user_email: true

A running gateway applies it on the next reload. On a managed deployment the administrator edits the machine configuration.

ConnectorSource
Claude CodeoauthAccount.emailAddress in the profile's .claude.json, on the owner's ai_component.observed records
CodexThe email claim of the ID token in the profile's .codex/auth.json, on ai_component.observed records. Treated as inventory evidence, not an authenticated assertion.
Cursoruser_email in the hook payload, on hook activity

On a managed host the hook guardian reads each enrolled account's own profile; you do not list profiles. An address never goes on a record without a user or on another account's record. A file the reader cannot safely open (a link out of the profile, or any link on Windows) gives no address and a named include_user_email warning in the hook guardian log (C:\ProgramData\Cisco\DefenseClaw\logs\guardian\hook-guardian.log on Windows). A per-user gateway does not attach these addresses to AI discovery rows. To get a connector email, join a hook event to the latest ai_component.observed with the same user.id; it is reported once per discovery cycle.

Email is plaintext in most profiles

none, sensitive and content send the address as plaintext to every configured destination, including the managed AI Defense destination. Only strict, or a custom profile that extends it, removes it. On the Secure Client profile every profile keeps it.

Optional principal

No record carries defenseclaw.user.principal or defenseclaw.session.kerberos_principal unless you opt in. The domain, directory, source and assurance are sent either way.

config_version: 9
ai_discovery:
  include_user_principal: true

The option applies to the whole gateway. To send principals to a trusted local Loki but not to a SaaS destination such as Galileo, turn it on and give the other destination the strict profile.

The option governs the two principal attributes only. On a Linux host joined with SSSD fully qualified names (use_fully_qualified_names = true), the home directory is /home/alice@corp.example.com, so any record that contains a home-directory path contains the UPN whatever this option says. That includes the rule-pack directory of a hook decision, health errors, AI discovery roots and defenseclaw-gateway audit export. Paths are the path field class: sensitive and content hash them, strict removes them, none keeps them. Free text is not path-aware: a command or prompt that names the home directory keeps it under sensitive, which detects emails but not an account name in a path; content and strict replace or remove that text.

Every redaction profile preserves defenseclaw.user.name. Except under the Secure Client integration, that is the bare account name (alice) on every record, IDE plugin records included. The qualified form alice@corp.example.com is only the principal, which strict removes. If a destination must not receive even the bare account name, do not send it user-attributed telemetry: keep that route on a trusted destination or disable the export. See Redaction.

See AI discovery for profile inventory and the IDE plugin inventory.