الرئيسية سجل المعايرة إخلاء المسؤولية التوثيق English
Metric Risk · QuantMarketEngine

مرجع الإعدادات والمفاتيح السرّية

كل إعداد بينقرأ من appsettings.json، أو من المخزن السرّي (التطوير)، أو من متغيّرات البيئة (الإنتاج، بصيغة Section__Key). المفاتيح السرّية ما بتنحط في ملف الإعدادات أبداً.

هاي الصفحة بتعدّد كل قسم إعدادات بيقراه الكود. إذا القسم مش هون، فهو مش مقروء — والعكس متحقَّق منه: الأسماء تحت هي ثوابت SectionName المعلَنة على أصناف الخيارات.

عدد الأقسام
19
المستضيفات
Bot · API · Dashboard · Migrator
المصدر
docs/configuration.md
آخر مراجعة
2026-08-31

على أي بيئة إنت شغّال

اقرأ هاد قبل أي إشي تاني بالصفحة. في سلوكين بيعتمدوا على البيئة، وولا واحد فيهم بيعلن عن حاله.

الأمر dotnet run بيرجع لوضع Production لما المشروع ما يكون فيه ملف تشغيل

ملف Properties/launchSettings.json بكل مشروع هو اللي بيختار البيئة. وبدونه .NET بيختار Production — ووقتها:

  • المخزن السرّي بينقرأ على Development بس في مستضيفَي الـ API واللوحة. على Production بيكون غايب ببساطة: إعداد إنت متأكد إنك خزّنته بيصير مفقود، وبلا أي رسالة خطأ. (مستضيف البوت بينادي AddUserSecrets صراحةً، فبيقراه بأي بيئة.)
  • اللوحة بترفض تقوم على Production بدون DataProtection:KeysDirectory.

اللوحة والـ API بيجوا مع ملف تشغيل بيحدّد ASPNETCORE_ENVIRONMENT=Development، فالتشغيل المحلي بيمشي صح. وعلى الخادم، حطّ كل قيمة عن طريق متغيّرات البيئة ولا تعتمد على المخزن السرّي.

المفاتيح السرّية

في الإنتاج: متغيّرات بيئة فقط

ولا واحد من هدول إله قيمة افتراضية آمنة على بنية تحتية تبع حدا تاني.

Saas__AdminApiKey سرّي host API

بيفعّل واجهة التشغيل (/api/v1/admin والمسارات القديمة api/*). بدونه كل نقطة تشغيل بترد 503. والمقارنة بتتم بزمن ثابت.

AlphaVantage__ApiKey سرّي host all

بيانات السوق الحيّة. بدونه المحرّك بيرجع لمزوّد الـ CSV المرفق — وهو للتطوير فقط، بس بيعني إن المحرّك بيشتغل وبينقاس بلا حساب عند أي جهة.

Telegram__BotToken سرّي host bot

النشر والمراجعة عبر تيليجرام.

ConnectionStrings__Quant host all

مسار قاعدة SQLite. الافتراضي على Docker Data Source=/data/quant.db على وحدة تخزين مشتركة.

Stripe__SecretKey سرّي host API + Dashboard

بدونه الفوترة معطّلة بكل مكان، واللوحة بتحوّل الترقيات لتفعيل يدوي — وبتقول ذلك للمستخدم بدل ما تفشل بصمت.

Stripe__WebhookSecret سرّي host API

مفتاح توقيع POST /api/v1/billing/webhook. النقطة بترد 503 لحد ما ينحط.

Stripe__PriceIds__analyst Stripe__PriceIds__desk host API + Dashboard

معرّفات أسعار Stripe لكل رمز خطة. الخطط المرتبطة فقط هي القابلة للشراء.

Email__SmtpHost / SmtpPort / SmtpUser / SmtpPassword / FromAddress سرّي host Dashboard (+API)

إرسال البريد عبر أي مزوّد. بدون المضيف، الرسائل بتصير أسطر في السجل — يعني مسار استعادة كلمة المرور بيصير ما بيعمل إشي بصمت.

دورة حياة الفوترة

كلها مستضافة عند Stripe. بيانات البطاقة ما بتمرّ على المنصة إطلاقاً.

الدفع يبدأ من /actions/billing/checkout
صفحة دفع مستضافة عند Stripe
checkout.session.completedبتفعّل الخطة المدفوعة وبتلغي صف الخطة المجانية (اشتراك حيّ واحد لكل مستخدم)
customer.subscription.updatedبتعكس الحالة ونهاية الفترة، وبتغطّي past_due
customer.subscription.deletedبتلغي وبترجّع الحساب للخطة المجانية

كل انتقال بينكتب في سجل التدقيق بفاعل billing.

إعداد الـ webhook عند Stripe: النقطة https://<api-host>/api/v1/billing/webhook، والأحداث: التلاتة فوق.

التوسّع والنسخ الاحتياطي

كل المستضيفات
Database:Provider default Sqlite

Sqlite لعقدة واحدة، أو Postgres عبر Npgsql. وPostgres بدّه مجموعة ترحيلات خاصة فيه.

Database:MigrateOnStartup default true

حطّه false على النشر متعدّد العقد، وشغّل الـ Migrator مرة قبلها، عشان العقد ما تتسابق على Migrate().

Redis:ConnectionString default unset

لما ينحط، حصة الـ API وقفل تسجيل الدخول بيستخدموا Redis — مشترك بين العقد — بدل العدّادات داخل العملية. مطلوب للتوسّع الأفقي.

Database:Backup:Enabled default true

نسخ احتياطي مجدوَل ومتحقَّق منه داخل مستضيف البوت. طفّيه بس لو في عملية خارجية بتصوّر وحدة التخزين.

Database:Backup:Directory default backups

المسارات النسبية بتنحلّ جنب قاعدة البيانات. حطّ مساراً مطلقاً على وحدة تخزين منفصلة في الإنتاج — النسخة على نفس القرص بتموت مع القرص.

Database:Backup:RetainCount default 7

عدد النسخ المحفوظة. الأقدم بتنشطب بعد كل تشغيل، مرتّبة حسب الطابع الزمني في اسم الملف.

Database:Backup:IntervalHours default 24

الفاصل بين التشغيلات التلقائية. وفي واحدة بتشتغل دايماً عند إقلاع المستضيف.

الـ Migrator كونسول بيشتغل مرة واحدة (Dockerfile.migrator) — بيطبّق الترحيلات وبيزرع الخطط بغضّ النظر عن الإعداد فوق. هاي خطوة ما قبل النشر لعنقود.

النسخ الاحتياطي خاص بـ SQLite (VACUUM INTO) وما بينسجّل لما يكون المزوّد Postgres؛ هديك النشرة بتاخد نسخها بأدوات الخادم نفسه.

لوحة المشتركين

QuantMarketEngine.Dashboard
Admin:Emails اضبطه أولاً default [] فاضي

الطريقة الوحيدة اللي بيصير فيها حدا مشغّلاً. مصفوفة عناوين بريد؛ المستخدم المسجَّل اللي عنوانه فيها بيوصل صفحات الإدارة، وغيره لأ.

الفاضي معناه ولا حدا. AdminAccess بيفشل مقفولاً، وصفحة الإدارة بتقول إنها غير مضبوطة بدل ما توهم إن الحساب ناقصه صلاحية.

وهو إعداد مش صفّاً في قاعدة البيانات عن قصد: المهاجم اللي بيوصل لقاعدة البيانات من خلال التطبيق ما بيقدر يعطي حاله صفحات المشغّل. بيتشحن فاضي، والمشتري بيحطّ عنوانه هو.

ConnectionStrings__Quant default content-root quant.db

لازم يأشّر على نفس قاعدة البيانات اللي بيستخدمها الـ API والبوت — /data/quant.db على Docker. المستضيفات التلاتة بتُشحن كلها مؤشّرة على ملف البوت: ../QuantMarketEngine.TelegramBot/quant.db من الـ API واللوحة، وquant.db من البوت نفسه.

وإذا غلط، ما بيطلع خطأ. المستضيف بيتعلّق بملف تاني، والواجهة بتبيّن فاضية وهي شغّالة تمام.

DataProtection:KeysDirectory مطلوب في الإنتاج default unset

المستضيف بيرفض يقوم بدونه خارج بيئة التطوير. بيحفظ مفاتيح تشفير الكوكيز عبر إعادات التشغيل — /data/dp-keys على Docker.

وبدونه، ASP.NET Core بيولّد حلقة مفاتيح لكل عملية، فكل إعادة تشغيل بتسجّل خروج كل المشتركين، وما في بالسجلات إشي بيفسّر ليش.

Support:Email default placeholder

بيظهر على صفحتَي الفوترة والدعم. حطّ العنوان الحقيقي قبل الإطلاق.

PdfExport:BrowserPath default auto-detect

المسار الكامل لـ Chrome أو Edge أو Chromium. خلّيه فاضي عشان يدوّر بأماكن التثبيت المعتادة.

PdfExport:Enabled default true

false بتطفّي تصدير الـ PDF حتى لو كان في متصفّح مثبّت.

PdfExport:NoSandbox مطفي افتراضياً default false

بيشغّل المتصفّح بصندوق حماية معطّل. بينلزم لما تكون الحاوية شغّالة كـ root بدون صلاحيات النواة اللي Chrome بحاجتها — هناك ما بيقوم أصلاً.

ومطفي افتراضياً لأن الخيار بيخلّي الميزة تشتغل بكل مكان وبيضعّفها بكل مكان، وهاد قرار المشغّل مش قرارنا. والسجل بيسمّي هاد الإعداد لما تفشل طباعة بشكل بيوحي برفض من صندوق الحماية.

PdfExport:TimeoutSeconds default 30

السقف الزمني لطباعة واحدة قبل ما ينقتل المتصفّح. الطباعة الحقيقية بتاخد حوالي ثانية.

تصدير تقرير PDF. صفحة التقارير بتعرض كل جلسة مؤرشفة كـ PDF منسّق — جداول مع رسم مخروط الاحتمالات — بتطبعها نسخة Chromium مثبّتة بوضع بلا واجهة. وما في إشي بيثبّت هاد المتصفّح عنك: على مستضيف بلا متصفّح، رابط الـ PDF بيخفي حاله، والنقطة بترد 503، وتصديرات العربي والإنجليزي والـ JSON ما بتتأثر. وصور Docker ما فيها متصفّح، فالتصدير مطفي في الحاوية الافتراضية لحد ما ينثبّت واحد.

الـ PDF إنجليزي فقط. العربي في PDF بدّه تخطيطاً ثنائي الاتجاه، والمُصيِّر المستخدَم بهاد المشروع بيعكس الأرقام داخل نص مختلط عربي/لاتيني — طبع 1.16805 على شكل 50861.1. والتقرير العربي لسّه بينسلّم كنص.

نموذج الدخول. بريد وكلمة مرور (UserCredential مع PBKDF2) بيتحوّلوا لكوكي جلسة HttpOnly منزلقة مدّتها 7 أيام. والتسجيل الذاتي بيمنح خطة observer المجانية. ومخمّد لكل عنوان IP: 8 محاولات فاشلة خلال 10 دقائق. ومفاتيح الـ API بتضل هي بيانات اعتماد الآلة؛ اللوحة بتصدرها وبتلغيها، والمفتاح الخام بينعرض مرة وحدة بالضبط.

طبقات التحليل

كل المستضيفات

أربع طبقات من خط التحليل قابلة للضبط، واتنتين منهم بيتشحنوا مطفيين. وهاد قرار مش إهمال، وكل واحدة بتقول ليش. القسمان CrossAsset وEconomicIndicators مش موجودين في أي appsettings.json — بيشتغلوا على القيم الافتراضية بالكود، وهاد بيستاهل تعرفه قبل ما تدوّر على قسم مش موجود.

CrossAsset

مفعّل افتراضياً

مقابل شو بينقاس ارتباط كل رمز مُحلَّل — هاي الطبقة اللي وراها أشرطة الارتباط بالتقرير.

Enabled افتراضي true؛ وfalse بتتخطّى الطبقة كلها.

Map افتراضي []، يعني المجموعة المؤسسية المدمجة لليورو/دولار: مؤشر الدولار، الذهب، وعائد السندات الأمريكية لعشر سنين. والمدخلات بصيغة { BaseSymbol, Symbol, Label }.

والأداة اللي ما بيقدر مزوّد البيانات يخدمها بتنتخطّى وقت التشغيل بدل ما تفشّل التقرير، فإدراج مؤشر أو عائد هون آمن حتى على باقة مجانية للعملات بس.

EconomicIndicators

مفعّل افتراضياً

الخلفية الاقتصادية الأمريكية: التضخّم، سعر الفائدة، سوق العمل.

Enabled true · Timeframe MONTHLY · FreshnessDays 45 · AttemptIntervalDays 1 · Indicators [] للمجموعة المدمجة.

وAttemptIntervalDays هو الإعداد اللي بيحكم التكلفة، مش FreshnessDays. البيانات الأمريكية بتُنشر بتأخير شهر لشهرين، فأحدث قراءة متاحة بتكون عادةً أقدم من أي بوابة نضارة معقولة، والبيانات ما بتقدر تخلّي حالها تبيّن حديثة أبداً. وقبل ما هاد الإعداد يوجد، أربع مؤشرات كانت بتنجلب من جديد في كل تشغيلة وترجع نفس الأرقام.

التكلفة: على الأكثر نداء واحد لكل مؤشر يومياً — يعني نداءات معدودة بالشهر.

EconomicCalendar

مطفي بالكود · مفعّل بالمشحون

قائمة يدوية بالإصدارات عالية الأثر القادمة، بتُستخدم للتحذير إن القراءة واقعة داخل نافذة تعتيم. والافتراضي بالكود مطفي لأن هاي قائمة لازم حدا يضل يكتبها: ما ورها تغذية آلية، والتقويم القديم أسوأ من ولا تقويم لأنه بيحذّر من أيام غلط.

وملف appsettings.json تبع البوت بيشغّلها، وحامل 14 إصداراً لبنوك مركزية وبيانات أمريكية لحد 17 ديسمبر 2026. ولما تخلص القائمة الطبقة بتسكت بدل ما تغلط — بس هاي مهمة صيانة إلها تاريخ، والمشتري لازم يعرف أي تاريخ.

BlackoutWindowHours 24 · MinimumImpact High · ومدخلات Events بصيغة { Name, ScheduledAt (UTC), Impact, Currencies[] }، والعملات الفاضية معناها عالمي.

FundamentalAnalysis

مطفي — ومسيَّج حتى لو انفتح

Enabled false · وDataFilePath فاضي. أشّر المسار على ملف JSON معبّى يدوياً بالإصدارات والفوائد والمواقف عشان تغذّي الطبقة ببيانات اختبار.

وتشغيلها ما بيحطّ أرقاماً مُدخَلة يدوياً قدّام العميل. المزوّد بيبلّغ IsLiveSource=false ومُخرِج الإخراج بيرمي القيم. الطبقة موجودة عشان يتطوّر عليها، والسياج بالكود عشان مساهم مستقبلي ما يقدر يفتحها للإنتاج بقلب إعداد.

مستضيف البوت

QuantMarketEngine.TelegramBot
Telegram:BotToken default empty

من @BotFather. وبدونه البوت بيضل ساكن — لا مستقبِل ولا مجدوِل. وباقي المستضيف بيضل شغّال.

Telegram:ReviewerChatId default 0

معرّف المحادثة الخاصة للمراجع البشري. هاد هو صندوق بوابة الموافقة.

Telegram:PublicChannelId default empty

معرّف القناة أو @username اللي بينُشر عليها التقارير المعتمَدة.

Telegram:ActiveSymbols default []

الرموز اللي بيحلّلها العامل المجدوَل كل دورة. وفاضية بالكود عن قصد: رابط الإعدادات في .NET بيضيف على المصفوفة الافتراضية غير الفاضية، فافتراضي ["EURUSD"] زائد نفس القيمة بالإعدادات بينربط لـ ["EURUSD","EURUSD"] — وبيولّد كل تقرير مرتين. فالقيمة بتيجي من الإعدادات وبس.

Telegram:Timeframe default 4H

الإطار الزمني اللي بيطلبه العامل المجدوَل.

Telegram:ScheduleHours default 4

كل قدّيش بيشتغل العامل المجدوَل.

ReviewerChatId وPublicChannelId حالياً في appsettings.json تبع البوت للتسهيل. وهم خاصّون بالنشرة: انقلهم لمتغيّرات بيئة بأي مكان مشترك.

العمّال الخلفيون

مستضيف البوت

الحلقتين إلهم قيم افتراضية آمنة وبيشتغلوا بلا أي ضبط.

EventTrigger:Enabled true بالكود · false بالمشحون

المراقب المدفوع بالأحداث. بيشتغل أكتر من الدورة المجدولة، بس بيحجز تقريراً بس لما يكتشف تغيّراً هيكلياً أو انقلاب نظام سائد.

وملف appsettings.json تبع البوت بيطفّيه. هاد هو سطر «المشغّل المدفوع بالأحداث بيتشحن معطّلاً» اللي بمواد البيع — وهو قيمة إعداد، مش كود ناقص.

EventTrigger:IntervalMinutes default 60

الدقائق بين تمريرات الكشف. محدودة بدقيقة كحد أدنى.

EventTrigger:StartupDelaySeconds default 45

بيخلّي ترحيلات الإقلاع وتحميل البيانات تستقر أول.

OutcomeEvaluation:Enabled مفعّل default true

حلقة التقييم الذاتي — الاختبار الرجعي الخلفي لـ VaR اللي بيُنتج سجلّ المعايرة. وتطفيتها بتوقّف الادعاء المركزي للمنتَج عن كونه مكتسَباً.

OutcomeEvaluation:IntervalMinutes default 60

محدودة بدقيقة كحد أدنى.

OutcomeEvaluation:StartupDelaySeconds default 30

بيخلّي ترحيلات الإقلاع وتحميل البيانات تستقر أول.

OutcomeEvaluation:BatchSize default 200

أقصى عدد تحليلات بينتقيّم في التمريرة الوحدة.

الموقع الثابت

بيصيّر التقارير المعتمَدة لصفحات HTML مسطّحة لـ GitHub أو Cloudflare أو Netlify Pages.

WebPublisher:OutputDirectory default empty

الفاضي بيعطّل النشر على الويب. حطّه وبتنكتب التقارير المعتمَدة هناك.

WebPublisher:SiteTitle default Quant Market Monitor

بيُستخدم على الصفحات العربية، وحامل الشعار العربي.

WebPublisher:SiteTitleEnglish default Metric Risk — Market Watch

محفوظ لحاله بدل ما ينشتق من اللي فوقه: طباعة الشعار العربي على صفحة إنجليزية كانت آخر إشي ضل بلا ترجمة لما الموقع صار بلغتين.

القالب محتوى تعليمي فقط — حامل إخلاء المسؤولية المحايد، وما بيحمل أبداً دعوة اشتراك أو سعر.

مستضيف الـ API

QuantMarketEngine.API
Security:RequestsPerMinutePerIp default 120

حدّ محيطي بنافذة ثابتة لكل عنوان IP؛ وبعده 429. ونقاط الصحة مستثناة.

Security:AllowedOrigins default []

أصول CORS. والفاضي معناه لا CORS إطلاقاً.

AnalysisCache:TtlSeconds default 300

عمر ذاكرة التحليل المؤقتة داخل العملية، لكل رمز وإطار زمني. و0 بتعطّلها.

Serilog:* default console, Information

قسم إعدادات Serilog القياسي.

Engine:SupportedSymbols default EURUSD / 4H

كتالوج الرموز. مشترك بين كل المستضيفات، فالرمز اللي بينضاف هون بتعرفه المنصة كلها.

نموذج الصلاحيات

تلات مستويات، بينتفحّصوا عند النقطة نفسها مش بينفترضوا من المسار.

عام

/api/v1/plans · /api/symbols · /health/live · /health/ready · /openapi/v1.json

مشترك

بمخطط X-Api-Key/api/v1/intelligence/* و/api/v1/alerts (محسوبة على الحصة)، و/api/v1/account (خارج الحصة)

مشغّل

بمخطط X-Admin-Key/api/v1/admin/* وكل المسارات القديمة: api/analysis، api/history، api/reports/*، api/review، api/calibration. وهاي أدوات تشغيل داخلية؛ واجهة العميل هي /api/v1 فقط، والمسارات القديمة مش جزء من العقد العام.

كل إجراء ذي صلاحية بيكتب صفّاً في AuditLogEntries. وكل نداء مشترك محسوب على الحصة بيكتب أو بيزيد صفّاً في ApiUsageRecords — وهو مصدر الحقيقة للفوترة وللوحة معاً.

التشغيل والمراقبة

GET /health/live

حياة العملية، بلا أي اعتماديات.

GET /health/ready

بيشمل ذهاباً وإياباً لقاعدة البيانات.

CorrelationId

السجلات مهيكلة عبر Serilog، وكل طلب حامل معرّف ربط، مع احترام X-Correlation-Id الوارد.

الترحيلات بتنطبّق تلقائياً عند إقلاع الـ API، على افتراض نسخة واحدة — راجع هاد قبل التوسّع الأفقي.

النسخ الاحتياطي لـ SQLite بيصوّر وحدة /data المركّبة، أو بيستخدم VACUUM INTO، بجدول. والانتقال لـ PostgreSQL مُدار هو المسار بعد العقدة الوحدة.

والتكامل المستمر بيبني وبيختبر، وبيفشل على أي حزمة NuGet معروفة الثغرة.