fix: key sessions on the clients native session id, not rotating credentials - #287
Closed
ranxianglei wants to merge 1 commit into
Closed
fix: key sessions on the clients native session id, not rotating credentials#287ranxianglei wants to merge 1 commit into
ranxianglei wants to merge 1 commit into
Conversation
…dentials refs #280 refs #286 The proxy session id was hash(protocol|upstream|credential|conversation). For Codex/ChatGPT the credential is a rotating OAuth bearer, and the upstream changes when a user switches relays — either change minted a new session id and orphaned ALL compression state (in-memory blocks, lastInputTokens, and the persisted record keyed by the same id). That is the "sessions 缺失" root cause behind #280: the restored session starts at usage=0% with the full raw history replayed. The client's native session id (codex session-id header, claude x-claude-code-session-id, opencode x-opencode-session, Responses body session_id, prompt_cache_key) is the only invariant tied to a conversation — the user can switch accounts or relays anytime. So: - client-provided identity (identity.clientProvided) → session id is hash(protocol|conversation) only; credential and upstream no longer break continuity. - content-fingerprint fallback (hermes, dsh, anonymous clients — no client signal) keeps the 4-way hash: the fingerprint is a content hash with a real collision surface and still needs the account/upstream dimensions for isolation. One-time cost: existing persisted sessions re-key once (old records orphaned); accepted per #286 discussion. Tests: codex native session id stable across bearer rotation + relay switch; body session_id / prompt_cache_key credential-independent; fingerprint + previous_response_id keep 4-way isolation. Full suite 660/660.
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-287Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr287.tgz
npm install -g packageThis comment is automatically updated on each push. |
Owner
Author
|
Superseded by #288 (merged): the verbatim session-id design replaces the hash(protocol|conversation) approach here, and deriveSessionId no longer exists on master. Closing. |
Owner
Author
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.
refs #280
refs #286
Background
The proxy session id was
hash(protocol | upstream | credential | conversation). Two of those dimensions are volatile even within ONE conversation:Either change minted a brand-new session id and orphaned ALL compression state — in-memory blocks,
lastInputTokens, and the persisted record (keyed by the same id, so it couldn't be restored either). That is the "sessions 缺失" root cause behind #280: after the churn, the session restarts at usage=0% with the full raw history replayed, the nudge goes blind, and the payload overflows the real window.Change
The client's native session id (codex
session-idheader, claudex-claude-code-session-id, opencodex-opencode-session, Responses bodysession_id,prompt_cache_key) is the only invariant tied to a conversation — the user can switch accounts or relays anytime, and the session id is what stays bound to the conversation (#286, owner-confirmed direction):src/session-id.ts:deriveSessionIdtakes the resolved identity; when it is client-provided (identity.clientProvided), the session id ishash(protocol | conversation)only.src/server.ts: passes the resolved identity (per protocol: header signal for anthropic, the openai/responses identity objects) into the derivation.previous_response_id(clientDerived,clientProvided:false) also stays 4-way.One-time cost: existing persisted sessions re-key once (old records orphaned) — accepted per #286.
Tests
session_idandprompt_cache_keyidentities credential-independent.previous_response_idkeep 4-way isolation (no cross-account/cross-provider bleed).Full suite: 660/660 pass.
Coordination
Complements #249 (thread-id subagent refinement + compaction fast path) — independent change, no overlap in the identity-derivation code path.
🤖 ework agent