Gateway timeout can orphan client correlation from completed request accounting #1591
Summary
I’ve been independently testing Gonka’s gateway/request-accounting flow in the local devshard test environment and found a reproducible causal-addressability edge case around client timeouts.
This is not being reported as a security vulnerability or a mainnet financial issue. The finding is currently scoped to the pinned local test environment.
What happens
A request can intentionally continue executing after the client disconnects or times out. That behavior itself appears intentional and useful.
The problem is correlation/addressability:
- the caller sends a request and may provide a caller-known request/correlation ID;
- Gonka creates its own internal request ID for execution/accounting;
- the client times out before receiving that generated internal ID;
- the inference continues and completes;
- request accounting exists under the internal request ID;
- the timed-out client no longer has a reliable key that resolves the completed accounting record.
In short:
caller-known correlation
↓
client timeout
↓
execution continues
↓
completed internal request/accounting
↓
internal request ID was never received by caller
Local reproduction
Pinned Gonka revision:
f040d0a5b5ef207a0c431894c9f9e2608f9d3073
Control parameters:
- deterministic downstream latency:
1800ms - client timeout:
350ms - caller supplies a known
X-Request-Id - a completed post-timeout request witness is required before classification
Observed in the local testenv:
- client timeout:
true - execution completion after timeout:
true - caller-known request ID resolves request accounting:
false
Evidence run:
https://github.com/safal207/ContractGraph-QA/actions/runs/31662057767
Important: the obvious fix is unsafe
I also tested the tempting remediation: use the caller-provided request ID directly as the canonical request_accounting.request_id.
That fixes addressability, but creates a different integrity problem if two independent operations reuse the same caller-controlled value.
In a storage guard test, two independent logical operations using the same caller ID collapsed into one canonical accounting row:
- logical operations:
2 - canonical accounting rows:
1 - attempt nonces retained together:
[101, 202] - resulting remediation classification:
REJECTED_AS_PRODUCTION_FIX
Evidence run:
https://github.com/safal207/ContractGraph-QA/actions/runs/31664550699
Safer correlation shape
The safer model appears to be:
client_correlation_id # caller-controlled, may repeat
↓ one-to-many
internal_request_id # gateway-generated, unique canonical ID
↓
execution attempt nonce(s) / accounting
That keeps Gonka’s internal request identity canonical while giving a timed-out caller a recoverable correlation path.
A lookup by caller correlation should be allowed to return multiple internal request IDs rather than silently selecting or overwriting one. Reusing a correlation ID should not imply idempotency.
Current work
I’m currently validating a non-collapsing correlation implementation against:
- repeated caller correlation IDs;
- timeout followed by retry;
- independent internal request identities;
- request-accounting lineage preservation.
I’m deliberately gating broader financial reconciliation work until this identity/correlation layer is proven.
Related independent work/evidence is tracked here:
https://github.com/safal207/ContractGraph-QA/pull/33
Related upstream observation
This is adjacent to, but different from, #1387. That issue is about client-visible success diverging from gateway request outcome. This issue is specifically about whether a caller can reliably recover the internal request/accounting lineage after a timeout.
Happy to share the minimal harness/evidence details if useful.
🔄 Auto-synced from Issue #1591 every hour.