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

@@ -296,7 +296,7 @@ export function createClient(options: ClientOptions = {}) {
/* ── صفحه‌ی خانه و نقشه‌ی مهارت ────────────────────────────────────── */
/** بدونِ gradeId، پایه‌ی ذخیره‌شده‌ی خودِ کاربر ملاک است. */
home: (gradeId?: number) =>
raw<HomeResponse>('GET', gradeId ? `/home?grade=${gradeId}` : '/home'),
raw<HomeResponse>('GET', gradeId ? `/home?gradeId=${gradeId}` : '/home'),
summary: () => raw<UserSummary>('GET', '/user/summary'),
hearts: () => raw<Hearts>('GET', '/user/hearts'),
streakCalendar: () =>