Per-Developer Identity
By default a governed request is attributed to the client that made it — the org, tenant, and license key. That is enough to isolate one customer's data from another, but it does not tell you which developer ran a given tool call, or which AI-tool session it belonged to. Per-developer identity closes that gap: when a developer's email is supplied on a request, AxonFlow records it on the canonical audit record so the customer portal's User column, the audit User filter, and the per-user views on the Claude Code dashboard resolve to an individual instead of a shared synthetic id.
Per-developer identity is an Enterprise capability of the customer portal and audit surfaces. It is asserted, not authenticated — supplying an email improves audit visibility, it is not a login. Access to the platform is still governed by the license key; the org and tenant on every stored row come from that license, never from the supplied identity, so a developer cannot cross a tenant boundary by changing their email.
What gets recorded
Two fields land on the canonical audit_logs decision record when they are supplied:
user_email— the individual developer, taken from theX-User-Emailrequest header.session_id— the AI-tool session that produced the request, taken from theX-Session-Idrequest header. Platform migrationcore/129adds a nullablesession_idcolumn toaudit_logs; it is purely additive and backward-compatible.
Both are read from request headers only and are never trusted from a request body, so a payload cannot spoof another developer's identity into the audit trail. Both are recorded on both governance planes: the agent's policy-check (check_policy) path and the orchestrator's tool-call audit path.
When no email is supplied, the row falls back to the client-scoped synthetic id mcp-client:<client-id> — never a blank User column. So attribution degrades gracefully: developers who have configured an email show up by name, and everyone else rolls up under the client identity.
The platform side of per-developer identity — recording user_email and session_id from the request headers, migration core/129, and the synthetic fallback — ships in platform v9.3.0. The client side that emits those headers ships in the Claude Code plugin v1.8.0 and Claude Desktop proxy v0.3.0, both of which pair with platform ≥ v9.3.0. Older clients (Claude Code plugin ≤ v1.7.0, Desktop proxy ≤ v0.2.1) do not send the headers, so their activity attributes to the synthetic mcp-client:<client-id> id rather than a named developer until you upgrade.
Configuring the Claude Code plugin
On v1.8.0 and later, the Claude Code plugin resolves a developer email in this order and sends it as the X-User-Email header on every governed request (the MCP connection and both the pre-tool and post-tool hooks):
- the
AXONFLOW_USER_EMAILenvironment variable — the supported source; - best-effort fallback to
git config user.email; - otherwise unset — the header is omitted and the row falls back to the synthetic client id.
Set it in the developer's shell profile:
export AXONFLOW_USER_EMAIL="[email protected]"
The session_id half needs no configuration: the plugin's PreToolUse and PostToolUse hooks forward Claude Code's own session_id (from the hook input) as X-Session-Id automatically, so every audit row carries the developer alongside the session they were working in. The MCP connection itself has no per-call session id and is unchanged.
The git fallback caveat
The git config user.email fallback is best-effort. It resolves to whatever git is configured with in the working directory at the time of the call — which may be a shared bot identity on CI, a personal address that differs from the corporate directory, or unset in a fresh container. For reliable, uniform attribution across a fleet, set AXONFLOW_USER_EMAIL explicitly rather than relying on the git fallback.
Configuring the Claude Desktop proxy
On v0.3.0 and later, the Claude Desktop MCP governance proxy sends the developer identity as X-User-Email from its AXONFLOW_LEADER_EMAIL configuration value, and forwards the Desktop session as X-Session-Id. Set AXONFLOW_LEADER_EMAIL in the proxy's managed configuration so Cowork and MCP-tool activity is attributed to the leader.
Setting the email across a fleet
For a managed fleet, distribute AXONFLOW_USER_EMAIL per developer through your MDM or fleet-configuration tooling so each machine carries its own developer's address. Because the value is per-person, it must be owned by the per-login mechanism your MDM provides (a run-on-every-login command or a per-user managed setting), not a static, machine-wide policy that would apply the same address to every user of a shared host. Your fleet-deployment runbook covers the platform-specific recipe (macOS configuration profile / command, Windows registry / command, Linux command) for injecting a per-developer value.
Where the identity shows up
Once AXONFLOW_USER_EMAIL is set, per-developer attribution flows through to:
- Audit logs — the portal User column resolves to the developer, and the User filter matches on their email. See Reading the audit logs in the portal.
- Usage & Analytics — governed Claude Code traffic is counted per organization; per-developer identity surfaces in the audit logs and the Claude Code dashboard, not in the usage totals (usage events are org-scoped and do not carry the developer email). See Portal Operations.
- The Claude Code dashboard — the per-user Grafana panel breaks decisions down by developer and verdict. See the Grafana Dashboard reference.
Related
- Audit Logging — the canonical
audit_logsrecorduser_emailandsession_idland on. - Claude Cowork & Claude Code OTEL Ingest — the ingest plane that carries the same
user_email/session_idfor Cowork and Claude Code activity. - Portal Operations — per-organization AI traffic, volume, and cost.
- Grafana Dashboard reference — the Claude Code governance dashboard and its per-user breakdown.
