mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
chore(dealix): launch runbooks, staging env templates, SQLite init on startup, product journey test
Co-authored-by: VoXc2 <VoXc2@users.noreply.github.com>
This commit is contained in:
parent
8c3d91c070
commit
69f5082e5e
36
salesflow-saas/.env.staging.example
Normal file
36
salesflow-saas/.env.staging.example
Normal file
@ -0,0 +1,36 @@
|
||||
# Staging template — copy to `.env` on the staging host (never commit `.env`).
|
||||
# Full variable list: `.env.example`. Phase-2 integrations checklist: `docs/INTEGRATION_MASTER_AR.md`
|
||||
# and `backend/.env.phase2.example`.
|
||||
|
||||
ENVIRONMENT=staging
|
||||
DEFAULT_TIMEZONE=Asia/Riyadh
|
||||
|
||||
# Docker Compose: keep @db / @redis hostnames. Bare metal: use 127.0.0.1 and matching ports.
|
||||
DB_NAME=salesflow
|
||||
DB_USER=salesflow
|
||||
DB_PASSWORD=REPLACE_ME_STRONG
|
||||
DATABASE_URL=postgresql+asyncpg://salesflow:REPLACE_ME_STRONG@db:5432/salesflow
|
||||
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
|
||||
SECRET_KEY=REPLACE_ME_RANDOM_32PLUS_CHARS
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||
|
||||
# Public URLs for your staging domain (CORS + webhooks)
|
||||
API_URL=https://api-staging.example.com
|
||||
FRONTEND_URL=https://app-staging.example.com
|
||||
NEXT_PUBLIC_API_URL=https://api-staging.example.com
|
||||
WEBHOOK_BASE_URL=https://api-staging.example.com/api/v1/webhooks
|
||||
|
||||
# LLM — set at least one real key for AI features in staging
|
||||
OPENAI_API_KEY=
|
||||
GROQ_API_KEY=
|
||||
|
||||
# Channels — fill only what you will smoke-test (see launch checklist)
|
||||
WHATSAPP_API_TOKEN=
|
||||
WHATSAPP_PHONE_NUMBER_ID=
|
||||
WHATSAPP_VERIFY_TOKEN=
|
||||
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
@ -28,10 +28,12 @@ Frontend: `http://localhost:3000`
|
||||
|
||||
**If the browser shows connection refused on `:3000` or `:8000`:** nothing is listening on that port yet. Start the stack (`docker compose up` from this folder) or run `uvicorn` / `npm run dev` manually. Confirm with `curl -sSf http://127.0.0.1:8000/api/v1/health` and ensure the browser is on the same machine as the server (not WSL/remote without port forwarding).
|
||||
|
||||
**Without Docker:** install Python 3.12+ and Node 22+, copy `.env` and `frontend/.env.local`, run Postgres/Redis (or point `DATABASE_URL` / `REDIS_URL` at existing instances), then `cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000` and `cd frontend && npm run dev`.
|
||||
**Without Docker:** install Python 3.12+ and Node 22+, copy `.env` and `frontend/.env.local`, run Postgres/Redis (or point `DATABASE_URL` / `REDIS_URL` at existing instances), then `cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000` and `cd frontend && npm run dev`. If `DATABASE_URL` uses SQLite (`sqlite+aiosqlite`), the API runs `init_db()` on startup so tables exist for local smoke tests; production should use Postgres + Alembic migrations.
|
||||
|
||||
**E2E locally:** after `npm ci`, run `npx playwright install chromium` once, then `npm run test:e2e` (matches CI).
|
||||
|
||||
**Staging env templates:** `.env.staging.example` (repo root) and `frontend/.env.staging.example` — copy to `.env` / `frontend/.env.local` on the host; see `docs/STAGING_ENV_CHECKLIST.md`.
|
||||
|
||||
**Customer onboarding (B2B):** `GET /api/v1/customer-onboarding/journey` and `docs/CUSTOMER_OS_ONBOARDING_AR.md`. Dashboard tab: **مسار التشغيل مع العميل**.
|
||||
|
||||
**Launch verification:** see `docs/LAUNCH_CHECKLIST.md`. From `salesflow-saas`: copy `frontend/.env.example` to `frontend/.env.local` and set `NEXT_PUBLIC_API_URL`. Run `.\verify-launch.ps1 -HttpCheck -SoftReady` (use `-BaseUrl` if the API is not on port 8000).
|
||||
|
||||
@ -61,6 +61,8 @@ async def get_db():
|
||||
|
||||
|
||||
async def init_db():
|
||||
import app.models # noqa: F401 — register all models on Base.metadata before create_all
|
||||
|
||||
async with engine.begin() as conn:
|
||||
if not IS_SQLITE:
|
||||
for ext in ["CREATE EXTENSION IF NOT EXISTS vector",
|
||||
|
||||
@ -12,6 +12,7 @@ from contextlib import asynccontextmanager
|
||||
import asyncio
|
||||
|
||||
from app.config import get_settings
|
||||
from app.database import IS_SQLITE, init_db
|
||||
from app.api.v1.router import api_router
|
||||
from app.flows.self_improvement_flow import self_improvement_flow
|
||||
from app.middleware.internal_api import InternalApiTokenMiddleware
|
||||
@ -70,6 +71,8 @@ async def lifespan(app: FastAPI):
|
||||
print(f" Environment: {settings.ENVIRONMENT}")
|
||||
print(f" LLM Primary: {settings.LLM_PRIMARY_PROVIDER}")
|
||||
print(f" LLM Fallback: {settings.LLM_FALLBACK_PROVIDER}")
|
||||
if IS_SQLITE:
|
||||
await init_db()
|
||||
yield
|
||||
# Shutdown
|
||||
stop_event.set()
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
"""
|
||||
Staging / CI — مسار منتج واحد + دخان قناة (بريد عبر outreach بدون إرسال SMTP).
|
||||
|
||||
يُكمّل test_new_subscriber_journey ويُثبت أن القنوات تستجيب بعد تسجيل مستخدم.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from app.main import app
|
||||
|
||||
|
||||
@pytest.mark.launch
|
||||
@pytest.mark.asyncio
|
||||
async def test_staging_happy_path_dashboard_and_email_channel_draft():
|
||||
suffix = uuid.uuid4().hex[:14]
|
||||
email = f"staging_path_{suffix}@dealix.journey.test"
|
||||
password = "Staging_Secure_Pass_9"
|
||||
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
||||
reg = await ac.post(
|
||||
"/api/v1/auth/register",
|
||||
json={
|
||||
"company_name": f"Staging Path Co {suffix}",
|
||||
"company_name_ar": "شركة مسار الاختبار",
|
||||
"full_name": "مالك الاختبار",
|
||||
"email": email,
|
||||
"password": password,
|
||||
"phone": "0501112233",
|
||||
"industry": "real_estate",
|
||||
},
|
||||
)
|
||||
assert reg.status_code == 200, reg.text
|
||||
token = reg.json()["access_token"]
|
||||
|
||||
dash = await ac.get(
|
||||
"/api/v1/dashboard/overview",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
)
|
||||
assert dash.status_code == 200
|
||||
|
||||
outreach = await ac.post(
|
||||
"/api/v1/outreach",
|
||||
json={
|
||||
"channel": "email",
|
||||
"lead": {
|
||||
"name": "عميل تجريبي",
|
||||
"company": "عقار الرياض",
|
||||
"sector": "عقار",
|
||||
},
|
||||
"campaign_type": "cold_intro",
|
||||
"language": "ar",
|
||||
},
|
||||
)
|
||||
assert outreach.status_code == 200, outreach.text
|
||||
body = outreach.json()
|
||||
assert body.get("channel") == "email"
|
||||
assert "subject" in body and "body" in body
|
||||
assert len(body["subject"]) > 0 and len(body["body"]) > 0
|
||||
40
salesflow-saas/docs/DOCKER_FULL_STACK.md
Normal file
40
salesflow-saas/docs/DOCKER_FULL_STACK.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Dealix — تشغيل الستاك الكامل بـ Docker Compose
|
||||
|
||||
من مجلد `salesflow-saas`:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# عدّل .env (SECRET_KEY، كلمات مرور DB، مفاتيح اختيارية)
|
||||
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## قاعدة البيانات والبذور
|
||||
|
||||
```bash
|
||||
make migrate
|
||||
make seed
|
||||
```
|
||||
|
||||
## Celery
|
||||
|
||||
الخدمات: `celery_worker`, `celery_beat`. للتحقق:
|
||||
|
||||
```bash
|
||||
docker compose logs -f celery_worker --tail=50
|
||||
```
|
||||
|
||||
إذا كانت الميزات (تسلسلات، مهام مجدولة) لا تعمل، راجع أن Redis و`REDIS_URL` سليمة وأن الـ worker يعمل دون أخطاء متكررة.
|
||||
|
||||
## إيقاف التشغيل
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
# مع حذف الحجم (احذر — يمسح بيانات Postgres المحلية):
|
||||
# docker compose down -v
|
||||
```
|
||||
|
||||
## بيئة بدون Docker
|
||||
|
||||
على أجهزة التطوير التي لا تتوفر فيها Docker، استخدم نفس أوامر CI: `pytest` مع SQLite و`npm run build`، وتشغيل `uvicorn` محلياً مع Postgres/Redis منفصلين أو قاعدة SQLite للاختبارات فقط — لا يغني ذلك عن اختبار staging حقيقي قبل الإنتاج.
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
- [ ] تشغيل من **أحدث** كود في المستودع:
|
||||
`cd backend && py -m uvicorn app.main:app --host 0.0.0.0 --port 8000`
|
||||
- [ ] **SQLite محلي فقط:** عند `DATABASE_URL=sqlite+aiosqlite://...` يُنشئ التطبيق الجداول عند الإقلاع (`init_db`) لتسهيل الاختبار؛ **الإنتاج يستخدم Postgres + Alembic** (`make migrate`) وليس الاعتماد على `create_all`.
|
||||
- [ ] إذا ظهر **404** على `/api/v1/marketing/hub` أو `/api/v1/strategy/summary` فالعملية غالباً **قديمة** — أعد تشغيل `uvicorn` بعد `git pull`.
|
||||
- [ ] اختبار HTTP:
|
||||
`py scripts/full_stack_launch_test.py --http-only --soft-ready`
|
||||
@ -31,6 +32,11 @@
|
||||
|
||||
- [ ] مراقبة `/api/v1/health` و `/api/v1/ready`.
|
||||
- [ ] مراجعة `go-live-gate` عند التكاملات الحقيقية (قد يعيد 403 حتى اكتمال التهيئة — متوقع).
|
||||
- [ ] خطة التراجع والقطع: `memory/runbooks/ROLLBACK_AND_GO_LIVE.md`.
|
||||
|
||||
## 6. تمييز السوق (قبل الإعلان)
|
||||
|
||||
- [ ] مراجعة `docs/MARKET_POSITIONING_AR.md` ومواءمة النسخ مع الميزات المفعّلة فعلياً.
|
||||
|
||||
---
|
||||
|
||||
|
||||
25
salesflow-saas/docs/MARKET_POSITIONING_AR.md
Normal file
25
salesflow-saas/docs/MARKET_POSITIONING_AR.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Dealix — تمييز السوق والرسالة (عربي)
|
||||
|
||||
## قصة قطاع: عقار في الرياض
|
||||
|
||||
**المشكلة:** فرق المبيعات تتلقى استفسارات من واتساب والموقع، لكن المتابعة غير موحّدة، والتأهيل يدوي، والامتثال لموافقات العملاء (PDPL) غير موثّق.
|
||||
|
||||
**الحل مع Dealix:** مسار واحد من Lead → تأهيل بالذكاء الاصطناعي (عربي) → تسلسل رسائل بحكم PDPL → لوحة للصفقات والموافقات. العملاء يرون **وقت أقل على التتبع** و**زيادة وضوح Pipeline**.
|
||||
|
||||
## مقارنة سريعة مع CRM عام (HubSpot-style)
|
||||
|
||||
| البعد | CRM عام | Dealix |
|
||||
|--------|---------|--------|
|
||||
| العربية والـ RTL | غالباً إضافة | أولاً في الواجهة والقوالب |
|
||||
| واتساب كقناة أولى | يحتاج تكاملات وإعداد طويل | مسارات وقنوات مدمجة في المنتج (انظر التكاملات في `docs/INTEGRATION_MASTER_AR.md`) |
|
||||
| PDPL والموافقات | مسؤولية العميل غالباً | طبقة خدمات ووثائق موجهة للسوق السعودي |
|
||||
| «يوم واحد» | استيراد جهات اتصال | تشغيل سريع مع قوائم التحقق والـ staging templates |
|
||||
|
||||
## الامتثال كميزة
|
||||
|
||||
- التحقق من الموافقة قبل أي إرسال صادر مذكور في سياسة المنتج (`services/pdpl`).
|
||||
- للمواد الخارجية: اذكر **PDPL** و**تسجيل الموافقات** بلغة عملاء الأعمال، دون وعود بميزات غير مفعّلة في البيئة التي تنشرونها.
|
||||
|
||||
## مواءمة النسخ مع المنتج الحي
|
||||
|
||||
قبل الحملات: راجع المسارات العامة (`/`، `/marketers`، `/strategy`) و`GET /api/v1/value-proposition/` و`GET /api/v1/customer-onboarding/journey` وتأكد أن الوعود في التسويق تطابق ما هو مُفعّل في الإنتاج.
|
||||
26
salesflow-saas/docs/STAGING_ENV_CHECKLIST.md
Normal file
26
salesflow-saas/docs/STAGING_ENV_CHECKLIST.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Dealix — قائمة تهيئة بيئة Staging
|
||||
|
||||
استخدم هذا الملف مع [LAUNCH_CHECKLIST.md](LAUNCH_CHECKLIST.md) و [INTEGRATION_MASTER_AR.md](INTEGRATION_MASTER_AR.md).
|
||||
|
||||
## 1) ملفات البيئة
|
||||
|
||||
| الملف | الإجراء |
|
||||
|--------|---------|
|
||||
| جذر `salesflow-saas` | انسخ [`.env.staging.example`](../.env.staging.example) إلى `.env` واستبدل القيم |
|
||||
| `frontend/` | انسخ [`frontend/.env.staging.example`](../frontend/.env.staging.example) إلى `frontend/.env.local` |
|
||||
| تكاملات موسعة | راجع `backend/.env.phase2.example` واملأ الأقسام التي ستفعّلها فقط |
|
||||
|
||||
## 2) CORS
|
||||
|
||||
- `FRONTEND_URL` في `.env` يجب أن يطابق أصل الواجهة (مثلاً `https://app-staging.example.com`).
|
||||
- إن تغيّر النطاق، حدّث إعدادات CORS في الباكند إن لزم.
|
||||
|
||||
## 3) بعد التشغيل
|
||||
|
||||
- `GET /api/v1/health` و `GET /api/v1/ready`
|
||||
- سكربت اختياري: `python scripts/full_stack_launch_test.py --http-only --soft-ready` مع `DEALIX_BASE_URL`
|
||||
- جولة يدوية سريعة للواجهة (RTL): `/`، `/landing`، `/marketers`، `/strategy`، `/login`، `/register`، `/dashboard`، `/settings`، `/privacy`، `/terms`
|
||||
|
||||
## 4) قنوات حقيقية
|
||||
|
||||
لا تفعّل واتساب/بريد إنتاجي حتى اكتمال فحوص PDPL والموافقات. للـ staging اختبر عنواناً داخلياً أو رقم sandbox.
|
||||
4
salesflow-saas/frontend/.env.staging.example
Normal file
4
salesflow-saas/frontend/.env.staging.example
Normal file
@ -0,0 +1,4 @@
|
||||
# Staging — copy to `.env.local` (or set in hosting dashboard). Do not commit `.env.local`.
|
||||
# Must be a URL the browser can reach (HTTPS in staging/production).
|
||||
|
||||
NEXT_PUBLIC_API_URL=https://api-staging.example.com
|
||||
31
salesflow-saas/memory/runbooks/ROLLBACK_AND_GO_LIVE.md
Normal file
31
salesflow-saas/memory/runbooks/ROLLBACK_AND_GO_LIVE.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Dealix — بوابة الإنتاج، المراقبة، والتراجع
|
||||
|
||||
**مرجع:** `docs/LAUNCH_CHECKLIST.md`، `GET /api/v1/autonomous-foundation/integrations/go-live-gate`، `GET /api/v1/autonomous-foundation/integrations/live-readiness`.
|
||||
|
||||
## ما قبل القطع (go-live gate)
|
||||
|
||||
1. دمج `main` مع CI أخضر (باكند pytest، فرونت lint/build، Playwright E2E).
|
||||
2. Postgres: `make migrate` (أو ما يعادله في الاستضافة) — **لا** تعتمد على `init_db()` في SQLite للإنتاج.
|
||||
3. ضبط `.env` و`frontend/.env.local` (`NEXT_PUBLIC_API_URL`، `FRONTEND_URL`، CORS).
|
||||
4. توقع **403** من `go-live-gate` حتى تكتمل التكاملات الحرجة — هذا متوقع إذا كانت البيئة غير مهيأة بالكامل؛ راجع `live-readiness` للتفاصيل.
|
||||
|
||||
## النشر
|
||||
|
||||
- باكند: صورة Docker أو عملية `uvicorn` خلف reverse proxy مع TLS.
|
||||
- فرونت: بناء Next.js (`npm run build`) أو منصة الاستضافة المختارة؛ نفس متغيرات الـ API العامة.
|
||||
|
||||
## المراقبة بعد الإطلاق
|
||||
|
||||
- `GET /api/v1/health` — الخدمة حية.
|
||||
- `GET /api/v1/ready` — جاهزية التبعيات (قاعدة، Redis، إلخ حسب التطبيق).
|
||||
- سجلات الأخطاء (مثلاً Sentry) ومراقبة معدل 5xx على المسارات الحرجة.
|
||||
|
||||
## التراجع (rollback)
|
||||
|
||||
1. **التطبيق:** إعادة نشر الإصدار السابق من صورة Docker / commit المعتمد.
|
||||
2. **قاعدة البيانات:** إن وُجدت ترحيلات Alembic تسبب خللاً، نفّذ `alembic downgrade` إلى المراجعة المعروفة بالاستقرار (بعد أخذ نسخة احتياطية).
|
||||
3. **الإعدادات:** أعد القيم السابقة للأسرار في مدير الأسرار إن تغيّرت أثناء القطع.
|
||||
|
||||
## فرع الكود للنشر
|
||||
|
||||
استخدم **`main`** كمصدر للإنتاج بعد الدمج؛ لا تعتمد على فروع مؤقتة قديمة في سكربتات النشر.
|
||||
@ -41,7 +41,7 @@ apt install git -y
|
||||
# 5. انسخ المشروع
|
||||
git clone https://github.com/VoXc2/system-prompts-and-models-of-ai-tools.git
|
||||
cd system-prompts-and-models-of-ai-tools
|
||||
git checkout claude/complete-system-prompts-wqJCm
|
||||
git checkout main
|
||||
cd salesflow-saas
|
||||
```
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user