ctrlrun.IdentityContext — class, defined at src/ctrlrun/identity.py:35
headers carries lowercased header names, because HTTP field names are
case-insensitive and a provider that had to guess the casing would be one that sometimes
worked. It is empty in-process; the gateway fills it.
agent and user are what an active context() supplied. They are a hint, not an
identity: a provider may ignore them, and both providers here do. They are passed so a
custom provider can implement “look up the token for this agent” without a second channel.