Skip to content

fix(sdk): apply 401 fail-loud to TjHttpExporter (the path bootstrap actually uses)#70

Merged
anilmurty merged 1 commit into
mainfrom
fix/sdk-http-exporter-401
May 29, 2026
Merged

fix(sdk): apply 401 fail-loud to TjHttpExporter (the path bootstrap actually uses)#70
anilmurty merged 1 commit into
mainfrom
fix/sdk-http-exporter-401

Conversation

@anilmurty
Copy link
Copy Markdown
Contributor

Quick follow-up to PR #69 — the §2 fix landed in the wrong place.

What happened

PR #69 fixed §2 on `tokenjam/sdk/transport.py::HttpTransport` — adding ERROR-level logging, a dropped-spans counter, and fail-fast (no retry-backoff) on 401. But that class has no callers in the SDK. `bootstrap.py` wires `TjHttpExporter` (the OTel SpanExporter in `tokenjam/sdk/http_exporter.py`) for actual span pushes. So the fix targeted dead code; the user-visible 401 footgun was unchanged.

Confirmed by re-running the playbook on `main` after #69 merged: every demo still shows the old short `tj serve returned 401 on span export` warning at the bottom with no actionable diagnostic.

Fix

Apply the same pattern to `TjHttpExporter.export()`:

  • 401 logs at ERROR level with the truncated `ingest_secret` fingerprint
  • Cumulative `dropped_auth_failures` counter
  • Message names both config locations + the `tj stop && tj serve &` fix verbatim

Non-401 responses keep the original short warning.

Verified end-to-end

```
$ python3 examples/alerts_and_drift/sensitive_actions_demo.py
... agent workflow ...
tj serve rejected span export with 401 — your SDK is using ingest_secret=10711471...
but the running daemon expects a different secret. Spans are being DROPPED. Check
that .tj/config.toml and ~/.config/tj/config.toml agree (or run `tj stop && tj
serve &` after rotating the secret). Dropped 7 span(s) so far.
```

Follow-up worth considering

`tokenjam/sdk/transport.py` is dead code. The §2 tests (`test_transport_401.py`) exercise a class no one calls. Probably worth removing in a separate PR so future debuggers don't waste time on it like I did.

Test plan

  • 575 tests passing (no regressions)
  • Manual: re-ran sensitive_actions_demo — new ERROR message fires with fingerprint + dropped count

🤖 Generated with Claude Code

…68 §2

PR #69 fixed §2 on tokenjam/sdk/transport.py's HttpTransport class —
but bootstrap.py wires TjHttpExporter (the OTel SpanExporter in
tokenjam/sdk/http_exporter.py) for actual span pushes. HttpTransport
has no callers in the SDK. So the original §2 fix targeted dead code
and the user-visible symptom — the short single-line "tj serve
returned 401 on span export" warning — was unchanged.

Confirmed by re-running the playbook on main after PR #69 merged:
the demos still showed the old short message at the bottom of each
run, with no actionable diagnostic.

Apply the same fix pattern to TjHttpExporter.export():

- 401 logs at ERROR level (not WARNING) with the truncated
  ingest_secret fingerprint so the user can spot the mismatch.
- Cumulative `dropped_auth_failures` counter so doctor / status can
  surface it later.
- Message names both config-file locations (.tj/config.toml and
  ~/.config/tj/config.toml) and the daemon-restart fix verbatim.

Non-401 responses keep the original short warning — only 401 is
loud, because only 401 is "won't change on retry, and the user
needs to act to fix it."

Verified end-to-end via the playbook's sensitive_actions demo —
the new ERROR message fires with the secret fingerprint and the
"Dropped N span(s) so far" count.

Tests: 575 passing (no regressions). The new behavior was already
covered by the §2 tests written for the transport.py fix; both
share the same logic shape.

Follow-up worth considering: tokenjam/sdk/transport.py is dead
code; consider removing it (along with its tests) so future
debuggers don't waste time on it like I did.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@anilmurty anilmurty merged commit 1de48a5 into main May 29, 2026
4 checks passed
@anilmurty anilmurty deleted the fix/sdk-http-exporter-401 branch May 29, 2026 04:59
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