Skip to content

feat(client): emit X-DevHelm-Surface telemetry headers#14

Merged
caballeto merged 1 commit into
mainfrom
feat/surface-telemetry
May 1, 2026
Merged

feat(client): emit X-DevHelm-Surface telemetry headers#14
caballeto merged 1 commit into
mainfrom
feat/surface-telemetry

Conversation

@caballeto
Copy link
Copy Markdown
Member

Summary

Reports the Terraform provider's identity to the DevHelm API on every authenticated request so the GTM rollup can attribute usage to the provider vs. SDKs / MCP / CLI. Wire contract documented at https://devhelm.io/telemetry; the matching API-side handler shipped in `devhelmhq/mono#332`.

What lands on the wire (defaults)

Header Value
`X-DevHelm-Surface` `tf`
`X-DevHelm-Surface-Version` provider version (already wired into `NewClient` from `main.version`, ldflags-overridden at release)
`X-DevHelm-Tf-Os` `-` (e.g. `darwin-arm64`, `linux-amd64`)

Opt-out

`DEVHELM_TELEMETRY=0` returns `nil` from `buildSurfaceHeaders` and the API receives no surface signal at all. Single env var, not a provider attribute. Auth + tenant + User-Agent headers are unaffected. Strict equality on `"0"` (so `DEVHELM_TELEMETRY=on` / `true` / `yes` don't accidentally read as opt-out).

Zero callsite changes

Headers are computed once in `NewClient` and applied uniformly inside `doRequestOnce` alongside the existing static headers (`Authorization`, `x-phelm-org-id`, `User-Agent`). Every existing resource using `api.Client` keeps working unchanged.

Tests

  • 3 new tests in `internal/api/surface_telemetry_test.go` using `httptest.Server` to capture the outbound request and assert headers
    • default emit
    • `DEVHELM_TELEMETRY=0` strips every `X-DevHelm-Surface*` header but keeps `Authorization`
    • strict-on-`"0"` parsing (table-driven across `1` / `on` / `true` / `false` / `yes`)
  • All existing client tests unaffected
  • `golangci-lint run ./...` clean

Test plan

  • `make build` — clean
  • `make test` — green
  • `make lint` — `0 issues`
  • Post-release: `terraform apply` against stage; verify the `org_surface_usage` row + `tf_provider_first_apply` PostHog event

Made with Cursor

Adds Terraform-provider surface identification to every authenticated API
call so the GTM rollup can attribute usage to the provider vs. SDKs / MCP /
CLI. Wire contract docs at https://devhelm.io/telemetry; matching API-side
handler in mono#332.

Headers emitted by default (every request):
- X-DevHelm-Surface: tf
- X-DevHelm-Surface-Version: provider version (already passed into
  NewClient via main.go ldflags-overridden const, no extra plumbing)
- X-DevHelm-Tf-Os: <GOOS>-<GOARCH> (e.g. darwin-arm64). Helps the
  platform team prioritise binary builds. Cheap to ship — runtime
  values are already constants once the binary is built.

Opt-out is a single env var, not a provider attribute: DEVHELM_TELEMETRY=0
returns nil from buildSurfaceHeaders and the API receives no surface
signal at all. Auth + tenant + User-Agent headers are unaffected. Strict
equality on "0" so DEVHELM_TELEMETRY=on / true / yes don't accidentally
read as opt-out.

Zero callsite changes — headers are computed once in NewClient and
applied uniformly in doRequestOnce alongside the existing static headers.
Every existing resource using the api.Client keeps working unchanged.

Tests: 3 new tests in internal/api/surface_telemetry_test.go using
httptest.Server to capture the outbound request and assert headers
(default emit, opt-out, strict-on-"0" parsing). Existing client tests
unaffected. golangci-lint clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
@caballeto caballeto merged commit 73950d5 into main May 1, 2026
6 checks passed
@caballeto caballeto deleted the feat/surface-telemetry branch May 1, 2026 17:24
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