fix: release QA hardening across processing, media, security, and CI gates (#649)

A release-readiness QA pass over the whole product. The commits split into
defects a user would hit and gates that were reporting green while measuring
nothing.

## Fixes that change behaviour

Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so
request.ip came from a client-set header and a forged X-Forwarded-For got past
the login limiter. The default is now a private-network trust list.

A transient Postgres outage stranded in-flight jobs, leaving finished output on
disk with no row pointing at it. A reconciler now resolves those rows and adopts
the bytes rather than dropping the work.

A Redis connection that moved to a new address wedged every read-blocked
consumer, so completions stopped signalling while health still answered 200.
Socket timeouts plus subscriber pings recover it.

Installing more than one AI bundle left the shared venv multi-versioned and
silently broke three tools. The installer now reconciles distributions to one
version each.

Converting an image to JXL at quality 1 through 4 returned a 500, because
libjxl 0.7 rejects the distance those values compute. The quality is floored at
what the encoder honours. A missing ffmpeg was also reported to the user as a
corrupt upload; it now says the engine is unavailable.

RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at
0.22.2, and the release scan was split so it can fail on an unfixed critical
instead of hiding it behind ignore-unfixed.

## Gates that could not fail

Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs
build; coverage discarded its whole report on any failing test; the lint gate
skipped root tests, scripts, and two workspaces; and several generated matrices
counted a host missing ffmpeg as a passing tool. Each now measures what it
claims.

Full evidence and the outstanding release items are tracked locally and are not
part of this branch.
This commit is contained in:
SnapOtter
2026-07-27 15:37:30 +08:00
committed by GitHub
parent bc32f86a07
commit d10d0f544f
855 changed files with 54564 additions and 13092 deletions
+13 -10
View File
@@ -1,8 +1,9 @@
---
description: "إدارة المستخدمين، والأدوار المدمجة والمخصصة، والأذونات، ومفاتيح API، والفرق، والجلسات، وسجل التدقيق في SnapOtter."
i18n_source_hash: 5e28af686c96
i18n_source_hash: bea8955f3aff
i18n_provenance: human
i18n_output_hash: 2d5801eeb616
i18n_output_hash: 07065d77a8f0
i18n_hash_version: 2
---
# المستخدمون والأدوار والأذونات {#users-roles-permissions}
@@ -82,12 +83,12 @@ i18n_output_hash: 2d5801eeb616
| `pipelines:all` | عرض وإدارة خطوط أنابيب جميع المستخدمين |
| `settings:read` | عرض إعدادات النسخة |
| `settings:write` | تعديل إعدادات النسخة |
| `users:manage` | إنشاء وتحديث وحذف حسابات المستخدمين |
| `users:manage` | إنشاء وإدارة حسابات المستخدمين ضمن حدود سلطة الممثل |
| `teams:manage` | إنشاء وتحديث وحذف الفرق |
| `features:manage` | تثبيت وإدارة حزم ميزات الذكاء الاصطناعي |
| `system:health` | الوصول إلى نقاط نهاية الصحة والجاهزية |
| `audit:read` | عرض سجل التدقيق وسرد الأدوار |
| `compliance:manage` | إدارة دورة حياة GDPR وميزات الامتثال |
| `compliance:manage` | إدارة دورة حياة اللائحة العامة لحماية البيانات وميزات الامتثال؛ تظل عمليات المستخدم المدمرة مقيدة بالسلطة |
| `webhooks:manage` | تكوين خطافات الويب الصادرة |
| `security:manage` | إدارة إعدادات الأمان (قائمة IP المسموح بها، فرض SSO) |
@@ -110,15 +111,17 @@ curl -X POST http://localhost:1349/api/v1/roles \
يجب أن تكون أسماء الأدوار من 2 إلى 30 حرفاً، أحرف وأرقام صغيرة مع شرطات وشرطات سفلية.
### الأذونات المحجوزة للمسؤول {#admin-reserved-permissions}
### حدود الإدارة المفوضة {#delegated-administration-boundaries}
ثلاثة أذونات محجوزة للأدوار المدمجة ولا يمكن تعيينها للأدوار المخصصة:
يمكن تفويض كافة الأذونات البالغ عددها 17 من خلال الأدوار المخصصة، لكن الإذن الإداري لا يجعل هذا الدور مكافئًا لدور `admin` المضمن. طفرات المستخدم المصرح بها من قبل `users:manage`، والعمليات التدميرية المصرح بها من قبل `compliance:manage`، وإدارة الأدوار المخصصة المصرح بها من قبل `security:manage` مقيدة بالسلطة الحالية للممثل:
- `compliance:manage`
- `webhooks:manage`
- `security:manage`
- الأدوار المضمنة تتبع `admin` > `editor` > `user`؛ الأدوار المخصصة موجودة أسفل الأدوار المضمنة.
- يجب أن تكون أذونات الهدف متضمنة في أذونات الفاعل **الفعالة**. وبالتالي، لا يمكن لمفتاح واجهة برمجة التطبيقات (API) ذو النطاق ممارسة الأذونات المحذوفة من نطاقه.
- يجب أن يتم احتواء الوصول إلى أداة الدور المستهدف من خلال الوصول إلى الأداة الخاصة بالممثل.
- يتم التحقق من الحساب المعطل مقابل دوره الأصلي عندما يتم تسجيل هذا الدور كـ `disabled:<original-role>`.
- يتطلب حذف دور مخصص أيضًا صلاحية تعيين احتياطي `user` المضمن؛ يظل الأعضاء المعطلون معطلين مثل `disabled:user`.
ترفض واجهة برمجة الأدوار أي طلب يتضمن هذه الأذونات. فقط الدور المدمج `admin` لديه الوصول إليها.
تعد بيانات الاعتماد والتكوين العالمية أكثر صرامة: يتطلب إصدار أو إلغاء الرمز المميز SCIM واستيراد تكوين المثيل دور `admin` المدمج مع سلطة إدارية فعالة كاملة.
### الأذونات على مستوى الأداة {#tool-level-permissions}