Skip to content

fix(ep-commerce): resolve checkout cart id server-side and test the cookie → shopper-bearer path (#387 leftovers) #415

Description

@field123

Carried over from #387, whose headline defect (checkout-context reading the session wrongly, so shopperAccessToken was always "") was fixed by #393 and is now closed. These two items from that issue were not part of the fix.

1. Resolve the checkout cart id in the package, not by patching the request body

examples/ep-commerce-app-router/app/api/checkout/sessions/route.ts still injects the server-resolved cart id into the request body before handing off:

const { ctx, epCartId } = await buildCheckoutContext(req);
const sreq = await toSessionRequest(req);
// Inject server-resolved cartId when client didn't pass one.
if (!sreq.body.cartId && epCartId) {
  sreq.body = { ...sreq.body, cartId: epCartId };
}
const sres = await handleCreateSession(sreq, ctx);

This is a workaround, and it can't simply be deleted: SessionHandlerContext (src/checkout/session/types.ts:231-248) has no cart-id field, so handleCreateSession has no server-side source for the cart.

The example is what implementors copy, so the body-patching pattern propagates. It also means the trust boundary reads oddly — a server-resolved value is laundered through client-shaped request body.

Suggested shape: carry the shopper's cart id on SessionHandlerContext (alongside shopperAccessToken, which is already resolved the same way, from the same session, by the same factory), have handleCreateSession prefer it over body.cartId, then drop the injection from the example route.

Worth deciding explicitly whether a client-supplied cartId should still be honoured when the session carries one, or be rejected as a mismatch.

  • Add a cart-id field to SessionHandlerContext
  • handleCreateSession reads it server-side; settle the client-supplied-cartId precedence question
  • Remove the body injection from the example route

2. Test the cookie → shopper-bearer path

No test covers the link that silently broke. All four tests referencing shopperAccessTokencart-shipping, pay, pay-single-shot, security-regression — inject the token directly into ctx, so they'd have passed throughout the entire window the example was broken.

  • Test: a checkout-session create with valid shopper cookies uses the shopper bearer (mock EP asserts the Authorization header), not the admin client_credentials grant
  • Cover the fallback too: no/invalid shopper cookies should not silently succeed on the admin token

Note when adding tests: this package runs both a jest and a vitest suite. yarn jest alone misses vitest — run yarn test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions