Skip to content

August 2026

The changes in the August 2026 releases that ask something of your project, newest first. See the August 2026 highlights for everything else that changed. Each one names the first version of each package that has it: you need the change only when you move from below that version to it or above. Where a later change replaced part of an earlier one, the earlier one says so: do what the later one asks.

The storefront packages need Next.js 16.2.11 or later

Section titled “The storefront packages need Next.js 16.2.11 or later”

In: commerce-ui 0.7.0, errors 0.3.0, feature-account 0.6.0, feature-auth 0.5.0, feature-cart 0.8.0, feature-invoice 0.8.0, feature-order 0.11.0, feature-organization 0.8.0, feature-quote 0.12.0, feature-return 0.7.0, feature-shopping-list 0.7.0, layout 0.3.0, ui 0.9.0

These packages declare next as a peer dependency, >=16.2.11 <17. Install Next.js 16.2.11 or later in your storefront.

In: cloud-adapter-gcp 0.4.0, commercetools-adyen 0.4.0, commercetools-buckaroo 0.4.0, commercetools-mollie 0.4.0, commercetools-paynl 0.4.0, commercetools-stripe 0.4.0, commercetools 0.11.0, contentful 0.6.0, core 1.2.0, mcp-core 1.2.0, medusa 0.4.0, payload 0.3.0, search 0.3.0, sfcc 0.8.0, sitemap 0.2.0, storyblok 0.5.0

The fastify peer range is >= 5.12.1 < 6.0.0, because earlier versions have a security flaw in trustProxy. Install Fastify 5.12.1 or later.

If you pass a number to trustProxy, such as http: { trustProxy: 1 } on createApplication, it no longer type-checks, and Fastify grants no trust at all, so request.ip becomes the nearest proxy. Pass the proxies’ IP addresses or CIDR ranges, or a function, instead.

In: commercetools 0.11.0

Each module asks only for the custom type keys of the resources it writes fields onto, and a missing key now stops the service at startup:

Module Keys
CartModule order, line-item
MultipleCartModule order
CheckoutModule payment (no longer needed from commercetools 0.14.0)
PaymentModule payment
CustomerModule customer

business-unit is no longer part of CustomTypeKeys. Remove it from the object you pass, but keep the custom type itself provisioned: the framework still reads its fields. One object with every key, passed to each module, keeps working as long as it is a variable and not an inline literal.

LoadedPackage.commands is a map of loaders

Section titled “LoadedPackage.commands is a map of loaders”

In: cli 0.4.0, commercetools 0.11.0, contentful 0.6.0, storyblok 0.5.0

This affects only code that uses the CLI programmatically, not the evolve command. Call the loader to get a command’s class:

const cls = await loaded.commands.get("eject")?.();

The evolve command now finds the commands of every package in your dependencies. Contentful and Storyblok both provide eject and tf-export, so a project that depends on both runs those two with --package.

In: commercetools-buckaroo 0.4.0

A shopper used to land on your success URL whether the payment succeeded, failed, or was cancelled. Now:

Outcome Lands on
Paid, for an order successUrl?success=true&orderId=…
Paid, for an invoice successUrl?success=true&invoiceId=…
Paid, for a cart successUrl?success=true&targetType=cart&targetId=…
Cancelled, failed, or pending failureUrl?success=false&reason=…&targetId=…&targetType=…

Check that your return pages handle these parameters.

In: commercetools-mollie 0.4.0, commercetools 0.11.0

Pass the settling Payment instead of its id. Code that pays through paymentCreate is not affected.

In: commercetools-stripe 0.4.0, commercetools 0.11.0, schemas 0.11.0

An order stays OPEN until the merchant’s own system accepts it, even after it is paid. If your storefront reads orderStatus PROCESSING as “paid”, read Order.paymentState instead. For local development, confirm an order with the simulator (simulate order confirm from commercetools 0.13.0).

Customer.addresses is paged and searchable

Section titled “Customer.addresses is paged and searchable”

In: commercetools 0.11.0, medusa 0.4.0, schemas 0.11.0, sfcc 0.8.0

Move your selection under items:

customer {
addresses { items { id city } pagination { totalCount hasNextPage } }
}

A schema module that declares an AddressResult field must also compose paginationSnippet.

updateTarget and settleTarget may return no order

Section titled “updateTarget and settleTarget may return no order”

In: commercetools-adyen 0.4.0, commercetools-pay-on-account 0.4.0, commercetools-paynl 0.4.0, commercetools-stripe 0.4.0, commercetools 0.11.0, schemas 0.11.0

paymentCreate can now pay an invoice, which settles no order, so both functions return Order | undefined. A custom payment adapter that uses the returned order needs a check for undefined. Add the paidByPayment field to your payment custom type.

A role’s permissions outrank roleCapabilities

Section titled “A role’s permissions outrank roleCapabilities”

In: commercetools 0.11.0

The capabilities of a business unit role now come from its commercetools permissions first, then from your roleCapabilities override, then from the framework defaults. There is nothing to run. After upgrading, check your logs: an override that no longer applies is logged as a warning with the role key. If a role shows up there, change its permissions in commercetools.

MANAGE_ORDERS and MANAGE_APPROVALS are split

Section titled “MANAGE_ORDERS and MANAGE_APPROVALS are split”

In: commercetools 0.11.0, medusa 0.4.0, schemas 0.11.0

Removed Replaced by
MANAGE_ORDERS MANAGE_MY_ORDERS, MANAGE_OTHERS_ORDERS
MANAGE_APPROVALS DECIDE_APPROVALS, MANAGE_APPROVAL_RULES

Replace each in your gates with the half the gate means. A gate for “may act at all” needs both. VIEW_OTHERS_CARTS is new. Of the default roles, supervisor is new, and admin does not hold DECIDE_APPROVALS.

Associate permissions decide who may change a cart

Section titled “Associate permissions decide who may change a cart”

In: commercetools 0.11.0, schemas 0.11.0

Inside a business unit, cart writes go through the associate endpoint, so commercetools checks the associate’s role. Before you upgrade, check that your roles grant what your buyers do today:

  • UpdateMyCarts and DeleteMyCarts, or a buyer cannot change or delete their own cart.
  • CreateMyOrdersFromMyCarts, or checkout fails at the last step.
  • UpdateOthersCarts, DeleteOthersCarts, and CreateOrdersFromOthersCarts, where colleagues work on each other’s carts.

Handle the new error code CART_NOT_PERMITTED.

core, federated-token, and graphql-yoga become peer dependencies

Section titled “core, federated-token, and graphql-yoga become peer dependencies”

In: cloud-adapter-aws 0.2.0, cloud-adapter-azure 0.3.0, cloud-adapter-gcp 0.4.0, commercetools-adyen 0.4.0, commercetools-buckaroo 0.4.0, commercetools-mollie 0.4.0, commercetools-pay-on-account 0.4.0, commercetools-paynl 0.4.0, commercetools-stripe 0.4.0, commercetools 0.11.0, contentful 0.6.0, core 1.2.0, json-schema-to-zod 0.2.0, mcp-core 1.2.0, medusa 0.4.0, payload 0.3.0, search-algolia 0.1.0, search 0.3.0, sfcc 0.8.0, sitemap 0.2.0, storyblok 0.5.0, user-notifications 0.3.0

Add these to your own dependencies if they are not there yet, in the range the packages ask for:

Package Range
@evolve-framework/core >= 1.0.0 < 2.0.0
@labdigital/federated-token >= 3.0.0 < 4.0.0, since the same release moved to 3.0.0
graphql-yoga >= 5.21.3 < 6.0.0

Adapters take their engine as a peer dependency

Section titled “Adapters take their engine as a peer dependency”

In: commercetools-adyen 0.4.0, commercetools-buckaroo 0.4.0, commercetools-mollie 0.4.0, commercetools-pay-on-account 0.4.0, commercetools-paynl 0.4.0, commercetools-stripe 0.4.0, search-algolia 0.1.0, search-meilisearch 0.2.0

Add the engine package to your own dependencies: @evolve-framework/commercetools (>= 0.10.0 < 2.0.0) for a commercetools payment provider, and @evolve-framework/search (>= 0.2.0 < 2.0.0) for a search adapter.

In: commercetools-adyen 0.4.0, commercetools-buckaroo 0.4.0, commercetools-mollie 0.4.0, commercetools-pay-on-account 0.4.0, commercetools-paynl 0.4.0, commercetools 0.11.0, schemas 0.11.0

  • Rename issuers to options in your queries and in any adapter you wrote. The type PaymentMethodIssuer is now PaymentMethodOption.
  • Remove a bank picker for iDEAL: the shopper picks their bank on the provider’s page. Stop sending arguments.issuer with a payment.

In: commercetools-pay-on-account 0.4.0, commercetools 0.11.0

  • Remove initialPaymentStateKey from CheckoutModule and PaymentModule. DEFAULT_INITIAL_PAYMENT_STATE_KEY is gone.
  • Remove creditGrantedPaymentStateKey from PayOnAccountPaymentAdapter.
  • Provision payment states with exactly these keys: PaymentInitial (with initial: true), PaymentPending, PaymentSuccess, PaymentFailure, PaymentRefunded, PaymentCancelled, and PaymentCreditGranted. Payments are always created in a state now.

The keys are exported as PAYMENT_STATES and PAYMENT_STATE_KEYS from @evolve-framework/commercetools/payments.

In: commercetools-pay-on-account 0.4.0, commercetools 0.11.0

At checkout, a payment on account moves into the credit granted state, records no transaction, and the order settles as CreditOwed. Paying the invoice later moves the order to Paid. This change made the adapter require creditGrantedPaymentStateKey, but the same release removed that option again: provision the PaymentCreditGranted state instead (see Payment state keys are fixed).

Three custom fields move to the business unit

Section titled “Three custom fields move to the business unit”

In: commercetools-pay-on-account 0.4.0, commercetools-paynl 0.4.0, commercetools 0.11.0, schemas 0.11.0

  • Pay on account is granted to a business unit, through its canPayOnAccount Boolean. It replaces the customer’s payPerInvoice field, and a shopper outside a business unit cannot pay on account. CT_CUSTOMER_CUSTOM_FIELD_PAY_ON_ACCOUNT, PAY_ON_ACCOUNT_ACTIVATED, and PAY_ON_ACCOUNT_ON_HOLD are replaced by CT_BUSINESS_UNIT_CUSTOM_FIELD_PAY_ON_ACCOUNT.
  • Pay.nl reads the VAT number from vatNumber on the business unit, not from the order’s vatId. CT_ORDER_CUSTOM_FIELD_VAT_ID is gone.
  • Customer.registrationNumber is removed from the schema.

Add canPayOnAccount (Boolean) and vatNumber (String) to your business unit custom type, and copy the values over from the customer and order types.

PaymentCreateResponse.redirect is now next

Section titled “PaymentCreateResponse.redirect is now next”

In: commercetools 0.11.0, schemas 0.11.0

next says whether the shopper goes to the provider or the payment is done. Replace redirect { redirectUrl } in your paymentCreate selection:

next {
... on PaymentRedirect { redirectUrl }
... on PaymentComplete { order { id } }
}

Payments and line items carry a custom type

Section titled “Payments and line items carry a custom type”

In: commercetools 0.11.0

CustomTypeKeys gained payment and line-item, and a payment and a line item are now created with their custom type. Code that calls the paymentCreate helper directly passes the locale and the payment type key as one object: paymentCreate(adapter, ctApi, args, { fallbackLocale, customTypeKey }). Which module needs which key changed again in the same release: see Custom type keys are asked for per module.

In: commercetools 0.11.0, medusa 0.4.0, schemas 0.11.0, sfcc 0.8.0

This affects you only if you implement Order for an engine of your own. The field is non-null, so resolve it, for example from your payment state.

In: commercetools 0.11.0

CartModule, MultipleCartModule, and CustomerModule require customTypes, with the keys of the custom types your project provisions. Hold one object and pass it to each module. CART_CUSTOM_TYPE_KEY and NOTIFICATION_PREFERENCES_TYPE_KEY are gone. Carts and customers are created with their type, and a service refuses to start when a configured type does not exist. For tests, @evolve-framework/commercetools/testing exports provisionCustomTypes, provisionPaymentStates, and TEST_CUSTOM_TYPES. The keys each module needs changed again in the same release: see Custom type keys are asked for per module.

Order.shippingNotice is replaced by deliveryRemarks

Section titled “Order.shippingNotice is replaced by deliveryRemarks”

In: commercetools 0.11.0, schemas 0.11.0

The old field always returned a placeholder. Select Order.deliveryRemarks. To use the fields this release reads, add them to your custom types: cocNumber, vatNumber, and defaultPaymentMethod on the business unit, defaultPaymentMethod on the customer, and deliveryRemarks on the cart and order type.

In: commercetools 0.10.0, schemas 0.10.0

PaymentContextInput.orderId and the ORDER_ID_REQUIRED error code are gone. Name what you pay in target:

paymentCreate(
target: { id: $orderId, type: ORDER }
paymentContext: { … }
)

PaymentErrorCodeType gained TARGET_NOT_FOUND, TARGET_NOT_PAYABLE, ORDER_AWAITING_APPROVAL, PAYMENT_IN_PROGRESS, and TRANSACTION_START_FAILED. This release also added initialPaymentStateKey to PaymentModule, which commercetools 0.11.0 removed again.

The secret name settings for commercetools are gone

Section titled “The secret name settings for commercetools are gone”

In: commercetools 0.10.0

CTP_CREDENTIALS_SECRET_NAME and CTP_USER_CREDENTIALS_SECRET_NAME are ignored. Remove them, and set CTP_CLIENT_ID and CTP_CLIENT_SECRET instead.

In: config 0.2.0, commercetools 0.10.0, contentful 0.5.0, mcp-core 1.1.0, medusa 0.3.0, sfcc 0.7.0, storyblok 0.4.3

export const loadConfig = async (): Promise<void> => {
config.load({ prefix: "PURCHASE_" });
await config.load({ prefix: "PURCHASE_" });
};

CommercetoolsConfig and MCPCoreConfig now extend the base class from @evolve-framework/config. A config class that extends either adds that package to its dependencies, and imports envfield, EnviConfig, and BaseConfig from it instead of from @labdigital/enviconf. Two smaller changes: a string field is no longer parsed as JSON, and an empty value counts as set.

In: core 1.1.0, commercetools 0.10.0, search 0.2.0, sitemap 0.1.0

PaymentProviderModule, SearchIndexerModule, and SitemapModule no longer serve /healthcheck, and their name option is gone. Compose HealthModule next to them:

new CompositeModule<CommercetoolsLoaderContext>([
new PaymentProviderModule({ adapter }),
new HealthModule({ name: "commercetools-adyen", graphql: false }),
]);

The body of /healthcheck becomes { componentName, ok, release }. A probe that checks only the status code is not affected.

commercetools-invoice is renamed commercetools-pay-on-account

Section titled “commercetools-invoice is renamed commercetools-pay-on-account”

In: commercetools-pay-on-account 0.3.0

  1. Replace the dependency @evolve-framework/commercetools-invoice with @evolve-framework/commercetools-pay-on-account, and update the imports.
  2. Rename InvoicePaymentAdapter to PayOnAccountPaymentAdapter, and InvoicePaymentAdapterOptions to PayOnAccountPaymentAdapterOptions.
  3. Rename the service or health check name commercetools-invoice in your deploy config.

This release also renamed the PAY_PER_INVOICE_* constants, which commercetools-pay-on-account 0.4.0 removed (see Three custom fields move to the business unit).

In: commercetools 0.8.0, contentful 0.4.0, core 0.7.0, sfcc 0.6.0, storyblok 0.4.0

A service no longer builds context.loaders itself:

  1. Remove loaders from your context factory, including any placeholder or merge of two packages’ loaders.
  2. Name your context where you compose the modules: new CompositeModule<ContextValue>([...]).
  3. Make sure the context carries what the loaders read: storeContext, clientContext, and globalScopedClient for commercetools, also clientFactory for SFCC, and request for Contentful and Storyblok.

The commercetools and SFCC packages split RequestContextValue, what your factory builds, from ContextValue, what resolvers read. Extend RequestContextValue in your factory. A service can no longer compose commercetools and SFCC together. See Caching and performance.

Cart.id is stable, and version is its own field

Section titled “Cart.id is stable, and version is its own field”

In: commercetools 0.7.0, schemas 0.7.0

Cart.id used to be "<id>:<version>". It is now the bare id, and the version is in Cart.version. Stop splitting the id. The cart mutations take an optional version: pass it to get CART_VERSION_CONFLICT instead of overwriting a change made elsewhere, and treat it as an opaque string.

In: commercetools 0.7.0, schemas 0.7.0

# before
quoteRequestCreate(id: $cartId, args: { comment: "…" })
# after
quoteRequestCreate(args: { cartId: $cartId, comment: "…" })

A cart that cannot be quoted comes back in quoteRequestErrors as a CartNotQuotableError with its reasons, instead of as an error. Handle it in your form.

createMcpHttpDomainService moves to /application

Section titled “createMcpHttpDomainService moves to /application”

In: mcp-core 0.6.0

import { createMcpHttpDomainService } from "@evolve-framework/mcp-core";
import { createMcpHttpDomainService } from "@evolve-framework/mcp-core/application";

storeKey, locale, and currency on InitialSessionContext are required.

Date and time fields get their own scalars

Section titled “Date and time fields get their own scalars”

In: commercetools 0.6.0, schemas 0.6.0, sfcc 0.5.0

CartLineItem.addedAt is a DateTime instead of a String, so an invalid value is rejected. Product.deliveryTime is removed. A new Date scalar holds calendar dates without a time.

In: commercetools 0.6.0, schemas 0.6.0, sfcc 0.5.0

orders(page: 1, pageSize: 20) {
results { orderNumber }
total
items { orderNumber }
pagination { totalCount hasNextPage hasPreviousPage }
}
  • AddressConnection, BusinessUnitAssociateConnection, and OrderApprovalConnection are now AddressResult, BusinessUnitAssociateResult, and OrderApprovalResult.
  • totalCount can be null when an engine cannot count exactly. Page with hasNextPage and hasPreviousPage.
  • pageSize defaults to 20 everywhere, and at most 100 is served.
  • products pages from 1, like every other list.
  • orderApprovalRules returns an OrderApprovalRuleResult.

In: commercetools 0.6.0, schemas 0.6.0

The REQUESTED placeholder is gone. QuoteRequestStatusType is SUBMITTED, ACCEPTED, REJECTED, or CANCELLED, and QuoteStatusType is PENDING, ACCEPTED, DECLINED, EXPIRED, or CANCELLED. Quote.validUntil is new.

In: commercetools 0.6.0, search 0.0.1, search-algolia 0.0.1

  • CatalogModule no longer reads config.searchEngine. Pass a provider: search: new DocumentSearchProvider({ adapter: new AlgoliaQueryAdapter({ … }) }). Without search, it uses commercetools’ own product search.
  • Renamed: CatalogSource to DocumentSource, ProductSyncService to IndexSyncService, and SearchQueryAdapter.searchProducts() to search().
  • A DocumentSource declares its documentTypes.
  • SearchIndexerModule refuses to start with open operational routes. Pass secret, routes: false, or allowUnauthenticatedRoutes: true.
  • A failed search throws instead of returning no products. Handle the GraphQL error in your storefront.
  • Declare sourceId, categoryIds, and variants.sku as filterOnly attributesForFaceting on each Algolia index. A custom toRecord must set sourceId.
  • The recommended Algolia setup needs new indices and a full reindex.

See Add search.

In: commercetools-adyen 0.3.0, commercetools-buckaroo 0.3.0, commercetools-mollie 0.3.0, commercetools-invoice 0.2.0, commercetools-paynl 0.3.0, commercetools-stripe 0.3.0, commercetools 0.5.0, contentful 0.3.0, core 0.6.0, payload 0.1.0, schemas 0.5.0, sfcc 0.4.0, storyblok 0.3.0

Run pnpm codegen and fix every query it reports:

  • Scalars validate. Currency, DateTime, EmailAddress, CountryCode, Locale, URL, and JSON reject invalid values.
  • Enum type names end in Type, such as OrderStatusType, and enum values are upper snake case, such as OPEN.
  • Versions are opaque strings. The version of quotes, quote requests, order approvals, and approval rules is a nullable String instead of an Int. Pass it back as you got it.
  • Error fields are named for their domain: refreshTokenErrors is customerErrors, applePayErrors is paymentErrors, and setActiveBusinessContextErrors is businessUnitErrors. Every …Errors list is null on success.
  • Names are renamed: redirectURL to redirectUrl, roleIDs to roleIds, productsBySKU to productsBySku, previewID to previewId, createPayment to paymentCreate, validateApplePayPayment to applePayPaymentValidate, setActiveBusinessContext to businessUnitSwitch, setOrderApprovalStatus to orderApprovalStatusUpdate, and on shopping lists items to lineItems and itemIds to lineItemIds. CartLineItemCreateInput and ShoppingListLineItemCreateInput end in AddInput.
  • A self-hosted remote payment adapter must be deployed together with the services that call it.

In: core 0.5.0, cloud-adapter-azure 0.1.0

await cache.configure({ url: process.env.REDIS_URL });

The ?connector=azure URL setting is gone. For Azure Managed Redis with Entra ID, pass credentialsProvider: createEntraIdCredentialsProvider() from @evolve-framework/cloud-adapter-azure.

In: cloud-adapter-gcp 0.2.0, core 0.6.0

createPubSubHandler(...).createApp() returns a Promise<Application> instead of a Fastify instance. Use app.fastify where you need Fastify, such as for inject in tests. @evolve-framework/core/service/http no longer exports createFastifyServer: build services with createApplication.

In: core 0.3.0

import { assertSingleValue } from "@evolve-framework/core/utils";
import { assertSingleValue } from "@evolve-framework/core/testing";
import { createGraphQLTestInstance } from "@evolve-framework/core/service/graphql";
import { createGraphQLTestInstance } from "@evolve-framework/core/testing";