Files
yvgude--lean-ctx/docs/enterprise/agent-identity.md
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

4.5 KiB

Agent Identities — Registered, Attested, Revocable

GitLab: #433 (H3 Epic D) · Module: core/agent_registry.rs · CLI: lean-ctx agent

AI agents stop being anonymous processes with a role config and become registered identities: unique, owned by a human, lifecycle-managed, auditable and revocable. This is the engine-side foundation for workforce governance — an org that runs 50 agents must be able to answer who runs, who owns, who switched off which agent, and when.

Model

Field Meaning
agent_id Stable identity (key); [A-Za-z0-9_-]
role Permission profile (roles/*.toml / built-ins) — what it may do
owner Mandatory human accountable — who answers for it
status activesuspendedactivedecommissioned (final)
public_key Ed25519 key bound to the identity (signs audit entries)
attestation Binary + role-config SHA-256 at registration/heartbeat
last_heartbeat Liveness timestamp

Identity (who) is deliberately separate from role (what): roles stay reusable profiles; accountability attaches to the identity.

Lifecycle

lean-ctx agent register --id ci-reviewer-1 --role reviewer --owner alice@org
lean-ctx agent heartbeat ci-reviewer-1          # liveness + drift check (exit 3 on drift)
lean-ctx agent suspend ci-reviewer-1 --reason "incident IR-42"
lean-ctx agent resume ci-reviewer-1
lean-ctx agent decommission ci-reviewer-1       # final; writes the audit-closing entry
lean-ctx agent check ci-reviewer-1              # enforce-path check (exit 1 = deny)

Every transition writes a tamper-evident audit entry (event types agent_registered, agent_suspended, agent_resumed, agent_decommissioned — OCP Part 4, included in evidence bundles). Decommissioned identities are never deleted and never reactivated: the record is part of the audit history.

Owner offboarding (the orphaned-agent problem)

Orphaned agents — running identities whose human owner left — are the security hole of the agent era. The registry closes it mechanically:

lean-ctx agent offboard-owner alice@org --reason "left the company"

suspends every active agent owned by alice@org in one transaction and audits each suspension. Wire this to your IdP:

  • SCIM (ENT-2): on active=false for a user, call agent_registry::suspend_agents_for_owner(user, "SCIM deactivated") (HTTP path: team-server SCIM handler) or run the CLI from your deprovisioning pipeline.
  • Manual: part of the leaver checklist.

Policy choice (suspend vs. transfer) stays with you: suspended agents can be resumed after register-ing a new owner via decommission + re-register.

Attestation — honest threat model

register and heartbeat hash the running binary and the active role file. A drifted hash (exit code 3) tells you something changed — upgrade, config edit, or tampering. This is drift detection, not proof of integrity: an attacker with full host control can fake hashes. What it does give you:

  • unnoticed config/binary changes surface in regular heartbeats,
  • the attestation history is part of the audit chain (tamper-evident after recording),
  • combined with evidence bundles, an auditor can see when the fleet drifted.

It does NOT replace host hardening, code signing or supply-chain controls.

Workload IAM (SPIFFE)

Every record maps to a SPIFFE-compatible workload identity:

spiffe://<trust-domain>/agent/<role>/<agent_id>
lean-ctx agent show ci-reviewer-1 --trust-domain org.example
  → spiffe://org.example/agent/reviewer/ci-reviewer-1

Kubernetes reference setup (SPIRE): register the node + workload with the same path scheme so the agent's K8s service account maps 1:1 to its LeanCTX identity:

spire-server entry create \
  -parentID  spiffe://org.example/ns/agents/sa/leanctx \
  -spiffeID  spiffe://org.example/agent/reviewer/ci-reviewer-1 \
  -selector  k8s:ns:agents -selector k8s:sa:ci-reviewer-1

The OIDC client-credentials path (agent visible as a service account in Entra/Okta) builds on the team-server token plane and is tracked as the hosted half of #433 — engine-side prerequisites (stable identity, status check, owner binding) are what this module provides.

Enforce mode

agent_registry::check(agent_id) is the single decision point: not registered ⇒ deny; suspended/decommissioned ⇒ deny; active ⇒ allow. Call paths (team-server middleware, A2A handlers) consult it in enforce mode and only log in monitor mode — start in monitor, switch to enforce once your fleet is registered.