pdppl-pii-audit
> متى تُستعمل: "PDPPL personal-data audit: PII encryption, leaks, consent, erasure, breach. Trigger: PDPPL, PII, privacy, nationalid. بيانات شخصية، خصوصية، تشفير"
SKILL.md.claude/skills/pdppl-pii-audit/SKILL.md
GitHubمتى تُستعمل: "PDPPL personal-data audit: PII encryption, leaks, consent, erasure, breach. Trigger: PDPPL, PII, privacy, national_id. بيانات شخصية، خصوصية، تشفير"
مدقّق PDPPL لـ SchoolOS
الغرض: أن يخرج كلُّ بيانٍ شخصيٍّ في المنصّة مشفَّراً حيث يلزم، ومستوراً حيث يُعرض بالجملة، ومُدقَّقاً حيث يُصدَّر، وغائباً عن السجلّات — بأدوات المنصّة القائمة لا باختراعٍ جديد.
المنصّةُ مدرسيّة: بياناتُ الطلبة بياناتُ أطفال، وهي والصحّةُ «ذاتُ طبيعةٍ خاصّة» بنصّ م.16 (المصدر: references/00-pdppl-articles.md).
متى تُستعمل ومتى لا
- نعم: حقلٌ أو نموذجٌ جديد، مُسلسِلٌ أو قالبُ قائمة، مُصدِّرُ PDF/Excel، سطرُ تسجيل، رفعُ ملفّ، تدفّقٌ لوليّ الأمر، مراجعةُ دمج.
- لا: صياغةُ رأيٍ قانونيٍّ ملزم — هذه إرشاداتٌ هندسيّة، والحكمُ القانونيّ للجهة المختصّة (الوكالة الوطنيّة للأمن السيبرانيّ) وللـDPO.
الإجراء
- شغّل الفاحص من شجرة عملك (يجد الجذرَ بـ
manage.py؛ الإصدارُ القديم كان يُعلن «سليم» في كلّ شجرة عمل):python .claude/skills/pdppl-pii-audit/scripts/pii_scan.py [--app clinic] [--include-tests]النتائجُ مرشَّحات؛ الإيجابيّاتُ الكاذبة المعروفة فيreferences/30-scanner.md. - صنِّف كلَّ حقلٍ جديد: ذو طبيعةٍ خاصّة (صحّة، نفسيّ، دين، عِرق — وكلُّ ما للطفل) ← تشفيرٌ إلزاميّ ودورٌ محدود؛ تعريفيٌّ (الرقم الشخصيّ، الهاتف، العنوان، الجواز، الميلاد، الصورة) ← تشفيرٌ أو ثلاثيّةُ HMAC؛ تشغيليّ (الصفّ، الدرجة، الحضور) ← صلاحيّاتٌ لا تشفير.
- مرّ على المسارات الثمانية وقارن بأداتها القائمة (الجدول في
references/10-platform-controls.md): التخزين · العرض الجماعيّ · التصدير · السجلّات وSentry · الصور المرفوعة · الموافقة · المحو · الاحتفاظ. - شغّل الحرّاس ذوي الصلة (الأسماء في
references/10-platform-controls.md) بأمر الاختبار فيCLAUDE.md. - اكتب الحكم: البندُ، ومسارُه:سطرُه، والمادّةُ المتحقَّقة، والأداةُ القائمة التي تعالجه، وما يحتاج قرارَ الـDPO.
القواعد وأسبابها
- الرقمُ الشخصيّ في كشفٍ جماعيٍّ مستورٌ دائماً (
|mask_idفي القالب،mask_national_idفي بايثون)، وكاملٌ فقط في وثيقةٍ فرديّةٍ مسمّاةٍ فيtests/test_national_id_never_bulk.py. السبب: صفحةٌ بخمسين رقماً تُصوَّر وتُرسَل، والقارئ يحتاج أن يميّز لا أن يعرف. المصدر:core/privacy.py. - كلُّ ملفٍّ يخرج من المنصّة يترك سطرَ تدقيق بـ
core.audit_export.log_export(نوعٌ، وعددُ صفوف، ورايةُ «رقمٌ كامل») — بلا اسمٍ ولا رقم. السبب: الملفُّ المنزَّل معالجةٌ تُخرج البيانَ من حوزة المنصّة. - لا قيمةَ شخصيّةَ في سطر تسجيل — المعرّفُ (UUID) وحده.
PIIMaskingFilterيقنّع الأنماطَ (رقم، هاتف، بريد) في الإنتاج فقط، والاسمُ العربيّ لا نمطَ له فلا يُقنَّع. المصدر:core/logging_filters.py،tests/test_log_data_minimization.py. AuditLogلا يُحذف ولا يُعدَّل — إلّا فصلُ هويّة الفاعل (user=None) عند المحو. السبب: أثرُ المساءلة يبقى والشخصُ يُفصل عنه. المصدر:core/models/audit.py::_ImmutableQuerySet.- نموذجٌ جديدٌ فيه مفتاحٌ إلى الطالب أو ملفٌّ مرفوع يُضاف إلى قائمتَي
governance/erasure_service.py(_lazy_student_fk_models،_lazy_file_field_models). السبب: المحوُ يمرّ على قائمةٍ صريحة، ولا حارسَ يكتشف النموذجَ المنسيّ. - رقمُ المادّة من الجدول المتحقَّق لا من تعليقات الشيفرة — التعليقاتُ متضاربة (م.8 وم.11 وم.13 وم.18 وم.19 لموضوعاتٍ لا تطابقها). السبب: اقتباسٌ خاطئٌ في تقرير امتثالٍ أسوأُ من غيابه.
- البيانُ الخاصّ الجديد (صحّيّ، نفسيّ…) قرارُ DPO قبل أن يكون شيفرة: م.16 تشترط تصريحاً من الإدارة المختصّة. والـDPO هو المالكُ نفسُه (ذاكرة
user_dpo_role.md) — اعرض عليه مباشرةً. - العملُ في شجرة عملك وقواعدُ الإيداع والدفع في مهارتَي
schoolos-flowوschoolos-git-safety.
فخاخٌ حقيقيّة
- خطأ:
phone = models.CharField(...)في نموذج وليّ أمرٍ جديد. الصواب:EncryptedTextFieldإن لم يُبحث به، وإلّا الثلاثيّة (خامٌ +_encrypted+_hmac) كما فيcore/models/user.py، وتعبئةُ القديم بأمر إدارةٍ عبر ORM (populate_phone_encryptionمثالاً). - خطأ: البحثُ في
EncryptedTextFieldبـfilter(field=q)— التشفيرُ غيرُ حتميّ فلا يطابق شيئاً. الصواب:hmac_field(q)على عمود_hmac. - خطأ:
fields = "__all__"في مُسلسِل نموذجٍ فيه بياناتٌ شخصيّة. الصواب: قائمةٌ صريحة، ونسخةٌ «آمنة» بالاسم (UserSafeSerializer)، وستر الرقم كما يفعلUserBriefSerializer.to_representation. - خطأ:
logger.info("طالب %s (national_id=%s)", user.full_name, nid)— موجودٌ اليوم فيstudent_affairs/services.py. الصواب:logger.info("طالب id=%s", user.pk). - خطأ:
{{ s.national_id }}داخل{% for %}. الصواب:{{ s.national_id|mask_id }}— والحارسُ يسقط الأوّل. - خطأ:
request.FILES["photo"]يُحفظ كما وصل. الصواب:core.photo_privacy.clean_photo(يمحو EXIF/GPS) — تقريرٌ طبّيٌّ من جوّالٍ يحمل موقعَ البيت. - خطأ: «
blood_typeمشفّرة كبقيّة السجلّ الصحّيّ». الصواب: هيCharFieldصريحٌ اليوم (clinic/models.py) — بندٌ مفتوحٌ لقرار الـDPO لا حقيقةٌ مفروغٌ منها. - خطأ: «الموعدُ النظاميّ للإخطار في نصّ القانون 72 ساعة». الصواب: القانون (م.14) يوجب الإخطار؛ الـ72 ساعة من إرشاد الوكالة للجهات الخاضعة، و
BreachReport.ncsa_deadlineيحسبها.
المراجع
| الملف | متى تقرأه |
|---|---|
references/00-pdppl-articles.md |
قبل أن تكتب رقمَ مادّةٍ أو تحكم أنّ شيئاً «يشترطه القانون» |
references/10-platform-controls.md |
لتعرف الأداةَ القائمة والحارسَ لكلّ مسارٍ من الثمانية |
references/20-patterns.md |
حين تكتب الإصلاح: حقلٌ مشفَّر، مُسلسِلٌ آمن، تسجيلٌ آمن، محوٌ، تصدير |
references/30-scanner.md |
حين تقرأ مخرجَ الفاحص أو تعدّله |
references/99-test-cases.md |
لاختبار تفعيل المهارة وجودة جوابها |