Skip to content

Keep request service tiers closed; open only the response tier - #44

Merged
krinart merged 1 commit into
spiceaifrom
viktor/closed-request-service-tier
Oct 9, 2026
Merged

krinart merged 1 commit into
spiceaifrom
viktor/closed-request-service-tier

Conversation

@krinart

@krinart krinart commented Oct 9, 2026

Copy link
Copy Markdown

Follow-up to #42, from review of spiceai/spiceai#14927.

#42 opened chat::ServiceTier and responses::ServiceTier. The request types share those enums, so requests started accepting any tier. Spice deserializes /v1/chat/completions and /v1/responses request bodies into these types, so a client-supplied service_tier: "fast" went from 422 to forwarded: an unreviewed widening of a published request field. Only the response side needed to change.

Change

  • ServiceTier (chat and responses) is closed again, byte-identical to before Accept a service_tier the enum does not name #42 (including Copy and the derived schema). It stays on CreateChatCompletionRequest and CreateResponse.
  • The response fields CreateChatCompletionResponse.service_tier, CreateChatCompletionStreamResponse.service_tier, and Response.service_tier use ServiceTierResponse. It names the same five tiers and keeps any other tier verbatim in #[serde(untagged)] Other(String), with the hand-written any-string schema from Accept a service_tier the enum does not name #42.
  • chat::ServiceTierResponse already existed and was unused. It gains Auto so it covers every request value. responses::ServiceTierResponse is new.

Callers that name the response field's type change from ServiceTier to ServiceTierResponse. In Spice that is one field in the Databricks stream type.

Validation

  • cargo test --features "chat-completion-types response-types" --test ser_de --test responses_ser_de: 13 passed. New: a_request_names_only_the_closed_tiers (priority accepted, fast refused) for both request types.
  • cargo clippy --all-features --all-targets builds with only the 4 existing warnings. Offline suites pass. The 12 lib and boxed_future failures are live-API tests that api.openai.com rejects with invalid_api_key.
  • Spice's llms guard tests (health check, request, and stream through both chat backends against an endpoint answering "fast", plus a new request-side check): 7 passed on this branch. On Accept a service_tier the enum does not name #42's merge (2c102dc), the request-side check fails because "fast" deserializes to Some(Other("fast")).

#42 made `chat::ServiceTier` and `responses::ServiceTier` open, and the
request types share them, so a request naming any tier became valid. A
caller that validates incoming requests against these types widened its
accepted values as a side effect of a response-decoding fix.

Split the two directions. `ServiceTier` is closed again, exactly as before
#42, and stays on `CreateChatCompletionRequest` and `CreateResponse`. The
response fields (`CreateChatCompletionResponse`,
`CreateChatCompletionStreamResponse`, `Response`) use `ServiceTierResponse`,
which keeps an unnamed tier verbatim in `Other(String)`, with the
hand-written any-string schema. `chat::ServiceTierResponse` was unused; it
gains `Auto` so it covers every value the request enum can hold.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The request/response type separation is consistent and adequately covered by focused serialization tests.

0 open findings

What changed in this PR

Separates closed request service tiers from forward-compatible response tiers.

Changes:

  • Restores closed service-tier request enums.
  • Adds open response enums preserving unknown tiers.
  • Adds request rejection and response round-trip tests.
File Description
async-openai/​src/​types/​chat/​chat_.rs Separates chat request and response tier types.
async-openai/​src/​types/​responses/​response.rs Adds a forward-compatible response tier type.
async-openai/​tests/​ser_de.rs Tests chat request restrictions and response tiers.
async-openai/​tests/​responses_ser_de.rs Tests Responses API request restrictions and response tiers.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@krinart
krinart merged commit dfadaed into spiceai Oct 9, 2026
52 checks passed
krinart added a commit to spiceai/spiceai that referenced this pull request Oct 9, 2026
…openai#44

spiceai/async-openai#42 opened `ServiceTier`, which the request types share,
so `/v1/chat/completions` and `/v1/responses` started accepting and
forwarding any `service_tier` a client sent. That widens a published request
field, which the #14916 fix did not need.

#44 (merged as dfadaed) restores the closed `ServiceTier` on requests and
moves only the response fields to the open `ServiceTierResponse`. The
Databricks stream type follows the response field. The guard now sends a
named tier and checks the server's unnamed tier comes back, and a new
`a_request_naming_an_unnamed_tier_is_refused` pins both request types to the
listed tiers, which fails on the previous pin.
@krinart krinart self-assigned this Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants