Skip to content

more google adc stuff#3964

Open
sxlijin wants to merge 12 commits into
canaryfrom
sam/google-auth
Open

more google adc stuff#3964
sxlijin wants to merge 12 commits into
canaryfrom
sam/google-auth

Conversation

@sxlijin

@sxlijin sxlijin commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Improved Vertex AI authentication with clear credential-source precedence (credentials file path → credentials_content inline JSON → ADC), plus consistent use of the same resolved credentials for tokens and project handling.
  • Bug Fixes
    • Rejects inline JSON provided via credentials (now treated strictly as a file path).
    • Ensures Vertex URL project placeholder replacement and bearer token creation use the same credentials; x-goog-user-project is added only when missing.
    • Auth harness now correctly treats an explicitly set-but-empty environment variable as set.
  • Documentation
    • Updated Vertex AI credential option documentation and expanded auth systest coverage notes.
  • Tests
    • Expanded/added integration and project-id/quota precedence test coverage.

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jul 11, 2026 1:43am
promptfiddle Ready Ready Preview, Comment Jul 11, 2026 1:43am
promptfiddle2 Ready Ready Preview, Comment Jul 11, 2026 1:43am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Vertex AI credential handling now distinguishes inline JSON, credential file paths, and ADC. The forked Google Cloud auth library adds deterministic discovery, token caching, project resolution, multiple credential exchanges, and expanded tests.

Changes

Vertex authentication

Layer / File(s) Summary
ADC discovery, caching, and project resolution
baml_language/forks/google-cloud-auth/*, baml_language/forks/google-cloud-auth/tests/project_id.rs, baml_language/forks/google-cloud-auth-systest/*
The auth fork adds deterministic ADC discovery, cached tokens, metadata fallback, project and quota-project resolution, and expanded documented and harness coverage.
Credential minting and exchange flows
baml_language/forks/google-cloud-auth/src/lib.rs, baml_language/forks/google-cloud-auth/tests/*
Credential dispatch now covers service accounts, authorized users, external accounts, STS, impersonation, metadata tokens, unsupported sources, and cache refresh behavior.
Vertex credential contract and request integration
baml_language/crates/baml_builtins2/.../llm_types.baml, baml_language/crates/sys_llm/src/auth_request/vertex.rs
credentials_content accepts BAML JSON, credentials is treated as a file path, ADC remains the fallback, and one resolved source supplies tokens, project IDs, and quota-project headers.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant VertexClient
  participant auth_vertex
  participant forked_google_cloud_auth
  participant GoogleCloudEndpoints
  VertexClient->>auth_vertex: provide Vertex options
  auth_vertex->>auth_vertex: resolve inline JSON, file path, or ADC
  auth_vertex->>forked_google_cloud_auth: request token and project data
  forked_google_cloud_auth->>GoogleCloudEndpoints: exchange credentials or query metadata
  GoogleCloudEndpoints-->>forked_google_cloud_auth: return token and project data
  forked_google_cloud_auth-->>auth_vertex: return authentication values
  auth_vertex-->>VertexClient: send authenticated Vertex request
Loading

Possibly related PRs

  • BoundaryML/baml#3323: Added related Vertex AI credential fields and authentication request handling.
  • BoundaryML/baml#3344: Refactored the Vertex authentication runtime I/O flow used by this credential-resolution work.
  • BoundaryML/baml#3617: Introduced the forked Google Cloud auth flow used by this refactor.

Poem

I’m a rabbit with credentials tucked tight,
JSON in a burrow, paths in moonlight.
ADC hops when the others are gone,
Tokens cache softly till freshness moves on.
Vertex follows one trail through the night—
Project and quota headers land just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and generic; it doesn’t clearly describe the main changes to Google ADC auth and credential resolution. Rename it to a specific summary of the main change, such as updating Google ADC credential resolution and auth handling.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sam/google-auth

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@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: 86fa89723d

ℹ️ 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 baml_language/crates/sys_llm/src/auth_request/vertex.rs Outdated
Comment on lines +828 to +832
if let Some(home) = io.env("HOME").await.filter(|s| !s.is_empty()) {
return Some(format!("{home}/.config/gcloud"));
}
if let Some(appdata) = io.env("APPDATA").await.filter(|s| !s.is_empty()) {
return Some(format!("{appdata}/gcloud"));

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 Prefer APPDATA for Windows ADC discovery

For Windows processes where both HOME and APPDATA are set, this returns $HOME/.config/gcloud before ever checking %APPDATA%\gcloud, so token_from_adc and project_id miss the real well-known ADC file and fall through to metadata/no credentials. Use a platform-specific order, or check APPDATA before HOME on Windows, to make the documented Windows ADC path reachable.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/sys_llm/src/auth_request/vertex.rs (1)

74-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Honor VertexAiOptions.project_id before credential discovery.

project_id is exposed in VertexAiOptions and named in the error message, but this path only resolves from credentials/environment. A configured options.project_id therefore cannot fill the Vertex URL placeholder.

Proposed fix
-        let project_id = project_id_from_credentials(&creds, &adapter)
-            .await
-            .ok_or_else(|| {
+        let project_id = match vertex_opts
+            .as_ref()
+            .and_then(|opts| opts.project_id.as_deref())
+            .map(str::trim)
+            .filter(|id| !id.is_empty())
+        {
+            Some(id) => id.to_owned(),
+            None => project_id_from_credentials(&creds, &adapter).await.ok_or_else(|| {
                 BuildRequestError::Other(
                     "Could not resolve project_id for Vertex AI. Set options.project_id, \
                      the GOOGLE_CLOUD_PROJECT env var, or provide credentials containing \
                      a project_id."
                         .to_string(),
                 )
-            })?;
+            })?,
+        };

Add a regression test with VertexAiOptions.project_id set and a credential document containing no project ID.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/sys_llm/src/auth_request/vertex.rs` around lines 74 -
89, Update the project ID resolution in the Vertex request-building path to
prefer the configured VertexAiOptions.project_id before falling back to
project_id_from_credentials and environment discovery, while preserving the
existing error when neither source resolves a value. Add a regression test
covering VertexAiOptions.project_id with credentials that omit a project ID, and
verify the placeholder in the request URL is replaced with the configured value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@baml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.baml`:
- Around line 561-563: Update the credential-path documentation near the LLM
credential option to explicitly include external_account_authorized_user
alongside the currently listed supported Google credential formats, keeping the
statement consistent with the resolver’s supported credential types.

In `@baml_language/forks/google-cloud-auth/src/lib.rs`:
- Around line 261-268: Remove the global cache lookup and storage for the GCE
metadata path in the metadata-token flow surrounding mint_metadata, so each
auth_vertex/BamlTokenIo runtime contacts its own metadata server; alternatively,
derive the cache key from a runtime-specific or credential-source-specific
namespace rather than the fixed "\0gce-metadata" value.

---

Outside diff comments:
In `@baml_language/crates/sys_llm/src/auth_request/vertex.rs`:
- Around line 74-89: Update the project ID resolution in the Vertex
request-building path to prefer the configured VertexAiOptions.project_id before
falling back to project_id_from_credentials and environment discovery, while
preserving the existing error when neither source resolves a value. Add a
regression test covering VertexAiOptions.project_id with credentials that omit a
project ID, and verify the placeholder in the request URL is replaced with the
configured value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 98cc1fe4-17f1-41ba-8603-586756e10f85

📥 Commits

Reviewing files that changed from the base of the PR and between 4fa203d and 86fa897.

⛔ Files ignored due to path filters (2)
  • baml_language/Cargo.lock is excluded by !**/*.lock
  • baml_language/forks/google-cloud-auth-systest/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.baml
  • baml_language/crates/sys_llm/src/auth_request/vertex.rs
  • baml_language/crates/sys_llm/src/build_request/google.rs
  • baml_language/forks/google-cloud-auth-systest/README.md
  • baml_language/forks/google-cloud-auth/Cargo.toml
  • baml_language/forks/google-cloud-auth/src/lib.rs
  • baml_language/forks/google-cloud-auth/tests/adc_precedence.rs
  • baml_language/forks/google-cloud-auth/tests/auth_flows.rs
  • baml_language/forks/google-cloud-auth/tests/project_id.rs
  • baml_language/sdk_tests/crates/python_pydantic2/llm_functions/customizable/test_main.py
  • baml_language/sdk_tests/fixtures/llm_functions/baml_src/ns_lorem/functions.baml
  • thoughts/sam-projects/google-adc-credentials/background.md
💤 Files with no reviewable changes (1)
  • baml_language/crates/sys_llm/src/build_request/google.rs

Comment on lines +561 to +563
/// Path to a Google credential JSON file (service account, authorized user,
/// workload identity federation, or impersonated service account). Inline
/// JSON is not supported; when unset, Application Default Credentials apply.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document workforce refresh credentials too.

external_account_authorized_user is supported by the resolver but omitted from this public option contract.

-  /// workload identity federation, or impersonated service account). Inline
+  /// workload identity federation, workforce refresh, or impersonated service
+  /// account). Inline
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Path to a Google credential JSON file (service account, authorized user,
/// workload identity federation, or impersonated service account). Inline
/// JSON is not supported; when unset, Application Default Credentials apply.
/// Path to a Google credential JSON file (service account, authorized user,
/// workload identity federation, workforce refresh, or impersonated service
/// account). Inline JSON is not supported; when unset, Application Default Credentials apply.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.baml`
around lines 561 - 563, Update the credential-path documentation near the LLM
credential option to explicitly include external_account_authorized_user
alongside the currently listed supported Google credential formats, keeping the
statement consistent with the resolver’s supported credential types.

Comment on lines 261 to +268
// 3. GCE metadata server.
token_from_metadata(io, scope).await
let key = cache_key("\u{0}gce-metadata", scope);
if let Some(token) = cached_token(&key) {
return Ok(token);
}
let token = mint_metadata(io, scope).await?;
store_token(key, &token);
Ok(token.access_token)

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not share metadata tokens across runtime instances.

The fixed "\0gce-metadata" cache key is scoped only by OAuth scope. Since auth_vertex creates a new BamlTokenIo around its supplied RuntimeIo per call, a later isolated runtime can receive the first runtime’s cached bearer token without contacting its metadata server. Namespace this cache per runtime/credential source, or do not globally cache metadata tokens.

Safe immediate fix
-    let key = cache_key("\u{0}gce-metadata", scope);
-    if let Some(token) = cached_token(&key) {
-        return Ok(token);
-    }
     let token = mint_metadata(io, scope).await?;
-    store_token(key, &token);
     Ok(token.access_token)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 3. GCE metadata server.
token_from_metadata(io, scope).await
let key = cache_key("\u{0}gce-metadata", scope);
if let Some(token) = cached_token(&key) {
return Ok(token);
}
let token = mint_metadata(io, scope).await?;
store_token(key, &token);
Ok(token.access_token)
// 3. GCE metadata server.
let token = mint_metadata(io, scope).await?;
Ok(token.access_token)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/forks/google-cloud-auth/src/lib.rs` around lines 261 - 268,
Remove the global cache lookup and storage for the GCE metadata path in the
metadata-token flow surrounding mint_metadata, so each auth_vertex/BamlTokenIo
runtime contacts its own metadata server; alternatively, derive the cache key
from a runtime-specific or credential-source-specific namespace rather than the
fixed "\0gce-metadata" value.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Binary size checks failed

1 violations · ✅ 6 passed

⚠️ Please fix the size gate issues or acknowledge them by updating baselines.

Artifact Platform File Gzip Gated on Baseline Delta Status
baml-cli Linux 🔒 22.1 MB 9.5 MB file 21.5 MB +578.7 KB (+2.7%) OK
packed-program Linux 🔒 16.0 MB 6.7 MB file 15.6 MB +329.2 KB (+2.1%) OK
baml-cli macOS 🔒 17.0 MB 8.2 MB file 16.6 MB +447.9 KB (+2.7%) OK
packed-program macOS 🔒 12.4 MB 5.9 MB file 12.1 MB +265.1 KB (+2.2%) OK
baml-cli Windows 🔒 18.6 MB 8.4 MB file 18.1 MB +480.8 KB (+2.7%) OK
packed-program Windows 🔒 13.3 MB 6.0 MB file 13.0 MB +267.8 KB (+2.1%) OK
bridge_wasm WASM 14.8 MB 🔒 4.2 MB gzip 4.1 MB +129.5 KB (+3.2%) FAIL

🔒 = the size this artifact is GATED on (ceiling + delta). Binaries gate on file size (installed binary); WASM gates on gzip (download size). The other size is shown for information only.

Details & how to fix

Violations:

  • bridge_wasm (WASM) gzip_bytes: 4.2 MB exceeds limit of 4.2 MB (exceeded by +7.7 KB, policy: max_gzip_bytes)
  • bridge_wasm (WASM) gzip_delta_pct: +3.2% exceeds limit of 3.0% (exceeded by +0.2pp, policy: max_delta_pct)

Add/update baselines:

.ci/size-gate/wasm32-unknown-unknown.toml:

[artifacts.bridge_wasm]
file_bytes = 14750419
gzip_bytes = 4188447

Generated by cargo size-gate · workflow run

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@baml_language/crates/sys_llm/src/auth_request/vertex.rs`:
- Around line 235-247: Update project_id_from_credentials to propagate errors
when a ResolvedCredentials::CredentialsFile path cannot be read, instead of
silently falling back to google_cloud_auth::project_id(adapter). Reuse
read_credentials_file or change the function’s return type as needed so the read
failure reaches the caller, while preserving JSON project-id extraction for
successfully read credential files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: eb02c41b-989c-4ecb-b3f7-f28853e4ab1b

📥 Commits

Reviewing files that changed from the base of the PR and between 86fa897 and beaaa3b.

⛔ Files ignored due to path filters (2)
  • baml_language/Cargo.lock is excluded by !**/*.lock
  • baml_language/forks/google-cloud-auth-systest/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.baml
  • baml_language/crates/sys_llm/src/auth_request/vertex.rs
  • baml_language/crates/sys_llm/src/build_request/google.rs
  • baml_language/forks/google-cloud-auth-systest/README.md
  • baml_language/forks/google-cloud-auth/Cargo.toml
  • baml_language/forks/google-cloud-auth/src/lib.rs
  • baml_language/forks/google-cloud-auth/tests/adc_precedence.rs
  • baml_language/forks/google-cloud-auth/tests/auth_flows.rs
  • baml_language/forks/google-cloud-auth/tests/project_id.rs
💤 Files with no reviewable changes (1)
  • baml_language/crates/sys_llm/src/build_request/google.rs
✅ Files skipped from review due to trivial changes (1)
  • baml_language/forks/google-cloud-auth-systest/README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_llm/llm_types.baml
  • baml_language/forks/google-cloud-auth/Cargo.toml
  • baml_language/forks/google-cloud-auth/tests/project_id.rs
  • baml_language/forks/google-cloud-auth/tests/adc_precedence.rs

Comment thread baml_language/crates/sys_llm/src/auth_request/vertex.rs
@blacksmith-sh

blacksmith-sh Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Found 18 test failures on Blacksmith runners:

Failures

Test View Logs
test_streaming_e2e/test_stream View Logs
test_streaming_e2e/test_stream View Logs
test_streaming_e2e/test_stream View Logs
test_streaming_e2e/test_stream_async View Logs
test_streaming_e2e/test_stream_async View Logs
test_streaming_e2e/test_stream_async View Logs
test_streaming_e2e/test_stream_collect_in_baml View Logs
test_streaming_e2e/test_stream_collect_in_baml View Logs
test_streaming_e2e/test_stream_collect_in_baml View Logs
test_streaming_e2e/test_stream_doc View Logs
test_streaming_e2e/test_stream_doc View Logs
test_streaming_e2e/test_stream_doc View Logs
test_streaming_e2e/test_stream_doc_async View Logs
test_streaming_e2e/test_stream_doc_async View Logs
test_streaming_e2e/test_stream_doc_async View Logs
test_streaming_e2e/test_stream_doc_collect_in_baml View Logs
test_streaming_e2e/test_stream_doc_collect_in_baml View Logs
test_streaming_e2e/test_stream_doc_collect_in_baml View Logs

Fix in Cursor

sxlijin added 3 commits July 10, 2026 17:30
…allbacks

Remove the legacy credential paths google-auth does not have: inline JSON
in GOOGLE_APPLICATION_CREDENTIALS, the BAML-specific
GOOGLE_APPLICATION_CREDENTIALS_CONTENT env var, the Vercel quoted-JSON
unwrap, and the `gcloud auth print-access-token` / `gcloud config get-value
project` shell-outs. The `credentials` option is now strictly a file path,
exactly like GOOGLE_APPLICATION_CREDENTIALS.

Inline credentials keep exactly one, explicit home: `credentials_content`,
retyped from string to `json | null` so it takes a real JSON object (a
pre-serialized JSON string still works). Resolution order is now:
options.credentials_content (inline JSON) -> options.credentials (file
path) -> Application Default Credentials.
Three parity fixes with google-auth (Python/Node):
- A set GOOGLE_APPLICATION_CREDENTIALS whose file cannot be read is now a
  hard error instead of silently falling through to the well-known file or
  metadata server.
- The well-known ADC config dir falls back to %APPDATA%\gcloud on Windows
  (after CLOUDSDK_CONFIG and HOME).
- The no-credentials error now says what was checked and points at
  `gcloud auth application-default login`, like DefaultCredentialsError.
Every call previously re-minted a token (fresh JWT sign + token-endpoint
round trip per request). Tokens are now cached process-wide, keyed by
SHA-256(credential material, scope) so the map never holds raw credentials
and distinct identities cannot collide, and reused until google-auth's
3m45s REFRESH_THRESHOLD before expiry. `expires_in` is parsed from token
responses; a response without one never expires (google-auth parity).

Internals refactor to support this: flows return a `Token {access_token,
expires_at}` and the public entry points are thin cache wrappers. In-file
MockIo tests that duplicated tests/auth_flows.rs are dropped in favor of the
integration suite; integration tests now use unique credential material per
test so the shared cache cannot leak tokens across tests.
sxlijin added 4 commits July 10, 2026 17:31
…d credentials

Extend the credential-type dispatch beyond service_account/authorized_user
to the remaining google-auth types BAML can support pure-Rust and wasm-safe:

- external_account (workload identity federation): file- and url-sourced
  subject tokens (text or JSON-field format), STS token exchange, optional
  service-account impersonation, Basic client auth, and the workforce-pool
  userProject option.
- impersonated_service_account: nested source credentials (service account
  or authorized user) exchanged at the IAM Credentials generateAccessToken
  endpoint, with delegates; expireTime (RFC 3339) feeds the token cache.
- external_account_authorized_user: workforce refresh grant against STS.

AWS-sourced federation, executable credential sources, and GDCH are
rejected with a clear AuthError::Unsupported. The dispatch is now public as
token_from_credentials_json, and the vertex `credentials` file option
routes through it, so a WIF or impersonation config file works anywhere
GOOGLE_APPLICATION_CREDENTIALS would.
Move project resolution into the fork and complete google-auth parity:
project_id() follows GOOGLE_CLOUD_PROJECT / legacy GCLOUD_PROJECT, the
GOOGLE_APPLICATION_CREDENTIALS file, the active gcloud configuration's
core.project (read from the config file on disk — the value google-auth
reports, without shelling out), the well-known ADC file's quota/project id,
then the GCE metadata server. quota_project_id() resolves
GOOGLE_CLOUD_QUOTA_PROJECT and credential-file quota_project_id.

The vertex consumer now delegates its project-id fallback chain to the fork
(dropping its local ADC-file/metadata reimplementation) and stamps
x-goog-user-project on requests when a quota project is configured,
matching google-auth Credentials.apply. Fork version bumped to 0.2.0.
Document the offline coverage added across the previous changes: WIF
(file/url, impersonation, workforce user-project), impersonated service
accounts, workforce refresh grants, APPDATA discovery, the GAC hard error,
token caching, and the project-id/quota-project chain. Offline tier is now
40 tests.
An env var set to the empty string was silently treated as unset
(`.filter(|s| !s.is_empty())` / `if !val.is_empty()`), hiding the
misconfiguration behind lower-priority sources. Set-but-empty values are
now honored verbatim so they fail visibly: GOOGLE_APPLICATION_CREDENTIALS=""
is a hard no-credentials error, GCLOUD_PROJECT="" yields an empty project
id (and a visibly broken request) instead of falling through, and
CLOUDSDK_CONFIG="" / HOME="" / APPDATA="" / GOOGLE_CLOUD_QUOTA_PROJECT="" /
CLOUDSDK_ACTIVE_CONFIG_NAME="" all take effect as written. Same for the
GOOGLE_CLOUD_QUOTA_PROJECT read in the vertex consumer and the systest
harness's NativeIo. (Deliberate divergence from google-auth, which treats
some empty vars as unset; documented in the crate docs.)
…tex-ai pointer

google-ai silently sent an unauthenticated request when no api_key was
configured (the server 401 was the only signal). Request construction now
fails fast in the vertex error style, offering both ways out: set
options.api_key (env.GOOGLE_API_KEY / env.GEMINI_API_KEY), or switch to the
vertex-ai provider with project_id + location to use Google Cloud
credentials — mirroring google-genai's "Missing key inputs argument!"
error, which likewise points at the Vertex backend.
sxlijin added 3 commits July 10, 2026 18:08
…ION / GOOGLE_CLOUD_PROJECT

Match google-genai: a vertex-ai client no longer needs location in BAML
options. When unset, the URL is built with a location placeholder (like the
existing project_id one) that auth resolves from GOOGLE_CLOUD_LOCATION,
handling the region-less "global" endpoint host. project_id already
resolved through GOOGLE_CLOUD_PROJECT via the credential chain. The
compile-time "requires either base_url or location" diagnostic is removed —
the compiler cannot see the env var — and a client with neither errors at
$build_request with an actionable message naming both fixes.
…rtex backend

google-genai parity for the backend switch: when GOOGLE_GENAI_USE_VERTEXAI
is "true"/"1", a google-ai client builds a Vertex request instead — Vertex
URL (location/project from GOOGLE_CLOUD_LOCATION / GOOGLE_CLOUD_PROJECT or
the credential chain), Google Cloud credentials via the ADC chain, and
bearer auth — exactly like `vertexai=True` in the Python SDK. The google-ai
default base_url is recognized and ignored on the Vertex path so the flip
does not send bearer tokens to generativelanguage. The missing-api_key
error now also mentions this env-only route. With this, an ADK-style env
setup (GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_CLOUD_PROJECT +
GOOGLE_CLOUD_LOCATION + gcloud ADC) works with provider google-ai and no
BAML option changes.
Four hermetic scenarios through real BAML programs calling $build_request
(one test fn: the scenarios mutate real Google env vars, and this file is
its own test binary, so nothing races them; all scenarios are network-free):

- google-ai with `api_key env.GOOGLE_API_KEY` unset: the strict env read
  fails naming the var; with no api_key at all, the fail-fast error points
  at vertex-ai and GOOGLE_GENAI_USE_VERTEXAI.
- google-ai with GOOGLE_GENAI_USE_VERTEXAI=true: builds a Vertex URL with
  location/project from GOOGLE_CLOUD_LOCATION / GOOGLE_CLOUD_PROJECT
  (express-mode query key keeps it token-free). This caught a real bug,
  fixed in the location-placeholder change: url::Url lowercases the host
  when query params are appended, so the placeholder must be lowercase.
- vertex-ai, GOOGLE_CLOUD_PROJECT set, GOOGLE_CLOUD_LOCATION unset:
  actionable location error naming options.location and the env var.
- vertex-ai, both unset: same location-first error, before any
  credential IO.
… resolution

project_id_from_credentials swallowed an unreadable options.credentials
path and fell through to the env/ADC project chain. On paths that only
need the project-id placeholder — express-mode API-key auth mints no token
— the broken file was completely masked and the request went out with a
project from the environment. The file read now reuses
read_credentials_file, so a bad path surfaces the same "failed to open
credentials file" error everywhere it is consulted.
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.

1 participant