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 <noreply@openai.com>
This commit is contained in:
Zyy
2026-07-27 13:13:44 +08:00
co-authored by Codex
parent 12c2b612de
commit 92090f28bf
34 changed files with 348 additions and 367 deletions
@@ -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,
@@ -1,4 +1,4 @@
//! Codex credential domain exports。
//! Codex credential 领域导出。
mod admin;
mod affinity;
@@ -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<Client, CustomCaError> {
}
// ---------------------------------------------------------------------------
// Error types
// 错误类型
// ---------------------------------------------------------------------------
/// Codex 上游 HTTP 客户端错误。
@@ -245,7 +245,7 @@ pub type CodexBackendSseStream =
Pin<Box<dyn Stream<Item = CodexClientResult<Bytes>> + 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<String>,
}
/// 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(
@@ -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};
@@ -60,7 +60,7 @@ pub struct CodexResponsesRequest {
pub responses_lite: Option<String>,
/// Memory consolidation 请求语义;HTTP 与 WebSocket opening 均使用 header。
pub memgen_request: Option<String>,
/// codex window id。
/// Codex window ID。
pub codex_window_id: Option<String>,
/// 父线程 ID。
pub parent_thread_id: Option<String>,
@@ -13,7 +13,7 @@ pub struct OpeningAuditSnapshot {
pub request_line: String,
/// 请求头顺序。
pub header_order: Vec<String>,
/// 红action后的请求头。
/// 脱敏后的请求头。
pub headers: Vec<OpeningAuditHeader>,
}
@@ -31,11 +31,11 @@ pub struct OpeningAuditHeader {
pub struct PayloadAuditSnapshot {
/// 按构造顺序记录的顶层字段。
pub top_level_keys: Vec<String>,
/// 红action后的 JSON payload。
/// 脱敏后的 JSON payload。
pub body: Value,
}
/// WebSocket audit artifact.
/// WebSocket 审计产物。
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct WebSocketAuditArtifact {
/// 实际选择的传输模式。
@@ -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<u64>,
@@ -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<String>,
@@ -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<Box<dyn Stream<Item = Result<Bytes, CodexWebSocketExchangeError>> + Send + 'static>>;
/// WebSocket live stream rate-limit header updates.
/// live 流中的限流头动态更新。
pub type CodexWebSocketRateLimitHeaderUpdates = Arc<Mutex<Vec<(String, String)>>>;
/// WebSocket live stream turn-state update.
/// live 流中的 turn state 动态更新。
pub type CodexWebSocketTurnStateUpdate = Arc<Mutex<Option<String>>>;
pub(super) fn reusable_websocket_metadata(
@@ -1,4 +1,4 @@
//! Codex HTTP Responses WebSocket transport。
//! Codex Responses WebSocket 传输。
mod audit;
mod breaker;
@@ -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,
@@ -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<SecretValue>,
state: Option<SecretValue>,
@@ -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<Self, CallbackRejection> {
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,
@@ -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<DiscoveryDocument, OAuthError> {
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,
@@ -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<Url>,
}
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<I, S>(uris: I) -> Result<Self, ConfigError>
where
I: IntoIterator<Item = S>,
@@ -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<AllowedRedirectUri, ConfigError> {
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<Self, ConfigError> {
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
@@ -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
@@ -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 {
@@ -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<String>) -> 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<String>) -> 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<Vec<u8>>,
}
impl OAuthHttpResponse {
/// Constructs a response from a status code and raw body.
/// 由状态码与原始响应体构造响应。
#[must_use]
pub fn new(status: u16, body: impl Into<Vec<u8>>) -> 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<Box<dyn Future<Output = Result<OAuthHttpResponse, TransportFailure>> + 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<'_>;
}
@@ -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
///
@@ -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<String>);
impl SecretValue {
/// Wraps an owned secret value.
/// 包装持有所有权的 secret 值。
#[must_use]
pub fn new(value: impl Into<String>) -> 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()
@@ -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<String>,
principal_id: impl Into<String>,
@@ -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<Duration> {
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<Duration> {
self.expires_in
@@ -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<Duration> {
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<Box<dyn Future<Output = Result<VerificationEvidence, VerificationFailure>> + 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;
+1 -1
View File
@@ -1,4 +1,4 @@
//! Official Grok Build OAuth Provider boundary.
//! 官方 Grok Build OAuth Provider 边界。
mod admin;
pub mod config;
+7 -10
View File
@@ -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<dyn GrokSessionSelector>,
transport: Arc<dyn GrokInferenceTransport>,
@@ -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<dyn GrokSessionSelector>,
transport: Arc<dyn GrokInferenceTransport>,
@@ -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,
}
}
@@ -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<Money> {
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<String>, request: &GrokResponsesRequest) -> Self {
Self {
@@ -356,7 +356,7 @@ impl GrokBillingTransportError {
}
}
/// Billing transport future。
/// 计费 transport 的 future。
pub type GrokBillingTransportFuture<'a> = Pin<
Box<
dyn Future<Output = Result<GrokBillingTransportResponse, GrokBillingTransportError>>
@@ -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
@@ -1,4 +1,4 @@
//! Grok Build CLI Responses provider boundary.
//! Grok Build CLI Responses provider 边界。
pub(crate) mod canonical;
pub(crate) mod catalog;
@@ -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,
@@ -1,4 +1,4 @@
//! Grok CLI runtime wire profile.
//! Grok CLI 运行时 wire profile。
use std::{
sync::{Arc, RwLock},
@@ -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 接受的形态。
@@ -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<String>) -> Result<Self, GrokSessionDataError> {
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<T> 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<ProviderAccountId> {
&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<dyn Future<Output = Result<SelectedGrokSession, GrokSessionSelectorError>> + 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<Duration>,
},
/// 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<Box<dyn Future<Output = ()> + 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<Duration>,
},
/// 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<Duration>,
},
/// 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,
}
@@ -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<GrokHeader>,
@@ -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<Box<dyn Stream<Item = Result<bytes::Bytes, GrokInferenceTransportError>> + 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<u64>,
@@ -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<str>) -> 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<u16> {
self.status
}
/// Returns the optional retry delay.
/// 返回可选的重试延迟。
#[must_use]
pub const fn retry_after(&self) -> Option<Duration> {
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<Output = Result<GrokInferenceResponse, GrokInferenceTransportError>> + 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<'_>;
}
@@ -1,4 +1,4 @@
//! External fixture-driven contracts for the transport and verification ports.
//! transport 与验证端口的外置 fixture 驱动契约。
use std::collections::VecDeque;
use std::future::ready;
@@ -1,4 +1,4 @@
//! External OIDC verifier contracts.
//! 外置的 OIDC verifier 契约。
use std::time::Duration;
@@ -1,4 +1,4 @@
//! External reqwest network policy contracts.
//! 外置的 reqwest 网络策略契约。
use std::cell::Cell;
use std::net::IpAddr;