Skip to content

v0.3.0

Choose a tag to compare

@apstndb apstndb released this 12 Jul 17:13
1839741

Summary

v0.3.0 makes authenticated clients fail closed around credential discovery and request origins, corrects API error classification, and gives NormalizeDocName a strict invalid-input contract.

This release contains PR #21.

Breaking changes

Authenticated requests are origin-bound

  • Client.DoAPIRequest, DoGet, and DoJSONPost now require the request URL to share the validated origin of Client.BaseURL.
  • Clients returned by NewAuthenticatedHTTPClient and NewADCHTTPClient restrict initial requests and redirects to AuthConfig.AllowedOrigin, which defaults to DefaultV1BaseURL.
  • Redirects during Client requests are same-origin-restricted even with a caller-supplied HTTPClient; a custom CheckRedirect callback is chained, not replaced.
  • Origins must be canonical, hierarchical ASCII HTTP(S) URLs without userinfo. Request Host overrides are also validated.

Migration: set AuthConfig.AllowedOrigin when a constructor-created authenticated client targets a non-default endpoint. A client used for https://apikeys.googleapis.com, for example, must explicitly allow that origin.

Explicit credential paths are strict

AuthConfig.CredentialsPath is evaluated exactly once and is now an explicit credential source. Missing, unreadable, malformed, or otherwise invalid files return an error instead of falling back to another ADC source.

Migration: omit CredentialsPath when standard platform or metadata-server ADC fallback is desired. Do not pass DefaultCredentialsPath merely to restate the default lookup behavior.

NormalizeDocName rejects invalid URL-like input

Empty or invalid input now returns "". URL-like input must be a hierarchical ASCII HTTP(S) URL without userinfo. Unsupported schemes, opaque URLs, protocol-relative URLs, malformed authorities, bracketed DNS/IPv4 authorities, and Unicode hostnames are rejected. Valid scheme-less host:port paths, including query- or fragment-only forms, and bracketed IPv6 paths remain supported.

For accepted URLs, hostnames are lowercased, default ports are stripped, percent-encoded path segments are preserved rather than decoded, and trailing slashes are removed. Callers that cache or compare normalized names may observe different strings after upgrading.

Migration: check for an empty result before sending the normalized resource name to the API.

APIError.Code is always the HTTP status

APIError.Code now comes from the HTTP response status rather than the JSON error.code field. IsBisectableDocumentError now requires the exact matched pairs 400 + INVALID_ARGUMENT or 404 + NOT_FOUND.

external_account credentials no longer require a quota project

Only authorized_user credentials require a quota project during client construction. external_account credentials can be used without one; when present, their quota_project_id is still honored.

Ambient CLOUDSDK_CONFIG errors are distinguished from absence

When the ADC file under CLOUDSDK_CONFIG exists, its bytes provide both the token source and quota-project metadata. Pure file absence continues to standard ADC discovery; permission failures, non-directory paths, dangling symlinks, malformed credentials, and other read errors are returned.

Additions

  • AuthConfig.AllowedOrigin configures the only origin that a constructor-created authenticated client may contact.
  • AuthConfig.QuotaProjectID explicitly configures x-goog-user-project and takes precedence over GOOGLE_CLOUD_QUOTA_PROJECT and credential-file metadata.

Fixes and hardening

  • Token sources and quota-project metadata are derived from the same credential bytes, avoiding mixed credential sources.
  • A custom AuthConfig.TokenSource no longer consults CredentialsPath or ambient credential-file metadata.
  • Rejected transport requests close their request bodies without invoking the wrapped transport.
  • Nil origins return an error instead of panicking.
  • CloseIdleConnections is delegated through the origin and quota-project transports.
  • Redirect callbacks are chained and revalidated after callback mutations.
  • URL authority validation covers empty and out-of-range ports, non-canonical brackets, IPv6, Unicode case folding, userinfo, opaque URLs, and Request.Host overrides.
  • CI asks actions/setup-go for the latest patch release before govulncheck, preventing stale hosted-toolcache versions from reintroducing fixed standard-library vulnerabilities.

Upgrade notes

Consumers upgrading directly from v0.1.x must also apply the context-first API migration documented in the v0.2.0 release notes.

go get github.com/apstndb/developerknowledge-go@v0.3.0

Verification

  • go test -race ./...
  • go vet ./...
  • golangci-lint run
  • govulncheck ./...
  • GitHub Actions on Go 1.24 and Go 1.25
  • Live v1 documents:batchGet: 20 names succeed; 21 names return 400 INVALID_ARGUMENT, so MaxBatchGetDocuments remains 20

Not included

  • The open retry-policy expansion and golang.org/x/oauth2 update are not part of this release.

Full diff: v0.2.0...v0.3.0

Release notes updated 2026-07-13 to clarify normalization output and redirect behavior; the v0.3.0 tag is unchanged.