Skip to content

feat(auth): add caller-attested X.509 transport capability - #523

Merged
jbeckwith-oai merged 11 commits into
mainfrom
codex/x509-ruby-1-attested-transport
Aug 25, 2026
Merged

feat(auth): add caller-attested X.509 transport capability#523
jbeckwith-oai merged 11 commits into
mainfrom
codex/x509-ruby-1-attested-transport

Conversation

@jbeckwith-oai

Copy link
Copy Markdown
Contributor

Summary

First PR in a five-part X.509 workload-identity stack. This change adds only the explicit, caller-owned mTLS transport capability; it does not enable OAuth exchange or change OpenAI::Client authentication.

  • Add immutable OpenAI::Auth::X509Transport for one concrete OpenAI::NetHTTPClient, an explicitly attested static certificate identity, the pinned token issuer, and approved global/US/EU mTLS API origins.
  • Reject unexpected authorities, credential/header aliases, redirects, ambient proxies in direct mode, and HTTPS-labeled proxies before proxy credentials reach the network.
  • Add an optional native-connection validation callback so proxy policy is checked on the actual configured Net::HTTP connection, including pooled connections.
  • Keep certificate/key ownership and rotation with the application; explicitly do not claim that object identity cryptographically binds a bearer token to a certificate.
  • Include Sorbet/RBS declarations and real-wire tests using the existing ephemeral PKI, authenticated HTTP CONNECT proxy, and separate issuer/API TLS servers.

Verification

  • bundle exec ruby test/openai/auth/x509_transport_test.rb
  • bundle exec ruby test/openai/net_http_client_mtls_test.rb
  • bundle exec rake lint
  • Real-wire adversarial cases verify that direct mode and unsupported HTTPS proxies are rejected before any proxy connection.

Stack

  1. This PR: attested transport and real-wire security boundary.
  2. Pinned X.509 token-exchange protocol.
  3. Public-client integration and two-leg mTLS end-to-end test.
  4. Refresh/retry/concurrency and final-credential hardening.
  5. Customer documentation, enrolled-credential live smoke, and installed-gem end-to-end coverage.

Review requested from @openai/sdks-team because this change touches authentication and transport security.

@jbeckwith-oai
jbeckwith-oai requested a review from a team as a code owner August 24, 2026 23:40
@jbeckwith-oai
jbeckwith-oai requested a review from a team August 24, 2026 23:40
@openai-sdks

openai-sdks Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

OkTest Summary

237/237 SDK tests passed in 10.051s for Ruby SDK PR #523.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 164ms
tests/chat-completions-create.test.ts ✅ Passed 243ms
tests/chat-completions-stream.test.ts ✅ Passed 135ms
tests/files-content-binary.test.ts ✅ Passed 273ms
tests/files-create-multipart.test.ts ✅ Passed 132ms
tests/files-list-pagination.test.ts ✅ Passed 166ms
tests/initialize-config.test.ts ✅ Passed 167ms
tests/instance-isolation.test.ts ✅ Passed 264ms
tests/models-list.test.ts ✅ Passed 162ms
tests/responses-background-lifecycle.test.ts ✅ Passed 240ms
tests/responses-body-method-errors.test.ts ✅ Passed 520ms
tests/responses-cancel-timeout.test.ts ✅ Passed 265ms
tests/responses-cancel.test.ts ✅ Passed 217ms
tests/responses-compact-retries.test.ts ✅ Passed 260ms
tests/responses-compact.test.ts ✅ Passed 213ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 175ms
tests/responses-create-advanced.test.ts ✅ Passed 174ms
tests/responses-create-disconnect.test.ts ✅ Passed 1.037s
tests/responses-create-errors.test.ts ✅ Passed 354ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 132ms
tests/responses-create-retries.test.ts ✅ Passed 283ms
tests/responses-create-stream-failures.test.ts ✅ Passed 166ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 213ms
tests/responses-create-stream-wire.test.ts ✅ Passed 2.441s
tests/responses-create-stream.test.ts ✅ Passed 127ms
tests/responses-create-terminal-states.test.ts ✅ Passed 271ms
tests/responses-create-timeout.test.ts ✅ Passed 322ms
tests/responses-create.test.ts ✅ Passed 267ms
tests/responses-delete.test.ts ✅ Passed 238ms
tests/responses-input-items-errors.test.ts ✅ Passed 178ms
tests/responses-input-items-list.test.ts ✅ Passed 184ms
tests/responses-input-items-options.test.ts ✅ Passed 222ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 352ms
tests/responses-input-tokens-count.test.ts ✅ Passed 253ms
tests/responses-malformed-inputs.test.ts ✅ Passed 2.017s
tests/responses-not-found-errors.test.ts ✅ Passed 410ms
tests/responses-parse.test.ts ✅ Passed 202ms
tests/responses-retrieve-retries.test.ts ✅ Passed 333ms
tests/responses-retrieve.test.ts ✅ Passed 236ms
tests/responses-stored-method-errors.test.ts ✅ Passed 674ms
tests/retry-behavior.test.ts ✅ Passed 3.005s
tests/sdk-error-shape.test.ts ✅ Passed 420ms

View OkTest run #32869829373

SDK merge (49ed04ad167c) · head (a6b28ca0dad1) · base (8057a053dca4) · OkTest (2b1bdfd25e98)

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-25T16:16:22.862397Z a6b28ca New commits
🔒 Security Review Completed 2026-08-25T16:09:30.654347Z a6b28ca New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Castiron custom code

✅ No new custom-code files detected.

48 mixed files remain; 4 existing customizations changed.

Compared 8057a053dca4a6b28ca0dad1. Generated baselines verified.

File Result Current custom patch
lib/openai.rb Existing customization changed +35 / −6
lib/openai/client.rb Existing customization changed +484 / −20
rbi/openai/client.rbi Existing customization changed +85 / −5
sig/openai/client.rbs Existing customization changed +38 / −1
44 existing customizations unchanged
  • lib/openai/models/chat/chat_completion_message.rb
  • lib/openai/models/chat/chat_completion_message_function_tool_call.rb
  • lib/openai/models/chat/completion_create_params.rb
  • lib/openai/models/response_format_json_schema.rb
  • lib/openai/models/responses/function_tool.rb
  • lib/openai/models/responses/response.rb
  • lib/openai/models/responses/response_create_params.rb
  • lib/openai/models/responses/response_format_text_config.rb
  • lib/openai/models/responses/response_format_text_json_schema_config.rb
  • lib/openai/models/responses/response_function_tool_call.rb
  • lib/openai/models/responses/response_function_web_search.rb
  • lib/openai/models/responses/response_output_text.rb
  • lib/openai/models/responses/tool.rb
  • lib/openai/resources/beta/responses.rb
  • lib/openai/resources/beta/threads.rb
  • lib/openai/resources/chat/completions.rb
  • lib/openai/resources/files.rb
  • lib/openai/resources/responses.rb
  • lib/openai/resources/vector_stores/file_batches.rb
  • lib/openai/resources/vector_stores/files.rb
  • lib/openai/resources/webhooks.rb
  • rbi/openai/models/chat/chat_completion_message.rbi
  • rbi/openai/models/chat/chat_completion_message_function_tool_call.rbi
  • rbi/openai/models/chat/completion_create_params.rbi
  • rbi/openai/models/response_format_json_schema.rbi
  • rbi/openai/models/responses/response.rbi
  • rbi/openai/models/responses/response_create_params.rbi
  • rbi/openai/models/responses/response_function_tool_call.rbi
  • rbi/openai/models/responses/response_function_web_search.rbi
  • rbi/openai/models/responses/response_output_text.rbi
  • rbi/openai/resources/chat/completions.rbi
  • rbi/openai/resources/files.rbi
  • rbi/openai/resources/responses.rbi
  • rbi/openai/resources/vector_stores/file_batches.rbi
  • rbi/openai/resources/vector_stores/files.rbi
  • scripts/castiron/README.md
  • scripts/castiron/custom_code_report.py
  • scripts/castiron/test_custom_code_report.py
  • sig/openai/models/responses/response.rbs
  • sig/openai/models/responses/response_function_web_search.rbs

4 more in the full report.

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 32869867675 --repo openai/openai-ruby \
  --name castiron-custom-code-32869867675-1 --dir /tmp/castiron-custom-code-32869867675-1
git apply --stat /tmp/castiron-custom-code-32869867675-1/custom-code.patch
cat /tmp/castiron-custom-code-32869867675-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin 8057a053dca400ab0796f8da6ae814a57689e396 a6b28ca0dad1344a0a3eadd49a18f874a6162dd6
python3 scripts/castiron/custom_code_report.py report \
  --base 8057a053dca400ab0796f8da6ae814a57689e396 \
  --head a6b28ca0dad1344a0a3eadd49a18f874a6162dd6 --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-a6b28ca0dad1
cat /tmp/castiron-custom-code-a6b28ca0dad1/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2471744f67

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread test/openai/auth/x509_transport_test.rb Outdated
Comment thread lib/openai/auth/x509_transport.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch 2 times, most recently from 21858c6 to 55a5103 Compare August 25, 2026 02:10

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 55a51038b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb
Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/net_http_client.rb
Comment thread lib/openai/auth/x509_transport.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from 55a5103 to 6fe267a Compare August 25, 2026 02:36

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6fe267ab93

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/net_http_client.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from 6fe267a to fc9061b Compare August 25, 2026 03:04
Comment thread lib/openai/auth/x509_transport.rb Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc9061b342

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from fc9061b to f67b8f2 Compare August 25, 2026 03:08

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f67b8f2683

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/auth/x509_transport.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from f67b8f2 to a5ab8f7 Compare August 25, 2026 03:18

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5ab8f70db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb
Comment thread lib/openai/auth/x509_transport.rb Outdated
Comment thread lib/openai/net_http_client.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from a5ab8f7 to 7065e61 Compare August 25, 2026 03:42

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7065e619a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/net_http_client.rb Outdated
@jbeckwith-oai
jbeckwith-oai force-pushed the codex/x509-ruby-1-attested-transport branch from 7065e61 to 4faf6fc Compare August 25, 2026 04:03

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4faf6fc712

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated
## Summary

Second PR in the stacked X.509 workload-identity series; targets the
transport-capability branch rather than `main`.

- Add immutable `OpenAI::Auth::X509WorkloadIdentity` configuration for
the mapped identity-provider and service-account IDs.
- Implement the exact pinned X.509 token-exchange request against
`https://mtls.auth.openai.com/oauth/token` using only the attested
transport.
- Require complete bounded OAuth JSON, strict bearer grammar,
access-token issuance/type markers, and finite positive expiry of at
most one hour.
- Close response resources, honor authentication deadlines, and redact
unknown/nested OAuth errors and sensitive network diagnostics.
- Include focused malformed-response and credential-isolation tests plus
matching Sorbet/RBS declarations.

The 64 KiB bound applies only to the small OAuth token-exchange
response; ordinary API JSON responses and SSE events remain unlimited by
this change.

## Verification

- `bundle exec ruby test/openai/auth/x509_token_exchange_test.rb`
- `bundle exec ruby test/openai/auth/x509_transport_test.rb`
- `bundle exec rake lint`

## Stack

1. Attested transport and real-wire security boundary.
2. **This PR:** X.509 identity and pinned token-exchange protocol.
3. Public-client integration and two-leg mTLS end-to-end test.
4. Refresh/retry/concurrency and final-credential hardening.
5. Customer documentation, enrolled-credential live smoke, and
installed-gem end-to-end coverage.

Review requested from `@openai/sdks-team` because this change introduces
an authentication protocol.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f203acc968

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa736d40b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/auth/x509_transport.rb Outdated

@HAYDEN-OAI HAYDEN-OAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One substantive HTTP request-framing security issue remains in the X.509 transport capability.

Comment thread lib/openai/auth/x509_transport.rb
Comment thread lib/openai/auth/x509_token_exchange.rb Fixed
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@apcha-oai apcha-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[sdk codex review] Approved at 5eb9eae682b495613823debb99dbc2fade62b5a9 after two independent full reviews of all 18 changed files, supporting runtime/contracts, tests and existing feedback. No substantiated merge-blocking defect found.

This reviewed range includes the attested transport and the token-exchange code merged from #524, despite the older transport-only PR description. Checked destination/authority and proxy restrictions, TLS verification callbacks and pool cleanup, immutable header validation, the fixed four-field exchange protocol, token-response validation, and lazy response/cleanup error sanitization. The prior framing-header and nested OAuth-code findings are fixed in this snapshot; no duplicate comments added.

Primary logs for CI 32812201617 confirm 1,291 tests per Ruby 3.3.12, 3.4.10 and 4.0.6, with zero failures/errors/skips. OkTest passed 237 tests across 42 suites. Both tested merge 11d772677cc7d5d545c938a9ca0c2a7efdcb255e, this head plus current main e7dd78b8c21a994edb2b9e94a3f2938cc5a2b17c; actual diff merge-base is c3fe427c6e9d9fad78acd23118b897ab0d6c5611.

Head/base, author, open/non-draft state, mergeability and feedback were rechecked before submission. No candidate code, tests, live API calls or security scans were run. This code review does not replace any separately required human/owner sign-off.

)

## Summary

Final open integration PR in the stacked X.509 workload-identity series.
The lifecycle-hardening PR (#526) and documentation/live-smoke PR (#527)
have already been merged into this branch, so this PR now contains their
complete reviewed changes as well.

- Accept `OpenAI::Auth::X509WorkloadIdentity` through the existing
`workload_identity:` client option and require an attested
`X509Transport` as `http_client:`.
- Default only certificate-authenticated clients to their approved mTLS
API origin and reject provider-owned, mismatched, or unsupported
destinations before credentials are acquired.
- Reuse the exact caller-owned transport for both the pinned issuer
exchange and the API request; keep existing API-key, JWT/ID
workload-identity, admin, and ordinary transport behavior.
- Fail closed for unsupported Realtime WebSocket connections.
- Add a public-client, real-wire end-to-end test with independently
terminating issuer/API TLS servers, a real client certificate and chain,
authenticated HTTP CONNECT, and observed bearer/header separation.
- Include bounded refresh/retry/concurrency handling, one-time
credential replay, custom mTLS base-path preservation, and final
credential/header hardening from #526.
- Include customer documentation, installed-gem verification,
production-enrolled certificate examples, and the optional protected
live-smoke workflow from #527.
- Inherit request-smuggling prevention and sanitized nested issuer OAuth
error codes from the transport/token-exchange base PR (#523).

## Verification

- Full Ruby 4 suite: **1,340 tests, 12,115 assertions, zero
failures/errors**.
- Full Ruby 3.3 suite: **1,340 tests, 12,114 assertions, zero
failures/errors**.
- `bundle exec rake lint`: **2,765 files inspected, no offenses**.
- Real production X.509 issuer exchange and mTLS API request succeeded
with the enrolled restricted-project service account, including with
ambient debug logging enabled.
- Focused real-wire issuer/API, framing-security, OAuth-redaction,
lifecycle, installed-gem, protected-workflow, and sanitized-example
regression coverage all pass.

## Stack

1. **#523 (open):** attested transport, real-wire security boundary, and
pinned token-exchange protocol; #524 has already merged into this base.
2. **#525 (this PR, open):** public-client integration, lifecycle/retry
hardening, customer documentation, protected optional live smoke, and
installed-gem end-to-end coverage; #526 and #527 have already merged
into this branch.

Review requested from `@openai/sdks-team` because this change affects
client authentication, endpoints, TLS, and a protected CI workflow.
Comment thread lib/openai/client.rb
rescue OpenAI::Errors::AuthenticationError
raise unless retry_count.zero? && request_replayable?(request)
@workload_identity_auth.invalidate_token
@workload_identity_auth.invalidate_token(context.fetch(:token)) if x509_request
Comment thread lib/openai/client.rb
@workload_identity_auth.invalidate_token
@workload_identity_auth.invalidate_token(context.fetch(:token)) if x509_request
replay_allowed = request_replayable?(request)
replay_allowed &&= x509_request ? replay_state.empty? : retry_count.zero?
Comment thread lib/openai/client.rb
raise unless replay_allowed

if x509_request
replay_state << true
Comment thread lib/openai/client.rb

if x509_request
replay_state << true
replay_state.freeze
Comment thread lib/openai/client.rb
if x509_request
replay_state << true
replay_state.freeze
issuer_retries = context.fetch(:issuer_retries)
Comment thread lib/openai/client.rb
replay_state << true
replay_state.freeze
issuer_retries = context.fetch(:issuer_retries)
auth_max_retries = context.fetch(:auth_max_retries)
Comment thread lib/openai/client.rb
replay_state.freeze
issuer_retries = context.fetch(:issuer_retries)
auth_max_retries = context.fetch(:auth_max_retries)
api_max_retries = context.fetch(:api_max_retries)
Comment thread lib/openai/client.rb
issuer_retries = context.fetch(:issuer_retries)
auth_max_retries = context.fetch(:auth_max_retries)
api_max_retries = context.fetch(:api_max_retries)
log_context = context.fetch(:log_context)
Comment thread lib/openai/client.rb
send_retry_header: send_retry_header
)
rescue OpenAI::Errors::AuthenticationError
@workload_identity_auth.invalidate_token(context.fetch(:token)) if x509_request
Comment thread lib/openai/client.rb

if (context = request[:x509_request_context])
context[:issuer_retries] = previous_issuer_retries + attempts
context[:token] = token.dup.freeze
@jbeckwith-oai
jbeckwith-oai added this pull request to the merge queue Aug 25, 2026
Merged via the queue into main with commit 712f3c8 Aug 25, 2026
19 checks passed
@jbeckwith-oai
jbeckwith-oai deleted the codex/x509-ruby-1-attested-transport branch August 25, 2026 16:09
@openai-sdks openai-sdks Bot mentioned this pull request Aug 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6b28ca0da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/openai/client.rb
@@ -197,16 +291,49 @@ class Client < OpenAI::Internal::Transport::BaseClient
send_retry_header: send_retry_header
)
rescue OpenAI::Errors::AuthenticationError

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Sanitize status-error URLs before leaving the X.509 path

When an X.509 API request containing a signed or otherwise sensitive query receives a terminal HTTP error, BaseClient constructs the resulting APIStatusError with the complete prepared URL, while this handler only intercepts authentication failures for replay. Consequently, errors such as 400, 403, 404, 429, 5xx, and the final 401 expose the query and fragment through error.url; reconstruct or sanitize these errors before they leave this boundary.

AGENTS.md reference: AGENTS.md:L35-L38

Useful? React with 👍 / 👎.

Comment thread lib/openai/client.rb
rescue Timeout::Error => error
raise unless x509_request

raise OpenAI::Errors::APITimeoutError.new(url: request.fetch(:url), message: error.message), cause: nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Redact the API URL on authentication timeouts

When the X.509 token exchange or its retry delay exhausts the request deadline for an API URL containing a sensitive query or fragment, this newly constructed APITimeoutError retains the complete API URL through its public url accessor. This bypasses the transport's URL sanitization because the timeout is raised in authentication preparation rather than network dispatch; strip the query and fragment before constructing the error.

AGENTS.md reference: AGENTS.md:L35-L38

Useful? React with 👍 / 👎.

"RUBYOPT" => nil,
"RUBYLIB" => nil
}
output, status = Open3.capture2e(environment, RbConfig.ruby, smoke_script, chdir: directory)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound the installed-gem smoke subprocess

If the installed-gem child stalls in its real issuer/API handshakes, response streaming, proxy shutdown, or connection cleanup, Open3.capture2e waits indefinitely and can hang the entire test job. Fresh evidence beyond the already-fixed wire-test subprocess is that this separate real-wire child still has no bounded wait or TERM/KILL cleanup; run it through the same timeout-safe subprocess helper.

Useful? React with 👍 / 👎.

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.

3 participants