pub fn inject_identity_env(
mstore: Arc<Store>,
id_store: Arc<Store>,
identity_store: Arc<Store>,
block_id: &str,
env_vars: &mut HashMap<String, String>,
) -> Result<(), SpawnGateError>Expand description
Inject identity-derived env vars into the spawn map for a block.
Synchronous, broker-less entry point — in production only the durable-jekt
sign-in recheck (server/jekt_held.rs) calls it. The CLI-spawn paths use
inject_identity_env_async instead (via build_persistent_spawn_env in
server/agent_handlers/input.rs). Resolution flow:
- Look up the active
AgentInstancefor this block. If none exists, the caller didn’t go through the launch modal — return immediately, no injection (unless the block names a deleted agent: that is refused withSpawnGateError::AgentDeleted, #3577). - Read its
identity_id. Empty / “blank” no longer short-circuits to ambient creds (see #2463 — this used to bypass the layer-3 gate entirely, so whether a spawn required a bound account depended on whether a stray ambient credential happened to exist on the test machine). It now falls through to the same steps below, which gate purely on the agent definition’s own provider — identical to how a non-empty-but-unresolvableidentity_id(e.g. a legacy sentinel) already behaved. - Read the
db_agent_identity_linksrows for the instance’s definition. - For each binding: fetch the account, resolve its
SecretRef, look up the provider’s env-var matrix, write each var intoenv_vars.- Api-key-class per-binding failures are logged and skipped — other bindings still inject (historical behavior).
- Oauth-class failures (account row missing, lookup error,
non-OAuthConfigDir secret_ref) are always BLOCKING: the function
returns
SpawnGateErrorbefore the CLI process is created.use_ambient_loginno longer exempts an agent and is not read here (the opt-out was retired, see m0017_ambient_login_grandfather.rs).
- If the agent definition’s own provider is oauth-class and no binding for it exists at all (fresh/never-bound or post-delete-cascade), the same gate applies — implicit ambient fallback is how the delete-doesn’t-deauthenticate gap happened (spec §2.2 edge case).
Layer 3 of SPEC_ACCOUNT_DELETE_DEAUTH_LAYERS_2_4_2026_07_14.md. Before it, this function was intentionally infallible (“the spawn never aborts because a secret didn’t resolve”) — that is still true for api-key-class bindings, but oauth-class resolution failures now fail the spawn by default so account deletion is honest at the next spawn.