Wire production domain, CORS for tenant subdomains, celery volume mounts, and nginx reverse proxy configs for apex, API, identity, auth, and wildcard tenants. Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
طرح دیتابیس (Database Schema)
بخش ۱ — دیتابیس Core Platform (core_platform_db) — فاز ۱
همه مدلها با SQLAlchemy 2.x و Alembic پیاده شدهاند. شناسهها از نوع UUID و زمانها timezone-aware هستند.
جدول tenants
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| name | varchar(255) | نام مستأجر (business_name در onboarding) |
| slug | varchar(100) unique | شناسه یکتا برای resolve |
| status | enum | draft / pending_activation / active / suspended / archived (+ مقادیر قدیمی inactive/deleted برای سازگاری) |
| owner_user_id | UUID null | مالک (از Identity Service) |
| business_type | varchar(100) null | نوع کسبوکار (فاز ۴ — onboarding) |
| default_locale | varchar(20) | پیشفرض fa-IR |
| timezone | varchar(50) | پیشفرض Asia/Tehran |
| primary_color | varchar(20) null | برندینگ |
| secondary_color | varchar(20) null | برندینگ |
| logo_url | varchar(500) null | برندینگ |
| favicon_url | varchar(500) null | برندینگ |
| onboarding_completed | bool | پیشفرض false؛ با POST .../complete به true تغییر میکند |
| created_at, updated_at | timestamptz |
ایندکسها: slug (unique)، status.
فیلدهای
business_typeتاonboarding_completedدر migration0005_tenant_onboardingاضافه شدهاند (فاز ۴ — Tenant Onboarding).
جدول domains
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| tenant_id | UUID (FK→tenants) | |
| domain | varchar(255) unique | |
| domain_type | enum | subdomain / custom_domain |
| is_verified | bool | |
| verified_at | timestamptz null | |
| is_primary | bool | دامنهٔ اصلی/پیشفرض tenant (زیردامنهٔ خودکار onboarding) — فاز ۴ |
| verification_status | enum | pending / verified / failed — فاز ۴ |
| created_at | timestamptz |
ایندکسها: domain (unique)، tenant_id.
جدول plans
id, code(unique), name, description, is_active, created_at. ایندکس: code.
جدول features
id, feature_key(unique), name, description, service_key, is_active.
ایندکسها: feature_key (unique)، service_key.
مثال feature_key: accounting.invoice.create، crm.lead.create،
ecommerce.product.create، live_chat.widget.enable، ai_assistant.chat.reply.
جدول plan_features
id, plan_id(FK), feature_id(FK), limit_value(null=نامحدود), limit_period(enum: day/month/year/total), is_enabled. محدودیت یکتا: (plan_id, feature_id). ایندکسها روی هر دو کلید خارجی.
جدول tenant_subscriptions
id, tenant_id(FK), plan_id(FK), status(enum: trialing/active/past_due/
canceled/expired), starts_at, ends_at, trial_ends_at, created_at.
ایندکسها: tenant_id، status.
جدول tenant_feature_access
override سفارشی دسترسی: id, tenant_id(FK), feature_id(FK), is_enabled, custom_limit_value(null=نامحدود), used_value, reset_at. محدودیت یکتا: (tenant_id, feature_id). ایندکسها روی هر دو کلید خارجی.
جدول service_registry
id, service_key(unique), name, base_url, status(enum), health_check_url,
created_at. ایندکس: service_key.
جدول module_registry
id, module_key(unique), name, description, is_system_module, is_active.
ایندکس: module_key.
جدول tenant_module_access
id, tenant_id(FK), module_id(FK), is_enabled, enabled_at, disabled_at.
محدودیت یکتا: (tenant_id, module_id). ایندکس: tenant_id.
جدول internal_service_tokens
id, service_key, token_hash(unique), scopes, expires_at, is_active, created_at.
فقط hash توکن ذخیره میشود. ایندکسها: service_key، token_hash.
جدول outbox_events
id, event_type, aggregate_type, aggregate_id, tenant_id, payload(JSON),
status(enum: pending/processed/failed), retry_count, created_at, processed_at.
ایندکسها: status، tenant_id.
جدول inbox_events
id, event_id(unique), source_service, event_type, tenant_id, payload(JSON),
processed_at. ایندکسها: event_id، tenant_id.
جدول audit_logs
id, tenant_id, actor_user_id, action, resource_type, resource_id,
metadata(JSON), ip_address, user_agent, created_at.
ایندکسها: tenant_id، created_at.
جدول users (OTP + لینک SSO — فاز ۳)
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| mobile | varchar(15) unique | شماره موبایل (09xxxxxxxxx) — الزامی |
| keycloak_sub | varchar(100) null unique | لینک به کاربر Keycloak (SSO) |
| varchar(255) null | ایمیل (اختیاری، برای لینک SSO) | |
| mobile_verified | bool | تأیید OTP — true پس از verify موفق |
| role | enum | user / pending_tenant_admin / tenant_admin / platform_admin |
| status | enum | active / inactive / suspended |
| current_tenant_id | UUID null (FK→tenants, ON DELETE SET NULL) |
tenant انتخابشده جاری کاربر — فاز ۴ |
| created_at, updated_at | timestamptz |
ایندکسها: mobile (unique)، keycloak_sub (unique)، status.
نقشها بر اساس context OTP:
public→user(ثبتنام عمومی)admin→pending_tenant_admin(پنل ادمین tenant)PLATFORM_ADMIN_MOBILES→platform_admin
جدول tenant_memberships (فاز ۴ — Tenant Onboarding)
توجه: این جدول در
core_platform_dbاست و با جدول همنام درidentity_access_db(بخش ۳ همین سند) کاملاً متفاوت و بدون ارتباط مستقیم است. جدول Core عضویت واقعی کاربر↔workspace را برای جریان onboarding/authorization مدیریت میکند.
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| tenant_id | UUID (FK→tenants, cascade) | |
| user_id | UUID (FK→users, cascade) | |
| role | enum | platform_admin / tenant_owner / tenant_admin / tenant_editor / tenant_viewer |
| status | enum | active / invited / disabled |
| is_owner | bool | فقط یک یا چند owner فعال در هر tenant (حداقل یکی الزامی) |
| created_at, updated_at | timestamptz |
محدودیت یکتا: (tenant_id, user_id). ایندکسها: tenant_id، user_id، role، status.
قواعد:
- هنگام
POST /onboarding/tenant، کاربر سازنده بهصورت خودکار عضویتtenant_owner/is_owner=true/status=activeمیگیرد. POST /onboarding/tenant/{id}/completeبررسی میکند که حداقل یک owner فعال وجود داشته باشد؛ در غیر این صورت خطایowner_required.- کاربر میتواند در آینده چند عضویت (چند tenant) داشته باشد؛
users.current_tenant_idمشخص میکند کدامیک «جاری» است.
جدول plans و tenant_subscriptions (seed پیشفرض — فاز ۴)
ساختار جدولها از فاز ۱ بدون تغییر باقی مانده (نگاه کنید به پایین همین بخش)؛ در فاز ۴ موارد زیر اضافه شد:
- Migration
0005_tenant_onboardingدو پلنFREEوSTARTERرا باON CONFLICT (code) DO NOTHINGseed میکند (idempotent). PlanService.ensure_default_plan()همان پلنFREEرا در زمان اجرا نیز بهصورت idempotent تضمین میکند (برای محیطهای SQLite تست که migration اجرا نمیشود).POST /onboarding/tenantبهصورت خودکار یکtenant_subscriptionsباplan=FREE،status=activeمیسازد.
بخش ۲ — طراحی اولیه دیتابیس سرویسهای آینده (بدون migration)
اینها فقط طراحی مفهومیاند؛ در فازهای بعدی هر سرویس دیتابیس مستقل خود را با ستون
tenant_idدر جداول بیزینسی خواهد داشت.
- accounting_db: accounts (۴ سطحی)، journal_entries، journal_lines، cost_centers، projects، invoices، payments، taxes، reports.
- crm_db: customers، leads، opportunities، pipelines، stages، tasks، activities، automations.
- ecommerce_db: products، categories، inventory، orders، order_items، payments، shipments، discounts، carts.
- website_builder_db: sites، pages، blocks، forms، menus، media، content.
- live_chat_db: widgets، conversations، messages، agents، routing_rules.
- ai_assistant_db: assistants، knowledge_bases، documents، chat_sessions، messages، handoffs.
- smart_messenger_db: channels، accounts، threads، messages، automations.
- sms_panel_db: providers، templates، campaigns، messages، send_queue.
- link_shortener_db: links، domains، clicks، campaigns.
- notification_db: notifications، channels، templates، delivery_logs.
- file_storage_db: files، buckets، access_policies.
- restaurant_db: menus، menu_items، tables، orders، kitchen_tickets، payments، loyalty.
هر سرویس دسترسی قابلیتها را از Core (check_feature_access) استعلام میکند و
هرگز مستقیماً به core_platform_db متصل نمیشود.
بخش ۳ — دیتابیس Identity & Access (identity_access_db) — فاز ۲
جدول user_profiles
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| keycloak_sub | varchar unique | شناسه کاربر در Keycloak |
| varchar | ||
| username | varchar null | |
| display_name | varchar null | |
| mobile | varchar(15) null unique | شماره موبایل — الزامی برای کاربران جدید |
| mobile_verified | bool | تأیید OTP |
| mobile_verified_at | timestamptz null | زمان تأیید |
| core_user_id | UUID null | لینک به core_platform_db.users |
| status | enum | active / inactive / suspended |
| created_at, updated_at | timestamptz |
ایندکسها: keycloak_sub (unique)، email، mobile (unique).
قانون: کاربر تازهثبتنامشده تا پیش از mobile_verified=true کامل محسوب نمیشود.
کاربران SSO قدیمی بدون موبایل باید از /auth/verify-mobile تکمیل کنند.
جدول tenant_memberships
توجه: این جدول مربوط به
identity_access_db(لایهٔ هویت SSO) است و جدول متفاوتی نسبت بهtenant_membershipsدرcore_platform_dbاست که در بخش ۱ (فاز ۴ — Tenant Onboarding) مستند شده. این دو جدول در دو سرویس/ دیتابیس جدا زندگی میکنند و sync خودکار بین آنها وجود ندارد؛ منبع حقیقت (source of truth) برای نقش عملیاتی کاربر در یک workspace، جدول Core است.
| ستون | نوع | توضیح |
|---|---|---|
| id | UUID (PK) | |
| tenant_id | UUID | مرجع به tenant در Core (بدون FK بین DB) |
| user_id | UUID (FK→user_profiles) | |
| role | enum | tenant_admin / tenant_member |
| is_active | bool | |
| joined_at | timestamptz |
محدودیت یکتا: (tenant_id, user_id). ایندکسها: tenant_id, user_id.