docs(api): document the permission registry and correct two enforcement claims
clinic.md's default envelope is regenerated from the running app, so it now shows all 17 resources instead of 13, including services with its full create/delete actions. Both role docs point at permission.md for the shared registry and spell out the merge rule that makes new resources work on existing rows: deleting a key means "take the default", not "deny" — denying requires an explicit false. A systematic sweep over every gated route with all permissions off found two places where the docs claimed enforcement that does not exist: - GET /api/v1/subscription/my returns 200 with every permission off. Only trial is gated. - ServiceCatalogController has no gate at all. Both are pre-existing and both are left as-is rather than half-fixed: their endpoints are also consumed by the booking and subscription flows, where a hard gate would break secretaries who legitimately need them. The docs now say so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -150,13 +150,13 @@ Create a secretary for a doctor.
|
||||
| `insurances` | `InsuranceController` (insurance-pricing, tenant-insurances, service-coverage, doctor-insurance) | view/create/update/delete |
|
||||
| `inventory` | `InventoryController` (items + packages) | view/create/update/delete |
|
||||
| `tags` | `TenantTagController` (لیست با `tags.view` یا `patients.view`؛ نوشتنها با `tags.*`) | view/create/update/delete |
|
||||
| `services` | `ClinicServiceController` (sections + items). owner از محیطِ فعال با `SecretaryAccessChecker::resolveOwnerEntity` حل میشود چون `EntityContextResolver` منشی را نمیشناسد. گیتِ `services.*` پیش از گیتِ اشتراک اجرا میشود | view/create/update/delete |
|
||||
| `services` | `ClinicServiceController` (sections + items). ⚠ `ServiceCatalogController` (دستهبندی سرویسها، گروهها، روابط) گِیت **ندارد** — اندپوینتهایش در جریانِ ثبت نوبت هم مصرف میشوند و بستنِ یکجا نوبتدهی منشی را میشکند. owner از محیطِ فعال با `SecretaryAccessChecker::resolveOwnerEntity` حل میشود چون `EntityContextResolver` منشی را نمیشناسد. گیتِ `services.*` پیش از گیتِ اشتراک اجرا میشود | view/create/update/delete |
|
||||
| `staff` | `StaffController` (resolveEntity منشیآگاه) | view/create/update/delete |
|
||||
| `discounts` | `DiscountController` (CRUD؛ `suggestions` جزو flowِ جلسه است و با discounts گِیت نمیشود) | view/create/update/delete |
|
||||
| `sms` | `SmsWalletController` (balance/charge/logs/settings). endpointهای admin (قالب/ارسال) همچنان `ROLE_ADMIN` | view/create/update |
|
||||
| `appointment_settings` | `AppointmentSettingsController::denyDoctorAccess` → `SecretaryAccessChecker::canForDoctor` (اسکوپِ پزشکِ تخصیصیافته + توگل). `clinic_uuid` برای محیطِ کلینیک لازم است | view/update |
|
||||
| `clinic_doctors` (فقط کلینیک) | `ClinicController::detachDoctor` (delete)، `ClinicDoctorPermissionController` (view/update)، `ClinicInvitationController` (create/view/update/delete) via `SecretaryAccessChecker::canForClinic` | view/create/update/delete |
|
||||
| `subscription` | `SubscriptionController::my` (view) و `trial` (create)، `PaymentController::initiateSubscription` (create). resolveEntity از قبل منشیآگاه است | view/create |
|
||||
| `subscription` | `SubscriptionController::trial` (create)، `PaymentController::initiateSubscription` (create). ⚠ خواندنِ `GET /api/v1/subscription/my` گِیت **ندارد** — با همهٔ مجوزها خاموش هم ۲۰۰ میدهد؛ چون FeatureGate و useSubscription همهجا صداش میزنند، بستنش نیاز به بررسی جداگانه دارد | create |
|
||||
|
||||
نقشهای غیرمنشی (`ROLE_CLINIC`/`ROLE_DOCTOR`/`ROLE_ADMIN`) از این چک عبور میکنند (`canOrNonSecretary` برایشان `true`). منشیِ بدون رابطهٔ فعال/context هیچ مجوزی ندارد → همهچیز `403`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user