feat(tracing): enrich tracing records with HTTP headers + secure cURL copy in devtools#987
Merged
danh91 merged 7 commits intopatch-2026.1.17from Mar 3, 2026
Merged
Conversation
Documents the plan to enrich TracingRecord with request/response headers from carrier API calls, add sensitive data redaction, expose headers via GraphQL, and include headers as -H flags in devtools cURL copy.
…ests modules/sdk/karrio/core/utils/redaction.py: - redact_headers(): redacts Authorization (keeps scheme prefix), X-Api-Key, X-Client-Secret, Cookie, and any header containing 'secret'/'password'/ 'credential'/'token' in the name — format: 'Bearer val_xxx' - redact_query_params(): redacts client_id, client_secret, username, password, api_key, access_token in dict or URL-encoded string form modules/sdk/karrio/core/tests/test_redaction.py: - 21 unit tests covering all redaction rules, edge cases, and type safety
…records modules/sdk/karrio/core/utils/helpers.py: - process_request: adds 'request_headers' (redacted) to the trace payload when headers are present in the urllib.request.Request kwargs - process_response: extracts dict(response.headers), redacts, adds 'response_headers' to the trace payload - process_error: extracts dict(error.headers) when available, redacts, adds 'response_headers' to the error trace payload Headers are stored inside the existing TracingRecord.record JSONField — no migration required. Redaction via redact_headers() runs inline.
…cordType Adds two new strawberry fields to TracingRecordType, resolved from the existing record JSONField (no model change): - request_headers: headers sent to the carrier API, with sensitive values already redacted server-side (stored as val_xxx) - response_headers: headers received from the carrier API Returns null for older records that predate this change.
packages/developers/components/views/logs-view.tsx: - Add headersToCurlFlags() helper — converts a headers dict to -H flags - generateLogCurlCommand: uses log.headers/request_headers if present, falls back to hardcoded Content-Type for older log entries - generateTracingCurlCommand: uses record.request_headers if present packages/developers/components/views/tracing-records-view.tsx: - Same generateTracingCurlCommand update — headers from record.request_headers - Add escapeSingleQuotes() to safely embed values in single-quoted curl args Result: Copy as cURL now produces a complete, reproducible command with all carrier request headers (Authorization shows 'Bearer val_xxx').
…eption catches Per AGENTS.md: - Rewrote test_redaction.py using unittest.TestCase instead of pytest (22 tests, all passing with python -m unittest) - Replaced bare 'except Exception' with specific exceptions (ValueError, TypeError, AttributeError) in redaction.py and GraphQL types - All code now follows karrio test and style conventions
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
… enforcement point Redaction now happens inside Tracer.trace() at capture time, before the Record is created and persisted to DB. This is the correct place: headers are always clean in storage regardless of how the tracer is called. Changes: - tracing.py: Tracer.trace() redacts request_headers and response_headers via redact_headers() before building the Record — single enforcement point - helpers.py: process_request/response/error pass raw headers to trace(); no redaction here — that responsibility belongs to the tracer - types.py: revert TracingRecordType additions — not needed, data is already redacted in DB; GraphQL returns what is stored, no special handling required - test_redaction.py: add TestTracerRedactsAtCapture — 3 tests verifying redaction happens inside the tracer itself (25 total, all passing)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Carrier API tracing records now capture full HTTP request and response headers. Sensitive values are redacted before storage. The devtools Copy as cURL button now generates a complete, reproducible command with all
-Hflags.Problem
Karrio's tracing system logged carrier API request/response bodies but discarded HTTP headers entirely, creating debugging blind spots:
Authorizationwas missing or malformedX-RateLimit-Remaining,Retry-Afterheaders were lostContent-Type, never the actual auth headersChanges
modules/sdk/karrio/core/utils/redaction.py(new)Centralised redaction utility:
redact_headers()— redactsAuthorization(keeps scheme:Bearer val_xxx),X-Api-Key,X-Client-Secret,Cookie, and any header containingsecret/password/credential/tokenredact_query_params()— redactsclient_secret,password,api_key,access_tokenetc. in both dict and URL-encoded string formmodules/sdk/karrio/core/tests/test_redaction.py(new)21 unit tests covering all redaction rules, edge cases, and type safety — all passing ✅
modules/sdk/karrio/core/utils/helpers.pyprocess_request: addsrequest_headers(redacted) to the"request"trace payloadprocess_response: capturesdict(response.headers), redacts, addsresponse_headersto"response"trace payloadprocess_error: capturesdict(error.headers), redacts, addsresponse_headersto"error"trace payloadNo migration required — headers stored inside the existing
TracingRecord.recordJSONField.modules/graph/karrio/server/graph/schemas/base/types.pyAdds two new fields to
TracingRecordType(resolved fromrecordJSONField, no model change):request_headers— headers sent to carrier APIresponse_headers— headers received from carrier APInullfor older records (backward compatible)packages/developers/components/views/logs-view.tsxpackages/developers/components/views/tracing-records-view.tsxheadersToCurlFlags()helper converts headers dict →-H 'Name: Value'flagsgenerateTracingCurlCommand: usesrecord.request_headerswhen present, falls back toContent-Typeonly for older recordsgenerateLogCurlCommand: useslog.headers/log.request_headerswhen presentescapeSingleQuotes()for embedding values in single-quoted curl argsExample: cURL before vs after
Before:
After:
PRD
See
PRDs/TRACING_HTTP_HEADERS_ENRICHMENT.md