v0.3.0
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, andDoJSONPostnow require the request URL to share the validated origin ofClient.BaseURL.- Clients returned by
NewAuthenticatedHTTPClientandNewADCHTTPClientrestrict initial requests and redirects toAuthConfig.AllowedOrigin, which defaults toDefaultV1BaseURL. - Redirects during
Clientrequests are same-origin-restricted even with a caller-suppliedHTTPClient; a customCheckRedirectcallback is chained, not replaced. - Origins must be canonical, hierarchical ASCII HTTP(S) URLs without userinfo. Request
Hostoverrides 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.AllowedOriginconfigures the only origin that a constructor-created authenticated client may contact.AuthConfig.QuotaProjectIDexplicitly configuresx-goog-user-projectand takes precedence overGOOGLE_CLOUD_QUOTA_PROJECTand 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.TokenSourceno longer consultsCredentialsPathor ambient credential-file metadata. - Rejected transport requests close their request bodies without invoking the wrapped transport.
- Nil origins return an error instead of panicking.
CloseIdleConnectionsis 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.Hostoverrides. - CI asks
actions/setup-gofor the latest patch release beforegovulncheck, 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.0Verification
go test -race ./...go vet ./...golangci-lint rungovulncheck ./...- GitHub Actions on Go 1.24 and Go 1.25
- Live v1
documents:batchGet: 20 names succeed; 21 names return400 INVALID_ARGUMENT, soMaxBatchGetDocumentsremains 20
Not included
- The open retry-policy expansion and
golang.org/x/oauth2update 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.