Files
vmall/openspec/specs/store-directory/spec.md
T

3.5 KiB

store-directory Specification

Purpose

The buyer-facing view of a shop: its public profile — identity, contact and service copy — alongside the products it sells, so the store directory, a store's home page and the store card on a product page all read real shops.

Requirements

Requirement: Public shop directory

GET /api/shops SHALL list the active shops without authentication, and GET /api/shops/{slug} SHALL return one shop by slug, answering 404 for an unknown slug or a suspended shop. Each entry SHALL carry the shop's id, slug, bilingual name and its profile: logo and banner URLs, company, region, bilingual address, bilingual notice and after-sale copy, and four score values. A shop with no profile row SHALL still be returned, with the profile fields absent rather than invented.

Scenario: directory lists active shops only

  • WHEN a suspended shop exists alongside active ones
  • THEN the directory lists only the active shops

Scenario: store home by slug

  • WHEN a shopper opens a shop's slug
  • THEN the profile and the shop's products are available, with the products filtered by that shop through the catalog API

Scenario: unknown slug is a 404

  • WHEN a shopper opens a slug that does not exist
  • THEN the API answers 404 rather than an empty profile

Requirement: Shop profile management

A platform admin SHALL set a shop's profile with PUT /api/admin/shops/{id}/profile, which upserts the profile row and returns the composed shop. Bilingual fields SHALL carry non-empty en and zh text, and the write SHALL require the platform_admin role.

Scenario: profile upsert round-trips

  • WHEN an admin sets a profile and then reads the shop publicly
  • THEN the public read returns those values

Scenario: incomplete bilingual text is refused

  • WHEN an admin submits a notice with only en text
  • THEN the request is refused and the stored profile is unchanged

Scenario: only platform admins may write

  • WHEN a shop owner or customer submits a profile
  • THEN the API refuses the write

Requirement: Merchant self-service shop profile

A shop owner SHALL set their own shop's profile with PUT /api/shop/profile, which upserts the profile row of the shop the caller owns and returns the composed shop profile. The write SHALL require an authenticated user with a shop under the own_shop scope and SHALL accept logo and banner URLs, company, region, and bilingual address, notice and after_sale text with the same { en, zh } validation as the platform-admin profile write. Profile scores remain platform-set: merchant-supplied score_rating, score_agreement, score_service or score_speed values SHALL NOT be stored. A user without a shop SHALL be refused, and the platform-admin write and public reads SHALL keep their existing behavior.

Scenario: merchant upsert round-trips

  • WHEN a shop owner sets their profile and the storefront reads the shop by slug
  • THEN the public read returns those values for that shop

Scenario: incomplete bilingual text is refused

  • WHEN a shop owner submits a notice with only en text
  • THEN the request is refused and the stored profile is unchanged

Scenario: merchant cannot set scores

  • WHEN a shop owner submits score values with their profile
  • THEN the stored scores are unchanged

Scenario: a user without a shop is refused

  • WHEN a signed-in customer sends the merchant profile write
  • THEN the API refuses the write