agentmux_srv/identity/resolver/mod.rs
1// Copyright 2025-2026, AgentMux Corp.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Identity → env-var resolver.
5//!
6//! Per-provider matrix of which env vars carry which credential. The
7//! GitHub PAT becomes both `GITHUB_TOKEN` and `GH_TOKEN` because both
8//! the official `gh` CLI and direct API consumers (curl, oct.js) read
9//! one or the other; emitting both is the lowest-friction way to make
10//! every common workflow Just Work.
11//!
12//! **Before touching `gate_oauth_failure` / `inject_identity_env_with_broker`:**
13//! this module is where `SPEC_PROVIDER_ISOLATION_2026_06_20.md`'s INV-A
14//! ("never the user's global `~/.<P>` dir") is enforced — or, once already,
15//! silently stopped being enforced. Read
16//! `docs/retro/retro-auth-isolation-invariant-silently-orphaned-2026-07-14.md`
17//! first. Short version: an unbound oauth-class provider used to
18//! auto-route to an AgentMux-owned isolated dir (no user action, no global
19//! exposure); a 2026-07-08 refactor orphaned that path without meaning to,
20//! and it was never restored. Today's gate always blocks an unbound
21//! oauth-class provider; the per-agent "true ambient" opt-out
22//! (`use_ambient_login`) is no longer read.
23//!
24//! ## Module layout
25//!
26//! Split from a single ~2193-line `resolver.rs` file into a directory
27//! (pure relocation, no behavior change — mirrors the
28//! `backend/subagent_watcher/` and `backend/blockcontroller/subprocess/`
29//! splits) so each self-contained piece lives in its own file:
30//! - `oauth_probe`: `oauth_status` constants, `OAuthProbeStatus`, and
31//! `probe_oauth_status` — on-disk OAuth token-file probing.
32//! - `errors`: `SpawnGateError`, `ResolverError`.
33//! - `provider`: `ProviderClass`, `provider_class`
34//! — the provider classification table.
35//! - `secret`: `resolve_secret`.
36//! - `inject` — this module's security-critical core (see the warning
37//! above): `inject_identity_env`/`inject_identity_env_async`,
38//! `IdentityBinding`, `resolve_bindings_for_instance`, and
39//! `inject_identity_env_with_broker` — the layer-3 credential-
40//! injection spawn gate. The INV-A warning is repeated there,
41//! attached directly to `inject_identity_env_with_broker`, and every
42//! test exercising that function moved WITH it into `inject.rs` as
43//! one atomic unit.
44
45mod errors;
46mod inject;
47mod oauth_probe;
48mod provider;
49mod secret;
50
51pub use errors::SpawnGateError;
52pub(crate) use inject::block_agent_id;
53pub use inject::{
54 inject_identity_env, inject_identity_env_async, resolve_account,
55 agent_has_identity_binding, resolve_bound_claude_config_dir_for_agent, resolve_bound_oauth_config_dir,
56};
57pub use oauth_probe::oauth_status;
58pub use provider::{provider_class, ProviderClass};