# Execution: GCP HTTP wire logging at V(5) Plan: `docs/plans/2026-08-11-1838-gcp-http-wire-logging-v5.md` - [x] Step 1 — `wireLogger` + `option.WithLogger` wiring in `internal/provider/gcp/gcp.go` - [x] Step 2 — Tests (`TestWireLogger_gatesAtV5`, `TestWireLogger_infoLandsAtV1`) - [x] Step 3 — Live verification at `--zap-log-level=5` (user, on cluster) - [x] Step 3b — Post-verification fix: drop auth records, elide huge fields - [ ] Step 4 — CHANGELOG entry (after live confirmation of 3b; batch with the two earlier pending entries: GCP V-logging, version stamp) ## Steps 1–2 Went exactly as planned — the whole feature is ~10 lines of production code because both halves already existed: the compute SDK logs full HTTP request/response records at slog Debug to an injectable logger, and `logr.ToSlogHandler` does the slog→logr bridging. The only real design content is the level shift (`base.V(1)` + slog-Debug's +4 = V(5)) and the startup warning line when V(5) is active (raw payloads include cloud-init user-data, which the curated V(2) logging deliberately hides). Worth noting for future readers: - `option.WithLogger` **disables** `GOOGLE_SDK_GO_LOGGING_LEVEL` for this client (documented SDK precedence) — `--zap-log-level` is now the only knob for GCP wire logs. - The V(5) check in `New` runs once at startup; that is sound because the zap level is fixed by flags at process start. - Added `TestWireLogger_infoLandsAtV1` beyond the plan's table — it pins the shift arithmetic from the other side (slog Info → V(1)), so a future logr mapping change would fail loudly. Verified with: ```bash go test -race ./internal/provider/gcp/ go build ./... && go test ./... ``` ## Step 3b — what live verification exposed, and the fix Live V(5) output revealed two problems the plan missed: 1. **Security: the injected logger propagates into `cloud.google.com/go/auth`**, which logs its own token exchange (`auth.go:571/576`) — signed JWT assertion in the request, full bearer access token in the response. The plan's "auth token is safe" analysis only covered the compute client's request headers, not the auth library's own records. Fix: `wireLogger` now wraps the handler in a filter that drops every Debug record except the compute client's `"api request"`/`"api response"` (allowlist, so future SDK additions fail closed); Warn/Error still pass through. 2. **Readability: GCP responses embed multi-KB blobs** (Shielded-VM UEFI dbx databases) that swamp the line. Fix: string fields >1KiB are elided to `[elided N bytes]` by default, recursively through payload maps/arrays. Opt-out via new manager flag `--gcp-wire-log-full-payloads` (threaded through a constructor closure in `cmd/main.go` → `gcp.NewWithWireOptions`; the `registry.Constructor` signature stays unchanged). Chosen by the user: elision on by default, verbatim available on demand. Auth records are dropped in both modes. The filter/elision logic lives in `internal/provider/gcp/wirelog.go` with tests covering: auth-record drop (both modes), elision marker + small-field preservation, verbatim mode, and the original V(5) gating.