Configured Commerce Upgrade Watch: February 2026
sts 5.2.2602.424+sts Covers February 2026
Written by Lance Farquhar March 2, 2026
Release 5.2.2602.424+sts, published February 27, 2026. Each month we read what Optimizely says shipped, then go verify it against the actual source — frontend and backend — so you get more than a changelog recap.
The 30-Second Version
- Headline feature: Automatic user logout when role assignments change is real, and it's a clean, minimal implementation — a new
RolesChangedOntimestamp column plus one new check in the existing sign-out path. - Worth knowing: One-page checkout picks up a one-time shipping address option, backed by a new 197-line handler and substantial rewrites to the shipping form and section components.
- Also notable: Dynamic rule-based customer list assignment ships with real backend depth — two new database tables, two new entities, a new admin action, and a new scheduled job to keep list membership in sync.
- Verdict: one of the cleanest release-note-to-code matches in this series so far — ten of fourteen highlighted items map to specific, verifiable diffs, and the two most worth planning around are the role-change logout and a quiet Job Scheduler rewrite for Daylight Savings Time.
The Headline: Automatic Logout on Role Change
When a user's role assignments change, Configured Commerce now forces that user out of any active session the next time they make a request — rather than letting them keep working under permissions that no longer apply. It's a small feature by line count, but it closes a real gap: previously, a role change didn't take effect for a signed-in user until their session naturally expired.
The implementation is exactly as described, end to end. A new column tracks when a user's roles last changed:
ALTER TABLE [dbo].[UserProfile] ADD RolesChangedOn [datetimeoffset](7) NULL;
And LogOutValidateIdentity.cs gains one new check, run before the existing password-change logout check:
var user = userProfileRepository.GetByUserName(identityName);
if (user is { IsGuest: false } && user.RolesChangedOn > issuedUtc)
{
DependencyLocator.Current.GetInstance<IAuthenticationService>().SignOut();
return false;
}
issuedUtc is the timestamp already baked into the user's current session token. If RolesChangedOn is later than that, the session was issued under stale permissions, so it's torn down. The diagram below walks through the full sequence — from an admin editing a role assignment through to the next request that session makes:
Nothing about the sign-out mechanism itself is new — IAuthenticationService.SignOut() is the same call the password-change check already used. What's new is just the RolesChangedOn column and the single comparison against it, which is why the change stays this small while closing a real security gap.
What Else Shipped
No breaking changes this cycle. Optimizely reported none, and the diff doesn't surface anything that would qualify.
One-time shipping address for one-page checkout. A new SetUseOneTimeAddress.ts handler (197 new lines) mirrors the existing multi-page checkout handler of the same name, pulling allowOneTimeAddresses from customer settings, checking that the fulfillment method isn't pickup, and wiring into UpdateShipTo/ValidateShippingAddressForm. ShippingAddressForm.tsx and OnePageCheckoutShippingSection.tsx both picked up substantial companion changes (176 and 280 lines).
Order Approval Activity Log. ActivityLog.tsx was substantially rebuilt (530 changed lines) around a new CustomerOrderChangeModel type, adding an accordion-based changes view that surfaces product-level old/new price, quantity, and subtotal comparisons on approval requests — a real revision-history UI, not a cosmetic addition.
Dynamic rule-based customer list assignment. New backend infrastructure throughout: WishListCustomerAddition and WishListCustomerException tables and views, matching entity classes, a new RebuildListCustomerAssignmentAction.cs admin action, and a new scheduled job (JobPostprocessorRebuildListsCustomerAssignment.cs) that keeps dynamically-assigned list membership current.
Distinct promotion error messaging. 800_ValidateAppliedPromotion.cs now returns Promotion_AlreadyUsed specifically for customer-usage-limit violations, separate from the general Promotion_Not_Available message used for promotion-level limits.
Job Scheduler Daylight Savings Time handling. IntegrationJobSchedulingService.cs replaces manual UTC-offset math with a proper local-time recurrence calculation — converting to local time via TimeZoneInfo.ConvertTimeFromUtc, computing the next occurrence in local time, and converting back to UTC only at the end. This is a real rewrite of the scheduling math, not a patch on top of it.
Custom email template parameters, Google Geocoder server key, and a few smaller items. EmailService.cs now populates WebsiteUrl, LogoImagePath, WebsiteName, and CurrentYear onto outgoing email models automatically. A new GoogleGeocoderApiKeyServer setting lets you use a separate, IP-restricted key for server-side geocoding. The ValueMinimum for ordered-product promotion rules now defaults to 1 and accepts any decimal above zero. And PaymentGatewayCenpos.cs gained a genuinely new conditional branch for populating TokenEx Cenpos Level3 data on saved cards.
A few items with partial or indirect corroboration. Order Approval approver visibility shows one touched line (a data-test-selector addition) that's consistent with the described feature without directly proving it. Quote message dashboard display touches the messages pipeline (MessageService.ts, AddQuoteMessage.cs) in ways consistent with the release note but not conclusive on their own. The Spire performance work is real and substantial — a new /.spire/fonts/getFontCss route and a 285-line rewrite of fontProcessing.ts — though it reads more like a font-loading and CSS performance change than the specific "DDoS resistance" framing in the notes; either way, it's a real server-side change worth testing directly against a running instance if that's your focus. N-gram tokenization for part number search wasn't independently confirmed in this diff either — also worth testing directly rather than assuming from the notes alone.
Five items already shipped via January hotfix. TinyMCE editor control, v2 Products API performance work, Block Anonymous Traffic with Cloudflare country detection, archived-product-selection prevention in promotion codes, and the react-router dependency fix are all footnoted as already available in 5.2.2601 STS. All five checked out as byte-identical between the January and February commits — exactly what you'd expect from something that shipped the month before.
What We Actually Found: Enzyme Quietly Retires From the Test Suite
Buried in this month's frontend diff, unrelated to anything in the release notes, is a real test-infrastructure migration: enzyme and enzyme-adapter-react-16 are gone from package.json, the test:mobius script has been removed, and a batch of per-module jest.config.js and enzyme-setup.js files have been deleted along with a leftover GridContainer.ssr.test.jsx test file.
Put together, that's a codebase moving its test suite off Enzyme and onto native Jest, and cleaning up the per-module test scaffolding that Enzyme required along the way. None of it shows up in the release notes, which is exactly the kind of thing worth knowing about if you maintain custom widgets against this codebase: if your own test suite still imports enzyme or references one of the deleted config files, this is the release where that stops matching what ships upstream.
Under the Hood
Splitting one error path into two. The promotion validation logic used to return a single message for any rule violation. Now it distinguishes the specific failure:
if (invalidRuleTypes.Any(o => o == this.PromotionCustomerLimitRuleType))
{
return MessageProvider.Current.Promotion_AlreadyUsed;
}
if (invalidRuleTypes.Any(o => o == this.PromotionLimitRuleType))
{
return MessageProvider.Current.Promotion_Not_Available;
}
Two if blocks in place of one — a small change, but it's the difference between telling a customer "you've already used this code" versus "this code isn't available," which matters when your support team is reading the same error message.
A one-line addition that extends an existing search pattern. Line Notes search within Lists came in as a single added clause in GetWishListLineCollectionHandler/700_ApplyFiltering.cs:
|| o.WishListProduct.Notes.Contains(parameter.Query)
It sits alongside the existing ERP-number and manufacturer-item search clauses, reusing the same filtering pipeline rather than introducing a parallel search path.
A guarded branch for Level3 card data. PaymentGatewayCenpos.cs adds:
if (this.EnableLevel3Data) request.InvoiceDetail = this.AddLevel3Data(parameter);
Everything else touched in that file this cycle was decompiler noise (stripped this. prefixes), which makes this one new conditional easy to miss in a naive diff — but it's the entire substance of the TokenEx Cenpos Level3 fix.
A default value that closes an edge case. The ordered-product promotion rule's ValueMinimum parameter now specifies Min = 0.0000000001m, Default = 1m — a minimum just above zero paired with a default of exactly 1, which is precisely "default value of 1, accepting decimals greater than 0" from the release notes, expressed as two parameter attributes rather than new validation code.
What This Means for You
- Warn your support and integration teams before this ships. Any bulk role reassignment — via API, import, or a scripted process — will now force an immediate re-authentication for affected users. That's the intended behavior, but it will look like an unexpected logout if nobody's expecting it.
- Check recurring integration jobs anchored to a local-time hour. The Job Scheduler DST rewrite is a genuine change to the recurrence math. If you have jobs that need to run at a specific local time, verify their next scheduled run around the next Daylight Savings transition after upgrading.
- One-time shipping address is opt-in. It only appears when
allowOneTimeAddressesis enabled in customer settings, so there's nothing to change unless you want the option available. - Review the dynamic customer-list rebuild job before enabling dynamic rules on large lists. It's new scheduled-job infrastructure; understand its rebuild cadence before turning it on broadly.
- If you maintain custom widget tests, plan for the Enzyme-to-Jest change on your next frontend pull. Tests that still depend on
enzymeor a deleted per-module Jest config will need updating. - Treat N-gram tokenization and the Spire performance work as worth testing directly against a running instance rather than assuming behavior from the release notes alone — neither was independently confirmed in this month's diff.
- The five hotfix-footnoted items need no new action if you already applied January's hotfixes — they're unchanged between the January and February commits, exactly as expected.
Upgrading a Configured Commerce storefront and want a second set of eyes on what actually changed under a release before you take it? That's exactly the kind of review Nishtech does for clients every month — reach out and we'll walk through it with you.