تصور کنید سامانهای برای مدیریت دسترسیها دارید که در یک میلیون تست موفق شده است، اما تنها یک باگ کوچک، دسترسی کامل به کل شبکه را به کاربرانی میبخشد که نباید چنین قدرتی داشته باشند. برای حذف کامل این ریسکها، فرناندا گراسیولی (Fernanda Graciolli) و نادا امین (Nada Amin) استدلال میکنند که تنها راهکار واقعی «تأیید رسمی» (Formal Verification) است؛ فرآیندی که تضمین میکند کد شما از طریق ساختار ریاضی درست طراحی شده است.
در یک پلتفرم مدیریت اسرار (Secrets Management)، قوانینی تعیین میکنند چه کسی حق خواندن، ویرایش یا حذف دادهها را در محیطهای مختلف دارد. یک بررسی حساس مرزی باید تضمین کند که وقتی کاربری یک نقش سفارشی میسازد، دسترسیهای آن نقش حتماً زیرمجموعهای از دسترسیهای خود کاربر باشد. به زبان ساده، شما نباید بتوانید دسترسیای را به دیگران ببخشید که خودتان ندارید. یک مجموعه تست جامع ممکن است هر مورد را پاس کند، زیرا تستها معمولاً از مقادیر همپوشان استفاده میکنند و لبههای منطقی را نمیبینند.
اما یک باگ میتواند زمانی رخ دهد که کاربری که فقط به یک محیط خاص (مثلاً QA) دسترسی دارد، نقشی بسازد که محدوده آن «غیر از توسعه» (not development) تعریف شده باشد. این تعریف منطقاً با تمام محیطها بهجز توسعه مطابقت دارد؛ یعنی محیط تولید (Production)، محیطهای کَناری (Canary)، سندباکس (Sandbox) و تست پذیرش کاربر (UAT) را هم شامل میشود. در این سناریو، یک دسترسی تکمحیطی به دسترسی تقریباً جهانی تبدیل میشود. تستها این باگ را نمیگیرند چون باگ تنها زمانی فعال میشود که مقادیر همپوشان نباشند؛ در مجموعه تستهای موجود، مقدار استثنا معمولاً در مجموعه والد حضور دارد. این چالشها نشان میدهند که چرا اتوماسیونهای مدرن، مانند ابزار Claude Code در ردیابی حفرههای IDOR، تلاش میکنند با تحلیل دقیقتر، نقاط کور تستهای سنتی را پوشش دهند.
برای جلوگیری از این فاجعه، سیستم به یک «ناوردا» (Invariant) معنایی بنیادین نیاز دارد: مشتقات دسترسی باید «ناوردای زیرمجموعه» باشند. این یعنی مجموعه محیطهایی که توسط یک دسترسی مشتقشده شناسایی میشوند، باید همیشه زیرمجموعهای از محیطهای شناساییشده توسط دسترسی دهنده باشند. این ویژگی فارغ از اینکه دسترسیها به صورت مجموعههای محدود، مجموعههای منفی یا هر نمایش آیندهای باشند، باید برقرار باشد. وقتی این ناوردا تثبیت شود، بروز باگی از این کلاس بهصورت ساختاری غیرممکن میشود. تفاوت بین «کد در زمان اجرا خطا نداد» و «کد نمیتواند خطا دهد»، جوهرهٔ تأیید رسمی است.
به نقل از تحلیلگران حوزه نرمافزار، این سطح از قطعیت تا پیش از این تنها مختص صنایع هوافضا (Avionics)، طراحی تراشه، سامانههای هستهای و پروتکلهای رمزنگاری بود؛ دامنههایی که یک باگ در آنها به قیمت جان انسانها یا میلیاردها دلار خسارت تمام میشد. اکثر توسعهدهندگان به تستهای معمولی بسنده میکردند چون هزینه نوشتن اثباتهای ریاضی از هزینه نوشتن خودِ کد بسیار بیشتر بود. این کار نیازمند تخصص سطح PhD و ساعتها کلنجار رفتن دستی با پیامهای خطای نامفهوم بود. برای اکثر مهندسان، نتیجه منطقی این بود که تستها «به اندازه کافی خوب» هستند.
![]()
اما طبق گزارشهای منتشر شده در ژوئن ۲۰۲۶، این گلوگاه تغییر کرده است. مدلهای زبانی بزرگ پیشرو (Frontier LLMs) — و بهویژه مدل Opus 4.5 — اکنون قادرند پیشنویسهای رسمی (Formal Specifications) را از روی نیازمندیهای زبان طبیعی بنویسند و در یک چرخه بسته و سریع با یک «تأییدگر» (Verifier)، روی لمهای شکستخورده (Failing Lemmas) تکرار و اصلاح کنند. این تحول بخش سخت و پرزحمت کار را حذف میکند: تبدیل قوانین تجاری شهودی به فرمهای منطقی دقیق و صرف روزها زمان برای متقاعد کردن یک دستیار اثبات تا پذیرفتن یک ویژگی «بدیهی».
در این مدل، AI کاندیداهای پیادهسازی را پیشنهاد میدهد و یک فرآیند مکانیکی و قطعی (Deterministic)، صحت هر کاندید را بررسی میکند. اگر اثبات غلط باشد، تأییدگر آن را رد میکند و AI دوباره تلاش میکند. در اینجا اعتماد به AI به حداقل میرسد (تنها به سطح مشخصات محدود میشود) چون مرجع نهایی، یک تأییدگر خارجی و ریاضی است. این رویکرد، پاسخی عملی به بحثهای پیرامون ناکارآمدی تیکهای سبز تأییدیه در عاملهای هوش مصنوعی است، چرا که جایگزین اعتماد کورکورانه را با یک اثبات ریاضی بیرونی جایگزین میکند.
سازوکار قطعیت ریاضی
تأیید رسمی با تست متفاوت است؛ زیرا بهجای نمونهبرداری از ورودیها، تمام حالتهای شکست ممکن را یکباره حذف میکند. در حالی که تستهای ویژگی (Property Tests) ممکن است یک میلیون ورودی تصادفی را بررسی کنند و برخی باگها را بگیرند، سیستم همچنان در برابر ورودی یک میلیون و یکم آسیبپذیر است. اما تأیید رسمی به توسعهدهنده میگوید: «هیچ باگی اینجا وجود ندارد»، چون اثبات ریاضی تمام توالیهای ممکن را پیش از آنکه کد کامپایل شود، رد کرده است.
این روش نیازمند زبانی است که «آگاه به تأیید» (Verification-aware) باشد و در آن مشخصات (Specifications) و اثباتها در کنار کد پیادهسازی، شهروند درجهیک باشند. بر اساس گزارش queue.acm.org، چندین ابزار تخصصی در این میدان پیشتاز هستند:
- Dafny: از سبک امری (Imperative) استفاده میکند که برای اکثر توسعهدهندگان آشناست و بخش زیادی از اثباتها را از طریق حلکنندههای SMT (Satisifiability Modulo Theories) اتوماتیک میکند.
- Lean: ریشه در ریاضیات محض دارد و برای اثبات قضایا و نرمافزارهای تأییدشده بهسرعت در حال رشد است.
- Rocq (Coq سابق) و Isabelle: دستیارهای اثبات تعاملی با دهها سال سابقه در تحقیقات و سیستمهای با سطح اطمینان بالا (High-assurance systems).
- F*: هدفش برنامهنویسی سیستمهای تأییدشده با قابلیت استخراج به زبانهای C و OCaml است.
- TLA+: بر مشخصسازی و بررسی مدل (Model Checking) پروتکلهای توزیعشده تمرکز دارد.
در زبانی مثل Dafny، توسعهدهنده پیششرطها (requires) و پسشرطها (ensures) را تعریف میکند. تأییدگر کد را اجرا نمیکند؛ بلکه درباره ساختار آن استدلال میکند و شرایط تأیید را به یک «اوراکل» خودکار (حلکننده SMT) میسپارد تا تعیین کند آیا پسشرط برای هر ورودیِ مطابق با پیششرط برقرار است یا خیر. اگر حتی یک حالت دستیافتنی (Reachable state) وجود داشته باشد که قانون را بشکند، کد کامپایل نمیشود.
برای مثال در یک سبد خرید، شما میخواهید ثابت کنید که موجودی هرگز منفی نمیشود، هر آیتم در مبلغ کل لحاظ شده و برای هر سفارش تنها یک کد تخفیف اعمال میشود. برای تضمین اینکه موجودی هرگز منفی نشود، توسعهدهنده چنین مینویسد:method ApplyCoupon(balance: int, discount: int) returns (newBalance: int) requires discount >= 0 requires balance >= discount ensures newBalance >= 0 { newBalance := balance - discount; }
اگر مشخصات درست باشد، تضمین مطلق است: این ویژگی در هر حالت دستیافتنی برنامه برقرار خواهد بود.

کاربرد واقعی: حفاظت مالی
یک سفارش آنلاین را در نظر بگیرید که از یک ماشین حالت (State Machine) پیروی میکند: «سبد» $\to$ «ثبتشده» $\to$ «در حال ارسال» $\to$ «تحویلشده»، در حالی که حالت «لغو شده» از وضعیتهای «ثبتشده» یا «در حال ارسال» قابل دستیابی است. ثبت سفارش منجر به کسر وجه از کارت میشود و انبار ارسال را آغاز میکند. در هر نقطه پیش از تحویل، مشتری میتواند سفارش را لغو کند و باید استرداد وجه دریافت کند.
ویژگی بنیادی اینجا «حفاظت مالی» (Financial Conservation) است: مبلغ خالص پرداختی مشتری باید همیشه برابر با ارزش کالاهای دریافتی باشد. در حالت لغو، استرداد باید دقیقاً برابر با ارزش کالاهای ارسالنشده باشد. در Dafny، این مدل به این صورت است:
- انواع داده (Data Types):
State = Cart | Placed | Shipping | Delivered | CancelledItem = Item(name: string, price: nat)Order = Order(state: State, items: seq<Item>, shippedValue: nat, charged: nat, refunded: nat)
- گزاره معتبر (Valid Predicate): این گزاره تضمین میکند که
o.shippedValue <= Total(o.items). برای حالتCancelled(لغو شده)، صراحتاً اجرا میکند:o.charged == Total(o.items) && o.refunded == o.charged - o.shippedValue.
این یک خط کد، قانون حفاظت مالی را برای هر زمانِ لغوی — چه هیچ کالایی ارسال نشده باشد، چه نیمی از آنها ارسال شده باشند و چه همه بهجز یک آیتم ارسال شده باشند — کدگذاری میکند. این ناوردا تمام موارد را یکباره پوشش میدهد.
هر انتقال وضعیت یک متد با پیششرط و پسشرط است. مثلاً متد CancelOrder:method CancelOrder(o: Order) returns (o': Order) requires Valid(o) requires o.state == Placed || o.state == Shipping ensures Valid(o') && o'.state == Cancelled { var refund := Total(o.items) - o.shippedValue; o' := o.(state := Cancelled, refunded := refund); }
هر انتقال وضعیت، حالت Valid را حفظ میکند. اثباتهای تکمیلی، مانند یک گزاره شبح (Ghost Predicate) به نام FinanciallySound (که بیان میکند charged - refunded == shippedValue) و لم NoMoneyLost (که بیان میکند اگر پرداختی وجود دارد، یا کالا ارسال شده، یا استرداد صورت گرفته و یا سفارش هنوز در حال تکمیل است)، میتوانند بهطور خودکار تأیید شوند. این امر تضمین میکند که هیچ توالی از عملیات — افزودن آیتم، ثبت، ارسال یا لغو — نمیتواند منجر به ایجاد یک سفارش نامعتبر شود.
شناسایی انحرافات و حفظ هدف
وقتی حسابداری ساده است، این ویژگیها بدیهیاند. اما پیچیدگیهای دامنه (Domain Complexity) — مثل تخفیفهای شرطی، سفارشات دستهای و تکرارشونده یا پنجرههای بازگشت کالا — میتوانند خطا ایجاد کنند. کدگذاری حفاظت مالی در ابتدا، تضمین میکند که هیچ کدی در آینده در داخل این مدل نمیتواند این ویژگی بنیادی را نقض کند.
تصور کنید شش ماه بعد، قابلیت کوپنهای سطح سفارش اضافه شود، مثلاً «۲۰ دلار تخفیف برای خرید بالای ۱۰۰ دلار». این کار مقدار charged را به «مجموع آیتمها منهای تخفیف» تغییر میدهد. در حالی که مجموعههای تست سنتی ممکن است بهروزرسانی شوند و پاس کنند، ممکن است باگی معرفی شود که در سناریوهای خاص لغو، مشتری بیش از حد شارژ شود.
در یک دامنه تأییدشده، این قابلیت تخفیف باید در همان سیستم پیاده شود. چون ناوردا استرداد را بر اساس refunded == charged - shippedValue محاسبه میکرد و در ابتدا charged برابر با «مجموع آیتمها» بود، افزودن تخفیف یک «انحراف در هدف» (Drift in Intent) ایجاد میکند. ناوردا اکنون قانون مالی غلطی را کدگذاری میکند زیرا معنای charged تغییر کرده اما نام آن تغییری نکرده است. تأییدگر چیزی درباره حفظ معنا نمیگوید و اگر Valid تنها ناوردا باشد، پیادهسازی همچنان آن را ارضا میکند.
اما آنچه تأییدگر شکار میکند، ناسازگاری بین ناورداهاست. خطای تأییدگر باگ را مستقیماً رفع نمیکند، اما نشان میدهد که یک شکاف در طراحی وجود دارد. توسعهدهندگان باید تصمیم بگیرند تخفیفها چگونه توزیع شوند (مثلاً بهصورت تناسبی، ابتدا در کالاهای ارسالشده یا ابتدا در ارسالنشدهها). بهدلیل تأییدشده بودن سیستم، هیچ پیادهسازی از قابلیت تخفیف که ناورداهای اصلی را نقض کند، کامپایل نخواهد شد.
چرخه انسان و هوش مصنوعی
هوش مصنوعی نیاز به قضاوت انسانی را از بین نمیبرد، بلکه کارهای دستی و خستهکننده را حذف میکند. انسان مسئول طراحی سطح بالا، تصمیمگیری درباره اینکه کدام ویژگیها ارزش تضمین کردن دارند و طراحی کلی سیستم باقی میماند. AI کاندیداهای پیادهسازی را پیشنهاد میدهد و تأییدگر قطعی بهمثابه یک مرجع خارجی، صحت آنها را میسنجد.

با این حال، نویسندگان هشدار میدهند که اثبات فقط به اندازه «مشخصات» (Spec) خوب است. سختترین بخش و هستهٔ تأیید رسمی همینجاست. هیچ ابزاری نمیتواند تصمیمات طراحی یک اپلیکیشن را کاملاً اتوماتیک کند. تأییدگر هر چه شما بگویید را با بیرحمی اجرا میکند، اما نمیتواند به شما بگوید چه چیزی را باید اجرا کنید. طوفان فکری (Brainstorming) با AI و حسابرسیهای تداخل مشخصات در مرحله نوشتن میتواند این فرآیند را تسهیل کند. در واقع، همانطور که در بهبود موتورهای آزمون CompTIA با حذف محتوای زائد دیدیم، دقت خروجی AI به شدت به کیفیت دادههای ورودی و محدودههای تعریف شده وابسته است.
اگر مشخصات بیش از حد محدود باشند، تضمین نیز محدود خواهد بود. برای مثال، اگر در سیستم مدیریت اسرار فقط میگفتیم «دسترسیهای محدود فقط میتوانند شامل دسترسیهای محدود دیگر باشند»، اثبات پاس میشد اما سیستم همچنان در برابر حفرهٔ «غیر از توسعه» آسیبپذیر میماند. ناوردا باید در سطح انتزاع درست بیان شود و در عمق مناسب اثبات گردد، که این امر مستلزم درک عمیق دامنه است، حتی در هنگام بازبینی مصنوعات تولید شده.
مرزهای تأیید
تأیید رسمی در حال حاضر برای منطقهای بدون اثر جانبی (Effect-free logic) بیشترین اثر را دارد:
- ناورداها (Invariants)
- انتقال وضعیتها (State transitions)
- حل تعارضات (Conflict resolution)
این روش هنوز نمیتواند صحت سرتاسری (End-to-end) را تضمین کند، زیرا عناصر رابط کاربری، فراخوانیهای شبکه و تعاملات پایگاهداده معمولاً خارج از مرز تأیید هستند. تأیید رسمی هسته را ضدگلوله میکند، اما پیرامون سیستم همچنان جداست.
با این حال، هزینه اثباتها عملاً به قیمت توکنهای مورد نیاز برای تولید آنها کاهش یافته است. این تغییر به هر شرکتی که قوانین تجاری حساس دارد اجازه میدهد از حالت «کد در زمان اجرا شکست نخورد» به حالت «کد نمیتواند شکست بخورد» حرکت کند.
این تکامل باعث تغییر در شیوه کار توسعهدهندگان میشود. مهندسان بهجای نوشتن تست برای یافتن باگها، بهطور فزایندهای بر تعریف ناورداهای مطلق سیستمهای خود تمرکز میکنند و مهندسی اثبات را به AI میسپارند.
گام بعدی شما
- بررسی ابزار Dafny برای پیادهسازی قوانین حساس تجاری در پروژههای کوچک جهت آشنایی با مفاهیم Precondition و Postcondition.
- مطالعه مستندات Lean برای درک چگونگی تبدیل نیازمندیهای متنی به قضایای ریاضی.
- بازبینی معماری سیستمهای مدیریت دسترسی در سازمان خود برای شناسایی «ناورداهایی» که در حال حاضر فقط با تستهای احتمالی پوشش داده شدهاند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است؛ به تحلیل ما درباره تراشههای Blackwell و نقش آنها در استنتاج مدلهای استدلالی مراجعه کنید.




گفتگو