The merge creates the storefront-content capability (two requirements, five scenarios) and updates the mall's home-page requirement so its banner, promotion, quick-link and floor advert content comes from the content API. openspec validate --all --strict stays green at 12 passed / 0 failed.
2.2 KiB
storefront-content Specification
Purpose
The storefront's editable marketing content: the home page's banners, promotion tiles, quick links and floor advert art, written by platform admins and read publicly.
Requirements
Requirement: Public home content
GET /api/content/home SHALL be readable without authentication and SHALL return the active home content as four ordered lists: banners, promos, quick_links and floor_adverts. Each entry SHALL carry what the storefront renders: an image URL and a destination URL for banners and promos, a bilingual label and an inline SVG glyph for quick links, and an image URL for floor adverts, whose destination is the floor's own category. Entries flagged inactive SHALL never appear, and each list SHALL be ordered by its stored position.
Scenario: only active content is served
- WHEN a shopper loads the home content while one banner is marked inactive
- THEN that banner is absent from
banners, and the remaining entries keep their stored order
Scenario: an empty kind still answers
- WHEN a kind has no active entries
- THEN the response returns an empty list for it rather than omitting the key or failing, so the page renders without that block
Requirement: Content management
Platform admins SHALL read all home content with GET /api/admin/content and replace one kind at a time with PUT /api/admin/content/{kind}, where kind is banners, promos, quick-links or floor-adverts. A replacement SHALL validate every entry, apply as a single transaction, and reindex positions from the submitted order. A rejected entry SHALL leave the stored content exactly as it was. Writing SHALL require the platform_admin role.
Scenario: replace reorders and reindexes
- WHEN an admin submits the same three banners in a different order
- THEN a subsequent public read returns them in the new order
Scenario: an invalid entry is rejected atomically
- WHEN an admin submits a list whose second entry is missing its image URL
- THEN the request fails and the previously stored list is unchanged
Scenario: non-admins cannot write
- WHEN a signed-in customer or shop owner sends a replacement
- THEN the API refuses the write