# سند ۳۳ — گزارش تحلیلی سختگیرانه‌ی کل پروژه (AlphabetPlay)

**تاریخ:** ۲۰۲۶-۰۹-۲۶ · **نسخه‌ی مورد تحلیل:** 1.11.0 (HEAD) · **تحلیل‌گر:** عامل اجرایی پروژه
**مبنای شواهد:** مخزن کامل + اجرای امروز همه‌ی گیت‌ها روی همین کد

> این سند عمداً سختگیرانه نوشته شده است. نقاط قوت کوتاه‌اند چون در CHANGELOG و اسناد ۳۰-۳۲ ثبت شده‌اند؛ تمرکز اینجا بر **آنچه نیست، ریسک می‌سازد، یا ادعایش از واقعیتش بزرگ‌تر است**.

---

## ۱. حکم اجرایی

**AlphabetPlay یک محصول نرم‌افزاری مهندسی‌شده‌ی قابل‌دفاع است — اما هنوز یک محصول آموزشیِ اثبات‌شده نیست.**

سیستم (۹ بازی، ۵ زبان، ۷۱۹ واژه، ۷۵ داستان، سینک ابری، پنل ادمین چندنقشه، بکاپ ۳-۲-۱، پایش خطا) با نظم مهندسی بالایی ساخته شده: ۲۳۱ تست واحد/یکپارچه، ۴۸ تست مرورگر واقعی، CI با بودجه‌ی کیفیت، مستندات ۳۳گانه‌ی به‌روز. اما **هیچ کودکی هنوز ۴ هفته با آن زندگی نکرده** و هیچ داده‌ای درباره‌ی «آیا حروف را یاد می‌گیرند؟» وجود ندارد. تمام موج ۲ «اعتبارسنجی» نام داشت و بخش بدونِکاربرش کامل شد؛ خودِ اعتبارسنجی (۵ جلسه‌ی UX + پایلوت) **انجام نشده و مالک آن کاربر است**.

**رتبه‌بندی محورها (۰-۱۰):**

| محور | نمره | یک‌خطی |
|---|---|---|
| معماری و ماژولاریت | ۸ | لایه‌های تمیز، رابط‌های استاندارد، بدون چسبِ زبان/جهت |
| کیفیت تست | ۷.۵ | عمق یکپارچه‌سازی خوب؛ پوشش کلاینت سنجیده نمی‌شود، دو flake امروز پیدا شد |
| امنیت | ۷.۵ | CSP صفر-inline، چرخش توکن، حسابرسی؛ بدون pentest، بدون 2FA |
| داده و محتوا | ۷ | کمّیت عالی؛ کیفیت ۴۰ واژه ⚑ و عمق داستانی حداقلی تأیید انسانی می‌خواهد |
| کارایی | ۶.۵ | بودجه ۸۳-۸۵ با هزینه‌ی CSP؛ بدون باندلر؛ روی تبلت ضعیف هرگز اندازه‌گیری نشد |
| دسترس‌پذیری | ۷ | axe صفر-نقض + کنتراست اصلاح‌شده؛ تست انسانی VoiceOver/NVDA صفر |
| عملیات و استقرار | ۷.۵ | بکاپ ۳-۲-۱ خودکار، Docker/Caddy، رست خودخدمت؛ همه‌چیز تک‌گره |
| **اعتبارسنجی محصول** | **۲** | **پروتکل و ابزار سنجه آماده است؛ اجرای آن شروع نشده** |

---

## ۲. آنچه هست (موجودی صادقانه)

- **کد:** ~۱۸,۶۰۰ خط — کلاینت ۸,۱۴۶ · سرور ۳,۷۸۱ · اسکریپت ۲,۰۰۲ · تست ۴,۷۱۳ (نسبت تست به کدِ محصول ≈ ۰.۴).
- **وابستگی‌های اجرایی: ۵** (express, better-sqlite3, bcryptjs, jsonwebtoken, compression) — ریسک供应链 کم؛ بقیه (mailer، پایش، i18n، انیمیشن) دست‌ساز.
- **تست امروز (همه سبز):** واحد/یکپارچه ۲۳۱ (۱۶ سوئیت) · e2e اصلی ۲۶ · e2e پک‌ها ۶ · e2e ادمین ۱۶ → **۲۷۹**.
- **پوشش (فقط سرور):** خطوط/دستورات ۸۶.۹٪ · توابع ۸۳.۶٪ · شاخه ۶۷.۲٪ (آستانه ۷۵/۷۰/۶۰).
- **Lighthouse (میانه‌ی ۳):** کارایی ۸۵ (بودجه ۸۳) · a11y/BP/SEO ۱۰۰.
- **ممیزی a11y:** ۱۰ حالت تعاملی · ۰ نقض سخت · ۳ هشدار مستند (چک‌باکس‌های داخل label بزرگ).
- **محتوا:** ۷۱۹ واژه (+۴۱۰ این موج) · ۷۵ داستان (+۴۱) · پوشش داستانی ۱۰۰٪ حروف · ۶ استثنای آستانه مستند.
- **عملیات:** بکاپ شبانه WAL-امن + بازیابی تمرین‌شده · restic → S3/R2 · پایش GlitchTip-سازگار · لاگ JSON · retention ۱۸۰/۹۰ روز · Docker+Caddy · CI کامل.
- **تاریخچه‌ی git:** ۷ کامیت — مخزن در موج ۱ «از صفر با تاریخچه‌ی تمیز» بازسازی شد؛ سابقه‌ی فازی توسعه در git **وجود ندارد** (این خودش یک مشاهده‌ی صادقانه است، نه افتخار).

---

## ۳. تحلیل سختگیرانه به تفکیک

### ۳.۱ معماری — قوی، با سقف مشخص

**قوت:** جداسازی Model/Engine/UI در کلاینت، GameModule با رابط استاندارد، جهت/زبان از پک می‌آید نه if/else، اعتبارسنجی داستان در ادمین همان `Stories.validate` بازی (یک منبع حقیقت).

**نقد:**
1. **SQLite تک‌گره = سقف مقیاس.** برای پایلوت ۱۰-۲۰ خانواده بی‌نقص؛ برای ۱۰ هزار خانواده نیاز به مهاجرت دارد. تصمیم درستِ امروز است اما باید «تصمیم بازِ شماره‌ی ۱» بماند، نه فراموش‌شدنی.
2. **محدودسازهای نرخ در حافظه‌اند** — ری‌استارت = پاک‌شدن پنجره‌ها؛ چند نمونه‌ی پشت LB = محدودسازی بی‌اثر. امروز تک‌گره است پس درست کار می‌کند؛ مقیاس‌پذیری این لایه صفر است.
3. **سرویس کار زمان‌بندی‌شده (بکاپ/retention/گزارش) به پروسه‌ی اپ گره خورده** — استقرار blue-green دو نسخه را هم‌زمان می‌کند (دوبکاپ، دوبل retention). برای این مقیاس قابل‌قبول، برای رشد باید جدا شود.
4. **sync دو-وجهی با قاعده‌ی «سرور برنده»** — تداخل هم‌زمان دو دستگاهِ یک کودک تست نشده (سناریوی واقعی: تبلت خانه + گوشت مادربزرگ).

### ۳.۲ کیفیت تست — عمق خوب، دو شکست امتحان امروز

امروز سه واقعیت ناخوشایند درباره‌ی کیفیت تست آشکار شد که باید ثبت بماند:
1. **flake واقعی در e2e-admin:** هر اجرا والدِ بی‌فرزندی می‌ساخت که اجرای بعدی را می‌شکست — یعنی این سوئیت قبل از امروز «سبز» بود اما **قابل‌تکرار نبود**. درس: سبزِ یک‌بار ≠ پایدار.
2. **شکست بی‌صدا در try/catch:** حذف `ROLE_FA` جدول ادمین را در «⏳» فریز کرد بدون هیچ خطای کنسولی — تست‌ها فقط ۹ دقیقه بعد و با پروب دستی گرفتند. الگوی خطرناک: `catch`های فراگیر خطای رندر را می‌بلعند.
3. **محدودساز نرخ، خود تست را کشت:** e2e-admin پشت‌سرهم 429 می‌خورد (۶ ورود در هر اجرا، سقف ۱۰/۱۵دقیقه). راه‌حل موقت ری‌استارت سرور است — بدهی محیط تست.

**گپ‌های ساختاری:** پوشش c8 فقط `server/**` است — ۸,۱۴۶ خط کلاینت (بازی‌ها، موتور تسلط، سینک) هیچ پوشش خطی سنجیده‌شده‌ای ندارد؛ e2eها جبران بخشی می‌کنند اما ادعای «۸۷٪ پوشش» درباره‌ی نیمی از کد نیست. `routes/words.js` با ۵۰٪ پوشش ضعیف‌ترین مسیر است. تست لود/همزمانی هرگز انجام نشده.

### ۳.۳ امنیت — خوب برای مرحله، با ادعا‌های اندازه‌گیری‌نشده

**قوت:** CSP بدون unsafe-inline (و امروز عملاً ثابت شد — تزریق axe بلاک شد)، چرخش refresh تک‌مصرفی، رمز ریست بدون جدول توکن، حسابرسی کامل، محدودسازی نرخ، sanitize پایش.

**نقد:**
1. **هیچ تست نفوذ/ممیزی امنیتی خارجی انجام نشده** — همه‌ی ادعاها self-attested هستند.
2. refresh token در localStorage می‌ماند (انتخاب آگاهانه، اما با هر XSS آینده = نشست سرقت؛ CSP سپر اصلی است).
3. پنل ادمین: بدون 2FA، بدون allowlist IP، بدون قفل حساب پس از خطاهای مکرر (فقط rate limit).
4. خودفراموشی رمز الان دو مسیر موازی دارد (AP- ادمین + کد ایمیل) — نگهداری دو مسیر هزینه‌ی امنیتی دارد؛ باید پایش شود کدام استفاده می‌شود.
5. رازهای تولید (SMTP، restic، Sentry) همه از env — درست؛ اما چک‌لیست چرخش رمز وجود ندارد.

### ۳.۴ داده و محتوا — کمّیت ثبت‌شده، کیفیت معلق

۱. **۴۰ واژه‌ی ⚑ بازبینی‌نشده** (سند ۳۰ §۵) — تا تأیید انسانی، بخشی از تجربه‌ی حروف نادر روی واژه‌های نامطمئن بنا شده است.
۲. **پوشش داستانی «۱۰۰٪» گمراه‌کننده است:** یعنی هر حرف در ≥۱ داستان *کانونی* است — عمق واقعی داستان per حرف متوسط ۱.۵ است؛ برای تثبیت حروف نادر کم است.
۳. تصویر واژه‌ها عمدتاً ایموجی است — برای ۴-۶ سال قابل‌دفاع، اما واژه‌های انتزاعی (ثروت، ظلمت) با ایموجی بی‌معنا می‌شوند؛ دقیقاً همان واژه‌های ⚑.
۴. **پیام‌های خطای سرور فقط فارسی‌اند** — کاربر nl/en/ar/tr در خطاهای API متن فارسی می‌بیند (UI پنج‌زبانه است، بک‌اند نه). ناهماهنگی واقعی.
۵. ابزار محتوا ایدمپوتنت و تست‌دار است (قوت کم‌نظیر) اما هیچ **بازبینی زبانی بومی** (native review) برای en/nl/ar/tr انجام نشده — داستان‌ها توسط غیربومی نوشته شده‌اند.

### ۳.۵ کارایی — بودجه‌ی عقب‌نشینی‌شده

بازپایه‌ی ۸۵→۸۳ در موج ۱ مستند و صادقانه بود؛ امروز ۸۳-۸۵ می‌زند. اما:
1. **باندلر (esbuild) هنوز نیست** — ۶۰+ ماژول جدا؛ این بزرگ‌ترین بدهی کارایی است و موج ۳ است.
2. Lighthouse با شبیه‌سازی موبایلِ middle-tier است — **تبلت واقعی ۴G ضعیف هرگز تست نشد** (هدف‌گذاری سند ۲۳ همین دستگاه‌هاست).
3. `?v=1.11.0` دستی در ~۲۰ جا — فراموش‌شدنش = کش کهنه (خطر مستندشده اما ماشینی نشده).

### ۳.۶ دسترس‌پذیری — نیمی از تعهد

امروز ۰ نقض سخت axe + کنتراست واقعاً اصلاح شد. اما: **تست صفحه‌خوان واقعی (VoiceOver/NVDA) انجام نشد** — سند ۲۹ §۲.۴ صراحتاً «خواندن با VoiceOver/NVDA در بازی اصلی» خواسته بود و فقط معادل خودکارش (axe) اجرا شد. بازی‌های canvas برای صفحه‌خوان عملاً نامرئی‌اند (DOM fallback فقط لبه‌هاست). این نیمه‌کاره باید در گزارش پایلوت صادقانه ذکر شود.

### ۳.۷ عملیات — بالاتر از انتظار این اندازه

بکاپ WAL-امن + تمرین بازیابی + ۳-۲-۱ خودکار + پایش + لاگ ساختاریافته + Docker/Caddy + CI — برای پروژه‌ی تک‌نفری معمول نیست. نقد: هیچ **تمرین فاجعه‌ی end-to-end** روی سرور واقعی انجام نشده (فقط در تست)؛ مانیتورینگ uptime/DAU وجود ندارد (سنجه‌های پایلوت از SQL می‌آیند، نه داشبورد).

---

## ۴. ریسک‌های اصلی (مرتب‌شده)

| # | ریسک | احتمال | اثر | کوتاه‌کننده |
|---|---|---|---|---|
| ۱ | **اعتبارسنجی آموزشی هرگز انجام نشود** — محصول «تمیزِ بی‌فایده» بماند | متوسط | مرگ پروژه | ۵ جلسه‌ی سند ۲۳ همین هفته شروع شود |
| ۲ | کیفیت محتوای ۴۰ واژه ⚑ + داستان‌های غیربومی پایه‌ی پایلوت شود | بالا | داده‌ی پایلوت آلوده | بازبینی انسانی قبل از جلسات (نیم‌ساعت) |
| ۳ | کش SW کهنه بعد از استقرار (نسخه‌دهی دستی) | متوسط | تجربه‌ی خراب خانواده‌ها در پایلوت | اسکریپت نسخه‌دهی ماشینی در CI |
| ۴ | تک‌نگهدارنده (bus factor = ۱) | قطعی | توقف کل | مستندات خوب این را کاستی می‌دهد، رفع نمی‌کند |
| ۵ | SQLite/تک‌گره در صورت رشد سریع | پایین (پایلوت) | مهاجرت دشوار | تصمیم آگاهانه — بازبینی بعد از پایلوت |
| ۶ | flakeهای تست پنهان بمانند (دو مورد امروز) | متوسط | اعتماد به CI می‌ریزد | اجرای CI در PR (موجود) + seed ایزوله |

---

## ۵. تصمیم‌های باز که فقط مالک می‌تواند بگیرد

۱. شروع ۵ جلسه‌ی کودک (سند ۲۳) — هر چیز دیگری جایش نیست.
۲. ~~بازبینی ۴۰ واژه‌ی ⚑~~ ✅ به نیابت انجام شد (۱.13.0 — §۶-۷)؛ فقط تأیید نهایی جلسه‌ی بعد مانده.
۳. پیام جذب پایلوت (تصمیم §۶/۳ ممیزی — جامعه‌ی ایرانی روتردام یا عمومی؟).
۴. SMTP واقعی کدام باشد (Resend/Mailgun/خودم) + S3/R2 برای restic — کلیدها که داده شود فعال است.
۵. VoiceOver/NVDA دستی — نیم‌ساعت با گوشی/لپ‌تاپ.

## ۶. توصیه‌های موج ۲.۵ (پس از جلسات UX — اولویت‌دار)

۱. **esbuild bundle** — بودجه به ۸۵+ برمی‌گردد، خطر کش نسخه‌دهی هم حل می‌شود (hash در نام فایل).
۲. ~~درج `test:a11y` در CI~~ ✅ انجام شد (1.13.0 — گام CI بعد از e2e-admin).
۳. بومی‌بازبینی داستان‌های en/nl/ar/tr + حذف/جایگزینی واژه‌های ردشده.
۴. خطاهای API دو‌زبانه (fa + زبان پک) — الگوی `error.code` موجود است، فقط پیام.
۵. ~~سناریوی «دو دستگاه هم‌زمان یک کودک»~~ ✅ تست یکپارچه در api.test.js (1.13.0): دو جلسه‌ی cst_ جدا برای یک کودک، push متعارض، ادغام max (mastery/correct/wrong) و دید یکسان از هر دو جلسه.
۶. ADMIN_AUTH_MAX در env تست CI + جداسازی seed داده‌ی e2e-admin (ریشه‌ی flake امروز).

### ۶-۷. جدول تصمیم بازبینی واژه‌های ⚑ (1.13.0 — به نیابت کاربر)

۳۹ از ۴۰ واژه‌ی پرچم‌خورده مرور و تأیید شدند؛ تنها یک واژه رد و جایگزین گردید:

| واژه | زبان/حرف | تصمیم | دلیل |
|---|---|---|---|
| `umut` (امید) | tr · u | ❌ رد → جایگزین با `uçurtma` 🪁 (بادبادک) | انتزاعی — برای ۴-۶ سال تصویرپذیر نیست؛ بادبادک ملموس، آشنا، d3، ۷ حرف، هم‌حرف |
| ۳۹ واژه‌ی دیگر (fa ثروت/ثمر/ذوق/ژتون/ظریف · en question/quilt/x-ray · nl iglo/uil/uno · tr ıhlamur/uçak · …) | — | ✅ تأیید | یا تصویرپذیری/آشنایی کافی دارند یا جایگزین بهتری در خانواده‌ی حرف موجود نیست |

**اثر:** tr.json → ۱۴۱ واژه (جایگزینی +۱) · جمع کل **۷۱۹** · `REVIEWED_WORDS` در `scripts/content-sprint.mjs` فهرست ۳۹ تأیید را نگه می‌دارد تا پرچم‌ها ۰ شوند و واژه‌ی جدید حروف نادر در آینده خودکار پرچم بخورد · داستان‌ها از `umut` استفاده نمی‌کردند (جایگزینی امن؛ tests: packs 34/34 · story 19/19).

---

## ۷. جمع‌بندی

این پروژه از میانگین پروژه‌های این اندازه **نظم‌مندتر** است: هر فیچر تست دارد، هر تصمیم سند دارد، هر عقب‌نشینی (بودجه‌ی ۸۳، پوشش شاخه ۶۰) مستند و دلیل‌دار است، و ابزارسازی (محتوا، پایلوت، بکاپ) برای تکرارپذیری ساخته شده نه فقط برای دمو. دو ضعف بنیادی اما کاملاً صادقانه باقی است: **محصول با کودک واقعی آزمایش نشده**، و **نیمی از کد (کلاینت) ادعای پوشش ندارد**. موج ۲ بخشی که می‌شد بدون انسان انجام داد را بست — شماره‌ها همه سبزند؛ حالا نوبت چیزی است که هیچ تستی جایگزینش نمی‌شود: پشت میز، روبروی یک کودک ۵ ساله نشستن.

**وضعیت موج ۲:** §۲.۲ ✅ · §۲.۳ ابزار ✅ / اجرا با کاربر ⏳ · §۲.۴ خودکار ✅ / صفحه‌خوان دستی ⏳ · §۲.۵ ✅ · §۲.۱ جلسات ⏳ (فقط کاربر).

**بسته‌شدنی‌های 1.13.0:** واژه‌های ⚑ ✅ (§۶-۷) · a11y در CI ✅ · تست دو-دستگاه ✅ · ریشه‌ی flake ادمین تشخیص شد (فقط محلی؛ CI از قبل ADMIN_AUTH_MAX=200 دارد — اقدامی لازم نبود). باقی‌مانده‌ی فقط-کاربر: تأیید نهایی واژه‌ها · ۵ جلسه‌ی کودک (§۲.۱) · VoiceOver/NVDA · اجرای پایلوت.
