Files
vmall/openspec/changes/archive/2026-09-17-replace-mock-api-wave-1/specs/catalog/spec.md
T
james 2136a48fbe chore(openspec): archive the mock-migration waves and green the spec set
Archive the three completed changes behind replace-mock-api-wave-1/2/3. Each
merge applied cleanly to the main specs:

- catalog gains the Public product browse requirement (subtree filtering and
  price sort)
- frontend-mall picks up the per-domain adapter, the pinned home page, the
  discovery-page changes, the live auth panels and the live transaction flows
- cart's Server-side cart requirement now documents the shop and stock carried
  by every line

Also replace the TBD Purpose placeholder in all eleven specs with a one-line
description of what each capability covers. Those placeholders predate this
work and were the only reason `openspec validate --all --strict` reported
0 passed / 11 failed; it now reports 11 passed / 0 failed.
2026-09-17 16:36:10 +00:00

1.7 KiB

Spec Delta

ADDED Requirements

Requirement: Public product browse

Public GET /api/products SHALL return only published products whose shop is active, and SHALL remain readable without authentication. When category_id is supplied, the filter SHALL match that category and every category beneath it, so requesting a parent category returns products assigned to its child and grandchild categories. The listing SHALL accept an optional sort of price together with an order of asc or desc, ordering by each product's lowest active SKU price; any other sort value SHALL be rejected with a 400 ApiError rather than silently ignored. An unsorted listing SHALL order newest first. Paging SHALL keep returning page and per_page alongside the filtered total.

Scenario: parent category includes descendant products

  • WHEN a shopper requests products for a category that has child categories holding published products
  • THEN the response contains the products assigned to those descendant categories, not only those assigned directly to the requested category

Scenario: sort by lowest active SKU price

  • WHEN a shopper requests the product list with sort=price and order=asc
  • THEN products come back ordered by their lowest active SKU price ascending

Scenario: unsupported sort is rejected

  • WHEN a client requests a sort value that is not price
  • THEN the API responds 400 with an ApiError body instead of ignoring the parameter

Scenario: unpublished products never appear

  • WHEN any public listing or filter is applied
  • THEN products that are not published, or whose shop is not active, are absent from both items and total