الگو در مجموعه دادهها
در سراسر گزارشهای حادثه و کالبدشکافیها، امضایی تکرارشونده ظاهر میشود: یک عامل به یک endpoint زندهٔ شخص ثالث — یک پورتال دولتی، یک پلتفرم خردهفروشی، یک سطح پیامرسانی — بدون هیچ دستور اپراتور برای این کار دسترسی پیدا میکند. چارچوب عمومی به زبان همراستایی توسل میجوید: مدل چیزی میخواست، مدل از مسیر خارج شد. اما امضای عملیاتی محدودتر و قابلکنترلتر است. عامل مقصدی را resolve کرد که در دامنهٔ موردنظر نبود، و کنترلهای پیرامونی متوجه نشدند، چون کنترلها برای محدود کردن حجم ساخته شده بودند، نه دسترسی.
این تمایز مهم است چون تعیین میکند کدام کنترل واقعاً مشکل را حل میکند. اگر شکست ناشی از عدم همراستایی باشد، راهحل یک سیاست بهتر یا یک prompt بهتر است. اگر شکست ناشی از مسیریابی و دسترسی باشد، راهحل یک بودجهٔ خروجی است که بهصورت مجموعهای از مقصدها و قابلیتها بیان میشود و بیرون از چارچوب عامل اعمال میگردد.
چرا بودجههای نرخ آن را از دست میدهند
یک بودجهٔ نرخ، درخواستها در واحد زمان را محدود میکند. این یک کنترل کاهش بار است که از API gatewayها به ارث رسیده، جایی که نگرانی حفاظت از backend در برابر یک کلاینت پرترافیک بود. این کنترل به پرسش چند تا پاسخ میدهد، نه به کجا.
حالت شکست را مستقیم در نظر بگیرید. یک درخواست HTTP خوشساخت به یک میزبان ناخواسته در هر بودجهٔ نرخ معقولی میگنجد. یک درخواست در دقیقه بودجهٔ نرخی است که بیشتر اپراتورها محافظهکارانه میدانند؛ همچنین برای ارسال یک فرم، ارسال یک پیام، یا فعالسازی یک workflow روی یک سیستم شخص ثالث کافی است. محدودیت نرخ هرگز فعال نمیشود چون حجم ناچیز است. درخواست بیشازحد نیست؛ فقط به جای اشتباه آدرسدهی شده است.
سردرگمی از اینجا ناشی میشود که محدودیتهای نرخ و محدودیتهای دسترسی اغلب با هم مستقر میشوند و هر دو نزدیک مرز شبکه قرار دارند. اما آنها کلاسهای کنترل متفاوتی هستند. محدودیت نرخ یک کنترل ظرفیت است. محدودیت دسترسی یک کنترل مجوزدهی است. کنترلهای ظرفیت تحت بار بهنرمی تنزل مییابند؛ کنترلهای مجوزدهی برای هر مقصد دودویی هستند. جایگزین کردن اولی بهجای دومی، مجموعهٔ مقصدها را بدون محدودیت رها میکند.
شکست در حجم نیست. در مجموعهٔ مقصدهای قابلدسترسی است، و در قابلیتهایی که عامل در هر یک از آنها دارد.

طراحی یک بودجهٔ دسترسی
بودجهٔ دسترسی، شمارشی از کلاسهای مقصد است که یک اجرای عامل میتواند لمس کند، مقید به قابلیتهای مجاز در هر یک. این بودجه به مشخصات اجرا تعلق دارد، نه به تعریف ابزار.
این جایگذاری عمدی است. تعریف ابزار توصیف میکند که یک ابزار بهطور کلی چه میتواند بکند؛ مشخصات اجرا توصیف میکند که این اجرای خاص مجاز به چه کاری است. اگر دسترسی روی ابزار اعلام شود، هر اجرایی که ابزار را بارگذاری میکند کل دسترسی ابزار را به ارث میبرد و اپراتور توانایی محدود کردن یک وظیفهٔ مشخص را از دست میدهد. اگر دسترسی روی اجرا اعلام شود، همان ابزار میتواند تحت یک بودجهٔ باریک برای یک وظیفهٔ خلاصهسازی فقطخواندنی و تحت یک بودجهٔ گستردهتر برای وظیفهای که بهطور مشروع نیاز به نوشتن دارد، بارگذاری شود.
یک ورودی بودجه، یک کلاس مقصد را با یک مجموعهٔ قابلیت جفت میکند. کلاسهای مقصد باید بهقدری درشت باشند که قابل نگهداری بمانند و بهقدری مشخص که معنادار باشند: یک میزبان مستندات داخلی، یک API شریک نامدار، یک منبع دادهٔ عمومی، یک سطح پیامرسانی. قابلیتها باید از یک واژگان بستهٔ کوچک برگرفته شوند، برای مثال:
read-only fetch
authenticated write
form submission
file transfer (inbound)
file transfer (outbound)
واژگان باید بسته باشد تا بودجهها بهصورت مکانیکی قابل مقایسه و diff باشند. یک رشتهٔ قابلیت باز، زمینه را برای انحراف فراهم میکند.
دو ویژگی بودجه را در عمل قابل استفاده میکند.
نخست، درون یک اجرا یکنواست. یک عامل میتواند دسترسی خود را باریک کند — حذف یک کلاس مقصد که دیگر به آن نیاز ندارد — اما نمیتواند آن را بدون یک رویداد مجوزدهی جدید گسترش دهد. باریک کردن عملیاتی ایمن است چون فقط قابلیت را حذف میکند. گسترش دادن عملیاتی ممتاز است چون دسترسی را اضافه میکند، و باید یک رکورد قابل حسابرسی تولید کند: چه کسی گسترش را مجاز کرد، برای کدام مقصد، برای کدام قابلیت، در چه نقطهای از اجرا.
دوم، بودجه پیش از شروع اجرا اعلام میشود، نه از رفتار مشاهدهشده استنتاج میگردد. بودجهای که از آنچه عامل اتفاقاً انجام داده برگرفته شود، یک توصی
](/media/circuit-board-macro-5a0c33-e1886b.jpg)
نقاط اعمال
بودجه تنها بهقدر نقطهای که در آن اعمال میشود خوب است. سه نقطهٔ اعمال بیشترین وزن را حمل میکنند.
مقصدها را در پروکسی خروجی resolve کنید، نه درون چارچوب عامل. اگر چارچوب دسترسی را اعمال کند، کنترل به مسیر فراخوانی ابزار چارچوب، مدل plugin آن، و نسخهٔ آن گره میخورد. تعویض چارچوب بیسروصدا کنترل را حذف میکند. یک پروکسی خروجی که بین runtime عامل و شبکه قرار میگیرد، دسترسی را بدون توجه به اینکه کدام چارچوب درخواست را تولید کرده اعمال میکند. پروکسی مقصد را resolve میکند — میزبان، پورت، و در صورت لزوم آدرس resolveشده — و آن را پیش از برقراری اتصال با بودجهٔ اعلامشدهٔ اجرا بررسی میکند. چارچوب عامل میتواند بدون دست زدن به control plane جایگزین شود.
ردها را بهعنوان رویدادهای درجهیک ثبت کنید. یک درخواست ردشده باید یک رویداد ساختاریافته تولید کند که حامل مقصد درخواستشده، قابلیت ردشده، شناسهٔ اجرا، و ورودی بودجهای باشد که در صورت وجود آن را مجاز میکرد. ردها نویزی نیستند که فیلتر شوند؛ آنها سیگنال اصلیای هستند که یک اجرا تلاش کرده از دسترسی خود فراتر رود. باید در کنار درخواستهای موفق قابل پرسوجو باشند، نه در یک debug log مدفون.
پس از هر اجرا تطبیق دهید. پس از تکمیل اجرا، مجموعهٔ مقصدهای مشاهدهشده را با بودجهٔ اعلامشده مقایسه کنید. واگرایی — مقصدی که لمس شده اما اعلام نشده، یا قابلیتی که اعمال شده اما اعطا نشده — یک نقص است. باید مانند هر نقص دیگری با علت ریشهای و راهحل دستهبندی شود، نه بهعنوان یک کنجکاوی یادداشت گردد. مرحلهٔ تطبیق چیزی است که بودجه را از یک اعلام ایستا به یک حلقهٔ بازخورد تبدیل میکند.
یک بدهبستان صادقانه
بودجههای دسترسی هزینهٔ انعطافپذیری عملیاتی دارند. هر کلاس مقصد جدید تغییری در مشخصات اجرا است، که یعنی یک مرحلهٔ مدیریت تغییر پیش از آنکه عامل بتواند با یک میزبان جدید صحبت کند. در محیطهایی که مجموعهٔ مقصدهای مشروع واقعاً باز است — مثلاً عاملهای پژوهشی که ارجاعها را در سراسر وب عمومی دنبال میکنند — یک شمارش دقیق غیرعملی است، و اپراتورها وسوسه میشوند کلاس گستردهای مانند اینترنت عمومی، فقطخواندنی را اعلام کنند.
این وسوسه کشنده نیست، اما باید نامگذاری شود. یک کلاس گستردهٔ فقطخواندنی هنوز قابلیت را محدود میکند، که بیشترین ریسک در آن متمرکز است: خواندن یک صفحهٔ عمومی بهندرت عمل مضر است، در حالی که ارسال یک فرم یا نوشتن در یک endpoint احراز هویتشده چنین است. بدهبستان واقعی اما کراندار است. جایگزین — هیچ اعلام دسترسیای، و یک محدودیت نرخ که بهجای مجوزدهی میایستد — یک بدهبستان نیست؛ نبود کنترل است.
موضع عملی این است که با یک بودجهٔ درشت که واقعاً اعمال میشود شروع کنید، سپس آن را همزمان با تثبیت مجموعهٔ مقصدهای مشاهدهشده باریک کنید. یک بودجهٔ درشت که چیز اشتباه را رد میکند، مفیدتر از یک بودجهٔ دقیق است که فقط روی کاغذ وجود دارد.
