Highlights
Translation Module Stable
The Translation Module is out of beta is now installed in all Medusa projects by default. You can use translation features to translate content for products, categories, custom data models, and more.
Learn more in the Translation Module documentation.
Cross-Module Joins Replace the Index Module
Medusa now resolves cross-module queries using direct database joins rather than the Index Module, including in the /store/products API route. The Index Module is deprecated and will be removed in a future release.
If you have explicitly registered the Index Module in your project, you can remove it from your modules configuration. Cross-module queries via query.graph() and API filters that span module boundaries continue to work without any changes.
// In medusa-config.ts, remove the Index Module registration if present:
// { resolve: "@medusajs/index" }Learn more about cross-module joins with Query in the documentation.
Security Fix for Index Module
This release also comes with a security fix for users that have enabled the Index Module feature flag in their store. It ensures proper handling of ? characters in query parameters passed to the /store/products and /store/product-variants.
If you can't update to this version, we urge you to download and apply the patch of your Medusa version:
Promotion and Campaign Events
Medusa now emits events when promotions, promotion rules, and campaigns are created, updated, or deleted. Subscribers can react to these events to trigger automation workflows in response to discount and promotion changes.
Medusa Cloud Plugin
A new Medusa Cloud plugin integrates the admin dashboard with Medusa Cloud, surfacing in-app announcements about platform updates and new features directly in the admin UI. The plugin is included automatically for projects deployed on Medusa Cloud.
Features
- feat(cloud): add Medusa Cloud plugin with in-app announcements by @shahednasser in #17518
- feat: Redesign permissions UI by @olivermrbl in #17778
- feat(audit): add the Audit Module with Postgres and Medusa Cloud providers by @sradevski in #17787
- feat(framework,medusa,types,js-sdk,audit): record API requests as audit logs by @sradevski in #17795
- feat: improve handling of missing account holders for medusa payments by @sradevski in #17389
- feat(core-flows,utils): emit events for promotion, promotion rule, and campaign changes by @shahednasser in #17136
- feat(medusa,types,framework): use cross-module joins instead of the index module by @shahednasser in #17751
- feat(framework,types): allow additional cors option in project config by @NicolasGorga in #17576
- feat(core-flows): include metadata in the order passed to createOrderWorkflow's orderCreated hook by @shahednasser in #17058
Bugs
- fix(utils): resolve plugins installed as dependencies of @medusajs/medusa by @shahednasser in #17822
- fix(admin-bundler): resolve admin extensions of plugins that aren't direct project dependencies by @shahednasser in #17820
- fix(types): allow the
qfree-text filter inquery.graphfilters by @shahednasser in #17775 - fix(create-medusa-app): support installing projects with Yarn v1 by @shahednasser in #17794
- fix(index,promotion,product): handle
?characters in filter and context values by @shahednasser in #17773 - fix(core-flows): assign the super admin role to created users when no super admin exists, so users provisioned through SSO on a new RBAC deployment aren't locked out by @NicolasGorga in #17782
- fix(core-flows): only guard the last super admin when a removal takes the super admin role from a user by @NicolasGorga in #17767
- fix(dashboard): show an error toast when updating product attributes fails by @medusa-os-bot in #17772
- fix(promotion): check spend campaign budgets against all adjustments in a cart and skip promotions that don't fully fit by @medusa-os-bot in #17599
- fix(core-flows): re-price cart shipping methods after promotions are recomputed by @shahednasser in #17070
- fix(dashboard): disable product media Save while media is uploading by @medusa-os-bot in #17769
- fix(utils,medusa): invalidate cached localized reads and the admin translation list when a translation is created, updated or deleted by @NicolasGorga in #17746
- fix(framework,types): set security headers on HTTP responses by @shahednasser in #17763
- fix(ui,dashboard): stop DatePicker from calling onChange when its value prop changes and setSearchParams being called twice by @NicolasGorga in #17759
- fix(core-flows): don't record order refund transactions for refunds the payment provider rejected in
refundPaymentsWorkflowby @NicolasGorga in #17748 - fix(payment): recompute refunded amount when a refund fails at the provider by @shahednasser in #17489
- fix(utils): accept variant thumbnail and image columns in product import by @medusa-os-bot in #17488
- fix(event-bus-redis,workflow-engine-redis): catch failed Redis connects in loaders by @medusa-os-bot in #17553
- fix(utils,create-medusa-app): escape database names in database creation and existence queries by @shahednasser in #17521
- fix(promotion): don't apply buyget discounts to non-discountable items by @medusa-os-bot in #17443
- fix(product): don't run parallel queries inside category and variant creation by @medusa-os-bot in #17453
- fix(workflows-sdk): use the renamed step's handler when a step configured with a new name runs inside
whenby @shahednasser in #17162 - fix(promotion): prevent overlapping buy-get promotions from reusing units consumed by another promotion by @shahednasser in #17134
- fix(medusa,loyalty-plugin): import zod from
@medusajs/framework/zodinstead of the undeclared zod package by @shahednasser in #17096 - fix(core-flows): dismiss cart and draft order promotion links created by a failed promotions update by @shahednasser in #17066
- fix(types): allow filtering nullable
jsoncolumns and nullable to-many relations inquery.graphby @shahednasser in #16892 - fix(types): align
Pluralizetype with runtime pluralization for words ending in "o" by @shahednasser in #16999 - fix(core-flows): restore updated prices when rolling back the update price list prices step by @shahednasser in #17062
- fix: bump proxy-addr to 2.0.8 for CVE-2026-90711 by @shahednasser in #17762
- fix(product): set a correct mpath when moving a category to the top level by @medusa-os-bot in #17758
- fix(core-flows): restore product metadata and type on update rollback by @medusa-os-bot in #17722
- fix(http-types-generator): emit fields with a default value as optional by @medusa-os-bot in #17752
- fix(caching): use the framework graphql instance in the cache parser by @shahednasser in #17724
- fix(dashboard): allow removing locales from the locales modal and label translation languages as locales by @NicolasGorga in #17747
- fix(http-types-generator): accept tsconfig files with comments and trailing commas by @medusa-os-bot in #17753
- fix(dashboard): show an error toast when updating a user fails by @medusa-os-bot in #17756
- fix(medusa-oas-cli): download the public OAS of the installed Medusa version by @medusa-os-bot in #17743
- fix(query): push down cross-module filters nested below module-internal relations by @shahednasser in #17750
- fix(core-flows,types): add
is_custom_priceto order mutation types, and set the property on cart completion by @shahednasser in #16960 - fix(notification): reuse the existing notification's id when retrying a failed idempotency key by @shahednasser in #16951
- fix(utils,core-flows): invoke the deepFlatMap callback for an empty terminal array, fixing inventory check for carts and returns by @shahednasser in #16902
- fix(framework): only skip HTTP logging for the root
/healthendpoint, so requests like/admin/healthare logged by @shahednasser in #17046 - fix(dashboard): add accessible title and description to the order edit modals by @shahednasser in #17045
Documentation
- docs: remove beta badge from rbac references by @shahednasser in #17811
- docs(cloud): clarify how Cloud applies link changes during deployments by @shahednasser in #17803
- docs: document that updating a product's variants replaces its variant list by @shahednasser in #17792
- docs(cloud): document Cannot find module medusa-config build error by @shahednasser in #17777
- docs: add enterprise license FAQ by @shahednasser in #17774
- docs(resources): use a valid EAN in the manage products guide by @shahednasser in #17761
- docs(cloud): document that middleware fetches aren't cached on storefronts by @shahednasser in #17736
- docs: document renaming environments in Cloud by @medusa-os-bot in #17764
Chores
- chore: remove ignore tags for RBAC code by @shahednasser in #17770
- chore: remove translation module feature flag and enable by default by @NicolasGorga in #17741
- chore(index,query,medusa,types,utils): deprecate the Index Module by @shahednasser in #17754
- fix(ci): ignore stale not-started runs in release check by @shahednasser in #17789
- chore(docs): Updated API Reference by @medusa-os-bot in #17740
- chore(docs): Generated References by @medusa-os-bot in #17739
- chore(docs): Generated + Updated UI Reference by @medusa-os-bot in #17738
- chore(docs): Update version in documentation by @medusa-os-bot in #17737
Other Changes
- chore(dashboard): add missing translations by @medusa-os-bot in #17809
Full Changelog: v2.22.6...v2.22.7