D1 — تطبيع أرقام الهاتف (JO/EG/SY): - common/phone/phone.service.ts: مفتاح قانوني واحد لكل رقم حقيقي — يقبل صفراً محلياً/دولياً/+/00/بلا صفر ويرجع صيغة دولية موحّدة بلا + - يعالج لبس مصر تحديداً الذي ذكره المالك: "01012345678" يُطبَّع بمفتاح 20 الصحيح لا "2" — الخوارزمية عامة فلا تحتاج معرفة اللبس، فقط تحذف الصفر البادئ وتضيف مفتاح الدولة الحقيقي - send-otp و verify-otp و platform/users/role تمرّ كلها بالتطبيع الآن؛ كانت تخزّن/تبحث بالرقم الخام كما كُتب — رقم واحد بصيغتين = حسابان - هجرة NormalizePhones تُصحّح حسابات الاختبار الموجودة على السيرفر، بحذر: تتخطّى أي تصادم بدل كسر القيد الفريد (tenant_id, phone) - أُزيل config.callingCodes المكرّر — مصدر واحد للحقيقة D2 — ربط الجلسة بالجهاز (نمط سيرو): **مبنيّ ومطفأ** (AUTH_REQUIRE_DEVICE_BINDING=false) حتى يرسل فلاتر x-device-id. منفَّذ داخل JwtStrategy.validate نفسها (passReqToCallback) لا كحارس يُضاف يدوياً لكل متحكّم — فلا نقطة محميّة يمكن نسيانها. التوكن يحمل hash(deviceId) لا القيمة الخام. verifyOtp/refresh يمرّران x-device-id من المتحكّم عند إصدار التوكن. D3 — HMAC: منفَّذ فعلاً ضمن I6 (SigningService/SignatureGuard)، لا تكرار. خطأ ضبطته قبل الدفع: كتبت مفتاح `auth:` ثانياً في configuration.ts — كائنات JS تسمح بمفاتيح مكرّرة والأخير يطغى، فكان سيمحو otpDevMode/otpTtl/ otpLength بالكامل. دُمج في الكتلة الأصلية بدل مفتاح جديد. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tripz Backend — NestJS (Docker فقط)
لا تثبيت محلي على الماك. الكود يُكتب محلياً، والبناء والتشغيل والهجرات كلها داخل Docker على السيرفر.
التشغيل على السيرفر
cd backend
cp .env.example .env # ثم عدّل كلمات المرور والأسرار
docker compose up -d --build # يبني ويشغّل: postgres/postgis, redis, martin, api, worker
الهجرات (داخل حاوية الـ api)
docker compose exec api npm run migration:run
الهجرات تعمل على النسخة المترجمة
dist/config/data-source.js(صورة الإنتاج بلا ts-node). لو ما رفعت آخر نسخة بعد، شغّل مباشرة:docker compose exec api node_modules/.bin/typeorm migration:run -d dist/config/data-source.js
فحص سريع
curl http://<server>:4010/api/health # {"status":"ok",...}
# توثيق Swagger: http://<server>:4010/api/docs
العزل على السيرفر المشترك (راجع docs/14)
- Postgres: قاعدة
tripz، بادئة جداولtripz_(مثال:tripz_tenants). - Redis: DB رقم 3 غير الافتراضي + بادئة مفاتيح
tripz:. - منافذ مضيف غير قياسية (API 4010، Postgres 55432) لتفادي التصادم.
- أسماء حاويات/شبكة/فوليوم ببادئة
tripz-.
البنية الحالية (P0)
src/
├── main.ts # bootstrap API (+ Swagger)
├── worker.ts # نقطة دخول BullMQ (هيكل)
├── app.module.ts # ConfigModule + TypeORM(entityPrefix) + Throttler + TenantMiddleware
├── config/ # configuration.ts + data-source.ts (هجرات)
├── common/
│ ├── tenant/ # context (AsyncLocalStorage) + middleware + @Tenant()
│ └── usage/ # UsageInterceptor (أساس الفوترة)
├── database/
│ ├── entities/ # tenant.entity.ts
│ └── migrations/ # InitTenants
└── modules/
├── health/ # GET /api/health
└── tenants/ # GET /api/tenant/config/:slug ، admin/tenants
التالي (P1)
users · auth(OTP) · drivers · trips(★ آلة حالة) · matching(Redis GEO) · tariff · realtime(Socket.IO) · maps(وكيل انطلق).