# Tasks: replace-mock-api-wave-7 ## 1. Backend - [x] `apps/api/migrations/0009_addresses.sql`: table + `addresses_one_default` partial unique index - [x] `apps/api/src/routes/addresses.rs`: list/create/update/delete/set-default; customer role; `WHERE user_id` ownership (404 cross-user); transactional default switching; first address auto-default; delete-default promotes latest remaining - [x] Register module + router; `AddressBookEntry` row model ## 2. Shared contract - [x] `packages/shared/src/types.ts`: `AddressBookEntry` - [x] `packages/shared/src/api.ts`: `listMyAddresses`, `createAddress`, `updateAddress`, `deleteAddress`, `setDefaultAddress` ## 3. Mock adapter - [x] `apps/mall/mock/api.ts`: same five methods over persisted mock state (seed from `MOCK_ADDRESSES`) - [x] `apps/mall/plugins/api.ts`: `addresses` live pick + `DEFAULT_LIVE_DOMAINS` entry ## 4. Mall pages - [x] `user/addresses.vue`: real CRUD via `$api` (modal add/edit, delete, set-default) - [x] `checkout/index.vue`: load addresses from `$api`; radio select; inline manual form fallback when empty; submit selected address - [x] Locale keys (user/checkout domains, en+zh) ## 5. Seed + tests - [x] `scripts/seed-demo.mjs`: two idempotent demo customer addresses - [x] `apps/api/tests/addresses.rs`: CRUD, cross-user 404, single-default invariant, delete-default promotion, non-customer 403 ## 6. Verify - [x] `cargo test -p vmall-api` green (docker vmall_test + Redis) - [x] `pnpm --filter @vmall/mall build` + shop-admin + admin builds green (contract change) - [x] `openspec validate replace-mock-api-wave-7 --strict` green - [x] Browser smoke: address CRUD in user center; checkout with saved address end-to-end