Skip to content

Conversation

@guitavano
Copy link
Contributor

@guitavano guitavano commented Nov 19, 2025

Summary by CodeRabbit

  • Chores
    • Refined HTTP caching configuration for improved checkout page performance
    • Strengthened cart diagnostics through enhanced logging and tracking capabilities

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 19, 2025

Walkthrough

Modifies VTEX loaders to add conditional HTTP headers for checkout routes in the proxy handler, and enhances cart logging with defensive cookie-based data extraction including orderFormId and cookie count detection.

Changes

Cohort / File(s) Change Summary
Conditional checkout headers
vtex/loaders/proxy.ts
Adds conditional custom HTTP header logic: when a route path contains "/checkout", injects a Vary header with "Cookie, Accept-Encoding"; otherwise, customHeaders is an empty array.
Cart logging enhancements
vtex/loaders/cart.ts
Defensive JWT payload computation and cookie-based data extraction in logMismatchedCart: derives orderFormIdFromRequest from cookies, computes hasTwoCookies flag from request headers, includes these fields and jwtPayload in log payload when cart mismatches are detected.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Verify conditional header logic correctly identifies "/checkout" routes
  • Confirm defensive cookie parsing handles edge cases (absent cookies, malformed headers)
  • Validate new log fields (orderFormIdFromRequest, hasTwoCookies) are correctly extracted and serialized

Possibly related PRs

Poem

🐰 Headers dance conditionally near checkout gates,
Cookies counted twice, defenses abate,
Logs now capture what cookies relate,
A hop and a skip—no mismatch too late! 📝✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is completely empty, missing all required template sections including 'What is this Contribution About?', 'Issue Link', 'Loom Video', and 'Demonstration Link'. Add a complete pull request description following the repository template, including the purpose of the changes, relevant issue link, and ideally a Loom video and demonstration link for reviewer context.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'add Vary Cookie' is directly related to the main change in the changeset, which adds conditional Vary header configuration with 'Cookie, Accept-Encoding' in the proxy route handler.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-vary-cookie

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f8c16c and 288cf44.

📒 Files selected for processing (2)
  • vtex/loaders/cart.ts (1 hunks)
  • vtex/loaders/proxy.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • vtex/loaders/cart.ts
  • vtex/loaders/proxy.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

Tagging Options

Should a new tag be published when this PR is merged?

  • 👍 for Patch 0.133.7 update
  • 🎉 for Minor 0.134.0 update
  • 🚀 for Major 1.0.0 update

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fae26e and ab88e44.

📒 Files selected for processing (1)
  • vtex/loaders/proxy.ts (1 hunks)

Comment on lines 80 to 85
customHeaders: [
{
key: "Vary",
value: "Cookie, Accept-Encoding",
},
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Verify handler support and assess caching impact.

Adding Vary: Cookie will significantly affect caching behavior:

  1. Cache efficiency: Every unique cookie combination will create a separate cache entry, potentially causing dramatic reductions in CDN/cache hit rates and increased storage costs.

  2. Handler compatibility: Confirm that website/handlers/proxy.ts supports the customHeaders field.

  3. Documentation: Consider documenting why this change is necessary and the expected impact on cache performance.

For VTEX e-commerce sites handling personalized content (checkout, account), this may be intentional, but the broad application to all proxied paths warrants careful consideration.

Run the following script to verify the handler supports customHeaders:

Additionally, please search the web to understand best practices for Vary header usage in e-commerce CDN configurations:


🏁 Script executed:

#!/bin/bash
# Description: Check if website/handlers/proxy.ts supports customHeaders field

# Search for customHeaders in the proxy handler implementation
ast-grep --pattern $'customHeaders'

# Also check for the handler type definition
fd -e ts -e tsx proxy.ts | xargs rg -n "customHeaders" -A 3 -B 3

Length of output: 4595


🌐 Web query:

Vary Cookie header CDN caching best practices e-commerce

💡 Result:

Concise best-practices for using Vary/Cookie with CDNs on e‑commerce sites

  1. Avoid sending Vary: Cookie for whole Cookie header. it creates one cache key per full Cookie value (huge fragmentation, near-zero hit rate). (peakhour.io)

  2. Prefer isolating dynamic fragments (edge-side includes / edge functions) so the HTML shell is cacheable and only small pieces (cart count, “logged in” fragment) are fetched per user. This preserves high cache hit rates. (vodien.com)

  3. If you must vary on cookie, vary only on a specific cookie name/value (e.g., currency or locale) by using CDN rules that look up a single cookie, not the entire Cookie header. Many CDNs support “vary by cookie” or custom cache keys via edge config/workers. (peakhour.io)

  4. Mark truly user-private pages as Cache-Control: private / no-store (or bypass CDN caching) so session/PII never gets stored in shared caches. Don’t rely on Vary alone to protect private content. (httpwg.org)

  5. Know your CDN’s behavior and plan accordingly: some CDNs (or non‑Enterprise tiers) ignore Vary: Cookie for caching decisions or only support limited vary headers — test and use CDN-specific features (page rules, bypass-on-cookie, enterprise cache keys, workers). (simonwillison.net)

  6. Use short-lived edge-cache TTLs and cache purging/webhooks for frequently-updated dynamic content; combine with stale-while-revalidate or background refresh where supported to avoid blocking user requests. (blog.cloudflare.com)

  7. Test thoroughly (crawl as anonymous, logged-in, crawler UAs) to detect cache bleed (logged-in content served to anon) and validate SEO/crawler behavior. Maintain crawler rules so bots see expected variants. (vodien.com)

Quick implementation checklist

  • Don’t emit Vary: Cookie globally.
  • Use ESI/edge fragments or edge functions for per-user bits.
  • If varying, configure CDN to vary by a single cookie name or custom cache key.
  • Mark private responses as private/no-store.
  • Verify CDN’s Vary handling in your tier; use page rules/enterprise features if needed.
  • Add monitoring/crawls for cache correctness.

If you want, I can:

  • Map these recommendations to a specific CDN (Cloudflare, Fastly, Akamai) with exact configuration examples and tests.

Citations:


Clarify intent and use CDN-specific cookie variance instead of global Vary header.

Handler support confirmed ✓—customHeaders is properly implemented in website/handlers/proxy.ts. However, emitting Vary: Cookie creates one cache key per full Cookie value, resulting in huge fragmentation and near-zero hit rate, which is critical for e-commerce.

Industry best practices recommend:

  1. If varying on cookie, vary only on a specific cookie name/value via CDN rules or custom cache keys, not the entire Cookie header
  2. Use edge-side includes or edge functions so the HTML shell remains cacheable with only small user-specific fragments fetched per user
  3. Mark truly user-private pages as Cache-Control: private/no-store instead of relying on Vary alone

Why is this change needed? Please clarify the business reason—are you addressing a security issue, cache bleed, or something else? The Vary header approach will likely degrade performance significantly on checkout, account, and login paths.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
vtex/utils/cookies.ts (1)

25-27: Clean up extra whitespace.

Lines 25 and 27 contain trailing/unnecessary whitespace that should be removed for consistency.

-      : cookie;
-      
-    if(cookie.name === "checkout.vtex.com" && options?.shouldClearCartCookie) {
-     
+      : cookie;
+
+    if (cookie.name === "checkout.vtex.com" && options?.shouldClearCartCookie) {

Note: Also add a space after if for consistency with JavaScript/TypeScript style conventions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c79bc70 and a87c593.

📒 Files selected for processing (2)
  • vtex/loaders/cart.ts (3 hunks)
  • vtex/utils/cookies.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (1)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-42)
🔇 Additional comments (4)
vtex/utils/cookies.ts (1)

12-14: LGTM: Backward-compatible signature extension.

The optional options parameter properly extends the function signature without breaking existing callers.

vtex/loaders/cart.ts (3)

28-43: LGTM: Consistent return structure in error paths.

The function now returns a structured object { shouldClearCartCookie: false } in all early-return paths (missing cookie and JWT parse errors), which makes the function more predictable and easier to consume.


48-74: LGTM: Proper mismatch detection and flag setting.

The function correctly returns { shouldClearCartCookie: true } when an email mismatch is detected between the cookie and order form, and { shouldClearCartCookie: false } in the default case. The logging provides good observability for debugging cart mismatches.


110-114: Domain handling in proxySetCookie may prevent cookie clearing.

The integration in cart.ts is clean, but the underlying proxySetCookie function has a critical domain handling issue: when toDomain is not provided, the cookie is set with an empty string domain (vtex/utils/cookies.ts:35), which may prevent the "checkout.vtex.com" cookie from being properly cleared.

Additionally, the URL parsing at line 16 (new URL(toDomain)) lacks error handling and will throw if an invalid URL is passed.

Verify that:

  1. The empty string domain fallback actually clears cookies correctly in the browser
  2. req.url is always a valid URL in practice (though it should be, as a standard Request property)

Comment on lines 26 to 37
if(cookie.name === "checkout.vtex.com" && options?.shouldClearCartCookie) {

setCookie(to, {
name: "checkout.vtex.com",
value: "",
expires: new Date(0),
maxAge: 0,
path: "/",
secure: true,
httpOnly: true,
domain: newDomain ? newDomain?.hostname : "",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix domain handling when clearing cookie.

When toDomain is not provided (i.e., newDomain is falsy), line 36 sets domain: "", which may fail to clear the cookie. Cookies must be cleared with the same domain they were originally set with.

Consider either:

  1. Not setting the domain property when newDomain is falsy (allowing the browser to use the current domain)
  2. Using the original cookie's domain from cookie.domain

Apply this diff:

-      domain: newDomain ? newDomain?.hostname : "",
+      domain: newDomain ? newDomain.hostname : cookie.domain,

Additionally, line 36 has redundant optional chaining—if newDomain is truthy, .hostname is guaranteed to exist.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(cookie.name === "checkout.vtex.com" && options?.shouldClearCartCookie) {
setCookie(to, {
name: "checkout.vtex.com",
value: "",
expires: new Date(0),
maxAge: 0,
path: "/",
secure: true,
httpOnly: true,
domain: newDomain ? newDomain?.hostname : "",
});
if(cookie.name === "checkout.vtex.com" && options?.shouldClearCartCookie) {
setCookie(to, {
name: "checkout.vtex.com",
value: "",
expires: new Date(0),
maxAge: 0,
path: "/",
secure: true,
httpOnly: true,
domain: newDomain ? newDomain.hostname : cookie.domain,
});
🤖 Prompt for AI Agents
In vtex/utils/cookies.ts around lines 26 to 37, the cookie-clear code sets
domain: "" when newDomain is falsy and uses redundant optional chaining; change
it so the domain is only set when newDomain is provided (use domain:
newDomain.hostname) and otherwise either omit the domain property so the browser
uses the current origin or explicitly use the original cookie.domain value
(cookie.domain) when available; remove the unnecessary optional chaining on
newDomain.hostname.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
vtex/loaders/cart.ts (1)

75-82: Normalize ORDER_FORM_IDS_TO_CLEAR values to avoid subtle mismatches

The current parsing:

const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")?.split(",");
if (orderFormIdFromRequest && orderFormIdsToClear?.includes(orderFormIdFromRequest)) {
  return { shouldClearCartCookie: true };
}

is fragile if the env var contains spaces or empty entries (e.g., "id1, id2"). A small normalization step will make this more robust without changing behavior for well‑formatted values:

-    const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")?.split(",");
+    const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")
+      ?.split(",")
+      .map((id) => id.trim())
+      .filter(Boolean);

This ensures that operational misconfigurations (extra spaces, trailing commas) don’t silently prevent cookie clearing when it’s expected.

After adjusting, it’d be good to verify with a local env like ORDER_FORM_IDS_TO_CLEAR="foo , bar, baz " that only the intended IDs are recognized.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52a68f7 and d66604d.

📒 Files selected for processing (1)
  • vtex/loaders/cart.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (1)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-42)
🔇 Additional comments (3)
vtex/loaders/cart.ts (3)

34-36: Consistent return contract from logMismatchedCart looks good

Always returning { shouldClearCartCookie: boolean } (including on missing/invalid auth cookie and match cases) makes the loader usage straightforward and avoids undefined handling. No issues here; this is a solid shape change.

Also applies to: 40-43, 84-85


120-120: Wiring shouldClearCartCookie through to proxySetCookie is correct; consider tests

Plumbing the { shouldClearCartCookie } result from logMismatchedCart into proxySetCookie matches the updated proxySetCookie signature and cleanly centralizes the cookie‑clearing behavior there. The control flow looks coherent.

It would be valuable to add at least one integration/unit test that:

  • Forces a mismatch and a known orderFormIdFromRequest in ORDER_FORM_IDS_TO_CLEAR.
  • Asserts that the outgoing Set-Cookie for checkout.vtex.com is cleared as expected.

This will guard against regressions in the cookie parsing and env‑driven decision logic.

Also applies to: 123-125


55-58: The review comment is incorrect. The cookie parsing is already correct.

The code in vtex/loaders/cart.ts line 57 correctly extracts the orderFormId:

getCookies returns parsed cookie values as a Record<string, string>. The checkout.vtex.com cookie value is formatted as __ofid=<orderFormId> (not JSON or URL-encoded), as evidenced by vtex/utils/orderForm.ts:

  • Line 42: validation regex /^__ofid=([0-9a-fA-F])+$/ confirms the format
  • Line 47: uses identical logic ofidCookie.split("=") to extract the ID
  • Line 65: formatCookie creates the value as __ofid=${orderFormId}

The existing code at line 57 (split("=").at(1)) correctly extracts the order form ID and will properly match against ORDER_FORM_IDS_TO_CLEAR as checked at line 77. The suggested fix would unnecessarily complicate the code and break the current working implementation.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d66604d and 531d47d.

📒 Files selected for processing (1)
  • vtex/loaders/cart.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (1)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-42)
🔇 Additional comments (4)
vtex/loaders/cart.ts (4)

34-43: LGTM: Consistent return type improves type safety.

The early returns now provide a consistent object shape { shouldClearCartCookie: boolean }, which improves type safety and makes the function contract clearer.


57-83: Excellent observability improvements.

The addition of hasTwoCookies, OrderFormIdFromRequest in the mismatch logging, and the dedicated warning log when clearing cookies significantly improves debugging capability for cart-related issues.


124-128: LGTM: Clean integration with proxySetCookie.

The destructuring and passing of shouldClearCartCookie to proxySetCookie is implemented correctly and matches the updated signature in vtex/utils/cookies.ts.


1-1: Vary header implementation verified and confirmed.

The search confirms that the Vary header implementation exists in vtex/loaders/proxy.ts (lines 80-83). The implementation correctly:

  • Checks if the path template includes "/checkout"
  • Injects a Vary: Cookie, Accept-Encoding header for matching paths

The code changes are correct and no further action is required.

const emailFromCookie = jwtPayload?.sub;
const userIdFromCookie = jwtPayload?.userId;

const orderFormIdFromRequest = cookies["checkout.vtex.com"]?.split("=").at(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate cookie format before parsing.

The cookie parsing assumes the value contains an "=" separator and takes the part after it. This could fail silently if the cookie format is unexpected (e.g., no "=" present, multiple "=" characters).

Consider adding validation or using a more robust parsing approach:

-  const orderFormIdFromRequest = cookies["checkout.vtex.com"]?.split("=").at(1);
+  const cookieValue = cookies["checkout.vtex.com"];
+  const orderFormIdFromRequest = cookieValue?.includes("=") 
+    ? cookieValue.split("=").at(1) 
+    : cookieValue;

Alternatively, document the expected cookie format if this structure is guaranteed by the VTEX platform.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const orderFormIdFromRequest = cookies["checkout.vtex.com"]?.split("=").at(1);
const cookieValue = cookies["checkout.vtex.com"];
const orderFormIdFromRequest = cookieValue?.includes("=")
? cookieValue.split("=").at(1)
: cookieValue;
🤖 Prompt for AI Agents
In vtex/loaders/cart.ts around line 48, the code blindly splits
cookies["checkout.vtex.com"] on "=" and takes .at(1), which can fail for missing
or malformed values; validate the cookie string first (existence and that it
contains at least one "="), then parse robustly by finding the first "="
(indexOf) and using substring to get everything after it (so multiple "=" are
preserved), trim the result, and fall back to null or a safe default if
validation fails; add a brief comment documenting the expected cookie format.

Comment on lines 76 to 87
const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")?.split(",");

if (orderFormIdFromRequest && orderFormIdsToClear?.includes(orderFormIdFromRequest)) {
logger.warn(`Clearing cart cookie `, {
orderFormIdFromRequest,
EmailFromCookie: emailFromCookie,
EmailFromOrderForm: email,
})
return { shouldClearCartCookie: true };
}

return { shouldClearCartCookie: false };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add whitespace trimming for environment variable parsing.

The comma-separated ORDER_FORM_IDS_TO_CLEAR environment variable is split without trimming whitespace, which could cause matching failures if the configuration includes spaces (e.g., "id1, id2, id3").

Apply this diff to handle whitespace:

-  const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")?.split(",");
+  const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")
+    ?.split(",")
+    .map(id => id.trim())
+    .filter(id => id.length > 0);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
vtex/loaders/cart.ts around lines 76 to 87: the ORDER_FORM_IDS_TO_CLEAR env var
is split without trimming, so values like "id1, id2" won't match; update parsing
to split on commas, map each item to .trim(), and filter out empty strings
(e.g., .split(",").map(s => s.trim()).filter(Boolean)) before using
.includes(orderFormIdFromRequest) so whitespace in the env value won't prevent
matches.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
vtex/loaders/cart.ts (2)

28-28: Trim and sanitize ORDER_FORM_IDS_TO_CLEAR before matching

ORDER_FORM_IDS_TO_CLEAR is split on commas but entries aren’t trimmed, so a config like "id1, id2" will never match orderFormIdFromRequest (" id2" vs "id2"). It’s safer to normalize once at load time:

-const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")?.split(",");
+const orderFormIdsToClear = Deno.env.get("ORDER_FORM_IDS_TO_CLEAR")
+  ?.split(",")
+  .map((id) => id.trim())
+  .filter((id) => id.length > 0);

If this list ever grows, you might also consider turning it into a Set for faster lookups, but that’s optional at current scale.

Also applies to: 78-85


50-65: Harden checkout cookie parsing and avoid leaking sensitive headers in logs

Two things here:

  1. Checkout cookie parsing is brittle

cookies["checkout.vtex.com"]?.split("=").at(1) assumes:

  • The value always contains "=", and
  • You only care about the part after the first "=".

A malformed value (no "=") silently yields undefined, and multiple "=" lose everything after the second part. A more defensive parse that preserves everything after the first "=" is safer:

-  const orderFormIdFromRequest = cookies["checkout.vtex.com"]?.split("=").at(1);
+  const rawCheckoutCookie = cookies["checkout.vtex.com"];
+  const orderFormIdFromRequest = rawCheckoutCookie && rawCheckoutCookie.includes("=")
+    ? rawCheckoutCookie.slice(rawCheckoutCookie.indexOf("=") + 1).trim()
+    : rawCheckoutCookie;
+
+  // Expected format: "id=<orderFormId>" set by VTEX's checkout cookie

This keeps working for the current "id=<orderFormId>" shape, preserves any additional "=" in the value, and degrades gracefully if the format changes.

  1. reqHeaders logging may leak secrets

reqHeaders currently logs almost all request headers, only excluding "cookie" and "cache-control". That will typically include authorization and potentially other credentials/API keys, which is risky from a security/compliance standpoint.

Consider expanding the denylist or switching to a small allowlist of headers you genuinely need for debugging, e.g.:

-    const headersDenyList = new Set(["cookie", "cache-control"]);
+    const headersDenyList = new Set([
+      "cookie",
+      "cache-control",
+      "authorization",
+      "x-vtex-api-appkey",
+      "x-vtex-api-apptoken",
+    ]);

Or invert this logic to only log a vetted subset of headers.

Also applies to: 57-75

🧹 Nitpick comments (1)
vtex/loaders/cart.ts (1)

36-45: Confirm that env-driven cart clearing should depend on a valid auth cookie

Because of the early returns:

if (!userFromCookie) {
  return { shouldClearCartCookie: false };
}

const [jwtPayload, error] = safeParseJwt(userFromCookie);

if (error) {
  console.error("Error parsing JWT", error);
  return { shouldClearCartCookie: false };
}

the ORDER_FORM_IDS_TO_CLEAR logic only runs when a VtexIdclientAutCookie_* is present and the JWT parses correctly. Any requests without that cookie (or with an invalid one) can never trigger the env-based clearing, even if their checkout.vtex.com orderFormId is in the configured list.

If the intention is to clear only for authenticated sessions, this is fine but might merit a short comment. If instead you want to force-clear specific broken carts regardless of login state, consider moving the orderFormIdFromRequest/orderFormIdsToClear check before these early returns, or separating “logging mismatch” from “deciding whether to clear the cart cookie”.

Also applies to: 78-88

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 531d47d and 38b0543.

📒 Files selected for processing (1)
  • vtex/loaders/cart.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (3)
vtex/utils/types.ts (1)
  • OrderForm (8-43)
vtex/mod.ts (1)
  • AppContext (27-27)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-42)
🔇 Additional comments (1)
vtex/loaders/cart.ts (1)

124-128: Wiring shouldClearCartCookie into proxySetCookie looks consistent

Using logMismatchedCart to compute { shouldClearCartCookie } and passing it through to proxySetCookie centralizes the cookie-clearing decision and keeps the loader body clean. The control flow and types here look sound given the updated proxySetCookie signature.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
vtex/loaders/cart.ts (2)

28-29: Trim whitespace when parsing environment variable.

The comma-separated ORDER_FORM_IDS_TO_CLEAR environment variable is split without trimming whitespace. This could cause matching failures on line 70 if the configuration includes spaces (e.g., "id1, id2, id3").


41-41: Validate cookie format before parsing.

The cookie parsing assumes the value contains an "=" separator. This could fail silently if the cookie format is unexpected.

🧹 Nitpick comments (1)
vtex/loaders/cart.ts (1)

70-80: Consistent return type improves API contract.

The function now consistently returns an object { shouldClearCartCookie: boolean } in all code paths, which is a good improvement over the previous implementation that could return undefined.

Minor nitpick: Line 71 has a trailing space in the log message string.

Apply this diff to remove the trailing space:

-    logger.warn(`Clearing cart cookie `, {
+    logger.warn(`Clearing cart cookie`, {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38b0543 and 7be18a6.

📒 Files selected for processing (1)
  • vtex/loaders/cart.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (3)
vtex/utils/types.ts (1)
  • OrderForm (8-43)
vtex/mod.ts (1)
  • AppContext (27-27)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-42)
🔇 Additional comments (2)
vtex/loaders/cart.ts (2)

36-36: Good defensive coding practice.

Conditionally parsing the JWT only when userFromCookie exists prevents unnecessary parsing attempts and potential errors. This is more efficient and safer.


116-120: Clean integration of cookie-clearing flow.

The destructuring of shouldClearCartCookie and passing it to proxySetCookie properly connects the decision logic to the cookie-clearing implementation. The integration is straightforward and correct.

) {
const headersDenyList = new Set(["cookie", "cache-control"]);

const hasTwoCookies = req.headers.get("cookie")?.split("checkout.vtex.com")?.length === 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fragile duplicate cookie detection logic.

Splitting the entire cookie header on the string "checkout.vtex.com" and checking length === 3 could produce false positives if a cookie value happens to contain this substring. While this is only used for logging, a more robust approach would parse cookies properly and count actual cookie occurrences by name.

🤖 Prompt for AI Agents
In vtex/loaders/cart.ts around line 51, the current check splits the entire
Cookie header on the substring "checkout.vtex.com" and compares the resulting
array length to 3, which is fragile; instead parse the Cookie header into
individual cookies by splitting on ';', trim each pair, split each pair on the
first '=' to get the cookie name, then count how many cookie names exactly equal
(or match the expected cookie name) "checkout.vtex.com" (or the precise cookie
name used) and set hasTwoCookies when that count is >= 2; update the logging to
use this parsed-count value so detection is based on actual cookie names rather
than substring matches.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
vtex/loaders/proxy.ts (1)

80-87: Implementation is correct; caching concerns previously raised remain valid.

The conditional logic correctly applies the Vary header only to checkout-related paths. However, the previous review's concerns about CDN cache fragmentation with Vary: Cookie still apply here.

vtex/utils/cookies.ts (1)

26-39: Domain handling issue from previous review remains unresolved.

The previous review correctly identified that setting domain: "" on line 35 when newDomain is falsy may fail to clear the cookie. Additionally, line 35 contains redundant optional chaining (newDomain?.hostname when newDomain is already verified as truthy).

Apply the suggested fix from the previous review:

-      domain: newDomain ? newDomain?.hostname : "",
+      domain: newDomain ? newDomain.hostname : cookie.domain,
vtex/loaders/cart.ts (2)

59-59: Cookie parsing fragility from previous review remains unresolved.

The previous review correctly identified that this parsing assumes the cookie value contains an "=" separator, which could fail silently if the format is unexpected.

Apply the suggested fix from the previous review to handle edge cases:

-  const orderFormIdFromRequest = cookies["checkout.vtex.com"]?.split("=").at(1);
+  const cookieValue = cookies["checkout.vtex.com"];
+  const orderFormIdFromRequest = cookieValue?.includes("=") 
+    ? cookieValue.split("=").at(1) 
+    : cookieValue;

69-70: Fragile duplicate cookie detection from previous review remains unresolved.

The previous review correctly identified that splitting on the substring "checkout.vtex.com" could produce false positives if any cookie value contains this text.

A more robust approach would parse individual cookies by name rather than using substring matching, as suggested in the previous review.

🧹 Nitpick comments (1)
vtex/loaders/cart.ts (1)

89-102: Consider defensive trimming for orderFormIdsToClear matching.

The logic correctly checks if the order form ID should be cleared. However, if configuration values in orderFormIdsToClear could contain whitespace (e.g., from manual entry), the comparison might fail.

Consider adding defensive trimming:

  if (
    orderFormIdFromRequest &&
-   orderFormIdsToClear?.includes(orderFormIdFromRequest)
+   orderFormIdsToClear?.map(id => id.trim()).includes(orderFormIdFromRequest.trim())
  ) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7be18a6 and 1f8c16c.

📒 Files selected for processing (3)
  • vtex/loaders/cart.ts (5 hunks)
  • vtex/loaders/proxy.ts (1 hunks)
  • vtex/utils/cookies.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
vtex/loaders/cart.ts (3)
vtex/mod.ts (2)
  • Props (43-108)
  • AppContext (27-27)
vtex/utils/types.ts (1)
  • OrderForm (8-43)
vtex/utils/cookies.ts (1)
  • proxySetCookie (8-41)
🔇 Additional comments (4)
vtex/utils/cookies.ts (1)

12-14: LGTM!

The optional options parameter is properly typed and integrates well with the downstream usage in the cart loader.

vtex/loaders/cart.ts (3)

20-31: LGTM!

The Props interface is well-defined with clear documentation for the new configuration options.


41-46: LGTM!

The function signature change appropriately reflects the new behavior of returning mismatch status for downstream decision-making.


111-148: LGTM!

The loader integration correctly implements the new cart mismatch detection and cookie clearing flow. The conditional logic properly gates the cookie clearing behavior based on both the configuration flag and the detected mismatch.

@guitavano guitavano merged commit 3c7a7be into main Dec 10, 2025
2 checks passed
@guitavano guitavano deleted the add-vary-cookie branch December 10, 2025 16:24
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.

2 participants