Remove silent fallbacks found in the 2026-10-03 audit
- /api/ai/ask: the stub answer is reachable only under DEBUG or RAG_FORCE_MOCK. Without RAG keys on the server it used to return 200 with "this is a stub, set OPENAI_API_KEY" and spend the student's quota; now 503. - /api/home: the `grade` alias is gone and sending it is a 400 instead of a silent fallback to the user's own grade. No client sent it. - activate_subscription logs ERROR when the paid order's plan no longer exists (it silently became 30 days). - resolve_grade_title logs instead of `except: pass`; curriculum_io no longer reads an `intro_text` key no file contains. - CLAUDE.md: "No silent fallbacks" rules for future agents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -253,7 +253,7 @@ def _node_status(lesson_ids, completed_ids, is_first_unlocked_candidate, quiz_co
|
||||
|
||||
|
||||
class HomeView(APIView):
|
||||
"""GET /api/home?grade — نقشهی مهارتها + آمار (ادغامشده)"""
|
||||
"""GET /api/home?gradeId — نقشهی مهارتها + آمار (ادغامشده)"""
|
||||
|
||||
# userId همیشه از request.user.id (توکن معتبر) گرفته میشود، نه ورودی کلاینت (IDOR).
|
||||
permission_classes = [IsAuthenticated]
|
||||
@@ -265,8 +265,6 @@ class HomeView(APIView):
|
||||
OpenApiParameter('gradeId', OpenApiTypes.INT, required=False,
|
||||
description='پایهای که نقشهاش خواسته میشود؛ '
|
||||
'بدونِ آن، پایهی ذخیرهشدهی خودِ کاربر.'),
|
||||
OpenApiParameter('grade', OpenApiTypes.INT, required=False,
|
||||
deprecated=True, description='نامِ قدیمیِ gradeId.'),
|
||||
],
|
||||
responses=HomeResponseSerializer,
|
||||
tags=['Curriculum (content)'],
|
||||
@@ -278,13 +276,12 @@ class HomeView(APIView):
|
||||
# خودِ کاربر نادیده میماند؛ نتیجه این بود که اپ در «آشنایی» پایه را ثبت
|
||||
# میکرد و بعد صفحهی خانه خالی برمیگشت. حالا پارامتر اولویت دارد (برای
|
||||
# مرورِ پایهی دیگر) و در نبودش پایهی خودِ کاربر ملاک است.
|
||||
# هر دو نام پذیرفته میشوند. نامِ درست `gradeId` است — با بقیهی API
|
||||
# یکی است (profile و /user/grade هم gradeId میگویند) — ولی نسخهی
|
||||
# اولِ این اندپوینت `grade` بود و کلاینتهایی با همان بیرون رفتهاند.
|
||||
# پذیرفتنِ هر دو ارزان است؛ نپذیرفتن یعنی انتخابِ پایه بیصدا نادیده
|
||||
# گرفته میشود و کاربر نقشهی پایهی دیگری را میبیند.
|
||||
grade_param = (request.query_params.get('gradeId')
|
||||
or request.query_params.get('grade'))
|
||||
# فقط `gradeId` (همنام با بقیهی API). نامِ قدیمیِ `grade` در ۲۰۲۶-۱۰-۰۳
|
||||
# حذف شد: تنها کلاینت (MathApp_frontend) آن را نمیفرستد. فرستادنش ۴۰۰ است،
|
||||
# نه نادیده گرفتنِ بیصدا (که کاربر را به نقشهی پایهی خودش میبرد).
|
||||
if 'grade' in request.query_params:
|
||||
raise ValidationError({'grade': 'این پارامتر حذف شده؛ gradeId بفرستید.'})
|
||||
grade_param = request.query_params.get('gradeId')
|
||||
if grade_param:
|
||||
try:
|
||||
grade_id = int(grade_param)
|
||||
|
||||
Reference in New Issue
Block a user