Merit · Seller Portal · Requirement
This is the requirement behind MSP-392, dated 26 August 2026.
MSP-392 sat in backlog with an empty description and no assignee. The same question surfaced three times, in two channels and one DM.
Where the question came up
| Date | Where | Question |
|---|---|---|
| 10 Aug | #seller-portal-x-merchandise-service |
Ghaith Fakhouri asked who owns variant creation for products that do not exist yet, and how the parent gets created. |
| 20 to 24 Aug | #temp-ecomm-core-x-online-catalogue-sync |
Akshay Chennupati, Usman Abbas, Ghaith Fakhouri, Heba Wahba and Alex Korobchuk argued whether two items that share a variant attribute set are the same item. |
| 24 Aug | DM to Brian | Khawar Rasheed reported MSP-392 still in backlog, awaiting requirements. |
The Slack argument and MSP-392 are one question in two places: what makes a variant distinct. Merit already answered that question for a different case five days ago. Section 2 applies the same answer. Section 4 turns it into the upload flow.
Merit runs an Amazon-style catalogue. This is not new work, and MSP-392 sits on top of it rather than inventing a parallel model.
Product, Variant, Offer
One Product can carry several Variants. One Variant can carry several Offers, one per seller.
| Entity | Lives in | Holds | The buyer sees |
|---|---|---|---|
| Product (parent) | PIM | Canonical shared identity: name, brand, description, images, category, attributes | One product page |
| Variant | PIM | One buyable configuration. Carries the variant axis values, its own barcode, its own images | The selector on that page |
| Offer | Ecommerce Core | One seller's terms for one Variant: price, stock location, condition, shipping profile, channel | The price, and the seller behind it |
Sources: Master PIM Documentation section 2.1, PRD Ecom Core Seller Offer Management sections 2 and 5.1.
The rules that bind the design, from PRD PIM Category and Attribute Structure:
| Rule | What it says | Why it matters here |
|---|---|---|
FR-10 | Up to 5 attributes per category can be variant axes | Adding an axis is not free. There is a hard cap |
FR-15 | Variant axes are configured per category | The axis list is a category property, not a form property |
FR-17 | Every combination of axis values generates a child SKU with its own barcode, stock and price | Adding an axis multiplies SKUs across the whole category |
FR-18 (P2) | Sellers can define custom axes where the admin enabled it | Must stay OFF here. See rule 4 below |
FR-19 | Axis values must match the admin-defined allowed values list | This is what keeps a new axis from becoming free text |
A Variant is identified by the Product plus the complete set of its variant axis values. That combination is unique inside the Product.
The uniqueness constraint that Akshay's team deployed is correct. Keep it.
An axis is not live until every existing variant in that category carries a value for it. The admin names that default value at the moment the axis is created, and it must be one of the FR-19 allowed values. WAIT-0450 established the gap: an existing product does not pick up a new axis without a migration path. Without this clause the whole legacy population has no value on the new axis, so "the complete set" is false for all of it and uniqueness over a missing value is undefined.
When two real items collide on the same axis values, take the cheapest answer that is true, in this order. Never an Offer, at any rung.
An automatic new axis on every collision burns a permanent, category-wide axis slot to settle one pair of items, and multiplies SKUs across every product in the category under FR-17. The iPad case lands on rung 3 on its merits, not by default.
Merit already decided exactly this, for regional units. DEC-0172, decided 19 August: region becomes a third variant axis on Smartphones, pinned by an FR-19 allowed values list of exactly [UAE, International, US], and regional units stay one Product. The iPad case that Heba Wahba raised has the same shape. The answer is a Connectivity axis with WiFi and WiFi + Cellular, on the tablet category, pinned by FR-19. After that both items are ordinary variants and nothing is special-cased.
Ghaith reached this on 23 August: "that means they are different, and the variant attribute is what making them show separately". Akshay agreed the next day.
An Offer never carries anything that changes what the buyer receives, apart from condition.
Offers differ by seller, stock location, price, stock and condition, which is an enumerated field on the Offer entity (NEW, REFURBISHED, USED_LIKE_NEW, USED_GOOD, USED_ACCEPTABLE) and is shown to the buyer. Nothing else about the item may live on the Offer.
This is why the workaround Usman proposed, which links a second Offer to the existing Variant when the axis values collide, cannot be the answer. The B2C app shows the lowest-price Offer for the selected Variant, as Usman described on 24 August. Put a WiFi unit and a WiFi plus Cellular unit on one Variant as two Offers, and the buyer selects the item they want, is charged for the cheaper one, and receives the wrong hardware. Nothing errors anywhere. Merit would find it in returns.
Usman's closing message points at the same answer from the other side: "If you want to eliminate this confusion completely, you can provide us with unique Variants under each Product, where each Variant has a unique combination of attribute values."
A seller can never create a variant axis. Only a catalogue admin can.
The rule is absolute, not flag-driven. Product Upload never renders an axis-creation control, whatever allow-custom-axes says for the category. FR-18 stays available to admins inside PIM and stays out of reach of the seller flow. DEC-0172 already turned allow-custom-axes OFF for Smartphones and Electronics; this rule means the seller flow does not depend on that flag being read correctly for any other category. A seller-invented axis fragments the category permanently, and FR-17 means every existing product in that category gains a cross product of empty SKUs.
Ops cannot wait for a schema change on every collision, and the seller must not be able to force one. So the flow fails loudly and routes the request.
Failing loudly is the point. A silent merge or a duplicate only surfaces after a customer receives the wrong item.
PIM holds variant axes per category. The Online Catalogue holds required variant attributes per product group. They are not the same list, and the mismatch already broke production: Hexcode became a required variant attribute on the "Bags / Luggages" product group on 30 April 2026, existing products were never backfilled, and catalogue sync failed on 22 August.
The repair of that specific data has no owner and no ticket, checked on 31 August 2026. See open item 3.
For MSP-392 the source of truth is the PIM category axis list, because that is what the seller is creating into. The Online Catalogue product group attributes are a push-time requirement, checked before the outbound push, not a form requirement. Requirement G5 covers this.
The seller is in Product Upload and wants to sell something. Four paths exist. Only the first is specified today.
Merit has no dependable GTIN, EAN or UPC, so identity is resolved by matching, not by a barcode lookup. The one real seller catalogue Merit holds, 11,425 rows, has no barcode column at all. The waterfall runs the seller SKU map first, then semantic search on title and attributes, then LLM disambiguation, then seller confirmation. Every branch below is entered by a match result. Source: BRD for AI Product Matching, 20 August 2026.
Decision tree from the match result. Merit has no dependable GTIN, so identity comes from AI matching
Case A is covered by PRD Seller Portal Product Upload Improvements v1 section 3.2, the SKU conflict resolution flow. Cases B, C and D are the scope of MSP-392.
Requirement ids B1 to B9, C1 to C7, D1 to D5 and G1 to G5 are the deliverable of this document.
| # | Requirement |
|---|---|
| B1 | "Add a variant" is available from a product card in Search Existing Products. The variant count already on that card (PRD v1 section 3.1) tells the seller what exists. |
| B2 | The variant form is built from the category's variant axis list, read live from PIM. It is never a static form. |
| B3 | Every axis on the category is mandatory. A variant with a missing axis value is not a valid SKU under FR-17. |
| B4 | Axis values are selected from the FR-19 allowed values list where one is configured. Free text is only permitted where no list exists. |
| B5 | The form never offers "add a new option", in any category, whatever allow-custom-axes says. FR-18 is unreachable from the seller flow by construction, per rule 4 and DEC-0231. |
| B6 | On submit, the axis value combination is checked against every existing Variant of that parent. A collision goes to Case D. |
| B7 | The seller supplies their own seller SKU, variant images, and a barcode only if they hold one. The barcode is an optional stored field under FR-17 and is never the identity key. Merit has no dependable GTIN, EAN or UPC. Parent content is read only in this form. |
| B8 | A successful submit creates the Variant and the seller's Offer against it in one action. The seller never has to run Case A afterwards. |
| B9 | The new Variant enters LiveOps review before publish. |
| # | Requirement |
|---|---|
| C1 | The parent and at least one Variant are created in one flow. A parent with zero variants is never written. |
| C2 | The parent form asks only for shared content: name, description, brand, category, terms and conditions, shared images. Nothing region-specific and nothing SIM-specific in the description, per DEC-0164. |
| C3 | Before the parent is written, duplicate detection runs on brand plus name plus category, and the near matches are shown. The seller either picks an existing parent, which sends them to Case B, or confirms this is new. |
| C4 | Before the Variant is written, the AI product matching waterfall runs on it. An ambiguous match is shown to the seller to confirm or reject, per decision 8 of the AI Product Matching BRD. Barcode is not used, because Merit has none to match on. |
| C4a | Auto-routing is off until shadow mode ends. BRD business rule 6 says the service scores everything and links nothing until measured precision earns it, per category. So on day one every match is shown to the seller, and a confident match only routes straight to Case A once that category has passed the shadow-mode exit bar. The confidence bands are deliberately unset, and two existing documents disagree, so do not build a fixed threshold into this flow. See open item 8. |
| C5 | The variant part of the form follows B2 to B7 without exception. |
| C6 | Region defaults to MENA and country to Saudi Arabia for seller-portal-originated products, per the agreement Brian confirmed on 21 August in the sync channel. See open item 4, which records what that agreement did not settle. |
| C7 | The parent and the Variant enter LiveOps review before publish. Nothing a seller creates publishes without review. |
| # | Requirement |
|---|---|
| D1 | The create is blocked. The message names the conflicting Variant, its SKU and its axis values. |
| D2 | Two paths are offered: "this is the same item, create an offer instead", which goes to Case A, and "this is a different item, request a new option". |
| D3 | The axis request captures the category, both colliding items, and the axis or allowed value the seller believes is missing. It routes to a catalogue admin. |
| D4 | Adding an allowed value to an existing axis and adding a new axis are different decisions. The request states which one it is, because the second is capped by FR-10 and multiplies SKUs under FR-17. |
| D5 | No variant and no offer is written while the request is open. The seller sees the request state on their draft. |
| # | Requirement |
|---|---|
| G1 | Variant uniqueness is enforced server side, on the complete axis value set, inside the parent Product. The client-side check is a convenience only. |
| G2 | An Offer is only created against a Variant that already exists, and carries only seller, price, stock location, stock, condition, shipping profile and channel. |
| G3 | Identity keys on productId, variantId and offerId, never on sellerSku. A seller renaming their SKU must not orphan the product. |
| G4 | Inventory is held at Variant level, never at parent level. |
| G5 | Before the outbound push to the Online Catalogue, the record is checked against the target product group's required variant attributes. A missing required attribute blocks the push with a named error and does not fail silently. This is the Hexcode case. |
Five scenarios, one card each.
Scenario · seller adds a colour that does not exist yet
Scenario · two items share an axis value set
Scenario · seller cannot invent an axis
allow-custom-axes is set toScenario · required catalogue attribute missing at push time
Hexcode requiredHexcode valueHexcode and the product groupScenario · the product already exists and matching finds it
Every row was re-checked against its primary source on 31 August 2026. The Answer column records what was found, not what was assumed.
| # | Item | Owner | Answer, as at 31 Aug 2026 |
|---|---|---|---|
| 1 | Creating new products and variants in the Online Catalogue is Phase 2 of the OC API contract, not Phase 1. Phase 1 only pushes supplier products for variants that already exist in Seller Portal. DEC-0168 made the outbound leg the priority direction. | Akshay Chennupati | No date has ever been committed. The last live status is Akshay on 6 July 2026, in DM: "aiming for Phase 2 implementation-ready by the start of the next sprint. Firm estimate and target date to follow once the scope is fixed." The follow-up never came. Tahsin's MOM of 9 June recorded the same promise of a timeline. Still blocking. Asked again in the catalogue sync thread on 6 September 2026. |
| 2 | The axis request path in D3 and D4. | Brian Arfi, requirement. Catalogue admin decides | CLOSED 6 September 2026. Raised as MSP-545, a Task under epic MSP-118 beside MSP-392, carrying A8a (the backfill clause) and A8b (the DEC-0231 ladder). Ghaith Fakhouri is asked only to name the admin role that decides a request, which is an ops answer and not a build. |
| 3 | Backfill of required attributes added to a product group after it went live, the Hexcode case. |
Alex Korobchuk | Root cause is documented, the fix is not owned. Alex, 18 August: the product existed before Hexcode was added as a required dynamic field on 30 April 2026, and whoever added it never filled it for the other products in that group. No ticket, no owner and no status for the backfill itself. MPS-1602, strict merchandise variant field validation, is Done and adjacent, but it is validation and not a data repair. Needs a ticket. |
| 4 | Country and region defaults for seller-portal-originated products. | Akshay Chennupati, Alex Korobchuk | Decided, and the decision is Brian's own. The thread ran 19 to 21 August, not 22 August. Brian objected on 19 August that Just Lounge is live in UAE and would be tagged Saudi Arabia silently. Akshay answered on 20 August why a per-supplier country does not work, because one Product can carry suppliers in different countries, and never addressed Just Lounge. Brian confirmed the default on 21 August citing "as we agreed in grooming", a conversation captured nowhere. So C6 stands as written, but the Just Lounge case was never answered on its merits and no one has said what happens to that catalogue. |
| 5 | LiveOps review capacity. Every Case C submit creates review work. | Ghaith Fakhouri owns the measurement | Not an MSP-392 item. It is already tracked as WAIT-0393, which asks for the three numbers that would size it: share of rows reaching manual review, median and 90th-percentile minutes per review, and the split of reviewer outcomes. The AI Product Matching BRD states it plainly: no baseline exists, and the flow is not instrumented. One nudge has gone out. Track it there, not here. |
| 6 | allow-custom-axes is confirmed OFF for Smartphones and Electronics by DEC-0172. The setting for every other category is unknown. |
PIM team | CLOSED by DEC-0231, 6 September 2026. The flag state could not be answered from documents and the audit could not be sized, because Merit has no enumerated leaf-category list in any repo source. Rule 4 is now absolute, so Product Upload never renders the control and B5 no longer depends on the flag. The audit is still worth doing for PIM admin tooling, but it does not block this ticket. |
| 7 | B6, C3 and C4 sit on top of AI product matching. | Ruba Jaikat, PRD. Khawar Rasheed, ticket | Ticket exists and is as empty as MSP-392 was. MSP-506, "AI Matching Engine: Training with Common Products", P1, reporter Khawar, no description and no assignee. The BRD is at v2.1. Ruba owns the PRD, proposed for 3 September and explicitly not committed. WAIT-0392 has no progress note since 20 August. Blocking C3 and C4. B and D can still be built and tested against a parent the seller picked by hand. |
| 8 | The confidence bands that decide when C4 auto-routes to Case A. | Ruba Jaikat | Deliberately unset, and two documents disagree. The Bulk Upload TechSpec proposes 95 percent to auto-link and 70 to 95 for seller review. The BRD says two existing documents disagree, 90 and 60 against 95 and 70, and neither is calibrated. BRD business rule 6 is shadow mode first: the service scores everything and links nothing until measured precision earns it, per category. So C4 must not auto-route on day one. See C4. |
| 9 | Validation is being specified in three places. | Usman Abbas | WAIT-0395 already records that two PRDs specify the same validation independently. Requirement G5 here is a third. Someone has to pick one owner before all three ship a different error message. |
The variant identity rule is taken from three sources: the Slack thread where Akshay and Ghaith converged on 24 August, the B2C behaviour Usman described (the app shows the lowest-price Offer for the selected Variant), and DEC-0172, which already applied the same rule to regional units. This document did not read the MedusaJS schema or the Ecommerce Core code, so field names may need mapping by Usman Abbas and Hassan Ahmad.
The four cases in section 3 come from the existing Seller Portal product upload documentation plus the two Slack threads. If Product Upload has a fifth path that neither document records, it is not covered here.
Open item 6 was a gap this document could not close from the repo, and DEC-0231 closed it by making rule 4 absolute instead of flag-driven. Which categories allow custom axes today is still not written down anywhere found so far; it no longer blocks this ticket.
Merit Incentives · Seller Portal · Flow for Variant Creation in Product Upload (MSP-392)
Prepared by Brian Arfi Faridhi, 26 August 2026.