Docs brought to the current state: CLAUDE.md rewritten, README formal, handbook and diagrams redrawn
- CLAUDE.md: 1,225 → ~430 lines, current state only (the dated status log stays in git history). Server rules moved to the top: what is ours on 249/247 and what is not, non-negotiable rules, announce-before-acting, password handling, and the full "deploy it" procedure with verification. - README: formal entry page with current numbers (10 grades, 18,522 questions, 61 API operations, 973 tests, PostgreSQL/Redis). - Removed docs/frontend/ (Figma-era guide with guest login and its own api.ts; the frontend repo has the real client). Swagger's external-docs link now points at the frontend repo. - architecture/operations/security/content-authoring/loadtest/textbooks: SQLite, guest login, demo accounts, question packs and the port-80 note replaced by what is true now. - Technical handbook text updated throughout; all seven diagrams redrawn (PostgreSQL, phone-only login, subscriptions, current data model); PDF rebuilt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -169,35 +169,6 @@ Postgres 5440 (localhost) ◄── تونلِ SSH ─── zareian-pg-tunnel
|
||||
- **کلِ ۲۴۹ رفت:** همان بازیابی تا انتهای WAL روی ماشینِ تازه، و سفارشهای چند ثانیهی آخر را با پنلِ زرینپال/بازار
|
||||
تطبیق دهید.
|
||||
|
||||
بکاپِ دستیِ SQLite (توسعهی محلی):
|
||||
|
||||
|
||||
```bash
|
||||
cd /home/administrator/mathapp-v2
|
||||
mkdir -p .deploy-backups
|
||||
venv/bin/python - <<'PY'
|
||||
import sqlite3, datetime
|
||||
dst = ".deploy-backups/db-%s.sqlite3" % datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
src, out = sqlite3.connect("db.sqlite3"), sqlite3.connect(dst)
|
||||
with out:
|
||||
src.backup(out) # نسخهی سازگار حتی اگر همزمان کسی بنویسد
|
||||
out.close(); src.close()
|
||||
print("backup:", dst, sqlite3.connect(dst).execute("PRAGMA integrity_check").fetchone()[0])
|
||||
PY
|
||||
```
|
||||
|
||||
`sqlite3` بهعنوانِ فرمانِ خط فرمان روی آن سرور نصب **نیست** — از پایتونِ خودِ
|
||||
پروژه استفاده کنید، نه `cp`؛ کپیِ ساده وسطِ یک نوشتن، فایلِ نیمهکاره میدهد.
|
||||
|
||||
بازیابی: سرویس را بخوابانید، فایل را برگردانید، دوباره بالا بیاورید.
|
||||
|
||||
```bash
|
||||
sudo systemctl stop zareian-mathapp
|
||||
cp .deploy-backups/db-<timestamp>.sqlite3 db.sqlite3
|
||||
sudo systemctl start zareian-mathapp
|
||||
curl https://mathapi.tadrisino2.ir/api/health
|
||||
```
|
||||
|
||||
## متغیرهای محیطی
|
||||
|
||||
`.env` خودکار خوانده میشود (`python-dotenv`) و مقادیرش **با پیشفرضهای کد
|
||||
@@ -258,13 +229,12 @@ pendingِ همان کاربر را دوباره با زرینپال میس
|
||||
|
||||
## عوض کردنِ دامنه
|
||||
|
||||
آخرین جابهجایی: ۲۰۲۶-۰۹-۲۶، API از `api.math.tadrisino2.ir` به `mathapi.tadrisino2.ir`
|
||||
(رکوردِ DNSِ آدرسِ قبلی حذف شده). فرانت همان `math.tadrisino2.ir` ماند.
|
||||
دامنههای فعلی: API روی `mathapi.tadrisino2.ir` و فرانت روی `math.tadrisino2.ir`.
|
||||
|
||||
دامنه در کد فقط یکجا آمده: پیشفرضِ `PUBLIC_BASE_URL` و `FRONTEND_URL` در
|
||||
`config/settings.py`. `ALLOWED_HOSTS`، `CSRF_TRUSTED_ORIGINS`، `CORS_ALLOWED_ORIGINS`،
|
||||
callbackِ زرینپال، برگشت از پرداخت، `BAZAAR_REDIRECT_URI` و آدرسِ سلامت در
|
||||
`deploy.sh` همه از همین دو ساخته میشوند (۲۰۲۶-۰۹-۲۶). فرانت هم دامنه را در کد
|
||||
`deploy.sh` همه از همین دو ساخته میشوند (`config/tests_domains.py`). فرانت هم دامنه را در کد
|
||||
ندارد (README همان ریپو).
|
||||
|
||||
ترتیبِ کار، از بیرون به داخل:
|
||||
@@ -291,7 +261,7 @@ callbackِ زرینپال، برگشت از پرداخت، `BAZAAR_REDIRECT_U
|
||||
|
||||
## لغو و بازپرداختِ سفارش (از پنلِ ادمین)
|
||||
|
||||
از ۲۰۲۶-۱۰-۰۲. همه از `/admin/payment/order/` انجام میشود و SSH لازم نیست:
|
||||
همه از `/admin/payment/order/` انجام میشود و SSH لازم نیست:
|
||||
|
||||
1. سفارش را با شمارهاش یا شناسهی کاربر (`user_id`) پیدا کنید. شمارهی فاکتورِ `TD-000123` یعنی سفارشِ ۱۲۳.
|
||||
2. تیکش را بزنید و از فهرستِ «Action» یکی را انتخاب کنید:
|
||||
@@ -362,33 +332,32 @@ callbackِ زرینپال، برگشت از پرداخت، `BAZAAR_REDIRECT_U
|
||||
|
||||
## سرور
|
||||
|
||||
`mathapi.tadrisino2.ir` روی یک **ماشینِ مشترکِ شرکت** اجرا میشود
|
||||
(`administrator@78.38.35.249`)، نه سروری که مالِ این پروژه باشد. روی همان ماشین
|
||||
Gitea، سرویسِ ایمیل، DNS، چند دیتابیس و اپهای تیمهای دیگر در حالِ کارند.
|
||||
`mathapi.tadrisino2.ir` روی یک **ماشینِ مشترکِ شرکت** اجرا میشود (`administrator@78.38.35.249`)، نه سروری که مالِ این
|
||||
پروژه باشد. روی همان ماشین Gitea، ایمیل، DNS، چند دیتابیس و اپهای تیمهای دیگر در حالِ کارند، و حسابِ ما `sudo`ِ
|
||||
کامل دارد؛ تنها مانع میانِ یک فرمانِ بیدقت و دادهی کلِ شرکت، خودِ اجراکننده است. سرورِ بکاپ (`78.38.35.247`) هم
|
||||
مشترک است.
|
||||
|
||||
مالِ ما **دقیقاً یک دایرکتوری** است: `/home/administrator/mathapp-v2`، که با
|
||||
`gunicorn-mathapp.service` سرو میشود. همان یونیت با نامِ `zareian-mathapp` هم
|
||||
پاسخ میدهد و **همیشه همین نام را بنویسید**:
|
||||
مالِ ما روی ۲۴۹: پوشههای `~/mathapp-v2` (بکاند) و `~/mathapp_frontend_new` (فرانت)، سرویسِ `gunicorn-mathapp` با
|
||||
نامِ دومِ **`zareian-mathapp`** (همیشه همین نام را بنویسید)، `zareian-redis`، clusterِ Postgresِ `14/zareian`، تایمرِ
|
||||
`zareian-applog-archive`، و دو سایت و دو snippetِ nginx (بخشِ بعد). روی ۲۴۷ فقط `~/zareian-pgbackup/` و یونیتهای
|
||||
`zareian-*`.
|
||||
|
||||
```bash
|
||||
sudo systemctl restart zareian-mathapp # مالِ ما
|
||||
sudo systemctl restart gunicorn # مالِ ما نیست — اپِ تیمِ دیگر
|
||||
```
|
||||
|
||||
قواعدی که قابلِ مذاکره نیستند:
|
||||
قواعدی که قابلِ مذاکره نیستند (نسخهی کامل، با فهرستِ آنچه مالِ ما نیست و رویهی دیپلو، در `CLAUDE.md` «Working on
|
||||
the servers»):
|
||||
|
||||
1. **هیچ فرمانِ مخربی بیرون از `~/mathapp-v2` اجرا نشود.** مسیر را کامل
|
||||
بنویسید، به دایرکتوریِ جاری تکیه نکنید.
|
||||
2. **`git clean` آنجا هرگز اجرا نشود.** `db.sqlite3`، `.env` و
|
||||
`.django_secret_key` هیچکدام در گیت نیستند و همانجا زندگی میکنند؛
|
||||
`reset --hard` کاری با آنها ندارد ولی `clean -fd` دیتابیس، پیکربندی و
|
||||
همهی نشستهای فعال را نابود میکند.
|
||||
3. **پروژه هرگز پاک و «از نو clone» نشود** — به همان دلیل. برای برگرداندنِ
|
||||
درخت به حالتِ سالم از `git reset --hard origin/main` استفاده کنید.
|
||||
4. **`.env` فقط از راهِ Django خوانده شود.** `cat .env` نه، و مقادیرش در هیچ
|
||||
چتی paste نشود.
|
||||
5. **`df -h /` را قبل از هر کارِ پرنوشت چک کنید.** دیسک مدتیست حدودِ ۹۴٪ پر
|
||||
است؛ پر شدنش سرویسِ ایمیل و Gitea را هم با ما پایین میکشد.
|
||||
1. **اول فقط نگاه کنید**، بعد تغییر بدهید؛ هیچ فرمانِ مخربی بیرون از پوشههای ما، و مسیرها را کامل بنویسید.
|
||||
2. **`git clean` هرگز، و پروژه هرگز پاک و «از نو clone» نشود.** `.env`، `.django_secret_key`، لاگها و بکاپها در گیت
|
||||
نیستند و همانجا زندگی میکنند؛ راهِ برگشت `git reset --hard origin/main` است.
|
||||
3. **فقط `zareian-mathapp` ریاستارت شود**؛ nginx مشترک است: `nginx -t` و بعد `reload`، هرگز `restart`.
|
||||
4. **پیش از ویرایشِ هر چیز زیرِ `/etc` یا `.env` بکاپِ تاریخدار** در `~/mathapp-v2/.deploy-backups/`.
|
||||
5. **`.env` فقط از راهِ Django خوانده شود**؛ `cat .env` نه، و مقادیرش در هیچ چتی paste نشود.
|
||||
6. **`df -h /` پیش از هر کارِ پرنوشت.** پر شدنِ دیسک ایمیل و Gitea را هم پایین میکشد.
|
||||
7. **از منابعِ تیمهای دیگر استفاده نشود** (Redis، Postgres، صف، سایتِ nginx)؛ نیاز به آنها درخواست از ادمینِ سرور است.
|
||||
|
||||
## nginx (دو سایتِ ما)
|
||||
|
||||
@@ -426,6 +395,5 @@ sudo systemctl restart gunicorn # مالِ ما نیست — اپِ
|
||||
---
|
||||
|
||||
> **پیش از آمدنِ کاربرِ واقعی** فهرستِ [`security-before-production.md`](security-before-production.md)
|
||||
> را کامل ببندید: کلیدِ امضا، حسابهای دمو، جزئیاتِ عمومیِ `/api/health`، مستنداتِ عمومیِ API،
|
||||
> جدولِ رتبهبندیِ عمومی، پنلِ ادمین، پورتِ ۸۰ و دسترسیِ سرور.
|
||||
> را کامل ببندید (پنلِ ادمینِ عمومی، کدِ ورودِ بیهش، سقفِ پیامک، دسترسیِ مشترکِ سرور، …).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user