لفرق أمن المعلومات ومراجعي التطبيقات
الأمان في Peel
باختصار: يُشفَّر محتوى اللوحة في المتصفح بمفتاح يعيش في جزء الرابط، فتخزّن خوادمنا وتنقل نصًا مشفّرًا لا تستطيع قراءته. وإليك الطريقة بالضبط، وأين تقع الحدود.
الخلاصة
- نص البطاقات والأسماء وعناوين اللوحات والأصوات والملصقات مشفّرة بـ AES-256-GCM بمفتاح لوحة يُولَّد في المتصفح. ينتقل المفتاح في جزء الرابط (
#k=) ولا يُرسل إلى أي خادم أبدًا. - إجراءات الميسّر وترويسة اللوحة واللقطات موقّعة بمفتاح Ed25519 الخاص بالميسّر. ومعرّف اللوحة مشتق من هذا المفتاح، فيكتشف العملاء أي استبدال للمفاتيح.
- البطاقات المخفية مختومة للميسّر (صندوق X25519 مختوم) حتى الكشف، ومربوطة بالتزامات مملّحة فلا يمكن تبديل النص المكشوف.
- مجهولة الهوية افتراضيًا: العمليات لا تحمل معرّف كاتب؛ والأصوات والتفاعلات تستخدم معرّفًا عشوائيًا لكل لوحة.
- المشاركون لا يصادقون هويتهم أبدًا. لا أدوات تحليلات، ولا إعلانات، ولا سكربتات طرف ثالث باستثناء Paddle.js في صفحة الدفع.
- Cloudflare فقط. اللوحات غير المُطالَب بها تُحذف بعد 60 يومًا من آخر زيارة.
كيف تتدفق البيانات
جزء الرابط (كل ما يلي #) يتعامل معه المتصفح وليس جزءًا من طلب HTTP. وهناك يضع Peel مفتاح اللوحة.
نموذج التهديدات
نصمّم بحيث لا يعرف خادم مخترق بالكامل أو فضولي، بما في ذلك نحن، إلا أقل القليل عمّا يقوله الفريق.
ما نحميه
- نص البطاقات، واختيارات صور GIF، واسم الكاتب في وضع الأسماء.
- أسماء المشاركين وصورهم الرمزية، واسم اللوحة، وعناوين القوالب المخصّصة.
- من صوّت أو تفاعل على ماذا، ومن كتب أي بطاقة.
- سلامة جلسة الاسترجاع: المراحل والكشف وقرارات الميسّر لا يمكن تزويرها.
الخصوم الذين نأخذهم في الحسبان
- خوادمنا نفسها، أو موظف داخلي سيئ النية، أو من يخترق تخزيننا: يحصلون على نص مشفّر وبيانات وصفية.
- مهاجم على الشبكة: TLS في كل مكان؛ والمفتاح لا يعبر الشبكة أبدًا.
- خادم يستبدل المفاتيح: معرّف اللوحة مشتق من المفتاح العام للميسّر، والعملاء يتحققون من الترويسة الموقّعة.
- مشارك يريد التلصّص أو التزوير: البطاقات المخفية مختومة للميسّر؛ وعمليات الميسّر تحتاج إلى توقيعه؛ وتعديل البطاقات يحتاج إلى مفتاح البطاقة.
- ميسّر يعيد النشر عن كاتب غير متصل: الالتزامات تمنعه من تغيير النص.
خارج النطاق، بصراحة
- كل من يملك رابط المشاركين يستطيع قراءة اللوحة. الرابط هو آلية التحكم بالوصول. شاركه كما تشارك اللوحة نفسها.
- جهاز مخترق، أو إضافة متصفح خبيثة، أو شخص ينظر من فوق كتفك.
- تحليل حركة المرور: يرى الخادم التوقيت والأحجام والأعداد (راجع خريطة البيانات).
- حجب الخدمة من جهة الخادم: يستطيع إسقاط الرسائل أو تأخيرها، لكن لا قراءتها ولا تزويرها.
التشفير
كل العناصر الأولية تأتي من واجهة WebCrypto في المتصفح. لا تشفير مُصنَّع يدويًا، ولا مكتبات تشفير من طرف ثالث.
| المفتاح | الخوارزمية | الاستخدام |
|---|---|---|
| K_board | AES-256-GCM، مع IV عشوائي بطول 96 بت | يشفّر كل عملية ولقطة وتحديث حضور. البيانات الإضافية تربط معرّف اللوحة ونوع العملية ومعرّف العملية، فلا يمكن إعادة تشغيل النص المشفّر في لوحة أو موضع آخر. يعيش فقط في جزء الرابط #k=. |
| K_owner | Ed25519 | صلاحية الميسّر. يوقّع عمليات الميسّر (المرحلة، المؤقت، تسليط الضوء، القالب، الإعدادات، فتح الأصوات، إخفاء بطاقة) وترويسة اللوحة واللقطات. عدّاد متزايد تمامًا يمنع إعادة التشغيل. موجود في رابط الميسّر فقط (&o=). |
| معرّف اللوحة | SHA-256، أول 80 بت، base32 | مشتق من المفتاح العام للميسّر، فالمعرّف نفسه يُثبت أي مفتاح يملك اللوحة. يرفض العملاء أي ترويسة لا يطابق تجزئة مفتاحها المعرّف. |
| K_fac | صندوق مختوم X25519: X25519 مؤقت + HKDF-SHA256 + AES-256-GCM | تُختم البطاقات المخفية بالمفتاح العام للميسّر أثناء الكتابة. ولا يفتحها إلا رابط الميسّر (&f=). |
| مفاتيح البطاقات | Ed25519، مفتاح لكل بطاقة | يحتفظ به الكاتب وحده. التعديلات والكشف موقّعة به: أصالة دون كشف الهوية. |
| الالتزامات | HMAC-SHA256 مع ملح عشوائي بطول 128 بت | تنشر البطاقة المخفية التزامًا بمحتواها. عند الكشف يُنشر المحتوى والملح ويتحقق منهما كل عميل، فلا يستطيع أحد تبديل النص. |
| الحضور | AES-256-GCM بالمفتاح K_board | الأسماء والصور الرمزية ومؤشرات الكتابة مشفّرة مثل كل شيء آخر. |
| حزمة المفاتيح | HKDF-SHA256 من PRF لمفتاح المرور أو من رمز الاسترداد، AES-256-GCM | يمكن للميسّرين المسجّلين مزامنة مفاتيح اللوحات بين الأجهزة. تُشفَّر الحزمة على الجهاز؛ ولا يخزّن الخادم إلا نصًا مشفّرًا ومفاتيح مغلّفة. |
رسائل التوقيع مفصولة النطاق (مثل peel/sig/v1 وpeel/header/v1 وpeel/snap/v1)، فلا يمكن إعادة استخدام توقيع غرض ما لغرض آخر.
إخفاء الهوية
- العمليات لا تحمل أي معرّف للكاتب. لا يستطيع الخادم ربط بطاقة بشخص، ولا الميسّر افتراضيًا.
- الأصوات والتفاعلات مرتبطة بمعرّف عشوائي خاص بكل لوحة، غير مرتبط بأي اسم.
- مؤشرات الكتابة تُظهر أن أحدًا يكتب، لا ما يكتبه.
- وضع الأسماء إعداد صريح في اللوحة؛ وعندها ينتقل اسم الكاتب داخل البطاقة المشفّرة.
- المشاركون لا يسجّلون الدخول أبدًا، فلا يوجد حساب يمكن الربط به.
خريطة البيانات
كل ما نحتفظ به، وأين يعيش، ومن يستطيع قراءته، وكم يبقى.
| البيانات | المكان | من يستطيع القراءة | مدة الحفظ |
|---|---|---|---|
| البطاقات، الأصوات، التفاعلات، الملصقات، الإجراءات، اسم اللوحة، عناوين القوالب المخصّصة | تخزين Durable Object، كنص مشفّر | من يملكون رابط اللوحة | حتى تُحذف اللوحة |
| غلاف العملية: النوع، التسلسل والوقت على الخادم، الحجم، عدّاد الميسّر | تخزين Durable Object | Peel | حتى تُحذف اللوحة |
| أسماء المشاركين، الصور الرمزية، الكتابة | تُنقل كنص مشفّر؛ وتُحفظ في الذاكرة أثناء الاتصال | من يملكون رابط اللوحة | أثناء الاتصال |
| حالة اللوحة: المرحلة، أعداد المشاركين والبطاقات، معرّف قالب الكتالوج، علامة القفل، وقت الإنشاء وانتهاء الصلاحية | Durable Object، D1؛ رسائل Slack/Teams إن كانت مثبّتة | Peel؛ وقناتك في Slack/Teams | طوال عمر اللوحة |
| حساب الميسّر: معرّف المزوّد، الاسم، البريد الإلكتروني إن تمت مشاركته، المزوّدون المرتبطون، تاريخ الإنشاء، الجلسة | D1 | Peel | حتى تحذف الحساب |
| حزمة المفاتيح والمفاتيح المغلّفة | D1، كنص مشفّر | أنت فقط (مفتاح المرور أو رمز الاسترداد) | حتى تحذف الحساب |
| الباقة، حالة الاشتراك، معرّفات العميل والاشتراك في Paddle | D1؛ Paddle | Peel، Paddle | حسب ما يقتضيه قانون الضرائب |
| معرّفات مساحة العمل والقناة والرسائل في Slack/Teams؛ رمز البوت (مشفّر بـ AES-GCM) | D1 | Peel | حتى إلغاء التثبيت |
| عنوان IP | حافة شبكة Cloudflare، مؤقتًا (التسليم، حدود المعدّل) | Cloudflare، ومحدِّد المعدّل في Peel | لا يُخزَّن في قواعد بياناتنا |
| عدّادات يومية (اللوحات المنشأة، المراحل المُنجزة) | D1 | Peel | إجمالية فقط، بلا معرّفات |
ما يستطيعه خادمنا وما لا يستطيعه
يستطيع
- رؤية أنواع العمليات وأحجامها وتوقيتها، والمرحلة، وأعداد المشاركين والبطاقات، ومعرّف قالب الكتالوج، وعلامة القفل.
- إسقاط العمليات أو تأخيرها أو رفض تسليمها (حجب الخدمة).
- رؤية عناوين IP على حافة الشبكة.
- عدّ اللوحات والمراحل المُنجزة، بشكل إجمالي.
- حذف لوحة (انتهاء الصلاحية، بلاغات إساءة الاستخدام).
لا يستطيع
- قراءة نص البطاقات أو الأسماء أو عناوين اللوحات أو عناوين القوالب المخصّصة أو الأصوات أو الملصقات.
- قراءة البطاقات المخفية قبل الكشف (ولا حتى بعده).
- تزوير إجراءات الميسّر: فهي تحتاج إلى توقيعه.
- استبدال المفاتيح بمفاتيحه: معرّف اللوحة يفضحه.
- تغيير النص المكشوف لبطاقة: الالتزامات وتواقيع البطاقات تفضحه.
- معرفة من كتب أي بطاقة.
كما في أي تطبيق ويب، أنت تثق بالشيفرة التي نقدّمها. ونُبقي هذا السطح صغيرًا: سياسة أمان محتوى صارمة، وscript-src مقصور على نطاقنا، ولا سكربتات طرف ثالث، والبروتوكول متاح للمراجعة عند الطلب.
Slack وMicrosoft Teams
- الرسائل تحمل رابط اللوحة وبيانات وصفية (العنوان، المرحلة، الأعداد). ولا يُرسل نص البطاقات إلا عندما ينشر الميسّر ملخصًا ويؤكده.
- بطاقة الانضمام تحتوي على رابط المشاركين، وهو يتضمن المفتاح. كل من يستطيع قراءة تلك القناة يمكنه الانضمام، تمامًا كلصق الرابط فيها.
- معاينات الروابط تعرض المرحلة والأعداد فقط، ولا تعرض المحتوى أبدًا.
- صلاحيات Slack:
commandsوchat:writeوlinks:readوlinks:write؛ وusers:readفقط عندما يفعّل الفريق الإشارات. - رموز البوت مشفّرة أثناء التخزين (AES-GCM، والمفتاح محفوظ كسرّ في Worker). ويتم التحقق من تواقيع طلبات Slack ورموز Bot Framework في كل طلب.
- إلغاء تثبيت التطبيق يوقف كل النشر ويحذف رموزه.
الويب والبنية التحتية
- Cloudflare فقط: Pages وWorkers وDurable Objects وD1 وR2 وKV على حساب 1801 Labs. لا خوادم أخرى.
- TLS في كل مكان، وHSTS، وسياسة أمان محتوى صارمة.
- لا أدوات تحليلات، ولا إعلانات، ولا سكربتات طرف ثالث. الاستثناء الوحيد هو Paddle.js، ويُحمَّل في صفحة الدفع فقط.
- ملف تعريف ارتباط واحد، للميسّرين المسجّلين فقط:
peel_session، بخصائص httpOnly وSecure وSameSite=Lax. - البحث عن صور GIF والوسائط يمر عبر واجهتنا البرمجية، فلا تصل عناوين IP الخاصة بالمشاركين إلى GIPHY أبدًا.
- الخطوط والملفات مستضافة ذاتيًا. لا خطوط من CDN، ولا بكسلات تتبّع.
- حدود للمعدّل لكل IP ولكل لوحة؛ وبلاغات إساءة الاستخدام، وقفل بيد الميسّر.
الحسابات ومدة الاحتفاظ
- المشاركون لا يصادقون هويتهم أبدًا. الميسّرون يسجّلون الدخول عبر Google (أو Entra ID عبر Teams) فقط لحفظ اللوحات أو استخدام الميزات المدفوعة.
- يخزّن الحساب معرّفًا، والاسم والبريد الإلكتروني من مزوّد الخدمة، وحزمة مفاتيح مشفّرة تُفتح بمفتاح مرور (WebAuthn PRF) أو برمز استرداد. تسجيل الدخول يمنح الملكية، لا الوصول إلى المحتوى.
- المطالبة بلوحة تُثبت الملكية بتوقيع الميسّر. مفاتيح اللوحة لا تُرسل أبدًا.
- اللوحات بدون حساب تُحذف بعد 60 يومًا من آخر زيارة؛ وكل زيارة تعيد العدّاد من البداية. تنبيهات Durable Object تحذف التخزين.
- حذف حسابك يحذف الجلسات وحزمة المفاتيح ومكتبتك، ويعيد إلى لوحاتك مهلة الـ60 يومًا.
الإفصاح المسؤول
وجدت شيئًا؟ أخبرنا أولًا وسنعمل معك. نؤكد استلام البلاغات خلال ثلاثة أيام عمل.
- نرجو منحنا وقتًا معقولًا (نسعى إلى 90 يومًا) للإصلاح قبل الإفصاح.
- اختبر على لوحاتك وحساباتك الخاصة. لا تصل إلى بيانات الآخرين ولا تُضعف الخدمة.
- لن نتخذ إجراءات قانونية ضد الأبحاث التي تُجرى بحسن نية وتلتزم بهذه القواعد.
- جهة اتصال قابلة للقراءة آليًا:
/.well-known/security.txt.
عملاء باقة Company يحصلون على حزمة مراجعة أمنية (إجابات الاستبيانات، المعالجون الفرعيون، تدفقات البيانات). اتفاقية معالجة البيانات · الخصوصية