Expand description
The credential-injection entry points and the layer-3 spawn gate.
Split out of the single ~2193-line resolver.rs (pure relocation, no
behavior change): inject_identity_env / inject_identity_env_async
(thin public wrappers), IdentityBinding + resolve_bindings_for_instance
(direct-link lookup), and inject_identity_env_with_broker — the
security-critical credential-injection gate. Every test that exercises
inject_identity_env_with_broker moved here WITH it, as one atomic unit,
per the module split’s constraint that this function and its tests must
never be separated.
Before touching gate_oauth_failure / inject_identity_env_with_broker:
see the warning doc comment directly above inject_identity_env_with_broker
below.
Structs§
- Identity
Binding 🔒 - Resolved (provider, account) pair ready for env injection.
Functions§
- agent_
has_ identity_ binding - Whether an agent has any identity binding — its own links, or its template’s when it has none — checked without the binding resolver’s “no links” warning. For callers that ask on every sweep (memory), so an unlinked agent costs a lookup, not a log line.
- block_
agent_ 🔒id - The agent a block names (
agentId, or legacyagent:id), if any. - bound_
oauth_ 🔒config_ dir - inject_
identity_ env - Inject identity-derived env vars into the spawn map for a block.
- inject_
identity_ env_ async - The optional broker lets the OAuth-class branch publish
identityaccounts:changedon a status change discovered by the expiry probe.Noneskips the publish; theagentinputturn (server/agent_handlers/input.rs) andagent.send(app_api/agent_io.rs) passSome(broker.clone())throughbuild_persistent_spawn_envso any live account list flips its status badge without a reload. Per spec §4.4. - inject_
identity_ env_ with_ broker - Before touching
gate_oauth_failure/inject_identity_env_with_broker: this module is whereSPEC_PROVIDER_ISOLATION_2026_06_20.md’s INV-A (“never the user’s global~/.<P>dir”) is enforced — or, once already, silently stopped being enforced. Readdocs/retro/retro-auth-isolation-invariant-silently-orphaned-2026-07-14.mdfirst. Short version: an unbound oauth-class provider used to auto-route to an AgentMux-owned isolated dir (no user action, no global exposure); a 2026-07-08 refactor orphaned that path without meaning to, and it was never restored. Today’s gate always blocks an unbound oauth-class provider; the per-agent “true ambient” opt-out (use_ambient_login) is no longer read. - resolve_
account - Resolve an account by id, checking
id_storefirst — the authoritative, per-account-isolatable primary, which is what preserves the disposable-test-account isolation guarantee — and falling back toidentity_store’s read-through mirror (IDENTITY_STORE_SCHEMA_VERSIONv2,docs/specs/SPEC_IDENTITY_STORE_SPLIT_2026_08_17.md§3.1) only when the primary lookup misses. Returns the account alongside WHICH store it came from, so a caller that later writes a status update (the OAuth expiry probe below) writes it back to the SAME store instead of always assumingid_store— writing to the wrong store would silently create a second, never-read copy. - resolve_
account_ for_ spawn - SPAWN-PATH account lookup — current channel’s
id_storeonly, never the global mirror. - resolve_
bindings_ 🔒for_ instance - resolve_
bound_ claude_ config_ dir_ for_ agent resolve_bound_oauth_config_dirfor a Claude agent row by its id, with no block — memory resolution’s question (#3603): where does this agent’s Claude run, so where are its memories (projects/<cwd>/memory, a Claude layout).Nonefor any other provider, and for an account bound to the ambient~/.claude— the spawn refuses that dir, and memory writes must never land in the user’s own Claude projects.- resolve_
bound_ oauth_ config_ dir - Read-only lookup of a block’s identity-bound OAuth config dir — the same
directory
inject_identity_env_with_broker’s OAuth branch would inject, without any of that function’s side effects (no token-expiry probe, no account-status upsert, noidentityaccounts:changedpublish, noSpawnGateErroron failure). For a background caller that only needs to know WHERE to look (e.g.subagent_watcherdeciding which directory to watch at agent registration, not spawn) rather than what to inject. - template_
parent_ 🔒id_ if_ seeded - Resolve the identity bindings for an instance from the direct agent↔account links only.