Update: 2026-05-08 06:19:56

This commit is contained in:
Hamza-Ayed
2026-05-08 06:19:56 +03:00
parent df92a44878
commit 753497649a
18 changed files with 1310 additions and 21 deletions

View File

@@ -1,3 +1,6 @@
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
// START: FlutterFire Configuration
@@ -8,10 +11,17 @@ plugins {
id("dev.flutter.flutter-gradle-plugin")
}
// Load keystore properties from key.properties file
val keystorePropertiesFile = rootProject.file("key.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
namespace = "com.example.musadaq_app"
namespace = "com.musadaq.app"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
ndkVersion = "28.2.13676358"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
@@ -22,11 +32,19 @@ android {
jvmTarget = JavaVersion.VERSION_11.toString()
}
signingConfigs {
create("release") {
if (keystorePropertiesFile.exists()) {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.musadaq_app"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
applicationId = "com.musadaq.app"
minSdk = 24
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
@@ -35,9 +53,17 @@ android {
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
signingConfig = if (keystorePropertiesFile.exists()) {
signingConfigs.getByName("release")
} else {
signingConfigs.getByName("debug")
}
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}

View File

@@ -7,9 +7,9 @@
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:512384487867:android:eac271c0b0ea64b708749e",
"mobilesdk_app_id": "1:512384487867:android:6098e34775ad6c7708749e",
"android_client_info": {
"package_name": "com.example.musadaq_app"
"package_name": "com.musadaq.app"
}
},
"oauth_client": [],

View File

@@ -0,0 +1,22 @@
# Flutter ProGuard Rules for Musadaq
# Keep Flutter engine
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
# Keep Firebase
-keep class com.google.firebase.** { *; }
# Keep Dio
-keep class io.github.nicekun.** { *; }
-dontwarn okhttp3.**
-dontwarn okio.**
# Keep CameraAwesome
-keep class com.apparence.camerawesome.** { *; }
# Keep ObjectBox
-keep class io.objectbox.** { *; }
# Ignore missing Play Core classes referenced by Flutter Engine
-dontwarn com.google.android.play.core.**

View File

@@ -16,7 +16,7 @@
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<application
android:label="musadaq_app"
android:label="مُصادَق"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon"
android:enableOnBackInvokedCallback="true">

View File

@@ -1,4 +1,4 @@
package com.example.musadaq_app
package com.musadaq.app
import io.flutter.embedding.android.FlutterFragmentActivity

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">مُصادَق</string>
</resources>

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"musadaq-c12ca","appId":"1:512384487867:android:eac271c0b0ea64b708749e","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"musadaq-c12ca","appId":"1:512384487867:ios:03bd28c6088a4aa008749e","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"musadaq-c12ca","configurations":{"android":"1:512384487867:android:eac271c0b0ea64b708749e","ios":"1:512384487867:ios:03bd28c6088a4aa008749e"}}}}}}
{"flutter":{"platforms":{"android":{"default":{"projectId":"musadaq-c12ca","appId":"1:512384487867:android:6098e34775ad6c7708749e","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"musadaq-c12ca","appId":"1:512384487867:ios:c743b83778682d8308749e","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"musadaq-c12ca","configurations":{"android":"1:512384487867:android:6098e34775ad6c7708749e","ios":"1:512384487867:ios:c743b83778682d8308749e"}}}}}}

View File

@@ -9,7 +9,7 @@
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.example.musadaqApp</string>
<string>com.musadaq.app</string>
<key>PROJECT_ID</key>
<string>musadaq-c12ca</string>
<key>STORAGE_BUCKET</key>
@@ -25,6 +25,6 @@
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:512384487867:ios:03bd28c6088a4aa008749e</string>
<string>1:512384487867:ios:c743b83778682d8308749e</string>
</dict>
</plist>

View File

@@ -0,0 +1,237 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:freerasp/freerasp.dart';
import 'package:get/get.dart';
/// Device Security Service
/// Enterprise-grade jailbreak/root/tamper detection for Musadaq using freeRASP.
///
/// Detects: root, jailbreak, debugger, emulator, hooking frameworks,
/// tampered apps, unofficial stores, missing passcode.
///
/// Policy: On detection → block app with security warning (no data access).
class DeviceSecurityService extends GetxService {
final isCompromised = false.obs;
final threatDetails = <String>[].obs;
final securityChecked = false.obs;
@override
void onInit() {
super.onInit();
_initSecurity();
}
/// Initialize freeRASP
Future<void> _initSecurity() async {
try {
await _initFreeRASP();
} catch (e) {
debugPrint('[Security] freeRASP init failed: $e');
}
securityChecked.value = true;
}
/// Initialize freeRASP with full threat callbacks
Future<void> _initFreeRASP() async {
final callback = ThreatCallback(
onAppIntegrity: () => _onThreatDetected('تلاعب بالتطبيق'),
onObfuscationIssues: () => _onThreatDetected('عدم وجود تشفير الكود'),
onDebug: () => _onThreatDetected('وضع التصحيح مفعّل'),
onDeviceBinding: () => _onThreatDetected('تغيير جهاز غير مصرح'),
onDeviceID: () => _onThreatDetected('معرّف جهاز مزوّر'),
onHooks: () => _onThreatDetected('أدوات اختراق (Hooking)'),
onPasscode: () => _onThreatDetected('الجهاز بدون قفل شاشة'),
onPrivilegedAccess: () => _onThreatDetected('جهاز مروّت (Root/Jailbreak)'),
onSecureHardwareNotAvailable: () =>
_onThreatDetected('عدم توفر عتاد آمن'),
onSimulator: () => _onThreatDetected('محاكي (Emulator)'),
onUnofficialStore: () => _onThreatDetected('تثبيت من متجر غير رسمي'),
);
// Configure talsec
final config = TalsecConfig(
androidConfig: AndroidConfig(
packageName: 'com.musadaq.app',
signingCertHashes: ['4F:10:B4:E9:29:E0:5E:0A:3E:AE:B0:31:4C:C1:3A:DB:CB:E6:FF:DF:6A:F5:85:FC:68:FE:C1:E4:B6:29:6B:6F'],
supportedStores: ['com.android.vending'], // Google Play only
),
iosConfig: IOSConfig(
bundleIds: ['com.musadaq.app'],
teamId: 'REPLACE_WITH_YOUR_TEAM_ID',
),
watcherMail: 'security@musadaq.jo',
isProd: true,
);
await Talsec.instance.start(config);
Talsec.instance.attachListener(callback);
debugPrint('[Security] freeRASP initialized');
}
/// Handle threat detection
void _onThreatDetected(String threat) {
debugPrint('[Security] ⚠️ THREAT: $threat');
threatDetails.add(threat);
isCompromised.value = true;
// Block the app immediately
_showSecurityBlock();
}
/// Show a non-dismissible security warning that blocks the app
void _showSecurityBlock() {
// Only show once
if (Get.isDialogOpen == true) return;
Get.dialog(
PopScope(
canPop: false,
child: Scaffold(
backgroundColor: const Color(0xFF1A1A2E),
body: SafeArea(
child: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Shield icon
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red.withValues(alpha: 0.15),
),
child: const Icon(
Icons.shield_rounded,
size: 56,
color: Colors.red,
),
),
const SizedBox(height: 32),
// Title
const Text(
'تحذير أمني',
style: TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.bold,
fontFamily: 'El Messiri',
),
),
const SizedBox(height: 16),
// Message
const Text(
'تم اكتشاف أن هذا الجهاز غير آمن.\n'
'لحماية بياناتك المالية والضريبية،\n'
'لا يمكن تشغيل مُصادَق على هذا الجهاز.',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white70,
fontSize: 15,
height: 1.6,
),
),
const SizedBox(height: 24),
// Threat details
Obx(() => Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.red.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.red.withValues(alpha: 0.3)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'التهديدات المكتشفة:',
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
fontSize: 13,
),
),
const SizedBox(height: 8),
...threatDetails.map((t) => Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Row(
children: [
const Icon(Icons.warning_amber,
color: Colors.red, size: 16),
const SizedBox(width: 8),
Text(t,
style: const TextStyle(
color: Colors.white60,
fontSize: 13)),
],
),
)),
],
),
)),
const SizedBox(height: 32),
// Close button (exits the app)
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => SystemNavigator.pop(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
),
icon: const Icon(Icons.exit_to_app,
color: Colors.white),
label: const Text(
'إغلاق التطبيق',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 16),
// Help text
const Text(
'إذا كنت تعتقد أن هذا خطأ، تواصل مع\nsupport@musadaq.jo',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white38, fontSize: 12),
),
],
),
),
),
),
),
),
barrierDismissible: false,
);
}
/// Quick check if device is safe (for use in API calls)
bool get isSafe => !isCompromised.value;
/// Get security status for display
Map<String, dynamic> getSecurityStatus() {
return {
'is_safe': isSafe,
'checked': securityChecked.value,
'threats': threatDetails.toList(),
'threat_count': threatDetails.length,
};
}
}

View File

@@ -0,0 +1,147 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shorebird_code_push/shorebird_code_push.dart';
/// Shorebird Code Push Service
/// Handles OTA (Over-The-Air) updates for Dart code.
/// Checks for patches on app launch and notifies users when updates are available.
class ShorebirdUpdateService extends GetxService {
final _updater = ShorebirdUpdater();
final isUpdateAvailable = false.obs;
final isDownloading = false.obs;
final currentPatchNumber = 0.obs;
@override
void onInit() {
super.onInit();
_checkForUpdate();
}
/// Check if Shorebird is available (only works with shorebird release builds)
bool get isShorebirdAvailable => _updater.isAvailable;
/// Get current patch number
Future<void> loadCurrentPatch() async {
if (!isShorebirdAvailable) return;
try {
final patch = await _updater.readCurrentPatch();
currentPatchNumber.value = patch?.number ?? 0;
} catch (_) {}
}
/// Check for updates on launch
Future<void> _checkForUpdate() async {
if (!isShorebirdAvailable) {
debugPrint('[Shorebird] Not available (debug build)');
return;
}
try {
await loadCurrentPatch();
debugPrint('[Shorebird] Current patch: ${currentPatchNumber.value}');
final status = await _updater.checkForUpdate();
if (status == UpdateStatus.outdated) {
isUpdateAvailable.value = true;
debugPrint('[Shorebird] Update available!');
_showUpdateDialog();
} else {
debugPrint('[Shorebird] App is up to date');
}
} catch (e) {
debugPrint('[Shorebird] Error checking for update: $e');
}
}
/// Download and apply the update
Future<void> downloadUpdate() async {
if (!isShorebirdAvailable) return;
isDownloading.value = true;
try {
await _updater.update();
isDownloading.value = false;
isUpdateAvailable.value = false;
// Show restart prompt
Get.defaultDialog(
title: '✅ تم التحديث',
middleText: 'تم تحميل التحديث بنجاح.\nأعد تشغيل التطبيق لتطبيق التغييرات.',
textConfirm: 'حسناً',
confirmTextColor: Colors.white,
buttonColor: const Color(0xFF0F4C81),
onConfirm: () => Get.back(),
titleStyle: const TextStyle(fontWeight: FontWeight.bold),
radius: 14,
);
} catch (e) {
isDownloading.value = false;
debugPrint('[Shorebird] Download failed: $e');
Get.snackbar(
'خطأ',
'فشل تحميل التحديث',
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
}
/// Show update available dialog
void _showUpdateDialog() {
Get.defaultDialog(
title: '🔄 تحديث متاح',
middleText: 'يتوفر تحديث جديد لمُصادَق.\nهل تريد تحميله الآن؟',
textConfirm: 'تحديث',
textCancel: 'لاحقاً',
confirmTextColor: Colors.white,
buttonColor: const Color(0xFF0F4C81),
onConfirm: () {
Get.back();
downloadUpdate();
},
titleStyle: const TextStyle(fontWeight: FontWeight.bold),
radius: 14,
);
}
/// Manual check (can be called from settings)
Future<void> manualCheckForUpdate() async {
if (!isShorebirdAvailable) {
Get.snackbar(
'تنبيه',
'التحديث التلقائي متاح فقط في نسخة الإصدار',
backgroundColor: Colors.orange,
colorText: Colors.white,
);
return;
}
Get.snackbar(
'جارٍ الفحص...',
'يتم البحث عن تحديثات',
backgroundColor: const Color(0xFF0F4C81),
colorText: Colors.white,
showProgressIndicator: true,
duration: const Duration(seconds: 2),
);
try {
final status = await _updater.checkForUpdate();
if (status == UpdateStatus.outdated) {
isUpdateAvailable.value = true;
_showUpdateDialog();
} else {
Get.snackbar(
'✅ محدّث',
'التطبيق يعمل بأحدث إصدار (Patch ${currentPatchNumber.value})',
backgroundColor: const Color(0xFF10B981),
colorText: Colors.white,
);
}
} catch (e) {
Get.snackbar('خطأ', 'فشل البحث عن تحديثات',
backgroundColor: Colors.red, colorText: Colors.white);
}
}
}

View File

@@ -3,6 +3,8 @@ import 'package:get/get.dart';
import '../controllers/settings_controller.dart';
import '../../../app/routes/app_pages.dart';
import '../../../core/utils/app_snackbar.dart';
import '../../../core/services/shorebird_update_service.dart';
import '../../../core/services/device_security_service.dart';
class SettingsView extends GetView<SettingsController> {
const SettingsView({super.key});
@@ -148,6 +150,18 @@ class SettingsView extends GetView<SettingsController> {
isDark: isDark,
),
const Divider(height: 1),
Builder(builder: (_) {
final security = Get.find<DeviceSecurityService>();
return Obx(() => _buildInfoTile(
icon: security.isSafe
? Icons.verified_user_rounded
: Icons.gpp_bad_rounded,
title: 'حالة الأمان',
trailing: security.isSafe ? '✅ آمن' : '⚠️ غير آمن',
isDark: isDark,
));
}),
const Divider(height: 1),
_buildInfoTile(
icon: Icons.diamond_rounded,
title: 'الاشتراكات والباقات',
@@ -170,6 +184,17 @@ class SettingsView extends GetView<SettingsController> {
isDark: isDark,
onTap: () {},
),
const Divider(height: 1),
_buildInfoTile(
icon: Icons.system_update_rounded,
title: 'البحث عن تحديثات',
trailing: 'فحص →',
isDark: isDark,
onTap: () {
final shorebird = Get.find<ShorebirdUpdateService>();
shorebird.manualCheckForUpdate();
},
),
]),
const SizedBox(height: 32),
_buildLogoutButton(),

View File

@@ -51,7 +51,7 @@ class DefaultFirebaseOptions {
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyB7Gc_RNvFaFCsuN5acHK2SNkY5iMDecqk',
appId: '1:512384487867:android:eac271c0b0ea64b708749e',
appId: '1:512384487867:android:6098e34775ad6c7708749e',
messagingSenderId: '512384487867',
projectId: 'musadaq-c12ca',
storageBucket: 'musadaq-c12ca.firebasestorage.app',
@@ -59,10 +59,11 @@ class DefaultFirebaseOptions {
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyBLKc35OqzY6oQA5507E2uHCCHQbRWAC_M',
appId: '1:512384487867:ios:03bd28c6088a4aa008749e',
appId: '1:512384487867:ios:c743b83778682d8308749e',
messagingSenderId: '512384487867',
projectId: 'musadaq-c12ca',
storageBucket: 'musadaq-c12ca.firebasestorage.app',
iosBundleId: 'com.example.musadaqApp',
iosBundleId: 'com.musadaq.app',
);
}
}

View File

@@ -6,6 +6,8 @@ import 'app/routes/app_pages.dart';
import 'core/services/push_notification_service.dart';
import 'core/services/upload_progress_service.dart';
import 'core/services/home_widget_service.dart';
import 'core/services/shorebird_update_service.dart';
import 'core/services/device_security_service.dart';
import 'app/theme/app_theme.dart';
@pragma('vm:entry-point')
@@ -24,9 +26,13 @@ void main() async {
// 2. Register background handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
// 3. Register global services
// 3. Security check (MUST be first)
Get.put(DeviceSecurityService(), permanent: true);
// 4. Register global services
Get.put(UploadProgressService(), permanent: true);
Get.put(HomeWidgetService(), permanent: true);
Get.put(ShorebirdUpdateService(), permanent: true);
runApp(const MusadaqApp());
}

View File

@@ -592,6 +592,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
freerasp:
dependency: "direct main"
description:
name: freerasp
sha256: "76a3fb6f8e3fdd7d83e224866998523e7fb79d5779321983e484a6cfbf4b01b5"
url: "https://pub.dev"
source: hosted
version: "6.12.0"
frontend_server_client:
dependency: transitive
description:
@@ -1264,6 +1272,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
shorebird_code_push:
dependency: "direct main"
description:
name: shorebird_code_push
sha256: "55d5eea098a4293199d22dfd263ce1d6c10820ceb42c2acb950f971a8bcee0ce"
url: "https://pub.dev"
source: hosted
version: "2.0.6"
sky_engine:
dependency: transitive
description: flutter

View File

@@ -63,6 +63,12 @@ dependencies:
firebase_core: ^4.7.0
firebase_messaging: ^16.2.0
# ─── Code Push (OTA Updates) ────────────────────────
shorebird_code_push: ^2.0.0
# ─── Security (Root/Jailbreak/Tamper Detection) ─────
freerasp: ^6.6.0
dev_dependencies:
flutter_test:
sdk: flutter
@@ -85,6 +91,7 @@ flutter_launcher_icons:
flutter:
uses-material-design: true
assets:
- shorebird.yaml
- assets/images/logo.jpg
- assets/images/onboarding_1.png
- assets/images/onboarding_2.png

View File

@@ -0,0 +1,14 @@
# This file is used to configure the Shorebird updater used by your app.
# Learn more at https://docs.shorebird.dev
# This file does not contain any sensitive information and should be checked into version control.
# Your app_id is the unique identifier assigned to your app.
# It is used to identify your app when requesting patches from Shorebird's servers.
# It is not a secret and can be shared publicly.
app_id: 34bbf488-9870-4717-b6c7-408485fcf264
# auto_update controls if Shorebird should automatically update in the background on launch.
# If auto_update: false, you will need to use package:shorebird_code_push to trigger updates.
# https://pub.dev/packages/shorebird_code_push
# Uncomment the following line to disable automatic updates.
# auto_update: false

121
public/privacy.php Normal file
View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>سياسة الخصوصية مُصادَق</title>
<meta name="description" content="سياسة الخصوصية لمنصة مُصادَق. تعرف على كيفية حماية بياناتك ومعالجتها بأمان.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--emerald: #10b981; --emerald-dark: #059669; --emerald-glow: rgba(16,185,129,0.15);
--bg: #060a12; --bg2: #0c1220; --bg3: #111827;
--text: #f0f6fc; --text2: #8b949e; --border: rgba(255,255,255,0.08);
}
body { font-family: 'IBM Plex Sans Arabic', sans-serif; background: var(--bg); color: var(--text); line-height: 1.7; }
a { color: var(--emerald); text-decoration: none; }
a:hover { text-decoration: underline; }
/* === NAV === */
.nav { position: fixed; top: 0; width: 100%; z-index: 100; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; backdrop-filter: blur(20px); background: rgba(6,10,18,0.8); border-bottom: 1px solid var(--border); }
.nav-logo { font-size: 1.5rem; font-weight: 700; color: var(--emerald); }
.nav-links { display: flex; gap: 2rem; align-items: center; }
.nav-links a { color: var(--text2); font-size: 0.9rem; text-decoration: none; }
.nav-links a:hover { color: var(--emerald); text-decoration: none; }
/* === CONTENT === */
.container { max-width: 800px; margin: 8rem auto 4rem; padding: 0 2rem; }
h1 { font-size: 2.5rem; margin-bottom: 1rem; color: var(--emerald); }
.last-updated { color: var(--text2); font-size: 0.9rem; margin-bottom: 3rem; }
h2 { font-size: 1.5rem; margin: 2.5rem 0 1rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
p { margin-bottom: 1rem; color: #cbd5e1; }
ul { margin-bottom: 1rem; padding-right: 1.5rem; color: #cbd5e1; }
li { margin-bottom: 0.5rem; }
/* === FOOTER === */
footer { padding: 3rem 2rem; border-top: 1px solid var(--border); text-align: center; color: var(--text2); font-size: 0.85rem; margin-top: 4rem; }
</style>
</head>
<body>
<!-- NAV -->
<nav class="nav">
<div class="nav-logo"><a href="/" style="color: inherit; text-decoration: none;">مُصادَق</a></div>
<div class="nav-links">
<a href="/">الرئيسية</a>
<a href="/login.php">تسجيل الدخول</a>
</div>
</nav>
<!-- CONTENT -->
<div class="container">
<h1>سياسة الخصوصية</h1>
<div class="last-updated">آخر تحديث: 8 مايو 2026</div>
<p>نحن في <strong>مُصادَق</strong> ("نحن"، "المنصة"، أو "التطبيق") نولي اهتماماً بالغاً بخصوصية بياناتك المالية والشخصية. توضح سياسة الخصوصية هذه كيفية جمعنا، واستخدامنا، وحمايتنا لمعلوماتك عند استخدامك لخدمات منصة مُصادَق للفوترة الإلكترونية وتطبيق الهواتف الذكية التابع لها.</p>
<h2>1. المعلومات التي نجمعها</h2>
<p>عند استخدامك لخدماتنا، قد نقوم بجمع الأنواع التالية من المعلومات:</p>
<ul>
<li><strong>معلومات الحساب:</strong> الاسم، البريد الإلكتروني، رقم الهاتف، ومعلومات الشركة (الرقم الضريبي، السجل التجاري).</li>
<li><strong>البيانات المالية والفواتير:</strong> صور الفواتير التي تقوم برفعها أو التقاطها، البيانات المستخرجة منها عبر تقنيات الذكاء الاصطناعي، وبيانات الأطراف المتعاملة معك.</li>
<li><strong>معلومات الجهاز والاستخدام:</strong> نوع الجهاز، نظام التشغيل، عنوان الـ IP، وسجلات (Logs) تفاعلك مع المنصة للمساعدة في تحسين الخدمة واكتشاف الأخطاء.</li>
</ul>
<h2>2. كيف نستخدم معلوماتك</h2>
<p>نستخدم البيانات التي نجمعها للأغراض التالية:</p>
<ul>
<li>تقديم خدمات الفوترة الإلكترونية الأساسية ومعالجة الفواتير باستخدام الذكاء الاصطناعي.</li>
<li>ربط الفواتير وإرسالها إلى منظومة جوفوترا (JoFotara) الخاصة بدائرة ضريبة الدخل والمبيعات الأردنية بناءً على طلبك.</li>
<li>تحسين دقة نماذج الذكاء الاصطناعي في استخراج البيانات (دون ربطها بهويتك الشخصية).</li>
<li>إدارة حسابك وتوفير الدعم الفني.</li>
<li>إرسال التحديثات والتنبيهات الأمنية.</li>
</ul>
<h2>3. حماية بياناتك وأمنها</h2>
<p>تُعتبر حماية بياناتك من أهم أولوياتنا. ولضمان ذلك نطبق معايير أمنية صارمة منها:</p>
<ul>
<li>تشفير قواعد البيانات والمستندات الحساسة باستخدام خوارزميات التشفير المتقدمة (مثل AES-256-GCM).</li>
<li>استخدام تقنيات العزل (Multi-Tenancy) لضمان عدم تداخل بيانات الشركات.</li>
<li>تطبيق تقنيات الحماية النشطة (RASP) عبر أداة freeRASP في تطبيق الهواتف الذكية لمنع الاختراق، التعديل على الكود، أو العمليات الخبيثة.</li>
<li>حماية الوصول للتطبيق عبر المصادقة الحيوية (البصمة/الوجه).</li>
</ul>
<h2>4. مشاركة البيانات مع أطراف ثالثة</h2>
<p>نحن <strong>لا نبيع</strong> أو نؤجر بياناتك لأي جهات خارجية. قد نشارك معلوماتك فقط في الحالات التالية:</p>
<ul>
<li><strong>دائرة ضريبة الدخل والمبيعات (جوفوترا):</strong> تُرسل الفواتير التي تقوم باعتمادها حصرياً إلى المنظومة الوطنية وفق المتطلبات القانونية.</li>
<li><strong>مقدمي الخدمات السحابية:</strong> نستخدم خدمات آمنة (مثل Google Cloud أو منصات الـ AI المعتمدة) لمعالجة واستخراج البيانات، تخضع هذه الخدمات لاتفاقيات سرية صارمة.</li>
<li><strong>الامتثال القانوني:</strong> إذا طُلب منا ذلك بموجب مذكرة قانونية رسمية من الجهات المختصة في المملكة الأردنية الهاشمية.</li>
</ul>
<h2>5. الاحتفاظ بالبيانات وحذفها</h2>
<p>نحتفظ ببياناتك طالما كان حسابك نشطاً لتقديم الخدمات المطلوبة. يحق لك طلب حذف حسابك في أي وقت. عند الحذف، سنقوم بمسح كافة الفواتير والصور المرتبطة بحسابك من خوادمنا النشطة خلال 90 يوماً، مع مراعاة البيانات التي قد يفرض القانون الاحتفاظ بها لأغراض ضريبية.</p>
<h2>6. تحديثات سياسة الخصوصية</h2>
<p>قد نقوم بتحديث هذه السياسة من وقت لآخر لمواكبة التغيرات القانونية أو التقنية. سنقوم بإعلامك بأي تغييرات جوهرية عبر البريد الإلكتروني أو من خلال إشعار داخل المنصة.</p>
<h2>7. التواصل معنا</h2>
<p>إذا كانت لديك أي أسئلة أو استفسارات حول سياسة الخصوصية الخاصة بنا، يرجى التواصل معنا عبر البريد الإلكتروني:</p>
<p><a href="mailto:privacy@musadaq.jo" style="color: var(--emerald); font-weight: bold;">privacy@musadaq.jo</a></p>
</div>
<!-- FOOTER -->
<footer>
<div class="container" style="margin-top: 0;">
<p style="margin-bottom: 0.5rem; font-size: 1.1rem; color: var(--emerald); font-weight: 600;">مُصادَق</p>
<p>منصة أتمتة الفواتير الإلكترونية صُنع في الأردن 🇯🇴</p>
<div style="margin-top: 1rem; display: flex; justify-content: center; gap: 1rem;">
<a href="/privacy.php">سياسة الخصوصية</a>
<span></span>
<a href="#">الشروط والأحكام</a>
</div>
<p style="margin-top: 1rem;">© 2026 مُصادَق. جميع الحقوق محفوظة.</p>
</div>
</footer>
</body>
</html>