Skip to content

Conversation

@eduardoformiga
Copy link
Member

@eduardoformiga eduardoformiga commented Jan 21, 2026

What's the purpose of this pull request?

This PR aims to group changes to publish a new version.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced logout functionality with comprehensive browser storage clearance, including sessions, cookies, and local storage.
  • Bug Fixes

    • Resolved Partytown cross-origin errors in iframe environments.
    • Added slug field support to landing page schema.
  • Documentation

    • Improved CLI README with reorganized installation and usage sections.

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

lariciamota and others added 30 commits October 30, 2025 09:26
## What's the purpose of this pull request?

Build our default image loader.

## How it works?

- When the FastStore image component is used, the `faststoreLoader` is
used.
- When the Next image component is used directly, the
`customImageLoader` is used.
- Both have the same behavior when handling images from VTEX (from the
file manager/cms and product images) -- they add to the URL the info
regarding size, quality and aspect, since those VTEX services already
handles optimizations.
- The difference between those loaders is regarding external images --
the one used for Next images uses the Next optimizations, and the
FastStore one doesn't.

It won't be necessary to use a feature flag like
`enableVtexAssetsLoader`.

## How to test it?

<!--- Describe the steps with bullet points. Is there any external link
that can be used to better test it or an example? --->

### Starters Deploy Preview

PR: vtex-sites/faststoreqa.store#881

## References

- [Jira task](https://vtex-dev.atlassian.net/browse/SFS-2878)
- [Slack
thread](https://vtex.slack.com/archives/C03L3CRCDC4/p1761334946034969)
## What's the purpose of this pull request?

Atts.
## What's the purpose of this pull request?

This PR fixes a visual bug in the TextareaField component where long
text would appear underneath the floating label during scroll, making it
difficult to read. The issue was identified during the review of [PR
#2705](#2705 (review)).

Additionally, comprehensive Storybook documentation was added to
showcase all TextareaField variations and use cases.


https://github.com/user-attachments/assets/a86cd4df-e286-40f4-82b0-271a8bc66a26




## How it works?

**Bug Fix:**
- Added `--fs-textarea-field-label-background-color` CSS variable to
`packages/ui/src/components/molecules/TextareaField/styles.scss`
- Set default value to neutral-0 (white) to prevent text from showing
through the label
- When the textarea content is long and the user scrolls, the label now
has an opaque background, preventing text overlap

## How to test it?

**Test the scroll bug fix:**

From the project root:
```bash
pnpm --filter "@faststore/storybook" dev
```

Or navigate to the storybook package:
```bash
cd packages/storybook
pnpm dev
```

Then:
1. Open http://localhost:6006 in your browser
2. Navigate to **"TextareaField"** → **"LargeText"** story
3. Scroll inside the textarea content
4. Verify that the text no longer appears underneath the label

## References
- **Related Issue:** [PR #2705 - TextareaField label overlap issue
identified](#2705 (review))
- **Task:** [SFS-2385 ](https://vtex-dev.atlassian.net/browse/SFS-2385)
## What's the purpose of this pull request?

Revert changes from 
- #2988
since the approach to filter shopper changes to use text field instead
of selected filter in the drawer.

## details

remove purchaseAgentId filter and related components from
`MyAccountListOrders`.

This update removes the purchaseAgentId filter and its associated
components from the MyAccountListOrders section. The changes include:
- Deleting the MyAccountFilterFacetPlacedBy component and its styles.
- Adjusting the MyAccountListOrders and MyAccountSelectedTags components
to eliminate references to purchaseAgentId.
- Cleaning up related styles and imports to streamline the codebase.

These modifications aim to simplify the order filtering process and
improve overall maintainability.
## What's the purpose of this pull request?

From a current Next.js's known issue
([discussion#44013](vercel/next.js#44013)),
these changes aim to add an experimental custom hook to handle scroll
restoration when navigating back from PDPs to PLPs.


https://github.com/user-attachments/assets/9a452081-4c65-4a83-8c16-9775f97d226d

Along with this experimental hook, some adjustments needed to be made to
correct the behavior of related components, such as `Sentinel`.

While the Next.js experimental `scrollRestoration` flag is not working
as it should, we are proposing this FastStore's experimental scroll
restoration alternative.

## How it works?

While navigating through PLPs and loading more pages, when users
navigate to a PDP and navigate back the scroll should be restored to the
last position before the navigation.

### Starters Deploy Preview

vtex-sites/faststoreqa.store#878

## References

#2054
## What's the purpose of this pull request?

Merge the changes from main
## What's the purpose of this pull request?

By using the direction property users will be able to use RTL or LTR
layouts.
## What's the purpose of this pull request?

With these changes, if merchants remove the footer logo the entire
footer component will not be hid anymore, it will throw a console error
but the component should be displayed with no logo.
#3077)

## What's the purpose of this pull request?

This PR fixes the `border-radius` of the Slider thumb in Firefox. The
current CSS rule for Mozilla uses an inexistent variable, making the
browser render a square instead of a circle:

<img width="1028" height="181" alt="image"
src="https://github.com/user-attachments/assets/50c08d79-a6a9-4d31-b2e7-5ef9e287080f"
/>

## How it works?

The `--fs-slider-thumb-radius` variable is replaced by
`--fs-slider-thumb-border-radius`, the one that is defined in the
default thumb variables.

## How to test it?

- Use the `Local Install Instructions` from the [CodeSandbox
CI](https://ci.codesandbox.io/status/vtex/faststore/pr/3077) to add this
version in the `package.json` of a store.
- Import the `Slider` atom (and styles) in a component following the
docs: https://developers.vtex.com/docs/guides/faststore/atoms-slider
- Run the store in development mode and browse it in Mozilla Firefox.

### Starters Deploy Preview

I'm unable to generate a preview link but here's a screenshot from
localhost:

<img width="1287" height="617" alt="image"
src="https://github.com/user-attachments/assets/f0a5a5e9-d657-41db-9415-303b5d17fefd"
/>

## Checklist

**PR Title and Commit Messages**

- [x] PR title and commit messages follow the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification
- Available prefixes: `feat`, `fix`, `chore`, `docs`, `style`,
`refactor`, `ci` and `test`

**PR Description**

- [ ] Added a label according to the PR goal - `breaking change`, `bug`,
`contributing`, `performance`, `documentation`..
_(No permissions. It's a bug though.)_

**Dependencies**

- [N/A] Committed the `pnpm-lock.yaml` file when there were changes to
the packages

**Documentation**

- [x] PR description
- [N/A] For documentation changes, ping `@Mariana-Caetano` to review and
update (Or submit a doc request)
)

## What's the purpose of this pull request?

Adds a new "Pending Approval" filter to the MyAccount orders page,
allowing users to quickly filter orders that require their approval.

## How it works?

- New toggle filter: Added "Pending Approval" as the first filter option
in the orders filter slider
- Toggle switch: Users can turn on/off the filter to show only pending
approval orders
- URL integration: Filter state is reflected in the URL
(?pendingApproval=true)
- Selected tag: When active, shows "Pending my approval" tag below the
search bar

## How to test it?

- Go to /account/orders
- Open filter slider and verify "Pending Approval" is the first option
- Toggle the switch and click "Apply"
- Check URL - should include ?pendingApproval=true
- Verify tag appears - "Pending my approval" tag should show below
search bar
- Test removal - click "×" on tag or "Clear All" to remove filter
- Test direct URL - navigate to /account/orders?pendingApproval=true and
verify filter is active

## Starter deploy preview

vtex-sites/b2bfaststoredev.store#358

## References

[SFS-2618](https://vtex-dev.atlassian.net/browse/SFS-2618)

| List | Filter |
| - | - |
|
![image](https://github.com/user-attachments/assets/70a02298-4461-4b21-926d-8d6b754a78bc)
|
![image](https://github.com/user-attachments/assets/2d6afc76-7153-473a-b839-c141e4f0ca1f)
|

[SFS-2618]:

https://vtex-dev.atlassian.net/browse/SFS-2618?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

[SFS-2618]:
https://vtex-dev.atlassian.net/browse/SFS-2618?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Artur Santiago <artur.santiago@cubos.io>
)

## What's the purpose of this pull request?

Fix a bug that occurs when regionalized and `isSessionReady` is sent in
the' validateSession' and' validateCart' mutations.

## How does it work?

It removes the `isSessionReady` from the session sent to the `setRegion`
method.

<img width="1909" height="916" alt="Screenshot 2025-11-11 at 16 22 55"
src="https://github.com/user-attachments/assets/468cc987-a2ee-432f-b306-399bfd32e891"
/>
## What's the purpose of this pull request?

This PR aims to fix the build in the dev branch.
## What's the purpose of this pull request?

With these changes, a loading skeleton will be displayed when product
price is still being validated, preventing product price flickering on
PDP.

## How to test it?

### Starters Deploy Preview
## What's the purpose of this pull request?

Allow svg files in public folder, avoid it getting deleted/overwritten
when generating .faststore

## How it works?

Add it to the allow list.

## How to test it?

Create a svg file or modify an existing svg file, it should be copied
correctly to the `/.faststore/public` when running the build command.
You can use this PR to test:
vtex-sites/faststoreqa.store#887, I've added a
new svg file and changed an existing one, before it was being
deleted/overwritten.
<img width="287" height="420" alt="Screenshot 2025-11-20 at 09 57 19"
src="https://github.com/user-attachments/assets/7b01d806-bdf9-4c3b-a385-32ea11ab2518"
/>

Nothing else should change.

### Starters Deploy Preview

- https://storeframework-cm652ufll028lmgv665a6xv0g-h0max2o2h.b.vtex.app/

## References
- [Jira task](https://vtex-dev.atlassian.net/browse/SO-559)
## What's the purpose of this pull request?

This PR considers the session when deducing the changes to the orderForm
done externally.

## What it aims to solve

The current FastStore shows a competing nature when dealing with the
same cart on two different devices (E.g. 2 browsers, Chrome and
Firefox).

### How to reproduce the problem

- Open your store in Chrome and Firefox
- Make note of the checkout.vtex.com cookie value of Chrome and view the
content of the orderForm using a client like Postman
- Paste the value of the cookie to the checkout cookie of Firefox
- Now you should have the same orderForm in Chrome, Firefox and Postman
- Add an item to the cart from Chrome
- Without going to Firefox, verify that the item is present in the
orderForm using Postman
- Now go to Firefox, but you will not see the item (Expected: the item
should be present in the cart, Actual: the browser cart in Firefox will
override the items of the real orderForm object)
- Open Postman, and you will notice that the item is not present in the
orderForm
- Now go back to Chrome, and it will add back the item to the orderForm
- Open Postman, and you will notice that the item is present in the
orderForm

## How it works?

We include the session ID to the MD5 hash, so that when the store is
used in a different browser with the same orderForm, the two hashes are
different. The two browsers should respect the changes performed by each
other.

## How to test it?

- First verify that the existing behavior of the mutation `validateCart`
is as expected.
- Follow the steps under **How to reproduce the problem**, and verify
that the expected behavior is observed.

### Starters Deploy Preview

<!--- Add a link to a deploy preview from `starter.store` with this
branch being used. --->

<!--- Tip: You can get an installable version of this branch from the
CodeSandbox generated when this PR is created. --->

## References

<!--- Spread the knowledge: is there any content you used to create this
PR that is worth sharing? --->

<!--- Extra tip: adding references to related issues or mentioning
people important to this PR may be good for the documentation and
reviewing process --->

## Checklist

<em>You may erase this after checking them all 😉</em>

**PR Title and Commit Messages**

- [ ] PR title and commit messages follow the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification
- Available prefixes: `feat`, `fix`, `chore`, `docs`, `style`,
`refactor`, `ci` and `test`

**PR Description**

- [ ] Added a label according to the PR goal - `breaking change`, `bug`,
`contributing`, `performance`, `documentation`..

**Dependencies**

- [ ] Committed the `pnpm-lock.yaml` file when there were changes to the
packages

**Documentation**

- [ ] PR description
- [ ] For documentation changes, ping `@Mariana-Caetano` to review and
update (Or submit a doc request)
## What's the purpose of this pull request?

This PR aims to fix the source code to show `undefined` `searchTerm`.
<img width="916" height="811" alt="Screenshot 2025-11-20 at 19 01 42"
src="https://github.com/user-attachments/assets/b07e44a4-9e37-45e3-9712-6ab19b1af758"
/>


## How it works?

1. The source code can't access the searchTerm from the build time;
thus, this page uses the default
<img width="1899" height="656" alt="Screenshot 2025-11-20 at 18 42 43"
src="https://github.com/user-attachments/assets/697d1b4a-e5cb-4325-a5a1-3ba5d429b7b3"
/>

2. The final code (runtime code after hydration, you can see the element
tab in the devtools), can access the dynamic search term and uses it.
<img width="1570" height="1049" alt="Screenshot 2025-11-20 at 18 42 05"
src="https://github.com/user-attachments/assets/04e0a613-950f-4416-9200-dcc239326b41"
/>

## How to test it?

You can run `pnpm build && pnpm serve` and view the source code
(right-click> Source Code). Additionally, you can view the final code
using the Element tab in the DevTools.
vtexgithubbot and others added 20 commits December 23, 2025 22:58
…low and correct comment in discovery configuration
…ows, update Node.js version to 18 in release workflow, and refine comment in discovery configuration
## What's the purpose of this pull request?

This PR aims to clear storage data (cookies, session, local storage,
indexedDB) when logging out before redirecting to the identity URL.

## How it works?

It clears the browser data, beyond calling the new /api/fs/logout URL,
so that we can clear httpOnly cookies.

## How to test it?

You can use a temporary version from the sandbox, enable the `My
Account` experimental flag, and simulate a login in an account like
`b2bfaststoredev`. After that you can click the logout button and
compare the browser storage data.
1. login
2. add items to the cart
3. logout
4. see that the item is gone.

### Starters Deploy Preview

https://b2bfaststore.vtexfaststore.com/
## What's the purpose of this pull request?

We noticed the slug field (for preview and page creation) is not present
in the newest CMS schema for FS.

## How it works?

<img width="939" height="173" alt="image"
src="https://github.com/user-attachments/assets/ade6bc02-78bb-4021-9483-9b78b4bde2c7"
/>

## How to test it?


https://usb2bstore.myvtex.com/admin/content-platform/branches/main/form/faststore/landingPage/entries/b9a51bfe-3ce4-4f61-8e82-2542466a9728

Editing the slug and preview the page, it should work

## References

[PR adding the schemas](#3071)
)

## What's the problem this PR addresses?

  When FastStore is loaded inside an iframe (such as VTEX
  Preview), Partytown throws a SecurityError: Failed to read a 
  named property 'dispatchEvent' from 'Window' due to
  cross-origin restrictions. This prevents the preview from
  working correctly.

  ## Changes Made:

  - Modified ThirdPartyScripts.tsx to dynamically import
  Partytown only on client-side
## What's the purpose of this pull request?

<!--- Considering the context, what is the problem we'll solve? Where in
VTEX's big picture our issue fits in? Write a tweet about the context
and the problem itself. --->

## How it works?

<!--- Tell us the role of the new feature, or component, in its context.
Provide details about what you have implemented and screenshots if
applicable. --->

## How to test it?

<!--- Describe the steps with bullet points. Is there any external link
that can be used to better test it or an example? --->

### Starters Deploy Preview

<!--- Add a link to a deploy preview from `starter.store` with this
branch being used. --->

<!--- Tip: You can get an installable version of this branch from the
CodeSandbox generated when this PR is created. --->

## References

<!--- Spread the knowledge: is there any content you used to create this
PR that is worth sharing? --->

<!--- Extra tip: adding references to related issues or mentioning
people important to this PR may be good for the documentation and
reviewing process --->

## Checklist

<em>You may erase this after checking them all 😉</em>

**PR Title and Commit Messages**

- [ ] PR title and commit messages follow the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification
- Available prefixes: `feat`, `fix`, `chore`, `docs`, `style`,
`refactor`, `ci` and `test`

**PR Description**

- [ ] Added a label according to the PR goal - `breaking change`, `bug`,
`contributing`, `performance`, `documentation`..

**Dependencies**

- [ ] Committed the `pnpm-lock.yaml` file when there were changes to the
packages

**Documentation**

- [ ] PR description
- [ ] For documentation changes, ping `@Mariana-Caetano` to review and
update (Or submit a doc request)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Added repository-level configuration for automated code review:
auto-review on the dev base, auto-reply in review chat, and a relaxed
("chill") review profile with high-level summaries enabled while
request-changes workflow is disabled.
* Included path-specific review guidance for components, pages, SDK,
API, and TypeScript files, plus filters to exclude
build/output/generated directories.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Leandro Rodrigues <leandro.rodrigues@vtex.com>
…esent (#3178)

## What's the purpose of this pull request?

This PR aims to prioritize the checkout cookie in the `validateCart`
mutation, and clear the cart after an order is placed in FastCheckout.


## How it works?

- If this cookie is present, we should use it.
- If this cookie is not present, we should get a new orderForm (and a
new cookie) with an empty cart.

Previously, when the cookie was absent, we were retrieving the old
`indexedDB` cart value from the `orderForm`, which caused the cart to
retain items after an order is placed in FastCheckout.

see this thread and video

https://vtex.slack.com/archives/C08QH7W3C2Y/p1768601252009199?thread_ts=1756491477.629329&cid=C08QH7W3C2Y
@eduardoformiga eduardoformiga requested a review from a team as a code owner January 21, 2026 14:58
@eduardoformiga eduardoformiga requested review from hellofanny and ommeirelles and removed request for a team January 21, 2026 14:58
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Walkthrough

This PR introduces resilience improvements to VTEX orderForm API calls by making the ID parameter optional, refactors the validateCart resolver flow, and implements a new logout feature with comprehensive browser storage clearing. Additional changes include a landing page schema slug field, Partytown cross-origin error prevention, and documentation updates.

Changes

Cohort / File(s) Summary
VTEX Commerce API
packages/api/src/platforms/vtex/clients/commerce/index.ts, packages/api/src/platforms/vtex/resolvers/validateCart.ts
Made orderForm ID parameter optional; conditionally includes refreshOutdatedData in query params and omits body when ID is absent. Updated validateCart to fetch orderForm using cookie-derived ID and reordered data extraction to align with new retrieval pattern.
VTEX Integration Tests
packages/api/test/integration/mutations.test.ts, packages/api/test/mocks/ValidateCartMutation.ts
Added orderFormCookie to integration test headers; reordered query parameters in mock endpoint URLs to align with updated orderForm API calls.
Logout & Storage Clearing
packages/core/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx, packages/core/src/pages/api/fs/logout.ts, packages/core/src/utils/clearCookies.ts, packages/core/test/utils/clearCookies.test.ts
Introduced new logout flow with async storage clearing (sessionStorage, IndexedDB, VTEX cookies), server-side API route for cookie expiration via Set-Cookie headers, and utility functions for multi-domain/path cookie removal across client and server contexts. Comprehensive test coverage for cookie utilities.
Schema & Rendering Fixes
packages/core/cms/faststore/pages/cms_content_type__landingpage.jsonc, packages/core/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx
Added slug field to landing page schema; added guard condition to prevent Partytown rendering in cross-origin iframe contexts.
Documentation
packages/cli/CHANGELOG.md, packages/cli/README.md, packages/core/CHANGELOG.md
Added pre-release version entries and expanded CLI README with structured Usage, Installation, and Commands sections.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Drawer as OrganizationDrawer Component
    participant Storage as Browser Storage
    participant API as /api/fs/logout
    participant VTEX as VTEX Logout

    User->>Drawer: Click logout
    Drawer->>Storage: Clear sessionStorage keys
    Drawer->>Storage: Clear __fs_gallery_page_* keys
    Drawer->>Storage: Clear IndexedDB keyval-store
    Drawer->>API: POST with credentials + cookies
    API->>API: Extract & derive cookie domains/paths
    API->>API: Expire VTEX & additional cookies
    API->>Drawer: Return Set-Cookie headers + 200
    Drawer->>Drawer: Apply Set-Cookie headers
    Drawer->>VTEX: Redirect to VTEX logout endpoint
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • hellofanny
  • ommeirelles

Poem

🔐 A logout dance, both swift and clean,
Cookie crumbs swept from the browser scene—
VTEX paths and domains untangled with care,
Storage erased, no trace left there.
The orderForm bends to optional might,
Resilience blooms in the Faststore light! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'chore: version 2026 21 1144' is vague and does not convey meaningful information about the actual changes; it merely references a version number without describing what was fixed or implemented. Consider using a more descriptive title that highlights the primary change, such as 'chore: logout storage clearing and Partytown iframe handling' or similar, to help reviewers quickly understand the changeset's main purpose.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 21, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Copy link

@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

🤖 Fix all issues with AI agents
In `@packages/core/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx`:
- Around line 40-43: The current conditional render in ThirdPartyScripts.tsx
uses typeof window !== 'undefined' && window.self === window.top which differs
between SSR and client and causes hydration mismatch; update the
ThirdPartyScripts component to perform the iframe/top check only on the client
by introducing local state (e.g., isTopWindow) and setting it inside a useEffect
that runs on mount, then render <Partytown /> only when that state is true;
reference the ThirdPartyScripts component, the Partytown JSX element, and
useEffect/state to locate and modify the code.
🧹 Nitpick comments (6)
packages/core/test/utils/clearCookies.test.ts (1)

112-140: Weak test assertions for expireCookieClient.

The tests for expireCookieClient with domain and secure flags only verify that the function doesn't throw, but don't verify the actual cookie string being set. While jsdom has limitations for domain-specific cookies, you could spy on document.cookie setter to verify the correct string is constructed.

💡 Optional: Add spy-based assertion
 it('should expire a cookie with domain', () => {
-  document.cookie = 'test-cookie=value; path=/; domain=.example.com'
-
-  expireCookieClient({
-    name: 'test-cookie',
-    path: '/',
-    domain: '.example.com',
-  })
-
-  // Note: We can't easily verify domain-specific cookies in jsdom,
-  // but we can verify the function doesn't throw
-  expect(() => {
-    expireCookieClient({
-      name: 'test-cookie',
-      path: '/',
-      domain: '.example.com',
-    })
-  }).not.toThrow()
+  const cookieSpy = jest.spyOn(document, 'cookie', 'set')
+  
+  expireCookieClient({
+    name: 'test-cookie',
+    path: '/',
+    domain: '.example.com',
+  })
+
+  expect(cookieSpy).toHaveBeenCalledWith(
+    expect.stringContaining('test-cookie=; expires=Thu, 01 Jan 1970')
+  )
+  expect(cookieSpy).toHaveBeenCalledWith(
+    expect.stringContaining('domain=.example.com')
+  )
+  cookieSpy.mockRestore()
 })
packages/core/src/pages/api/fs/logout.ts (2)

17-24: Consider adding CSRF protection.

This endpoint clears authentication cookies via POST. While it requires the request to include cookies (credentials: 'include' on client), there's no CSRF token validation. An attacker could potentially trigger logout via a cross-site request.

Consider adding a CSRF token check or verifying the Origin/Referer header matches your domain:

 const handler: NextApiHandler = async (
   request: NextApiRequest,
   response: NextApiResponse
 ) => {
   if (request.method !== 'POST') {
     response.status(405).end()
     return
   }

+  // Basic CSRF check - verify origin matches host
+  const origin = request.headers.origin
+  const host = request.headers.host
+  if (origin && host && !origin.includes(host.split(':')[0])) {
+    response.status(403).json({ success: false, error: 'Forbidden' })
+    return
+  }

68-73: Error logging exposes internal details.

Logging the full error object could expose sensitive information in server logs.

🔒 Sanitize error logging
   } catch (error) {
-    console.error('Error clearing cookies:', error)
+    console.error('Error clearing cookies:', error instanceof Error ? error.message : 'Unknown error')
     response
       .status(500)
       .json({ success: false, error: 'Failed to clear cookies' })
   }
packages/core/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx (2)

22-54: Silent error swallowing obscures debugging.

Multiple nested try/catch blocks with empty catches make debugging difficult. Consider at least logging errors in development mode.

🔧 Optional: Add development-only logging
     for (const key of sessionStorageKeys) {
       try {
         window.sessionStorage?.removeItem(key)
-      } catch {}
+      } catch (e) {
+        if (process.env.NODE_ENV === 'development') {
+          console.debug('Failed to remove sessionStorage key:', key, e)
+        }
+      }
     }

73-81: O(n³) cookie clearing loop could be slow with many cookies.

The triple nested loop (names × paths × domains) could become slow if there are many VTEX cookies. For typical cases this is fine, but worth noting.

The current implementation is correct and defensive. If performance becomes an issue with many cookies, consider batching or parallel execution.

packages/core/src/utils/clearCookies.ts (1)

1-12: Consider exporting type definitions.

The ExpireCookieClientParams and ExpireCookieServerParams types are useful for consumers of these utilities but aren't exported.

-type ExpireCookieClientParams = {
+export type ExpireCookieClientParams = {
   name: string
   path: string
   domain?: string
   secure?: boolean
 }

-type ExpireCookieServerParams = {
+export type ExpireCookieServerParams = {
   name: string
   path: string
   domain?: string
 }

Comment on lines +40 to +43
{/* Only render Partytown when not in an iframe to prevent cross-origin errors. */}
{typeof window !== 'undefined' && window.self === window.top && (
<Partytown key="partytown" />
)}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential hydration mismatch with window check in JSX.

The typeof window !== 'undefined' check evaluates differently between SSR (false) and client hydration (true), causing a hydration mismatch. During SSR, Partytown won't be included in the HTML, but React will try to render it during hydration.

Consider using a useEffect with state to handle the iframe detection client-side only:

🔧 Suggested fix
+import { useState, useEffect } from 'react'
+
 function ThirdPartyScripts() {
   const forwards = []
   if (includeVTEX) forwards.push('sendrc')
+  
+  const [shouldRenderPartytown, setShouldRenderPartytown] = useState(true)
+  
+  useEffect(() => {
+    // Disable Partytown in iframe contexts to prevent cross-origin errors
+    if (window.self !== window.top) {
+      setShouldRenderPartytown(false)
+    }
+  }, [])

   return (
     <>
       {/* ... existing code ... */}
-      {/* Only render Partytown when not in an iframe to prevent cross-origin errors. */}
-      {typeof window !== 'undefined' && window.self === window.top && (
-        <Partytown key="partytown" />
-      )}
+      {shouldRenderPartytown && <Partytown key="partytown" />}
     </>
   )
 }
🤖 Prompt for AI Agents
In `@packages/core/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx` around
lines 40 - 43, The current conditional render in ThirdPartyScripts.tsx uses
typeof window !== 'undefined' && window.self === window.top which differs
between SSR and client and causes hydration mismatch; update the
ThirdPartyScripts component to perform the iframe/top check only on the client
by introducing local state (e.g., isTopWindow) and setting it inside a useEffect
that runs on mount, then render <Partytown /> only when that state is true;
reference the ThirdPartyScripts component, the Partytown JSX element, and
useEffect/state to locate and modify the code.

@eduardoformiga eduardoformiga merged commit e5fde28 into main Jan 21, 2026
8 of 9 checks passed
@eduardoformiga eduardoformiga deleted the release/version-2026-21-1144 branch January 21, 2026 15:07
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.