feat(bot): add strict whitelist auth bypass, multi-STT consensus pipeline, and applicant logging
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
# گزارش جامع: اعتبارسنجی گزارشها و راهکار کرال موتور STT بله
|
||||
|
||||
> **تاریخ:** ۱۵ مهر ۱۴۰۵
|
||||
> **موضوع:** افزودن متن تولیدشده توسط قابلیت «تبدیل ویس به متن» پیامرسان بله بهعنوان یک کاندید در خطلوله چندمدله STT بات تدارکات
|
||||
> **ورودیها:** سه سند ارائهشده (تحلیل جامع، پلیبوک اجرایی، تحلیل مقایسهای) + راستیآزمایی مستقل وب
|
||||
> **محدودیت:** `integration_report` شماره ۱ و ۲ در دسترس من نبود و فقط از روی نقلقولهای همین اسناد قضاوت شدهاند. دستورهای کشف (بخش ۴) در محیط من اجرا نشدهاند، چون شبکه sandbox بسته بود.
|
||||
|
||||
---
|
||||
|
||||
## ۱. خلاصه مدیریتی
|
||||
|
||||
1. **Bot API رسمی بله STT ندارد.** همه اسناد در این مورد درست میگویند.
|
||||
2. **تناقض اصلی** (مهندسی معکوس «غیرعملی است» در برابر «ساده است») هیچکدام کاملاً درست نیست. مسیر شدنی است، ولی «افزودن یک متد» نیست و نیاز به یک فاز کشف دارد.
|
||||
3. **دو فرض اثباتنشده** کل مسیر را تحت تأثیر قرار میدهد:
|
||||
- دکمه «تبدیل به متن» روی **وب** بله وجود دارد (هر سه سند فرض کردهاند، هیچ منبعی تأیید نکرده).
|
||||
- پکیج `aiobale-py` نسخه 0.3.9 فعال است (پیدا نشد؛ به بخش ۲ مراجعه کنید).
|
||||
4. **کشف جدید:** پکیج `bale-sdk` با ۶۰۷ RPC تایپشده و پروتوهای بازیابیشده. احتمال وجود RPC ترنسکریپشن در آن بالاست. ولی مجوز آن اختصاصی است.
|
||||
5. **بزرگترین صرفهجویی:** آزمون دقت را **قبل از ساخت** و بهصورت **دستی** روی ۳۰ ویس واقعی انجام دهید. اگر بله از خطلوله فعلی بهتر نبود، پروژه لازم نیست.
|
||||
6. **ریسک حقوقی/ToS** (استفاده خودکار از حساب کاربری) تصمیم مدیریتی است و باید قبل از استقرار روشن شود.
|
||||
|
||||
---
|
||||
|
||||
## ۲. اعتبارسنجی گزارشها
|
||||
|
||||
### ۲.۱ جدول ادعاها
|
||||
|
||||
| ادعا | نتیجه | توضیح |
|
||||
|---|---|---|
|
||||
| Bot API رسمی STT ندارد | ✅ تأیید | پروبها همگی ۴۰۴ دادهاند و تایپهای SDKها برای Voice فقط شناسه فایل و مدتزمان دارند. **تذکر:** ۴۰۴ برای نامهای حدسی چیزی درباره فیلد مخفی در payload نمیگوید؛ تست T1 (ویس به یک بات تستی و خواندن JSON کامل) هنوز لازم است (۳۰ دقیقه). |
|
||||
| بله قابلیت تبدیل ویس به متن دارد | ✅ با شرط | نسخه جدید بله این قابلیت را برای اندروید و iOS منتشر کرده. وجود دکمه در **وب** تأییدنشده است و ریسک اصلی مسیر Playwright همین است. |
|
||||
| مهندسی معکوس «غیرعملی» است (گزارش ۲) | ⚠️ بدبینانه | کلاینتهای متنباز مهندسیمعکوسشده وجود دارند. اما استدلال «Protobuf خودتوصیف است» نادرست است: wire format بدون `.proto` فقط تا حدی (شماره فیلد و نوع خام، بدون نام و معنا) دیکود میشود. |
|
||||
| مهندسی معکوس «در حد افزودن یک متد» است (پلیبوک) | ⚠️ خوشبینانه | کشف RPC، نگاشت فیلدها و پایداری نشست کار واقعی است. تخمین «نیمروز» برای T2 ریسکی است. |
|
||||
| `aiobale-py` v0.3.9 فعال است و نام `aiobale` را پکیج خالی گرفته | ❌ تأییدنشده / احتمالاً غلط | `aiobale-py` را پیدا نکردم. `aiobale` یک کتابخانه واقعی است (MIT، مستندات `docs.aiobale.ir`، نسخههای 0.1.x). فورکهایی مثل Autobale میگویند نسخه اصلی نگهداری نمیشود و باگ دارد. قبل از وابستگی به هر نام، `pip index versions` را اجرا کنید. |
|
||||
| `bale-sdk` (کشف جدید) | 🔎 مهم | از کلاینت وب بله مهندسی معکوس شده؛ ۶۰۷ RPC در ۵۲ سرویس، پروتوهای بازیابیشده، احراز با JWT یا OTP؛ نسخه 0.1.1 (ژوئن ۲۰۲۶). **مجوز اختصاصی و «همه حقوق محفوظ»**. |
|
||||
| تأخیر «زیر ۱ ثانیه» | ❌ رد | همه موافقند. اعداد ۱–۴ ثانیه (R2) و ۴–۸ ثانیه (Playwright) هم **اندازهگیری نشدهاند**؛ فقط T5 عدد واقعی میدهد. |
|
||||
| AI Chat بله ویس را «پیاده» میکند (R3) | ⚠️ تأییدنشده و نامطلوب | حتی اگر درست باشد، خروجی «متن + تفسیر مدل» است و برای consensus مناسب نیست. با کنار گذاشتن موافقم. |
|
||||
| RAM ۳۵۰–۵۰۰ مگابایت برای Playwright | ✅ معقول | برای بات تککاربره قابلتحمل است. |
|
||||
| Playwright در ۱–۲ روز | ⚠️ خوشبینانه | وابسته به وجود دکمه وب، چالشهای ورود و پایداری سلکتورها. |
|
||||
| ساختار Gate / State-machine پلیبوک | ✅ قوی | بهترین بخش اسناد. ایراد: دروازه دقت (T7) بعد از ساخت آمده، در حالی که دستی و قبل از ساخت شدنی است. |
|
||||
| ریسک بن، ToS و حریم خصوصی | ✅ درست و حیاتی | فقط پلیبوک به آن پرداخته است. |
|
||||
| ترجیح WebSocket به POST gRPC (پلیبوک) | ✅ منطقی | کلاینت رسمی بله POST gRPC را عمدتاً برای چند متد احراز هویت استفاده میکند؛ استفاده زیاد از آن غیرعادی به نظر میرسد. |
|
||||
| «Playwright اول» (سند مقایسهای) در برابر «R2 اول» (پلیبوک) | ⚠️ هر دو مشروط | بدون نتیجه کشف روز اول قابل تصمیم نیست. |
|
||||
|
||||
### ۲.۲ ایرادهای کد adapter در سند اول
|
||||
|
||||
- کلید پیشفرض ضعیف (`bale_secure_token`) و مقایسه کلید با `!=` بهجای مقایسه ثابتزمان.
|
||||
- بلعیدن همه استثناها بدون لاگ.
|
||||
- بازگرداندن ۲۰۰ با متن خالی: ممکن است بات آن را یک کاندید معتبر (خالی) در consensus بشمارد. باید در `bot/app/stt.py` بررسی شود که پاسخ ۵xx و متن خالی چطور مدیریت میشوند. توصیه: در خطا ۵۰۳ برگردد.
|
||||
- نبود قفل ترتیبی، سقف روزانه و تأخیر تصادفی در خود adapter.
|
||||
|
||||
### ۲.۳ نکات فنی اصلاحشده
|
||||
|
||||
- فریم gRPC-Web پیشوند ۵ بایتی دارد (۱ بایت فلگ + ۴ بایت طول). این برای **POST gRPC-Web** درست است؛ اینکه فریمهای WebSocket بله هم همان قالب را دارند فرض اثباتنشدهای است و باید در T2 دیده شود.
|
||||
- هاستها و نام ماژولهایی مثل `maviz-ws.bale.ai` و `SpeechTranscript` از تحلیل باندل آمدهاند و در وب ایندکس نشدهاند. باید با چشم در کپچر تأیید شوند.
|
||||
|
||||
---
|
||||
|
||||
## ۳. راهکارها
|
||||
|
||||
| راهکار | توضیح | رم | خلوص متن | ریسک | حکم |
|
||||
|---|---|---|---|---|---|
|
||||
| **A. مسیر رسمی** | درخواست API یا همکاری از بله | — | — | — | هزینه صفر؛ قبل از هر کار غیررسمی یک ایمیل بزنید |
|
||||
| **B. RPC مستقیم** | کلاینت کاربری روی WebSocket با `bale-sdk` یا `aiobale` + RPC ترنسکریپت | ≈ ۲۰ MB | خالص | متوسط (تغییر پروتکل، بن) | **بهترین نتیجه فنی**، مشروط به کشف RPC |
|
||||
| **C. Playwright** | Chromium headless روی `web.bale.ai` با پروفایل پایدار | ۳۵۰–۵۰۰ MB | خالص | کم–متوسط | مقاوم، **فقط اگر دکمه وب موجود باشد** |
|
||||
| **D. AI Chat** | ویس به چت هوش مصنوعی بله و استخراج از پاسخ | ≈ ۲۰ MB | ❌ متن + تفسیر | بالا | کنار گذاشته شود |
|
||||
| **E. سرویس ثالث** | پروکسیهای STT با ادعای بله | — | نامشخص | حریم خصوصی/پایداری | کنار گذاشته شود |
|
||||
| **F. اندروید امولاتور** | اپ بله + uiautomator | زیاد | خالص | بالا (شکننده) | آخرین چاره اگر B و C ممکن نشد |
|
||||
|
||||
---
|
||||
|
||||
## ۴. مسیر دقیق اجرا
|
||||
|
||||
### گام ۰: آزمون دقت دستی (نیمروز، بدون کد)
|
||||
|
||||
۳۰ ویس واقعی تدارکاتی (با رضایت فرستندگان؛ صداها را بلندمدت نگه ندارید) را در اپ بله دستی به متن تبدیل کنید و سه حالت را مقایسه کنید:
|
||||
|
||||
1. خروجی فعلی بات (whisper/سایرین + consensus)
|
||||
2. فقط متن بله
|
||||
3. consensus با اضافهشدن بله
|
||||
|
||||
سه معیار: WER متن، دقت استخراج اقلام (نام کالا، برند، تعداد، واحد) و تعداد موارد سخت لهجهای که با بله درست شدهاند.
|
||||
|
||||
**معیار پیشنهادی:** کاهش نسبی خطای استخراج حدود ۱۵٪ یا بیشتر، یا حل حداقل ۲ مورد سخت. در غیر این صورت **STOP**.
|
||||
|
||||
### گام ۱: کشف سریع (حدود ۳۰ دقیقه)
|
||||
|
||||
```bash
|
||||
python -m venv .v && . .v/bin/activate
|
||||
pip index versions aiobale-py # وجود یا عدم وجود را بررسی کنید
|
||||
pip download bale-sdk --no-deps --no-binary :all: && tar xzf bale_sdk-*.tar.gz
|
||||
grep -rniE "transcri|speech|asr|stt" bale_sdk-*/proto bale_sdk-*/docs | head -50
|
||||
```
|
||||
|
||||
همچنین در پایتون `from bale import ALL_RPCS` را با همان کلیدواژهها فیلتر کنید.
|
||||
|
||||
همزمان **T1**: یک بات تستی مستقل بسازید، یک ویس بفرستید و JSON کامل آپدیت را بخوانید. اگر فیلد ترنسکریپشن وجود داشت، پروژه کرالر لازم نیست.
|
||||
|
||||
### گام ۲: وب و کپچر (نیمروز تا یک روز)
|
||||
|
||||
1. با **یک حساب اختصاصی شرکت** روی `web.bale.ai` وارد شوید و بررسی کنید دکمه «تبدیل به متن» روی ویس هست یا نه (روی ویس دریافتی و ارسالی).
|
||||
2. DevTools تب Network را با Preserve log و فیلتر WS و Fetch/XHR ضبط کنید و هنگام کلیک روی دکمه ذخیره کنید:
|
||||
- URL کامل و ترابری (unary یا WS)
|
||||
- هدر احراز
|
||||
- `req.bin` و `resp.bin`
|
||||
- زمان پاسخ (همان تأخیر واقعی ASR)
|
||||
3. ۵ تا ۱۰ ویس متنوع (کوتاه، بلند، لهجهدار) را تکرار کنید و در `findings.md` خلاصه کنید.
|
||||
4. دیکود آفلاین: پیشوند ۵ بایتی را بردارید، سپس `protoc --decode_raw` یا `protoscope`.
|
||||
|
||||
### گام ۳: انتخاب مسیر
|
||||
|
||||
| وضعیت | مسیر |
|
||||
|---|---|
|
||||
| RPC در `bale-sdk` یا کپچر پیدا شد | **B** |
|
||||
| RPC پیدا نشد ولی دکمه وب هست | **C** |
|
||||
| هیچکدام | **F** یا توقف |
|
||||
| ترنسکرایب نیاز به امضا یا اثر انگشت مرورگر دارد | **C** |
|
||||
|
||||
**الگوی پیشنهادی برای B:** بات خودتان با `sendVoice(file_id)` ویس را برای حساب کرالر بفرستد (کرالر یکبار بات را `/start` کرده). اینطور نیازی به دانلود و آپلود مجدد نیست و `message_id` بومی در اختیار کرالر است. پس از دریافت متن، پیام حذف شود. اگر RPC به `message_id` نیاز نداشت، مستقیم فایل یا بایت داده شود.
|
||||
|
||||
**مجوز:** `aiobale` مجوز MIT دارد ولی نگهداری نمیشود (فورکها: Autobale و BaleClient). `bale-sdk` مجوز اختصاصی دارد؛ برای استفاده تجاری از نویسنده اجازه بگیرید.
|
||||
|
||||
### گام ۴: ساخت adapter سختشده
|
||||
|
||||
قرارداد OpenAI-compatible (همان `POST /v1/audio/transcriptions` که بات انتظار دارد) و موتور قابلسوییچ با `BALE_STT_ENGINE=grpc|playwright`. پیشنهاد کد:
|
||||
|
||||
```python
|
||||
import os, secrets, asyncio, logging
|
||||
from fastapi import FastAPI, File, Form, Header, HTTPException, UploadFile
|
||||
|
||||
log = logging.getLogger("bale-stt")
|
||||
app = FastAPI()
|
||||
KEY = os.environ["BALE_STT_INTERNAL_KEY"] # بدون مقدار پیشفرض
|
||||
DAILY_CAP = int(os.environ.get("BALE_STT_DAILY_CAP", "100"))
|
||||
lock = asyncio.Lock() # اجرای ترتیبی
|
||||
count_today = 0 # در عمل با ریست روزانه
|
||||
|
||||
@app.get("/healthz")
|
||||
def healthz():
|
||||
return {"status": "ok"}
|
||||
|
||||
@app.post("/v1/audio/transcriptions")
|
||||
async def transcribe(file: UploadFile = File(...), model: str = Form("bale-stt"),
|
||||
language: str = Form("fa"), authorization: str = Header("")):
|
||||
if not secrets.compare_digest(authorization, f"Bearer {KEY}"):
|
||||
raise HTTPException(401)
|
||||
if count_today >= DAILY_CAP:
|
||||
raise HTTPException(429)
|
||||
async with lock:
|
||||
try:
|
||||
text = await run_engine(await file.read()) # + تأخیر تصادفی ۱ تا ۳ ثانیه
|
||||
except Exception:
|
||||
log.exception("bale stt failed")
|
||||
raise HTTPException(503) # تا بات فقط همین کاندید را حذف کند
|
||||
if not text:
|
||||
raise HTTPException(503)
|
||||
return {"text": text}
|
||||
```
|
||||
|
||||
اتصال به بات (بدون تغییر کد):
|
||||
|
||||
```env
|
||||
PROCUREMENT_BOT_STT_PROVIDER_3_NAME=bale
|
||||
PROCUREMENT_BOT_STT_PROVIDER_3_BASE_URL=http://bale-stt:8080/v1
|
||||
PROCUREMENT_BOT_STT_PROVIDER_3_API_KEY=<INTERNAL_KEY>
|
||||
PROCUREMENT_BOT_STT_PROVIDER_3_MODEL=bale-stt
|
||||
PROCUREMENT_BOT_STT_PROVIDER_3_LANGUAGE=fa
|
||||
```
|
||||
|
||||
> پرووایدر فقط وقتی فعال میشود که هم `BASE_URL` و هم `API_KEY` پر باشند.
|
||||
|
||||
### گام ۵: عملیات و ایمنی
|
||||
|
||||
- فقط **شماره اختصاصی شرکت**؛ هرگز شماره شخصی.
|
||||
- `session_file` یا پروفایل مرورگر روی ولوم داکر و هرگز در گیت.
|
||||
- **OTP تنها گام انسانی** است. در ابطال نشست: هشدار به ادمین و هدایت ترافیک به سایر پرووایدرها.
|
||||
- اجرای ترتیبی، فاصله تصادفی ۱ تا ۳ ثانیه، سقف روزانه، و ترجیح WebSocket به POST gRPC.
|
||||
- حذف فوری پیام اسکرچ پس از استخراج و عدم نگهداری فایل صوتی روی دیسک.
|
||||
- پایش: نرخ موفقیت، p50 و p95 تأخیر، انواع خطا، وضعیت نشست. هشدار اگر نرخ خطا در ۳۰ دقیقه بیش از ۲۰٪ شد.
|
||||
- **Rollback:** خالی کردن `STT_PROVIDER_3_*` در env بات و توقف کانتینر. بات فوراً به وضعیت قبل برمیگردد.
|
||||
- سکرتهایی که در `docker-compose.yml` کامیت شدهاند (توکن بات، کلید DeepSeek) باید rotate شوند و `DRAFT_TOKEN_SECRET` پیشفرض ضعیف را عوض کنید.
|
||||
- روی برنچهای دیگران (`prod-v7` و غیره) دخالت نکنید و بدون تأیید مالک چیزی پوش نشود.
|
||||
|
||||
### گام ۶: اندازهگیری و سواک
|
||||
|
||||
- **T5:** ۵۰ تا ۱۰۰ ویس ترتیبی با فاصله انسانی؛ پذیرش پیشنهادی: موفقیت ≥ ۹۵٪ و p95 ≤ ۸ ثانیه.
|
||||
- **سواک یکهفتهای** با حجم کم (حدود ۱۰۰ ترنسکرایب در روز): ثبت تعداد ورود مجدد، چالشهای امنیتی و عمر واقعی توکن.
|
||||
|
||||
---
|
||||
|
||||
## ۵. دروازههای تصمیم (خلاصه)
|
||||
|
||||
| دروازه | شرط عبور | در صورت شکست |
|
||||
|---|---|---|
|
||||
| G0 دقت دستی | بهبود ≈ ۱۵٪ یا ۲ مورد سخت | **STOP** |
|
||||
| G1 (T1) | فیلد ترنسکریپشن نبود | اگر بود: پایان، مستقیم وصل شود |
|
||||
| G2 کشف | RPC یا دکمه وب پیدا شد | F یا توقف |
|
||||
| G3 پروتوتایپ | درخواست ساخته و پاسخ خوانده شد | سوییچ به C |
|
||||
| G4 نرخ و پایداری | ≥ ۹۵٪ موفقیت، p95 ≤ ۸ ثانیه | کاهش نرخ و backoff؛ در صورت بن: توقف |
|
||||
| G6 ToS | تصمیم مکتوب مدیریت | **STOP** یا حجم بسیار محدود |
|
||||
| G7 سواک | نشست سالم یک هفته | rollback و بازگشت به G4 |
|
||||
|
||||
---
|
||||
|
||||
## ۶. زمانبندی واقعبینانه
|
||||
|
||||
| مرحله | زمان |
|
||||
|---|---|
|
||||
| گام ۰ و ۱ (دقت دستی + کشف سریع) | نیمروز |
|
||||
| گام ۲ (وب و کپچر) | ۱ روز |
|
||||
| ساخت B یا C | ۲ تا ۴ روز |
|
||||
| T5 و سواک | ۱ هفته |
|
||||
|
||||
---
|
||||
|
||||
## ۷. رجیستر ریسک
|
||||
|
||||
| ریسک | احتمال | اثر | مقابله |
|
||||
|---|---|---|---|
|
||||
| بن یا rate-limit حساب | متوسط | توقف مسیر | حجم کم، WS-first، سقف روزانه، حساب اختصاصی قابلتعویض |
|
||||
| تغییر پروتکل یا UI بله | متوسط | قطع سرویس | هشدار خطا، فالبک، سوییچ موتور با env، rollback با env |
|
||||
| انقضای نشست و نیاز به OTP | بالا (دورهای) | توقف موقت | ولوم نشست + هشدار + runbook ورود انسانی |
|
||||
| دکمه وب وجود ندارد | نامعلوم | ناممکنشدن C | بررسی در گام ۲ قبل از ساخت |
|
||||
| دقت ناکافی نسبت به هزینه | نامعلوم | هزینه بیفایده | G0 قبل از ساخت |
|
||||
| ToS / مسائل حقوقی | نامعلوم | توقف اجباری | تصمیم مکتوب مدیریت (G6)؛ ایمیل به بله (A) |
|
||||
| مجوز اختصاصی `bale-sdk` | بالا | ممنوعیت استفاده | اجازه از نویسنده یا استفاده از `aiobale` (MIT) |
|
||||
| حریم خصوصی صدا | کم | اعتباری | حذف فوری پیامها، عدم نگهداری فایل |
|
||||
| وابستگی به یک فرد نگهدارنده | متوسط | رکود | مستندسازی و مالک رسمی |
|
||||
|
||||
---
|
||||
|
||||
## ۸. دروازههای انسانی
|
||||
|
||||
1. OTP ورود حساب (بار اول و هر انقضا).
|
||||
2. تصمیم ToS / حقوقی.
|
||||
3. جمعآوری نمونه ویس واقعی با رضایت.
|
||||
4. تأیید نهایی استقرار و مرج توسط مهندس ارشد.
|
||||
|
||||
---
|
||||
|
||||
## ۹. توصیه نهایی
|
||||
|
||||
1. **همین هفته:** گام ۰ (دقت دستی) + ایمیل به بله + گام ۱ (کشف سریع و T1).
|
||||
2. **اگر دقت توجیه داشت:** گام ۲ و انتخاب B یا C بر اساس شواهد.
|
||||
3. **معماری:** adapter با قرارداد OpenAI و موتور قابلسوییچ؛ بات دستنخورده میماند.
|
||||
4. **تصمیم مدیریتی** درباره ToS قبل از استقرار.
|
||||
5. اگر هر کدام از G0 یا G6 شکست خورد، **توقف** و ادامه با پرووایدرهای فعلی.
|
||||
|
||||
---
|
||||
|
||||
## منابع
|
||||
|
||||
- aiobale (PyPI): https://pypi.org/project/aiobale
|
||||
- bale-sdk (PyPI): https://pypi.org/project/bale-sdk/
|
||||
- Autobale (فورک aiobale): https://pypi.org/project/autobale/
|
||||
- خبر انتشار نسخه بله با قابلیت تبدیل پیام صوتی به متن (خبرگزاری آنا): https://ana.ir/fa/news/994908
|
||||
- مستندات رسمی بات بله: https://docs.bale.ai
|
||||
Reference in New Issue
Block a user