Skip to content

feat(internal): shared venue HTTP transport + secret redaction (06-01 PR1)#36

Merged
imbingox merged 5 commits into
mainfrom
feat/shared-venue-infrastructure
Jun 2, 2026
Merged

feat(internal): shared venue HTTP transport + secret redaction (06-01 PR1)#36
imbingox merged 5 commits into
mainfrom
feat/shared-venue-infrastructure

Conversation

@imbingox

@imbingox imbingox commented Jun 2, 2026

Copy link
Copy Markdown
Owner

范围

06-01 共享 venue 基础设施的 PR1:抽出 venue-agnostic 的内部 REST 传输层并迁移现有 adapter。PR2(统一 TimeProvider)与 PR3(rate limiter)不在本 PR。

改动

  • 新增 src/internal/http-client.tshttpRequest + typed TransportErrorkind/retryable/attempts)+ isTransportError 鸭子 guard(避开跨 bundle instanceof)+ redactSecrets / redactUrl / parseRetryAfterMs
  • 迁移:binance market-catalog、binance private-adapter、juplend private-adapter 全部改走共享 client;PrivateSubscriptionCoordinator 的 bootstrap 错误经 redactSecrets 再进 public AcexError
  • per-call 幂等:重试性由调用点显式声明 —— NO_RETRY_POLICY(下单/撤单)、SAFE_READ_RETRY_POLICY(只读 GET)、LISTEN_KEY_KEEPALIVE_RETRY_POLICY。写操作零重试。
  • D5 错误脱敏(安全):错误的 url / message / rawBody 都不再泄漏 signature / apiKey / listenKey / token / passphrase;venue 注入的 messages 回调只拿得到已脱敏的输入。
  • 限流拆分:429/418 归类为 rate_limited 并解析 Retry-After,但不重试、不 sleep(主动退避属 PR3)。

等价性

三处 adapter 迁移保持行为等价(method / 重试语义 / 错误 message 文案逐端点核对),唯一 intended diff 是脱敏带来的 message 变化。等价矩阵见 .trellis/tasks/06-01-shared-venue-infrastructure/pr1-equivalence-matrix.md

契约

新增 spec:adapter-contract.md 的「共享 HTTP 传输客户端」Scenario(§3.11–3.16)。

测试

  • bun run lint(biome)✅
  • bun run type-check(tsc --noEmit)✅
  • bun run test94 pass / 0 fail / 423 expect()

Release

patch changeset(beta pre-release):「错误信息不再泄漏签名与密钥」—— 向后兼容行为修复,不改公共类型 / API 形状。

Commits

  • d9bacb6 feat(internal): add shared HTTP transport with secret redaction; migrate binance/juplend adapters
  • df49fa1 docs(spec): document shared HTTP transport contract (REST skeleton, per-call idempotency, redaction)
  • 362b6b5 chore(task): record 06-01 shared venue infrastructure PR1
  • 827a185 chore: record journal

Summary by CodeRabbit

  • New Features

    • Introduced a unified HTTP transport used across adapters for consistent retries, timeouts, and error classification.
  • Bug Fixes

    • External error messages and URLs no longer expose sensitive auth data (signatures, API keys, tokens, etc.); such values are redacted.
  • Documentation

    • Added detailed adapter/transport specs, PRD, and migration checklists covering retry, rate-limit, and redaction behavior.
  • Tests

    • Added unit and integration tests validating transport behavior, redaction, and rate-limit handling.

imbingox added 4 commits June 2, 2026 05:20
…ate binance/juplend adapters

PR1 of 06-01 shared venue infrastructure: extract a venue-agnostic REST
transport (src/internal/http-client.ts) and migrate binance catalog,
binance private adapter, and juplend adapter onto it.

- typed TransportError (kind/retryable/attempts) + isTransportError duck-type guard
- per-call retry policy declared at call site: NO_RETRY for orders, SAFE_READ for GETs
- secret redaction on error url/message/rawBody (signature/apiKey/listenKey/token)
- 429/418 classified as rate_limited + Retry-After parsed, but no retry/sleep
- coordinator bootstrap errors re-redacted before AcexError
- rate limiter and unified time provider deferred to PR3/PR2
…er-call idempotency, redaction)

Add a new Scenario to adapter-contract.md covering src/internal/http-client.ts:
venue-injected URL/signing, per-call retry policy (NO_RETRY for writes), typed
TransportError instead of AcexError, and the D5 secret-redaction guarantee on
error url/message/rawBody. Rate limiter / time provider noted as PR3/PR2 scope.
Update backend index entry + change-trigger.
Task artifacts for PR1: prd, implement/check jsonl phases, codex prd review,
and the REST migration equivalence matrix.
Session 17: shared venue infrastructure PR1 (REST skeleton + secret redaction).
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 63e8554f-e555-4a6a-a078-fe9cdc56ea16

📥 Commits

Reviewing files that changed from the base of the PR and between 827a185 and aca1cc0.

📒 Files selected for processing (4)
  • src/adapters/binance/private-adapter.ts
  • src/adapters/juplend/private-adapter.ts
  • src/internal/http-client.ts
  • tests/unit/http-client.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/adapters/binance/private-adapter.ts
  • src/adapters/juplend/private-adapter.ts
  • src/internal/http-client.ts

📝 Walkthrough

Walkthrough

Adds a shared TypeScript HTTP client with typed TransportError, secret redaction, retry/backoff and timeout behavior; migrates Binance (catalog & private) and Juplend adapters to use it; maps transport error kinds to runtime reasons in the private subscription coordinator; updates tests, docs, and task tracking.

Changes

Shared venue HTTP infrastructure

Layer / File(s) Summary
HTTP transport contract and specification
.trellis/spec/backend/adapter-contract.md, .trellis/spec/backend/index.md, .trellis/tasks/06-01-shared-venue-infrastructure/prd.md, .trellis/tasks/06-01-shared-venue-infrastructure/pr1-equivalence-matrix.md, .changeset/redact-transport-error-secrets.md
Spec and PRD documents define the shared httpRequest contract, typed TransportError, redaction rules (D5), per-call idempotency/retry policy requirements, and verification/checklist items.
Shared HTTP client implementation
src/internal/http-client.ts
New module exposing httpRequest, TransportError type/class and guard, redaction helpers (redactSecrets, redactUrl), parseRetryAfterMs, retry/backoff with jitter, abort/timeout handling, and response parsing strategies.
Adapter migrations to shared HTTP client
src/adapters/binance/market-catalog.ts, src/adapters/binance/private-adapter.ts, src/adapters/juplend/private-adapter.ts
Binance catalog and private adapter, and Juplend private adapter now use httpRequest with injected fetchFn/timeoutMs and explicit HttpRetryPolicy choices (safe reads, no-retry for writes/listenKey start/close, dedicated keepalive retry).
Coordinator error mapping & redaction
src/client/private-subscription-coordinator.ts
Maps TransportError kind rate_limited to runtime reason "rate_limited" via transportReason() and redacts bootstrap error details with bootstrapErrorDetail() using redactSecrets.
Unit & integration tests and test infra
tests/unit/http-client.test.ts, tests/integration/account.test.ts, tests/support/exchanges/binance.ts, tests/support/test-utils.ts
Adds unit tests covering parsing, classification, retry/backoff, redaction and parseRetryAfterMs; integration tests assert bootstrap error redaction and rate-limit mapping; test infra simulates 429 bootstrap responses and extends test helpers.
Task configuration and tracking
.trellis/tasks/06-01-shared-venue-infrastructure/task.json, .trellis/tasks/06-01-shared-venue-infrastructure/check.jsonl, .trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl, .trellis/tasks/06-01-shared-venue-infrastructure/codex-prd-review.md
Adds task records, implementation checklist, and PRD review notes for tracking acceptance criteria, tests, and migration requirements.
Agent workspace and roadmap
.trellis/workspace/codex-agent/index.md, .trellis/workspace/codex-agent/journal-1.md, docs/multi-venue-roadmap.md
Workspace journal/session added for PR1; roadmap updated to mark Step 3 in-progress and narrow TimeProvider scope to local-time default.

Sequence Diagram

sequenceDiagram
  participant Adapter
  participant httpRequest
  participant Fetch as fetch
  participant httpClient as Classifier
  participant Coordinator

  Adapter->>httpRequest: request(options)
  httpRequest->>Fetch: perform fetch(url, signal, timeout)
  Fetch-->>httpRequest: Response / Error
  httpRequest->>httpClient: classify -> TransportError(kind, status)
  httpClient->>httpRequest: redactSecrets(url, rawBody)
  httpRequest-->>Adapter: HttpClientResponse / TransportError
  Adapter->>Coordinator: publish degraded state (TransportError)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped a request across the nets so wide,
I scrubbed the secrets from the query and the tide.
Retries that whisper, timeouts that keep,
A tidy path for adapters — no secrets to leak.
Catalogs and privates now travel side by side.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: introduction of a shared venue HTTP transport client with secret redaction, which is the core focus of the PR across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/shared-venue-infrastructure

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl (1)

8-8: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

删除尾部结构不一致的 JSONL 行。

Line 8 的 8 不是该清单约定的对象记录,建议移除,避免检查/实现脚本读取异常。

💡 建议修复
-8
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl at line 8,
Remove the trailing malformed JSONL record "8" from the file (the standalone
line 8) so every line is a valid JSON object as expected by the checklist
scripts; edit .trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl
and delete the single-character line "8" (the inconsistent tail record) ensuring
the file ends with only well-formed JSONL object records.
.trellis/tasks/06-01-shared-venue-infrastructure/check.jsonl (1)

9-9: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

移除尾部无效 checklist 记录。

Line 9 的裸值 9 与前面对象结构不一致,容易在按对象 schema 解析 JSONL 时触发失败或脏数据。

💡 建议修复
-9
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.trellis/tasks/06-01-shared-venue-infrastructure/check.jsonl at line 9,
Remove the trailing standalone numeric value "9" at the end of check.jsonl (the
bare value on line 9) so every line is a valid JSON object matching the
checklist schema; ensure the file contains only JSON objects (no naked
primitives), re-run a JSONL/schema linter to validate, and commit the cleaned
file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/adapters/binance/private-adapter.ts`:
- Around line 167-176: The timeout message hardcodes 10000ms via
BINANCE_PAPI_HTTP_MESSAGES causing misleading errors when httpTimeoutMs is
overridden; change this to a factory that accepts timeoutMs (e.g., implement
getBinancePapiHttpMessages(timeoutMs): HttpClientMessages) and replace
BINANCE_PAPI_HTTP_MESSAGES with that factory, then compute timeoutMs once at
each request site where httpTimeoutMs is used and pass messages:
getBinancePapiHttpMessages(timeoutMs) so the timeout template uses the actual
configured duration.

In `@src/adapters/juplend/private-adapter.ts`:
- Around line 95-99: JUPLEND_HTTP_MESSAGES currently hardcodes the timeout
message to DEFAULT_HTTP_TIMEOUT_MS, causing inaccurate messages when
requestJuplendJson(...) is called with a dynamic httpTimeoutMs; update the
timeout message path in the error messaging flow so the actual timeoutMs passed
to requestJuplendJson (httpTimeoutMs) is used in the text instead of
DEFAULT_HTTP_TIMEOUT_MS—locate JUPLEND_HTTP_MESSAGES and the caller
requestJuplendJson (and its parameter httpTimeoutMs) and change the timeout
message generation to accept and interpolate the runtime timeout value.

In `@src/internal/http-client.ts`:
- Around line 166-177: The current redaction only replaces the signature value
and leaves the rest of the signed query exposed; update the redaction logic
around the redacted variable (the three replace calls in
src/internal/http-client.ts) to detect and redact the entire signed query
fragment (the contiguous query parameters that end with signature=...) rather
than only the signature field. Replace those signature-only replacements with a
single pattern that, when it finds a '?' or '&' followed by any query params
ending in signature=..., replaces the whole fragment with a single stable token
(e.g. "?signed_query=[REDACTED]" or "&signed_query=[REDACTED]") so inputs like
"symbol=...&side=...&timestamp=...&signature=..." no longer leak other params;
keep the separate JSON "signature" replacement for object payloads if present.
- Line 289: The retry backoff currently blocks aborts because
delayBeforeRetry(attempt, options.retryPolicy) ignores options.signal; update
delayBeforeRetry to accept and observe an AbortSignal (options.signal) and to
return early by rejecting with an AbortError when the signal is aborted, or
alternatively have httpRequest race the sleep with the signal so the sleep is
cancelled; specifically modify delayBeforeRetry (and any callers in httpRequest)
to check options.signal.aborted before sleeping, attach a signal listener that
rejects the delay promise when triggered, and ensure the rejection propagates so
httpRequest returns immediately on abort instead of waiting the full backoff.

---

Outside diff comments:
In @.trellis/tasks/06-01-shared-venue-infrastructure/check.jsonl:
- Line 9: Remove the trailing standalone numeric value "9" at the end of
check.jsonl (the bare value on line 9) so every line is a valid JSON object
matching the checklist schema; ensure the file contains only JSON objects (no
naked primitives), re-run a JSONL/schema linter to validate, and commit the
cleaned file.

In @.trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl:
- Line 8: Remove the trailing malformed JSONL record "8" from the file (the
standalone line 8) so every line is a valid JSON object as expected by the
checklist scripts; edit
.trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl and delete the
single-character line "8" (the inconsistent tail record) ensuring the file ends
with only well-formed JSONL object records.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3e252d46-0665-453a-9f1a-d687417a1996

📥 Commits

Reviewing files that changed from the base of the PR and between 544b925 and 827a185.

📒 Files selected for processing (21)
  • .changeset/redact-transport-error-secrets.md
  • .trellis/spec/backend/adapter-contract.md
  • .trellis/spec/backend/index.md
  • .trellis/tasks/06-01-shared-venue-infrastructure/check.jsonl
  • .trellis/tasks/06-01-shared-venue-infrastructure/codex-prd-review.md
  • .trellis/tasks/06-01-shared-venue-infrastructure/implement.jsonl
  • .trellis/tasks/06-01-shared-venue-infrastructure/pr1-equivalence-matrix.md
  • .trellis/tasks/06-01-shared-venue-infrastructure/prd.md
  • .trellis/tasks/06-01-shared-venue-infrastructure/task.json
  • .trellis/workspace/codex-agent/index.md
  • .trellis/workspace/codex-agent/journal-1.md
  • docs/multi-venue-roadmap.md
  • src/adapters/binance/market-catalog.ts
  • src/adapters/binance/private-adapter.ts
  • src/adapters/juplend/private-adapter.ts
  • src/client/private-subscription-coordinator.ts
  • src/internal/http-client.ts
  • tests/integration/account.test.ts
  • tests/support/exchanges/binance.ts
  • tests/support/test-utils.ts
  • tests/unit/http-client.test.ts

Comment thread src/adapters/binance/private-adapter.ts Outdated
Comment thread src/adapters/juplend/private-adapter.ts Outdated
Comment thread src/internal/http-client.ts
Comment thread src/internal/http-client.ts Outdated
…d bare signed query, abort-aware retry backoff

- binance/juplend: timeout error message reflects the configured httpTimeoutMs
  instead of the hardcoded default (messages built per-request via factory)
- http-client redaction: fold bare/relative signed query fragments to
  "?query=[REDACTED]" (full URLs were already folded — defense-in-depth)
- http-client backoff: delayBeforeRetry observes the abort signal and returns
  immediately on cancel instead of waiting out the full backoff delay
- tests: +2 (abort-during-backoff, bare signed-query redaction)

Skipped 2 review findings as false positives: the trailing "8"/"9" flagged in
implement.jsonl/check.jsonl were cat -n line numbers, not file content (both
files are valid JSONL ending in a clean object).
@imbingox
imbingox merged commit cf1fa93 into main Jun 2, 2026
2 checks passed
@imbingox
imbingox deleted the feat/shared-venue-infrastructure branch June 2, 2026 12:15
@coderabbitai coderabbitai Bot mentioned this pull request Jun 13, 2026
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