Files
Siro/knowledge/syria_driver_registration_report.md
2026-06-19 01:47:48 +03:00

353 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# تقرير نظام تسجيل السائق — سوريا 🇸🇾
> **ملف المحاكاة التفاعلية:** [siro_driver_registration_simulation.html](file:///Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/siro_driver_registration_simulation.html)
---
## 🗺️ خريطة النظام الكاملة
```mermaid
flowchart TD
A[📱 السائق يفتح التطبيق] --> B[RegisterCaptainController<br/>إدخال رقم الهاتف]
B --> C{التحقق من الدولة}
C -->|🇸🇾 سوريا| D[Phone Formatting<br/>09xx → 963xx]
D --> E[POST /auth/otp/request.php<br/>country: Syria]
E --> F{OTP Router}
F -->|Primary| G[Intaleq WhatsApp]
F -->|Failover 1| H[Nabeh JWT]
F -->|Failover 2| I[SMS]
G --> J[DB: phone_verification<br/>AES-GCM encrypted × 5min]
J --> K[OtpVerificationController<br/>countdown 120s]
K --> L[POST /auth/otp/verify.php]
L --> M{✅ صحيح؟}
M -->|نعم| N[RegistrationController<br/>3-Step Wizard]
M -->|لا| K
N --> O[Step 1: Driver Info<br/>الاسم + HID + DOB + License]
O --> P[Step 2: Car Info<br/>Plate + Make + Model + VIN]
P --> Q[Step 3: Doc Upload × 8]
Q --> R[uploadToSyria × 8<br/>MultipartRequest + JWT]
R --> S[uploadSyrianDocs.php<br/>private_uploads Signed URL 48h]
S --> T[submitRegistration<br/>POST /register_driver_and_car.php]
T --> U[🤖 Gemini Flash<br/>Vision AI Analysis]
U --> V{AI Face Match}
V -->|✅ high| W[DB Transaction<br/>driver + CarRegistration]
V -->|❌ mismatch| X[jsonError - رفض]
W --> Y[FCM → topic:service<br/>Admin Notification]
Y --> Z[status: yet ⏳]
Z --> AA[Admin Review]
AA --> AB[status: active ✅]
AB --> AC[JWT + driverToken<br/>السائق جاهز للعمل]
```
---
## 📱 مراحل التسجيل (8 خطوات)
### 1⃣ إدخال رقم الهاتف — `RegisterCaptainController`
**منطق تنسيق الرقم السوري:**
```php
// من: register_driver_and_car.php
if (strpos($phone, '00963') === 0) {
$phone = substr($phone, 2); // 00963 → 963
} elseif (strpos($phone, '09') === 0) {
$phone = '963' . substr($phone, 1); // 09xx → 9639xx
} elseif (strpos($phone, '9') === 0 && strlen($phone) == 9) {
$phone = '963' . $phone; // 9xxxxxxxx → 9639xxxxxxxx
}
// التأكد من وجود 9 بعد 963
if (strpos($phone, '963') === 0 && strpos($phone, '9639') !== 0) {
$phone = '9639' . substr($phone, 3);
}
```
---
### 2⃣ نظام OTP — `OtpVerificationController`
| الدولة | المزود الأساسي | Failover 1 | Failover 2 |
|--------|---------------|-----------|-----------|
| 🇸🇾 سوريا | Intaleq WhatsApp | Nabeh JWT | SMS |
| 🇪🇬 مصر | Kazumi SMS | Intaleq WhatsApp | Nabeh JWT |
| 🇯🇴 الأردن | Intaleq SMS | Nabeh JWT | — |
**مخطط DB:**
```sql
-- جدول التحقق للسائق
INSERT INTO phone_verification (
phone_number, -- مشفر AES-GCM
driverId,
email, -- مشفر AES-GCM
token_code, -- مشفر AES-GCM (3 أرقام)
expiration_time, -- NOW() + 5 دقائق
is_verified -- 0 → 1 عند النجاح
)
```
> [!NOTE]
> Rate Limiting: 3 محاولات كل 5 دقائق لكل IP عبر Redis
---
### 3⃣ معلومات السائق — `RegistrationController` Page 0
**الحقول المطلوبة:**
- `first_name`, `last_name`, `national_number`, `birthdate`, `expiry_date`
- التحقق عبر `driverInfoFormKey.validate()`
**ملاحظة تاريخ الميلاد:**
```php
// من register_driver_and_car.php
$data['birthdate'] = trim($data['birthdate']) . '-01-01';
// "1990" → "1990-01-01"
```
---
### 4⃣ معلومات المركبة — `RegistrationController` Page 1
**الحقول الجديدة (vehicle_category_id + fuel_type_id):**
| ID | نوع المركبة | ID | نوع الوقود |
|---|------------|---|-----------|
| 1 | سيارة (Car) | 1 | بنزين (Petrol) |
| 2 | دراجة نارية | 2 | ديزل (Diesel) |
| 3 | فان / باص | 3 | كهربائي |
| — | — | 4 | هايبرد |
```dart
// Flutter → submitRegistration()
_addField(fields, 'vehicle_category_id', selectedVehicleCategoryId.toString());
_addField(fields, 'fuel_type_id', selectedFuelTypeId.toString());
_addField(fields, 'fuel', fuelObj['name'].toString()); // للتوافق
```
---
### 5⃣ رفع الوثائق — `uploadToSyria()` × 8
**الوثائق المطلوبة لسوريا:**
| المستند | الحقل | إلزامي سوريا؟ |
|---------|-------|--------------|
| هوية — وجه | `id_front` | ✅ |
| هوية — خلف | `id_back` | ✅ |
| رخصة القيادة — وجه | `driver_license` | ✅ |
| رخصة القيادة — خلف | `driver_license_back` | **🇸🇾 إلزامي فقط!** |
| صورة شخصية | `profile_picture` | ✅ |
| لا حكم عليه | `criminal_record` | ✅ |
| ترخيص سيارة — وجه | `car_license_front` | ✅ |
| ترخيص سيارة — خلف | `car_license_back` | ✅ |
**آلية الرفع:**
```dart
// Flutter: uploadToSyria()
final req = http.MultipartRequest('POST', syrianUploadUri);
req.headers.addAll({
'Authorization': 'Bearer JWT',
'X-HMAC-Auth': hmacHeader,
});
req.fields['driver_id'] = driverId;
req.fields['doc_type'] = docType; // e.g., 'driver_license_back'
// timeout: 120 ثانية — 3 محاولات تلقائية
```
**Backend — الرد (Signed URL):**
```json
{
"status": "success",
"file_url": "https://api-syria.siromove.com/siro/secure_image.php?driver_id=DRV...&doc_type=id_front&ext=jpg&expires=1720000000&signature=sha256...",
"mime_type": "image/jpeg",
"size_bytes": 98340,
"expires_at": "2024-06-21T..."
}
```
> [!IMPORTANT]
> الملفات تُحفظ في `private_uploads/` (خارج الويب العام) ولا يمكن الوصول إليها إلا عبر رابط موقّع صالح لمدة **48 ساعة**.
---
### 6⃣ الذكاء الاصطناعي Gemini Flash — Vision AI
**البرومبت الكامل يطلب:**
```json
{
"status": "success|failure",
"reason": "إذا فشل",
"face_match_confidence": "high|low",
"driver": {
"full_name": "", // الاسم الكامل بالعربي
"national_number": "", // أرقام لاتينية فقط
"dob": "YYYY-MM-DD",
"governorate": "",
"license_expiry_date": "YYYY-MM-DD",
"license_category": "B|D1|..."
},
"car": {
"car_plate": "", // e.g., "155186 درعا"
"vin": "", // أحرف وأرقام لاتينية
"color": "",
"color_hex": "#FFFFFF",
"make": "", "model": "", "year": ""
}
}
```
**قواعد الذكاء الاصطناعي الحرجة:**
1. **FACE MATCHING**: مقارنة الصورة الشخصية ↔ الهوية ↔ رخصة القيادة
2. **OCR ذكي**: المسح من كلا وجهي كل وثيقة
3. تحويل الأرقام العربية (٠١٢) إلى لاتينية (012)
4. تطبيع ألوان السيارات `أبيض → White → #FFFFFF`
5. الفشل الكلي فقط عند: وجه غير متطابق / وثائق مزورة
> [!WARNING]
> **SSRF Protection**: URLs يُسمح بها فقط من `allowedHosts` — يُمنع تحميل أي صورة من مصادر خارجية.
---
### 7⃣ إدراج قاعدة البيانات — Transaction Atomique
**الحقول المشفرة في جدول `driver`:**
```php
$toEncryptDriver = [
"phone", "email", "first_name", "last_name",
"name_arabic", "gender", "national_number",
"address", "site", "fullNameMaritial", "birthdate"
];
// كلها تُشفَّر بـ AES-GCM قبل الإدراج
```
**كلمة المرور (HMAC + bcrypt):**
```php
$baseString = implode('|', [$data['id'], $data['phone'], $data['national_number']]);
$rawSecret = hash_hmac('sha256', $baseString, $pepper, true);
$pwdHashed = password_hash($rawSecret, PASSWORD_DEFAULT);
```
---
### 8⃣ جداول قاعدة البيانات (`schema_primary.sql`)
**`CarRegistration` — الجدول الرئيسي للمركبات:**
```sql
CREATE TABLE `CarRegistration` (
`id` int AUTO_INCREMENT PRIMARY KEY,
`driverID` varchar(100) NOT NULL, -- FK → driver.id
`vin` varchar(100) NOT NULL, -- مشفر
`car_plate` varchar(150), -- مشفر
`make` varchar(255) NOT NULL,
`model` varchar(255) NOT NULL,
`year` int NOT NULL,
`expiration_date` varchar(30) NOT NULL,
`color` varchar(255) NOT NULL,
`owner` varchar(255) NOT NULL, -- مشفر
`color_hex` varchar(20) NOT NULL,
`fuel` varchar(100) NOT NULL,
`vehicle_category_id` tinyint DEFAULT 1, -- 1=Car,2=Moto,3=Van
`fuel_type_id` tinyint DEFAULT 1, -- 1=Petrol,2=Diesel...
`status` varchar(20) DEFAULT 'yet', -- yet|active|suspended
`isDefault` tinyint DEFAULT 0,
KEY `idx_driverID` (`driverID`)
)
```
**`driver` — الجدول الرئيسي للسائقين:**
```sql
CREATE TABLE `driver` (
`id` varchar(100) NOT NULL, -- DRV{timestamp}{random}
`phone` varchar(255) NOT NULL, -- مشفر AES-GCM
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL, -- bcrypt(HMAC)
`first_name` varchar(255) NOT NULL, -- مشفر
`last_name` varchar(255) NOT NULL, -- مشفر
`national_number` varchar(255), -- مشفر (UNIQUE)
`name_arabic` varchar(255), -- مشفر — من AI
`birthdate` varchar(255), -- مشفر
`status` varchar(20) DEFAULT 'notDeleted', -- yet|active|notDeleted
`expiry_date` date, -- انتهاء رخصة القيادة
UNIQUE KEY `national_number` (`national_number`)
)
```
**`driver_documents`:**
```sql
CREATE TABLE `driver_documents` (
`id` int AUTO_INCREMENT PRIMARY KEY,
`driverID` varchar(64) NOT NULL,
`doc_type` varchar(64) NOT NULL, -- id_front, driver_license_back, ...
`image_name` varchar(255) NOT NULL,
`link` varchar(512) NOT NULL, -- Signed URL
`upload_date` datetime NOT NULL,
KEY `driverID` (`driverID`)
)
```
---
## 🔒 طبقات الأمان
| الطبقة | التقنية | التفاصيل |
|--------|---------|---------|
| Authentication | JWT Bearer | يُعاد التوليد عند كل دخول |
| Transport | HMAC-SHA256 | X-HMAC-Auth header |
| Encryption at Rest | AES-GCM | جميع البيانات الحساسة |
| Password | HMAC + bcrypt | pepper من env |
| Rate Limiting | Redis | 3 OTP / 5 دقائق لكل IP |
| File Access | Signed URLs | HMAC-SHA256 صالح 48 ساعة |
| SSRF Protection | Allowlist hosts | منع URL injection في AI |
| SQL Injection | PDO Prepared Statements | كل الاستعلامات |
| File Upload | MIME detection + finfo | ليس Content-Type فقط |
---
## ✅ النتيجة: هل النظام يعمل صح؟
| العملية | السلوك | التقييم |
|---------|--------|---------|
| تنسيق الهاتف السوري | `09xx``9639xx` تلقائياً | ✅ |
| OTP سوريا | Intaleq WhatsApp → Nabeh Failover | ✅ |
| خلف رخصة القيادة | إلزامي فقط لـ `countryCode == Syria` | ✅ |
| رفع الوثائق | Retry × 3 + Timeout 120s | ✅ |
| AI Face Match | Gemini Flash Vision — تحقق ذكي | ✅ |
| AI يعيد كتابة البيانات | اسم، DOB، لوحة، VIN من الوثائق | ✅ |
| Transaction | Atomic: driver + CarRegistration + documents | ✅ |
| تشفير الحقول | phone, name, national_number → AES-GCM | ✅ |
| `vehicle_category_id` و `fuel_type_id` | يُرسلان من Flutter ويُخزنان في CarRegistration | ✅ |
| إشعار خدمة العملاء | FCM → topic:service بعد التسجيل | ✅ |
| Signed URL | صالح 48 ساعة + HMAC signed | ✅ |
> [!CAUTION]
> **ملاحظة:** حقل `vin` في `submitRegistration()` يُرسل كـ `'yet'` افتراضياً ولا يُرسل من حقل `carVinController`:
> ```dart
> _addField(fields, 'vin', 'yet'); // ← يجب ربطه بـ carVinController.text
> ```
> AI سيُصحح هذا من خلال استخراج VIN من صورة ترخيص السيارة، لكن إذا لم يعمل AI فسيُخزن 'yet'.
---
## 📁 الملفات المرجعية
| الملف | الدور |
|-------|-------|
| [registration_controller.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/lib/controller/auth/syria/registration_controller.dart) | Controller رئيسي — رفع الوثائق + تقديم التسجيل |
| [register_captin_controller.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/lib/controller/auth/captin/register_captin_controller.dart) | تسجيل مبدئي + OTP |
| [opt_token_controller.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/lib/controller/auth/captin/opt_token_controller.dart) | إدارة OTP (120 ثانية countdown) |
| [register_driver_and_car.php](file:///Users/hamzaaleghwairyeen/development/App/Siro/backend/auth/syria/driver/register_driver_and_car.php) | Backend — Gemini AI + DB Transaction |
| [uploadSyrianDocs.php](file:///Users/hamzaaleghwairyeen/development/App/Siro/backend/auth/syria/uploadSyrianDocs.php) | Backend — رفع الوثائق + Signed URL |
| [request.php](file:///Users/hamzaaleghwairyeen/development/App/Siro/backend/auth/otp/request.php) | Backend — إرسال OTP حسب الدولة |
| [verify.php](file:///Users/hamzaaleghwairyeen/development/App/Siro/backend/auth/otp/verify.php) | Backend — التحقق من OTP |
| [schema_primary.sql](file:///Users/hamzaaleghwairyeen/development/App/Siro/backend/schema_primary.sql) | DB Schema — driver + CarRegistration + driver_documents |