Summary
Add Kubernetes-style frontmatter support for ProductVariant resources so variants can model sellable SKUs, selected options, inventory controls, pricing, and media attachments under a parent product.
Scope
In scope:
- Support
ProductVariant documents with top-level apiVersion, kind, metadata, spec and status
- Define
ProductVariantSpec with:
title
sku
productRef
manageInventory
inventory
pricing
selectedOptions
media
- Support markdown body description content for variant-specific notes/copy
- Validate resource identity as
kind: ProductVariant
- Validate parent linkage semantics via
productRef
Out of scope:
- Variant pricing engine implementation
- Inventory reservation workflows
- Automatic generation of all option combinations
Implementation Notes
ProductVariant
apiVersion (string)
kind (string)
metadata (ObjectMeta)
spec (ProductVariantSpec)
status (ProductVariantStatus)
ProductVariantSpec
title (string) — Display title for the specific variant
sku (string) — Unique Stock Keeping Unit for the variant
productRef (ObjectReference) — Parent product reference
inventory (InventoryDefinition) — Variant inventory definition/details
pricing (PricingDefinition) — Variant pricing definition/details
selectedOptions ([]SelectedOptionDefinition)
selectedOptions.name (string)
selectedOptions.value (string)
media ([]MediaDefinition) — Similar to Product media definition
InventoryDefinition
managed (bool)
policy (string) - Allowed values are deny and backorder
stockLocationRefs ([]ObjectReference)
PricingDefinition
priceSet (PriceSet)
priceSet.name (string)
priceSet.prices ([]PriceTemplate)
PriceTemplate
name (string)
validFromTime (Time) Start date the price can be applied
validUntilTime (Time) End date the price is valid up to
quantity (QuantityDefinition)
quantity.min (int16)
quantity.max (int16)
currencyCode (string)
amount (Decimal)
strategy (StrategyDefinition)
strategy.type (string) The pricing strategy
priority (int8)
eligibility (EligibilityDefinition)
eligibility.operator (string) One of All or Any
eligibility.constraints ([]PriceRuleConstraint)
eligibility.constraints.name (string)
eligibility.constraints.expression (string)
This is a CEL expression to evaluate the rule. e.g. region.code == 'EU', this price is applied if the cart context is in Europe. Multiple expressions are evaluated as OR.
ProductVariantStatus
conditions ([]Condition)
lastAppliedRevision (string)
observedGeneration (int64)
resolved (ResolvedProductVariantDefinition)
product.name (string)
product.uid (string)
product.resourceVersion (int64)
priceSet.hash (string)
priceSet.compiledAt (Time)
priceSet.name (string)
priceSet.priceCount (int64)
priceSet.currencies ([]string)
priceSet.strategies ([]string)
inventory.availableQuantity (int64)
inventory.managed (bool)
media[].name (string)
media[].url (string)
media[].contentType (string)
Validation constraints
sku must be unique across variants
productRef.name must reference an existing product
selectedOptions should align with options defined on parent product
Example Document
---
apiVersion: catalog.gitstore.dev/v1beta1
kind: ProductVariant
metadata:
# name: Usually generated as a slug from the .spec.title
namespace: ensi-store
labels:
gitstore.dev/brand: Apple
gitstore.dev/vendor: Apple
processor: M4 Max
ram: 64GB
storage: 1TB SSD
spec:
title: "Macbook Pro 64GB 1TB SSD M4 (Silver / 17)"
sku: MBP-M4MAX-SILVER-17-64-1TB
productRef:
name: macbook-pro-64gb-1tb-ssd-m4
apiVersion: catalog.gitstore.dev/v1beta1
kind: Product
inventory:
managed: true
policy: deny
stockLocationRefs:
- name: berlin-warehouse
apiVersion: inventory.gitstore.dev/v1beta1
kind: StockLocation
pricing:
priceSet:
name: ps_mbp_m4max_silver_17_64_1tb
prices:
- name: base-eur
currencyCode: EUR
amount: "2499.00"
strategy:
type: fixedUnitPrice
priority: 0
- name: eu-business
currencyCode: EUR
amount: "2399.00"
strategy:
type: fixedUnitPrice
priority: 50
eligibility:
operator: All
constraints:
- expression: "region.code == 'EU'"
- expression: "customer.group == 'business'"
- name: eu-business-bulk-10
currencyCode: EUR
amount: "2299.00"
strategy:
type: fixedUnitPrice
quantity:
min: 10
priority: 100
eligibility:
operator: All
constraints:
- name: european-union
expression: "region.code == 'EU'"
- name: business-customers
expression: "customer.group in ['business']"
- name: vip-summer-campaign
currencyCode: EUR
amount: "2199.00"
strategy:
type: fixedUnitPrice
validFromTime: "2026-06-01T00:00:00Z"
validUntilTime: "2026-06-30T23:59:59Z"
priority: 200
eligibility:
operator: All
constraints:
- expression: "customer.group == 'vip'"
- expression: "params.salesChannel == 'web'"
selectedOptions:
- name: color
value: silver
- name: size
value: "17"
- name: ram
value: 64GB
- name: storage
value: 1TB SSD
media:
- fileRef:
name: macbook-hero
optional: true
status:
observedGeneration: 4
conditions:
- type: Published
status: "True"
observedGeneration: 4
reason: ReleaseTagApplied
message: Published at v1.0
- type: AdmissionAccepted
status: "True"
observedGeneration: 4
reason: PolicyPassed
- type: ProductResolved
status: "True"
observedGeneration: 4
reason: ProductFound
message: Product reference resolved.
- type: OptionsAccepted
status: "True"
observedGeneration: 4
reason: OptionsMatchProduct
message: Selected options are valid for parent product.
- type: PricingAccepted
status: "True"
observedGeneration: 4
reason: PriceSetValid
message: 4 prices compiled.
- type: Ready
status: "True"
observedGeneration: 4
reason: Reconciled
message: Variant is ready for checkout pricing.
resolved:
product:
name: macbook-pro
uid: 0a1a10e2-15f4-46b2-9e80-1c01e99dd3fb
resourceVersion: "88"
priceSet:
name: ps_mbp_m4max_silver_17_64_1tb
compiledAt: "2026-05-24T10:00:00Z"
hash: sha256:...
priceCount: 4
currencies: ["EUR"]
strategies: ["fixedUnitPrice"]
media:
- name: macbook-hero
url: s3://catalog/macbook-hero.jpeg
contentType: image/jpeg
inventory:
managed: true
availableQuantity: 18
lastAppliedRevision: main@sha1:a1b2c3d
---
Variant-specific description...
Acceptance Criteria
Implementation Plan
#208 — Contract and scope baseline
#209 — Validation and parsing semantics (blocked by #208)
#210 — Secondary domain constraints (blocked by #208)
#211 — Integration tests and docs (blocked by #209 and #210)
Tracking
Summary
Add Kubernetes-style frontmatter support for
ProductVariantresources so variants can model sellable SKUs, selected options, inventory controls, pricing, and media attachments under a parent product.Scope
In scope:
ProductVariantdocuments with top-levelapiVersion,kind,metadata,specandstatusProductVariantSpecwith:titleskuproductRefmanageInventoryinventorypricingselectedOptionsmediakind: ProductVariantproductRefOut of scope:
Implementation Notes
ProductVariant
apiVersion(string)kind(string)metadata(ObjectMeta)spec(ProductVariantSpec)status(ProductVariantStatus)ProductVariantSpec
title(string) — Display title for the specific variantsku(string) — Unique Stock Keeping Unit for the variantproductRef(ObjectReference) — Parent product referenceinventory(InventoryDefinition) — Variant inventory definition/detailspricing(PricingDefinition) — Variant pricing definition/detailsselectedOptions([]SelectedOptionDefinition)selectedOptions.name(string)selectedOptions.value(string)media([]MediaDefinition) — Similar to Product media definitionInventoryDefinition
managed(bool)policy(string) - Allowed values aredenyandbackorderstockLocationRefs([]ObjectReference)PricingDefinition
priceSet(PriceSet)priceSet.name(string)priceSet.prices([]PriceTemplate)PriceTemplate
name(string)validFromTime(Time) Start date the price can be appliedvalidUntilTime(Time) End date the price is valid up toquantity(QuantityDefinition)quantity.min(int16)quantity.max(int16)currencyCode(string)amount(Decimal)strategy(StrategyDefinition)strategy.type(string) The pricing strategypriority(int8)eligibility(EligibilityDefinition)eligibility.operator(string) One ofAllorAnyeligibility.constraints([]PriceRuleConstraint)eligibility.constraints.name(string)eligibility.constraints.expression(string)This is a CEL expression to evaluate the rule. e.g.
region.code == 'EU', this price is applied if the cart context is in Europe. Multiple expressions are evaluated as OR.ProductVariantStatus
conditions([]Condition)lastAppliedRevision(string)observedGeneration(int64)resolved(ResolvedProductVariantDefinition)product.name(string)product.uid(string)product.resourceVersion(int64)priceSet.hash(string)priceSet.compiledAt(Time)priceSet.name(string)priceSet.priceCount(int64)priceSet.currencies([]string)priceSet.strategies([]string)inventory.availableQuantity(int64)inventory.managed(bool)media[].name(string)media[].url(string)media[].contentType(string)Validation constraints
skumust be unique across variantsproductRef.namemust reference an existing productselectedOptionsshould align with options defined on parent productExample Document
Acceptance Criteria
ProductVariantdocuments are supported withapiVersion: catalog.gitstore.dev/v1beta1andkind: ProductVariantProductVariantSpecsupportstitle,sku,productRef,manageInventory,inventory,pricing,selectedOptions, andmediaskuand valid parentproductRefselectedOptionsand parent product optionsProductVariantare updated as part of this taskImplementation Plan
#208— Contract and scope baseline#209— Validation and parsing semantics (blocked by#208)#210— Secondary domain constraints (blocked by#208)#211— Integration tests and docs (blocked by#209and#210)Tracking
catalogp1 – critical