feat(captcha): add ALTCHA configuration endpoint and integrate into HomeController

- Introduced a new endpoint `/api/v1/altcha/config` in CaptchaController to return the status of the ALTCHA captcha.
- Updated HomeController to inject AltchaService and pass the captcha status to the home page template.
- Modified the home.html.twig template to conditionally render the ALTCHA widget based on the captcha status.
- Updated manifest.json and cache files to reflect changes in the codebase.
This commit is contained in:
hamed
2026-07-10 11:18:40 +03:30
parent 6f2e0ec2f1
commit c3c520801d
15 changed files with 727 additions and 625 deletions
+19 -2
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import 'altcha';
// ALTCHA خودمیزبان: widget با گرفتن challenge از بک‌اند، proof-of-work را در
@@ -34,6 +34,21 @@ declare module 'react' {
export default function Altcha({ onVerified, challengeUrl = '/api/v1/altcha/challenge' }: AltchaProps) {
const ref = useRef<HTMLElement>(null);
// null=در حال بررسی وضعیت، true/false=فعال/غیرفعال بودن کپچا در سرور
const [enabled, setEnabled] = useState<boolean | null>(null);
useEffect(() => {
let alive = true;
fetch('/api/v1/altcha/config')
.then((r) => r.json())
.then((c) => {
if (!alive) return;
setEnabled(!!c.enabled);
if (!c.enabled) onVerified(''); // کپچا خاموش → فرم بدون مانع ارسال شود
})
.catch(() => { if (alive) setEnabled(false); });
return () => { alive = false; };
}, [onVerified]);
useEffect(() => {
const el = ref.current;
@@ -48,7 +63,9 @@ export default function Altcha({ onVerified, challengeUrl = '/api/v1/altcha/chal
el.addEventListener('statechange', onStateChange);
return () => el.removeEventListener('statechange', onStateChange);
}, [onVerified]);
}, [onVerified, enabled]);
if (enabled !== true) return null;
return <altcha-widget ref={ref as React.Ref<HTMLElement>} challengeurl={challengeUrl} strings={FA_STRINGS} />;
}
+1 -1
View File
@@ -33,7 +33,7 @@ security:
provider: api_doc_provider
public_endpoints:
pattern: ^/(api/v1/altcha/challenge$|api/v1/user/(send-code|verify-code|register|otp-login|reset-password)|oauth/token$|session/token|api/v1/categorys/|api/v1/doctors$|api/v1/clinics$|api/v1/clinic/doctor-list/|api/v1/clinic/[^/]+/addresses$|api/v1/clinic-pro/doctor-addresses/|api/v1/appointment-slots|api/v1/appointment-settings/month-availability/|api/v1/comments/|api/v1/rate/[^/]+$|api/v1/specialties|api/v1/blogs$|api/v1/tags$|api/v1/clinic-invitation/|api/v1/pre-registration$)
pattern: ^/(api/v1/altcha/(challenge|config)$|api/v1/user/(send-code|verify-code|register|otp-login|reset-password)|oauth/token$|session/token|api/v1/categorys/|api/v1/doctors$|api/v1/clinics$|api/v1/clinic/doctor-list/|api/v1/clinic/[^/]+/addresses$|api/v1/clinic-pro/doctor-addresses/|api/v1/appointment-slots|api/v1/appointment-settings/month-availability/|api/v1/comments/|api/v1/rate/[^/]+$|api/v1/specialties|api/v1/blogs$|api/v1/tags$|api/v1/clinic-invitation/|api/v1/pre-registration$)
stateless: true
security: false
+13 -4
View File
@@ -37,8 +37,9 @@ x-app-env: &app-env
MAX_FILE_SIZE_BYTES: "5242880"
UPLOAD_DIR: var/uploads
# ALTCHA self-hosted captcha. HMAC key is a secret → inject from Coolify's
# Environment Variables tab. Enabled in prod; tunables fixed here.
ALTCHA_ENABLED: "1"
# Environment Variables tab. Symfony reads this via %env(bool:...)% so
# true/false (or 1/0) both work; کپچا در prod روشن است.
ALTCHA_ENABLED: "true"
ALTCHA_HMAC_KEY: ${ALTCHA_HMAC_KEY}
ALTCHA_MAX_NUMBER: "100000"
ALTCHA_EXPIRE_SECONDS: "300"
@@ -95,7 +96,11 @@ services:
stop_grace_period: 30s
# No port to probe — just confirm the consumer process is alive (busybox ps).
healthcheck:
test: ["CMD-SHELL", "ps -o args 2>/dev/null | grep -q '[m]essenger:consume async' || exit 1"]
test:
[
"CMD-SHELL",
"ps -o args 2>/dev/null | grep -q '[m]essenger:consume async' || exit 1",
]
interval: 30s
timeout: 5s
retries: 3
@@ -114,7 +119,11 @@ services:
depends_on: [app]
stop_grace_period: 30s
healthcheck:
test: ["CMD-SHELL", "ps -o args 2>/dev/null | grep -q '[m]essenger:consume scheduler_default' || exit 1"]
test:
[
"CMD-SHELL",
"ps -o args 2>/dev/null | grep -q '[m]essenger:consume scheduler_default' || exit 1",
]
interval: 30s
timeout: 5s
retries: 3
+11
View File
@@ -28,6 +28,17 @@
---
## GET `/api/v1/altcha/config`
وضعیت فعال بودن کپچا. **عمومی**. کلاینت‌ها قبل از رندر widget این را می‌خوانند؛ اگر `enabled=false` باشد، هیچ widgetی نشان داده نمی‌شود و فرم‌ها بدون فیلد `altcha` ارسال می‌شوند (بک‌اند هم no-op است).
### Response `200`
```json
{ "enabled": false }
```
---
## اعمال کپچا روی endpointهای محافظت‌شده
کلاینت مقدار حل‌شده‌ی widget (base64) را با کلید `altcha` در بدنه‌ی همان درخواست می‌فرستد:
-13
View File
@@ -560,7 +560,6 @@
"558": "Community 558",
"559": "Community 559",
"560": "Community 560",
"561": "Community 561",
"562": "Community 562",
"563": "Community 563",
"564": "Community 564",
@@ -625,19 +624,16 @@
"623": "Community 623",
"624": "Community 624",
"625": "Community 625",
"626": "Community 626",
"627": "Community 627",
"628": "Community 628",
"629": "Community 629",
"630": "Community 630",
"631": "Community 631",
"632": "Community 632",
"633": "Community 633",
"634": "Community 634",
"635": "Community 635",
"636": "Community 636",
"637": "Community 637",
"638": "Community 638",
"639": "Community 639",
"640": "Community 640",
"641": "Community 641",
@@ -657,7 +653,6 @@
"655": "Community 655",
"656": "Community 656",
"657": "Community 657",
"658": "Community 658",
"659": "Community 659",
"660": "Community 660",
"661": "Community 661",
@@ -666,16 +661,13 @@
"664": "Community 664",
"665": "Community 665",
"666": "Community 666",
"667": "Community 667",
"668": "Community 668",
"669": "Community 669",
"670": "Community 670",
"671": "Community 671",
"672": "Community 672",
"673": "Community 673",
"674": "Community 674",
"675": "Community 675",
"676": "Community 676",
"677": "Community 677",
"678": "Community 678",
"679": "Community 679",
@@ -689,7 +681,6 @@
"687": "Community 687",
"688": "Community 688",
"689": "Community 689",
"690": "Community 690",
"691": "Community 691",
"692": "Community 692",
"693": "Community 693",
@@ -699,13 +690,11 @@
"697": "Community 697",
"698": "Community 698",
"699": "Community 699",
"700": "Community 700",
"701": "Community 701",
"702": "Community 702",
"703": "Community 703",
"704": "Community 704",
"705": "Community 705",
"706": "Community 706",
"707": "Community 707",
"708": "Community 708",
"709": "Community 709",
@@ -726,12 +715,10 @@
"724": "Community 724",
"725": "Community 725",
"726": "Community 726",
"727": "Community 727",
"728": "Community 728",
"729": "Community 729",
"730": "Community 730",
"731": "Community 731",
"732": "Community 732",
"733": "Community 733",
"734": "Community 734",
"735": "Community 735",
+115 -160
View File
@@ -1,16 +1,16 @@
# Graph Report - clinicpro (2026-07-10)
## Corpus Check
- 736 files · ~541,454 words
- 736 files · ~541,658 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 9269 nodes · 12824 edges · 740 communities (589 shown, 151 thin omitted)
- 9273 nodes · 12830 edges · 727 communities (581 shown, 146 thin omitted)
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 279 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `aded5267`
- Built from commit: `6f2e0ec2`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -576,7 +576,6 @@
- [[_COMMUNITY_Community 558|Community 558]]
- [[_COMMUNITY_Community 559|Community 559]]
- [[_COMMUNITY_Community 560|Community 560]]
- [[_COMMUNITY_Community 561|Community 561]]
- [[_COMMUNITY_Community 562|Community 562]]
- [[_COMMUNITY_Community 563|Community 563]]
- [[_COMMUNITY_Community 565|Community 565]]
@@ -634,15 +633,12 @@
- [[_COMMUNITY_Community 620|Community 620]]
- [[_COMMUNITY_Community 621|Community 621]]
- [[_COMMUNITY_Community 625|Community 625]]
- [[_COMMUNITY_Community 626|Community 626]]
- [[_COMMUNITY_Community 631|Community 631]]
- [[_COMMUNITY_Community 632|Community 632]]
- [[_COMMUNITY_Community 633|Community 633]]
- [[_COMMUNITY_Community 634|Community 634]]
- [[_COMMUNITY_Community 635|Community 635]]
- [[_COMMUNITY_Community 636|Community 636]]
- [[_COMMUNITY_Community 637|Community 637]]
- [[_COMMUNITY_Community 638|Community 638]]
- [[_COMMUNITY_Community 639|Community 639]]
- [[_COMMUNITY_Community 640|Community 640]]
- [[_COMMUNITY_Community 641|Community 641]]
@@ -660,7 +656,6 @@
- [[_COMMUNITY_Community 655|Community 655]]
- [[_COMMUNITY_Community 656|Community 656]]
- [[_COMMUNITY_Community 657|Community 657]]
- [[_COMMUNITY_Community 658|Community 658]]
- [[_COMMUNITY_Community 659|Community 659]]
- [[_COMMUNITY_Community 660|Community 660]]
- [[_COMMUNITY_Community 661|Community 661]]
@@ -669,15 +664,12 @@
- [[_COMMUNITY_Community 664|Community 664]]
- [[_COMMUNITY_Community 665|Community 665]]
- [[_COMMUNITY_Community 666|Community 666]]
- [[_COMMUNITY_Community 667|Community 667]]
- [[_COMMUNITY_Community 668|Community 668]]
- [[_COMMUNITY_Community 669|Community 669]]
- [[_COMMUNITY_Community 671|Community 671]]
- [[_COMMUNITY_Community 672|Community 672]]
- [[_COMMUNITY_Community 673|Community 673]]
- [[_COMMUNITY_Community 674|Community 674]]
- [[_COMMUNITY_Community 675|Community 675]]
- [[_COMMUNITY_Community 676|Community 676]]
- [[_COMMUNITY_Community 677|Community 677]]
- [[_COMMUNITY_Community 678|Community 678]]
- [[_COMMUNITY_Community 679|Community 679]]
@@ -691,7 +683,6 @@
- [[_COMMUNITY_Community 687|Community 687]]
- [[_COMMUNITY_Community 688|Community 688]]
- [[_COMMUNITY_Community 689|Community 689]]
- [[_COMMUNITY_Community 690|Community 690]]
- [[_COMMUNITY_Community 691|Community 691]]
- [[_COMMUNITY_Community 692|Community 692]]
- [[_COMMUNITY_Community 693|Community 693]]
@@ -701,13 +692,11 @@
- [[_COMMUNITY_Community 697|Community 697]]
- [[_COMMUNITY_Community 698|Community 698]]
- [[_COMMUNITY_Community 699|Community 699]]
- [[_COMMUNITY_Community 700|Community 700]]
- [[_COMMUNITY_Community 701|Community 701]]
- [[_COMMUNITY_Community 702|Community 702]]
- [[_COMMUNITY_Community 703|Community 703]]
- [[_COMMUNITY_Community 704|Community 704]]
- [[_COMMUNITY_Community 705|Community 705]]
- [[_COMMUNITY_Community 706|Community 706]]
- [[_COMMUNITY_Community 707|Community 707]]
- [[_COMMUNITY_Community 708|Community 708]]
- [[_COMMUNITY_Community 709|Community 709]]
@@ -728,12 +717,10 @@
- [[_COMMUNITY_Community 724|Community 724]]
- [[_COMMUNITY_Community 725|Community 725]]
- [[_COMMUNITY_Community 726|Community 726]]
- [[_COMMUNITY_Community 727|Community 727]]
- [[_COMMUNITY_Community 728|Community 728]]
- [[_COMMUNITY_Community 729|Community 729]]
- [[_COMMUNITY_Community 730|Community 730]]
- [[_COMMUNITY_Community 731|Community 731]]
- [[_COMMUNITY_Community 732|Community 732]]
- [[_COMMUNITY_Community 733|Community 733]]
- [[_COMMUNITY_Community 734|Community 734]]
- [[_COMMUNITY_Community 735|Community 735]]
@@ -755,29 +742,29 @@
10. `formatDate()` - 39 edges
## Surprising Connections (you probably didn't know these)
- `Pagination()` --calls--> `formatNumber()` [EXTRACTED]
assets/admin/components/ui/Pagination.tsx → assets/admin/lib/utils.ts
- `toForm()` --calls--> `rialToToman()` [EXTRACTED]
assets/admin/pages/SettingsPage.tsx → assets/admin/lib/utils.ts
- `SettlementsPage()` --calls--> `formatRial()` [EXTRACTED]
assets/admin/pages/SettlementsPage.tsx → assets/admin/lib/utils.ts
- `ServiceTariffModal()` --calls--> `formatNumber()` [EXTRACTED]
assets/admin/components/ServiceTariffModal.tsx → assets/admin/lib/utils.ts
- `LogsPage()` --calls--> `formatDateTime()` [EXTRACTED]
assets/admin/pages/LogsPage.tsx → assets/admin/lib/utils.ts
- `SmsPage()` --calls--> `formatDateTime()` [EXTRACTED]
assets/admin/pages/SmsPage.tsx → assets/admin/lib/utils.ts
- `NewAppointmentModal()` --calls--> `useAuthStore` [EXTRACTED]
assets/admin/pages/AppointmentsPage.tsx → assets/admin/stores/authStore.ts
- `LogoUploadField()` --calls--> `useAuthStore` [EXTRACTED]
assets/admin/pages/CategoriesPage.tsx → assets/admin/stores/authStore.ts
## Import Cycles
- None detected.
## Communities (740 total, 151 thin omitted)
## Communities (727 total, 146 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.04
Nodes (48): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, useSubscription(), DEGREE_OPTIONS (+40 more)
Cohesion: 0.06
Nodes (35): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, DEGREE_OPTIONS, DoctorFormPage() (+27 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (41): AddressData, AddrForm, addrSchema, AVATAR_COLORS, BookingMeta, CityOpt, DateOverrideData, DEFAULT_BOOKING_META (+33 more)
Nodes (52): addMinutes(), AddressData, AddrForm, addrSchema, AVATAR_COLORS, BookingMeta, calcSlotCount(), CityOpt (+44 more)
### Community 2 - "Community 2"
Cohesion: 0.10
@@ -788,16 +775,16 @@ Cohesion: 0.10
Nodes (20): `RepresentationActionController` — welcome به‌صورت inline (بدون تمپلت), `SmsMessageTemplate::DEFAULTS` (فاقد نام تمپلت و نگاشت token), `SmsService::sendNow` — انتخاب بین lookup و متن‌آزاد, الگوی فعلی همه‌ی call-siteها (به‌جز OTP) — متن‌آزاد، بدون `templateCode`, تبدیل همه‌ی پیامک‌های سیستمی به VerifyLookup کاوه‌نگار (تمپلت نام‌دار), تنها جای درست (OTP) — که باید الگوی بقیه شود, زمینه, فایل‌های مرتبط (+12 more)
### Community 4 - "Community 4"
Cohesion: 0.06
Nodes (8): DoctorService, Doctor, DoctorServiceRepository, Collection, self, User, WeeklySchedule, ManagerRegistry
Cohesion: 0.05
Nodes (11): DoctorServiceController, DoctorService, Doctor, DoctorServiceRepository, Collection, self, User, WeeklySchedule (+3 more)
### Community 5 - "Community 5"
Cohesion: 0.07
Nodes (3): UserProfile, self, User
### Community 6 - "Community 6"
Cohesion: 0.12
Nodes (12): SettlementController, SettlementRepository, WalletTransactionRepository, Settlement, JsonResponse, Request, User, ManagerRegistry (+4 more)
Cohesion: 0.09
Nodes (15): SettlementController, SettlementRepository, WalletTransactionRepository, CommissionService, Settlement, JsonResponse, Request, User (+7 more)
### Community 7 - "Community 7"
Cohesion: 0.07
@@ -825,7 +812,7 @@ Nodes (44): Clinic Doctor Invitation API, DELETE `/api/v1/admin/clinic/invitatio
### Community 13 - "Community 13"
Cohesion: 0.04
Nodes (46): get, PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), api, ApiError, ApiResponse, downloadFile() (+38 more)
Nodes (46): get, PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), useSubscription(), api, ApiError, downloadFile() (+38 more)
### Community 14 - "Community 14"
Cohesion: 0.10
@@ -836,8 +823,8 @@ Cohesion: 0.25
Nodes (7): PaymentController, Appointment, JsonResponse, Payment, Request, Response, User
### Community 16 - "Community 16"
Cohesion: 0.07
Nodes (7): PatientSession, SmsWallet, Appointment, Collection, PatientRecord, self, SessionService
Cohesion: 0.06
Nodes (8): PatientSession, SmsWallet, AppointmentExpiryService, Appointment, Collection, PatientRecord, self, SessionService
### Community 17 - "Community 17"
Cohesion: 0.05
@@ -849,15 +836,15 @@ Nodes (38): API, API, API, API, API, Route, Route, Route (+30 more)
### Community 19 - "Community 19"
Cohesion: 0.03
Nodes (91): PaginatedResponse, CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, LogoUploadField(), ProvinceForm (+83 more)
Nodes (61): ALL_STATUSES, CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, LogoUploadField(), ProvinceForm (+53 more)
### Community 20 - "Community 20"
Cohesion: 0.13
Nodes (4): AdminApiController, JsonResponse, Request, StreamedResponse
### Community 21 - "Community 21"
Cohesion: 0.03
Nodes (50): ServiceTariffModal(), formatNumber(), ClinicAddress, ClinicDetailPage(), ClinicDoctorItem, ClinicInvitation, EditForm, editSchema (+42 more)
Cohesion: 0.04
Nodes (43): formatNumber(), ClinicAddress, ClinicDetailPage(), ClinicDoctorItem, ClinicInvitation, EditForm, editSchema, HUES_LIST (+35 more)
### Community 22 - "Community 22"
Cohesion: 0.15
@@ -880,8 +867,8 @@ Cohesion: 0.24
Nodes (4): InsuranceController, JsonResponse, Request, User
### Community 27 - "Community 27"
Cohesion: 0.06
Nodes (35): 55. 🟢 `GET` all tag, 56. 🟢 `GET` supplementary_insurance, 57. 🟢 `GET` categories list, 58. 🟢 `GET` all state, 59. 🟢 `GET` all city, 60. 🟢 `GET` all specially doctor, 61. 🔵 `POST` post, 63. 🔴 `DELETE` DELETE (+27 more)
Cohesion: 0.05
Nodes (40): 55. 🟢 `GET` all tag, 56. 🟢 `GET` supplementary_insurance, 57. 🟢 `GET` categories list, 58. 🟢 `GET` all state, 59. 🟢 `GET` all city, 60. 🟢 `GET` all specially doctor, 61. 🔵 `POST` post, 62. 🟡 `PATCH` patch (+32 more)
### Community 28 - "Community 28"
Cohesion: 0.08
@@ -892,8 +879,8 @@ Cohesion: 0.06
Nodes (35): Bulk import / export, DELETE `/api/v1/admin/city/{id}`, DELETE `/api/v1/admin/province/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/cities` (+27 more)
### Community 30 - "Community 30"
Cohesion: 0.23
Nodes (7): Money, BillingCalculator, InvoiceService, CoverageRule, ShareBreakdown, Invoice, PatientSession
Cohesion: 0.09
Nodes (13): BillingCalculatorTest, BillingCalculator, Money, BillingCalculator, InvoiceService, PatientService, CoverageRule, ShareBreakdown (+5 more)
### Community 31 - "Community 31"
Cohesion: 0.06
@@ -904,8 +891,8 @@ Cohesion: 0.06
Nodes (32): 10. Modal / Dialog, 11. Toast Notifications, 12. Empty States & Loading, 13. Page Header (هر صفحه), 14. تکنولوژی Stack, 15. Responsive Breakpoints, 16. Dark Mode (اختیاری — فاز دوم), 17. نمونه رنگ‌بندی صفحه داشبورد (+24 more)
### Community 33 - "Community 33"
Cohesion: 0.08
Nodes (21): CoverageRow, Draft, KIND, TenantInsurance, TariffResponse, TariffRow, EMPTY_ITEMS, EMPTY_SECTIONS (+13 more)
Cohesion: 0.06
Nodes (27): CoverageRow, Draft, KIND, TenantInsurance, ServiceTariffModal(), TariffResponse, TariffRow, EMPTY_ITEMS (+19 more)
### Community 34 - "Community 34"
Cohesion: 0.06
@@ -968,8 +955,8 @@ Cohesion: 0.11
Nodes (4): Payment, Appointment, self, User
### Community 49 - "Community 49"
Cohesion: 0.06
Nodes (28): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+20 more)
Cohesion: 0.07
Nodes (21): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+13 more)
### Community 50 - "Community 50"
Cohesion: 0.07
@@ -984,8 +971,8 @@ Cohesion: 0.07
Nodes (26): الزامات UI, باگ‌فیکس صفحه نوبت‌ها, باگ ۱ — کرش تقویم, باگ ۲ — روز هفته در DateNavigator, باگ ۳ — پیام «slot نیست», باگ ۴ — نوبت جدید: نام اجباری + find-or-create patient, باگ ۵ — patient_mobile نشان می‌دهد موبایل پزشک, باگ ۶ — نوبت‌های رزرو شده در نمایش زمانبندی (+18 more)
### Community 53 - "Community 53"
Cohesion: 0.10
Nodes (13): AppLogRepository, ClaimItemRepository, PreRegistrationRepository, SessionServiceRepository, SmsSettingsRepository, ServiceEntityRepository, SmsSettings, ManagerRegistry (+5 more)
Cohesion: 0.07
Nodes (18): AppLogRepository, PaymentLog, ClaimItemRepository, PaymentLogRepository, PreRegistrationRepository, SessionServiceRepository, SiteConfigRepository, SmsSettingsRepository (+10 more)
### Community 54 - "Community 54"
Cohesion: 0.10
@@ -1004,8 +991,8 @@ Cohesion: 0.08
Nodes (24): Blog API, DELETE `/api/v1/blog/{uuid}`, Errors, Errors, Errors, Errors, Errors, GET `/api/v1/blog/{slug}` (+16 more)
### Community 58 - "Community 58"
Cohesion: 0.15
Nodes (8): Blog, BlogController, BlogRepository, JsonResponse, Request, User, ManagerRegistry, QueryBuilder
Cohesion: 0.28
Nodes (4): Blog, BlogRepository, ManagerRegistry, QueryBuilder
### Community 59 - "Community 59"
Cohesion: 0.22
@@ -1025,7 +1012,7 @@ Nodes (25): Bulk import / export, DELETE `/api/v1/admin/specialty/{id}`, Errors,
### Community 63 - "Community 63"
Cohesion: 0.05
Nodes (51): FreeVisitPrice(), Pricing, Contract, InsuranceOption, KIND_LABEL, cn(), formatDate(), formatDateTime() (+43 more)
Nodes (51): FreeVisitPrice(), Pricing, cn(), formatDate(), formatDateTime(), formatRial(), iranMobileOptionalSchema, isValidIranMobile() (+43 more)
### Community 64 - "Community 64"
Cohesion: 0.29
@@ -1057,7 +1044,7 @@ Nodes (12): AdminUserDetail, AVATAR_COLORS, EditForm, editSchema, GENDER_LABELS,
### Community 72 - "Community 72"
Cohesion: 0.09
Nodes (4): ClaimItem, Claim, Collection, self
Nodes (3): Claim, Collection, self
### Community 74 - "Community 74"
Cohesion: 0.09
@@ -1088,8 +1075,8 @@ Cohesion: 0.09
Nodes (23): dependencies, @ckeditor/ckeditor5-build-classic, @ckeditor/ckeditor5-react, @fontsource/vazirmatn, @heroicons/react, @hookform/resolvers, jalaali-js, leaflet (+15 more)
### Community 82 - "Community 82"
Cohesion: 0.07
Nodes (8): CategoryImportTest, Connection, RepositoryClassMappingTest, KernelTestCase, DbLogger, CategoryImporter, DbLoggerTest, Stringable
Cohesion: 0.06
Nodes (11): CategoryImportTest, Connection, CategoryImportController, RepositoryClassMappingTest, KernelTestCase, DbLogger, CategoryImporter, DbLoggerTest (+3 more)
### Community 83 - "Community 83"
Cohesion: 0.09
@@ -1105,7 +1092,7 @@ Nodes (30): devDependencies, @babel/core, @babel/preset-env, @babel/preset-react
### Community 86 - "Community 86"
Cohesion: 0.05
Nodes (16): AppointmentExpiryServiceTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListNPlusOneTest, ClaimsListPaginationTest, CaptchaFlowTest, ServiceItemStaffOwnershipTest, EntityManagerInterface (+8 more)
Nodes (16): AppointmentExpiryServiceTest, DateOverrideOwnershipTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, CaptchaFlowTest, ServiceItemDeleteCleanupTest, ServiceItemStaffOwnershipTest (+8 more)
### Community 87 - "Community 87"
Cohesion: 0.10
@@ -1388,8 +1375,8 @@ Cohesion: 0.12
Nodes (15): Endpoint ها, GET /api/v1/payment/{uuid}, POST /api/v1/payment, POST /api/v1/payment/callback/mellat, Strategy Pattern برای درگاه‌ها, Subscription Payment — POST /api/v1/subscription-payment, ⚠ امنیت: IP Whitelist برای Callback, ⚠ امنیت: جلوگیری از Open Redirect (+7 more)
### Community 160 - "Community 160"
Cohesion: 0.09
Nodes (21): Appointment Settings API, Available Locations, Date Overrides, DELETE `/api/v1/appointment-settings/date-override/{uuid}`, Errors, Errors, Errors, `GET /api/v1/appointment-settings/available-locations/{doctorUuid}` (+13 more)
Cohesion: 0.13
Nodes (15): Date Overrides, DELETE `/api/v1/appointment-settings/date-override/{uuid}`, Errors, Errors, GET `/api/v1/appointment-settings/date-override/list/{doctorUuid}`, GET `/api/v1/appointment-settings/date-override/{uuid}`, PATCH `/api/v1/appointment-settings/date-override/{uuid}`, POST `/api/v1/appointment-settings/date-override` (+7 more)
### Community 161 - "Community 161"
Cohesion: 0.24
@@ -1424,8 +1411,8 @@ Cohesion: 0.10
Nodes (20): api.ir (استعلام هویت — Shahkar / IbanMatch), اتصال به دیتابیس‌های مستقل (الزامی), اسرار (الزامی — قبل از اولین دیپلوی), امنیت و منابع, بررسی سلامت, دامنه‌ها و CORS, دیپلوی‌های بعدی, راهنمای دیپلوی ClinicPro (Coolify + Docker Compose) (+12 more)
### Community 169 - "Community 169"
Cohesion: 0.15
Nodes (5): EntityInsurancePricing, TenantInsuranceCleanupTest, EntityInsurancePricingRepository, TenantInsuranceCleanupService, ManagerRegistry
Cohesion: 0.13
Nodes (7): EntityInsurancePricing, EntityInsurancePricingRepository, TenantServiceCoverageRepository, TenantInsuranceCleanupService, ManagerRegistry, ManagerRegistry, TenantServiceCoverage
### Community 170 - "Community 170"
Cohesion: 0.13
@@ -1544,8 +1531,8 @@ Cohesion: 0.14
Nodes (13): Endpoint ها, PATCH /api/v1/secretary/{uuid}, POST /api/v1/secretary, تسک ۱۴: ماژول منشی, توضیح, زمان تخمینی, ساختار JSON, سیستم مجوزها — Resource-Based Permissions (مقیاس‌پذیر) (+5 more)
### Community 201 - "Community 201"
Cohesion: 0.17
Nodes (12): Admin API, Clinic Invitation Management, Dashboard, GET `/api/v1/admin/dashboard/charts`, GET `/api/v1/admin/dashboard/recent`, GET `/api/v1/admin/dashboard/stats`, GET /api/v1/admin/settings, PATCH /api/v1/admin/settings (+4 more)
Cohesion: 0.12
Nodes (16): Admin API, Clinic Invitation Management, Dashboard, GET `/api/v1/admin/dashboard/charts`, GET `/api/v1/admin/dashboard/recent`, GET `/api/v1/admin/dashboard/stats`, GET `/api/v1/admin/pre-registrations`, GET /api/v1/admin/settings (+8 more)
### Community 202 - "Community 202"
Cohesion: 0.15
@@ -1556,16 +1543,16 @@ Cohesion: 0.15
Nodes (12): Clinic Services API, DELETE /api/v1/service-item/{uuid}, DELETE /api/v1/service-section/{uuid}, GET /api/v1/service-items/{sectionUuid}, GET /api/v1/service-items/{uuid}/tariffs, GET /api/v1/service-sections, PATCH /api/v1/service-item/{uuid}, PATCH /api/v1/service-section/{uuid} (+4 more)
### Community 204 - "Community 204"
Cohesion: 0.13
Nodes (12): AbstractAuthenticator, AuthenticationException, ExceptionSubscriber, SecurityHeadersSubscriber, EventSubscriberInterface, ExceptionEvent, Passport, ResponseEvent (+4 more)
Cohesion: 0.21
Nodes (6): AuthenticationException, ExceptionSubscriber, SecurityHeadersSubscriber, EventSubscriberInterface, ExceptionEvent, ResponseEvent
### Community 205 - "Community 205"
Cohesion: 0.07
Nodes (20): Command, CancelExpiredAppointmentsCommand, CreateAdminCommand, PruneLogsCommand, SeedCategoriesCommand, SeedDemoDataCommand, SeedSmsMessageTemplatesCommand, InputInterface (+12 more)
### Community 206 - "Community 206"
Cohesion: 0.08
Nodes (14): MellatGateway, MockGateway, SepGateway, SoapClient, PaymentGatewayInterface, PaymentInitResult, PaymentRefundResult, PaymentVerifyResult (+6 more)
Cohesion: 0.06
Nodes (17): GatewayFactory, MellatGateway, MockGateway, SepGateway, MellatGateway, SepGateway, SoapClient, PaymentGatewayInterface (+9 more)
### Community 207 - "Community 207"
Cohesion: 0.15
@@ -1625,7 +1612,7 @@ Nodes (5): PaymentRepository, Appointment, ManagerRegistry, Payment, User
### Community 225 - "Community 225"
Cohesion: 0.07
Nodes (20): emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema, PLAN_DISPLAY, PlanForm, planSchema (+12 more)
Nodes (19): Contract, InsuranceOption, KIND_LABEL, FormData, schema, Claim, ClaimItem, DebtRow (+11 more)
### Community 226 - "Community 226"
Cohesion: 0.15
@@ -1700,8 +1687,8 @@ Cohesion: 0.28
Nodes (4): SubscriptionService, ClinicSubscription, Payment, SubscriptionPlan
### Community 245 - "Community 245"
Cohesion: 0.17
Nodes (8): FormValues, schema, SectionDef, SectionId, SECTIONS, Settings, TaxHistoryRow, toForm()
Cohesion: 0.15
Nodes (11): emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema, PLAN_DISPLAY, PlanForm, planSchema (+3 more)
### Community 246 - "Community 246"
Cohesion: 0.17
@@ -1816,8 +1803,8 @@ Cohesion: 0.15
Nodes (5): Authentication, ClinicPro — API Documentation Index, Error Code Reference, Modules, Standard Response Envelope
### Community 275 - "Community 275"
Cohesion: 0.17
Nodes (6): MellatGateway, MellatGatewayTest, ErrorCodesTest, KavehNegarProviderTest, TestCase, KavehNegarProvider
Cohesion: 0.15
Nodes (6): MellatGatewayTest, CorsRegexEnvProcessorTest, ErrorCodesTest, KavehNegarProviderTest, TestCase, KavehNegarProvider
### Community 276 - "Community 276"
Cohesion: 0.20
@@ -1888,12 +1875,12 @@ Cohesion: 0.20
Nodes (9): AdminApiController — dashboardCharts با بازه زمانی, DashboardController — اضافه کردن from/to, date range selector component:, تغییر Backend, تغییر Frontend — DashboardPage.tsx, فایل‌هایی که تغییر می‌کنند, معماری — تسک ۱۶: داشبورد هوشمند, نصب dependency: (+1 more)
### Community 294 - "Community 294"
Cohesion: 0.36
Nodes (3): DoctorServiceController, JsonResponse, Request
Cohesion: 0.30
Nodes (6): AbstractAuthenticator, Passport, PasswordAuthenticator, Request, Response, TokenInterface
### Community 295 - "Community 295"
Cohesion: 0.22
Nodes (8): AbstractController, AdminController, HomeController, SeoController, Response, Response, Request, Response
Cohesion: 0.29
Nodes (5): AbstractController, AdminController, HomeController, Response, Response
### Community 296 - "Community 296"
Cohesion: 0.22
@@ -1916,8 +1903,8 @@ Cohesion: 0.42
Nodes (3): PreRegistrationController, JsonResponse, Request
### Community 301 - "Community 301"
Cohesion: 0.09
Nodes (20): AddForm, addSchema, ClinicsPage(), HUES_LIST, EMPTY, PreRegistration, STATUS_META, STATUS_TABS (+12 more)
Cohesion: 0.05
Nodes (48): ApiResponse, PaginatedResponse, iranMobileSchema, STATUS_FILTERS, AddForm, addSchema, HUES_LIST, FILTERS (+40 more)
### Community 302 - "Community 302"
Cohesion: 0.12
@@ -1929,7 +1916,7 @@ Nodes (16): آماده‌سازی پروژه ClinicPro برای دیپلوی ر
### Community 304 - "Community 304"
Cohesion: 0.22
Nodes (9): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 33. 🔵 `POST` image_clinic, 6. کلینیک (Clinic), هدرهای اضافی, پارامترهای Query, پاسخ‌ها, پاسخ‌ها (+1 more)
Nodes (9): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 36. 🟢 `GET` get my rate, 6. کلینیک (Clinic), هدرهای اضافی, پارامترهای Query, پاسخ‌ها, پاسخ‌ها (+1 more)
### Community 306 - "Community 306"
Cohesion: 0.07
@@ -1940,8 +1927,8 @@ Cohesion: 0.28
Nodes (3): UserActiveContext, self, User
### Community 308 - "Community 308"
Cohesion: 0.36
Nodes (4): SiteConfigController, JsonResponse, Request, User
Cohesion: 0.17
Nodes (7): HealthController, SiteConfigController, EntityManagerInterface, JsonResponse, Request, User, JsonResponse
### Community 309 - "Community 309"
Cohesion: 0.22
@@ -2028,8 +2015,8 @@ Cohesion: 0.22
Nodes (8): Query های جدید, بیماران منحصربه‌فرد در بازه, درآمد بر اساس روز (از patient_sessions), فروش اشتراک بر اساس پنل (admin), نوبت‌ها بر اساس روز (admin chart), نکات مهم, هیچ migration لازم نیست, پایگاه داده — تسک ۱۶: داشبورد هوشمند
### Community 333 - "Community 333"
Cohesion: 0.06
Nodes (35): DELETE `/api/v1/clinic-pro/doctor-address/{id}`, DELETE `/api/v1/doctor/{uuid}`, Doctor API, Errors, Errors, Errors, Errors, Errors (+27 more)
Cohesion: 0.05
Nodes (39): DELETE `/api/v1/clinic-pro/doctor-address/{id}`, DELETE `/api/v1/doctor/{uuid}`, Doctor API, Errors, Errors, Errors, Errors, Errors (+31 more)
### Community 334 - "Community 334"
Cohesion: 0.25
@@ -2156,8 +2143,8 @@ Cohesion: 0.25
Nodes (7): ادمین, دکتر نمونه کامل — تبریز, دکتران bulk (۱۵۰۰ دکتر در ۱۵ شهر), ساخت مجدد, منشی دکتر نمونه, کاربران تستی, کلینیک نمونه — تبریز
### Community 367 - "Community 367"
Cohesion: 0.24
Nodes (3): Altcha, AltchaService, altcha
Cohesion: 0.15
Nodes (7): Altcha, AltchaService, altcha, Altcha(), AltchaProps, FA_STRINGS, IntrinsicElements
### Community 368 - "Community 368"
Cohesion: 0.36
@@ -2268,8 +2255,8 @@ Cohesion: 0.33
Nodes (6): Refactoring Plan, فاز ۰ — مستندسازی (۳ تا ۵ روز، قبل از هر کدنویسی), فاز ۱ — زیرساخت پایه (task-01), فاز ۲ — پیاده‌سازی ماژول‌ها (به ترتیب dependency), فاز ۳ — بهینه‌سازی (بعد از پیاده‌سازی), فاز ۴ — آماده‌سازی تولید
### Community 397 - "Community 397"
Cohesion: 0.36
Nodes (4): ClaimAmountBoundsTest, Claim, Doctor, User
Cohesion: 0.21
Nodes (6): ClaimAmountBoundsTest, ClaimsListNPlusOneTest, ClaimItem, Claim, Doctor, User
### Community 398 - "Community 398"
Cohesion: 0.22
@@ -2277,7 +2264,7 @@ Nodes (7): initiate(), refund(), reverse(), verify(), PaymentInitResult, Payment
### Community 399 - "Community 399"
Cohesion: 0.23
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260614183527
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260629161536
### Community 401 - "Community 401"
Cohesion: 0.12
@@ -2288,8 +2275,8 @@ Cohesion: 0.11
Nodes (17): بازطراحی معماری پرداخت — سرویس‌محور، امن، توسعه‌پذیر (Backend), تست دستی (ddev، در حالت `payment_test_mode=1`), خروجی نهایی (طبق spec — در گزارش اجرا ارائه شود), زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی (+9 more)
### Community 407 - "Community 407"
Cohesion: 0.27
Nodes (8): MessageBusInterface, MockObject, SmsServiceLookupOnlyTest, SmsLogRepository, SmsMessageTemplateRepository, SmsService, SmsTextResolver, KavehNegarProvider
Cohesion: 0.16
Nodes (9): MessageBusInterface, MockObject, SmsTextResolver, SmsServiceLookupOnlyTest, SmsLogRepository, SmsMessageTemplateRepository, SmsService, SmsTextResolver (+1 more)
### Community 418 - "Community 418"
Cohesion: 0.17
@@ -2315,10 +2302,18 @@ Nodes (5): PatientController, JsonResponse, PatientSession, Request, User
Cohesion: 0.43
Nodes (3): InvoiceRepository, Invoice, ManagerRegistry
### Community 439 - "Community 439"
Cohesion: 0.33
Nodes (4): BlogController, JsonResponse, Request, User
### Community 440 - "Community 440"
Cohesion: 0.11
Nodes (18): [F10] راهنمای کهنه در `CLAUDE.md`: endpoint `categorys/{bundle}` منتقل شده, [F11] داشبورد دکتر `GET /api/v1/dashboard/doctor` همیشه 500 (فیلد ناموجود در DQL) — ✅ رفع شد, [F1] phpstan: مقایسهٔ همیشه‌درست در محاسبهٔ estimated SMS — ✅ رفع شد, [F2] تست‌های PHPUnit به API خارجی Kavenegar درخواست واقعی می‌زنند, [F3] دیتابیس تست seed نشده — فقط کاربر ادمین وجود دارد, [F4] اسکریپت seeder `create_test_users.php` وجود ندارد, [F5] ادمین با JWT معتبر به `/api/doc` (Swagger UI) دسترسی ندارد (401), [F6] ناسازگاری کدهای خطا بین دامنه‌ها (+10 more)
### Community 451 - "Community 451"
Cohesion: 0.20
Nodes (8): AdminUser, ChangeRoleModal(), getPrimaryRole(), HUES_LIST, ROLE_META, ROLE_TABS, RoleBadge(), UserStats
### Community 452 - "Community 452"
Cohesion: 0.33
Nodes (6): GET /api/v1/sms/balance — موجودی حساب پیامک, POST /api/v1/sms/queue — افزودن به صف, ۴. سیستم حساب و صف پیامک, ۴.۱ حساب پیامک (SMS Account), ۴.۲ صف پیامک (SMS Queue), ۴.۳ API پیامک
@@ -2328,8 +2323,8 @@ Cohesion: 0.15
Nodes (12): رفع افتادن مودال‌ها به پایین صفحه (portal برای همه مودال‌ها), زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, پروژه (+4 more)
### Community 458 - "Community 458"
Cohesion: 0.47
Nodes (6): formatPersianDate(), gToJ(), jFirstDayOfWeek(), PersianDateInput(), todayGregorian(), toPersianNums()
Cohesion: 0.24
Nodes (10): gridItemStyle, JALALI_MONTHS, jalaliFirstWeekday(), jalaliToGregorian(), navBtnStyle, PersianCalendar(), pf, Props (+2 more)
### Community 459 - "Community 459"
Cohesion: 0.33
@@ -2416,12 +2411,12 @@ Cohesion: 0.39
Nodes (3): ProvinceRepository, ManagerRegistry, Province
### Community 482 - "Community 482"
Cohesion: 0.47
Nodes (3): CommissionService, Payment, Representation
Cohesion: 0.29
Nodes (6): Appointment Settings API, Available Locations, Errors, `GET /api/v1/appointment-settings/available-locations/{doctorUuid}`, Response `200`, Slot Calculation Logic (Reference)
### Community 483 - "Community 483"
Cohesion: 0.33
Nodes (4): PatientService, Appointment, PatientRecord, PatientSession
Cohesion: 0.57
Nodes (3): SeoController, Request, Response
### Community 486 - "Community 486"
Cohesion: 0.40
@@ -2435,10 +2430,6 @@ Nodes (5): Errors, GET `/api/v1/representation/dashboard/summary`, GET `/api/v1/
Cohesion: 0.40
Nodes (5): Admin Endpoints, GET /api/v1/admin/sms/settings/review, GET /api/v1/admin/sms/wallet-report, POST /api/v1/admin/sms/settings/{id}/approve, POST /api/v1/admin/sms/settings/{id}/reject
### Community 490 - "Community 490"
Cohesion: 0.53
Nodes (3): PaymentLog, PaymentLogRepository, ManagerRegistry
### Community 491 - "Community 491"
Cohesion: 0.12
Nodes (15): `Modal.tsx` (بدون Portal), `PersianCalendar.tsx` (buttonها بدون `type`) — نمونه‌ها, باگ ۱ — علت, باگ ۲ — علت, رفع دو باگ Modal و تقویم شمسی در پنل ادمین, زمینه, فایل‌های مرتبط, مشکل / هدف (+7 more)
@@ -2455,6 +2446,10 @@ Nodes (4): Error Codes, POST `/api/v1/user/reset-password`, Request Body, Respon
Cohesion: 0.12
Nodes (15): CORS — `config/packages/nelmio_cors.yaml`, MellatGateway — تشخیص فعال‌بودن, payment/config — `PaymentController::config()` (خط ۵۴۶), resolveGateway + callback (کد واقعی), رفع باگ‌های پروداکشن: CORS + payment/config 500 + درگاه‌های فعال و callback ملت, زمینه, فایل‌های مرتبط, فرانت — `SubscriptionPage.tsx` (+7 more)
### Community 496 - "Community 496"
Cohesion: 0.40
Nodes (5): Errors, PATCH `/api/v1/clinic-pro/doctor-address/{id}`, Path Parameters, Request Body, Response `200`
### Community 497 - "Community 497"
Cohesion: 0.53
Nodes (3): SlotUniquenessTest, Appointment, Doctor
@@ -2465,7 +2460,7 @@ Nodes (10): license, private, scripts, build, dev, dev-server, test, test:cov (+
### Community 499 - "Community 499"
Cohesion: 0.40
Nodes (5): addMinutes(), calcSlotCount(), hasOverlap(), parseMinutes(), SessionEditor()
Nodes (3): Props, StatTone, TONE
### Community 500 - "Community 500"
Cohesion: 0.40
@@ -2560,8 +2555,8 @@ Cohesion: 0.50
Nodes (4): GET /api/v1/appointment-settings/slots — دریافت اسلات‌های خالی, POST /api/v1/appointment-settings/holidays — ثبت تعطیلی (فقط ادمین), POST /api/v1/appointment-settings/overrides — ثبت Override توسط دکتر, Task-09: API تنظیمات نوبت
### Community 527 - "Community 527"
Cohesion: 0.16
Nodes (4): RanginehProvider, SmsService, SendSmsMessage, SmsProviderInterface
Cohesion: 0.13
Nodes (5): LoggerInterface, RanginehProvider, SmsService, SendSmsMessage, SmsProviderInterface
### Community 528 - "Community 528"
Cohesion: 0.50
@@ -2584,8 +2579,8 @@ Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/notification-mobile/verify`, Request Body, Response `200`
### Community 533 - "Community 533"
Cohesion: 0.33
Nodes (3): Closure, CorsRegexEnvProcessor, EnvVarProcessorInterface
Cohesion: 0.19
Nodes (6): BaseKernel, Closure, CorsRegexEnvProcessor, EnvVarProcessorInterface, MicroKernelTrait, Kernel
### Community 534 - "Community 534"
Cohesion: 0.30
@@ -2644,8 +2639,8 @@ Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/representation/appointments`, Query Parameters, Response `200`
### Community 552 - "Community 552"
Cohesion: 0.43
Nodes (3): CategoryImportController, JsonResponse, Request
Cohesion: 0.67
Nodes (3): 33. 🔵 `POST` image_clinic, هدرهای اضافی, پاسخ‌ها
### Community 553 - "Community 553"
Cohesion: 0.50
@@ -2672,17 +2667,13 @@ Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/admin/sms/template/{uuid}/reject`, Request Body, Response `200`
### Community 559 - "Community 559"
Cohesion: 0.25
Nodes (4): SmsMessageTemplateRepository, SmsTextResolver, SmsMessageTemplate, ManagerRegistry
Cohesion: 0.22
Nodes (6): SmsMessageController, SmsMessageTemplateRepository, SmsMessageTemplate, JsonResponse, Request, ManagerRegistry
### Community 560 - "Community 560"
Cohesion: 0.50
Nodes (4): GET /api/v1/sms/wallet/balance, GET /api/v1/sms/wallet/logs, POST /api/v1/sms/wallet/charge, SMS Wallet
### Community 561 - "Community 561"
Cohesion: 0.43
Nodes (3): BaseKernel, MicroKernelTrait, Kernel
### Community 563 - "Community 563"
Cohesion: 0.67
Nodes (3): submit(), Claim, ClaimSubmissionResult
@@ -2756,7 +2747,7 @@ Cohesion: 0.50
Nodes (3): Entity: Payment, ساختار فایل‌ها, معماری — تسک ۱۵: ماژول پرداخت
### Community 595 - "Community 595"
Cohesion: 0.43
Cohesion: 0.53
Nodes (3): SmsLogRepository, SmsLog, ManagerRegistry
### Community 596 - "Community 596"
@@ -2764,8 +2755,8 @@ Cohesion: 0.40
Nodes (5): 35. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 597 - "Community 597"
Cohesion: 0.29
Nodes (7): Configuration, Errors, GET `/api/v1/admin/sms/templates`, GET `/api/v1/sms/template/{uuid}`, Response `200`, Response `200`, SMS API
Cohesion: 0.20
Nodes (10): Configuration, Errors, GET `/api/v1/admin/sms/templates`, GET `/api/v1/sms/template/{uuid}`, POST `/api/v1/admin/sms/template/{uuid}/approve`, Request Body (`application/json`), Response `200`, Response `200` (+2 more)
### Community 599 - "Community 599"
Cohesion: 0.67
@@ -2791,22 +2782,10 @@ Nodes (5): RepresentationController, JsonResponse, Representation, Request, User
Cohesion: 0.67
Nodes (3): بک‌اند, فرانت‌اند, وضعیت فعلی کد (مهم — قبل از تغییر بخوان)
### Community 618 - "Community 618"
Cohesion: 0.16
Nodes (5): ServiceItemDeleteCleanupTest, ServiceCoverageNPlusOneTest, TenantServiceCoverageRepository, ManagerRegistry, TenantServiceCoverage
### Community 625 - "Community 625"
Cohesion: 0.40
Nodes (5): 31. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 626 - "Community 626"
Cohesion: 0.43
Nodes (3): SmsMessageController, JsonResponse, Request
### Community 631 - "Community 631"
Cohesion: 0.40
Nodes (5): 62. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 633 - "Community 633"
Cohesion: 0.40
Nodes (5): Errors, GET `/api/v1/clinic/my-doctor/{doctorUuid}`, Path Parameters, Response `200`, Schedule Fields Notes
@@ -2819,10 +2798,6 @@ Nodes (3): ImageCropModalProps, createImage(), getCroppedImage()
Cohesion: 0.12
Nodes (16): Runbook — تشخیص «ری‌استارت» سرور: recycle عادی یا خرابی واقعی؟, اقدامات تکمیلی روی سرور (خارج از repo), تأیید روی سرور — اسکریپت آماده, جدول تفسیر خروجی اسکریپت, خلاصه یک‌خطی, علامت مشکل, چرا این اتفاق می‌افتاد (و فیکس اعمال‌شده), چک‌لیست رفع (+8 more)
### Community 638 - "Community 638"
Cohesion: 0.40
Nodes (5): Errors, PATCH `/api/v1/doctor/{uuid}`, Path Parameters, Request Body (`application/json`), Response `200`
### Community 640 - "Community 640"
Cohesion: 0.43
Nodes (3): InvoiceItemRepository, InvoiceItem, ManagerRegistry
@@ -2860,8 +2835,8 @@ Cohesion: 0.38
Nodes (5): MyAppointmentsController, Doctor, JsonResponse, Request, User
### Community 656 - "Community 656"
Cohesion: 0.33
Nodes (6): Captcha API (ALTCHA), GET `/api/v1/altcha/challenge`, Response `200`, اعمال کپچا روی endpointهای محافظت‌شده, امنیت, خطای اعتبارسنجی کپچا `422`
Cohesion: 0.25
Nodes (8): Captcha API (ALTCHA), GET `/api/v1/altcha/challenge`, GET `/api/v1/altcha/config`, Response `200`, Response `200`, اعمال کپچا روی endpointهای محافظت‌شده, امنیت, خطای اعتبارسنجی کپچا `422`
### Community 657 - "Community 657"
Cohesion: 0.20
@@ -2879,10 +2854,6 @@ Nodes (5): BeforeInstallPromptEvent, usePwaInstall(), PwaInstallBanner(), detect
Cohesion: 0.20
Nodes (10): Application Logs, DELETE `/api/v1/admin/logs`, GET `/api/v1/admin/logs`, GET `/api/v1/admin/logs/export`, Log Retention, Query Parameters, Query Parameters, Response `200` (+2 more)
### Community 667 - "Community 667"
Cohesion: 0.40
Nodes (4): Altcha(), AltchaProps, FA_STRINGS, IntrinsicElements
### Community 672 - "Community 672"
Cohesion: 0.17
Nodes (11): تشخیص «ری‌استارت» سرور روی Coolify + رفع نویز لاگ + بررسی خطای ACME, زمینه, فایل‌های مرتبط, نکات مهم, وضعیت فعلی, وظایف, پروژه, ۱. کاهش نویز لاگ workerها (بدون تغییر رفتار) (+3 more)
@@ -2891,10 +2862,6 @@ Nodes (11): تشخیص «ری‌استارت» سرور روی Coolify + رفع
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/secretaries`, Query Parameters, Response `200`, Secretary Management
### Community 676 - "Community 676"
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/pre-registrations`, POST `/api/v1/admin/pre-registrations/{uuid}/approve`, POST `/api/v1/admin/pre-registrations/{uuid}/reject`, Pre-Registration Management
### Community 677 - "Community 677"
Cohesion: 0.40
Nodes (5): 37. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
@@ -2947,10 +2914,6 @@ Nodes (3): Errors, POST `/api/v1/sms/send` — ⛔ غیرفعال (Deprecated),
Cohesion: 0.17
Nodes (11): رفع خطاهای ارسال پیامک کاوه‌نگار در سرور prod (431 + Idle timeout), زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, پروژه (+3 more)
### Community 700 - "Community 700"
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/doctor/{uuid}`, Path Parameters, Response `200`
### Community 701 - "Community 701"
Cohesion: 0.17
Nodes (11): رفع خطای `Class "SoapClient" not found` در پرداخت ملت (سرور prod), زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, پروژه (+3 more)
@@ -3023,10 +2986,6 @@ Nodes (4): 40. 🔵 `POST` post, مثال Request, هدرهای اضافی, پا
Cohesion: 0.50
Nodes (4): 44. 🟢 `GET` list comment, هدرهای اضافی, پارامترهای Query, پاسخ‌ها
### Community 727 - "Community 727"
Cohesion: 0.67
Nodes (3): POST `/api/v1/admin/sms/template/{uuid}/approve`, Request Body (`application/json`), Response `200`
### Community 728 - "Community 728"
Cohesion: 0.50
Nodes (4): 46. 🟡 `PATCH` patch, مثال Request, هدرهای اضافی, پاسخ‌ها
@@ -3039,10 +2998,6 @@ Nodes (3): Errors, GET `/api/v1/notification-mobile/{target}`, Response `200`
Cohesion: 0.67
Nodes (3): 34. 🔵 `POST` image logo, هدرهای اضافی, پاسخ‌ها
### Community 732 - "Community 732"
Cohesion: 0.67
Nodes (3): 36. 🟢 `GET` get my rate, هدرهای اضافی, پاسخ‌ها
### Community 733 - "Community 733"
Cohesion: 0.67
Nodes (3): 42. 🔴 `DELETE` delete, هدرهای اضافی, پاسخ‌ها
@@ -3072,24 +3027,24 @@ Cohesion: 0.67
Nodes (3): 43. 🟢 `GET` get, هدرهای اضافی, پاسخ‌ها
## Knowledge Gaps
- **4031 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps`, `TenantInsurance`, `CoverageRow` (+4026 more)
- **4032 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps`, `TenantInsurance`, `CoverageRow` (+4027 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **151 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **146 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Altcha` connect `Community 367` to `Community 667`, `Community 485`?**
- **Why does `Altcha` connect `Community 367` to `Community 485`?**
_High betweenness centrality (0.068) - this node is a cross-community bridge._
- **Why does `BaseController` connect `Community 108` to `Community 6`, `Community 138`, `Community 139`, `Community 14`, `Community 654`, `Community 655`, `Community 15`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 294`, `Community 295`, `Community 552`, `Community 424`, `Community 300`, `Community 433`, `Community 308`, `Community 58`, `Community 59`, `Community 318`, `Community 64`, `Community 75`, `Community 77`, `Community 607`, `Community 480`, `Community 230`, `Community 104`, `Community 107`, `Community 109`, `Community 626`, `Community 380`, `Community 121`, `Community 122`, `Community 252`?**
_High betweenness centrality (0.037) - this node is a cross-community bridge._
- **Why does `ApiTestCase` connect `Community 86` to `Community 397`, `Community 534`, `Community 535`, `Community 541`, `Community 169`, `Community 690`, `Community 562`, `Community 565`, `Community 573`, `Community 574`, `Community 575`, `Community 594`, `Community 82`, `Community 729`, `Community 609`, `Community 484`, `Community 618`, `Community 497`, `Community 371`, `Community 632`?**
_High betweenness centrality (0.026) - this node is a cross-community bridge._
- **Why does `BaseController` connect `Community 108` to `Community 4`, `Community 6`, `Community 138`, `Community 139`, `Community 14`, `Community 654`, `Community 655`, `Community 15`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 295`, `Community 424`, `Community 300`, `Community 559`, `Community 433`, `Community 308`, `Community 439`, `Community 59`, `Community 318`, `Community 64`, `Community 75`, `Community 77`, `Community 82`, `Community 607`, `Community 480`, `Community 230`, `Community 104`, `Community 107`, `Community 109`, `Community 380`, `Community 121`, `Community 122`, `Community 252`?**
_High betweenness centrality (0.043) - this node is a cross-community bridge._
- **Why does `Version20260705070546` connect `Community 646` to `Community 399`?**
_High betweenness centrality (0.023) - this node is a cross-community bridge._
- **What connects `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps` to the rest of the system?**
_4031 weakly-connected nodes found - possible documentation gaps or missing edges._
_4032 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.04390451832907076 - nodes in this community are weakly interconnected._
_Cohesion score 0.05725490196078432 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.028985507246376812 - nodes in this community are weakly interconnected._
_Cohesion score 0.028481012658227847 - nodes in this community are weakly interconnected._
- **Should `Community 2` be split into smaller, more focused modules?**
_Cohesion score 0.09523809523809523 - nodes in this community are weakly interconnected._
@@ -0,0 +1 @@
{"nodes": [{"id": "users_hamed_pj_my_pj_clinic_pro_clinicpro_docs_api_captcha_md", "label": "captcha.md", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L1"}, {"id": "api_captcha_captcha_api_altcha", "label": "Captcha API (ALTCHA)", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L1"}, {"id": "api_captcha_get_api_v1_altcha_challenge", "label": "GET `/api/v1/altcha/challenge`", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L10"}, {"id": "api_captcha_response_200", "label": "Response `200`", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L14"}, {"id": "api_captcha_get_api_v1_altcha_config", "label": "GET `/api/v1/altcha/config`", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L31"}, {"id": "api_captcha_response_200_35", "label": "Response `200`", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L35"}, {"id": "api_captcha_\u0627\u0639\u0645\u0627\u0644_\u06a9\u067e\u0686\u0627_\u0631\u0648\u06cc_endpoint\u0647\u0627\u06cc_\u0645\u062d\u0627\u0641\u0638\u062a_\u0634\u062f\u0647", "label": "\u0627\u0639\u0645\u0627\u0644 \u06a9\u067e\u0686\u0627 \u0631\u0648\u06cc endpoint\u0647\u0627\u06cc \u0645\u062d\u0627\u0641\u0638\u062a\u200c\u0634\u062f\u0647", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L42"}, {"id": "api_captcha_\u062e\u0637\u0627\u06cc_\u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc_\u06a9\u067e\u0686\u0627_422", "label": "\u062e\u0637\u0627\u06cc \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u06a9\u067e\u0686\u0627 `422`", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L65"}, {"id": "api_captcha_\u0627\u0645\u0646\u06cc\u062a", "label": "\u0627\u0645\u0646\u06cc\u062a", "file_type": "document", "source_file": "docs/api/captcha.md", "source_location": "L78"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_docs_api_captcha_md", "target": "api_captcha_captcha_api_altcha", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L1", "weight": 1.0}, {"source": "api_captcha_captcha_api_altcha", "target": "api_captcha_get_api_v1_altcha_challenge", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L10", "weight": 1.0}, {"source": "api_captcha_get_api_v1_altcha_challenge", "target": "api_captcha_response_200", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L14", "weight": 1.0}, {"source": "api_captcha_captcha_api_altcha", "target": "api_captcha_get_api_v1_altcha_config", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L31", "weight": 1.0}, {"source": "api_captcha_get_api_v1_altcha_config", "target": "api_captcha_response_200_35", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L35", "weight": 1.0}, {"source": "api_captcha_captcha_api_altcha", "target": "api_captcha_\u0627\u0639\u0645\u0627\u0644_\u06a9\u067e\u0686\u0627_\u0631\u0648\u06cc_endpoint\u0647\u0627\u06cc_\u0645\u062d\u0627\u0641\u0638\u062a_\u0634\u062f\u0647", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L42", "weight": 1.0}, {"source": "api_captcha_\u0627\u0639\u0645\u0627\u0644_\u06a9\u067e\u0686\u0627_\u0631\u0648\u06cc_endpoint\u0647\u0627\u06cc_\u0645\u062d\u0627\u0641\u0638\u062a_\u0634\u062f\u0647", "target": "api_captcha_\u062e\u0637\u0627\u06cc_\u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc_\u06a9\u067e\u0686\u0627_422", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L65", "weight": 1.0}, {"source": "api_captcha_captcha_api_altcha", "target": "api_captcha_\u0627\u0645\u0646\u06cc\u062a", "relation": "contains", "confidence": "EXTRACTED", "source_file": "docs/api/captcha.md", "source_location": "L78", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "label": "HomeController.php", "file_type": "code", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L1"}, {"id": "controller_homecontroller_homecontroller", "label": "HomeController", "file_type": "code", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L10"}, {"id": "abstractcontroller", "label": "AbstractController", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "controller_homecontroller_homecontroller_construct", "label": ".__construct()", "file_type": "code", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L12"}, {"id": "controller_homecontroller_homecontroller_index", "label": ".index()", "file_type": "code", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L14"}, {"id": "response", "label": "Response", "file_type": "code", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L14"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "target": "altchaservice", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L5", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "target": "abstractcontroller", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L6", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "target": "response", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "target": "route", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L8", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_controller_homecontroller_php", "target": "controller_homecontroller_homecontroller", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L10", "weight": 1.0}, {"source": "controller_homecontroller_homecontroller", "target": "abstractcontroller", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L10", "weight": 1.0}, {"source": "controller_homecontroller_homecontroller", "target": "controller_homecontroller_homecontroller_construct", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L12", "weight": 1.0}, {"source": "controller_homecontroller_homecontroller", "target": "controller_homecontroller_homecontroller_index", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L14", "weight": 1.0}, {"source": "controller_homecontroller_homecontroller_index", "target": "response", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Shared/Controller/HomeController.php", "source_location": "L14", "weight": 1.0, "context": "return_type"}], "raw_calls": [{"caller_nid": "controller_homecontroller_homecontroller_index", "callee": "render", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Controller/HomeController.php", "source_location": "L17", "receiver": null}, {"caller_nid": "controller_homecontroller_homecontroller_index", "callee": "enabled", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Controller/HomeController.php", "source_location": "L18", "receiver": null}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "label": "CaptchaController.php", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L1"}, {"id": "captcha_captchacontroller_captchacontroller", "label": "CaptchaController", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L10"}, {"id": "basecontroller", "label": "BaseController", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "captcha_captchacontroller_captchacontroller_construct", "label": ".__construct()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L13"}, {"id": "captcha_captchacontroller_captchacontroller_challenge", "label": ".challenge()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15"}, {"id": "jsonresponse", "label": "JsonResponse", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15"}, {"id": "captcha_captchacontroller_captchacontroller_config", "label": ".config()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L26"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "basecontroller", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L5", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "attributes", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L6", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "jsonresponse", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "route", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L8", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "captcha_captchacontroller_captchacontroller", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L10", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "basecontroller", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L11", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_construct", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L13", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_challenge", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller_challenge", "target": "jsonresponse", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15", "weight": 1.0, "context": "return_type"}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_config", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L26", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller_config", "target": "jsonresponse", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L26", "weight": 1.0, "context": "return_type"}], "raw_calls": [{"caller_nid": "captcha_captchacontroller_captchacontroller_challenge", "callee": "createChallenge", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Captcha/CaptchaController.php", "source_location": "L23", "receiver": null}, {"caller_nid": "captcha_captchacontroller_captchacontroller_config", "callee": "enabled", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Captcha/CaptchaController.php", "source_location": "L34", "receiver": null}]}
+1 -1
View File
File diff suppressed because one or more lines are too long
+533 -431
View File
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -1550,8 +1550,8 @@
"semantic_hash": ""
},
"src/Shared/Controller/HomeController.php": {
"mtime": 1781248993.1596208,
"ast_hash": "dc0ad4e679dd2d45bd47e2c835e962d8",
"mtime": 1783669189.7814353,
"ast_hash": "d040ce564fe867e1a7f7b3dd23b44607",
"semantic_hash": ""
},
"src/Shared/Doctrine/JsonContains.php": {
@@ -2260,8 +2260,8 @@
"semantic_hash": ""
},
"config/packages/security.yaml": {
"mtime": 1783666096.9829946,
"ast_hash": "7236c28a514152be0d7dbf02834096c4",
"mtime": 1783669243.3956637,
"ast_hash": "aa39bbbcb9476e4663f7f7e8e513528c",
"semantic_hash": ""
},
"config/packages/twig.yaml": {
@@ -3245,8 +3245,8 @@
"semantic_hash": ""
},
"docker-compose.yml": {
"mtime": 1783608242.4596496,
"ast_hash": "466eb229daac6f54667dd7ecb20efadf",
"mtime": 1783669013.1104357,
"ast_hash": "d2b26d468f967197b376295721bcb435",
"semantic_hash": ""
},
"docs/DEPLOY.md": {
@@ -3805,8 +3805,8 @@
"semantic_hash": ""
},
"assets/admin/components/ui/Altcha.tsx": {
"mtime": 1783668418.3771482,
"ast_hash": "121352e982ca664204d71d9f779984f0",
"mtime": 1783669268.9603772,
"ast_hash": "7d54c6ce3a09652debabd3d8fdca8cfa",
"semantic_hash": ""
},
"src/Shared/Captcha/AltchaService.php": {
@@ -3815,8 +3815,8 @@
"semantic_hash": ""
},
"src/Shared/Captcha/CaptchaController.php": {
"mtime": 1783666097.1135097,
"ast_hash": "e6fccf870e0891e4d836baf6c27aa958",
"mtime": 1783669229.4041903,
"ast_hash": "4243706cbee22c8a57d27b48c55eeded",
"semantic_hash": ""
},
"src/Shared/Captcha/CaptchaGuard.php": {
@@ -3840,8 +3840,8 @@
"semantic_hash": ""
},
"docs/api/captcha.md": {
"mtime": 1783668751.744952,
"ast_hash": "977820fe357db7b73b2dc2de861eaae9",
"mtime": 1783669288.2668343,
"ast_hash": "56e9b036792f8b79aafd0f60dbd546e9",
"semantic_hash": ""
}
}
+11
View File
@@ -22,4 +22,15 @@ class CaptchaController extends BaseController
{
return new JsonResponse($this->altcha->createChallenge());
}
#[OA\Get(
path: '/api/v1/altcha/config',
summary: 'وضعیت فعال/غیرفعال بودن کپچا — کلاینت‌ها بر اساس آن widget را رندر می‌کنند',
responses: [new OA\Response(response: 200, description: '{ "enabled": bool }')]
)]
#[Route('/api/v1/altcha/config', methods: ['GET'])]
public function config(): JsonResponse
{
return new JsonResponse(['enabled' => $this->altcha->enabled()]);
}
}
+6 -1
View File
@@ -2,15 +2,20 @@
namespace App\Shared\Controller;
use App\Shared\Captcha\AltchaService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class HomeController extends AbstractController
{
public function __construct(private readonly AltchaService $altcha) {}
#[Route('/', name: 'home', methods: ['GET'])]
public function index(): Response
{
return $this->render('public/home.html.twig');
return $this->render('public/home.html.twig', [
'altcha_enabled' => $this->altcha->enabled(),
]);
}
}
+2
View File
@@ -557,8 +557,10 @@
</div>
</div>
{% if altcha_enabled %}
<!-- ALTCHA captcha — proof-of-work در پس‌زمینه (بدون تعامل کاربر) -->
<altcha-widget id="regAltcha" challengeurl="/api/v1/altcha/challenge" auto="onload" style="display:block;margin-top:16px" strings='{"label":"من ربات نیستم","verifying":"در حال بررسی...","verified":"تأیید شد","waitAlert":"در حال بررسی... لطفاً منتظر بمانید.","error":"احراز هویت ناموفق بود. کمی بعد دوباره تلاش کنید.","expired":"احراز هویت منقضی شد. دوباره تلاش کنید."}'></altcha-widget>
{% endif %}
<!-- Error / Success -->
<div id="regMsg" style="display:none;margin-top:14px;padding:12px 16px;border-radius:10px;font-size:13px"></div>