From 92090f28bfc7bccd6d08231d972cfb39870e8a4b Mon Sep 17 00:00:00 2001 From: Zyy Date: Mon, 27 Jul 2026 13:13:44 +0800 Subject: [PATCH] docs(backend): unify provider comments to Chinese Convert the remaining English doc comments in the openai and xai provider crates to Chinese, function-oriented wording so the whole backend follows one convention. Explanatory narration is compressed into what the item does and what its errors mean; code identifiers, route paths, rustdoc links and `# Errors` headings stay as-is. Also fixes two half-translated comments left in the websocket protocol module and merges a duplicated doc block on the OIDC verifier constructor. No code, signature or `#[error(...)]` string changes. Co-authored-by: Codex --- .../src/redis/native_continuation.rs | 2 +- .../providers/openai/src/credential/mod.rs | 2 +- .../providers/openai/src/transport/client.rs | 28 ++-- .../openai/src/transport/diagnostics.rs | 2 +- .../src/transport/protocol/responses.rs | 2 +- .../src/transport/protocol/websocket.rs | 6 +- .../openai/src/transport/websocket/error.rs | 4 +- .../src/transport/websocket/exchange/mod.rs | 10 +- .../openai/src/transport/websocket/mod.rs | 2 +- .../openai/src/transport/websocket/model.rs | 2 +- .../xai/src/credential/authorization_code.rs | 21 ++- .../providers/xai/src/credential/client.rs | 33 +++-- .../providers/xai/src/credential/config.rs | 35 +++-- .../providers/xai/src/credential/discovery.rs | 16 +-- .../providers/xai/src/credential/error.rs | 124 +++++++++--------- .../providers/xai/src/credential/http.rs | 77 ++++++----- .../xai/src/credential/oidc_verifier.rs | 8 +- .../providers/xai/src/credential/secret.rs | 7 +- .../providers/xai/src/credential/token.rs | 36 ++--- .../xai/src/credential/verification.rs | 58 ++++---- backend/crates/providers/xai/src/lib.rs | 2 +- backend/crates/providers/xai/src/provider.rs | 17 +-- .../providers/xai/src/transport/canonical.rs | 8 +- .../providers/xai/src/transport/catalog.rs | 2 +- .../providers/xai/src/transport/headers.rs | 14 +- .../crates/providers/xai/src/transport/mod.rs | 2 +- .../providers/xai/src/transport/network.rs | 2 +- .../providers/xai/src/transport/profile.rs | 2 +- .../providers/xai/src/transport/request.rs | 7 +- .../providers/xai/src/transport/session.rs | 91 +++++++------ .../providers/xai/src/transport/transport.rs | 87 ++++++------ .../providers/xai/tests/credential/client.rs | 2 +- .../xai/tests/credential/oidc_verifier.rs | 2 +- .../providers/xai/tests/transport/network.rs | 2 +- 34 files changed, 348 insertions(+), 367 deletions(-) diff --git a/backend/crates/gateway-store/src/redis/native_continuation.rs b/backend/crates/gateway-store/src/redis/native_continuation.rs index 08e702e4f..441791d7f 100644 --- a/backend/crates/gateway-store/src/redis/native_continuation.rs +++ b/backend/crates/gateway-store/src/redis/native_continuation.rs @@ -60,7 +60,7 @@ end return 1 "#; -/// Redis-backed, best-effort native response continuation affinity. +/// 基于 Redis 的 best-effort 原生响应 continuation 亲和。 #[derive(Clone)] pub struct RedisNativeContinuationRepository { connection: ConnectionManager, diff --git a/backend/crates/providers/openai/src/credential/mod.rs b/backend/crates/providers/openai/src/credential/mod.rs index 5318ef031..c12d8539b 100644 --- a/backend/crates/providers/openai/src/credential/mod.rs +++ b/backend/crates/providers/openai/src/credential/mod.rs @@ -1,4 +1,4 @@ -//! Codex credential domain exports。 +//! Codex credential 领域导出。 mod admin; mod affinity; diff --git a/backend/crates/providers/openai/src/transport/client.rs b/backend/crates/providers/openai/src/transport/client.rs index e8d7214c3..208573a6a 100644 --- a/backend/crates/providers/openai/src/transport/client.rs +++ b/backend/crates/providers/openai/src/transport/client.rs @@ -35,7 +35,7 @@ use super::websocket::{ }; // --------------------------------------------------------------------------- -// Constants +// 常量 // --------------------------------------------------------------------------- const MAX_UPSTREAM_ERROR_BODY_BYTES: usize = 1024 * 1024; @@ -82,7 +82,7 @@ pub fn build_reqwest_client() -> Result { } // --------------------------------------------------------------------------- -// Error types +// 错误类型 // --------------------------------------------------------------------------- /// Codex 上游 HTTP 客户端错误。 @@ -245,7 +245,7 @@ pub type CodexBackendSseStream = Pin> + Send + 'static>>; // --------------------------------------------------------------------------- -// Request context & response types +// 请求上下文与响应类型 // --------------------------------------------------------------------------- /// 单次 Codex 上游请求的上下文。 @@ -253,7 +253,7 @@ pub type CodexBackendSseStream = pub struct CodexRequestContext<'a> { /// Provider 已构造并脱敏持有的完整 Authorization 值。 pub authorization: &'a str, - /// ChatGPT account id。 + /// ChatGPT 账号 ID。 pub account_id: Option<&'a str>, /// 代理请求 ID。 pub request_id: &'a str, @@ -261,11 +261,11 @@ pub struct CodexRequestContext<'a> { pub turn_state: Option<&'a str>, /// 客户端 turn metadata;其中 installation ID 已按当前账号处理。 pub turn_metadata: Option<&'a str>, - /// x-codex-beta-features。 + /// x-codex-beta-features 头值。 pub beta_features: Option<&'a str>, - /// x-responsesapi-include-timing-metrics。 + /// x-responsesapi-include-timing-metrics 头值。 pub include_timing_metrics: Option<&'a str>, - /// version。 + /// 客户端版本号。 pub version: Option<&'a str>, /// 客户端 window ID。 pub codex_window_id: Option<&'a str>, @@ -335,9 +335,9 @@ impl fmt::Debug for CodexRequestContext<'_> { /// Codex Responses 实际使用的上游传输。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CodexBackendTransport { - /// HTTP SSE transport. + /// HTTP SSE 传输。 HttpSse, - /// WebSocket transport. + /// WebSocket 传输。 WebSocket, } @@ -382,10 +382,10 @@ pub struct CodexTransportMetrics { pub http_version: Option, } -/// Live stream rate-limit updates captured after the response headers. +/// 响应头之后在 live 流中采集的限流更新。 pub type CodexRateLimitHeaderUpdates = CodexWebSocketRateLimitHeaderUpdates; -/// Live stream turn-state updates captured after the response headers. +/// 响应头之后在 live 流中采集的 turn state 更新。 pub type CodexTurnStateUpdate = CodexWebSocketTurnStateUpdate; /// Codex Responses 上游 live SSE 响应。 @@ -449,7 +449,7 @@ pub(super) struct PreparedWebSocketRoute { } // --------------------------------------------------------------------------- -// Response helpers +// 响应辅助函数 // --------------------------------------------------------------------------- pub(super) fn log_websocket_pool_decision( @@ -587,7 +587,7 @@ pub(super) async fn read_capped_error_body( } // --------------------------------------------------------------------------- -// Request helpers +// 请求辅助函数 // --------------------------------------------------------------------------- pub(super) fn websocket_upstream_request(request: &CodexResponsesRequest) -> CodexResponsesRequest { @@ -649,7 +649,7 @@ pub(super) fn openai_subagent_from_metadata(client_metadata: Option<&Value>) -> } // --------------------------------------------------------------------------- -// Error conversion helpers +// 错误转换辅助函数 // --------------------------------------------------------------------------- pub(super) fn websocket_exchange_error_to_client_error( diff --git a/backend/crates/providers/openai/src/transport/diagnostics.rs b/backend/crates/providers/openai/src/transport/diagnostics.rs index 0b9e5f90a..050cd5260 100644 --- a/backend/crates/providers/openai/src/transport/diagnostics.rs +++ b/backend/crates/providers/openai/src/transport/diagnostics.rs @@ -1,4 +1,4 @@ -//! Upstream response diagnostics captured at the transport boundary. +//! 在 transport 边界采集的上游响应诊断信息。 use super::protocol::responses::ResponsesSseFailure; use base64::{Engine as _, engine::general_purpose::STANDARD}; diff --git a/backend/crates/providers/openai/src/transport/protocol/responses.rs b/backend/crates/providers/openai/src/transport/protocol/responses.rs index 486b29c5b..ab2c050e3 100644 --- a/backend/crates/providers/openai/src/transport/protocol/responses.rs +++ b/backend/crates/providers/openai/src/transport/protocol/responses.rs @@ -60,7 +60,7 @@ pub struct CodexResponsesRequest { pub responses_lite: Option, /// Memory consolidation 请求语义;HTTP 与 WebSocket opening 均使用 header。 pub memgen_request: Option, - /// codex window id。 + /// Codex window ID。 pub codex_window_id: Option, /// 父线程 ID。 pub parent_thread_id: Option, diff --git a/backend/crates/providers/openai/src/transport/protocol/websocket.rs b/backend/crates/providers/openai/src/transport/protocol/websocket.rs index c628c137a..f8b24f0f8 100644 --- a/backend/crates/providers/openai/src/transport/protocol/websocket.rs +++ b/backend/crates/providers/openai/src/transport/protocol/websocket.rs @@ -13,7 +13,7 @@ pub struct OpeningAuditSnapshot { pub request_line: String, /// 请求头顺序。 pub header_order: Vec, - /// 红action后的请求头。 + /// 脱敏后的请求头。 pub headers: Vec, } @@ -31,11 +31,11 @@ pub struct OpeningAuditHeader { pub struct PayloadAuditSnapshot { /// 按构造顺序记录的顶层字段。 pub top_level_keys: Vec, - /// 红action后的 JSON payload。 + /// 脱敏后的 JSON payload。 pub body: Value, } -/// WebSocket audit artifact. +/// WebSocket 审计产物。 #[derive(Debug, Clone, Serialize, PartialEq, Eq)] pub struct WebSocketAuditArtifact { /// 实际选择的传输模式。 diff --git a/backend/crates/providers/openai/src/transport/websocket/error.rs b/backend/crates/providers/openai/src/transport/websocket/error.rs index 0c67b0e76..e956d0909 100644 --- a/backend/crates/providers/openai/src/transport/websocket/error.rs +++ b/backend/crates/providers/openai/src/transport/websocket/error.rs @@ -10,7 +10,7 @@ use crate::transport::diagnostics::CodexUpstreamSendPhase; use super::PreviousResponseUnavailableReason; -/// Responses WebSocket exchange error. +/// Responses WebSocket 交互错误。 #[derive(Debug, Error)] pub enum CodexWebSocketExchangeError { /// opening request 无法构造。 @@ -98,7 +98,7 @@ pub enum CodexWebSocketExchangeError { /// WebSocket 上游错误帧载荷。 #[derive(Debug, Clone, PartialEq, Eq)] pub struct CodexWebSocketUpstreamError { - /// HTTP-style upstream status code. + /// 上游返回的 HTTP 风格状态码。 pub status_code: u16, /// 推导出的重试秒数。 pub retry_after_seconds: Option, diff --git a/backend/crates/providers/openai/src/transport/websocket/exchange/mod.rs b/backend/crates/providers/openai/src/transport/websocket/exchange/mod.rs index 9e7440349..c4870c11c 100644 --- a/backend/crates/providers/openai/src/transport/websocket/exchange/mod.rs +++ b/backend/crates/providers/openai/src/transport/websocket/exchange/mod.rs @@ -24,11 +24,11 @@ const WEBSOCKET_STREAM_BUFFER: usize = 16; pub(super) use self::stream::{WebSocketStreamPoolReturn, stream_websocket_response}; -/// Responses WebSocket live SSE exchange result. +/// Responses WebSocket live SSE 交互结果。 pub struct CodexWebSocketStreamingExchange { /// 关联请求日志与底层 pump 生命周期日志的连接标识。 pub(crate) websocket_connection_id: Uuid, - /// Live SSE bytes converted from WebSocket events. + /// 由 WebSocket 事件转换出的 live SSE 字节流。 pub body: CodexWebSocketSseStream, /// 上游 metadata 帧中的最新 turn state。 pub turn_state: Option, @@ -50,12 +50,12 @@ pub struct CodexWebSocketStreamingExchange { pub response_metadata: CodexResponseMetadata, } -/// Responses WebSocket live SSE byte stream. +/// Responses WebSocket live SSE 字节流。 pub type CodexWebSocketSseStream = Pin> + Send + 'static>>; -/// WebSocket live stream rate-limit header updates. +/// live 流中的限流头动态更新。 pub type CodexWebSocketRateLimitHeaderUpdates = Arc>>; -/// WebSocket live stream turn-state update. +/// live 流中的 turn state 动态更新。 pub type CodexWebSocketTurnStateUpdate = Arc>>; pub(super) fn reusable_websocket_metadata( diff --git a/backend/crates/providers/openai/src/transport/websocket/mod.rs b/backend/crates/providers/openai/src/transport/websocket/mod.rs index e291cca82..cc07e39db 100644 --- a/backend/crates/providers/openai/src/transport/websocket/mod.rs +++ b/backend/crates/providers/openai/src/transport/websocket/mod.rs @@ -1,4 +1,4 @@ -//! Codex HTTP Responses WebSocket transport。 +//! Codex Responses WebSocket 传输。 mod audit; mod breaker; diff --git a/backend/crates/providers/openai/src/transport/websocket/model.rs b/backend/crates/providers/openai/src/transport/websocket/model.rs index d1a5429dd..618430408 100644 --- a/backend/crates/providers/openai/src/transport/websocket/model.rs +++ b/backend/crates/providers/openai/src/transport/websocket/model.rs @@ -13,7 +13,7 @@ pub struct CodexWebSocketConnection { pub(super) headers: Vec<(String, String)>, } -/// Prepared Responses WebSocket request descriptor. +/// 已构造完成的 Responses WebSocket 请求描述。 #[derive(Debug, Clone, PartialEq, Eq)] pub struct CodexWebSocketRequest { pub(super) connection: CodexWebSocketConnection, diff --git a/backend/crates/providers/xai/src/credential/authorization_code.rs b/backend/crates/providers/xai/src/credential/authorization_code.rs index 7a5e04f5b..40819276c 100644 --- a/backend/crates/providers/xai/src/credential/authorization_code.rs +++ b/backend/crates/providers/xai/src/credential/authorization_code.rs @@ -14,7 +14,7 @@ use crate::{ const MAX_CALLBACK_VALUE_BYTES: usize = 64 * 1024; -/// Parsed callback whose code and state remain redacted in debug output. +/// 已解析的回调;code 与 state 在 debug 输出中保持脱敏。 pub struct AuthorizationCallback { code: Option, state: Option, @@ -22,13 +22,13 @@ pub struct AuthorizationCallback { } impl AuthorizationCallback { - /// Parses an OAuth callback query while rejecting duplicate security fields. - /// Raw server descriptions are intentionally discarded. + /// 解析 OAuth 回调 query,并拒绝重复的安全敏感参数。 + /// 服务端原始描述文本一律丢弃。 /// /// # Errors /// - /// Returns [`CallbackRejection::DuplicateParameter`] for repeated `code`, - /// `state`, or `error` keys. + /// `code`、`state` 或 `error` 键重复出现时返回 + /// [`CallbackRejection::DuplicateParameter`]。 pub fn parse(query: &str) -> Result { let mut code = None; let mut state = None; @@ -72,7 +72,7 @@ impl fmt::Debug for AuthorizationCallback { } } -/// Authorization Code + PKCE state awaiting one callback. +/// 等待一次回调的 Authorization Code + PKCE 状态。 pub struct PendingAuthorization { authorization_url: Url, redirect_uri: AllowedRedirectUri, @@ -122,7 +122,7 @@ impl PendingAuthorization { }) } - /// Returns the URL that an administrator opens at the official issuer. + /// 返回管理员需在官方 issuer 打开的 URL。 #[must_use] pub fn authorization_url(&self) -> &Url { &self.authorization_url @@ -180,12 +180,11 @@ impl PendingAuthorization { }) } - /// Consumes the one-time flow and validates mandatory callback state. + /// 消费一次性流程并校验必需的回调 state。 /// /// # Errors /// - /// Returns a callback rejection for missing/mismatched state, provider - /// denial, or a missing code. + /// state 缺失或不匹配、provider 拒绝、code 缺失时返回回调拒绝错误。 pub fn accept_callback( self, callback: AuthorizationCallback, @@ -247,7 +246,7 @@ impl fmt::Debug for PendingAuthorization { } } -/// State-validated authorization grant ready for one token exchange. +/// 已通过 state 校验、可用于一次 token 交换的授权 grant。 pub struct AuthorizationCodeGrant { code: SecretValue, redirect_uri: AllowedRedirectUri, diff --git a/backend/crates/providers/xai/src/credential/client.rs b/backend/crates/providers/xai/src/credential/client.rs index 675e81dc0..303019826 100644 --- a/backend/crates/providers/xai/src/credential/client.rs +++ b/backend/crates/providers/xai/src/credential/client.rs @@ -9,7 +9,7 @@ use crate::{ VerificationMethod, VerifiedTokenSet, }; -/// Transport-agnostic official Grok Build OAuth protocol client. +/// 与 transport 无关的官方 Grok Build OAuth 协议客户端。 #[derive(Clone)] pub struct GrokOAuthClient { config: GrokOAuthConfig, @@ -19,7 +19,7 @@ pub struct GrokOAuthClient { } impl GrokOAuthClient { - /// Creates a client with explicit HTTP and token verification trust ports. + /// 创建客户端,显式注入 HTTP 与 token 验证两个信任端口。 #[must_use] pub fn new( config: GrokOAuthConfig, @@ -35,18 +35,18 @@ impl GrokOAuthClient { } } - /// Returns the immutable official provider configuration. + /// 返回不可变的官方 provider 配置。 #[must_use] pub const fn config(&self) -> &GrokOAuthConfig { &self.config } - /// Fetches and validates official same-origin OIDC discovery. + /// 拉取并校验官方同源 OIDC 发现文档。 /// /// # Errors /// - /// Fails on transport errors, non-success status, malformed JSON, issuer - /// mismatch, cross-origin endpoints, missing JWKS, or insecure algorithms. + /// transport 失败、非成功状态、JSON 非法、issuer 不匹配、端点跨 origin、 + /// 缺少 JWKS 或算法不安全时返回错误。 pub async fn discover(&self) -> Result { let response = self .execute( @@ -63,12 +63,11 @@ impl GrokOAuthClient { DiscoveryDocument::parse(&self.config, response.body()) } - /// Starts Authorization Code + PKCE without performing network I/O. + /// 启动 Authorization Code + PKCE,不产生网络 I/O。 /// /// # Errors /// - /// Returns an entropy error if secure random state, nonce, or verifier - /// generation fails. + /// 安全随机 state、nonce 或 verifier 生成失败时返回熵不可用错误。 pub fn start_authorization_code( &self, discovery: &DiscoveryDocument, @@ -78,13 +77,13 @@ impl GrokOAuthClient { PendingAuthorization::start(&self.config, discovery, redirect_uri, principal) } - /// Exchanges a state-validated authorization grant exactly once, then - /// requires nonce-bound ID-token verification before returning credentials. + /// 对已校验 state 的授权 grant 只做一次交换,返回凭据前强制通过 + /// nonce 绑定的 ID token 验证。 /// /// # Errors /// - /// Fails on transport/protocol errors, missing ID token, failed verification, - /// or any non-success OAuth response. No automatic retry is performed. + /// transport/协议错误、缺少 ID token、验证失败或任何非成功 OAuth 响应时 + /// 返回错误。不做自动重试。 pub async fn exchange_authorization_code( &self, discovery: &DiscoveryDocument, @@ -216,13 +215,13 @@ impl GrokOAuthClient { Ok(VerifiedTokenSet::new(tokens, evidence, scope)) } - /// Exchanges a refresh token once. The caller must serialize refreshes and - /// persist rotated tokens through credential-revision CAS. + /// 执行一次 refresh token 交换。调用方须串行化刷新,并通过 credential + /// revision CAS 持久化轮换后的 token。 /// /// # Errors /// - /// Returns a classified OAuth error. Ambiguous transport failures must not - /// be retried automatically because the refresh token may have rotated. + /// 返回已分类的 OAuth 错误。refresh token 可能已轮换,Ambiguous 类 + /// transport 失败不得自动重试。 pub async fn refresh( &self, discovery: &DiscoveryDocument, diff --git a/backend/crates/providers/xai/src/credential/config.rs b/backend/crates/providers/xai/src/credential/config.rs index f450be47e..7c1b20389 100644 --- a/backend/crates/providers/xai/src/credential/config.rs +++ b/backend/crates/providers/xai/src/credential/config.rs @@ -4,16 +4,16 @@ use url::{Host, Url}; use crate::ConfigError; -/// Official first-party OIDC issuer used by Grok Build. +/// Grok Build 使用的官方第一方 OIDC issuer。 pub const OFFICIAL_ISSUER: &str = "https://auth.x.ai"; -/// Official public OAuth client identifier embedded in Grok Build. +/// Grok Build 内置的官方 public OAuth client 标识。 pub const OFFICIAL_CLIENT_ID: &str = "b1a00492-073a-47ea-816f-4c329264a828"; /// 官方桌面客户端使用的固定 loopback OAuth 回调地址。 pub const OFFICIAL_REDIRECT_URI: &str = "http://127.0.0.1:56121/callback"; -/// Official first-party OAuth scope set used by current Grok Build clients. +/// 当前 Grok Build 客户端使用的官方第一方 OAuth scope 集合。 pub const OFFICIAL_SCOPES: &[&str] = &[ "openid", "profile", @@ -23,12 +23,12 @@ pub const OFFICIAL_SCOPES: &[&str] = &[ "api:access", ]; -/// Exact redirect URI that has passed syntax and local allowlist checks. +/// 已通过语法与本地 allowlist 校验的精确回调 URI。 #[derive(Debug, Clone, PartialEq, Eq)] pub struct AllowedRedirectUri(Url); impl AllowedRedirectUri { - /// Returns the exact redirect URI sent during authorization and exchange. + /// 返回授权与 token 交换时发送的精确回调 URI。 #[must_use] pub fn as_url(&self) -> &Url { &self.0 @@ -39,20 +39,19 @@ impl AllowedRedirectUri { } } -/// Explicit callback allowlist. Public HTTPS callbacks and dynamic loopback -/// callbacks must be inserted before a flow can start. +/// 显式回调 allowlist。公网 HTTPS 回调与动态 loopback 回调必须先登记才能启动流程。 #[derive(Debug, Clone)] pub struct RedirectUriAllowlist { entries: Vec, } impl RedirectUriAllowlist { - /// Validates and constructs an exact redirect allowlist. + /// 校验并构造精确回调 allowlist。 /// /// # Errors /// - /// Returns [`ConfigError::InvalidRedirectUri`] for non-HTTPS public URIs, - /// user-info, query strings, fragments, or malformed values. + /// 公网 URI 非 HTTPS、含 user-info、query、fragment 或格式非法时返回 + /// [`ConfigError::InvalidRedirectUri`]。 pub fn new(uris: I) -> Result where I: IntoIterator, @@ -66,11 +65,11 @@ impl RedirectUriAllowlist { Ok(Self { entries }) } - /// Validates a candidate and requires an exact local allowlist match. + /// 校验候选 URI,并要求与本地 allowlist 精确匹配。 /// /// # Errors /// - /// Returns a configuration error when the URI is invalid or absent. + /// URI 非法或未登记时返回配置错误。 pub fn authorize(&self, candidate: &str) -> Result { let candidate = validate_redirect_uri(candidate)?; if self.entries.iter().any(|entry| entry == &candidate) { @@ -81,36 +80,36 @@ impl RedirectUriAllowlist { } } -/// Immutable official Grok Build OAuth configuration. +/// 不可变的官方 Grok Build OAuth 配置。 #[derive(Clone)] pub struct GrokOAuthConfig { issuer: Url, } impl GrokOAuthConfig { - /// Builds the fixed official issuer, client, and scope configuration. + /// 构造固定的官方 issuer、client 与 scope 配置。 /// /// # Errors /// - /// Returns an error when the fixed official issuer cannot be constructed. + /// 固定官方 issuer 无法构造时返回错误。 pub fn official() -> Result { let issuer = Url::parse(OFFICIAL_ISSUER).map_err(|_| ConfigError::UntrustedIssuer)?; Ok(Self { issuer }) } - /// Returns the fixed issuer URL. + /// 返回固定的 issuer URL。 #[must_use] pub fn issuer(&self) -> &Url { &self.issuer } - /// Returns the official public client identifier. + /// 返回官方 public client 标识。 #[must_use] pub const fn client_id(&self) -> &'static str { OFFICIAL_CLIENT_ID } - /// Returns the official scope set. + /// 返回官方 scope 集合。 #[must_use] pub const fn scopes(&self) -> &'static [&'static str] { OFFICIAL_SCOPES diff --git a/backend/crates/providers/xai/src/credential/discovery.rs b/backend/crates/providers/xai/src/credential/discovery.rs index fa2f30eda..3a31988eb 100644 --- a/backend/crates/providers/xai/src/credential/discovery.rs +++ b/backend/crates/providers/xai/src/credential/discovery.rs @@ -5,8 +5,7 @@ use crate::{GrokOAuthConfig, OAuthError, OAuthOperation, ProtocolViolation}; pub(crate) const MAX_OAUTH_RESPONSE_BYTES: usize = 64 * 1024; -/// A discovery document whose issuer and endpoints have passed the official -/// Grok Build origin policy. +/// issuer 与端点均已通过官方 Grok Build origin 策略校验的发现文档。 #[derive(Debug, Clone, PartialEq, Eq)] pub struct DiscoveryDocument { issuer: Url, @@ -70,38 +69,37 @@ impl DiscoveryDocument { }) } - /// Returns the validated issuer from the discovery document. + /// 返回发现文档中已校验的 issuer。 #[must_use] pub fn issuer(&self) -> &Url { &self.issuer } - /// Returns the validated authorization endpoint. + /// 返回已校验的 authorization 端点。 #[must_use] pub fn authorization_endpoint(&self) -> &Url { &self.authorization_endpoint } - /// Returns the validated token endpoint. + /// 返回已校验的 token 端点。 #[must_use] pub fn token_endpoint(&self) -> &Url { &self.token_endpoint } - /// Returns the validated JWKS endpoint required by an ID-token verifier. + /// 返回 ID token 校验器所需的已校验 JWKS 端点。 #[must_use] pub fn jwks_uri(&self) -> &Url { &self.jwks_uri } - /// Returns the validated authoritative user-info endpoint. + /// 返回已校验的权威 user-info 端点。 #[must_use] pub fn userinfo_endpoint(&self) -> &Url { &self.userinfo_endpoint } - /// Returns algorithms advertised by discovery. The verifier must still - /// enforce its own cryptographic allowlist. + /// 返回发现文档声明的算法;校验器仍须强制自身的密码学 allowlist。 #[must_use] pub fn signing_algorithms(&self) -> &[String] { &self.signing_algorithms diff --git a/backend/crates/providers/xai/src/credential/error.rs b/backend/crates/providers/xai/src/credential/error.rs index d0e648283..3b94c9f83 100644 --- a/backend/crates/providers/xai/src/credential/error.rs +++ b/backend/crates/providers/xai/src/credential/error.rs @@ -2,188 +2,188 @@ use thiserror::Error; use crate::TransportFailureKind; -/// Static OAuth operation labels used for safe telemetry and classification. +/// OAuth 操作标签,用于脱敏遥测与错误分类。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OAuthOperation { - /// OpenID Provider discovery. + /// OpenID Provider 发现。 Discovery, - /// Authorization-code token exchange. + /// Authorization Code 换取 token。 AuthorizationCodeToken, - /// Refresh-token exchange. + /// Refresh token 换取 token。 RefreshToken, /// 已有 OAuth token 的受控导入验证。 CredentialImport, } -/// Stable OAuth error codes that are safe to expose to control-plane logic. +/// 可安全暴露给控制面的稳定 OAuth 错误码。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OAuthErrorCode { - /// The human rejected authorization. + /// 用户拒绝授权。 AccessDenied, - /// A code or refresh token is invalid or already consumed. + /// code 或 refresh token 无效或已被消费。 InvalidGrant, - /// The configured public client is rejected. + /// 配置的 public client 被拒绝。 InvalidClient, - /// The requested official scope set is rejected. + /// 请求的官方 scope 集合被拒绝。 InvalidScope, - /// The authorization server is temporarily unavailable. + /// 授权服务器暂时不可用。 TemporarilyUnavailable, - /// An unrecognized code whose raw server text is intentionally discarded. + /// 无法识别的错误码;不保留服务端原文。 Other, } -/// High-level action a coordinator may take after a failure. +/// 失败后协调方可采取的处置类别。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FailureClass { - /// Safe transient failure; a later, separately coordinated attempt may run. + /// 瞬时失败,允许后续独立协调的重试。 Transient, - /// Send state is ambiguous and the one-time artifact must not be replayed. + /// 发送状态不确定,一次性凭据不得重放。 Ambiguous, - /// Credential material is permanently rejected at its current revision. + /// 当前 revision 的凭据被永久拒绝。 CredentialPermanent, - /// Provider/client configuration is permanently rejected. + /// Provider 或 client 配置被永久拒绝。 ConfigurationPermanent, - /// The human denied or must restart the interactive flow. + /// 用户已拒绝,或需要重新发起交互流程。 UserActionRequired, - /// Protocol or trust-boundary validation failed closed. + /// 协议或信任边界校验失败并 fail closed。 Security, - /// The official deployment does not offer the requested flow. + /// 官方部署不提供该流程。 Unsupported, } -/// Configuration failures detected before any network request. +/// 发起网络请求前检出的配置错误。 #[derive(Debug, Error, Clone, PartialEq, Eq)] pub enum ConfigError { - /// Redirect URI is malformed, insecure, or contains forbidden components. + /// 回调 URI 格式非法、不安全或包含禁止成分。 #[error("invalid OAuth redirect URI")] InvalidRedirectUri, - /// Redirect URI was not explicitly registered in the local allowlist. + /// 回调 URI 未登记在本地 allowlist。 #[error("OAuth redirect URI is not allowlisted")] RedirectUriNotAllowlisted, - /// Issuer differs from the official Grok Build issuer. + /// issuer 不是官方 Grok Build issuer。 #[error("OIDC issuer is not the official Grok Build issuer")] UntrustedIssuer, - /// A discovered endpoint leaves the official issuer origin. + /// 发现文档中的端点离开了官方 issuer origin。 #[error("OIDC discovery returned an untrusted endpoint")] UntrustedEndpoint, - /// Optional team principal metadata is empty or contains unsafe text. + /// 可选的 team principal 元数据为空或含不安全文本。 #[error("invalid OAuth principal metadata")] InvalidPrincipal, } -/// Safe, field-oriented protocol validation errors. +/// 按字段定位的脱敏协议校验错误。 #[derive(Debug, Error, Clone, Copy, PartialEq, Eq)] pub enum ProtocolViolation { - /// JSON could not be decoded into the expected wire schema. + /// JSON 无法解析为预期 wire 结构。 #[error("OAuth response is not valid JSON")] InvalidJson, - /// A required wire field is absent. + /// 缺少必需的 wire 字段。 #[error("OAuth response is missing field `{0}`")] MissingField(&'static str), - /// A wire field violates its format or size contract. + /// wire 字段违反格式或长度约束。 #[error("OAuth response contains invalid field `{0}`")] InvalidField(&'static str), - /// A response exceeded the bounded parser limit. + /// 响应超出解析器的体积上限。 #[error("OAuth response exceeds the maximum body size")] ResponseTooLarge, - /// The discovery document permits the insecure `none` signing algorithm. + /// 发现文档允许不安全的 `none` 签名算法。 #[error("OIDC discovery advertises an insecure signing algorithm")] InsecureSigningAlgorithm, } -/// Callback failures that never retain the authorization code or state value. +/// 回调失败原因;不保留 code 与 state 值。 #[derive(Debug, Error, Clone, Copy, PartialEq, Eq)] pub enum CallbackRejection { - /// Query contains repeated security-sensitive keys. + /// query 中出现重复的安全敏感参数。 #[error("OAuth callback contains a duplicate parameter")] DuplicateParameter, - /// Provider callback omitted the one-time state. + /// 回调缺少一次性 state。 #[error("OAuth callback is missing state")] MissingState, - /// Provider callback omitted the authorization code. + /// 回调缺少 authorization code。 #[error("OAuth callback is missing code")] MissingCode, - /// One-time state does not match the pending flow. + /// 一次性 state 与 pending flow 不匹配。 #[error("OAuth callback state mismatch")] StateMismatch, - /// Authorization server returned `access_denied`. + /// 授权服务器返回 `access_denied`。 #[error("OAuth authorization was denied")] AccessDenied, - /// Authorization server returned another callback error. + /// 授权服务器返回其他回调错误。 #[error("OAuth authorization callback was rejected")] ProviderRejected, } -/// Reasons an unverified token set cannot cross the credential boundary. +/// 未验证 token 集合无法通过凭据边界的原因。 #[derive(Debug, Error, Clone, Copy, PartialEq, Eq)] pub enum VerificationFailure { - /// No JWT/JWKS or authoritative user-info verifier was wired. + /// 未注入 JWT/JWKS 或权威 user-info 校验器。 #[error("token verification is unavailable; refusing unverified credentials")] Unavailable, - /// Authorization-code response omitted its required ID token. + /// Authorization Code 响应缺少必需的 ID token。 #[error("authorization-code response is missing an ID token")] MissingIdToken, - /// The verifier rejected signature, issuer, audience, nonce, expiry, or identity. + /// 校验器拒绝了签名、issuer、audience、nonce、过期时间或身份。 #[error("token verification failed")] Rejected, - /// Authorization-code flow was not verified through an ID token. + /// Authorization Code 流程未经 ID token 验证。 #[error("authorization-code flow requires verified ID-token evidence")] WrongEvidence, } -/// Secret-free OAuth protocol error. +/// 不含密钥的 OAuth 协议错误。 #[derive(Debug, Error)] pub enum OAuthError { - /// Local trust or redirect configuration is invalid. + /// 本地信任或回调配置非法。 #[error(transparent)] Configuration(#[from] ConfigError), - /// Replaceable transport failed without retaining its raw error message. + /// 可替换 transport 失败;不保留原始错误信息。 #[error("OAuth transport failed during {operation:?}: {kind:?}")] Transport { - /// Operation being executed. + /// 执行中的操作。 operation: OAuthOperation, - /// Safe send-state classification. + /// 脱敏的发送状态分类。 kind: TransportFailureKind, }, - /// Non-success HTTP response without a recognized OAuth code. + /// 非成功 HTTP 响应,且没有可识别的 OAuth 错误码。 #[error("OAuth endpoint returned HTTP {status} during {operation:?}")] HttpStatus { - /// Operation being executed. + /// 执行中的操作。 operation: OAuthOperation, - /// HTTP status code. + /// HTTP 状态码。 status: u16, }, - /// Recognized OAuth error response. + /// 可识别的 OAuth 错误响应。 #[error("OAuth endpoint returned {code:?} during {operation:?}")] Server { - /// Operation being executed. + /// 执行中的操作。 operation: OAuthOperation, - /// HTTP status code. + /// HTTP 状态码。 status: u16, - /// Stable OAuth error code. + /// 稳定 OAuth 错误码。 code: OAuthErrorCode, }, - /// Callback was rejected before token exchange. + /// token 交换前回调即被拒绝。 #[error(transparent)] Callback(#[from] CallbackRejection), - /// Wire response violated the strict parser contract. + /// wire 响应违反严格解析契约。 #[error("{operation:?} protocol violation: {violation}")] Protocol { - /// Operation being parsed. + /// 解析中的操作。 operation: OAuthOperation, - /// Safe field-oriented reason. + /// 按字段定位的脱敏原因。 violation: ProtocolViolation, }, - /// Token set failed the mandatory verification boundary. + /// token 集合未通过强制验证边界。 #[error(transparent)] Verification(#[from] VerificationFailure), - /// Cryptographically secure entropy was unavailable before a flow started. + /// 流程启动前无法获得安全随机数。 #[error("secure OAuth entropy is unavailable")] EntropyUnavailable, } impl OAuthError { - /// Returns a low-cardinality failure class for orchestration decisions. + /// 返回供编排决策使用的低基数失败类别。 #[must_use] pub fn class(&self) -> FailureClass { match self { diff --git a/backend/crates/providers/xai/src/credential/http.rs b/backend/crates/providers/xai/src/credential/http.rs index 62a38a969..6145678f7 100644 --- a/backend/crates/providers/xai/src/credential/http.rs +++ b/backend/crates/providers/xai/src/credential/http.rs @@ -7,16 +7,16 @@ use zeroize::Zeroizing; use crate::SecretValue; -/// HTTP methods needed by the OAuth protocol. +/// OAuth 协议所需的 HTTP 方法。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HttpMethod { - /// Read-only discovery request. + /// 只读的发现请求。 Get, - /// Form-encoded OAuth request. + /// form 编码的 OAuth 请求。 Post, } -/// A request header whose value is public protocol metadata. +/// 值为公开协议元数据的请求头。 #[derive(Debug, Clone, PartialEq, Eq)] pub struct HttpHeader { name: &'static str, @@ -24,7 +24,7 @@ pub struct HttpHeader { } impl HttpHeader { - /// Creates a public request header. + /// 创建公开请求头。 #[must_use] pub fn new(name: &'static str, value: impl Into) -> Self { Self { @@ -33,30 +33,30 @@ impl HttpHeader { } } - /// Returns the header name. + /// 返回请求头名称。 #[must_use] pub fn name(&self) -> &'static str { self.name } - /// Returns the public header value. + /// 返回公开的请求头值。 #[must_use] pub fn value(&self) -> &str { &self.value } } -/// A public or sensitive form field value. +/// 公开或敏感的 form 字段值。 #[derive(Clone)] pub enum FormValue { - /// Non-sensitive protocol metadata. + /// 非敏感的协议元数据。 Public(String), - /// Authorization code, verifier, or token. + /// authorization code、verifier 或 token。 Secret(SecretValue), } impl FormValue { - /// Exposes a value at the HTTP encoder boundary. + /// 在 HTTP 编码边界暴露值。 #[must_use] pub fn expose(&self) -> &str { match self { @@ -75,7 +75,7 @@ impl fmt::Debug for FormValue { } } -/// One `application/x-www-form-urlencoded` field. +/// 单个 `application/x-www-form-urlencoded` 字段。 #[derive(Debug, Clone)] pub struct FormField { name: &'static str, @@ -83,7 +83,7 @@ pub struct FormField { } impl FormField { - /// Creates a public field. + /// 创建公开字段。 #[must_use] pub fn public(name: &'static str, value: impl Into) -> Self { Self { @@ -92,7 +92,7 @@ impl FormField { } } - /// Creates a sensitive field. + /// 创建敏感字段。 #[must_use] pub fn secret(name: &'static str, value: SecretValue) -> Self { Self { @@ -101,20 +101,20 @@ impl FormField { } } - /// Returns the form field name. + /// 返回 form 字段名。 #[must_use] pub fn name(&self) -> &'static str { self.name } - /// Returns the form field value. + /// 返回 form 字段值。 #[must_use] pub fn value(&self) -> &FormValue { &self.value } } -/// A transport-neutral OAuth HTTP request. +/// 与 transport 无关的 OAuth HTTP 请求。 #[derive(Debug, Clone)] pub struct OAuthHttpRequest { method: HttpMethod, @@ -142,39 +142,39 @@ impl OAuthHttpRequest { } } - /// Returns the request method. + /// 返回请求方法。 #[must_use] pub const fn method(&self) -> HttpMethod { self.method } - /// Returns the validated destination URL. + /// 返回已校验的目标 URL。 #[must_use] pub fn url(&self) -> &Url { &self.url } - /// Returns public request headers. + /// 返回公开请求头。 #[must_use] pub fn headers(&self) -> &[HttpHeader] { &self.headers } - /// Returns form fields. Transport implementations must not log them. + /// 返回 form 字段。transport 实现不得记录这些值。 #[must_use] pub fn form(&self) -> &[FormField] { &self.form } } -/// A response body that is zeroized and omitted from debug output. +/// 响应体会被清零,且不出现在 debug 输出中。 pub struct OAuthHttpResponse { status: u16, body: Zeroizing>, } impl OAuthHttpResponse { - /// Constructs a response from a status code and raw body. + /// 由状态码与原始响应体构造响应。 #[must_use] pub fn new(status: u16, body: impl Into>) -> Self { Self { @@ -183,7 +183,7 @@ impl OAuthHttpResponse { } } - /// Returns the HTTP status code. + /// 返回 HTTP 状态码。 #[must_use] pub const fn status(&self) -> u16 { self.status @@ -205,51 +205,48 @@ impl fmt::Debug for OAuthHttpResponse { } } -/// Whether an HTTP failure definitely occurred before sending or may have -/// consumed a one-time authorization artifact. +/// 区分 HTTP 失败确定发生在发送前,还是可能已消费一次性授权凭据。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TransportFailureKind { - /// No request bytes were sent, so a coordinator may safely retry. + /// 未发送任何请求字节,协调方可安全重试。 NotSent, - /// The server may have consumed a code or rotating refresh token. + /// 服务端可能已消费 code 或轮换的 refresh token。 Ambiguous, - /// A timeout occurred and send state is unknown. + /// 发生超时,发送状态未知。 Timeout, - /// TLS establishment or validation failed before an accepted response. + /// 在收到有效响应前 TLS 建立或校验失败。 Tls, } -/// A deliberately low-cardinality, secret-free transport error. +/// 有意保持低基数且不含密钥的 transport 错误。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct TransportFailure { kind: TransportFailureKind, } impl TransportFailure { - /// Creates a transport failure without retaining a potentially sensitive - /// third-party error message. + /// 创建 transport 失败,不保留可能敏感的第三方错误信息。 #[must_use] pub const fn new(kind: TransportFailureKind) -> Self { Self { kind } } - /// Returns the send-state classification. + /// 返回发送状态分类。 #[must_use] pub const fn kind(self) -> TransportFailureKind { self.kind } } -/// Future returned by an OAuth HTTP transport. +/// OAuth HTTP transport 返回的 Future。 pub type TransportFuture<'a> = Pin> + Send + 'a>>; -/// Replaceable HTTP boundary for OAuth protocol requests. +/// OAuth 协议请求的可替换 HTTP 边界。 /// -/// Implementations must enforce TLS, bounded response bodies, and proxy/IP -/// affinity outside this crate. They must never log form values or response -/// bodies. +/// 实现方需在本 crate 之外保证 TLS、有界响应体与 proxy/IP 亲和性, +/// 且不得记录 form 值或响应体。 pub trait OAuthHttpTransport: Send + Sync { - /// Executes one request without hidden retries. + /// 执行一次请求,不做隐式重试。 fn execute(&self, request: OAuthHttpRequest) -> TransportFuture<'_>; } diff --git a/backend/crates/providers/xai/src/credential/oidc_verifier.rs b/backend/crates/providers/xai/src/credential/oidc_verifier.rs index 249f3ca43..6dc9f0651 100644 --- a/backend/crates/providers/xai/src/credential/oidc_verifier.rs +++ b/backend/crates/providers/xai/src/credential/oidc_verifier.rs @@ -43,12 +43,8 @@ pub struct ReqwestOidcTokenVerifier { } impl ReqwestOidcTokenVerifier { - /// 构建只允许访问 `auth.x.ai` 官方验证端点的 verifier。 - /// - /// # Errors - /// - /// TLS client 初始化失败时返回 transport build error。 - /// 构建使用显式 endpoint policy 与 JWKS cache TTL 的 verifier。 + /// 构建 verifier;使用显式 endpoint policy 与 JWKS cache TTL,只允许访问 + /// `auth.x.ai` 官方验证端点。 /// /// # Errors /// diff --git a/backend/crates/providers/xai/src/credential/secret.rs b/backend/crates/providers/xai/src/credential/secret.rs index c021bca0f..d61028ea4 100644 --- a/backend/crates/providers/xai/src/credential/secret.rs +++ b/backend/crates/providers/xai/src/credential/secret.rs @@ -2,19 +2,18 @@ use std::fmt; use zeroize::Zeroizing; -/// An in-memory secret whose debug output is always redacted and whose buffer -/// is zeroized on drop. +/// 内存中的 secret;debug 输出恒为脱敏,缓冲区在 drop 时清零。 #[derive(Clone)] pub struct SecretValue(Zeroizing); impl SecretValue { - /// Wraps an owned secret value. + /// 包装持有所有权的 secret 值。 #[must_use] pub fn new(value: impl Into) -> Self { Self(Zeroizing::new(value.into())) } - /// Exposes the secret only at an explicit protocol or transport boundary. + /// 仅在明确的协议或 transport 边界暴露 secret。 #[must_use] pub fn expose(&self) -> &str { self.0.as_str() diff --git a/backend/crates/providers/xai/src/credential/token.rs b/backend/crates/providers/xai/src/credential/token.rs index f95cf8e57..04c61b33b 100644 --- a/backend/crates/providers/xai/src/credential/token.rs +++ b/backend/crates/providers/xai/src/credential/token.rs @@ -12,7 +12,7 @@ use crate::{ const MAX_TOKEN_BYTES: usize = 64 * 1024; const MAX_TOKEN_LIFETIME_SECONDS: u64 = 366 * 24 * 60 * 60; -/// Optional team principal fields sent during refresh. +/// refresh 请求可选携带的 team principal 字段。 #[derive(Clone, PartialEq, Eq)] pub struct OAuthPrincipal { principal_type: String, @@ -30,12 +30,12 @@ impl fmt::Debug for OAuthPrincipal { } impl OAuthPrincipal { - /// Creates validated principal metadata. + /// 创建校验过的 principal 元数据。 /// /// # Errors /// - /// Returns [`ConfigError::InvalidPrincipal`] for empty, oversized, or - /// control-character-bearing values. + /// 值为空、超长或含控制字符时返回 + /// [`ConfigError::InvalidPrincipal`]。 pub fn new( principal_type: impl Into, principal_id: impl Into, @@ -52,27 +52,27 @@ impl OAuthPrincipal { }) } - /// Returns the official principal type value. + /// 返回官方 principal 类型值。 #[must_use] pub fn principal_type(&self) -> &str { &self.principal_type } - /// Returns the official principal identifier. + /// 返回官方 principal 标识。 #[must_use] pub fn principal_id(&self) -> &str { &self.principal_id } } -/// Input for one refresh-token exchange. +/// 单次 refresh token 交换的输入。 #[derive(Clone)] pub struct RefreshTokenGrant { refresh_token: SecretValue, } impl RefreshTokenGrant { - /// Creates a refresh grant for an existing verified credential. + /// 为已验证的现有凭据创建 refresh grant。 #[must_use] pub fn new(refresh_token: SecretValue) -> Self { Self { refresh_token } @@ -92,7 +92,7 @@ impl fmt::Debug for RefreshTokenGrant { } } -/// Initial token set that crossed the mandatory verification boundary. +/// 已通过强制验证边界的初始 token set。 #[derive(Clone)] pub struct VerifiedTokenSet { access_token: SecretValue, @@ -119,13 +119,13 @@ impl VerifiedTokenSet { } } - /// Returns the verified access token. + /// 返回已验证的 access token。 #[must_use] pub fn access_token(&self) -> &SecretValue { &self.access_token } - /// Returns the optional refresh token. + /// 返回可选的 refresh token。 #[must_use] pub fn refresh_token(&self) -> Option<&SecretValue> { self.refresh_token.as_ref() @@ -143,13 +143,13 @@ impl VerifiedTokenSet { &self.scope } - /// Returns the server-provided lifetime. + /// 返回服务端下发的有效期。 #[must_use] pub const fn expires_in(&self) -> Option { self.expires_in } - /// Returns trusted identity verification evidence. + /// 返回可信身份验证证据。 #[must_use] pub const fn evidence(&self) -> &VerificationEvidence { &self.evidence @@ -173,8 +173,8 @@ impl fmt::Debug for VerifiedTokenSet { } } -/// Result of refreshing an already verified credential. An omitted refresh -/// token means the caller must retain the existing one under revision CAS. +/// 刷新已验证凭据的结果。未返回 refresh token 时,调用方须在 revision CAS 下 +/// 保留原有 refresh token。 #[derive(Clone)] pub struct RefreshedTokenSet { access_token: SecretValue, @@ -183,19 +183,19 @@ pub struct RefreshedTokenSet { } impl RefreshedTokenSet { - /// Returns the replacement access token. + /// 返回替换后的 access token。 #[must_use] pub fn access_token(&self) -> &SecretValue { &self.access_token } - /// Returns a rotated refresh token when the server supplied one. + /// 服务端下发轮换 refresh token 时返回它。 #[must_use] pub fn rotated_refresh_token(&self) -> Option<&SecretValue> { self.rotated_refresh_token.as_ref() } - /// Returns the replacement access-token lifetime. + /// 返回替换后 access token 的有效期。 #[must_use] pub const fn expires_in(&self) -> Option { self.expires_in diff --git a/backend/crates/providers/xai/src/credential/verification.rs b/backend/crates/providers/xai/src/credential/verification.rs index e30faf8a3..a941ccab4 100644 --- a/backend/crates/providers/xai/src/credential/verification.rs +++ b/backend/crates/providers/xai/src/credential/verification.rs @@ -7,10 +7,10 @@ use url::Url; use crate::{SecretValue, VerificationFailure}; -/// OAuth flow whose initial access token is being verified. +/// 正在验证首个 access token 的 OAuth 流程。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum VerificationFlow { - /// Authorization Code + PKCE with a mandatory nonce-bound ID token. + /// Authorization Code + PKCE;必须携带与 nonce 绑定的 ID token。 AuthorizationCode, /// 已有 token 的导入;必须通过官方 user-info 验证当前 access token。 CredentialImport, @@ -18,17 +18,17 @@ pub enum VerificationFlow { CredentialImportRefreshed, } -/// Trusted verification mechanism reported by the injected verifier. +/// 注入的校验器报告的可信验证机制。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum VerificationMethod { - /// Full JWT/JWKS validation including issuer, audience, expiry, and nonce. + /// 完整 JWT/JWKS 校验,含 issuer、audience、过期时间与 nonce。 IdToken, - /// Authoritative official user-info lookup using the access token. + /// 用 access token 查询官方权威 user-info。 UserInfo, } -/// Evidence produced by a trusted verifier. Identity is redacted from debug -/// output and is not derived by this crate through unverified JWT decoding. +/// 可信校验器产出的验证证据。身份在 debug 输出中脱敏,且本 crate 不会通过 +/// 未经验证的 JWT 解码推导身份。 #[derive(Clone)] pub struct VerificationEvidence { method: VerificationMethod, @@ -36,7 +36,7 @@ pub struct VerificationEvidence { } impl VerificationEvidence { - /// Creates evidence after full ID-token verification. + /// 完整 ID token 校验通过后创建证据。 #[must_use] pub fn id_token(subject: String) -> Self { Self { @@ -45,7 +45,7 @@ impl VerificationEvidence { } } - /// Creates evidence after an authoritative official user-info lookup. + /// 官方权威 user-info 查询通过后创建证据。 #[must_use] pub fn user_info(subject: String) -> Self { Self { @@ -54,13 +54,13 @@ impl VerificationEvidence { } } - /// Returns the verification method. + /// 返回验证机制。 #[must_use] pub const fn method(&self) -> VerificationMethod { self.method } - /// Exposes the verified subject at the credential construction boundary. + /// 在凭据构造边界暴露已验证的 subject。 #[must_use] pub fn subject(&self) -> &str { self.subject.expose() @@ -77,7 +77,7 @@ impl fmt::Debug for VerificationEvidence { } } -/// Immutable trust context supplied to a token verifier. +/// 传给 token 校验器的不可变信任上下文。 #[derive(Debug, Clone, Copy)] pub struct TokenVerificationContext<'a> { flow: VerificationFlow, @@ -110,51 +110,51 @@ impl<'a> TokenVerificationContext<'a> { } } - /// Returns the flow being verified. + /// 返回正在验证的流程。 #[must_use] pub const fn flow(&self) -> VerificationFlow { self.flow } - /// Returns the exact expected issuer. + /// 返回精确匹配的预期 issuer。 #[must_use] pub fn issuer(&self) -> &Url { self.issuer } - /// Returns the exact expected audience/client identifier. + /// 返回精确匹配的预期 audience/client 标识。 #[must_use] pub const fn client_id(&self) -> &str { self.client_id } - /// Returns the same-origin JWKS URL from validated discovery. + /// 返回已校验发现文档中的同源 JWKS URL。 #[must_use] pub fn jwks_uri(&self) -> &Url { self.jwks_uri } - /// Returns the same-origin authoritative user-info URL from discovery. + /// 返回发现文档中的同源权威 user-info URL。 #[must_use] pub fn userinfo_endpoint(&self) -> &Url { self.userinfo_endpoint } - /// Returns discovery-advertised algorithms. Implementations must intersect - /// them with a local cryptographic allowlist and reject `none`. + /// 返回发现文档声明的算法。实现必须与本地密码学 allowlist 取交集,并拒绝 + /// `none`。 #[must_use] pub const fn signing_algorithms(&self) -> &[String] { self.signing_algorithms } - /// Returns the expected nonce for authorization-code flows. + /// 返回 Authorization Code 流程的预期 nonce。 #[must_use] pub const fn expected_nonce(&self) -> Option<&SecretValue> { self.expected_nonce } } -/// Borrowed token material available only to the trusted verification port. +/// 仅向可信校验端口开放的借用 token 材料。 pub struct TokenCandidate<'a> { access_token: &'a SecretValue, id_token: Option<&'a SecretValue>, @@ -174,19 +174,19 @@ impl<'a> TokenCandidate<'a> { } } - /// Returns the access token for authoritative user-info verification. + /// 返回用于权威 user-info 验证的 access token。 #[must_use] pub const fn access_token(&self) -> &SecretValue { self.access_token } - /// Returns the ID token for full JWT/JWKS validation, when provided. + /// 返回用于完整 JWT/JWKS 校验的 ID token(若存在)。 #[must_use] pub const fn id_token(&self) -> Option<&SecretValue> { self.id_token } - /// Returns the server-provided lifetime. + /// 返回服务端给出的有效期。 #[must_use] pub const fn expires_in(&self) -> Option { self.expires_in @@ -204,14 +204,14 @@ impl fmt::Debug for TokenCandidate<'_> { } } -/// Future returned by a token verification port. +/// token 校验端口返回的 future。 pub type VerificationFuture<'a> = Pin> + Send + 'a>>; -/// Trust boundary for full JWT/JWKS or authoritative user-info validation. +/// 完整 JWT/JWKS 或权威 user-info 校验的信任边界。 pub trait TokenVerifier: Send + Sync { - /// Verifies an initial token set. Implementations must never base64-decode - /// JWT claims without signature and claim validation. + /// 验证初始 token 集合。实现不得在未做签名与 claim 校验的情况下 base64 解码 + /// JWT claims。 fn verify<'a>( &'a self, context: TokenVerificationContext<'a>, @@ -219,7 +219,7 @@ pub trait TokenVerifier: Send + Sync { ) -> VerificationFuture<'a>; } -/// Default verifier that makes incomplete wiring fail closed. +/// 默认校验器,未完成接线时 fail closed。 #[derive(Debug, Default)] pub struct FailClosedTokenVerifier; diff --git a/backend/crates/providers/xai/src/lib.rs b/backend/crates/providers/xai/src/lib.rs index d3e5cb753..110da7cc9 100644 --- a/backend/crates/providers/xai/src/lib.rs +++ b/backend/crates/providers/xai/src/lib.rs @@ -1,4 +1,4 @@ -//! Official Grok Build OAuth Provider boundary. +//! 官方 Grok Build OAuth Provider 边界。 mod admin; pub mod config; diff --git a/backend/crates/providers/xai/src/provider.rs b/backend/crates/providers/xai/src/provider.rs index 0f9208a62..a09266839 100644 --- a/backend/crates/providers/xai/src/provider.rs +++ b/backend/crates/providers/xai/src/provider.rs @@ -1,4 +1,4 @@ -//! `gateway-core` Provider adapter for official Grok Build sessions. +//! 官方 Grok Build 会话的 `gateway-core` Provider adapter。 use std::collections::{BTreeMap, BTreeSet}; use std::sync::{Arc, Mutex}; @@ -70,12 +70,10 @@ const MIN_REASONING_CIPHERTEXT_ENTROPY: f64 = 0.85; const REASONING_DECODE_FAILED_CODE: &str = "reasoning_decode_failed"; const RESPONSE_NOT_FOUND_CODE: &str = "not_found"; -/// Official Grok Build provider with injected session selection and HTTP SSE -/// transport ports. +/// 官方 Grok Build Provider;会话选择与 HTTP SSE transport 均由外部注入。 /// -/// Each call selects exactly one OAuth session and prepares exactly one visible -/// upstream POST. Retries, credential rotation, endpoint fallback, and public -/// xAI API-key inference are deliberately outside this adapter. +/// 每次调用只选择一个 OAuth 会话,只准备一次可见的上游 POST。重试、凭据轮换、 +/// endpoint fallback 以及公开 xAI API key 推理都不在该 adapter 内。 pub struct GrokBuildProvider { selector: Arc, transport: Arc, @@ -88,7 +86,7 @@ pub struct GrokBuildProvider { } impl GrokBuildProvider { - /// Creates a provider over explicit session and transport boundaries. + /// 在显式的会话与 transport 边界上创建 Provider。 pub fn new( selector: Arc, transport: Arc, @@ -380,9 +378,8 @@ fn tool_support(evidence: GrokCatalogCapabilityEvidence) -> SupportLevel { match evidence { GrokCatalogCapabilityEvidence::DeclaredNative => SupportLevel::Native, GrokCatalogCapabilityEvidence::DeclaredUnsupported => SupportLevel::Unsupported, - // Grok Build's Responses tool protocol remains available when the - // optional catalog field is omitted; the request adapter normalizes - // the client-only tool shapes before sending. + // catalog 省略该可选字段时,Grok Build 的 Responses 工具协议仍可用; + // 请求 adapter 会在发送前规范化仅客户端侧的工具结构。 GrokCatalogCapabilityEvidence::Unknown => SupportLevel::Emulated, } } diff --git a/backend/crates/providers/xai/src/transport/canonical.rs b/backend/crates/providers/xai/src/transport/canonical.rs index 466b7a1da..185ff9e96 100644 --- a/backend/crates/providers/xai/src/transport/canonical.rs +++ b/backend/crates/providers/xai/src/transport/canonical.rs @@ -1,4 +1,4 @@ -//! Official Grok Responses SSE to gateway canonical events. +//! 官方 Grok Responses SSE 到网关 canonical 事件的转换。 use std::collections::{BTreeMap, BTreeSet}; @@ -128,7 +128,7 @@ fn usd_price_per_million(per_token_ticks: u128) -> Option { usd_money(per_token_ticks.checked_mul(1_000_000)?) } -/// Incremental decoder for one official Grok Responses attempt. +/// 单次官方 Grok Responses 尝试的增量解码器。 /// /// 每个上游 event 同时保留 OpenAI wire,并在可识别时附加 canonical facts。 pub struct GrokCanonicalDecoder { @@ -158,8 +158,8 @@ impl GrokCanonicalDecoder { } } - /// Creates a decoder that restores request-scoped tool aliases before the - /// canonical and wire projections observe each upstream event. + /// 创建在 canonical 与 wire 投影处理每个上游 event 前先还原请求级 tool 别名的 + /// 解码器。 #[must_use] pub fn for_request(fallback_model: impl Into, request: &GrokResponsesRequest) -> Self { Self { diff --git a/backend/crates/providers/xai/src/transport/catalog.rs b/backend/crates/providers/xai/src/transport/catalog.rs index 7666532ff..e9d3b12f9 100644 --- a/backend/crates/providers/xai/src/transport/catalog.rs +++ b/backend/crates/providers/xai/src/transport/catalog.rs @@ -356,7 +356,7 @@ impl GrokBillingTransportError { } } -/// Billing transport future。 +/// 计费 transport 的 future。 pub type GrokBillingTransportFuture<'a> = Pin< Box< dyn Future> diff --git a/backend/crates/providers/xai/src/transport/headers.rs b/backend/crates/providers/xai/src/transport/headers.rs index 2b70362b3..9732c41b1 100644 --- a/backend/crates/providers/xai/src/transport/headers.rs +++ b/backend/crates/providers/xai/src/transport/headers.rs @@ -35,17 +35,17 @@ impl fmt::Debug for GrokClientIdentity { } } -/// Public or sensitive official Grok request header value. +/// 官方 Grok 请求头的公开或敏感取值。 #[derive(Clone)] pub enum GrokHeaderValue { - /// Non-sensitive protocol metadata. + /// 非敏感的协议元数据。 Public(String), - /// OAuth, identity, or session value that must be redacted. + /// 必须脱敏的 OAuth、身份或会话值。 Sensitive(SecretValue), } impl GrokHeaderValue { - /// Exposes a value only at the injected HTTP transport boundary. + /// 仅在注入的 HTTP transport 边界处暴露取值。 #[must_use] pub fn expose(&self) -> &str { match self { @@ -64,7 +64,7 @@ impl fmt::Debug for GrokHeaderValue { } } -/// One official Grok CLI proxy request header. +/// 一个官方 Grok CLI 代理请求头。 #[derive(Debug, Clone)] pub struct GrokHeader { name: &'static str, @@ -72,13 +72,13 @@ pub struct GrokHeader { } impl GrokHeader { - /// Returns the static header name. + /// 返回静态 header 名。 #[must_use] pub const fn name(&self) -> &'static str { self.name } - /// Returns the typed header value. + /// 返回类型化的 header 值。 #[must_use] pub const fn value(&self) -> &GrokHeaderValue { &self.value diff --git a/backend/crates/providers/xai/src/transport/mod.rs b/backend/crates/providers/xai/src/transport/mod.rs index a2a3608d0..e56a96731 100644 --- a/backend/crates/providers/xai/src/transport/mod.rs +++ b/backend/crates/providers/xai/src/transport/mod.rs @@ -1,4 +1,4 @@ -//! Grok Build CLI Responses provider boundary. +//! Grok Build CLI Responses provider 边界。 pub(crate) mod canonical; pub(crate) mod catalog; diff --git a/backend/crates/providers/xai/src/transport/network.rs b/backend/crates/providers/xai/src/transport/network.rs index ff5fc0455..a91cf2b4d 100644 --- a/backend/crates/providers/xai/src/transport/network.rs +++ b/backend/crates/providers/xai/src/transport/network.rs @@ -159,7 +159,7 @@ impl GrokDnsResolutionPolicy { #[error("Grok official DNS resolution was rejected")] pub struct GrokDnsResolutionError; -/// HTTP client construction and endpoint validation are one injected security boundary. +/// HTTP client 构造与端点校验合为一个可注入的安全边界。 pub trait GrokEndpointPolicy: fmt::Debug + Send + Sync { fn build_oauth_client( &self, diff --git a/backend/crates/providers/xai/src/transport/profile.rs b/backend/crates/providers/xai/src/transport/profile.rs index 5ca196608..a299ac50e 100644 --- a/backend/crates/providers/xai/src/transport/profile.rs +++ b/backend/crates/providers/xai/src/transport/profile.rs @@ -1,4 +1,4 @@ -//! Grok CLI runtime wire profile. +//! Grok CLI 运行时 wire profile。 use std::{ sync::{Arc, RwLock}, diff --git a/backend/crates/providers/xai/src/transport/request.rs b/backend/crates/providers/xai/src/transport/request.rs index afe782398..f966575cc 100644 --- a/backend/crates/providers/xai/src/transport/request.rs +++ b/backend/crates/providers/xai/src/transport/request.rs @@ -270,17 +270,16 @@ impl fmt::Debug for GrokResponsesRequest { } } -/// Generate-to-Responses encoding error that never retains option or prompt -/// values. +/// Generate 到 Responses 的编码错误,不保留 option 与 prompt 值。 #[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)] pub enum GrokRequestEncodeError { /// 数据面只接受 OpenAI adapter 保留的原始 Responses object。 #[error("Grok Build request is missing its OpenAI protocol payload")] InvalidProtocolPayload, - /// JSON serialization unexpectedly failed. + /// JSON 序列化意外失败。 #[error("Grok Build request serialization failed")] Serialization, - /// Responses compatibility fields could not be normalized safely. + /// Responses 兼容字段无法安全归一化。 #[error("Grok Build request normalization failed")] InvalidRequestNormalization, /// 请求中的具体字段无法安全转换为 Grok Build 接受的形态。 diff --git a/backend/crates/providers/xai/src/transport/session.rs b/backend/crates/providers/xai/src/transport/session.rs index 73fe043f3..1431bd13b 100644 --- a/backend/crates/providers/xai/src/transport/session.rs +++ b/backend/crates/providers/xai/src/transport/session.rs @@ -13,17 +13,16 @@ use sha2::{Digest as _, Sha256}; use crate::SecretValue; -/// Opaque, pseudonymous egress/session key understood by the injected -/// inference transport. +/// 注入的推理 transport 可识别的不透明假名化 egress/session 键。 #[derive(Clone, PartialEq, Eq, Hash)] pub struct GrokSessionBinding(String); impl GrokSessionBinding { - /// Creates a bounded, non-secret binding reference. + /// 创建有界的非敏感绑定引用。 /// /// # Errors /// - /// Rejects empty, oversized, control-character, or reserved values. + /// 值为空、超长、含控制字符或使用保留前缀时返回错误。 pub fn new(value: impl Into) -> Result { let value = value.into(); if value.is_empty() @@ -36,7 +35,7 @@ impl GrokSessionBinding { Ok(Self(value)) } - /// Returns the pseudonymous transport lookup key. + /// 返回假名化的 transport 查找键。 #[must_use] pub fn as_str(&self) -> &str { &self.0 @@ -75,12 +74,12 @@ impl fmt::Debug for GrokSessionAffinityKey { } } -/// Selector-owned guard for credential, capacity, and egress affinity. +/// 由 selector 持有的凭据、容量与 egress 亲和守卫。 pub trait GrokSessionLeaseGuard: Send + Sync + 'static {} impl GrokSessionLeaseGuard for T where T: Send + Sync + 'static {} -/// One selected OAuth session and its owned live lease. +/// 一个选中的 OAuth 会话及其持有的活跃 lease。 pub struct SelectedGrokSession { account_id: ProviderAccountId, credential_revision: CredentialRevision, @@ -92,11 +91,11 @@ pub struct SelectedGrokSession { } impl SelectedGrokSession { - /// Constructs a selected session from Provider-owned plaintext OAuth material. + /// 从 Provider 持有的明文 OAuth 材料构造选中会话。 /// /// # Errors /// - /// Rejects a credential-less snapshot or malformed auth/header values. + /// 快照缺少凭据,或 auth/header 值格式非法时返回错误。 pub fn new( account_id: ProviderAccountId, credential_revision: CredentialRevision, @@ -125,19 +124,19 @@ impl SelectedGrokSession { }) } - /// Returns the selected account ID. + /// 返回选中的账号 ID。 #[must_use] pub const fn account_id(&self) -> &ProviderAccountId { &self.account_id } - /// Returns the selector-frozen credential revision. + /// 返回 selector 冻结的凭据 revision。 #[must_use] pub const fn credential_revision(&self) -> CredentialRevision { self.credential_revision } - /// Returns metadata recorded by Core for this upstream call. + /// 返回 Core 为本次上游调用记录的元数据。 #[must_use] pub fn resource(&self) -> ProviderResource { ProviderResource::Account { @@ -146,25 +145,25 @@ impl SelectedGrokSession { } } - /// Returns the OAuth access token for explicit header construction. + /// 返回用于显式构造 header 的 OAuth access token。 #[must_use] pub const fn access_token(&self) -> &SecretValue { &self.access_token } - /// Returns the verified user ID for official proxy headers. + /// 返回用于官方代理 header 的已验证 user ID。 #[must_use] pub const fn user_id(&self) -> &SecretValue { &self.user_id } - /// Returns the optional verified email for official proxy headers. + /// 返回用于官方代理 header 的可选已验证 email。 #[must_use] pub const fn email(&self) -> Option<&SecretValue> { self.email.as_ref() } - /// Returns the pseudonymous egress/session transport binding. + /// 返回假名化的 egress/session transport 绑定。 #[must_use] pub const fn binding(&self) -> &GrokSessionBinding { &self.binding @@ -186,7 +185,7 @@ impl fmt::Debug for SelectedGrokSession { } } -/// Input to one selector call. It owns a frozen, secret-free attempt view. +/// 单次 selector 调用的入参,持有冻结且不含密钥的尝试视图。 #[derive(Debug, Clone)] pub struct GrokSessionSelection { upstream_model: UpstreamModelId, @@ -198,7 +197,7 @@ pub struct GrokSessionSelection { } impl GrokSessionSelection { - /// Creates the immutable selection request. + /// 创建不可变的选择请求。 #[must_use] pub fn new( upstream_model: UpstreamModelId, @@ -224,25 +223,25 @@ impl GrokSessionSelection { self } - /// Returns the frozen upstream model. + /// 返回冻结的上游模型。 #[must_use] pub const fn upstream_model(&self) -> &UpstreamModelId { &self.upstream_model } - /// Returns accounts already attempted by the coordinator. + /// 返回协调方已尝试过的账号。 #[must_use] pub const fn excluded_accounts(&self) -> &BTreeSet { &self.excluded_accounts } - /// Returns the sole account permitted for this call, when constrained by Core. + /// 返回 Core 约束下本次调用唯一允许的账号。 #[must_use] pub const fn required_account(&self) -> Option<&ProviderAccountId> { self.required_account.as_ref() } - /// Returns the frozen global account scheduling policy. + /// 返回冻结的全局账号调度策略。 #[must_use] pub const fn account_selection_policy(&self) -> AccountSelectionPolicy { self.account_selection_policy @@ -254,44 +253,44 @@ impl GrokSessionSelection { self.affinity.as_ref() } - /// Returns the absolute deadline that bounds the scheduling lease. + /// 返回限定调度租约的绝对截止时间。 #[must_use] pub const fn deadline(&self) -> SystemTime { self.deadline } } -/// Future returned by a Grok session selector. +/// Grok session selector 返回的 future。 pub type GrokSessionSelectorFuture<'a> = Pin< Box> + Send + 'a>, >; -/// Credential-scoped upstream failure safe to persist as availability feedback. +/// 凭据维度的上游失败,可安全落库为可用性反馈。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GrokCredentialFailure { - /// The selected OAuth token was rejected. + /// 选中的 OAuth token 被拒绝。 Unauthorized, - /// The selected OAuth account was rate limited. + /// 选中的 OAuth 账号被限流。 RateLimited { - /// Already parsed and redacted delay; no raw upstream header is retained. + /// 已解析并脱敏的延迟;不保留上游原始 header。 retry_after: Option, }, - /// The selected OAuth account exhausted its quota. + /// 选中的 OAuth 账号配额耗尽。 QuotaExhausted, - /// A successful SSE response ended before a terminal Responses event. + /// 成功的 SSE 响应在终止 Responses 事件前结束。 StreamInterrupted, } -/// Future returned after one best-effort credential feedback write. +/// 一次 best-effort 凭据反馈写入返回的 future。 pub type GrokCredentialFeedbackFuture<'a> = Pin + Send + 'a>>; -/// Runtime port that selects exactly one eligible OAuth session and acquires -/// all credential/capacity/egress leases required for the stream lifetime. +/// 运行时端口:选出恰好一个可用 OAuth 会话,并获取流生命周期所需的全部 +/// 凭据、容量与出口租约。 pub trait GrokSessionSelector: Send + Sync { - /// Performs one selection without internal provider fallback. + /// 执行一次选择,不做 Provider 内部回退。 fn select(&self, request: GrokSessionSelection) -> GrokSessionSelectorFuture<'_>; - /// Persists one classified failure without retrying or replacing the error. + /// 持久化一条已分类的失败,不重试也不替换原错误。 fn record_failure<'a>( &'a self, session: &'a SelectedGrokSession, @@ -299,39 +298,39 @@ pub trait GrokSessionSelector: Send + Sync { ) -> GrokCredentialFeedbackFuture<'a>; } -/// Secret-free selector failure. +/// 不含密钥的选择器失败。 #[derive(Debug, thiserror::Error, PartialEq, Eq)] pub enum GrokSessionSelectorError { - /// No session satisfies model, state, and exclusion constraints. + /// 没有会话同时满足模型、状态与排除约束。 #[error("no eligible Grok Build session is available")] NoEligibleSession, - /// All eligible sessions are currently leased or rate-spaced. + /// 所有可用会话当前均被租出或处于限速间隔。 #[error("Grok Build session capacity is unavailable")] CapacityUnavailable { - /// Optional selector-derived delay. + /// 选择器推导出的可选延迟。 retry_after: Option, }, - /// Every eligible session is inside its runtime cooldown window. + /// 每个可用会话都处于运行时冷却窗口内。 #[error("Grok Build account is cooling down")] AccountCoolingDown { - /// Remaining cooldown of the earliest recovering session. + /// 最早恢复的会话剩余冷却时长。 retry_after: Option, }, - /// Session metadata or Provider-owned plaintext secret is invalid. + /// 会话元数据或 Provider 持有的明文密钥非法。 #[error("Grok Build session data is invalid")] InvalidSession, - /// Selector backing service is unavailable. + /// 选择器依赖的后端服务不可用。 #[error("Grok Build session selector is unavailable")] Unavailable, } -/// Selected-session construction failure. +/// 构造选中会话时的失败。 #[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)] pub enum GrokSessionDataError { - /// Access token or verified identity header is malformed. + /// access token 或已验证身份头格式非法。 #[error("selected session contains an invalid secret value")] InvalidSecretValue, - /// Egress/session binding is invalid. + /// 出口/会话绑定非法。 #[error("selected session binding is invalid")] InvalidBinding, } diff --git a/backend/crates/providers/xai/src/transport/transport.rs b/backend/crates/providers/xai/src/transport/transport.rs index b4be4ce7c..4d044563b 100644 --- a/backend/crates/providers/xai/src/transport/transport.rs +++ b/backend/crates/providers/xai/src/transport/transport.rs @@ -12,7 +12,7 @@ use zeroize::Zeroizing; use super::{GrokHeader, GrokSessionBinding}; -/// Owned request handed to the injected HTTP SSE transport. +/// 交给注入的 HTTP SSE transport 的自持有请求。 pub struct GrokInferenceRequest { endpoint: Url, headers: Vec, @@ -35,25 +35,25 @@ impl GrokInferenceRequest { } } - /// Returns the strict official Responses endpoint. + /// 返回严格限定的官方 Responses 端点。 #[must_use] pub const fn endpoint(&self) -> &Url { &self.endpoint } - /// Returns typed headers; adapters must not log sensitive values. + /// 返回类型化 header;适配层不得记录敏感值。 #[must_use] pub fn headers(&self) -> &[GrokHeader] { &self.headers } - /// Returns the serialized typed Responses body. + /// 返回序列化后的类型化 Responses body。 #[must_use] pub fn body(&self) -> &[u8] { &self.body } - /// Returns the pseudonymous proxy/egress lookup binding. + /// 返回假名化的 proxy/egress 查找绑定。 #[must_use] pub const fn binding(&self) -> &GrokSessionBinding { &self.binding @@ -75,16 +75,16 @@ impl fmt::Debug for GrokInferenceRequest { } } -/// Stream of raw SSE byte chunks returned after the POST is accepted. +/// POST 被接受后返回的原始 SSE 字节块流。 pub type GrokInferenceChunkStream = Pin> + Send + 'static>>; -/// Whether the account-isolated inference client was already cached. +/// 账号隔离的推理 client 是否已在缓存中。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GrokInferenceClientCacheStatus { - /// The binding reused its existing account-isolated client. + /// 绑定复用了已有的账号隔离 client。 Hit, - /// The binding was absent when the request first checked the cache. + /// 请求首次查缓存时该绑定不存在。 Miss, } @@ -98,12 +98,12 @@ impl GrokInferenceClientCacheStatus { } } -/// Resolver that supplied the addresses used by the request. +/// 提供本次请求所用地址的解析器。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GrokInferenceDnsSource { - /// The system resolver returned an entirely public address set. + /// 系统解析器返回了完全公网的地址集合。 System, - /// The system result was unusable and the trusted DoH fallback supplied addresses. + /// 系统结果不可用,由受信 DoH 回退提供地址。 TrustedDoh, } @@ -117,7 +117,7 @@ impl GrokInferenceDnsSource { } } -/// DNS work observed while opening an upstream connection. +/// 建立上游连接期间观测到的 DNS 工作量。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct GrokInferenceDnsObservation { source: GrokInferenceDnsSource, @@ -144,7 +144,7 @@ impl GrokInferenceDnsObservation { } } -/// Low-cardinality transport timings and pool facts for one inference request. +/// 单次推理请求的低基数 transport 耗时与连接池事实。 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub struct GrokInferenceTransportMetrics { headers_ms: Option, @@ -190,8 +190,8 @@ impl GrokInferenceTransportMetrics { } } -/// Accepted inference response. Non-success HTTP responses must be returned as -/// [`GrokInferenceTransportError`] instead. +/// 已被接受的推理响应。非成功 HTTP 响应必须改为返回 +/// [`GrokInferenceTransportError`]。 pub struct GrokInferenceResponse { body: GrokInferenceChunkStream, http_version: UpstreamHttpVersion, @@ -201,7 +201,7 @@ pub struct GrokInferenceResponse { } impl GrokInferenceResponse { - /// Wraps one accepted SSE response body. + /// 包装一个已被接受的 SSE 响应体。 #[must_use] pub fn new( body: GrokInferenceChunkStream, @@ -265,34 +265,34 @@ impl fmt::Debug for GrokInferenceResponse { } } -/// Secret-free transport failure category. +/// 不含密钥的 transport 失败分类。 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GrokInferenceTransportErrorKind { - /// Canonical request semantics were rejected by the official proxy. + /// 官方代理拒绝了 canonical 请求语义。 InvalidRequest, - /// The official proxy does not support a requested capability. + /// 官方代理不支持请求的某项能力。 Unsupported, - /// Access token was rejected. + /// access token 被拒绝。 Unauthorized, - /// Session lacks model or feature entitlement. + /// 会话缺少模型或特性授权。 PermissionDenied, - /// Per-session or provider rate limit. + /// 会话级或 Provider 级限流。 RateLimited, - /// Account credits or quota are exhausted. + /// 账号额度或配额耗尽。 QuotaExhausted, - /// Deadline or transport timeout. + /// 截止时间或 transport 超时。 Timeout, - /// Network/TLS/connection failure. + /// 网络/TLS/连接失败。 Transport, - /// HTTP/SSE response violates the expected contract. + /// HTTP/SSE 响应违反预期契约。 Protocol, - /// Official CLI proxy is unavailable. + /// 官方 CLI 代理不可用。 Unavailable, - /// Caller cancellation observed by the transport. + /// transport 观测到调用方取消。 Cancelled, } -/// Classified transport error that never contains an upstream response body. +/// 已分类的 transport 错误,绝不包含上游响应体。 #[derive(Clone, PartialEq, Eq)] pub struct GrokInferenceTransportError { kind: GrokInferenceTransportErrorKind, @@ -308,7 +308,7 @@ pub struct GrokInferenceTransportError { } impl GrokInferenceTransportError { - /// Creates a classified error with the transport's conservative send state. + /// 以 transport 保守判定的发送状态创建已分类错误。 #[must_use] pub const fn new(kind: GrokInferenceTransportErrorKind, send_state: UpstreamSendState) -> Self { Self { @@ -329,7 +329,7 @@ impl GrokInferenceTransportError { } } - /// Attaches a valid HTTP status. + /// 附着合法的 HTTP 状态码。 #[must_use] pub fn with_status(mut self, status: u16) -> Self { if (100..=599).contains(&status) { @@ -338,7 +338,7 @@ impl GrokInferenceTransportError { self } - /// Attaches a bounded retry delay parsed by the transport. + /// 附着 transport 解析出的有界重试延迟。 #[must_use] pub const fn with_retry_after(mut self, retry_after: Duration) -> Self { self.retry_after = Some(retry_after); @@ -378,32 +378,32 @@ impl GrokInferenceTransportError { self } - /// Discards a possibly sensitive upstream body while retaining that fact. + /// 丢弃可能敏感的上游响应体,仅保留「已丢弃」这一事实。 #[must_use] pub fn redact_sensitive_context(mut self, _value: impl AsRef) -> Self { self.sensitive_context_redacted = true; self } - /// Returns the stable transport category. + /// 返回稳定的 transport 分类。 #[must_use] pub const fn kind(&self) -> GrokInferenceTransportErrorKind { self.kind } - /// Returns the conservative payload send state. + /// 返回保守判定的 payload 发送状态。 #[must_use] pub const fn send_state(&self) -> UpstreamSendState { self.send_state } - /// Returns the sanitized HTTP status. + /// 返回清洗后的 HTTP 状态码。 #[must_use] pub const fn status(&self) -> Option { self.status } - /// Returns the optional retry delay. + /// 返回可选的重试延迟。 #[must_use] pub const fn retry_after(&self) -> Option { self.retry_after @@ -434,7 +434,7 @@ impl GrokInferenceTransportError { self.credential_recovery_required } - /// Reports whether a sensitive body was discarded. + /// 报告是否丢弃过敏感响应体。 #[must_use] pub const fn sensitive_context_was_redacted(&self) -> bool { self.sensitive_context_redacted @@ -477,17 +477,16 @@ impl fmt::Display for GrokInferenceTransportError { impl std::error::Error for GrokInferenceTransportError {} -/// Future returned by the inference transport. +/// 推理 transport 返回的 future。 pub type GrokInferenceTransportFuture<'a> = Pin< Box< dyn Future> + Send + 'a, >, >; -/// Runtime HTTP SSE port. Implementations must issue exactly one POST, use the -/// supplied session binding for egress affinity, and never retry, switch -/// credentials, or fall back to another endpoint. +/// 运行时 HTTP SSE 端口。实现必须只发出一次 POST,用传入的 session binding +/// 维持 egress 亲和,且不得重试、切换凭据或回退到其他端点。 pub trait GrokInferenceTransport: Send + Sync { - /// Starts one official CLI proxy request. + /// 发起一次官方 CLI 代理请求。 fn execute(&self, request: GrokInferenceRequest) -> GrokInferenceTransportFuture<'_>; } diff --git a/backend/crates/providers/xai/tests/credential/client.rs b/backend/crates/providers/xai/tests/credential/client.rs index d4c4fe3af..32aef2a7e 100644 --- a/backend/crates/providers/xai/tests/credential/client.rs +++ b/backend/crates/providers/xai/tests/credential/client.rs @@ -1,4 +1,4 @@ -//! External fixture-driven contracts for the transport and verification ports. +//! transport 与验证端口的外置 fixture 驱动契约。 use std::collections::VecDeque; use std::future::ready; diff --git a/backend/crates/providers/xai/tests/credential/oidc_verifier.rs b/backend/crates/providers/xai/tests/credential/oidc_verifier.rs index a462fd1dc..02d425ea6 100644 --- a/backend/crates/providers/xai/tests/credential/oidc_verifier.rs +++ b/backend/crates/providers/xai/tests/credential/oidc_verifier.rs @@ -1,4 +1,4 @@ -//! External OIDC verifier contracts. +//! 外置的 OIDC verifier 契约。 use std::time::Duration; diff --git a/backend/crates/providers/xai/tests/transport/network.rs b/backend/crates/providers/xai/tests/transport/network.rs index c3d0e70f5..a0cabbc53 100644 --- a/backend/crates/providers/xai/tests/transport/network.rs +++ b/backend/crates/providers/xai/tests/transport/network.rs @@ -1,4 +1,4 @@ -//! External reqwest network policy contracts. +//! 外置的 reqwest 网络策略契约。 use std::cell::Cell; use std::net::IpAddr;