Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLI
Assigneesjohn

Relationships

#461 swamp CLI: send user/device identity on extension-registry HTTP calls

Opened by john · 5/27/2026· Shipped 5/27/2026

Problem

CLI-initiated HTTP traffic to swamp.club (extension pulls, metadata lookups, checksum verifies) is anonymous at the HTTP layer and therefore unattributable in server-side telemetry, even when the CLI is running on a logged-in user's machine.

Concrete: when I ran swamp extension pull @webframp/cloudflare just now from a machine where I'm logged in as john, the resulting three HTTP requests landed on the server like this:

target=/api/v1/extensions/@webframp/cloudflare                              auth=anonymous  user=  distinct_id=anon_nquhxl
target=/api/v1/extensions/@webframp/cloudflare@2026.05.27.1/download       auth=anonymous  user=  distinct_id=anon_nquhxl
target=/api/v1/extensions/@webframp/cloudflare@2026.05.27.1/checksum       auth=anonymous  user=  distinct_id=anon_nquhxl

anon_nquhxl is a per-request hash the server computes from request headers (IP + UA). It's not stable across invocations from the same device — every CLI call produces a different anon_* ID. So per-user and per-device attribution are both impossible.

Traces in Axiom: download, checksum, metadata.

Why it matters

With this gap closed we'd be able to answer (from telemetry alone):

  • Which user pulled @foo/bar and how often?
  • Which version of an extension does a given operative tend to install?
  • Are publishes by user X correlated with pulls by users Y, Z?
  • Per-user consumer.stats.publish latency — which heavy users are driving the p99? (the consumer-side question we were ultimately trying to answer with the recent observability work)

Today none of these are answerable for CLI traffic. Web-app traffic already attributes correctly because BetterAuth sessions ride the Cookie header.

Current state on the server

The swamp-club Fresh middleware (routes/_middleware.ts) already accepts three forms of auth on /api/*:

  • Authorization: Bearer swamp_<personal-key> → resolved via BetterAuth's verifyApiKey, stamps user.id + user.username
  • Authorization: Bearer swamp_org_<collective-key> → stamps collective.id + collective.slug
  • x-api-key: <key> → same as Bearer

No retro server-side changes are needed for the personal-key path — it's been live the whole time. The CLI just isn't using it.

Proposed change

The CLI should send identity on extension-registry HTTP calls. Two reasonable shapes (could land in either order, or both):

Shape A — Authoritative identity when logged in When the user has a swamp auth login session, attach Authorization: Bearer swamp_<personal-key> to all swamp.club/api/* requests (pulls, checksums, metadata, search, …). Server already stamps user.id / user.username on the span and the existing OTel baggage propagation (PRs #601 + #602) will carry that identity through to repo / S3 / downstream-service spans automatically — so the per-user "what did john pull?" query starts working immediately.

Shape B — Stable device identity when not logged in For anonymous users (or for CLI calls that intentionally don't carry the user token), send a stable per-device X-Distinct-Id header generated and persisted by the CLI (same value already in the body of cli_invocation telemetry events). The server-side middleware prefers this over the per-request anon_* hash. That makes attribution work device-level even pre-login, and matches the existing distinct_id-in-event-body convention.

Shape B is the smaller change and likely lands first; Shape A is the fuller fix and matches what every other authenticated HTTP client in the ecosystem does.

Surface to look at on the CLI side

Wherever the CLI builds the fetch() call for extension pulls / checksums (probably a shared client.ts or similar wrapper around swamp.club/api/v1/extensions/...). Whatever already constructs the /ingest telemetry POST body is the place that knows the distinct_id for Shape B, and whatever already implements swamp auth login knows the bearer token for Shape A.

Out of scope

  • Auth on the /ingest endpoint specifically — telemetry events already carry distinct_id in their body, and the server-side identity_map resolves username from that asynchronously. This issue is only about the extension-fetch HTTP traffic.
  • Forcing login. Shape B explicitly preserves anonymous-but-attributed flows for users who haven't run swamp auth login.

Background

This came out of a multi-PR observability sweep on swamp-club ( #597, #599, #601, #602) that got identity (user.username, user.id, distinct_id) propagating automatically through every server span via OTel baggage + the AsyncLocalStorageContextManager fix. The server-side story is now complete — this is the remaining gap that lives on the CLI side.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 12 MOREFINDINGS+ 3 MOREPR_MERGEDSHIPPED

Shipped

5/27/2026, 7:39:31 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
john assigned john5/27/2026, 5:01:19 PM

Sign in to post a ripple.