| T1 | سشن مشتری جدا نبود | `customer-auth/`، `JWT_CUSTOMER_SECRET`، `typ: 'customer'` | JWT جدا از ادمین؛ خواندن مجدد DB در هر درخواست | انجامشده — verify | [ ] |
| SEC-02 | `POST /orders` عمومی با `customerId` از body | `orders.controller/service`، DTO، Cart | `@CustomerAuth()`؛ customerId فقط از توکن | انجامشده — verify | [ ] |
| SEC-02b | `GET /orders/:id` IDOR | همان ماژول | `getOwnedById` → **404** نه 403؛ ادمین مسیر جدا | انجامشده — verify | [ ] |
| SEC-11 | OTP در `SmsMessage.body` plaintext | `customer-auth.service``deliver()` | فقط خط audit سانسورشده | انجامشده — verify | [ ] |
| SEC-04 | JWT ضعیف پیشفرض + CORS باز | boot API / CORS | production بدون `JWT_SECRET` بالا نیاید؛ `CORS_ORIGINS` | انجامشده — verify | [ ] |
| SEC-05 | seed دمو (پسورد = موبایل) در production | `prisma/seed.ts`، `bootstrap.ts` | دمو فقط با `SEED_DEMO_DATA=true` | انجامشده — verify | [ ] |
| ID | ایراد | مسیر تقریبی | فیکس | وضعیت | انجام |
|---|---|---|---|---|---|
| STUB-03 | کل کاتالوگ یکجا؛ pagination فقط کلاینت | catalog API + اپها | page/filter/sort سرور؛ `?ids=`، `/:id`، `/facets` | **مرحله ۴ انجام شد 2026-10-17** — Search/Newest/Home/Collection روی هر دو اپ؛ UI همان زبان طراحی | [x] |
| FAV-01 | علاقهمندی فقط memory | API `customer/me/favorites*`، `favoritesStore` | load/toggle سمت سرور | انجامشده — verify | [ ] |
| SMS-03 | بدون SMS ثبت سفارش | `orders.service` notify + `ORDER_ADMIN_MOBILES` | SMS بعد commit به ادمین/مشتری/کارشناس | انجامشده — verify | [ ] |
رفرنس منطق PWA (اگر از پروژهٔ مرجع بیاید — فقط رفتار، نه UI): composable `usePwaInstall` + مودال dismiss/defer؛ markup را با کامپوننتهای خود اپ بازنویسی کن.
---
## ۷) ادمین / پرمیشن / UX (دیزاین قابلرفرنس)
| ID / تم | ایراد | مسیر تقریبی | فیکس | وضعیت | انجام |
- فیچرهای اپ مثل PWA install، pull-refresh، incomplete-profile banner: فقط منطق/رفتار را port کن؛ UI را با زبان طراحی و کامپوننتهای خودِ این اپ بساز — از مودال/رنگ/illustration هدنا کپی نکن.
- پنل ادمین یکی است: برای دیزاین drawer سفارش، Icon محلی، dashboard unify، فرمها میتوانی مستقیم از ادمین مرجع رفرنس بگیری (باز هم بدون تعویض لوگو).
- قبل از هر تغییر UI سمت اپ از مالک بپرس.
A) امنیت
- روتهای ledger و تغییر وضعیت سفارش را از Public دربیاور؛ فقط ادمین با rid مناسب
- GET لیست مشتری برای login را حذف کن؛ سشن مشتری با JWT جدا (JWT_CUSTOMER_SECRET، typ=customer)
- OTP واقعی: bcrypt، انقضا ۲ دقیقه، ۵ تلاش، یکبارمصرف، throttle؛ OTP را در SMS audit plaintext ذخیره نکن
- POST /orders پشت CustomerAuth؛ customerId فقط از توکن؛ GET order با مالکیت → 404 نه 403
- production بدون JWT_SECRET بالا نیاید؛ CORS از CORS_ORIGINS؛ seed دمو فقط با SEED_DEMO_DATA
- env خالی "" را unset بگیر (envOr)؛ JWT مشتری fallback به secret ادمین نداشته باشد
- OTP_MASTER_CODE در production ممنوع مگر فلگ تست
B) پول/سفارش
- wage/discount/rial را از کلاینت نپذیر؛ فرمول سرور + لاگ mismatch
- sync بدهی سفارش idempotent با delta (نه پست دوباره)
- canPlaceOrders در اپ 403 کند؛ ادمین بتواند برای مشتری ثبت کند
- سقف موجودی در سبد (capQty/maxQty)
- سفارشهای اپ را WHOLESALE ذخیره کن نه RETAIL (اگر دامنه B2B است)
C) مشتری
- firstName/lastName جدا؛ percent خود مشتری (makingChargeOffsetPercent) نه کمیسیون نماینده
- پروفایل کارشناس فروش کامل؛ درخت شهر استان؛ تاریخ تولد؛ faToEn روی موبایل
D) اپ (منطق بله — دیزاین از خودِ این پروژه)
- requestOtp: 404 ثبتنشده، 503 SMS fail، 403 پیام جدا برای کارشناس
- toast ورود برای صفحات شخصی + redirect=
- act-as کارشناس با هدر X-Act-As-Customer (نه mint توکن)
- back تاریخچهدار؛ بعد login/401 از replace استفاده کن
- صفحات keep-alive را روی activate دوباره fetch کن
- PWA install: beforeinstallprompt + dismiss/defer؛ UI با کامپوننتهای خود اپ
- IRANSans را وصل کن؛ لوگو و کاروسل را دست نزن
E) کاتالوگ/SMS
- pagination/فیلتر سرور برای محصولات؛ favorites سمت سرور
- SMS ثبت سفارش بعد commit؛ شمارهها از env نه hardcode
- آپلود مدرک مشتری برای complete-profile
F) ادمین (دیزاین قابلرفرنس)
- ridهای یتیم dashboard را merge کن
- ویژگیهای خطرناک فقط super-admin؛ سوپرادمین ALL_RIDS
- Order status UX به صورت drawer راست + confirm logout — layout از ادمین مرجع
- Icon محلی بهجای @ant-design/icons-vue اگر همان وابستگی را دارید
- IRANSans در ادمین؛ لوگو را عوض نکن
برای هر آیتم: اول محل معادل در این ریپو را پیدا کن، بعد فیکس را با تست/smoke کوتاه اعمال کن.
جزئیات کامل: در ریپوی مرجع فایل docs/REPLICATION-CHECKLIST.md
```
---
## منبع برای جزئیات بیشتر
- لاگ کامل What/Why/Target: [`parity/CHANGELOG.md`](parity/CHANGELOG.md)