summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-13 14:24:31 -0600
committert <t@tjp.lol>2026-06-15 15:08:32 -0600
commit20e6e08a42240aef0b36ecf627cbcde921912071 (patch)
treefd7e1f860f28ffa41d33416fb6277a95e530191e /docs
parentfbee69ca8c4b485b7b2d6fe7448b13367c4716c8 (diff)
auth: flatten [auth.<name>] config + ${...} substitution
Collapse the auth schema: infer `type` from keys, replace key/key_env_var with a single `key` (resolved via substitution), flatten the exchange to flat `exchange_*` keys, and drop the auth-level headers tables in favor of reusing the provider's `extra_headers` on the auth HTTP calls. Add `${sibling}` and `${env:VAR}` substitution over auth values (GitHub Enterprise = set `domain`). Restore api_key-empty → provider-drop. Update default config, docs, and tests.
Diffstat (limited to 'docs')
-rw-r--r--docs/oauth-provider-auth.md31
1 files changed, 25 insertions, 6 deletions
diff --git a/docs/oauth-provider-auth.md b/docs/oauth-provider-auth.md
index 9f5c7fe..96312e1 100644
--- a/docs/oauth-provider-auth.md
+++ b/docs/oauth-provider-auth.md
@@ -501,10 +501,28 @@ None of these are required for Copilot or Codex auth correctness.
The first pass landed as a clean break (no compatibility shim): every networked
provider must name an `[auth.<name>]` session via `auth = "<name>"`;
provider-level `api_key`/`api_key_env_var` are gone. Resolved decisions for the
-open questions above: TOML uses `key_env_var`; `auth` is required for networked
-providers; Codex device auth is modelled as a `dialect = "codex"` variant of
-the generic `oauth_device` type; keychain storage is deferred (file-backed
-`$PANTO_HOME/auth/<name>.json`, owner-only `0600`).
+open questions above: `auth` is required for networked providers; Codex device
+auth is a `dialect = "codex"` variant of the generic `oauth_device` type;
+keychain storage is deferred (file-backed `$PANTO_HOME/auth/<name>.json`,
+owner-only `0600`).
+
+The `[auth.<name>]` schema is deliberately flat and minimal:
+
+- **`type` is inferred** — `key` ⇒ `api_key`, `client_id` ⇒ `oauth_device`
+ (explicit `type` still works).
+- **`${...}` substitution** on every value — `${env:VAR}` reads the
+ environment, `${sibling}` reads another key in the same section. The common
+ api-key session is one line: `key = "${env:OPENAI_API_KEY}"`. An unset
+ `${env:VAR}` resolves to empty, and a provider whose `api_key` resolves empty
+ is **dropped** (reproducing "export your key or the provider disappears").
+ GitHub Enterprise is a one-liner: set `domain = "company.ghe.com"` and the
+ `${domain}`-templated URLs follow.
+- **The exchange is flat** — `exchange_url`, `exchange_method`,
+ `exchange_token_path`, `exchange_expires_path`, `exchange_base_url_path` (no
+ `[auth.<name>.exchange]` sub-table); presence of `exchange_url` enables it.
+- **No auth-level headers** — the provider's `extra_headers` (the client
+ identity, e.g. Copilot's editor headers) are reused on the auth HTTP calls
+ (device/poll/exchange) as well as the model request, so they're written once.
### What core owns (libpanto)
@@ -519,8 +537,9 @@ the generic `oauth_device` type; keychain storage is deferred (file-backed
### What the CLI owns (`src/`)
- `config_file.zig` parses `[auth.<name>]` and the `auth = "<name>"` reference,
- resolving `api_key` sessions eagerly (literal/env). Providers always survive
- resolution; an unresolved session fails the request with a clear error.
+ runs `${...}`/`${env:VAR}` substitution, infers `type`, and resolves
+ `api_key` sessions eagerly. A provider whose `api_key` resolves empty is
+ dropped; OAuth providers always survive (resolved at turn time).
- `auth_manager.zig` resolves the active provider's auth before each turn
(load → login → refresh → exchange → build credential), patching the live
`ProviderConfig` (bearer, dynamic `base_url`, merged headers).