انتقل إلى المحتوى

Gerege Kiosk

Production · الطبقة 4 — منتج قطاعي · المستودع: gerege-kiosk-mn · geregekiosk.mn

منصّة موحّدة لأكشاك الخدمة الذاتية — قائمة على eID ومعزَّزة بالذكاء الاصطناعي. تربط الكشك القائم في مكان عام بالهوية الإلكترونية، فيحصل المواطن على إفادته ويسدّد رسمه ويطبع مستنده من دون وقوفٍ في طابور ولا لقاءٍ بموظّف. خدمةٌ على مدار الساعة لا تتقيّد بأوقات العمل.

الملكية

تملك المنصّةَ وتُشغّلها شركة Gerege Kiosk ХХК. والشيفرة المصدرية في مستودع خاص، وهي مبنيّة على الأساس المشترك open-gerege-core من Gerege Systems.

صار geregekiosk.mn يقدّم Gerege Nexus

جرى التحقّق في 2026-08-07: يعيد https://geregekiosk.mn/ نشرةً من Gerege Nexus — فعنوان الصفحة «Gerege Nexus» ووصفها هو وصف Nexus. وللنطاق شهادته الصالحة الخاصة، وهو على 38.180.243.183.

ولذلك فإنّ سلوك gerege-kiosk-mn الموصوف في هذه الصفحة قد لا يطابق بعدُ ما يقدّمه النطاق العام. فقابِل النسخة العاملة على الطرفية بتلك النشرة.

الفكرة المِحورية — تطبيق رقيق وأساس سميك

الواجهة الخلفية لـ Kiosk بلغة Go ملفٌّ واحد. فالمصادقة وRBAC وبوابة API ومسار الذكاء الاصطناعي وeID/SSO — كل الإمكانات الأساسية تقع في وحدة github.com/gerege-systems/open-gerege-core؛ ويجتذبها هذا المستودع بإصدارها ويُشغّلها باسمه:

func main() {
    server.ServiceName = "gerege-kiosk"

    app, err := server.NewApp()
    if err != nil { /* … */ }

    // Routes specific to this app are added here:
    //   app.Router().Route("/api/xxx", xxx.Routes(app.Pool()))

    if err := app.Run(); err != nil { /* … */ }
}

وهذا هو حلّ الدَّين التقني الناتج عن مزامنة التفريعات المذكور في صفحة Template Platform: فقد كانت شيفرةُ الأساس تُنسَخ في كل مستودع، ويُنقل كل تحسين يدويًا. أمّا الآن فـ Kiosk مستهلِك مُصدَّر الإصدار لـ open-gerege-core: تنتشر الرقع الأمنية من نقطة واحدة، ويتمّ التحديث بأمرٍ واحد هو go get open-gerege-core@latest.

الطبقة حيث تعيش من يملكها
الخلفية الأساسية (المصادقة، RBAC، الذكاء الاصطناعي، البوابة، الترحيلات) وحدة open-gerege-core Gerege Systems
نقطة التشغيل والعلامة والإعدادات gerege-kiosk-mn/backend Gerege Kiosk ХХК
واجهة BFF وواجهة المستخدم gerege-kiosk-mn/frontend Gerege Kiosk ХХК
النشر ومضيف الحافّة الافتراضي gerege-kiosk-mn/deploy Gerege Kiosk ХХК

البنية

gerege-kiosk-mn/
├── backend/     # Go · thin consumer of open-gerege-core (cmd/api/main.go)
├── frontend/    # Next.js 15 BFF — Node 20, TanStack Query, mn/en/zh/ru
├── ios/         # SwiftUI reference client (talks only through the BFF)
└── deploy/      # compose, edge nginx vhost, internal DB TLS certificate

وتتّبع الخلفية الأساسية معمارية Clean Architecture — ‏handler → usecase → repository → domain، بلا استيراد عكسي وبلا ORM (‏SQL يدوي فوق pgx).

المصادقة — عبر Gerege SSO وحده

في شاشة الدخول زرٌّ واحد فقط: الدخول عبر Gerege SSO. فلا كلمات مرور ولا تسجيل بالبريد أو برمز OTP ولا مسار eID مباشر.

graph LR
    C["مواطن / كشك"] --> W["geregekiosk.mn<br/>Next.js BFF"]
    W --> A["Kiosk API"]
    A --> S["sso.gerege.mn<br/>Gerege SSO"]
    S --> E["eID Mongolia"]
    S -.->|"eID proxy"| A
  • مسار الجهة المعتمِدة لـ OIDC — ‏/api/auth/sso/startsso.gerege.mn/sso/callback. وللهاتف مسارٌ منفصل لعميل عمومي بـ PKCE (native).
  • الجلسة — ‏JWT access + refresh، ورمز التحديث متجدّد؛ وتسجيل الخروج يُبطل رمز التحديث ويضع رمز الوصول في قائمة منع.
  • الرمز لا يصل إلى المتصفّح — بل يبقى في كوكي httpOnly، وكل شيء يمرّ عبر BFF.

لماذا ليست Kiosk جهةً معتمِدة لـ eID بنفسها؟

بمقتضى قاعدة الحدود رقم 2، لا تصل تطبيقات الطبقتين 3–4 إلى eID مباشرةً. فـ Kiosk لا تملك بيانات اعتماد جهة معتمِدة لـ eID — وكل تعامل مع eID يمرّ عبر Gerege SSO. وبذلك تُحصر بيانات الاعتماد في موضع واحد ولا ينقطع أثر التدقيق.

ملف PKI الخاص بـ eID — عبر الوكيل

تُجتذب لوحةُ PKI للمواطن الذي سجّل دخوله عبر وكيل eID في الدخول الموحّد. فتستدعي Kiosk برمز وصول المستخدم، ويجلب الدخولُ الموحّد البياناتَ ببيانات اعتماد eID الخاصة به.

ماذا حيث يظهر
ملخّص موحّد /me/eid/id
الشهادات وحالتها /me/eid/certificates
الأجهزة المرتبطة /me/eid/devices
سجل المصادقة/التوقيع /me/eid/logs
الجهات المرتبطة والمفوَّضون بالتوقيع /me/organizations

أمّا حالة تعطيل الوكيل (خدمة eid-proxy غير مفعّلة في الدخول الموحّد) أو انتهاء صلاحية الرمز، فتتولّاها الواجهة على حدة — ولا تُرمى في صورة خطأ 5xx.

مزوّد OIDC بذاتها

تستطيع Kiosk أن تكون جهةً معتمِدة للدخول الموحّد وفي الوقت نفسه مزوّد هوية. فمتى ضُبط OAUTH_ISSUER ومفتاح الحالة، تفعّل مزوّد OAuth2/OIDC الخاص بها بلغة Go (من دون Ory Hydra):

  • شاشات login · consent · logout تحت /oauth،
  • تسجيل الجهات المعتمِدة في جدول oauth_clients، وتدوير الأسرار،
  • تخطّي الموافقة لعملاء الطرف الأول، وتذكّر الموافقة،
  • ‏discovery وuserinfo وid_token — ويُخزَّن مفتاح التوقيع مشفَّرًا.

وبذلك تستطيع التطبيقات الصغيرة المحيطة بـ Kiosk أن تتيح «Sign in with Gerege Kiosk».

السطح الموجَّه إلى المواطن

القسم ما يفعله
/me/dashboard لوحة شخصية
/me/services · /me/applications كتالوج الخدمات والطلبات وسيرها
/me/references الإفادات
/me/notifications الإشعارات
/me/payments المدفوعات
/me/appointments حجز المواعيد
/me/organizations الجهات والعضويات والصلاحيات
/me/eid/sign التوقيع الإلكتروني على مستند
/me/integrations الاتّصالات مع أطراف ثالثة وGerege Space
/me/ai · /me/translate المساعد الذكي والترجمة الفورية

وعند إنشاء جهةٍ أو البحث عنها يُستعلَم من السجل الحكومي عبر Gerege Verify. وبيانات الجهات محميّة لكل مستخدم بـ RLS في Postgres.

سجل الخدمات الموحّد

المكوّن R1 من Ring System — جواز الخدمة وإدارة الأدلّة:

  • كتالوج الخدمات والإصدارات والنشر/الأرشفة،
  • أحداث الحياة (life events) — تجميع الخدمات بحسب حال المواطن،
  • الأدلّة (evidences) ولوحة مرّة واحدة فقط التي تقيس مدى تطبيق مبدأ عدم إعادة طلب مستندٍ سُلِّم من قبل.

والصلاحيات على مستويين: registry.view (قراءة) وregistry.manage (كتابة).

بوابة API

كتالوج خدمات يُدار من لوحة المشرف: services · routes · consumers · مفاتيح API · policy، ويضاف إليه قياس الطلبات عن بُعد (نظرة عامة + سجلّات).

النطاق الحالي

البوابة حتى الآن طبقةُ إدارة وقياس. أمّا الإنفاذ الفعلي لما يُضبط من route/policy بوصفها وكيلًا عكسيًا حقيقيًا (تحديد المعدّل والحصص على مستوى الـ consumer) فهو مدرَج في الخطّة.

التوقيع الإلكتروني وsign relay

  • PAdES — توقيع ملفات PDF من جهة الخادم عبر واجهة /v3 في eID Mongolia، بشهادة Document-Signer دائمة (وفي الإنتاج fail-closed).
  • Sign relay — بوابةٌ تتيح للجهات المعتمِدة الخارجية التوقيع بواسطة بيانات اعتماد eID الخاصة بالمنصّة. ولا يمرّ هذا المسار عبر BFF الويب، بل يتوجّه من الحافّة إلى الواجهة البرمجية مباشرةً (منفذ loopback). ويُبلَّغ عن النتيجة بـ webhook.

وللفرق بين توقيع المواطن الشخصي بـ PIN2 وتوقيع النظام بشهادة Document-Signer راجع صفحة G-Sign.

المساعد الذكي (Gemini)

مسارٌ قائم على عميل REST بلا SDK:

الإمكانية الوصف
المحادثة رسائل نصّية وصوتية، واستدعاء الدوال
STT كلام ← نص
TTS نص ← كلام (PCM→WAV)
الترجمة ترجمة فورية متدفّقة

موجّه نظام من ثلاث طبقات: ضوابط مثبَّتة في الشيفرة، مع نطاقٍ وتعليماتٍ يضبطها المشرف عبر قاعدة البيانات. وطبقة الضوابط غير قابلة للضبط أبدًا.

وتُرسي أداة search_knowledge الإجابةَ على بيانات حقيقية من قاعدة المعرفة. والبحث دلالي — تضمين Gemini مع تقارب جيب التمام على pgvector، وبالتراجع إلى ILIKE عند الفشل.

وإن تعطّل Gemini مؤقّتًا فلا تصير المحادثةُ خطأ 5xx، بل تُعاد استجابة متدنّية (degraded: true) بلغة المستخدم. ومسارات /ai/* محدودة بنحو 20 طلبًا في الدقيقة لكل عنوان IP.

التكامل والتخزين

  • اتّصالات OAuth مع أطراف ثالثة — ‏Google Drive · Google Meet · Dropbox. وتُخزَّن الرموز مشفَّرةً بـ AES-256-GCM؛ وإن لم تُضبط بيانات الاعتماد ظهرت البطاقة المعنية معطَّلةً بحالة «قريبًا».
  • Gerege Space — تخزين SFTP خاص بالتطبيق، بحصّة لكل مستخدم. ويُتحقَّق من مفتاح مضيف SFTP (وهو إلزامي في الإنتاج، وإلّا فـ fail-closed).

الصلاحيات والإدارة والتدقيق

  • RBAC — أدوار ديناميكية وكتالوج صلاحيات، بنموذج من أربع مراتب (superadmin → admin → manager → user).
  • المشرف الأعلى — حساب منفصل، ومسار تهيئة بمصادقة متعدّدة العوامل (قائمة سماح للدعوات ← Google ← eID ← رمز OTP بالبريد ← TOTP + رموز استرداد). ولأنّه يُخزَّن في جدول خاص، يمكن للشخص الواحد أن يكون مشرف eID ومشرفًا أعلى معًا.
  • سجل التدقيق — مترابط بسلسلة تجزئة، للإضافة فقط؛ يقرؤه المشرف، وله نقطة نهاية للتحقّق من السلامة.
  • الأحداث الأمنية — استقبالها ولوحةٌ لمراقبتها.
  • مظهر الموقع — لون التمييز والخط والكثافة والسمة يضبطها المشرف، مع إمكان تجاوزها لكل مستخدم.

الأمان

الضابط التنفيذ
عزل البيانات RLS في Postgres (‏ENABLE + FORCE)؛ وتتّصل الواجهة البرمجية بدور ليس superuser، ويُتحقَّق عند الإقلاع من أنّه مُنفَّذ
الجلسة كوكي httpOnly، ولا يصل الرمز إلى جافاسكربت العميل أبدًا
CSRF حماية مزدوجة — ترويسة مخصّصة + فحص الأصل (على كل مسارات التعديل في BFF)
الترويسات ‏CSP · HSTS · COOP/COEP/CORP، وقائمة سماح لـ CORS
تحديد المعدّل الدخول نحو 5 طلبات/دقيقة (حدّ الجسم 4 KiB)، والتطبيق 50 طلبًا/ثانية، و/ai/* نحو 20/دقيقة
الاتّصال بقاعدة البيانات في الإنتاج sslmode=verify-full — ‏TLS بسلطة تصديق داخلية
نقاط نهاية الملاحظة في الإنتاج /metrics و/swagger محميّان برمز bearer
الثقة بالوكيل إن لم يُضبط TRUSTED_PROXIES فلا يُوثَق بـ X-Forwarded-For (حمايةً من تضليل تحديد المعدّل والتدقيق)

ولمتطلّبات المنظومة العامة راجع صفحة الأمان.

قابلية الملاحظة

تتبّع OpenTelemetry + مقاييس Prometheus + سجلّات Zap المُهيكَلة. وتظهر الخدمة في القياس عن بُعد باسم gerege-kiosk.

النشر

حزمة Docker Compose: ‏db (‏Postgres 16 + pgvector) · redis · migrate (لمرّة واحدة) · api · web. ولا يبلغ المتصفّح إلّا web؛ أمّا api وdb وredis فتبقى في الشبكة الداخلية ولا تفتح منافذ عامة.

وثلاثة قرارات في النشر تستحقّ الانتباه:

  1. الترحيل خطوة مستقلّة لا جزءٌ من up -d. فقد كان كل تشغيل جديد لـ migrate يُعيد إنشاء api وweb، حتى إنّ إيداعًا لا يمسّ الشيفرة كان يُحدث خطأ 502 لثانية.
  2. إن لم يتغيّر شيء فلا يتحرّك شيء. فبناء Docker غير قابل لإعادة الإنتاج، ومن الشيفرة نفسها يخرج معرّف صورة جديد. ولذلك يُتخطّى النشر كلّه إذا لم يتغيّر HEAD.
  3. خدمات البيانات لا تُبنى مع كل نشرة — فإعادة إنشاء db تقطع كل الاتّصالات النشطة بقاعدة البيانات.

ويملك هذا المستودع مضيفَ edge nginx الافتراضي بنفسه — إذ يُثبَّت مع كل نشرة في conf.d، ويُفحَص بـ nginx -t، ثم يُعاد التحميل؛ وإن سقط الفحص أُعيد الإعدادُ السابق. وهذا النموذج نفسه المتّبع في docs.gerege.mn وDeveloper Portal وTemplate Platform.

اللغات

الواجهة والوثائق بأربع لغات: Монгол · English · 中文 · Русский. ويفرض اختبارٌ اكتمالَ قواميس الواجهة الأمامية — فإن غاب مفتاحٌ في إحدى اللغات سقط التكامل المستمر.

الحالة الراهنة

Production تعمل على geregekiosk.mn. وقد وُرِثت إمكانات المنصّة الأساسية كاملةً؛ ولا تزال المسارات الخاصة بقطاع الأكشاك تُضاف تدريجيًا.

الخطوات التالية: الإنفاذ الفعلي في البوابة، واستجابات المحادثة المتدفّقة (SSE)، وسياسة CSP قائمة على nonce، والنسخ الاحتياطي التلقائي لقاعدة البيانات مع اختبار الاستعادة، وبيئة staging.

صفحات ذات صلة