Files
vmall/openspec/changes/archive/2026-09-18-replace-mock-api-wave-7/proposal.md
T
Chengdong Zhang c51e96ae41 feat(mall): address book wave 7 frontend, contract, and archive
Live addresses domain for the mall: shared contract (AddressBookEntry +
five client methods), mock adapter state v3, live domain pick, addresses
page CRUD, checkout saved-address picker with manual fallback, demo seed,
and the archived change plus address-book capability spec.
2026-09-18 16:00:05 +08:00

35 lines
2.9 KiB
Markdown

# Proposal: replace-mock-api-wave-7
## Why
The address book is the last piece of the core purchase chain still on fixed mock data: `user/addresses.vue` renders `MOCK_ADDRESSES` with local-only edits, and checkout picks from the same static list. A real address entity closes the chain end-to-end against the live API, following the established wave pattern (per-domain live pick in the mall's api plugin, mock adapter stays as fallback).
## What Changes
- New `addresses` table: `user_id` FK (cascade), recipient/phone/country/region/city/line1/postal_code, `is_default`, timestamps; partial unique index enforces one default per user.
- New route module `apps/api/src/routes/addresses.rs`: `GET/POST /api/addresses`, `PUT/DELETE /api/addresses/:id`, `POST /api/addresses/:id/default` — customer role only, ownership via `WHERE user_id =` (cross-user → 404). Default management is transactional (unset siblings in the same statement/transaction); the first address becomes default automatically; deleting the default promotes the most recent remaining address.
- `packages/shared`: `AddressBookEntry` type + `listMyAddresses` / `createAddress` / `updateAddress` / `deleteAddress` / `setDefaultAddress` on `ApiClient`.
- Mall mock adapter implements the same methods against its persisted state (seeded from `MOCK_ADDRESSES`), so mock mode keeps working and the rollback flag stays meaningful.
- Mall pages: `user/addresses.vue` switches to real CRUD (existing `UiModal` form pattern, plus delete + set-default); `checkout/index.vue` loads the address list from the API (falls back to an inline manual form when the list is empty) and submits the selected one; `addresses` joins `LIVE_PICKS`/`DEFAULT_LIVE_DOMAINS`.
- `scripts/seed-demo.mjs` seeds two demo addresses for `customer@vmall.local`, idempotently.
- Integration tests in `apps/api/tests/addresses.rs` (fixtures from `tests/common/mod.rs`): CRUD happy path, cross-user 404, single-default invariant, delete-default promotion, role guard.
## Capabilities
### New Capabilities
- `address-book`: per-customer saved shipping addresses with a single default.
### Modified Capabilities
- `frontend-mall`: the buyer center address page and checkout address selection use the live address API.
## Impact
`apps/api/migrations/0009_addresses.sql`, `apps/api/src/routes/{addresses.rs,mod.rs}`, router registration, `packages/shared/src/{types.ts,api.ts}`, `apps/mall/{mock/api.ts,plugins/api.ts,pages/user/addresses.vue,pages/checkout/index.vue,locales/user.ts,locales/checkout.ts}`, `scripts/seed-demo.mjs`, `apps/api/tests/addresses.rs`. The contract change rebuilds all three frontends.
## Non-goals
- No address auto-geocoding, no region cascader data (free-text region/city stays), no address selector inside the order-before flow beyond radio pick.
- Coupons, favorites, wallet stats, marketing subsystems (seckill/collective/integral) and reviews remain mock/future work, unchanged.