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:
2026-10-03 10:38:42 +03:30
parent 7e4b8b54a6
commit 7307bfcadb
10 changed files with 98 additions and 24 deletions

View File

@@ -7,8 +7,12 @@
(کاربر قبلاً با اسمِ نادرست به مشکل خورده بود). کلیدِ فیلترِ درس/فصل خودکار
از روی subject انتخاب می‌شه — نگاه کنید به rag/services/known_collections.py.
"""
import logging
from django.conf import settings
logger = logging.getLogger(__name__)
def rag_is_configured() -> bool:
return bool(
@@ -39,8 +43,9 @@ def resolve_grade_title(grade_id, fallback: str = '') -> str:
grade = Grade.objects.filter(pk=grade_id).only('title').first()
if grade is not None:
return normalize_grade_title(grade.title)
except Exception:
pass
except Exception: # noqa: BLE001
# پیش‌تر `pass` بود: خطای دیتابیس retrieval را بی‌صدا خالی می‌کرد.
logger.exception('resolve_grade_title: خواندنِ پایه‌ی %s شکست خورد', grade_id)
return fallback