Skip to content

Gate Shopify response state on established sessions - #3960

Open
frandiox wants to merge 11 commits into
previewfrom
fd-server-timing-refactor
Open

Gate Shopify response state on established sessions#3960
frandiox wants to merge 11 commits into
previewfrom
fd-server-timing-refactor

Conversation

@frandiox

Copy link
Copy Markdown
Contributor

TL;DR

Prevent concurrent cold Storefront API responses from installing conflicting Shopify browser state before the marked consent request completes, while keeping cacheable responses free of replayed state.

Why

A new session can issue several Storefront API requests concurrently. If each response is allowed to return captured cookies or timing state, an unrelated response can race with and eclipse the response that establishes consent. The response gate needs a single explicit bootstrap path without changing established-session behavior.

What changed

  • Allow Shopify response state on cold sessions only for the marked consent-management request.
  • Continue returning updates for requests that arrive with an established essential session.
  • Do not apply captured cookies or Server-Timing to GET, HEAD, document, or methodless responses, preserving shared-cache eligibility.
  • Stop Hydrogen from inventing visitor and visit tokens when no tracking state exists.
  • Preserve guarded legacy tracking headers for consumers that still require header-based compatibility, without allowing legacy values to override newer cookie state.
  • Add focused coverage for cold-session races, established sessions, request methods, documents, and legacy token compatibility.

Review boundary

This PR contains only the server-side response-state and token behavior. The async consent/bootstrap integration is intentionally left for a follow-up branch and should not ship until the corresponding consent-tracking-api bundle is released. Data SHS enablement is also out of scope.

Testing

  • Focused request-context tests passed (39 tests).
  • Shopify route and redirect tests passed.

Versioning

No changeset is included because this changes internal request/response coordination and does not add or change a public API.

frandiox and others added 9 commits August 20, 2026 20:56
Document responses can be cached and must not expose generated visitor identifiers through Server-Timing. Keep fallback tokens request-scoped while browser-side visitor-state transport remains disabled.

Co-authored-by: Codex <codex@openai.com>
Parallel cold Storefront API requests can race to install conflicting browser sessions. Return captured response state only for an established essential session or the marked async consent request, keep documents clean, and prevent replayed state from being cached publicly.

Co-authored-by: Codex <codex@openai.com>
Keep the compatibility reason close to the request-header plumbing so future cleanup does not remove headers that remain necessary for consumers without cookie fallback.

Co-authored-by: Codex <codex@openai.com>
Essential-only sessions can coexist with legacy tracking cookies during migration. Continue forwarding those values for consumers without cookie fallback, while parsing the inbound Cookie header once for consistent presence and value lookups.

Co-authored-by: Codex <codex@openai.com>
Do not replay Storefront API cookies or Server-Timing onto GET, HEAD, document, or methodless responses. This preserves shared-cache eligibility for read requests while retaining the established-session and marked-consent gates for state-changing requests.

Co-authored-by: Codex <codex@openai.com>
Hydrogen should preserve legacy token compatibility without inventing identity values when no tracking state exists. Keep the modern-cookie guard so legacy values cannot override newer Shopify state.

Co-authored-by: Codex <codex@openai.com>
Direct Storefront API proxy responses already carry upstream Server-Timing, bypassing the request-context replay gate. Capture that timing state before returning the proxy response so cold and cacheable requests suppress it while marked consent requests retain it.

Co-authored-by: Codex <codex@openai.com>
Remove assertions that only confirm empty tracking input stays empty, while preserving coverage that injects upstream or legacy state and verifies the response gate. Also apply the required formatter output so the CI formatting check passes.

Co-authored-by: Codex <codex@openai.com>
Capture upstream Storefront API cookies before removing them from direct proxy responses so the request-context consent and cacheability policy is always applied. This avoids leaking unrecognized or future upstream cookies around the gate.

Co-authored-by: Codex <codex@openai.com>
frandiox and others added 2 commits August 21, 2026 16:32
Rename the existing proxy header options to requestHeaders and nest response preparation under responseHeaders.prepare so both directions have a symmetric, extensible configuration shape.

Co-authored-by: Codex <codex@openai.com>
Consume proxy cookies and timing in the request context so Shopify state is gated consistently while preserving deliberate user response headers. Replay captured timing idempotently without parsing individual metrics.

Co-authored-by: Codex <codex@openai.com>
@frandiox
frandiox marked this pull request as ready for review August 21, 2026 08:48
@frandiox
frandiox requested a review from a team as a code owner August 21, 2026 08:48
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