Skip to content

feat(client): forward APIMUX_CALLER_CTX_* env vars as X-Apimux-Caller-Ctx-* headers#16

Merged
skadai merged 1 commit into
developfrom
feat/billing-webhook-headers
Jun 7, 2026
Merged

feat(client): forward APIMUX_CALLER_CTX_* env vars as X-Apimux-Caller-Ctx-* headers#16
skadai merged 1 commit into
developfrom
feat/billing-webhook-headers

Conversation

@skadai

@skadai skadai commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

apimux's billing-webhook fan-out (kamay/apimux!69) only fires when the request carries at least one X-Apimux-Caller-Ctx-* header. The CLI must participate transparently so subprocess callers (kamay-agent's Claude Bash tool, future partners) can inject attribution context without depending on CLI version upgrades when their schema evolves.

Scan the process environment for the APIMUX_CALLER_CTX_ prefix and copy each non-empty value to the matching header. The prefix → header mapping is intentionally generic — this CLI has no compile-time knowledge of which keys downstreams use; apimux groups them into a single opaque caller_context jsonb on its side.

Wire shape

APIMUX_CALLER_CTX_USER_ID="usr_x"    → X-Apimux-Caller-Ctx-User-Id: usr_x       → caller_context["user_id"]
APIMUX_CALLER_CTX_RUN_TAG="smoke"    → X-Apimux-Caller-Ctx-Run-Tag: smoke       → caller_context["run_tag"]
APIMUX_CALLER_CTX_<anything>=<value> → X-Apimux-Caller-Ctx-<Anything>: <value>  → caller_context["<anything>"]

Whitespace-only values are dropped (treated as "header absent"); apimux records SQL NULL when no headers are sent.

Test plan

  • go test ./internal/client/... — five new tests covering full set / empty set / partial / whitespace trim / arbitrary unknown key
  • Manual smoke against a local apimux service: built CLI binary, ran apimux reddit search --query x with APIMUX_CALLER_CTX_USER_ID=usr_via_cli APIMUX_CALLER_CTX_RUN_TAG=cli-smoke-1, verified api_call_logs.caller_context = {"user_id":"usr_via_cli","run_tag":"cli-smoke-1",...} and the webhook receiver got the matching nested caller_context object

Rollout coupling

This PR is not consumed in isolation:

  • apimux-service must ship kamay/apimux!69 first (extracts these headers, persists to jsonb)
  • kamay-agent must set the APIMUX_CALLER_CTX_* env vars when spawning the Claude SDK (their MR coming separately)

Each can ship out of order safely: missing headers → apimux just records SQL NULL → behavior identical to no-webhook today.

…-Ctx-* headers

apimux-service collects any X-Apimux-Caller-Ctx-* header into the per-call
caller_context jsonb that drives the billing-webhook fan-out. The CLI must
participate transparently so subprocess callers (kamay-agent, future
partners) can inject attribution context without depending on CLI version
upgrades when their schema evolves.

Scan the process environment for the APIMUX_CALLER_CTX_ prefix and copy
each non-empty value to the matching header (trimmed; whitespace-only
treated as absent). The prefix → header mapping is intentionally generic
— this CLI has no compile-time knowledge of which keys downstreams use.
@skadai skadai merged commit c9f0002 into develop Jun 7, 2026
1 check passed
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