# Variant options are clearly defined and enumerated

- **Pattern:** `ab-001119` (`ecommerce-catalog.variant-pricing.variant-options-defined`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001119
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001119)

## Why it matters

Variant options stored as free-form strings (`'medium'`, `'Med'`, `'M'`) for the same logical value produce duplicate facets in filters, inconsistent add-to-cart payloads, and inventory mismatches when orders reference `'M'` but the stock record uses `'Medium'`. ISO 25010:2011 functional-correctness requires consistent behavior across the same logical input. Without an enum or lookup table, every new developer who touches the product creation form can introduce a new spelling, and there's no schema-level enforcement to catch it. Filter UIs built on free-form strings show three separate size options when there should be one.

## Severity rationale

High because uncontrolled variant option strings produce inventory mismatches, broken filters, and add-to-cart failures when the selected string doesn't exactly match a database record.

## Remediation

Define variant options as enum types or a reference table in `prisma/schema.prisma` so the database rejects any value not in the allowed set.

```prisma
enum Size {
  XS
  S
  M
  L
  XL
}

model ProductVariant {
  id        String @id @default(cuid())
  productId String
  product   Product @relation(fields: [productId], references: [id])
  size      Size
  color     String
}
```

For more flexible option systems, use a separate `OptionValue` reference table and foreign key instead of a Prisma enum — this allows adding new values via migration rather than code change.

## Detection

- **ID:** `variant-options-defined`
- **Severity:** `high`
- **What to look for:** Count all variant option types in the schema or codebase (size, color, material, etc.). For each option type, enumerate the allowed values: are they defined as enums, a reference table, or free-form strings? Check `prisma/schema.prisma` for enum definitions, `src/types/` for TypeScript union types, or a separate `options` table in migrations.
- **Pass criteria:** For products with variants, at least 1 option type has predefined allowed values (enum, lookup table, or union type), not free-form text input. Count all option types found and report: "X option types found, Y of X have predefined values."
- **Fail criteria:** Variant options are stored as arbitrary strings with no enumeration or validation anywhere in the codebase — no enums, no lookup tables, no TypeScript unions.
- **Skip (N/A) when:** The project has no products with variants (all SKUs are fixed) — confirmed by finding no variant model, no option fields, and no size/color references in the codebase.
- **Cross-reference:** For data integrity of variant options, the Database Design & Operations audit covers enum and constraint patterns.
- **Cross-reference:** For variant display and selection UX, the Accessibility Fundamentals audit covers form control patterns and label associations.
- **Cross-reference:** For variant URL structure, the SEO Fundamentals audit covers parameterized URL patterns.
- **Detail on fail:** `"Variant sizes are stored as free-form text with no enumeration in prisma/schema.prisma. Examples: 'medium', 'Med', 'M' used for the same size in prisma/seed.ts"` or `"No variant option schema found — 0 option types defined"`
- **Remediation:** Define variant options with enums or a separate reference table in `prisma/schema.prisma`:

  ```prisma
  model ProductVariant {
    id String @id @default(cuid())
    productId String
    product Product @relation(fields: [productId], references: [id])
    size String @db.Enum("XS", "S", "M", "L", "XL")
    color String @db.Enum("Red", "Blue", "Green", "Black")
  }
  ```

## External references

- iso-25010 functional-correctness

Taxons: data-integrity

HTML version: https://auditbuffet.com/patterns/ab-001119
