Files
tripz-llc/backend
Hamza-AyedandClaude Opus 4.8 253fbb4b2a feat: المجموعة E (كشف الاحتيال) + تشفير الهاتف at-rest
E — اتصال ثم إلغاء (من driver_ride_scam عند سيرو):
- E1: driver_called_passenger + last_call_at/by/count على الرحلة نفسها لا
  Redis فقط — حقيقة دائمة تفيد التحقيق بعد انتهاء الرحلة وزوالها من الكاش.
  يُسجَّل عند call:offer (بدء المكالمة الفعلي) في RealtimeGateway عبر
  Repository<Trip> مباشرة — لا استيراد TripsModule كاملاً (يستورد
  RealtimeModule أصلاً، فدورة استيراد)
- E2: FraudService.recordCallThenCancel — عدّاد يومي منفصل عن عدّاد الإلغاء
  العام بالساعة. 3/يوم = إنذار لا يمنع الإلغاء، 6/يوم = حظر مؤقت (طلب
  المالك حرفياً). يرتبط فقط إن كانت المكالمة خلال 30 دقيقة من الإلغاء

تشفير الهاتف at-rest (ملاحظة المالك) — بفهرس أعمى منفصل، لا تشفير ساذج:
- AES-256-GCM عشوائي IV يمنع WHERE phone = :x من المطابقة أصلاً (كل تشفير
  مختلف شكلاً حتى لنفس الرقم) — لو طُبِّق التشفير مباشرة بلا هذا لكسر تسجيل
  الدخول بالكامل بصمت
- users.phone_bidx = HMAC-SHA256(الرقم المطبَّع) — حتمي، يصلح للبحث
  وللقيد الفريد. القيد انتقل من (tenant_id, phone) إلى (tenant_id,
  phone_bidx) — القديم كان سيقبل تكرار نفس الرقم الحقيقي فعلياً
- findByPhone/create يحسبان البصمة؛ لا نقطة أخرى تقرأ phone بمساواة خام
- هجرة EncryptPhone تُشفّر الصفوف القائمة فوراً وتبني البصمة بأثر رجعي —
  استثناء متعمَّد من تسامح decrypt() المعتاد (الهاتف عمود بحث يومي، خطره
  كنص صافٍ أعلى من name)
- يعتمد على تطبيع D1: بصمة حتمية لنفس *النص*، فلا بد أن يصل الرقم مطبَّعاً
  قبلها وإلا عاد نفس الرقم بصيغتين ليصير رقمين مرة أخرى

هجرات: TripCallSignal · EncryptPhone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 17:25:18 +03:00
..

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(وكيل انطلق).