Commit Graph

9 Commits

Author SHA1 Message Date
a973c41db2 Security review fixes: admin permissions, guest sessions, payment edge cases, assistant leaks
- Admin: refund/cancel/mark-resolved/Bazaar-link actions need change permission; question and
  curriculum import need add/delete; content browser needs view_question; guest device ids are
  shown to superusers only.
- Accounts: registering a guest's phone revokes the guest's earlier sessions; self-deletion keeps
  Redemption, UserOffer and the phone's OTP rows; the public demo guest cannot be deleted
  (DEMO_GUEST_DEVICE_IDS); display-name contact filter covers any separator and social handles.
- Payment: callback without Authority is 400; a second Bazaar purchase on a paid order is 409;
  orders snapshot credits/hearts/days at creation (payment.0011).
- Assistant: a broken diagram no longer makes a streamed answer free; a late off-topic marker
  refuses the answer (not stored, not cached); a disconnect saves the partial answer; only
  KNOWN_COLLECTIONS are searched.
- Infra: secret-key file is created atomically (workers no longer split keys); no default
  INTERNAL_SERVICE_KEY; Kavenegar key and Bazaar token kept out of error logs; Swagger/ReDoc
  pinned; schema throttled; docker compose bound to 127.0.0.1; non-ASCII digit ids are 400;
  ticket text capped at 5000.
- docs/security-before-production.md: remaining open items 24-31 and the guard tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:52:25 +03:30
4393087fa7 wait up to 10 s to reach Kavenegar and 30 s for its reply
Iranian network paths can be slow; the owner asked for 30 s. The frontend's
requestOtp timeout goes to 45 s in the same change so it outlasts both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 22:14:23 +03:30
ca46e66024 keep the login code when Kavenegar answers late instead of failing the request
Seen live on 2026-09-27: Kavenegar took 5.4 s, our 5 s timeout fired, the
API answered 503 and deleted the code, but the SMS arrived, so the site
said "service unavailable" while the phone held a code that no longer
worked. A read timeout now means "delivery unknown": the code is kept and
the request succeeds (the cooldown still blocks a second SMS). A failed
connection is still an explicit 503. Read timeout raised to 10 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 22:06:34 +03:30
f6cdfddaa9 record the 2026-09-26 Bazaar fix deploy: bdd5aba live, authorize link sent
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 22:01:39 +03:30
0580aec7b0 harden OTP for real SMS and close the second audit round
Kavenegar is being switched on, so every OTP request now costs credit:
- phone numbers are normalised to 09XXXXXXXXX everywhere (login, OTP,
  family invite, TEST_LOGIN_PHONES keys) and existing rows are migrated;
  non-Iranian and landline numbers are rejected before any SMS
- cooldown and a daily per-phone cap are counted in the database, so the
  three gunicorn workers no longer triple them
- a global daily OTP SMS cap (default 300) stops SMS pumping
- per-IP rates widened for CGNAT / school Wi-Fi (env-overridable)
- provider message id is logged; SMS text warns not to share the code

Second audit round: an offer no longer shortens a longer paid plan,
Zarinpal error bodies no longer 500, island XP reaches the parent report,
a non-numeric questionId no longer 500s after the answer is generated.

596 tests green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:28:06 +03:30
683bd40169 cleanup: trim bloated multi-line comments across the project 2026-08-26 03:22:20 +03:30
a9200772a3 Add campaigns/ Add supervisor/ Add messaging features/ Separate SMS 2026-08-25 03:39:41 +03:30
80298b47b1 throttling, abuse-protection & logging/monitoring pass 2026-08-23 23:44:00 +03:30
cb18c93a3e Harden auth, AI tutor, payments, and subscriptions 2026-08-22 04:42:36 +03:30