Products without a category assignment become invisible to browsing and filtering — they exist in the database but can't be discovered through any navigation path other than direct search. Beyond UX, ISO 25010:2011 functional-correctness treats uncategorized products as broken catalog behavior: the product is present but unreachable. A nullable categoryId foreign key means every product creation path in the codebase can skip assignment, and there's no audit trail for which products were left uncategorized. At scale, this creates catalog rot: orphaned products accumulate, promotional campaigns miss items, and inventory counts diverge from what customers see.
High because uncategorized products disappear from browse and filter paths, making inventory effectively invisible to customers navigating the catalog — a silent revenue leak.
Add a non-optional many-to-many relationship between Product and Category in prisma/schema.prisma, and enforce at least one category assignment in src/app/api/products/route.ts.
model Product {
id String @id @default(cuid())
name String
categories Category[]
}
model Category {
id String @id @default(cuid())
name String
products Product[]
}
In the product creation route, reject requests with an empty categories array:
if (!categoryIds || categoryIds.length === 0) {
return Response.json({ error: 'At least one category is required' }, { status: 400 })
}
ID: ecommerce-catalog.product-data.category-assignment
Severity: high
What to look for: Count all category-related schema definitions (Category model, join tables, foreign keys). Enumerate every product creation path (API routes in src/app/api/products/, admin forms, seed scripts) and check whether category assignment is required during creation. Before evaluating, extract and quote the category relationship definition from the product schema.
Pass criteria: A category relationship exists in the product schema (many-to-many join table or foreign key) and at least 1 product creation path enforces category assignment as required (not optional). Count all product creation paths found and report: "X of Y creation paths enforce category assignment."
Fail criteria: The schema allows products without category assignment (nullable foreign key, optional relation), or the codebase contains product creation logic that does not require a category.
Do NOT pass when: A category field exists but is nullable or optional in the schema, even if the UI happens to always include it — the database constraint must enforce it.
Skip (N/A) when: The project uses a flat catalog with no category concept (e.g., single-product SaaS, digital downloads with no grouping).
Cross-reference: For category hierarchy and navigation patterns, the SEO Fundamentals audit covers URL structure and site architecture.
Cross-reference: For database relationship patterns, the Database Design & Operations audit covers join table design and referential integrity.
Cross-reference: For admin form validation, the Error Resilience audit covers form validation and user input handling.
Detail on fail: "Product schema has no category relationship — no Category model or join table found" or "Product creation in src/app/api/products/route.ts allows categoryId to be null"
Remediation: Add a many-to-many relationship between products and categories in prisma/schema.prisma:
model Product {
id String @id @default(cuid())
name String
categories Category[]
}
model Category {
id String @id @default(cuid())
name String
products Product[]
}
Enforce that at least one category is assigned in src/app/api/products/route.ts when creating a product.