Repository navigation
[PR] fix(wiring): credential fingerprint covers all forwarded auth headers, order-independent (#6148) - #6154
ranxianglei wants to merge 1 commit into
Conversation
…, order-independent (#6148) credentialFingerprint broke on the FIRST recognized credential header in insertion order, so a lane forwarding two distinct credentials (shared gateway 'authorization' + per-account 'x-api-key') got an identity that was both order-dependent (reorder flipped the digest -> 429 governor holds missed) and incomplete (second credential invisible -> another account behind the same gateway inherited, and could clear on success, the first account's hold). Collect every recognized header, dedupe by normalized value (Bearer-envelope strip + SDK-HMAC Access-key folding preserved), hash the SORTED set. Single-distinct-value sets hash byte-identically to before; only lanes with >=2 distinct credentials change identity - which had no stable identity before. Behavior change: for >=2-distinct-credential requests the throttle hold key and cache-ledger kp move from 'first header in insertion order' to 'sorted full set'. Single-credential requests are byte-identical.
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.8996-pr.6154.5191816This exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr6154.tgz
npm install -g packageInstall instructions are refreshed on each push. |
🔶 需要决策 背景:本 PR(GitHub #6154)与外部 PR #6149(Afloat16 fork,早开约 4.5 小时)修的是同一个缺陷 #6148、同一机制、同一修法家族(归一化凭证集合排序后哈希,单凭证保持字节一致),两者都 open 且都声明 Closes #6148。
(ai: vllm-qwen/qwen3.8-27b) 查重结论:重复 —— PR #6149(Afloat16/billion-context,opened 2026-11-10T15:35Z)与本 PR(opened 20:01Z)目标同为 #6148、同根因同机制,属同一修复的两个在途实现;按先来后到,本 PR 是后到者。如实说明:此重复先于本会话存在——#6154 开出时未查到 #6149。 标签:bug · p2 · scope/wiring(+ needs-decision,对应上方待决项)。理由:仅多凭证车道受影响、特定条件下限流/归属判定出错,无数据丢失/可用性毁灭/缓存命中崩坏 → p2;无具体客户端车道,不打客户端标签。GitHub PR 侧已存在同样三个标签(live 核验)。 Live state(今日核验):PR open、mergeable=true;head Review of #6154(independent pass)① Direction — verified. Root cause is real and correctly located: ② Regression audit — existing behaviors on the touched paths:
No fail-fast→swallow, no threshold/timing/output-format drift, persistence format untouched. No unintended regressions found. ③ Code. Clean rewrite: collect-all → normalize → Set-dedupe by normalized value → hash the sorted set ( ④ Tests. 10 rows against REAL governor state (no mocks): env knobs explicitly pinned so daemon config can't leak into rows, deterministic integer timestamps, ⑤ Diff. Two files, every line on-purpose, single commit, clean message, house-style imports ( Side-by-side: #6149 vs #6154
Both are correct implementations of the same fix; neither warrants rework. The differences are test-matrix granularity vs base freshness + the critical clear-path row. 八问
收工判定:代码本身达到可合并质量;但同一 issue 不应留两个 open PR——按先来后到推荐选项 A(合 #6149、关 #6154),等 owner 拍板;若选 B,我立即 rebase 并补正向清除测试行。 |
Closes #6148
Problem
credentialFingerprint(src/cache-ledger.ts) broke on the first recognized auth header in insertion order, so a lane forwarding two distinct credentials (e.g. a shared gatewayauthorizationplus a per-accountx-api-key) got an identity that was both:The pre-ingest fast path (src/server/handle.ts, #5795) collects all four header names in fixed name-order, which is exactly how it could disagree with the real governor's key for the same outbound request.
Fix
Collect every recognized header, normalize each (trim / strip Bearer envelope / fold SDK-HMAC-SHA256 lines to their Access key id), dedupe by normalized value, and hash the sorted set (
\u0000-joined). Order-independent by construction, complete by construction.Behavior change (disclosed)
Affected surfaces: the throttle hold key (
upstreamThrottleGate/noteUpstreamThrottle429/noteUpstreamThrottleResolved) and cache-ledgerkpattribution. Multi-credential lanes had no stable identity before this fix (it flipped with insertion order), so nothing consistent is invalidated.Tests
New
tests/issue6148-multi-cred-fingerprint.test.ts(10 rows):Verified: 6 of the 10 rows fail against unchanged source (the rest are regression guards). Local targeted run: 148 tests across the cache-ledger / fingerprint / governor / fast-path suites pass; typecheck + build clean. Full suite rides CI.
Scope
Single module (
src/cache-ledger.ts) + test file. No config surface, no wire/message shape, nokernel/, no persistence-format change. Purefix:.