# テスト妥当性レビュー: provider - 評価: 概ね良い ## 確認した範囲 - Crate: `crates/provider` - 確認した主な責務: - provider/model catalog の読み込みと `ModelManifest` 解決 - auth 参照から `ResolvedAuth` への解決 - `LlmClient` 構築エントリポイント - Codex OAuth の auth.json 解析、token refresh、header 生成、error mapping - 読んだファイル: - `crates/provider/Cargo.toml` - `crates/provider/README.md` - `crates/provider/src/lib.rs` - `crates/provider/src/catalog.rs` - `crates/provider/src/codex_oauth/{mod.rs,auth_json.rs,jwt.rs,refresh.rs,error.rs}` - `resources/providers/builtin.toml` - `resources/models/builtin.toml` ## 現在のテストがよくカバーしていること - Catalog resolution は有用な振る舞いレベルでカバーされている。 - builtin provider/model catalog が parse できる。 - `ref` 解決が provider catalog と model catalog のフィールドを merge する。 - inline manifest form が `scheme`、`model_id`、`auth` を要求する。 - manifest override が catalog default より優先される。 - unknown provider は hard error になる一方、unknown model は provider default に fallback する。 - `openrouter/anthropic/claude-sonnet-4.6` のような nested model id がカバーされている。 - context-window override と backend max clamping がカバーされている。 - User catalog override の振る舞いには意味のあるカバレッジがある。 - `YOI_CONFIG_DIR` は serial tests で保護されている。 - provider override は存在する場合 builtin より優先される。 - override が存在しない場合は builtin に fallback する。 - malformed provider TOML は silent fallback ではなく parse error を返す。 - Auth resolution tests は重要な local safety property をカバーしている。 - `SecretRef` resolution は injectable resolver を使う。 - missing secret は logical id を露出するが、key に見える material は露出しない。 - API key file loading は whitespace を trim する。 - relative auth file path は reject される。 - missing API key は期待される `ApiKeyMissing` を返す。 - auth-less Ollama-style construction は成功する。 - Codex OAuth tests は local integration として十分に強い。 - `auth.json` loading は unknown field を保持する。 - `id_token` JWT からの account id fallback がテストされている。 - missing auth file は login-oriented error を報告する。 - persistence は unknown field を保持し、Unix で `0600` を強制する。 - JWT parsing は `exp`、ChatGPT claims、missing `exp`、malformed JWT をカバーしている。 - refresh tests は timeout classification と一般的な permanent 401 classifications をカバーしている。 - provider-level tests は fresh-token headers、FedRAMP header、persistence 付き expired-token refresh、permanent refresh login hint、missing auth file を検証している。 ## 不足 / 疑問のあるテスト - `build_client` / `build_client_from_config` の construction tests は、ほとんどが `is_ok()` または 1 つの error shape を assert している。構築された transport の effective base URL、選択された scheme、model id、capability fallback、Codex-OAuth-specific OpenAI Responses behavior を検証していない。このため、重要な provider-factory invariant のテストが弱い。 - Codex OAuth default base URL path は直接テストされていない。`effective_base_url` には `https://chatgpt.com/backend-api/codex` 用の特別な `AuthRef::CodexOAuth` branch があるが、誤って OpenAI Responses scheme default に fallback しても検知するテストがない。 - Codex OAuth 用の OpenAI Responses special case は、`max_output_tokens`、`temperature`、`top_p` の forwarding を無効化する。これは重要な compatibility invariant だが、provider crate にはそれに対する focused assertion がない。transport internals が opaque なままであれば、狭い test hook か、所有 layer でのより高レベルな request-building test が必要かもしれない。 - Builtin catalog tests は、正確な provider list と count を assert している箇所がやや脆い: - `builtin_has_four_providers` - `load_falls_back_to_builtin_when_override_absent` これは偶発的な catalog drift を捕捉できるため価値があるが、正当な provider を追加すると、invariant-oriented というより一部 snapshot-like なテスト更新が必要になることも意味する。意図的であれば許容できるが、pure behavior testing ではなく catalog contract testing として扱うべき。 - User model override behavior は provider override behavior よりカバーが薄い。 - `models.toml` override precedence に相当するテストがない。 - malformed `models.toml` parse-error test がない。 - providers と models は設計上独立して override されるため、対称的なカバレッジが必要。 - Codex OAuth guarded-reload behavior は文書化されているが、直接テストされていない。 - “file becomes fresh between stale read and refresh” をカバーするテストがない。 - refresh 前に account id が変わり、そのため refresh を skip するケースをカバーするテストがない。 - これらは concurrency/race-safety invariants であり、現在のテストは通常の refresh path は検証しているが、race guards は検証していない。 - `last_refresh + 8 days` による Codex OAuth staleness fallback は直接テストされていない。現在の provider tests は access-token `exp` を使って fresh/expired cases を強制している。実際の auth file で malformed/non-JWT access token が想定されるなら、この fallback はテストするだけの重要性がある。 - Refresh HTTP tests は outbound request shape を assert していない。 - `client_id` - `grant_type = refresh_token` - `refresh_token` - JSON content type 現在の mock は期待される path へ POST が発生したことは証明しているが、Codex-compatible body が正しいことは証明していない。 - Error conversion のカバレッジは間接的である。`CodexAuthError::to_client_error` の permanent-path behavior は provider-level login-message test を通して部分的にカバーされているが、transient refresh と config-classified errors は `ClientError` variants として直接 assert されていない。 - `CodexAuthProvider::from_default_home` の environment precedence(`HOME` より `CODEX_HOME`)や missing `HOME` に対するテストがない。これは小さいが public construction path である。 ## 追加を提案するテスト - Codex OAuth construction invariants に対する provider-factory tests を追加する: - `ref = "codex-oauth/gpt-5.5"` が `AuthRef::CodexOAuth` として resolve/build される。 - `base_url` がない場合、official OpenAI ではなく ChatGPT backend base URL になる。 - explicit `base_url` は引き続き優先される。 - 広い internals を露出せずに assert できるなら、Codex OAuth OpenAI Responses が unsupported output/sampling parameters を無効化する。 - 対称的な model catalog override tests を追加する: - `load_models()` は `/models.toml` を優先する。 - malformed model override は `CatalogError::Parse` を返す。 - provider override と model override は片方だけが存在する場合も独立している。 - Codex OAuth race-guard tests を追加する。できれば `auth_json::load` 周辺の小さな test seam を使うか、呼び出し間で temp-file changes を構成する: - stale initial snapshot、fresh pre-refresh snapshot: HTTP refresh しない。 - pre-refresh account id が異なる: HTTP refresh せず、新しい account を採用する。 - staleness fallback unit tests を追加する: - invalid/non-JWT access token + recent `last_refresh` は stale ではない。 - invalid/non-JWT access token + old `last_refresh` は stale。 - invalid/non-JWT access token + missing `last_refresh` は stale。 - `wiremock` で request body matching を使って refresh HTTP tests を強化し、偶発的な Codex OAuth request-shape 変更を捕捉できるようにする。 - catalog churn が想定されるなら、正確な builtin provider-count tests をより contract-focused な checks に置き換えることを検討する: - required provider ids が存在する - 各 provider が必要な scheme/auth/default context/capability を持つ - 各 builtin model が known provider を参照する 正確なリストが意図的に product contract の一部であるなら、現在の snapshot-style assertions で問題ない。 ## 実行したコマンド - `cargo test -p provider` - Result: passed - Summary: `47 passed; 0 failed; 0 ignored` - Doc tests: `0 passed; 0 failed`