سند تحلیل معماری — نسخه ۱.۰

پلتفرم اتوماسیون تجاری چند‌مستأجری
Universal Workflow Automation Platform

تحلیل جامع معماری، طراحی سیستم، مدل تجاری و نقشه‌راه پیاده‌سازی — قابل استفاده برای هر کسب‌وکاری (SaaS ابری + نصب روی سرور مشتری + ارائه به‌صورت REST API)

بک‌اند: Laravel 11 (PHP 8.3+) پنل: Nuxt 4 + Vue 3 دیتابیس: PostgreSQL / MySQL صف: Redis + Horizon هدف: ۳ → ۱۰۰ مشتری در ۲۴ ماه

۱ تعریف محصول

این محصول یک پلتفرم اتوماسیون جریان‌کار (Workflow Automation Platform) است؛ مشابه n8n، Make.com و Zapier، اما با تفاوت کلیدی: هسته عمومی و افقی که با نصب «ماژول» به هر کسب‌وکاری تخصصی می‌شود. مشتری CRM می‌خواهد → ماژول CRM نصب می‌کند، فروشگاهی است → ماژول Ecommerce، کلینیک است → ماژول نوبت‌دهی و پیام‌رسان.

منطق پایه: Trigger → Condition → Action

  ┌──────────┐    ┌───────────┐    ┌────────┐    ┌───────────┐    ┌────────┐
  │ Trigger  │───►│ Condition │───►│ Action │───►│ Condition │───►│ Action │
  │ (محرک)   │    │  (شرط)    │    │ (عمل)  │    │  (شرط)    │    │ (عمل)  │
  └──────────┘    └───────────┘    └────────┘    └───────────┘    └────────┘
      │
      ├─ Webhook        (دریافت داده از بیرون)
      ├─ Schedule/Cron  (زمان‌بندی)
      ├─ Event          (رویداد داخلی سیستم)
      └─ Manual         (اجرای دستی)

۱.۱ سه حالت ارائه به مشتری

۱) SaaS ابری

مشتری روی زیرساخت ما ثبت‌نام می‌کند، پلن می‌خرد، همان لحظه ماژول‌ها فعال می‌شوند.

درآمد ماهانهOnboarding فوری

۲) Self-Hosted

همان کدبیس روی دامنه و سرور مشتری نصب می‌شود (Docker). لایسنس سالانه + اتصال heartbeat.

لایسنس سالانهداده در سرور مشتری

۳) Web Service / API

موتور اتوماسیون به‌صورت API در اختیار مشتری قرار می‌گیرد تا داخل نرم‌افزار خودش مصرف کند.

White-LabelEmbedded
مزیت کلیدی معماری: هر سه حالت از یک کدبیس واحد ساخته می‌شوند. لایه Platform/ (بیلینگ و چند‌مستأجری) در حالت Self-Hosted غیرفعال می‌شود. یعنی نگهداری یک محصول، فروش در سه بازار.

۲ معماری کلان

┌──────────────────────────────────────────────────────────────────────┐
│                         PLATFORM LAYER                                │
├──────────────────────────────────────────────────────────────────────┤
│   ┌─────────────┐   ┌──────────────────┐   ┌──────────────────┐      │
│   │  SaaS Mode  │   │  Self-Hosted Mode│   │   API Gateway    │      │
│   │  (Cloud)    │   │  (On-Premise)    │   │   (REST / Token) │      │
│   └──────┬──────┘   └────────┬─────────┘   └────────┬─────────┘      │
│          └───────────────────┼──────────────────────┘                │
│                              ▼                                       │
│                 ┌────────────────────────────┐                       │
│                 │     CORE ENGINE (Laravel)  │                       │
│                 │ ┌────────────────────────┐ │                       │
│                 │ │  Workflow Engine       │ │                       │
│                 │ │  Execution Engine      │ │                       │
│                 │ │  Trigger Dispatcher    │ │                       │
│                 │ │  Action Resolver       │ │                       │
│                 │ │  Module Registry       │ │                       │
│                 │ │  License Manager       │ │                       │
│                 │ └────────────────────────┘ │                       │
│                 └──────────────┬─────────────┘                       │
│         ┌──────────────────────┼──────────────────────┐              │
│         ▼                      ▼                      ▼              │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────────┐       │
│  │ PostgreSQL / │    │  Redis /     │    │  Queue Workers   │       │
│  │   MySQL      │    │  RabbitMQ    │    │ (Laravel Horizon)│       │
│  └──────────────┘    └──────────────┘    └──────────────────┘       │
├──────────────────────────────────────────────────────────────────────┤
│                    ADMIN PANEL  (Nuxt 4 + Vue 3)                      │
└──────────────────────────────────────────────────────────────────────┘

۲.۱ جریان یک اجرا (Execution Flow)

  [Webhook / Cron / Event]
            │
            ▼
  ┌────────────────────┐
  │  Trigger Controller│  ← احراز هویت، امضای HMAC، Rate Limit
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │ Check Plan & Quota │  ← آیا پلن مشتری اجازه این اجرا را می‌دهد؟
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │  Push to Queue     │  ← ExecuteWorkflowJob (Redis)
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │  Graph Resolver    │  ← Topological Sort روی DAG
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │  Node Executor(s)  │  ← اجرای موازی شاخه‌های مستقل
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │ Execution Logger   │  ← لاگ هر گره + ورودی/خروجی
  └─────────┬──────────┘
            ▼
  ┌────────────────────┐
  │ Usage Meter        │  ← ثبت مصرف برای بیلینگ
  └────────────────────┘

۳ طراحی ماژولار

سیستم به سه لایه مستقل تقسیم می‌شود: هسته (Core)، ماژول‌ها (Modules) و پلتفرم (Platform). هر لایه قابل تست، قابل نسخه‌بندی و قابل فروش جداگانه است.

۳.۱ هسته اتوماسیون (Core) — رایگان و ثابت

┌─────────────────────────────────────────────────────────┐
│                     CORE MODULES                          │
├─────────────────────────────────────────────────────────┤
│  automation-core                                          │
│  ├── Workflow          (تعریف جریان)                      │
│  ├── Node              (گره: trigger/action/condition)     │
│  ├── Edge              (اتصال بین گره‌ها)                  │
│  ├── Execution         (نمونه اجرا)                       │
│  ├── ExecutionContext  (زمینه اجرا و متغیرها)              │
│  └── VariableResolver  (حل {{ path.to.value }})            │
├─────────────────────────────────────────────────────────┤
│  automation-engine                                        │
│  ├── WorkflowExecutor  ← ارکستراتور اصلی                  │
│  ├── NodeDispatcher    ← انتخاب و اجرای گره               │
│  ├── ErrorHandler      ← retry / fallback / circuit break │
│  ├── ParallelExecutor  ← اجرای همزمان شاخه‌ها              │
│  └── ExecutionLogger   ← ثبت لاگ ساخت‌یافته                │
├─────────────────────────────────────────────────────────┤
│  automation-trigger                                       │
│  ├── WebhookTrigger    ├── ScheduleTrigger (Cron)         │
│  ├── EventTrigger      └── ManualTrigger                  │
├─────────────────────────────────────────────────────────┤
│  automation-action                                        │
│  ├── HttpAction        ├── EmailAction                    │
│  ├── DatabaseAction    ├── WebhookAction                  │
│  └── CustomAction (قابل توسعه توسط ماژول‌ها)              │
└─────────────────────────────────────────────────────────┘

۳.۲ ماژول‌های قابل خرید و نصب (Marketplace)

اسلاگ ماژولکاربردتاریخ انتشار پیشنهادی
module-crmلید، مخاطب، قیف فروش، پیگیری خودکارفاز ۱ (MVP)
module-messagingپیامک، ایمیل، تلگرام، واتس‌اپفاز ۱
module-ecommerceسفارش، موجودی، سبد رهاشدهفاز ۲
module-paymentدرگاه پرداخت، اشتراک، فاکتورفاز ۲
module-approvalگردش کار تأیید چندمرحله‌ایفاز ۲
module-data-transformتبدیل/نقشه‌برداری JSON، فرمول، تاریخفاز ۱
module-notificationاطلاع‌رسانی چندکاناله + قالب‌سازفاز ۲
module-schedulerزمان‌بندی پیشرفته، تقویم کاری، تعطیلاتفاز ۲
module-aiگره‌های شرط/عمل مبتنی بر LLM (طبقه‌بندی، خلاصه‌سازی)فاز ۴
module-analyticsگزارش، داشبورد، KPI اتوماسیون‌هافاز ۳

۳.۳ قرارداد (Contract) هر ماژول

هر ماژول یک Laravel Package است که ۴ مورد را register می‌کند:

// app/Modules/Crm/ModuleServiceProvider.php
class CrmServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        // ۱) گره‌های قابل استفاده در Workflow
        NodeRegistry::register([
            'crm.contact.create'  => Actions\CreateContact::class,
            'crm.deal.move_stage' => Actions\MoveDealStage::class,
            'crm.lead.capture'    => Triggers\LeadCaptured::class,
        ]);

        // ۲) شرط‌های اختصاصی
        ConditionRegistry::register([
            'crm.contact.exists' => Conditions\ContactExists::class,
        ]);

        // ۳) متریک مصرف (برای بیلینگ پلن‌محور)
        UsageMeter::define('crm.contacts_created');

        // ۴) منوی پنل و مجوزها
        AdminMenu::add('crm', 'CRM', capability: 'module.crm');
    }
}
قاعده طلایی: هسته هیچ وابستگی‌ای به ماژول‌ها ندارد. ارتباط یک‌طرفه است: ماژول → هسته. این باعث می‌شود افزودن ماژول جدید حتی نیاز به تغییر هسته نداشته باشد.

۴ مدل تجاری‌سازی و پلن‌ها

با هدف ۳ مشتری اولیه → ۱۰۰ مشتری در ۲۴ ماه، ساختار قیمت‌گذاری باید سه لایه داشته باشد: اشتراک پلنی، فروش ماژول، و لایسنس Self-Hosted.

۴.۱ پلن‌های اشتراکی (SaaS)

Free / Trial

۱۰۰ اجرا/ماه
  • ۱ جریان فعال
  • فقط هسته (Core)
  • تست ۱۴ روزه ماژول‌ها
  • پشتیبانی انجمنی

Starter

۵۰۰ اجرا/ماه
  • ۱۰ جریان فعال
  • ۳ ماژول
  • Webhook اختصاصی
  • لاگ ۳۰ روزه

Business

۵۰۰۰ اجرا/ماه
  • ۱۰۰ جریان فعال
  • ۱۰ ماژول
  • ۵ کاربر + نقش‌ها
  • لاگ ۹۰ روزه
  • API Access

Enterprise / Self-Hosted

∞ اجرا
  • بدون محدودیت جریان
  • تمام ماژول‌ها + کد منبع
  • نصب روی سرور مشتری
  • White-Label
  • SLA و پشتیبانی اختصاصی

۴.۲ جریان‌های درآمدی (Revenue Streams)

#جریان درآمدینوعحاشیه سوداولویت
۱اشتراک ماهانه/سالانه SaaSتکرارشوندهبالا (~۸۵٪)فاز ۲
۲فروش/اجاره ماژول‌هاتکرارشونده + یک‌باربالافاز ۲
۳لایسنس Self-Hosted (سالانه)تکرارشوندهبسیار بالافاز ۳
۴White-Label / OEMقرارداد سالانهبسیار بالافاز ۳
۵اجرای پیاده‌سازی و آموزشیک‌بارمتوسطفاز ۱
۶پشتیبانی Premium / SLAتکرارشوندهبالافاز ۳
۷درآمد Marketplace (کمیسیون ماژول شخص ثالث)تکرارشوندهبالافاز ۴

۴.۳ منطق کنترل دسترسی (Entitlement)

  Tenant
    │
    ├── Subscription ──► Plan
    │                      │
    │                      ├── plan_limits      (max_workflows, runs/month, retention)
    │                      └── plan_modules ──┐
    │                                          ▼
    ├── ModuleAccess ──────────────► آیا این ماژول برای tenant فعال است؟
    │                                 │
    │                                 ├── از پلن (خودکار)
    │                                 ├── از خرید تکی (add-on)
    │                                 └── از trial (۱۴ روزه)
    │
    └── UsageCounter (Redis, ریست ماهانه)
           │
           ├── runs_this_month  → اگر ≥ سقف پلن ⇒ صف متوقف + اعلان ارتقا
           └── overage          → محاسبه هزینه مازاد (اختیاری)

  ┌──────────────────────────────────────────────────┐
  │  PlanGate Middleware:                            │
  │   1) tenant دارد؟  2) اشتراک فعال است؟           │
  │   3) ماژول مجاز است؟  4) سقف مصرف رد نشده؟      │
  └──────────────────────────────────────────────────┘
مرگ پنهان SaaS: اگر از ابتدا Usage Metering نسازید، بعداً نمی‌توانید پلن‌بندی و صورتحساب دقیق داشته باشید. این بخش باید در فاز ۱ ساخته شود، حتی اگر در فاز ۱ صورتحساب نگیرید.

۵ مدل داده (Data Model)

۵.۱ رابطه‌ی موجودیت‌ها

┌──────────────┐       ┌──────────────┐       ┌──────────────┐
│   tenants    │──1:N─►│  workspaces  │──1:N─►│  workflows   │
└──────┬───────┘       └──────────────┘       └──────┬───────┘
       │                                             │
       │                          ┌──────────────────┼─────────────────┐
       │                          ▼                  ▼                 ▼
       │                   ┌─────────────┐   ┌─────────────┐   ┌──────────────┐
       │                   │workflow_nodes│  │    edges    │   │  executions  │
       │                   └──────┬──────┘   └─────────────┘   └──────┬───────┘
       │                          │                                  │
       │                   ┌──────▼──────┐                    ┌──────▼───────┐
       │                   │  node_types │                    │execution_logs│
       │                   │ (registry)  │                    │ (per node)   │
       │                   └─────────────┘                    └──────────────┘
       │
       ├──1:N─► subscriptions ──N:1──► plans ──1:N──► plan_modules
       │
       ├──1:N─► module_access ──N:1──► modules
       │
       ├──1:N─► api_keys
       ├──1:N─► webhooks      (endpoint دریافتی)
       ├──1:N─► schedules     (cron definitions)
       ├──1:N─► usage_counters (ریست ماهانه)
       ├──1:N─► secrets       (اعتبارنامه‌های رمزنگاری‌شده)
       └──1:N─► licenses      (فقط حالت Self-Hosted)

۵.۲ جدول‌های اصلی و وظیفه هرکدام

جدولوظیفهنکات کلیدی
tenantsهر شرکت/مشتری = یک tenantدارای slug برای ساب‌دامین و custom_domain
workspacesفضای کاری داخل tenant (تفکیک دپارتمان)پیش‌فرض: یک workspace «Main»
workflowsتعریف جریانستون graph JSON یا نرمال‌سازی‌شده در nodes/edges
workflow_nodesگره‌های جریانtype (اسلاگ از رجیستری) + config JSON + position
workflow_edgesاتصال گره‌هاfrom_node, to_node, branch (true/false/default)
executionsهر بار اجرای یک جریانstatus, trigger_type, duration_ms, payload JSON
execution_logsلاگ در سطح گرهinput/output (masked), error, attempt
node_typesرجیستری انواع گرهاز ماژول‌ها پر می‌شود؛ پنل از این جدول فرم داینامیک می‌سازد
modulesکاتالوگ ماژول‌هاslug, version, price, is_core
module_accessکدام tenant به کدام ماژول دسترسی داردمنبع: plan / add-on / trial + expires_at
plansپلن‌هاlimits JSON (max_workflows, runs_per_month, retention_days)
subscriptionsاشتراک فعال tenantstatus: trialing/active/past_due/canceled
licensesلایسنس نسخه Self-Hostedkey, domain, fingerprint, expires_at
api_keysکلیدهای APIفقط hash ذخیره شود + prefix برای شناسایی
secretsتوکن‌ها و رمزهای سرویس‌های بیرونیرمزنگاری با Laravel Crypt و کلید مخصوص tenant
usage_countersشمارنده مصرفادغام Redis (سرعت) + جدول (ماندگاری و صورتحساب)

۵.۳ نمونه Migration هسته

// database/migrations/..._create_workflows_table.php
Schema::create('workflows', function (Blueprint $t) {
    $t->id();
    $t->foreignId('tenant_id')->constrained()->cascadeOnDelete();
    $t->foreignId('workspace_id')->constrained()->cascadeOnDelete();
    $t->string('name');
    $t->string('slug');
    $t->text('description')->nullable();
    $t->string('status')->default('draft'); // draft|active|paused|archived
    $t->string('trigger_type');            // webhook|schedule|event|manual
    $t->json('trigger_config')->nullable();
    $t->json('settings')->nullable();       // timeout, retry, concurrency
    $t->unsignedInteger('version')->default(1);
    $t->timestamp('last_run_at')->nullable();
    $t->timestamps();
    $t->unique(['tenant_id', 'slug']);
    $t->index(['tenant_id', 'status']);
});
// نکته: برای مقیاس ۱۰۰ مشتری، ایندکس ترکیبی tenant_id لازم است

۶ ساختار پروژه Laravel

ساختار پیشنهادی بر پایه Domain-Driven Design سبک است: سه فضای نام اصلی (Core، Modules، Platform) که مرزهای مسئولیت را شفاف نگه می‌دارند.

app/
├── Core/                          ← موتور اتوماسیون (مستقل از کسب‌وکار)
│   ├── Workflow/
│   │   ├── Models/Workflow.php
│   │   ├── WorkflowManager.php         (سرویس اصلی CRUD + نسخه‌بندی)
│   │   ├── WorkflowBuilder.php         (DSL ساخت جریان با کد)
│   │   └── WorkflowValidator.php       (اعتبارسنجی DAG، حلقه‌ی بی‌نهایت)
│   ├── Engine/
│   │   ├── Engine.php                  (ارکستراتور)
│   │   ├── GraphResolver.php           (Topological Sort)
│   │   ├── NodeExecutor.php            (اجرای یک گره)
│   │   ├── ContextManager.php          (مسیر داده بین گره‌ها)
│   │   ├── ParallelExecutor.php
│   │   └── ErrorHandler.php            (retry/fallback/circuit-breaker)
│   ├── Trigger/
│   │   ├── Contracts/TriggerContract.php
│   │   ├── WebhookTrigger.php
│   │   ├── ScheduleTrigger.php
│   │   ├── EventTrigger.php
│   │   └── TriggerDispatcher.php
│   └── Action/
│       ├── Contracts/ActionContract.php
│       ├── NodeRegistry.php            ← رجیستری مرکزی
│       ├── HttpAction.php
│       ├── EmailAction.php
│       └── DatabaseAction.php
│
├── Modules/                       ← ماژول‌های تجاری (قابل خرید/نصب)
│   ├── Crm/
│   │   ├── Actions/  Triggers/  Conditions/  Migrations/
│   │   ├── Http/Controllers/
│   │   └── CrmServiceProvider.php
│   ├── Messaging/
│   ├── Ecommerce/
│   └── ...
│
├── Platform/                      ← لایه تجاری (در Self-Hosted غیرفعال)
│   ├── Billing/
│   │   ├── SubscriptionManager.php
│   │   ├── PlanResolver.php            (پلن فعال tenant)
│   │   └── UsageMeter.php              (شمارش مصرف)
│   ├── Licensing/
│   │   ├── LicenseManager.php
│   │   └── LicenseClient.php           (اتصال heartbeat به سرور ما)
│   ├── Tenancy/
│   │   ├── TenantManager.php
│   │   ├── TenantScope.php             (Global Scope)
│   │   └── TenantResolver.php          (ساب‌دامین/هدر/کلید)
│   └── Marketplace/
│       ├── ModuleRegistry.php
│       └── ModuleInstaller.php
│
├── Http/
│   ├── Controllers/Api/V1/        ← REST API برای مشتریان
│   ├── Controllers/Api/Admin/     ← API پنل مدیریت پلتفرم
│   └── Middleware/
│       ├── ResolveTenant.php
│       ├── EnsurePlanFeature.php       (PlanGate)
│       ├── EnsureModuleAccess.php
│       ├── EnforceQuota.php
│       └── VerifyLicense.php           (فقط Self-Hosted)
│
└── Jobs/
    ├── ExecuteWorkflowJob.php
    ├── ExecuteNodeJob.php
    ├── DispatchScheduledWorkflowsJob.php
    └── ReportUsageJob.php

۶.۱ نسخه‌بندی API و قرارداد پاسخ

// مسیرها: routes/api_v1.php
Route::prefix('v1')->middleware([
    'auth:sanctum', ResolveTenant::class,
    EnsurePlanFeature::class, EnforceQuota::class,
])->group(function () {
    Route::apiResource('workflows', WorkflowController::class);
    Route::post('workflows/{workflow}/execute', [WorkflowController::class, 'execute']);
    Route::apiResource('executions', ExecutionController::class)->only(['index', 'show']);
    Route::get('nodes/types', [NodeTypeController::class, 'index']); // رجیستری گره‌ها
    Route::apiResource('modules', ModuleController::class)->only(['index', 'show']);
    Route::post('modules/{slug}/install', [ModuleController::class, 'install']);
});

// Webhook عمومی (بدون Sanctum، با امضای HMAC)
Route::post('v1/hooks/{token}', WebhookReceiverController::class)
     ->middleware(['throttle:webhooks', VerifyWebhookSignature::class]);
اصل مهم: پنل Nuxt هیچ‌گاه مستقیم به دیتابیس وصل نمی‌شود. تمام تعامل از طریق همان REST API عمومی انجام می‌شود؛ یعنی پنل اولین مصرف‌کننده API است و API مشتریان بیرونی زیرمجموعه‌ی همان قرارداد.

۷ موتور Workflow (قلب سیستم)

۷.۱ ساختار JSON یک جریان

{
  "name": "Auto Welcome New Customer",
  "status": "active",
  "trigger": {
    "type": "webhook",
    "config": {
      "method": "POST",
      "mapping": { "email": "$.email", "name": "$.full_name" }
    }
  },
  "nodes": [
    { "id": "n1", "type": "action.http_request", "config": {
        "url": "{{ secrets.crm_url }}/contacts",
        "method": "POST",
        "body": { "email": "{{ trigger.email }}" } } },

    { "id": "n2", "type": "condition.if", "config": {
        "expression": "{{ n1.data.plan }} == 'premium'" } },

    { "id": "n3", "type": "action.send_email", "config": {
        "to": "{{ trigger.email }}", "template": "premium_welcome" } },

    { "id": "n4", "type": "action.send_email", "config": {
        "to": "{{ trigger.email }}", "template": "basic_welcome" } }
  ],
  "edges": [
    { "from": "trigger", "to": "n1" },
    { "from": "n1", "to": "n2" },
    { "from": "n2", "to": "n3", "branch": "true"  },
    { "from": "n2", "to": "n4", "branch": "false" }
  ]
}

۷.۲ قرارداد اجرای یک گره (Node Contract)

interface NodeContract
{
    public static function slug(): string;          // 'action.http_request'
    public static function schema(): array;           // فرم داینامیک پنل
    public static function outputSchema(): array;     // برای auto-complete متغیرها
    public function execute(NodeContext $ctx): NodeResult;
    public function validate(array $config): void;        // پیش از ذخیره
    public function retryPolicy(): RetryPolicy;
}

۷.۳ الگوریتم‌های کلیدی موتور

┌───────────────────────────────────────────────────────────────┐
│                  EXECUTION ALGORITHM                           │
├───────────────────────────────────────────────────────────────┤
│  1) اعتبارسنجی گراف                                            │
│     ├── آیا DAG است؟ (تشخیص حلقه با DFS)                       │
│     ├── آیا همه گره‌ها به هم متصل‌اند؟ (unreachable nodes)      │
│     └── آیا انواع گره در رجیستری فعال tenant وجود دارد؟        │
│                                                                │
│  2) Topological Sort  →  تعیین ترتیب اجرا                      │
│                                                                │
│  3) اجرای گره‌به‌گره                                            │
│     ├── Context مشترک: { trigger, nodes.{id}.data, env }       │
│     ├── VariableResolver: حل {{ path.to.value }}               │
│     ├── شاخه‌های مستقل ⇒ همزمان (Queue::batch)                 │
│     ├── Wait/Delay ⇒ Delayed Job                              │
│     └── شرط شرطی ⇒ انتخاب یال branch                          │
│                                                                │
│  4) مدیریت خطا در هر گره                                        │
│     ├── Retry با backoff نمایی  (1s, 5s, 30s)                  │
│     ├── Error Output Branch  (مسیر جایگزین)                    │
│     ├── Circuit Breaker  (قطع پس از N خطای متوالی)             │
│     └── Continue On Fail  (ادامه بدون توقف کل جریان)           │
│                                                                │
│  5) ثبت نتیجه                                                  │
│     ├── execution_logs هر گره (input/output masked)            │
│     ├── به‌روزرسانی usage_counter                              │
│     └── رویداد WebSocket برای نمایش زنده در پنل                │
└───────────────────────────────────────────────────────────────┘

۷.۴ نمونه کد اجرای جریان

class ExecuteWorkflowJob implements ShouldQueue
{
    public function handle(Engine $engine): void
    {
        $execution = Execution::create([
            'workflow_id' => $this->workflow->id,
            'status'      => 'running',
            'payload'     => $this->payload,
        ]);

        $engine->run(
            workflow:  $this->workflow,
            context:   ContextManager::from($this->payload, $this->workflow->settings),
            execution: $execution,
        );
    }

    public function failed(Throwable $e): void
    {
        // اطلاع‌رسانی به tenant + ثبت در monitoring
    }
}
کلید عملکرد صحیح: هر اجرا باید در یک Context ایزوله باشد و هرگز state را بین اجراها به اشتراک نگذارد. تنها منبع حقیقت، رکورد executions است.

۸ چند‌مستأجری (Multi-Tenancy)

۸.۱ انتخاب استراتژی

استراتژیمزیتعیبمناسب برای
Single DB + tenant_id انتخاب‌شده ساده، ارزان، مهاجرت آسان، یک کدبیس نیاز به انضباط در اسکوپ کوئری‌ها ۳ تا ۱۰۰ مشتری ✅
DB-per-Tenant ایزوله‌سازی کامل، بکاپ مستقل هزینه عملیاتی بالا، مهاجرت پیچیده +۵۰۰ مشتری یا نیازهای امنیتی سخت
Schema-per-Tenant تعادل بین دو مورد قبل پیچیدگی PostgreSQL، ابزار کمتر Enterprise خاص
توصیه: با هدف ۱۰۰ مشتری، Single Database + tenant_id + Global Scope بهترین گزینه است. معماری را طوری بنویسید که مسیر مهاجرت به DB-per-Tenant باز بماند (همه دسترسی‌ها از Repository/Service، نه کوئری مستقیم در Controller).

۸.۲ زنجیره تشخیص tenant

┌────────────────────────────────────────────────────────────┐
│              TENANT RESOLUTION CHAIN                        │
├────────────────────────────────────────────────────────────┤
│  ۱. Subdomain    →  acme.automation.ir   →  tenant #1      │
│  ۲. Custom Domain→  automation.acme.ir   →  tenant #1      │
│  ۳. API Key      →  ak_live_xxxx (prefix lookup)           │
│  ۴. JWT Claim    →  tid: 1                                 │
│  ۵. Header       →  X-Tenant-Id: 1   (فقط برای Super Admin)│
│                                                            │
│  نتیجه → app(TenantManager::class)->set($tenant)           │
│         → TenantScope روی همه مدل‌ها اعمال می‌شود           │
└────────────────────────────────────────────────────────────┘

۸.۳ پیاده‌سازی Global Scope

trait BelongsToTenant
{
    protected static function bootBelongsToTenant(): void
    {
        // ۱) فیلتر خودکار همه کوئری‌ها
        static::addGlobalScope('tenant', function (Builder $q) {
            if ($id = app(TenantManager::class)->id()) {
                $q->where($q->getModel()->getTable().'.tenant_id', $id);
            }
        });

        // ۲) مقداردهی خودکار هنگام ساخت رکورد
        static::creating(function ($model) {
            if (empty($model->tenant_id)) {
                $model->tenant_id = app(TenantManager::class)->id();
            }
        });
    }
}
خطر امنیتی جدی: در حالت tenant_id مشترک، یک باگ در اسکوپ = نشت داده بین مشتریان. برای همین باید در فاز ۱ یک تست خودکار نوشت که برای هر مدل بررسی کند آیا رکورد tenant دیگر از طریق API قابل خواندن است؟ (Data Leakage Test).

۹ معماری Self-Hosted و سیستم لایسنس

این بخش تعیین‌کننده‌ی مدل درآمدی پرسود محصول است. چالش اصلی: مشتری روی سرور خودش نصب می‌کند، پس چطور مطمئن شویم لایسنس معتبر است و از محدوده خارج نشده؟

۹.۱ معماری ارتباط با سرور لایسنس

┌───────────────────────────────────────────────────────────────┐
│                  SELF-HOSTED ARCHITECTURE                      │
├───────────────────────────────────────────────────────────────┤
│                                                                │
│   سرور مشتری                          سرور ما (License Server) │
│  ┌────────────────┐                  ┌───────────────────────┐ │
│  │  Laravel App   │   HTTPS POST     │  License API          │ │
│  │ (همان کدبیس)   │ ───────────────► │  ├─ validate(key)     │ │
│  │                │ ◄─────────────── │  ├─ bind(domain,fp)   │ │
│  │ LicenseMiddleware  Signed JWT     │  ├─ heartbeat()       │ │
│  │  ▼ cache 24h   │                  │  └─ usage report      │ │
│  │                │   POST /usage    │                       │ │
│  │ UsageReporter  │ ───────────────► │  Metering + Billing   │ │
│  └────────────────┘                  └───────────────────────┘ │
│                                                                │
│  حالت آفلاین:  Grace Period ۷ روزه (لایسنس در cache)           │
│  محافظت:       امضای دیجیتال کد + تشخیص دستکاری فایل‌ها        │
│  توزیع:        docker-compose + اسکریپت نصب یک‌خطی              │
└───────────────────────────────────────────────────────────────┘

۹.۲ چرخه حیات لایسنس

مرحلهاتفاقپاسخ سیستم در صورت خطا
۱. صدورپس از پرداخت، کلید LIC-XXXX-XXXX تولید و به مشتری ارسال می‌شود—
۲. فعال‌سازیمشتری کلید را در پنل وارد می‌کند؛ کلید به domain + fingerprint قفل می‌شودخطا: «لایسنس روی دامنه دیگری فعال است»
۳. صدور JWTسرور ما JWT امضاشده با کلید خصوصی برمی‌گرداند (اعتبار ۲۴ ساعت)—
۴. heartbeat روزانههر ۲۴ ساعت تمدید خودکار + ارسال آمار مصرفتا ۷ روز: هشدار / پس از آن: حالت محدود
۵. انقضاپس از پایان دوره، حالت محدود: فقط خواندن داده و توقف اجراهای جدیدبنر اعلان تمدید در پنل
۶. لغو/انتقالمدیر می‌تواند قفل دامنه را آزاد کنداجازه فعال‌سازی روی دامنه جدید

۹.۳ کد اعتبارسنجی لایسنس

class LicenseMiddleware
{
    public function handle($request, Closure $next)
    {
        if (config('app.mode') !== 'self_hosted') {
            return $next($request);   // در حالت SaaS بررسی لازم نیست
        }

        $license = Cache::remember('license.state', now()->addDay(), function () {
            return app(LicenseClient::class)->verify();
        });

        if (! $license->isValid() && $license->expiredMoreThan(7)) {
            return response()->json([
                'error'   => 'license_invalid',
                'message' => 'لایسنس منقضی شده است. برای تمدید با پشتیبانی تماس بگیرید.',
                'renew_url' => config('license.renew_url'),
            ], 402);
        }

        return $next($request);
    }
}
تعادل طلایی: محافظت باید منصفانه باشد. مشتری سازمانی که پول داده، اگر اینترنت قطع شد نباید سیستمش بخوابد. Grace Period ۷ روزه + حالت «فقط توقف اجراهای جدید» (نه توقف کامل) تعادل درست را ایجاد می‌کند.

۱۰ طراحی RESTful API

قرارداد اصلی: پاسخ‌ها همیشه ساختار ثابت داشته باشند، خطاها معنادار و نسخه‌بندی از روز اول موجود باشد.

۱۰.۱ نقاط پایانی (Endpoints)

متدمسیرتوضیحمحدودیت پلن
GET/api/v1/workflowsلیست جریان‌ها—
POST/api/v1/workflowsساخت جریانmax_workflows
GET/api/v1/workflows/{id}جزئیات + گراف کامل—
PUT/api/v1/workflows/{id}ویرایش جریان—
DELETE/api/v1/workflows/{id}حذف—
POST/api/v1/workflows/{id}/executeاجرای دستیruns_per_month
POST/api/v1/workflows/{id}/activateفعال‌سازی—
POST/api/v1/workflows/{id}/duplicateکپی جریان (قالب)max_workflows
GET/api/v1/workflows/{id}/executionsتاریخچه اجراretention_days
GET/api/v1/executions/{id}جزئیات اجرا—
GET/api/v1/executions/{id}/logsلاگ سطح گره—
POST/api/v1/executions/{id}/retryاجرای مجددruns_per_month
GET/api/v1/nodes/typesرجیستری گره‌های مجاز tenantفیلتر بر اساس ماژول
GET/api/v1/modulesکاتالوگ ماژول‌ها—
POST/api/v1/modules/{slug}/installنصب ماژولmodules_limit
DELETE/api/v1/modules/{slug}حذف ماژول
GET/api/v1/secretsمدیریت اعتبارنامه‌هاsecrets_limit
POST/api/v1/hooks/{token}دریافت وب‌هوک (عمومی)rate/plan
GET/api/v1/usageمصرف ماه جاری + سقف—
GET/api/v1/plansپلن‌های قابل خرید—
POST/api/v1/subscription/checkoutشروع فرآیند پرداخت—
POST/api/v1/licenses/activateفعال‌سازی لایسنس (Self-Hosted)—

۱۰.۲ قرارداد ثابت پاسخ

// موفق
{
  "data": { "id": "wf_01H...", "name": "...", "status": "active" },
  "meta": { "request_id": "req_...", "tenant": "acme" }
}

// خطا (همیشه یک ساختار)
{
  "error": {
    "code": "quota_exceeded",
    "message": "سقف اجرای ماهانه پلن شما تکمیل شده است.",
    "details": { "limit": 500, "used": 500, "resets_at": "2026-10-01T00:00:00Z" },
    "upgrade_url": "https://panel.example.com/billing"
  }
}

۱۰.۳ امنیت API

احراز هویت

  • Sanctum برای کاربران پنل
  • API Key برای سیستم‌های بیرونی (با prefix قابل شناسایی)
  • Scope-based: هر کلید فقط دسترسی تعریف‌شده

محدودیت و پایداری

  • Rate limit سطری: per-tenant / per-key / per-endpoint
  • Idempotency-Key برای جلوگیری از اجرای تکراری
  • Versioned API: /v1 → /v2 بدون شکستن مشتریان قدیمی

۱۱ پنل مدیریت (Nuxt 4 + Vue 3)

۱۱.۱ ساختار پروژه پنل

panel/                                (Nuxt 4)
├── app/
│   ├── pages/
│   │   ├── index.vue                  (داشبورد: مصرف، اجراها، خطاها)
│   │   ├── workflows/
│   │   │   ├── index.vue              (لیست جریان‌ها)
│   │   │   ├── [id].vue               (★ Builder بصری)
│   │   │   └── [id]/executions.vue    (تاریخچه اجرا)
│   │   ├── executions/
│   │   │   ├── index.vue
│   │   │   └── [id].vue               (timeline اجرای گره‌ها)
│   │   ├── marketplace/index.vue      (کاتالوگ + خرید ماژول)
│   │   ├── secrets/index.vue          (مدیریت اعتبارنامه‌ها)
│   │   ├── api-keys/index.vue
│   │   ├── billing/
│   │   │   ├── plans.vue
│   │   │   └── invoices.vue
│   │   ├── settings/                  (کاربران، نقش‌ها، دامنه)
│   │   └── admin/                     (★ فقط Super Admin پلتفرم)
│   │       ├── tenants.vue            (مدیریت مشتریان)
│   │       ├── licenses.vue
│   │       ├── modules.vue            (انتشار ماژول)
│   │       └── revenue.vue            (MRR, Churn, Usage)
│   ├── components/
│   │   ├── builder/                   ← ★ بخش حیاتی پروژه
│   │   │   ├── FlowCanvas.vue         (Vue Flow + کانواس)
│   │   │   ├── NodePalette.vue        (لیست گره‌ها، جست‌وجو)
│   │   │   ├── NodeConfigPanel.vue    (فرم داینامیک از schema)
│   │   │   ├── VariablePicker.vue     (انتخاب {{ }} با autocomplete)
│   │   │   ├── TestRunPanel.vue       (اجرای آزمایشی + نمایش نتیجه)
│   │   │   └── TriggerConfig.vue
│   │   └── ui/                        (دکمه، جدول، مودال، Toast)
│   ├── composables/
│   │   ├── useApi.ts                  (لایه fetch + retry + خطا)
│   │   ├── useWorkflow.ts
│   │   ├── useNodeRegistry.ts
│   │   ├── useUsage.ts
│   │   └── useRealtime.ts             (Laravel Echo / WebSocket)
│   ├── stores/
│   │   ├── auth.ts                    (Pinia)
│   │   ├── tenant.ts
│   │   ├── workflowBuilder.ts         (state کانواس)
│   │   └── notifications.ts
│   └── middleware/
│       ├── auth.ts
│       └── planGuard.ts               (قفل UI بر اساس پلن)
│
└── nuxt.config.ts

۱۱.۲ فهرست صفحه‌ها و مسئولیت هرکدام

صفحهکاربرامکانات کلیدی
داشبوردمشتریمصرف ماه، نرخ موفقیت اجراها، خطاهای اخیر، مصرف به تفکیک ماژول
Workflow BuilderمشتریDrag&Drop، اتصال گره‌ها، فرم داینامیک، اجرای آزمایشی، پیکربندی شرط‌ها
تاریخچه اجرامشتریفیلتر بر اساس وضعیت، timeline گره‌به‌گره، مشاهده ورودی/خروجی هر گره، retry
Marketplaceمشتریمرور ماژول‌ها، پیش‌نمایش گره‌های هر ماژول، نصب/خرید، Trial ۱۴ روزه
اعتبارنامه‌هامشتریذخیره امن توکن سرویس‌های بیرونی + تست اتصال
کلیدهای APIمشتریساخت/لغو کلید، انتخاب Scope، مشاهده آخرین استفاده
صورتحسابمشتریپلن فعلی، ارتقا/تغییر، فاکتورها، افزودن ماژول (add-on)
مدیریت مشتریانSuper Adminساخت tenant، تعلیق، تغییر پلن دستی، ورود به پنل مشتری (impersonate)
لایسنس‌هاSuper Adminصدور کلید، قفل/آزادسازی دامنه، مشاهده heartbeat
درآمد و متریکSuper AdminMRR، ARR، Churn، ماژول‌های پرفروش، مصرف کل

۱۱.۳ کتابخانه‌های پیشنهادی

@vue-flow/core (کانواس گراف) @vue-flow/background / controls / minimap Pinia (state) @nuxt/ui (کامپوننت‌ها) vee-validate + zod (فرم داینامیک) @vueuse/core Laravel Echo + Reverb (نمایش زنده اجرا) Monaco Editor (ویرایش JSON/Expression)
نکته مهم فنی: فرم پیکربندی هر گره باید از schema سرور ساخته شود (نه هاردکد در فرانت). با این کار، افزودن ماژول جدید در بک‌اند بدون هیچ تغییر در فرانت در پنل ظاهر می‌شود. این تنها راه مقیاس‌پذیری واقعی است.

۱۲ نقشه‌راه توسعه

با هدف ۳ مشتری در ۶ ماه اول و ۱۰۰ مشتری در ۲۴ ماه، اولویت‌بندی بر پایه «اول درآمد، بعد مقیاس» است.

فاز ۱ — MVP قابل فروش ۱ تا ۲ ماه  |  هدف: اولین مشتری پرداخت‌کننده
  • Scaffold پروژه: Laravel 11 + Nuxt 4 + PostgreSQL + Redis + Horizon
  • هسته Workflow: مدل داده + موتور اجرای متوالی (بدون موازی در ابتدا)
  • ۵ نوع گره پایه: webhook trigger, schedule trigger, http request, if condition, send email
  • Variable Resolver ساده ({{ trigger.x }} با پشتیبانی نقطه‌گذاری)
  • REST API اصلی: CRUD جریان + اجرا + تاریخچه
  • Workflow Builder بصری با Vue Flow (Drag&Drop + فرم پیکربندی)
  • احراز هویت Sanctum + یک tenant ساده (تک‌مشتری، آماده چند‌مستأجری)
  • Usage Metering از روز اول (شمارش اجراها، حتی بدون صورتحساب)
  • لاگ اجرا: سطح گره با ورودی/خروجی (masked)
قابل فروشبازخورد مشتری واقعی
فاز ۲ — پلتفرم و پلن‌بندی ۳ تا ۶ ماه  |  هدف: ۱۰ مشتری
  • Multi-Tenancy کامل: TenantResolver + Global Scope + Data Leakage Tests
  • سیستم پلن و اشتراک: plans, subscriptions, PlanGate Middleware
  • Module Registry + نصب/فعال‌سازی ماژول + gating بر اساس پلن
  • Marketplace داخلی پنل (مرور، نصب، Trial)
  • گره‌های پیشرفته: parallel branching, loop, delay/wait, data transform, error branch
  • Retry + Circuit Breaker + Continue-on-fail
  • پنل Super Admin: مدیریت مشتریان، مصرف، تعلیق
  • ۲ ماژول تجاری اول: module-crm و module-messaging
  • نمایش زنده اجرا با WebSocket (Laravel Reverb)
درآمد تکرارشوندهمقیاس‌پذیری
فاز ۳ — تجاری‌سازی و Self-Hosted ۶ تا ۱۲ ماه  |  هدف: ۳۰ مشتری + اولین مشتری Enterprise
  • درگاه پرداخت + صورتحساب خودکار + فاکتور
  • بسته Self-Hosted: Docker Compose + اسکریپت نصب + مستندات نصب فارسی
  • سرور لایسنس: صدور، قفل دامنه، heartbeat، Grace Period
  • White-Label: لوگو، رنگ، دامنه و ایمیل اختصاصی مشتری
  • مستندات API عمومی (OpenAPI/Swagger) + نمونه‌کد چندزبانه
  • مدیریت Secrets رمزنگاری‌شده + تست اتصال سرویس‌ها
  • Marketplace ماژول‌های شخص ثالث (فرآیند انتشار و بررسی)
  • قالب‌های آماده جریان (Template Gallery) برای صنایع مختلف
حاشیه سود بالابازار سازمانی
فاز ۴ — مقیاس و تمایز ۱۲ تا ۲۴ ماه  |  هدف: ۱۰۰ مشتری
  • گره‌های AI (طبقه‌بندی، استخراج داده، خلاصه‌سازی، پاسخ خودکار)
  • داشبورد تحلیلی اتوماسیون: نرخ موفقیت، زمان صرفه‌جویی‌شده، ROI
  • بهینه‌سازی کارایی: کش، صف اختصاصی per-tenant، Sharding در صورت نیاز
  • Concurrency Control: جلوگیری از اجرای همزمان بیش از حد per workflow
  • Sub-workflow / Reusable Blocks (توابع قابل استفاده مجدد)
  • Version Control جریان‌ها + Rollback نسخه
  • Sandbox اجرا برای مشتریان Enterprise (ایزوله‌سازی قوی‌تر)
  • پشتیبانی چند-منطقه‌ای (Multi-Region) در صورت نیاز
تمایز رقابتیآماده +۵۰۰ مشتری
معیار عبور از هر فاز: فقط زمانی به فاز بعد بروید که در فاز فعلی حداقل یک مشتری پرداخت‌کننده واقعی داشته باشید و سه جریان واقعی روی سیستم اجرا شده باشد. این کار از ساخت قابلیت‌های بدون تقاضا جلوگیری می‌کند.

۱۳ نکات کلیدی فنی

موضوعراه‌حل انتخابیدلیل
اجرای جریانLaravel Queue + Horizon + Job Chainingمقیاس‌پذیر، قابل مانیتور، آشنای Laravel
دریافت وب‌هوکEndpoint عمومی + امضای HMAC + Rate Limitامنیت و جلوگیری از سوءاستفاده
ارزیابی شرط‌هاsymfony/expression-language در Sandbox محدودقدرتمند، امن‌تر از eval، قابل محدودسازی
حل متغیرهاموتور قالب سفارشی {{ path.to.value }}سادگی برای کاربر غیرفنی + کنترل کامل
پیمایش گرافTopological Sort + Visitor Patternتشخیص حلقه، اجرای موازی، قابل تست
چند‌مستأجریSingle DB + tenant_id + Global Scopeسادگی عملیاتی برای ۱۰۰ مشتری
اعتبارسنجی لایسنسJWT امضاشده + heartbeat روزانه + Grace ۷ روزتعادل بین محافظت و رضایت مشتری
نصب ماژولLaravel Package Discovery + Service Providerبدون تغییر هسته، قابل نسخه‌بندی
محدودیت نرخRedis + Token Bucket per-tenantمحافظت از پلتفرم در برابر مشتری پرمصرف
ایزوله‌سازی اجراContext مستقل per execution + عدم state مشترکجلوگیری از نشت داده بین اجراها
SecretsLaravel Crypt + کلید مجزا per tenantعدم ذخیره متن خام اعتبارنامه‌ها
مانیتور زندهLaravel Reverb (WebSocket)Self-Hosted friendly، بدون وابستگی به سرویس خارجی
صیانت داده اجراMasking مقادیر حساس + پاکسازی دوره‌ای per retentionکاهش ریسک امنیتی و هزینه ذخیره‌سازی
پایداری اجرای طولانیTimeout per node + Kill Switch جریانجلوگیری از اشغال بی‌پایان worker
Idempotencyهدر Idempotency-Key + ذخیره در Redisجلوگیری از اجرای تکراری وب‌هوک

۱۳.۱ چالش‌های پیش‌بینی‌شده و راهکار

۱) انفجار ترکیبی گره‌ها

هر ماژول گره‌های جدید اضافه می‌کند و پیکربندی پیچیده می‌شود.

راهکار: رجیستری متمرکز node_types با schema استاندارد + دسته‌بندی و جست‌وجو در پالت پنل.

۲) دیباگ جریان‌های پیچیده

مشتری نمی‌فهمد کجا خطا خورده است.

راهکار: Timeline اجرای گره‌به‌گره + نمایش ورودی/خروجی واقعی + «اجرای گام‌به‌گام» در Builder + Test Payload ذخیره‌شده.

۳) نسخه‌بندی و تغییرات مخرب

ویرایش یک جریان فعال ممکن است اجراها را بشکند.

راهکار: جریان «پیش‌نویس» جدا از «منتشرشده» + شماره نسخه + امکان بازگشت.

۴) تفاوت SaaS و Self-Hosted

خطر جدا شدن کدبیس و دوباره‌کاری.

راهکار: یک ریپو، پرچم app.mode، تمام کدهای بیلینگ در Platform/ که در حالت Self-Hosted بارگذاری نمی‌شود.

۱۴ تصمیمات معماری

تصمیم ۱ — یک کدبیس یا دو ریپازیتوری؟

انتخاب‌شده: MONOREPO
├── packages/
│   ├── core/         (موتور اتوماسیون — قابل استفاده در همه حالت‌ها)
│   ├── modules/      (ماژول‌های تجاری)
│   └── platform/     (بیلینگ، چند‌مستأجری، لایسنس)
├── apps/
│   ├── api/          (Laravel)
│   └── panel/        (Nuxt)
└── docker/           (بسته Self-Hosted)

مزیت: یک کدبیس ⇒ SaaS و Self-Hosted هر دو از یک منبع
عیب:  نیاز به انضباط در جداسازی لایه‌ها (تست‌های مرزی)

تصمیم ۲ — محل ذخیره تعریف جریان

  • ذخیره نرمال‌سازی‌شده در workflow_nodes و workflow_edges ← منبع حقیقت
  • ساختار graph JSON فقط به‌عنوان کش/خروجی برای پنل و API
  • دلیل: امکان کوئری، گزارش‌گیری و اعتبارسنجی سمت سرور

تصمیم ۳ — حالت اجرا: Sync یا Async؟

حالتمناسب برایپاسخ API
Async پیش‌فرضهمه جریان‌ها، مخصوصاً چندگره‌ای و طولانی202 Accepted + execution_id
Sync (اختیاری)جریان‌های سبک که مشتری منتظر پاسخ است200 OK + داده خروجی (timeout سخت ۵ ثانیه)
Hybridمشتری با ?mode=wait&timeout=10 تعیین می‌کندتکمیل در زمان مشخص ⇒ 200، وگرنه 202

تصمیم ۴ — زبان Expression

الف) قالب ساده

{{ trigger.email }}

ساده، امن، برای کاربر غیرفنی. لایه پیش‌فرض

ب) Expression Language

trigger.amount > 1000 and trigger.plan == "vip"

برای شرط‌های پیچیده، در Sandbox. لایه پیشرفته

ج) کد کامل (JS/PHP)

منعطف ولی پرخطر. فقط Enterprise با sandbox ایزوله

تصمیم ۵ — توزیع نسخه Self-Hosted

Docker Compose (انتخاب‌شده — نصب یک‌خطی) ZIP + Installer Wizard (اختیاری برای مشتریان بدون Docker) کد منبع کامل (فقط Enterprise با قرارداد NDA)

تصمیم: Docker Compose به‌عنوان روش رسمی؛ ZIP فقط در صورت درخواست مشتری و با هزینه پیاده‌سازی.

۱۵ جمع‌بندی و گام بعدی

۱۵.۱ نمای کلی نهایی

لایهتکنولوژیمسئولیت
موتور اتوماسیونLaravel 11 / PHP 8.3اجرای جریان‌ها، گراف، Context، مدیریت خطا
APILaravel REST + Sanctum + API Keyارتباط پنل و سیستم‌های مشتری
صف و اجراRedis + Laravel Horizonاجرای Async، retry، مانیتورینگ
دیتابیسPostgreSQL (یا MySQL)داده اصلی + JSON برای پیکربندی‌ها
پنل مدیریتNuxt 4 + Vue 3 + PiniaBuilder بصری، پنل مشتری، پنل Super Admin
کانواس جریان@vue-flow/coreDrag&Drop، اتصال گره‌ها، فرم داینامیک
WebSocketLaravel Reverbنمایش زنده اجرا و رویدادها
Self-HostedDocker Composeنصب روی سرور مشتری
لایسنسJWT امضاشده + heartbeatکنترل نسخه Self-Hosted
چند‌مستأجریSingle DB + tenant_id + Global Scopeجداسازی داده مشتریان
ماژول‌هاLaravel Packages + Module Registryتخصصی‌سازی برای هر صنعت
بیلینگپلن + Usage Metering + درگاه پرداختدرآمد تکرارشونده

۱۵.۲ پنج اصل غیرقابل مذاکره

  1. هسته هرگز به ماژول وابسته نمی‌شود. ارتباط یک‌طرفه: ماژول → هسته.
  2. Usage Metering از روز اول. بدون آن، پلن‌بندی و صورتحساب غیرممکن می‌شود.
  3. فرم گره‌ها از schema سرور ساخته می‌شود. نه هاردکد در فرانت.
  4. یک کدبیس برای هر سه حالت. تفاوت فقط با پرچم app.mode و لایه Platform/.
  5. ایزوله‌سازی tenant غیرقابل چشم‌پوشی است. تست نشت داده در CI.

۱۵.۳ گام بعدی پیشنهادی

پیشنهاد می‌کنم به ترتیب زیر پیش برویم و برای هر بخش یک فایل تحلیل جداگانه بسازیم:

  1. تحلیل تفصیلی ماژول اول (module-crm): گره‌ها، فرم‌ها، سناریوهای واقعی
  2. طراحی کامل اسکیمای دیتابیس (Migration کامل + ERD)
  3. تعریف قرارداد NodeContract و ساختار schema استاندارد
  4. طراحی UX دقیق Workflow Builder (سیم‌کشی، انتخاب متغیر، اجرای آزمایشی)
  5. طراحی سیستم PlanGate و Usage Metering
  6. Sprint Plan فاز ۱ با تسک‌های قابل تخمین

۱۵.۴ سؤالات باز برای تصمیم‌گیری

#سؤالتأثیر
۱بازار هدف اولیه کدام صنعت است؟ (CRM / فروشگاه / کلینیک / ...)ماژول اول، پیام بازاریابی، قالب‌های آماده
۲درگاه پرداخت داخلی (زرین‌پال/آیدی‌پی) یا بین‌المللی (Stripe) یا هر دو؟معماری Billing و صورتحساب
۳پنل Builder در فاز ۱ کامل باشد یا ساده (JSON Editor + پیش‌نمایش)؟زمان MVP — تفاوت ۲ تا ۳ هفته
۴نسخه Self-Hosted از ابتدا یا فاز ۳؟پیچیدگی معماری و زمان‌بندی
۵مجوز ماژول‌های شخص ثالث: فقط داخلی یا Marketplace باز؟طراحی فرآیند انتشار و بررسی