Files
vmall/openspec/changes/add-merchant-onboarding/specs/merchant-onboarding/spec.md
T

4.8 KiB

ADDED Requirements

Requirement: Merchant application submission

A prospective seller SHALL submit one merchant onboarding application as either a personal (个人) or an enterprise (企业) entity. Each kind SHALL require its own entity information, one or more operating categories referenced from the published category tree, contact details, and qualification materials submitted as URL fields. The API MUST reject submissions with missing kind-specific fields, unknown categories, or malformed qualification URLs. The form MAY be filled anonymously, but submission SHALL require an authenticated user.

Scenario: enterprise submission accepted

  • WHEN an authenticated user submits an enterprise application with entity information, operating categories, contact details, and qualification URLs
  • THEN the application is stored with status pending and returned to the applicant

Scenario: personal submission missing identity document

  • WHEN a user submits a personal application without the required identity document URL
  • THEN the API returns a validation error and stores no application row

Scenario: anonymous submit requires sign-in

  • WHEN a signed-out visitor submits the completed form
  • THEN no application is stored and the visitor must register or sign in before submitting

Requirement: One active application per user

Submission SHALL be deduplicated per user: a user holding a pending or approved application MUST NOT create another one, enforced by service validation backed by a database partial unique index so concurrent submissions cannot both succeed. A user whose application was rejected MAY apply again.

Scenario: duplicate pending submission

  • WHEN a user with a pending application submits again
  • THEN the API rejects the request with a conflict and exactly one application row exists

Scenario: re-apply after rejection

  • WHEN a user whose application was rejected submits a new application
  • THEN a new pending application row is created

Requirement: Review state machine

An application SHALL move only from pending to approved or rejected, executed as guarded updates matching the pending state so concurrent or repeated reviews of the same application fail with a conflict instead of overwriting each other. Rejecting SHALL require a non-empty reason recorded on the row, and approved and rejected are terminal states that MUST NOT transition again.

Scenario: double review conflict

  • WHEN two platform admins review the same pending application concurrently
  • THEN exactly one transition succeeds and the other receives a conflict

Scenario: rejection records a reason

  • WHEN a platform admin rejects a pending application with a reason
  • THEN the application becomes rejected with the reason stored on the row

Scenario: terminal state is immutable

  • WHEN a platform admin reviews an already approved or rejected application
  • THEN the API returns a conflict and the stored state is unchanged

Requirement: Transactional approval provisioning

Approving an application SHALL, within a single database transaction, create the shop, create a dedicated shop_owner account scoped to that shop, and mark the application approved referencing the created shop. The generated initial password SHALL be returned exactly once in the approve response and MUST NOT be retrievable through any later read. If any step fails, the status change and all provisioning SHALL roll back so the application remains pending.

Scenario: approval provisions shop and account

  • WHEN a platform admin approves a pending application
  • THEN one transaction results in an approved application, an active shop, and a working shop_owner login scoped to that shop

Scenario: credentials shown once

  • WHEN the approver reads the application again after approval
  • THEN the initial password is absent from every subsequent response

Scenario: provisioning failure rolls back

  • WHEN shop or account creation fails during approval
  • THEN no shop or account persists and the application remains pending

Requirement: Application visibility

An applicant SHALL read only their own application history, including status, submitted data, timestamps, and rejection reason. Platform admins SHALL list all applications with status filtering and pagination and read any application detail. Other users' applications MUST NOT be readable through customer routes.

Scenario: applicant checks status

  • WHEN a signed-in applicant requests their application status
  • THEN their own application state and rejection reason are returned

Scenario: other applicant is hidden

  • WHEN one authenticated user requests another user's application through customer routes
  • THEN the API returns no data about the other user's application