docs(dealix): production readiness — go-live gate CLI, LAUNCH_CHECKLIST, internal token note

- Add scripts/check_go_live_gate.py for in-process go-live-gate summary
- LAUNCH_CHECKLIST: go-live-gate section, CORS/FRONTEND_URL/NEXT_PUBLIC details, internal token review
- internal_api: pointer to checklist section 6 for strict production review

Made-with: Cursor
This commit is contained in:
Sami Assiri 2026-04-13 02:44:15 +03:00
parent a07829d485
commit c114ac34ae
3 changed files with 86 additions and 4 deletions

View File

@ -1,4 +1,8 @@
"""Optional bearer token for /api/v1 when DEALIX_INTERNAL_API_TOKEN is set (production hardening)."""
"""Optional bearer token for /api/v1 when DEALIX_INTERNAL_API_TOKEN is set (production hardening).
Exemption list is broad (public marketing, demo widgets). Before strict production, see
docs/LAUNCH_CHECKLIST.md section 6.
"""
from __future__ import annotations

View File

@ -21,10 +21,22 @@
`.\scripts\grand_launch_verify.ps1 -HttpCheck -SoftReady`
مع `DEALIX_BASE_URL` إذا لم يكن الـ API على `http://127.0.0.1:8000`.
### 2.1 بوابة الجاهزية التجارية (`go-live-gate`)
- [ ] مع تشغيل الـ API وبعد ضبط `.env` الحقيقي (staging أو إنتاج): استدعِ
`GET /api/v1/autonomous-foundation/integrations/go-live-gate`
- [ ] **200** + `launch_allowed: true` يعني اجتياز الفحوص الحاسمة حسب [`go_live_matrix.py`](../backend/app/services/go_live_matrix.py). **403** مع نفس شكل JSON يعني وجود فحوص معطّلة — راجع `blocked_reasons` و`blocking`.
- [ ] من الطرفية (خادم على 8000):
`curl -sS http://127.0.0.1:8000/api/v1/autonomous-foundation/integrations/go-live-gate`
- [ ] ملخص سريع بدون uvicorn (يحمّل التطبيق داخل العملية، مثل الاختبارات): من جذر `salesflow-saas`:
`py -3 scripts/check_go_live_gate.py`
(للطباعة الكاملة: `py -3 scripts/check_go_live_gate.py --json`)
## 3. الواجهة (Next.js)
- [ ] ضبط `NEXT_PUBLIC_API_URL` لنقطة نهاية الـ API العامة (انظر `frontend/.env.example`).
- [ ] التأكد من أن الـ backend يضمّن نطاق الواجهة في CORS (`FRONTEND_URL` / `main.py`).
- [ ] ضبط **`NEXT_PUBLIC_API_URL`** لعنوان الـ API الذي يصل إليه المتصفح فعليًا (HTTPS في الإنتاج). مرجع: [`frontend/.env.example`](../frontend/.env.example).
- [ ] **CORS:** في الباكند عرّف **`FRONTEND_URL`** (أصل الواجهة الافتراضي، مثل `https://app.dealix.sa`) في `backend/.env` — يُستخدم في [`main.py`](../backend/app/main.py) مع أصول ثابتة إضافية. لأصول إضافية (معاينة، دومين قديم): **`CORS_EXTRA_ORIGINS`** قائمة مفصولة بفواصل — انظر [`app/config.py`](../backend/app/config.py).
- [ ] تحقق من أن قيمة `NEXT_PUBLIC_API_URL` على الواجهة **تطابق** المخطط والشهادة (لا خلط `http`/`https` أو دومين خاطئ) حتى لا تفشل طلبات `fetch` / `apiFetch`.
## 4. الأسرار والبيئة
@ -34,7 +46,15 @@
## 5. ما بعد الإطلاق
- [ ] مراقبة `/api/v1/health` و `/api/v1/ready`.
- [ ] مراجعة `go-live-gate` عند التكاملات الحقيقية (قد يعيد 403 حتى اكتمال التهيئة — متوقع).
- [ ] إعادة فحص **`go-live-gate`** بعد أي تغيير على أسرار الطرف الثالث (Stripe، البريد، CRM، إلخ).
## 6. أمان `DEALIX_INTERNAL_API_TOKEN` (إنتاج)
عند تعيين **`DEALIX_INTERNAL_API_TOKEN`** في الباكند، يُطلب `Authorization: Bearer <التوكن>` على معظم مسارات `/api/v1`، مع **قائمة إعفاءات** واسعة للمسارات العامة والتسويق والديمو — التنفيذ في [`app/middleware/internal_api.py`](../backend/app/middleware/internal_api.py).
- [ ] **Staging / ديمو:** الإعفاءات الحالية تسمح للواجهة بجلب محتوى عام ولوحات ديمو دون التوكن الداخلي؛ هذا متعمد لتجربة المطوّر.
- [ ] **إنتاج صارم:** راجع ما إذا كانت مسارات الإعفاء (مثل أجزاء من التسويق أو `dealix/generate-leads`) مقبولة لسياسة المنتج؛ يمكن لاحقًا تقييد الإعفاءات حسب `ENVIRONMENT` أو إلزام **`apiFetch` + JWT** لمسارات حساسة بدل الإعفاء.
- [ ] إن لم تُضبط المتغير (فارغ)، الميدلوير لا يفرض التوكن — مناسب للتطوير المحلي فقط.
---

View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""
Print a short summary of GET /api/v1/autonomous-foundation/integrations/go-live-gate.
Uses the in-process FastAPI app (same deps as pytest). Does not start uvicorn.
Run from repo:
cd salesflow-saas && py -3 scripts/check_go_live_gate.py
Against a running API instead:
curl -sS http://127.0.0.1:8000/api/v1/autonomous-foundation/integrations/go-live-gate | py -3 -m json.tool
Exit code: 0 always (informational). Use HTTP status / launch_allowed in the JSON when calling from CI.
"""
from __future__ import annotations
import json
import os
import sys
from pathlib import Path
def main() -> int:
saas = Path(__file__).resolve().parent.parent
backend = saas / "backend"
os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///./go_live_gate_cli.db")
os.environ.setdefault("DEALIX_INTERNAL_API_TOKEN", "")
sys.path.insert(0, str(backend))
os.chdir(backend)
from fastapi.testclient import TestClient
from app.main import app
c = TestClient(app)
r = c.get("/api/v1/autonomous-foundation/integrations/go-live-gate")
try:
body = r.json()
except Exception:
print("HTTP", r.status_code, "non-JSON body", r.text[:500])
return 0
la = body.get("launch_allowed")
print(f"HTTP {r.status_code} launch_allowed={la}")
print(f"readiness_percent_total={body.get('readiness_percent_total')}")
br = body.get("blocked_reasons") or []
if br:
print("blocked_reasons (up to 8):")
for line in br[:8]:
print(f" - {line}")
blocking = body.get("blocking") or []
print(f"blocking_checks={len(blocking)}")
if "--json" in sys.argv:
print(json.dumps(body, indent=2, ensure_ascii=False))
return 0
if __name__ == "__main__":
raise SystemExit(main())