
hamedandClaude Opus 4.8
af125572c9
feat(doctor): complete IRIMC import feature — claim flow, least-privilege importer, unique import key
- Extract import logic from AdminApiController into DoctorImportService
(thin DoctorImportController keeps the same route/contract)
- Surrogate users get marker role ROLE_UNCLAIMED_DOCTOR (+ backfill command
app:doctors:backfill-surrogate-role) enabling safe deletion after claim
- DB-level UNIQUE (source, medical_system_code) + concurrent-import retry
- Doctor profile claim flow (climed.md): shahkar + PersonInfo identity checks
via existing ApiIrService, Persian name normalization (PersianText),
pessimistic-lock race protection, DoctorClaimRequest audit table
(national code hashed, mobile masked), doctor_claim rate limiter,
public claim-info endpoint, welcome SMS
- Admin support tools: manual transfer endpoint + paginated doctor-claims
audit list + owner_status filter/fields in admin doctors list
- Least privilege: system owner now gets ROLE_IMPORTER (ROLE_ADMIN stripped),
import endpoint accepts ADMIN|IMPORTER, isStaff includes IMPORTER
- Headless crawler login: X-Service-Token header bypasses captcha only
(rate limit + password checks intact; empty env = no bypass)
- docs: doctor-claim.md (new), doctor-import.md, admin.md, doctor.md
- tests: DoctorImportTest (6), DoctorClaimTest (11), PersianTextTest (5)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 11:39:15 +03:30
..
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-09 22:00:34 +03:30
2026-06-10 10:03:46 +03:30
2026-06-10 13:02:47 +03:30
2026-06-10 14:22:26 +03:30
2026-06-10 14:32:00 +03:30
2026-06-10 14:45:01 +03:30
2026-06-10 14:45:01 +03:30
2026-06-10 15:09:19 +03:30
2026-06-28 09:32:27 +03:30
2026-06-10 21:29:29 +03:30
2026-06-10 22:13:39 +03:30
2026-06-28 09:32:27 +03:30
2026-06-11 12:20:12 +03:30
2026-06-11 12:20:12 +03:30
2026-06-12 12:31:27 +03:30
2026-06-12 13:39:37 +03:30
2026-06-14 22:10:28 +03:30
2026-06-14 22:10:28 +03:30
2026-06-14 22:10:28 +03:30
2026-06-14 22:10:28 +03:30
2026-06-14 22:10:28 +03:30
2026-06-14 22:10:28 +03:30
2026-06-15 11:03:56 +03:30
2026-06-15 11:03:56 +03:30
2026-06-15 11:19:37 +03:30
2026-06-15 17:53:27 +03:30
2026-06-16 00:25:59 +03:30
2026-06-19 10:19:47 +03:30
2026-06-19 20:42:04 +03:30
2026-06-19 20:42:04 +03:30
2026-06-21 12:35:22 +03:30
2026-06-21 13:26:47 +03:30
2026-06-22 19:44:17 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 15:05:24 +03:30
2026-06-23 16:10:36 +03:30
2026-06-23 22:13:51 +03:30
2026-06-24 11:52:13 +03:30
2026-06-24 13:06:17 +03:30
2026-06-24 13:17:08 +03:30
2026-06-24 16:14:41 +03:30
2026-06-25 17:34:39 +03:30
2026-06-25 19:38:47 +03:30
2026-06-28 17:04:23 +03:30
2026-06-28 17:13:44 +03:30
2026-06-28 19:04:54 +03:30
2026-06-28 19:08:26 +03:30
2026-06-28 19:10:53 +03:30
2026-06-28 20:28:24 +03:30
2026-06-28 21:03:54 +03:30
2026-06-29 20:01:03 +03:30
2026-07-02 10:09:14 +03:30
2026-07-02 15:36:08 +03:30
2026-07-03 12:30:03 +03:30
2026-07-05 10:46:31 +03:30
2026-07-05 11:20:53 +03:30
2026-07-05 11:54:12 +03:30
2026-07-08 00:03:33 +03:30
2026-07-08 12:19:06 +03:30
2026-07-09 07:26:58 +03:30
2026-07-11 08:59:36 +03:30
2026-07-11 11:39:15 +03:30
2026-07-11 11:39:15 +03:30