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.
2. Test the cookie → shopper-bearer path
No test covers the link that silently broke. All four tests referencing shopperAccessToken — cart-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.
Note when adding tests: this package runs both a jest and a vitest suite. yarn jest alone misses vitest — run yarn test.
Carried over from #387, whose headline defect (checkout-context reading the session wrongly, so
shopperAccessTokenwas 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.tsstill injects the server-resolved cart id into the request body before handing off:This is a workaround, and it can't simply be deleted:
SessionHandlerContext(src/checkout/session/types.ts:231-248) has no cart-id field, sohandleCreateSessionhas 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(alongsideshopperAccessToken, which is already resolved the same way, from the same session, by the same factory), havehandleCreateSessionprefer it overbody.cartId, then drop the injection from the example route.Worth deciding explicitly whether a client-supplied
cartIdshould still be honoured when the session carries one, or be rejected as a mismatch.SessionHandlerContexthandleCreateSessionreads it server-side; settle the client-supplied-cartIdprecedence question2. Test the cookie → shopper-bearer path
No test covers the link that silently broke. All four tests referencing
shopperAccessToken—cart-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.Authorizationheader), not the adminclient_credentialsgrantNote when adding tests: this package runs both a jest and a vitest suite.
yarn jestalone misses vitest — runyarn test.