Summary

  • يقترح draft-saha-aadp-bound-permit-00، المنشور في 29 سبتمبر، تصريحاً قصير العمر يحمل قرار AADP معتمداً على حالة داخلية عبر حد ثقة، ويربطه بمستقبِل واحد ومفتاح تقديم واحد وطلب HTTP واحد ونسخة فعل محددة.
  • التحقق من التصريح شرط واحد ضمن اقتران: يجب أن يسمح الـ mandate المشار إليه بالمعاملة نفسها، وأن تسمح سياسة المستقبِل المحلية، وأن تثبت currentness. تستطيع كل طبقة الرفض، ولا تستطيع أي طبقة توسيع الأخرى.
  • لا يستهلك المستقبِل (iss, jti) ذرياً إلا بعد نجاح بقية الفحوص. يمكن للطلب المكرر نفسه استعادة النتيجة المخزنة، لكن ذلك لا يضمن أثراً خارجياً exactly once؛ فالنتيجة المجهولة تحتاج إلى مطابقة السجلات لا إلى تصريح جديد.

ما لا يستطيع الطرف البعيد إعادة حسابه

عندما يطلب وكيل دفع 40 يورو، قد يعتمد قرار المُرسل على إنفاق تراكمي، وحجز حي في الميزانية، وموافقة لم تنته، وعمليات سابقة، ومفتاح إيقاف طارئ. توجد هذه الحالة داخل نطاق المُرسل. لا يملك مزود الدفع البعيد دفتر الميزانية ولا دورة الموافقات، ولذلك لا يستطيع إعادة اتخاذ القرار عند وصول الطلب.

يمكن للهوية أن تقول من يتصل، وللتفويض أن يحدد ما أُوكل إلى الوكيل. لكنهما لا يثبتان أن هذه العملية المحددة حجزت مبلغها في تلك اللحظة. فإذا وصل المبلغ 40.01 يورو، لا تكفي صحة توقيع JWT للإجابة.

هذه هي الفجوة الضيقة التي يعالجها أول إصدار من مشروع Shamik Saha بشأن action-bound permits. إنه Internet-Draft فردي نشط، ويذكر رأسه نية Standards Track. ليس RFC ولا إجماعاً في IETF ولا منتج فريق عمل ولا دليلاً على نشر إنتاجي.

المقترح يحمل قراراً واحداً تعجز الجهة الأخرى عن إعادة حسابه؛ ولا ينشئ نظام تفويض عاماً بين المؤسسات.

خمسة قيود على تصريح واحد

الغلاف JWT بتسلسل JWS compact، ونوعه الدقيق aadp-permit+jwt. يحمل aud مستقبِلاً واحداً؛ وتعدد الجمهور سبب للرفض. ويسمي cnf.jkt مفتاح proof-of-possession الخاص بالمقدِّم. يجب التحقق من HTTP Message Signature للطلب بذلك المفتاح. وإلا صار التصريح bearer token، وهو ما يمنعه النص عبر حد الثقة.

يغطي التوقيع على الأقل method وauthority وpath وquery وContent-Digest وIdempotency-Key وحقل التصريح. يعيد المستقبِل حساب digest على البايتات التي استلمها قبل التحليل أو إعادة التسلسل. لذلك قد يفشل JSON ذو المعنى نفسه إذا تغير تمثيله على السلك.

ثم يأتي الربط الدلالي مستقلاً. يحدد كل action type كيف يُشتق الكائن A من path وquery والجسم. يطبّق المستقبِل RFC 8785، ويضيف domain separator، ويقارن action_digest. تطابق البايتات لا ينقذ اشتقاقاً غيّر القيمة أو المستفيد؛ وتطابق المعنى لا يبرر تغيير البايتات.

أما الزمن فيضع الحد الخامس. لا يتجاوز exp مهلة execute_within في AADP. وعند غيابها لا تزيد الفترة بين iat وexp على 120 ثانية. ويسجل المستقبِل clock skew لا يتجاوز 60 ثانية، من دون تمديد الموعد الأصلي.

مستقبِل واحد، ومفتاح واحد، وطلب واحد، وفعل واحد، وفترة قصيرة: صعوبة إعادة الاستخدام هي خاصية الأمان.

ثلاث طبقات تملك حق الرفض

لا يتحرك المستقبِل إلا إذا تحققت ثلاثة شروط معاً. أولاً: يصح القرار المقيّد وتصح روابط الطلب. ثانياً: إذا ذُكر mandate، يُقيّمه المستقبِل مستقلاً ضد المعاملة نفسها ويجب أن يسمح. ثالثاً: تسمح سياسته المحلية.

يصف Agent Authorization Envelope المقترح ما فُوّض إليه الوكيل. أما bound permit فيصف ما قرره PDP الآن اعتماداً على حالته. يقارن المستقبِل digest ويقيّم AAE بنفسه. تؤدي DENY وPENDING وعدم التطابق وعدم توافر mandate إلزامي إلى الرفض. لا يحول التصريح PENDING إلى PERMIT.

ثم يبقى للمستقبِل قراره. يمكن لمزود الدفع أن يثق بالمُصدر، ويتحقق من المبلغ والتوقيع، ثم يرفض بسبب الحساب أو الاحتيال أو العقوبات أو حدود الخدمة. التوقيع يثبت قرار نطاق آخر؛ ولا يمنحه سيادة على النظام الذي يتحمل النتيجة.

حتى الثقة بالمُصدر لها scope. يقيد الجدول المقترح المفاتيح وأنواع الأفعال وحدود الحقول وتاريخ الانتهاء وأدنى currentness. الثقة بجهة لإجازة تحويلات صغيرة لا تمنحها حق إغلاق حساب أو تحديد مبالغ بلا سقف.

التوقيع الصحيح قد يصف قراراً قديماً

قد تُستبدل policy أو يُسحب mandate بعد التوقيع وقبل الوصول. العمر القصير يصغّر النافذة ولا يكشف ما حدث فيها. لذلك يعلن التصريح أحد نمطين.

في time-bounded يُعد التصريح جارياً حتى exp من دون فحص إضافي، وفقط للأزواج التي يسمح إعدادها بهذا الخطر. وفي status-checked يثبت المستقبِل وقت التحقق أن التصريح وpolicy_version والـ mandate ما زالت جارية، باستخدام status list أو freshness statement حديث وموقع من المُصدر.

إذا تعذر الوصول إلى الحالة، أو تعذر تحليلها، أو كانت قديمة، فالنتيجة المعتادة status-unavailable. ولا يُسمح بـ fail-open إلا ضمن سياسة محلية صريحة ومدققة لفئة قليلة المخاطر، مع تسجيل استعمال الاستثناء. لا يجوز إخفاؤه تحت عبارة «token valid».

تمنع reality layers لدى Lu Heng الخلط هنا. التصريح يمثل قراراً في لحظة سابقة. وفحص الحالة يمثل ملاحظة لاحقة. أما الأثر الخارجي فهو واقع ثالث. يجب ربطها، لا استبدال إحداها بالأخرى.

الاستهلاك آخر خطوة

يرتب المشروع الفحوص في ثلاث عشرة مرحلة: البنية، والمُصدر والتوقيع، والجمهور، والزمن، ونوع الفعل، وscope المُصدر، وdigest الجسم، وتوقيع المقدِّم، والفعل الدلالي، وcurrentness، والـ mandate، والسياسة المحلية، ثم الاستهلاك الذري لـ (iss, jti). ولا يُحاول الأثر إلا بعد ذلك.

يمنع هذا الترتيب طلباً تالفاً من إحراق الاستخدام الصحيح. كما أن الرفض المحلي لا يستهلك التصريح. وإذا تعطل consume store فالحالة could-not-check، لا رفض سياسة ولا إذن بالمتابعة. والمستقبِل الذي لا يملك مخزناً ذرياً دائماً ومشتركاً بين العقد لا ينبغي أن يقبل التصاريح.

jti ليس permit_id الداخلي في AADP. يُنشأ مستقلاً ولا يكون أحدهما مشتقاً من الآخر. يحتفظ المُصدر بالربط، لكن jti وحده يعبر الحد ويصبح Idempotency-Key. لا ينبغي لمعرف دورة داخلية أن يتحول إلى credential خارجي لمجرد سهولة التنفيذ.

في العرض الأول يُستهلك المفتاح ويُنفذ الأثر وتُحفظ النتيجة. العرض اللاحق لنفس (iss, jti) ونفس content digest يعيد النتيجة المخزنة من دون أثر ثانٍ. الجسم المختلف يؤدي إلى idempotency-conflict. وإذا كانت المحاولة الأولى جارية، يكون الرد قابلاً لإعادة المحاولة.

ومع ذلك لا يضمن البروتوكول exactly once في العالم الخارجي. إذا ضاع الرد ولم يعرف المُرسل هل وقع الدفع، فلا يحصل على تصريح جديد ويرسل ثانية. يبلغ timeout، ويطابق السجلات بواسطة jti أو recipient_action_id، ويصعّد إذا فشلت المطابقة. idempotency تضبط التكرار؛ ولا تمحو المجهول.

توقيع من الجهة التي حاولت تنفيذ الأثر

بعد الاستهلاك ومحاولة الأثر، يعيد المستقبِل confirmation موقعة تشير إلى التصريح والطلب وdigest قاعدة التوقيع وaction digest وmandate verdict والنتيجة ومعرف الفعل المحلي. يضع المقدِّم digest هذه الوثيقة في تقرير AADP بوصفها discharge evidence لالتزام present_bound.

لكل توقيع معنى منفصل: المُصدر يقول «اتخذت القرار»، والمقدِّم يقول «أرسلت هذا الطلب»، والمستقبِل يقول «فعلت به كذا». يسمح الرفض الموقع بدعم failure مع no_effect: true. أما الخطأ غير الموقع فلا يثبت غياب الأثر؛ وغياب confirmation يبقي النتيجة timeout.

التصريح لقفزة واحدة. وجود claim باسم parent يؤدي إلى chained-permit-unsupported. إذا احتاج B إلى الاتصال بـ C، يتخذ نطاق B قراراً جديداً. يمكن ذكر القفزة السابقة كـ provenance، لكنها دليل لا سلطة، ولا تخفف فحوص C.

هنا يظهر Minimum Initial Specification بصورة عملية: توحيد أقل قدر من الروابط وأسباب الرفض ليتحقق الطرفان من المحاولة نفسها، مع إبقاء اختيار الثقة والمخاطر والنتيجة المحلية لدى من يتحملها.

ثغرتان معلنتان في كود المرجع

يشير المشروع إلى commit ثابت في مستودع onedoor. يسرد manifest أربعة وعشرين vector، وتصف خريطة التتبع اثنين وعشرين بأنها implemented. تبقى V17 الخاصة باكتشاف policy مستبدلة في status-checked، وV22 الخاصة بـ confirmation تشير إلى request digest آخر، كفجوتين. ويذكر النص نجاح 92 اختباراً للـ permit.

هذه أدلة قابلة لإعادة التشغيل لكنها مرتبطة بالمؤلف. كما أن رسالة commit تتناول صيانة أخرى في المستودع وليست إصداراً خاصاً بالتصريح، ولا توجد هنا قابلية تشغيل بينية مستقلة أو قياسات إنتاج. Running-Code Primacy يعني أن يعيد طرف مستقل تشغيل الـ vectors، ولا سيما الفجوتين، وينشر الاختلاف؛ لا أن يصبح snapshot تصويتاً معيارياً.

المصادر والحدود

تثبت المصادر وجود مقترح فردي نشط، ومواصفاته التابعة، وsnapshot تنفيذ مرتبط بالمؤلف. ولا تثبت إجماع IETF أو RFC أو interoperabilty مستقلة أو نشراً آمناً أو سياسة صحيحة أو مستقبِلاً صادقاً أو أثراً exactly once. يملك هذا المقال أطروحة revision 00 فقط: حمل قرار AADP معتمد على الحالة كمحاولة واحدة مقيدة بالمستقبِل والمقدِّم والطلب والفعل، ثم إغلاق السجل بتوقيع المستقبِل.