Motoshub · System Architecture
معماری کامل سیستم موتوشاب
این سند معماری محصول، معماری نرمافزار، بکاند، فرانتاند و اسکیمای کامل داده را بهصورت جداگانه و دقیق شرح میدهد. مبنای همهی توضیحات، مطالعهی کامل سورس و اندازهگیری زنده روی استک در حال اجراست.
۱. معماری محصول
موتوشاب در حال گذار از یک وبسایت اکسوالِ یکپارچه به یک معماری Gateway + Strangler-Fig است: یک درگاه واحد جلوی چند بکاند میایستد و بهتدریج قابلیتها از هستهی قدیمی PHP به بکاند جدید Django منتقل میشوند، بدون قطع سرویس.
مصرفکنندهها
اپ موبایلiOS / Android
فرانت جدیدmotonextfront.shub.ir
سایت زندهی فعلیmotonext.shub.ir
↓
درگاه (Gateway)
api.shub.irنقطهی ورود واحد برای موبایل و کل اپ آینده؛ توکن را pass-through و بین بکاندها مسیردهی میکند برنامهریزی
↓
بکاندها
api1.shub.irموتوشاب فعلی (PHP/Oxwall + REST API v1). قابلیتهای امروز اینجاست. آمادهی استقرار
api2.shub.irبکاند Django (بازنویسی تدریجی). endpointها یکییکی از api1 به اینجا منتقل میشوند. در حال توسعه
↓
داده و مستندات
MariaDB مشترکپایگاهدادهی واحد؛ هر دو لایهی PHP روی همان جدولها
docs.shub.irمستندات فنی و API زنده
وضعیت فعلی سابدامینها
| سابدامین | نقش | وضعیت |
| motonext.shub.ir | سایت زندهی فعلی (شاخهی motonext) | بالا |
| motonextfront.shub.ir | فرانت جدید موتوشاب | بالا |
| docs.shub.ir | مستندات (این سند) | بالا، گواهی معتبر |
| api.shub.ir | Gateway — موبایل و کل اپ آینده | نیازمند DNS |
| api1.shub.ir | موتوشاب فعلی (کار REST API v1) | نیازمند DNS |
| api2.shub.ir | بکاند Django | نیازمند DNS |
چرا این معماری؟ api1 (موتوشاب فعلی) باید یک قرارداد تمیز، پایدار و ماژولار باشد تا (۱) Gateway بتواند جلویش بایستد و (۲) Django بتواند بهتدریج هر endpoint را جداگانه تحویل بگیرد. به همین دلیل REST API v1 بهصورت ماژولهای مستقل ساخته شده است.
۲. معماری نرمافزار (api1 — موتوشاب فعلی)
موتوشاب یک fork از Oxwall است که یک لایهی REST مدرن به نام Bridge رویش سوار شده. دو لایهی دسترسی به داده روی یک پایگاهداده همزیستی دارند.
لایهی HTTP
nginxreverse proxy، FastCGI به PHP-FPM
Bridge Routerrouting مبتنی بر attribute، middleware، dispatcher
↓
لایهی REST API v1 (جدید) — تمپلیت هر فیچر
Controllerattribute route + OpenAPI
FormRequestاعتبارسنجی و sanitize
Resourceسریالسازی خروجی
Policyمجوز per-action
Serviceمنطق کسبوکار؛ BOL موجود را صدا میزند
Repositoryکوئری Eloquent
Model / DTOEloquent Model + DTO
QueriesFilter / Search / Sort
↓
لایهی BOL قدیمی Oxwall
*_BOL_*Serviceمنطق شیپشدهی هر پلاگین (بازنویسی نشده)
OW_BaseDao + OW_Exampleدسترسی دادهی قدیمی (SQL دستی)
OW_EventManagerرویدادها، کش، اعلانها
↓
داده و احراز هویت
MariaDB 10.5۴۰۷ جدول، پیشوند ow_
JWT (HS256)پل بین توکن و OW::getUser() در هر درخواست
RBAC اکسوالگروه/اکشن/نقش
نکتهی مهم — دو ORM روی یک دیتابیس: لایهی جدید از
Eloquent (کامپوننت ORM لاراول، نه خود لاراول) و لایهی قدیمی از
OW_BaseDao استفاده میکند؛ هر دو به همان جدولها مینویسند. نوشتن با Eloquent، رویداد/کش لایهی قدیمی را دور میزند. جزئیات در
راهنمای عملیات.
اعداد کلیدی لایهی API
| مورد | مقدار |
| عملیات REST | ۲۹۳ (GET ۱۱۵ / POST ۸۵ / DELETE ۵۶ / PATCH ۳۷) |
| مسیرها | ۱۷۸ |
| مدلهای Eloquent | ۷۴ مدل در ۲۶ پلاگین |
| پلاگینهای فعال | ۵۱ (هرکدام init.php در هر درخواست) |
| تستهای Pest | ۴۴ فایل، ۱۲۰ assertion سبز |
۳. بکاند
api1 — PHP / Oxwall (فعلی)
- پشته: PHP 8.4-FPM، MariaDB 10.5، nginx. OPcache فعال. Composer با Smarty + Twig + اجزای Illuminate (Eloquent) + Symfony + Guzzle + Shieldon (WAF) + swagger-php + firebase/php-jwt.
- الگوی مهاجرت: هر فیچر یک ماژول کامل (Controller+Request+Resource+Service+Policy+Repository+Model+DTO+Queries). منطق کسبوکار بازنویسی نشده — هر Service همان BOL موجود را صدا میزند.
- مجوزها: هر پلاگین اکشنهای REST خودش را در install.php و update.php ثبت و به نقشها grant میکند (خودکفا، بدون دستور مرکزی).
api2 — Django (در حال توسعه)
- بازنویسی تدریجی؛ endpointها یکییکی از api1 به api2 منتقل میشوند و Gateway مسیر را عوض میکند.
- برای همزیستی، هر دو بکاند باید هویت مشترک بفهمند (بخش احراز هویت).
احراز هویت میان PHP و Django
API فعلی با JWT (HS256) کار میکند؛ توکن با sha256(OW_PASSWORD_PEPPER) امضا و claims دارد: { iat, exp, sub: userId }.
- راه کمریسک (بدون تغییر کد): راز مشترک — همان pepper را به Django بدهید؛ Django با PyJWT همان توکن HS256 را verify کند؛ Gateway توکن را pass-through کند.
sub همان userId جدول ow_base_user است.
- مسیر بلندمدت: RS256 (کلید نامتقارن، تک صادرکننده) یا یک Identity Provider مرکزی (Keycloak) با verify کلید عمومی در همهی سرویسها.
۴. فرانتاند
- motonextfront.shub.ir — فرانت جدید که REST API v1 را مصرف میکند (دیگر از رندر سمتسرور اکسوال استفاده نمیکند).
- قرارداد مصرف: ورود از
POST /v1/auth/login، ارسال Authorization: Bearer <token> در هر درخواست، مدیریت ۴۰۱/۴۰۳/۴۲۲/۴۰۴، تولید کلاینت از openapi.json. جزئیات کامل در راهنمای فرانتاند.
- motonext.shub.ir — سایت زندهی فعلی (رندر سمتسرور اکسوال) که تا کاملشدن فرانت جدید پابرجاست.
۵. اسکیمای داده (MariaDB — ۴۰۷ جدول، پیشوند ow_)
اسکیما بر پایهی هستهی Oxwall است؛ هر پلاگین جدولهای خودش را دارد. مهمترین دامنهها:
| دامنه | جداول کلیدی | توضیح |
| هویت و کاربر | ow_base_user, ow_base_user_profile, ow_base_question_data | حساب کاربری، پروفایل، مقادیر پرسشهای پروفایل (نام نمایشی از اینجا) |
| مجوز (RBAC) | ow_base_authorization_role, _action, _group, _role_permission | گروه/اکشن/نقش و grant؛ مبنای Policyهای API |
| پلاگین و ویجت | ow_base_plugin, ow_base_component, ow_base_component_place | پلاگینهای نصب/فعال، ویجتهای صفحهی اصلی (index/dashboard) |
| تازهها (فید) | ow_newsfeed_action, _activity, _action_feed, _status | پستها؛ visibility bitmask و privacy کنترل دیدهشدن برای مهمان |
| رسانه | ow_photo, ow_photo_album, ow_video_clip | عکس/آلبوم/ویدیو |
| محتوا | ow_blogs_post, ow_iisnews_entry, ow_forum_topic, ow_forum_post | بلاگ، خبر، فروم |
| اجتماع | ow_groups_group, ow_event_item, ow_friends_friendship, ow_mailbox_conversation | گروه، رویداد، دوستی، پیامرسان |
| سازمانی/پژوهشی | ow_iisgrant_*, ow_iiscfp_*, ow_iisticketing_*, ow_iisjcse_* | گرنت، فراخوان، تیکتینگ، نشریه |
نکتهی طراحی داده: اسکیمای اکسوال ستونهای created_at/updated_at استاندارد لاراول را ندارد؛ به همین دلیل مدلهای Eloquent با $timestamps=false تنظیم شدهاند و فیلدهای زمانی (مثل addDatetime) دستی مدیریت میشوند. تاریخها بهصورت timestamp عددی ذخیره و در خروجی API به ISO-8601 + جلالی تبدیل میشوند.
مدل رابطهای نمونه (رسانه)
ow_base_user (id) ────< ow_photo_album (userId)
│
└────< ow_photo (albumId)
│
└── ow_photo_album_cover (photoId)
۶. معماری استقرار (این سند و docs.shub.ir)
- موتوشاب مستقل است: استک اپ بهصورت Docker جداگانه اجرا میشود (app=PHP-FPM، db=MariaDB، web=nginx) و هیچ ارتباطی با زیرساختهای دیگر ندارد.
- docs.shub.ir در یک namespace کاملاً جدا و برچسبخوردهی
motoshub-docs سرو میشود، ایزوله از سایر سرویسهای سرور؛ گواهی معتبر Let's Encrypt با تمدید خودکار.
- مصرف منابع: app بیبار ~۵۲MB، db ~۱۶۶MB، هر worker PHP ~۵۵MB. سیستم memory-bound است. مشخصات سرور برای هر مشتری و پایش زنده در راهنمای عملیات.