| 1 | # OAuth Plugin DOX |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | - Own account-backed OAuth model-provider connections for Agent Zero. |
| 6 | - Provide local OpenAI-compatible proxy endpoints for connectable account providers. |
| 7 | - Keep provider-specific OAuth behavior inside this plugin, not in core model code. |
| 8 | - Preserve Codex/ChatGPT compatibility while allowing additional providers through the provider registry. |
| 9 | |
| 10 | ## Ownership |
| 11 | |
| 12 | - `plugin.yaml`, `default_config.yaml`, and `README.md` own the plugin manifest, settings defaults, and user-facing connection notes. |
| 13 | - `conf/model_providers.yaml` owns OAuth-backed model provider definitions and their `api_key_mode: oauth` metadata. |
| 14 | - `api/` owns provider-aware settings modal endpoints such as status, login start, polling, manual callback, models, and disconnect. |
| 15 | - `helpers/providers/` owns provider implementations, provider metadata, registry wiring, token storage helpers, and provider-specific endpoint validation. |
| 16 | - `helpers/summary.py` owns the shared provider-status/account summary shape consumed by the status API, discovery cards, onboarding, and OAuth settings UI. |
| 17 | - `helpers/routes.py` owns local OAuth callback and OpenAI-compatible proxy routes mounted by the route bootstrap extension. |
| 18 | - `webui/config.html` and `webui/oauth-config-store.js` own the OAuth Connections settings UI. |
| 19 | - `extensions/python/_functions/models/get_api_key/end/` owns the dummy API-key extension used by OAuth model providers. |
| 20 | - `tests/test_oauth_*.py` own provider contract, security, static UI, and compatibility regressions. |
| 21 | |
| 22 | ## Local Contracts |
| 23 | |
| 24 | - Core model code such as `models.py` must stay provider-agnostic. Do not add Codex, GitHub Copilot, Gemini, xAI, or other OAuth provider knowledge outside plugin-owned config or plugin hooks. |
| 25 | - Add OAuth model providers in `_oauth/conf/model_providers.yaml`, not `_model_config/provider_metadata.yaml`. |
| 26 | - Provider cards and model slot actions must be driven by backend provider status. Do not reintroduce hardcoded frontend provider lists or fallback provider catalogs. |
| 27 | - OAuth account surfaces in settings, discovery, and onboarding must use the provider registry/status summary rather than Codex-only frontend state. |
| 28 | - OAuth settings pending-auth controls such as device codes, manual callback input, and provider setup fields must render inline under the relevant provider row, not as a detached section below all providers. |
| 29 | - OAuth device-code polling must honor provider `interval`, `expires_at`, and `slow_down` updates; do not poll immediately or keep a stale fixed interval after a provider asks the client to slow down. |
| 30 | - OAuth settings model slots must keep provider choice editable per slot, list only connected OAuth account providers, and persist the selected provider IDs into `chat_model.provider` and `utility_model.provider`. |
| 31 | - When exactly one OAuth provider is connected, use it as an unsaved default only for empty slots or slots already using that provider. A different saved provider must keep the explicit `Choose connected provider` prompt until the user opts into the switch. |
| 32 | - OAuth provider rows show a status pill only for connected accounts; model catalogs open from the model-slot field or its embedded magnifier, not from provider-row model-check actions. |
| 33 | - OAuth model-slot fields must match `_model_config` input and below-field dropdown geometry while opening the catalog when the field is clicked. |
| 34 | - OAuth settings must dispatch `model-setup-changed` when a provider connection completes; provider defaults may be inferred from one connected account, but model-name selection remains explicit. |
| 35 | - `helpers/providers/registry.py` is the source of truth for connectable OAuth providers. |
| 36 | - The models API must preserve the legacy plain `models` slug list and may add `model_metadata` entries for richer provider catalogs. |
| 37 | - OAuth provider config must not expose the dummy `oauth` API key in `conf/model_providers.yaml`; the dummy key is a runtime-only shim supplied by the `get_api_key` extension after the account provider reports connected. |
| 38 | - Usage-plan metadata belongs only to connectable providers. Do not add metadata-only subscription families for providers this plugin cannot connect. |
| 39 | - API handlers should remain provider-aware. Missing or blank `provider_id` defaults to Codex only for existing backward compatibility; falsey non-string IDs must not silently default. |
| 40 | - Codex success contracts must preserve legacy fields such as `account_id` while allowing newer fields such as `account_label`. |
| 41 | - Do not modify Codex chat-to-responses multimodal conversion without preserving the image/text regression coverage in `tests/test_oauth_codex.py`. |
| 42 | - Token files are password-equivalent credentials. Store them under plugin-owned `usr/plugins/_oauth/<provider>/auth.json` paths with private permissions, and do not share rotating refresh-token files with external CLIs. |
| 43 | - Stored upstream base URLs and OAuth token endpoints must be validated against provider-owned allowlists before sending bearer or refresh tokens. |
| 44 | - Browser callback providers must support manual callback paste when the browser cannot reach the local callback route. |
| 45 | - Local proxy routes must remain loopback or token protected and must not add broad CORS access. |
| 46 | - Codex Responses proxy requests must include Codex client metadata and compatibility headers such as `client_metadata`, `x-codex-installation-id`, `originator`, `session-id`, and `thread-id`, and must forward `input` as a list for upstream Codex compatibility. |
| 47 | - Codex Responses proxy requests must translate the legacy top-level `reasoning_effort` field to `reasoning.effort`; an explicit native `reasoning` field takes precedence. |
| 48 | - Codex Responses proxy defaults for reasoning effort, reasoning summary, and text verbosity come from the `codex` plugin config; explicit native request values take precedence. |
| 49 | - Codex request shaping tightens an already-advertised native `response` tool to a strict required `text` schema; it must not add tools omitted by the framework tool policy. |
| 50 | - Non-streaming Codex proxy responses must retain completed SSE output items when the final `response.completed` envelope omits them. |
| 51 | - OAuth providers intentionally using Responses must set `a0_api_mode: responses`; all others inherit the Chat Completions default, since a local proxy route alone does not prove upstream support. |
| 52 | |
| 53 | ## Work Guidance |
| 54 | |
| 55 | - When adding a connectable provider, add the provider class, registry entry, model-provider config, default settings, route registration, UI support when needed, tests, and README/DOX updates together. |
| 56 | - Keep provider classes explicit about their auth endpoints, scopes, refresh behavior, and safe API hosts. |
| 57 | - Use shared helpers only for duplicated mechanics such as callback parsing, attempt lookup, model-list parsing, and JSON/error helpers. |
| 58 | - Keep provider policy visible in each provider module; avoid abstracting away endpoint validation or billing/quota caveats. |
| 59 | - Prefer plugin-local imports such as `plugins._oauth.helpers...` for bundled plugin code. |
| 60 | - Keep `_oauth` account providers separate from API-key providers in core configuration. |
| 61 | - Keep the OAuth settings page account-backed only. API-key and local provider setup belongs in model configuration and onboarding. |
| 62 | - Treat Gemini API OAuth as a Google Cloud OAuth-client flow. Do not conflate it with Antigravity, Gemini Code Assist, Gemini CLI, Google AI Pro, or Google AI Ultra subscription quota. |
| 63 | - Treat Claude Code subscription auth and Antigravity product auth as non-connectable unless their vendors provide an explicit third-party provider contract. |
| 64 | - Keep user-facing errors safe: report setup or tier restrictions without exposing tokens, callback secrets, or raw auth payloads. |
| 65 | |
| 66 | ## Verification |
| 67 | |
| 68 | - Run `pytest tests/test_oauth_*.py` after backend provider, route, token, or UI contract changes. |
| 69 | - Run `pytest tests/test_plugin_scan_prompt.py` after plugin structure, extension, or docs changes. |
| 70 | - Run onboarding or model-config tests when provider metadata, `api_key_mode`, or model-provider config changes. |
| 71 | - Run `git diff --check` before committing. |
| 72 | - For security-sensitive changes, include regressions that prove bearer tokens are not sent to malicious stored endpoints. |
| 73 | - For Codex changes, include `tests/test_oauth_codex.py` and preserve `account_id` and multimodal image bridge regressions. |
| 74 | |
| 75 | ## Child DOX Index |
| 76 | |
| 77 | No child DOX files. |