- remove the family app from the root (separate parent accounts, invite codes, parental settings); progress.0006 drops its tables, permissions and migration history, and Profile.parent_phone, the two family notification types and ?userId= on /api/progress/nodes go with it - GET /api/user/weekly-report: last 7 days next to the 7 before (estimated minutes, questions, accuracy, islands, tutor questions) for the "parent report" page - profile birthDate in Jalali (accounts/jalali.py), ages 5-99, birthYear derived from it - GET /api/payment/invoices; orders now snapshot list price and plan title - tutor answers only math: server pre-filter, scope rule in the prompt (tutor-v11), refusal marker replaced with fixed text; self-harm gets a help line instead - streamed answers now record token usage (it was always 0) - daily tutor quota: AI_DAILY_QUOTA_FREE (default 3) vs Plan.ai_daily_quota - delete_users management command for wiping test accounts across every app - docs/ai-cost-and-guardrails.md: measured cost per question and guardrail results Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
121 lines
8.9 KiB
Plaintext
121 lines
8.9 KiB
Plaintext
# نمونهی تنظیماتِ بکاندِ تدریسینو — برای لپتاپ و سرور.
|
||
#
|
||
# cp .env.example .env
|
||
#
|
||
# هیچکدام برای بالا آمدنِ سرویس اجباری نیست: دامنهها، CORS، کلیدِ امضا و کش در
|
||
# خودِ config/settings.py پیشفرضِ کارا دارند. مقدارهای این فایل با آن پیشفرضها
|
||
# ادغام میشوند، جایگزینشان نمیشوند. شرحِ کامل: docs/operations.md.
|
||
#
|
||
# مقدارِ واقعیِ کلیدها فقط در .env (که در git نیست)، هرگز در این فایل یا در چت.
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۱) پایه
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
|
||
# روی لپتاپ 1، روی سرور همیشه 0.
|
||
# DEBUG=1 روی سرور یعنی کدِ ورودِ 0000 برای هر شمارهای و صفحهی خطا با تنظیمات.
|
||
DJANGO_DEBUG=0
|
||
|
||
# خالی بماند: بارِ اول یک کلیدِ تصادفی ساخته و در .django_secret_key (0600) نگه
|
||
# داشته میشود. هرگز مقدارِ django-insecure-… داخلِ settings.py را اینجا نگذارید.
|
||
DJANGO_SECRET_KEY=
|
||
|
||
# Redis برای محدودیتِ نرخِ مشترک بینِ workerها؛ خالی = کشِ حافظهی هر worker
|
||
# (/api/health هشدار میدهد). مثال: redis://127.0.0.1:6379/1
|
||
CACHE_URL=
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۲) دامنهها — دو آدرس، بقیه از آنها ساخته میشوند
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ALLOWED_HOSTS، CSRF، CORS، callbackِ زرینپال، برگشت از پرداخت و redirectِ بازار
|
||
# همه از این دو ساخته میشوند. پیشفرضشان همین دامنههای فعلی است.
|
||
# جابهجاییِ دامنه: docs/operations.md، بخشِ «عوض کردنِ دامنه».
|
||
#
|
||
# PUBLIC_BASE_URL=https://mathapi.tadrisino2.ir
|
||
# FRONTEND_URL=https://math.tadrisino2.ir
|
||
#
|
||
# فقط برای دامنهی *اضافه* (مثلاً دامنهی قبلی در دورانِ جابهجایی):
|
||
# DJANGO_ALLOWED_HOSTS=old.example.ir
|
||
# CSRF_TRUSTED_ORIGINS=https://old.example.ir
|
||
# CORS_ALLOWED_ORIGINS=https://old-app.example.ir
|
||
|
||
# تعدادِ پروکسیهای جلوی اپ. سرورِ فعلی: ArvanCloud → nginx، یعنی 2.
|
||
# بیشتر از واقعیت = جعلِ IP و دور زدنِ محدودیتِ نرخ؛ کمتر = همهی مهمانها یک IP.
|
||
NUM_PROXIES=2
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۳) پیامکِ کدِ ورود (کاوهنگار)
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# بدونِ کلید، درخواستِ کد خطای صریحِ ۵۰۳ میدهد (نه موفقیتِ ساختگی).
|
||
KAVENEGAR_API_KEY=
|
||
# نامِ الگوی تأییدشده در پنلِ کاوهنگار (verify/lookup). روی سرورِ فعلی SMSVerify.
|
||
# خطِ این حساب پیامکِ متنِ آزاد را لغو میکند، پس بدونِ الگو کدی نمیرسد.
|
||
KAVENEGAR_OTP_TEMPLATE=
|
||
# خطِ اختصاصی؛ خالی = خطِ پیشفرضِ حساب.
|
||
KAVENEGAR_SENDER=
|
||
|
||
# شمارههای تستیِ تیم با کدِ ثابت، بدونِ پیامک: «شماره:کد» با کاما.
|
||
# کد تصادفی باشد؛ پیش از کاربرِ واقعی خالی شود (/api/health تا آنوقت هشدار میدهد).
|
||
# TEST_LOGIN_PHONES=09120000001:834512,09120000002:110947
|
||
TEST_LOGIN_PHONES=
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۴) دستیارِ هوش مصنوعی (RAG)
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# بدونِ این دو کلید، POST /api/ai/ask پاسخِ آزمایشیِ ثابت (stub) میدهد.
|
||
# GapGPT پروکسیِ OpenAI است و فقط از داخلِ ایران جواب میدهد.
|
||
OPENAI_API_KEY=
|
||
OPENAI_BASE_URL=https://api.gapgpt.app/v1
|
||
QDRANT_URL=https://qdrant.tadrisino2.ir:443
|
||
QDRANT_API_KEY=
|
||
|
||
# مدلها؛ پیشفرضها در settings.py همیناند و سنجیده شدهاند (docs/architecture.md).
|
||
# OPENAI_CHAT_MODEL=gpt-4.1-mini
|
||
# OPENAI_VISION_MODEL=gpt-4.1-mini
|
||
# مدلِ جدا فقط برای پایههای ۱۰ تا ۱۲؛ خالی = همان مدلِ بالا.
|
||
# OPENAI_CHAT_MODEL_UPPER=
|
||
# embedding را عوض نکنید مگر collectionهای Qdrant هم با همان مدل بازساخته شوند.
|
||
# OPENAI_EMBEDDING_MODEL=text-embedding-3-small
|
||
# سقفِ سوالِ روزانه از دستیار برای کاربرِ بدونِ اشتراک (پیشفرض ۳). سقفِ مشترکان روی
|
||
# هر پلن در ادمین است (ai_daily_quota). حسابِ هزینه: docs/ai-cost-and-guardrails.md
|
||
# AI_DAILY_QUOTA_FREE=3
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۵) پرداخت
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# زرینپال. بدونِ مرچنت، پرداخت ۵۰۳ میدهد. مرچنت باید برای دامنهی PUBLIC_BASE_URL
|
||
# ثبت شده باشد، وگرنه زرینپال خطای -14 میدهد.
|
||
ZARINPAL_MERCHANT_ID=
|
||
# 1 = محیطِ آزمایشیِ زرینپال (بیپولِ واقعی). روی سرورِ فعلی خالی است: درگاهِ واقعی.
|
||
ZARINPAL_SANDBOX=
|
||
|
||
# کافهبازار (فقط خریدِ درونبرنامهایِ اپِ اندروید). روشِ ترجیحی توکنِ ثابتِ پیشخان
|
||
# است؛ سه متغیرِ OAuth فقط وقتی آن نیست. بدونِ هیچکدام، مسیرِ بازار بسته میماند.
|
||
BAZAAR_PISHKHAN_API_SECRET=
|
||
BAZAAR_CLIENT_ID=
|
||
BAZAAR_CLIENT_SECRET=
|
||
BAZAAR_REFRESH_TOKEN=
|
||
# BAZAAR_PACKAGE_NAME=ir.tadrisino.app
|
||
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# ۶) اختیاری — پیشفرضها معمولاً کافیاند
|
||
# ═══════════════════════════════════════════════════════════════════════
|
||
# کلیدِ مسیرهای داخلیِ سرور-به-سرور؛ خالی روی سرور = آن مسیرها بستهاند.
|
||
# INTERNAL_SERVICE_KEY=
|
||
# با صفر قلب جلوی جواب دادن گرفته شود؟ فقط وقتی فرانت صفحهی «قلب تمام شد» دارد.
|
||
# HEARTS_ENFORCED=0
|
||
# سقفهای کدِ ورود: هر شماره در روز، و کلِ سامانه در روز (ضدِ SMS pumping).
|
||
# OTP_REQUEST_PHONE_DAILY_MAX=10
|
||
# OTP_SMS_GLOBAL_DAILY_MAX=300
|
||
# سقفِ خواندن روی اندپوینتهای پرترافیک، و سقفِ /api/health.
|
||
# READ_THROTTLE_RATE=120/min
|
||
# HEALTH_THROTTLE_RATE=60/min
|
||
# کشِ پاسخِ دستیار (ثانیه)؛ سوالِ تکراری دوباره به مدل نمیرود.
|
||
# RAG_ANSWER_CACHE_TTL=1800
|
||
# 1 = دستیار حتی با کلیدها هم پاسخِ آزمایشی بدهد.
|
||
# RAG_FORCE_MOCK=
|
||
# لاگ در فایل علاوه بر stdout (فقط داخلِ Docker).
|
||
# LOG_DIR=
|
||
# رمزِ ادمینِ Grafana در docker compose (فقط محلی).
|
||
# GRAFANA_ADMIN_PASSWORD=admin
|