schema: spec-driven context: | VMall: B2B2C e-commerce MVP, spec-driven in phases. Tech stack: - Backend: Rust (axum 0.8, sqlx 0.8 + Postgres 18, redis 8, JWT, argon2) at apps/api, crate vmall-api. Money is stored as integer minor units + ISO currency code; never floats. - Frontends: three Nuxt 3 apps in pnpm workspace: apps/mall (customer storefront, port 3000), apps/shop-admin (merchant console, 3001), apps/admin (platform console, 3002). - Shared contract: packages/shared (@vmall/shared) — TS types, API client, en/zh locales, ui.css. Frontends must use it; no per-app API reimplementation. - Dev infra: Postgres + Redis run in local docker (containers pg18, rdb8); databases vmall / vmall_test; API runs migrations on boot (sqlx migrate). Conventions: - i18n: product/shop/category content stored as JSONB {"en": "...", "zh": "..."}; UI strings in @vmall/shared locales. - Multi-currency: currencies table with rate_to_base; prices stored in the SKU's own currency; display conversion via /api/currencies/convert. - RBAC roles: platform_admin, shop_owner, shop_staff, customer. - API errors: {"error": {"code", "message"}} with proper HTTP status. rules: proposal: - Keep proposals under 300 words with a Non-goals section tasks: - Group tasks by milestone with verifiable checkboxes