Skip to content

Route a conversation's encrypted history back to the provider that holds it - #120

Merged
fylorn merged 2 commits into
devfrom
fix/encrypted-history-pin
Oct 22, 2026
Merged

fylorn merged 2 commits into
devfrom
fix/encrypted-history-pin

Conversation

@fylorn

@fylorn fylorn commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Enterprise side of ThinkWatchProject/ThinkWatch-Core#368.

OpenAI Responses with store: false (how Codex always sends) hands the client encrypted state to send back every turn: reasoning, remote compactions, Codex sub-agent messages, encrypted tool output. Only the account that encrypted it can read it. A conversation that moved to another provider (affinity expiry, a tripped breaker, failover) was refused with invalid_encrypted_content on every turn from then on.

What changes

  • The gateway remembers, per conversation (authenticated user + x-session-id, or the client's own session header such as Codex's session_id), the provider that last answered it: Redis, 30 days, independent of the affinity settings.
  • A Responses request carrying encrypted content (tw_dialect::sealed) goes back to that provider:
    • more than reasoning encrypted: only that provider, no strategy pick, no failover, even with its breaker open; if it no longer has a route for the model, refused up front with SealedHistoryUnavailable (409);
    • only reasoning encrypted: that provider first, normal failover after it.
  • An upstream refusing encrypted history (4xx, or an error event inside a 200 stream) becomes SealedHistoryRefused, which explains what happened and what to do, followed by the upstream's words. It no longer counts against the route.
  • The request log detail records pinned_by: encrypted_history.

Before the next release

The core crates point at core main at the merge of ThinkWatchProject/ThinkWatch-Core#368 (rev, set on the dependency lines so core's CI can still append its [patch]). Replace with the next core tag before the next enterprise release.

Tests

crates/test-support/tests/gateway_sealed_history.rs (5 integration tests) plus one in gateway_responses_ws.rs; unit tests for the decision, narrowing, failure classification and refusal mapping. Full integration suite and workspace unit tests pass locally; fmt and clippy clean.

🤖 Generated with Claude Code

fylorn and others added 2 commits October 22, 2026 22:45
…lds it

OpenAI Responses with store: false (Codex always sends it) hands the
client encrypted state it sends back every turn: reasoning, remote
compactions, agent messages, encrypted tool output. Only the account
that encrypted it can read it, so a conversation that moved to another
provider (affinity expiry, a tripped breaker, failover) was refused with
invalid_encrypted_content on every turn from then on.

The gateway now remembers, per conversation (authenticated user plus
x-session-id, or the client's own session header such as Codex's
session_id), the provider that last answered it, in Redis for 30 days,
independent of the affinity settings. A Responses request carrying
sealed content (tw_dialect::sealed) goes only to that provider: no
strategy pick, no failover, its open breaker does not stop it; when the
provider has no route for the model any more the request is refused up
front with 409. A request carrying only sealed reasoning prefers that
provider and still fails over. An upstream's refusal of sealed history,
as a 4xx or as the error event of a stream, becomes SealedHistoryRefused
with a plain explanation and the upstream's words, and no longer counts
against the route. The log row records pinned_by: encrypted_history.

Core crates point at the core branch fix/encrypted-history-pin until it
is tagged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn marked this pull request as ready for review October 22, 2026 15:59
@fylorn
fylorn merged commit f9fe732 into dev Oct 22, 2026
7 checks passed
@fylorn
fylorn deleted the fix/encrypted-history-pin branch October 22, 2026 15:59
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant