دانشکده مهندسی کامپیوتر / سند دفاعیه معماری بک‌اند و پایگاه داده NEXRO

کالبدشکافی خط‌به‌خط ۱۴ فایل بک‌اند، ۱۹ جدول MySQL و مکانیزم‌های امنیتی Zero-Trust

⌕
جست‌وجوی سریع جلسه دفاع:
بخش اول · فلسفه معماری و استراتژی اتصال فرانت‌اند به بک‌اند

معماری Decoupled REST API + Non-Invasive DOM Hydration

PHP 8.2 + PDO + ES6 Hydration

مسئله مهندسی چه بود؟ در این پروژه، فایل‌های فرانت‌اند (index.html، products.html، about.html، contact.html و admin.html) از قبل با استایل‌های دقیق، متغیرهای رنگی (#0b0b0b و #c9a57e) و انیمیشن‌های CSS توسط فرانت اند کار طراحی شده بودند. ما در این پروژه صرفاً منطق بک‌اند و پایگاه داده را به آن‌ها متصل کردیم.

راه‌حل معماری ما چگونه کار می‌کند؟ به جای استفاده از روش منسوخ ترکیب کردن کوئری‌های SQL و کدهای PHP در لابه‌لای تگ‌های HTML صفحات عمومی (که باعث ایجاد Spaghetti Code و به‌هم‌ریختگی تگ‌های استایل می‌شود)، ما معماری را به ۳ لایه کاملاً مستقل (Three-Tier Decoupled Architecture) تقسیم کردیم:

لایه ۱: هسته داده و امنیت (Core & DB Layer)

شامل فایل‌های .htaccess، config/database.php، DatabaseBootstrapper.php و AdminSecurityGuard.php. این لایه مسئول اتصال امن PDO به دیتابیس jprttapf_nexro، ساخت خودکار ۱۹ جدول در اولین اجرا بدون نیاز به کوئری دستی در phpMyAdmin، و اعمال امنیت Zero-Trust (قفل IP، هش SHA-256 نشست‌ها و ضد Brute-Force) است.

لایه ۲: وب‌سرویس‌های ایزوله (REST JSON APIs)

شامل api/admin_api.php (مدیریت ۱۳ بخش پنل ادمین)، api/products_api.php (کاتالوگ زنده مکمل‌ها و سبد خرید سشن) و api/public_api.php (تنظیمات عمومی سایت و فرم تماس ضداسپم). این فایل‌ها هیچ خروجی HTML ندارند و صرفاً با استاندارد application/json و تراکنش‌های ACID با دیتابیس صحبت می‌کنند.

لایه ۳: پل‌های تزریق داده (JS Hydration Bridges)

شامل admin-backend-bridge.js، products.js، contact.js و storefront.js. این اسکریپت‌ها در پس‌زمینه داده‌ها را با fetch() از لایه دوم دریافت کرده، با تابع escapeHtml() پاکسازی امنیتی می‌کنند و دقیقاً درون تگ‌ها و کلاس‌های CSS موجود در فرانت‌اند قرار می‌دهند.

بخش دوم · مهندسی پایگاه داده رابطه‌ای (MySQL / phpMyAdmin)

کالبدشکافی تک‌به‌تک ۱۹ جدول دیتابیس (jprttapf_nexro)

3NF · InnoDB · utf8mb4_unicode_ci

در جدول زیر، تمامی ۱۹ جدول طراحی‌شده در پروژه (شامل ۱۷ جدول موجودیت‌های کسب‌وکار در نسخه ۱.۰ و ۲ جدول امنیتی اضافه‌شده برای حفاظت از پنل مدیریت در نسخه ۱.۲) به صورت تفکیک‌شده به همراه ستون‌ها، کلیدها و دلیل مهندسی ساخت هر جدول تشریح شده‌اند:

# نام جدول (Table Name) ستون‌ها، کلیدهای اصلی (PK)، یکتا (UK) و خارجی (FK) فلسفه طراحی و نقشی که در سیستم ایفا می‌کند
۱ users id (PK), uuid (UK), full_name, email (UK), phone, password_hash, role ENUM('owner','admin','coach','customer'), status, registered_jalali, failed_login_attempts, locked_until, last_login_at, last_login_ip, deleted_at جدول مرکزی کاربران و کنترل دسترسی مبتنی بر نقش (RBAC). هر ۴ نقش خواسته شده در صورت‌مسئله (مالک، ادمین، مربی و مشتری) در این جدول با ستون role تفکیک می‌شوند. ستون‌های failed_login_attempts و locked_until برای قفل کردن خودکار حساب پس از ۵ بار رمز اشتباه تعبیه شده‌اند.
۲ user_physical_profiles id (PK), user_id (UK, FK -> users.id ON DELETE CASCADE), gender, height_cm, weight_kg, fitness_goal, activity_level, medical_conditions, dietary_allergies نگهداری پروفایل فیزیکی و آنتروپومتریک ورزشکار (قد، وزن، هدف ورزشی، بیماری‌ها و حساسیت‌های غذایی). جداسازی این ستون‌ها از جدول users باعث سبک ماندن جدول کاربران در هنگام لاگین و رعایت نرمال‌سازی (3NF) می‌شود.
۳ coach_profiles id (PK), user_id (UK, FK -> users.id ON DELETE CASCADE), specialty_title, experience_years, bio, commission_rate_pct نگهداری اطلاعات تخصصی کاربران دارای نقش مربی (coach) شامل عنوان تخصص، سال‌های سابقه، بیوگرافی و درصد پورسانت مربی از فروش برنامه‌های تمرینی و غذایی.
۴ brands id (PK), name (UK), slug (UK), is_active, created_at نگهداری برندهای سازنده مکمل (Optimum Nutrition، MyProtein، Cellucor، Universal Nutrition). با نگه‌داشتن brand_id در جدول محصولات، افزونگی داده (Data Redundancy) حذف شده و فیلتر برند در products.html با سرعت بالا انجام می‌شود.
۵ categories id (PK), name_fa (UK), slug (UK), sort_order, is_active, created_at نگهداری دسته‌بندی‌های مکمل‌های ورزشی (پروتئین، کراتین، پیش‌تمرین، ویتامین، سلامت عمومی) با قابلیت تعیین ترتیب نمایش (sort_order).
۶ products id (PK), client_id (UK), sku (UK), brand_id (FK -> brands.id), category_id (FK -> categories.id), name, slug, supplement_form ENUM('powder','tablet','capsule'), tag_label, short_description, price_toman (BIGINT), stock_quantity, low_stock_threshold, status_label, image_path, is_active, deleted_at جدول اصلی مکمل‌های باشگاهی. ستون supplement_form دقیقاً فیلتر مکمل‌های پودری و قرصی/کپسولی در صفحه products.html را تغذیه می‌کند. ستون price_toman از نوع BIGINT UNSIGNED برای دقت مالی و deleted_at برای حذف نرم (Soft Delete) در نظر گرفته شده است.
۷ inventory_movements id (PK), client_id (UK), product_name, change_label, reason, date_label, actor_user_id, created_at دفتر کل گردش موجودی انبار (Inventory Ledger). هر بار که مدیر در بخش «مدیریت موجودی» پنل ادمین تعداد یک مکمل را کم یا زیاد می‌کند، مقدار تغییر، علت تغییر و شناسه مدیر در این جدول ثبت می‌گردد.
۸ coupons id (PK), client_id (UK), code (UK), discount_type_label, discount_value, start_label, expires_label, usage_limit, status_label نگهداری کدهای تخفیف (درصدی و مبلغ ثابت) مربوط به تب «تخفیف و کدها» در پنل مدیریت به همراه سقف مجاز استفاده و بازه زمانی اعتبار.
۹ orders id (PK), client_id (UK), order_number (UK), date_label, customer_client_id, customer_name, customer_phone, customer_email, shipping_address, items_json (JSON), subtotal_toman, discount_toman, shipping_toman, total_toman, payment_label, status_label نگهداری سربرگ سفارش‌های مشتریان (مانند NX-2408)، وضعیت پرداخت، وضعیت ارسال و مبالغ مالی شامل جمع جزء، تخفیف، هزینه ارسال و مبلغ نهایی.
۱۰ order_items id (PK), order_id (FK -> orders.id ON DELETE CASCADE), product_id (FK -> products.id), item_title_snapshot, unit_price_toman, quantity, line_total_toman نگهداری ریز اقلام هر سفارش به صورت رابطه‌ای و Snapshot کردن نام و قیمت واحد محصول در لحظه خرید تا تغییرات قیمت آتی محصولات، اسناد مالی قبلی را مخدوش نکند.
۱۱ workout_plans id (PK), client_id (UK), coach_id, title, goal_label, level_label, duration_label, description, status_label نگهداری برنامه‌های تمرینی تدوین‌شده توسط مربیان یا ادمین (شامل عنوان برنامه، هدف تمرینی، سطح دشواری مبتدی/متوسط/پیشرفته و مدت زمان به هفته).
۱۲ workout_plan_exercises id (PK), workout_plan_id (FK -> workout_plans.id ON DELETE CASCADE), day_number, exercise_name, target_muscle_group, sets_count, reps_scheme, rest_seconds, tempo نگهداری ریز حرکات ورزشی هر روز از برنامه تمرینی (نام حرکت، عضله هدف، تعداد ست، تکرار، زمان استراحت بین ست‌ها و ریتم اجرای حرکت).
۱۳ nutrition_plans id (PK), client_id (UK), coach_id, title, goal_label, duration_label, description, status_label نگهداری برنامه‌های تغذیه و رژیم‌های مکمل ورزشی طراحی‌شده برای اهداف افزایش حجم، کاهش وزن یا حفظ تناسب اندام.
۱۴ nutrition_plan_meals id (PK), nutrition_plan_id (FK -> nutrition_plans.id ON DELETE CASCADE), day_number, meal_type, meal_title_fa, food_items_text, supplement_instructions, calories, protein_grams, carbs_grams, fats_grams نگهداری وعده‌های غذایی روزانه (صبحانه، قبل تمرین، بعد تمرین، ناهار، شام) به همراه دستور مصرف مکمل‌ها و ماکروهای هر وعده.
۱۵ contact_messages id (PK), client_id (UK), name, email, phone, subject, message, date_label, is_read (TINYINT), is_archived (TINYINT), created_at ذخیره پیام‌های ارسال‌شده از فرم «تماس با ما» (contact.html). ستون is_read شمارنده پیام‌های خوانده‌نشده (#unread-count) در پنل مدیریت را تغذیه می‌کند.
۱۶ reviews id (PK), client_id (UK), product_name, author_name, rating (1..5), comment_text, date_label, status_label نگهداری نظرات و امتیازهای مشتریان درباره محصولات. فقط دیدگاه‌هایی که در پنل مدیریت به وضعیت تأییدشده تغییر یابند در صفحه اصلی سایت نمایش داده می‌شوند.
۱۷ site_settings id (PK), setting_group, setting_key (UK), setting_value (LONGTEXT), updated_at نگهداری تنظیمات کلیدی فروشگاه (نام، ایمیل، تلفن، واحد پول، محصولات ویژه صفحه اول و متن‌های CMS) در قالب Key-Value ساخت‌یافته.
۱۸ admin_sessions id (PK), user_id (FK -> users.id ON DELETE CASCADE), token_hash (CHAR 64 UK), csrf_token (CHAR 64), ip_address, user_agent_hash (CHAR 64), expires_at, last_activity_at, is_revoked جدول امنیتی نشست‌های مدیران و مربیان. توکن خام هرگز ذخیره نمی‌شود، بلکه فقط هش SHA-256 آن به همراه توکن اختصاصی CSRF و اثرانگشت مرورگر ذخیره می‌گردد.
۱۹ security_rate_limits & audit_logs id (PK), ip_address, action_key (UK), attempts, locked_until + actor_user_id, action, entity_type, old_values_json, new_values_json فایروال سطح دیتابیس برای محدودسازی نرخ درخواست‌ها (Rate Limiting در لاگین و فرم تماس) و ثبت لاگ ممیزی تغییرناپذیر (Forensic Audit Trail) از تمام اقدامات مدیران.
بخش سوم · تشریح خط‌به‌خط و متدبه‌متد تمامی ۱۴ فایل پروژه

کالبدشکافی کامل فایل‌های بک‌اند و پل‌های ارتباطی فرانت‌اند

فایل شماره ۱ · فایروال سطح وب‌سرور

/home/jprttapf/public_html/nexro/.htaccess

Apache mod_rewrite لایه دفاعی اول
چرا این فایل را ساختیم و چه کمکی می‌کند؟

پروژه ما در زیرپوشه https://aisos.shop/nexro/ روی وب‌سرور Apache/LiteSpeed در سی‌پنل اجرا می‌شود. اگر این فایل نباشد: اولاً هر کاربری می‌تواند با تایپ مستقیم /nexro/admin.html صفحه استاتیک ادمین را بدون لاگین ببیند؛ ثانیاً ربات‌های اسکنر می‌توانند محتویات پوشه‌های حساس config/، database/ و storage/ را فراخوانی کنند.

چگونه فرانت‌اند را بدون تغییر ظاهری هندل می‌کند؟

به جای حذف فایل admin.html یا تغییر لینک‌های داخلی، دستور RewriteRule در سطح وب‌سرور هر درخواستی به admin.html یا admin_2.html را به صورت شفاف با کد 302 به گیت امنیتی admin.php منتقل می‌کند.

تشریح خط‌به‌خط دستورات داخل فایل:

دستور (Directive) عملکرد دقیق فنی در وب‌سرور
Options -Indexes غیرفعال کردن Directory Listing؛ اگر پوشه‌ای (مثل js/ یا css/) فایل index نداشته باشد، وب‌سرور لیست فایل‌های داخل آن را به کاربر نشان نمی‌دهد و خطای 403 Forbidden برمی‌گرداند.
RewriteEngine On & RewriteBase /nexro/ فعال‌سازی موتور بازنویسی URL و تنظیم ریشه مسیردهی روی زیرپوشه /nexro/ تا قوانین در زیرپوشه دامین اصلی تداخل ایجاد نکنند.
RewriteRule ^admin(_2)?\.html$ admin.php [R=302,L] مسدودسازی دسترسی مستقیم به فایل استاتیک پنل ادمین و هدایت اجباری کاربر به فایل محافظت‌شده admin.php.
RewriteRule ^(config|database|storage)/ - [F,L] فلگ [F,L] (Forbidden & Last Rule) باعث می‌شود هر درخواست HTTP به پوشه‌های تنظیمات دیتابیس، کلاس بوت‌استرپر و لاگ‌ها فوراً با کد 403 مسدود شود، در حالی که اسکریپت‌های PHP روی سرور همچنان با require_once به آن‌ها دسترسی دارند.
فایل شماره ۲ · پیکربندی مرکزی دیتابیس و زیرپوشه

/home/jprttapf/public_html/nexro/config/database.php

Namespace: Nexro\Config Zero SQLi Profile

چرا این فایل را ساختیم؟ برای جلوگیری از تکرار نام کاربری و رمز عبور دیتابیس در فایل‌های مختلف و اعمال متمرکز سیاست‌های امنیتی درایور PDO. این فایل شامل کلاس final class DatabaseConfig است.

کالبدشکافی خط‌به‌خط متدها و ثابت‌های کلاس DatabaseConfig:

بخش / متد / فلگ تشریح کامل عملکرد و دلیل مهندسی
declare(strict_types=1); فعال‌سازی تایپینگ سخت‌گیرانه در سطح موتور PHP 8؛ از تبدیل نوع ضمنی (Implicit Type Coercion) جلوگیری کرده و امنیت نوع داده‌ها را تضمین می‌کند.
SCHEMA_VERSION = '1.2.0' ثابت نسخه اسکیمای دیتابیس. هر زمان جدول یا ستون جدیدی به پروژه اضافه شود، با تغییر این عدد، کلاس DatabaseBootstrapper به صورت خودکار متوجه تغییر شده و مایگریشن جدید را اجرا می‌کند.
public static function app(): array برگرداندن متادیتای برنامه شامل آدرس کامل (https://aisos.shop/nexro)، مسیر پایه کوکی‌ها ('base_path' => '/nexro') و منطقه زمانی (Asia/Tehran).
public static function connection(): array تنظیم مشخصات اتصال به دیتابیس سی‌پنل: database => 'jprttapf_nexro' و username => 'jprttapf_nexro_user' با پشتیبانی از متغیرهای محیطی (getenv).
PDO::ATTR_EMULATE_PREPARES => false حیاتی‌ترین تنظیم امنیتی PDO؛ شبیه‌سازی کوئری‌ها در PHP را خاموش می‌کند و باعث می‌شود کوئری‌های پارامتریک مستقیماً توسط هسته MySQL کامپایل شوند. این کار تزریق SQL (SQL Injection) را از نظر ریاضی و ساختاری غیرممکن می‌سازد.
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION پرتاب استثنای استاندارد (PDOException) در صورت بروز هرگونه خطای SQL تا بتوانیم تراکنش‌ها را در بلوک catch به صورت کامل rollBack() کنیم.
PDO::ATTR_STRINGIFY_FETCHES => false حفظ نوع عدد صحیح (INT / BIGINT) هنگام خواندن قیمت‌ها و موجودی انبار از دیتابیس، به جای تبدیل آن‌ها به رشته متنی.
PDO::MYSQL_ATTR_INIT_COMMAND اجرای خودکار دستور SET NAMES utf8mb4 و فعال‌سازی STRICT_TRANS_TABLES در لحظه برقراری اتصال برای جلوگیری از ذخیره شدن داده‌های ناقص یا خارج از محدوده.
فایل شماره ۳ · موتور خودکار ساخت، ترمیم و مقداردهی دیتابیس

/home/jprttapf/public_html/nexro/database/DatabaseBootstrapper.php

Singleton + Advisory Lock Self-Healing Engine

چرا این فایل را ساختیم؟ شما تاکید داشتید که نمی‌خواهید وارد phpMyAdmin شوید و به صورت دستی کوئری بزنید، بلکه می‌خواهید تمام ساختار جداول و داده‌های اولیه در یک فایل کد نگهداری شوند تا هر زمان سورس روی هاست بارگذاری شد، خودش همه چیز را بسازد و اگر تغییری در نسخه دیتابیس رخ داد، بدون خطای ۵۰۰ خودش را ترمیم کند.

کالبدشکافی کامل متدهای داخل DatabaseBootstrapper.php:

نام متد (Method) شرح دقیق منطق اجرا، الگوریتم و نقش در سیستم
public static function boot(): PDO پیاده‌سازی الگوی Singleton؛ اگر در طول یک درخواست HTTP قبلاً اتصال دیتابیس ساخته شده باشد، همان نمونه self::$pdoInstance را در زمان $\mathcal{O}(1)$ برمی‌گرداند تا از باز شدن چندباره سوکت جلوگیری شود.
initializeConnectionAndSchema() مدیر اصلی چرخه اتصال: ۱. اتصال به MySQL را برقرار می‌کند (اگر خطای 1049 Unknown database رخ دهد، متد ساخت دیتابیس را صدا می‌زند). ۲. فایل قفل schema.lock را بررسی می‌کند. ۳. اگر دیتابیس نیاز به ساخت یا آپدیت داشت، با دستور SELECT GET_LOCK('nexro_schema_migration_lock', 10) یک قفل انحصاری در سطح سرور MySQL می‌گیرد تا اگر همزمان چند کاربر وارد سایت شدند، تداخل (Race Condition) رخ ندهد.
resolveSchemaConflicts(PDO $pdo) مکانیزم خودترمیم‌گر (Self-Healing): با اجرای SHOW COLUMNS FROM `users` LIKE 'registered_jalali' بررسی می‌کند که آیا جداول قبلی متعلق به نسخه قدیمی اسکیما هستند یا خیر. در صورت وجود مغایرت، به صورت خودکار جداول قدیمی را با غیرفعال کردن موقت FOREIGN_KEY_CHECKS پاکسازی و با ساختار جدید جایگزین می‌کند (همین متد مشکل خطای ۵۰۰ شما را به طور کامل برطرف کرد).
provisionTables(PDO $pdo) اجرای حلقه روی آرایه getTableDefinitions() و اجرای تمامی ۱۹ دستور CREATE TABLE IF NOT EXISTS با موتور InnoDB.
seedInitialData(PDO $pdo) تزریق داده‌های پایه درون یک تراکنش اتمیک (beginTransaction / commit): شامل ۳ حساب مدیریتی (owner@aisos.shop، admin@aisos.shop، coach@aisos.shop با رمز هش‌شده Bcrypt cost=12)، ۵ مشتری نمونه، ۴ برند، ۵ دسته‌بندی، ۹ محصول، ۶ سفارش، ۳ برنامه تمرینی، ۲ برنامه تغذیه، ۲ کوپن، ۳ پیام، ۳ دیدگاه و تنظیمات اولیه سایت. تمام کوئری‌ها با ON DUPLICATE KEY UPDATE نوشته شده‌اند تا اجرای چندباره آن‌ها هرگز داده تکراری نسازد.
isSchemaUpToDate() & writeSchemaLock() پس از اولین ساخت موفق جداول، فایل storage/schema.lock حاوی JSON نسخه اسکیما نوشته می‌شود. در تمام درخواست‌های بعدی، وجود و تطابق این فایل در کسری از میلی‌ثانیه چک شده و دیگر هیچ کوئری ساخت جدولی اجرا نمی‌شود.
ensureStorageDirectories() & logError() ساخت خودکار پوشه storage/logs/ با پرمیشن امن 0750، قرار دادن فایل .htaccess با دستور Deny from all داخل آن، و ثبت هرگونه خطای دیتابیس در فایل database_error.log به جای نمایش اطلاعات حساس به کاربر.
فایل شماره ۴ · گیت راه‌انداز عمومی API

/home/jprttapf/public_html/nexro/api/bootstrap.php

HTTP 503 Failover

وظیفه و عملکرد دقیق: نقطه ورود سبک برای اسکریپت‌های API که هدرهای امنیتی پایه (X-Content-Type-Options: nosniff، X-Frame-Options: DENY و Referrer-Policy) را تنظیم کرده و DatabaseBootstrapper::boot() را درون بلوک try / catch فراخوانی می‌کند. اگر دیتابیس سی‌پنل به هر دلیلی در دسترس نباشد، به جای نمایش خطای خام PHP، کد استاندارد 503 Service Unavailable را با پیام JSON فارسی برمی‌گرداند.

فایل شماره ۵ · هسته امنیتی Zero-Trust، احراز هویت و ضد نفوذ

/home/jprttapf/public_html/nexro/api/AdminSecurityGuard.php

Zero-Trust Security Engine RBAC + Anti-BruteForce

چرا این فایل را ساختیم؟ طبق خواسته شما برای اینکه پنل ادمین تحت هیچ شرایطی قابل هک، دور زدن یا Brute-Force نباشد، تمام منطق امنیتی در کلاس AdminSecurityGuard متمرکز شد.

کالبدشکافی متدبه‌متد مکانیزم‌های دفاعی در AdminSecurityGuard.php:

متد / ثابت امنیتی نحوه عملکرد خط‌به‌خط و حمله‌ای که خنثی می‌کند
applySecurityHeaders() اعمال هدرهای سخت‌گیرانه مرورگر: ۱. X-Frame-Options: DENY و frame-ancestors 'none' برای جلوگیری ۱۰۰٪ از حملات Clickjacking (بارگذاری پنل ادمین داخل iframe سایت مهاجم). ۲. Content-Security-Policy (CSP) که بارگذاری اسکریپت یا ارسال فرم به هر دامین خارجی را مسدود می‌کند (ضد XSS و Data Exfiltration). ۳. Cache-Control: no-store برای جلوگیری از ذخیره شدن صفحات ادمین در کش مرورگر.
requireAuthenticatedPage() گارد محافظ صفحات HTML/PHP (مانند admin.php). قبل از رندر شدن صفحه، نشست را با دیتابیس چک می‌کند و در صورت نامعتبر بودن، با هدر Location: /nexro/admin-login.php و کد 302 اجرای اسکریپت را متوقف (exit) می‌کند.
requireAuthenticatedApi($allowedRoles, $enforceCsrf) گارد محافظ وب‌سرویس‌های JSON: ۱. اعتبار نشست را بررسی می‌کند (در صورت عدم اعتبار: کد 401 Unauthorized). ۲. نقش کاربر (owner، admin، coach) را با آرایه مجاز مقایسه می‌کند (در صورت عدم مجوز: ثبت در audit_logs و کد 403 Forbidden). ۳. در درخواست‌های تغییر داده (POST/PUT/DELETE)، هدر HTTP_X_CSRF_TOKEN را با توکن ذخیره شده در جدول admin_sessions به کمک تابع زمان‌ثابت hash_equals() تطبیق می‌دهد (در صورت عدم تطابق: کد 419).
attemptLogin($identifier, $password, $honeypotTrap) موتور ۸ مرحله‌ای احراز هویت:
گام ۱ (Honeypot): اگر فیلد مخفی $honeypotTrap پر شده باشد، درخواست مربوط به ربات است؛ فوراً IP را قفل کرده و در لاگ امنیتی ثبت می‌کند.
گام ۲ (IP Lockout): با متد isIpLocked() بررسی می‌کند آیا IP کاربر به دلیل ۵ خطای قبلی در قفل ۱۵ دقیقه‌ای است یا خیر.
گام ۳ (User Lookup): کاربر را بر اساس ایمیل یا شماره موبایل واکشی می‌کند.
گام ۴ (ضد Timing Attack): اگر کاربر وجود نداشت، به جای بازگشت سریع، ثابت DUMMY_BCRYPT_HASH را با password_verify() بررسی می‌کند تا زمان پردازش CPU دقیقاً برابر با حالت وجود کاربر شود و هکر نتواند ایمیل‌های موجود در دیتابیس را شناسایی کند.
گام ۵ و ۶ (بررسی قفل حساب و رمز): بررسی قفل نبودن حساب (locked_until)، تطابق هش Bcrypt و داشتن نقش مجاز.
گام ۷ و ۸ (صدور نشست رمزنگاری‌شده): تولید توکن تصادفی ۲۵۶ بیتی (bin2hex(random_bytes(32)))، ذخیره هش SHA-256 آن در دیتابیس و ارسال توکن خام در کوکی HttpOnly + Secure + SameSite=Strict.
validateCurrentRequestSession() توکن داخل کوکی NEXRO_ADMIN_SEC_TOKEN را می‌خواند، هش SHA-256 آن را محاسبه کرده و با جدول admin_sessions و users جوین می‌زند. سپس هش User-Agent فعلی مرورگر را با هش ثبت‌شده در لحظه لاگین مقایسه می‌کند. اگر کوکی توسط هکر سرقت شده و در مرورگر دیگری استفاده شود، عدم تطابق شناسایی شده، نشست در دیتابیس باطل (is_revoked = 1) می‌شود و کوکی پاک می‌گردد.
writeAuditLog(...) ثبت تغییرناپذیر تمام رویدادهای حساس (ورود موفق، تلاش ناموفق، تغییر موجودی، حذف محصول، ریست دیتابیس) به همراه IP، مرورگر و مقادیر قدیم/جدید در جدول audit_logs.
فایل شماره ۶ · پورتال ورود اختصاصی مدیران و مربیان

/home/jprttapf/public_html/nexro/admin-login.php

PHP + NEXRO Bronze UI
بخش اول فایل (منطق PHP بالای صفحه - خطوط ۱ تا ۶۵):
  • فراخوانی AdminSecurityGuard::applySecurityHeaders().
  • راه‌اندازی سشن با کوکی SameSite=Strict و HttpOnly در مسیر /nexro.
  • بررسی validateCurrentRequestSession(): اگر مدیر از قبل لاگین باشد، بدون نمایش فرم لاگین مستقیماً به admin.php هدایت می‌شود.
  • تولید توکن ضد جعل فرم ($_SESSION['login_csrf_token']).
  • دریافت درخواست POST، بررسی صحت توکن CSRF با hash_equals، ارسال ورودی‌ها و فیلد تله website_url_trap به attemptLogin() و چرخش مجدد توکن CSRF در صورت بروز خطا.
بخش دوم فایل (رابط کاربری همگون با قالب - خطوط ۶۶ تا انتها):
  • بارگذاری مستقیم css/admin.css و استفاده از متغیرهای --admin-bg، --admin-panel، --admin-bronze و --admin-copper.
  • طراحی دو ستونه شامل فرم ورود در سمت راست و نشان گرافیکی حلقه‌ای برند NEXRO (.auth-emblem-ring) در سمت چپ، کاملاً هماهنگ با صفحات about.html و contact.html.
  • قرار دادن فیلد تله ربات (.hp-trap-field) خارج از دید کاربر انسانی با tabindex="-1" و aria-hidden="true".
فایل شماره ۷ · پوسته محافظت‌شده سمت سرور پنل مدیریت

/home/jprttapf/public_html/nexro/admin.php

Server-Side Gatekeeper

چرا این فایل را ساختیم و چه تفاوتی با admin.html دارد؟ اگر پنل مدیریت یک فایل .html صرف باشد، وب‌سرور کل ساختار صفحه را بدون بررسی لاگین برای هر درخواست‌کننده‌ای ارسال می‌کند. با تبدیل پوسته به admin.php، احراز هویت در سمت سرور اجباری شد، در حالی که ۱۰۰٪ تگ‌ها، ابعاد، سایدبار و کلاس‌های CSS فایل admin.html بدون تغییر حفظ شدند.

۱. گارد خط اول فایل: اجرای $adminSession = AdminSecurityGuard::requireAuthenticatedPage(); پیش از ارسال تگ <!DOCTYPE html>.
۲. تزریق متاتگ‌های امنیتی: قرار دادن <meta name="csrf-token" content="..."> و <meta name="admin-role"> در <head> برای استفاده در درخواست‌های AJAX.
۳. داینامیک‌سازی پروفایل هدر: نمایش نام واقعی مدیر لاگین‌شده، حرف اول نام در آواتار (mb_substr)، عنوان نقش فارسی و دکمه خروج امن (#admin-logout-btn).
فایل شماره ۸ · کنترلر جامع REST برای ۱۳ بخش پنل مدیریت

/home/jprttapf/public_html/nexro/api/admin_api.php

ACID Transactions Relational-to-State Adapter

چرا این فایل را ساختیم؟ فایل js/admin.js فرانت‌اند شما برای رندر کردن ۱۳ بخش پنل، به یک آبجکت وضعیت واحد (state.data) شامل آرایه‌های products، orders، customers، workouts، nutrition، coupons، messages، reviews، inventoryHistory، content و settings نیاز دارد. این فایل وظیفه ترجمه دوطرفه بین این ساختار و جداول رابطه‌ای MySQL را بر عهده دارد.

تشریح دقیق اکشن‌ها و منطق دیتابیس در api/admin_api.php:

اکشن / تابع عملیات دقیق SQL و منطق بک‌اند
fetchAdminStateFromDatabase(PDO $pdo) واکشی همزمان ۱۰ بخش از دیتابیس: اجرای INNER JOIN بین جدول products، brands و categories برای ساخت لیست محصولات؛ دیکود کردن items_json در جدول orders؛ تبدیل وضعیت کاربران (active به 'فعال')؛ تبدیل فیلدهای بولین is_read و is_archived پیام‌ها و خواندن JSON تنظیمات و محتوا از جدول site_settings.
action=load_state (GET) پس از تایید نشست و نقش توسط AdminSecurityGuard::requireAuthenticatedApi()، خروجی تابع بالا را در قالب JSON به پنل مدیریت تحویل می‌دهد.
action=sync_state (POST) مهم‌ترین بخش عملیاتی پنل که درون یک تراکنش $pdo->beginTransaction() اجرا می‌شود:
• محصولات: اگر برند یا دسته‌بندی جدیدی تایپ شده باشد، ابتدا آن را در جدول brands یا categories درج یا پیدا می‌کند، سپس محصول را با INSERT ... ON DUPLICATE KEY UPDATE ذخیره می‌نماید. اگر محصولی در UI حذف شده باشد، ستون deleted_at = CURRENT_TIMESTAMP را برای حذف نرم آپدیت می‌کند.
• برنامه‌های تمرین، تغذیه و کوپن‌ها: درج و بروزرسانی رکوردها بر اساس client_id و حذف موارد پاک‌شده.
• سفارش‌ها، مشتریان، پیام‌ها و دیدگاه‌ها: بروزرسانی وضعیت ارسال سفارش، وضعیت فعال/غیرفعال مشتری، وضعیت خوانده‌شدن/بایگانی پیام و وضعیت تایید/رد دیدگاه.
• محتوا و تنظیمات: ذخیره تغییرات بخش CMS و تنظیمات عمومی در جدول site_settings و ثبت لاگ در audit_logs.
action=reset_to_seed (POST) محدود به نقش owner و admin؛ جداول عملیاتی را TRUNCATE کرده و متد seedInitialData() را از کلاس بوت‌استرپر فراخوانی می‌کند تا دیتابیس به حالت استاندارد اولیه بازگردد.
action=logout (POST) فراخوانی AdminSecurityGuard::logout() برای باطل کردن توکن در جدول admin_sessions و حذف کوکی مرورگر.
فایل شماره ۹ · وب‌سرویس کاتالوگ مکمل‌ها و سبد خرید سشن

/home/jprttapf/public_html/nexro/api/products_api.php

Storefront Catalog API
اکشن اول: action=list (واکشی کاتالوگ زنده)

با اجرای کوئری SELECT ... FROM products p INNER JOIN brands b ... INNER JOIN categories c ... WHERE p.deleted_at IS NULL AND p.is_active = 1 تمامی محصولات فعال دیتابیس را می‌خواند. همچنین نوع مکمل (powder، tablet، capsule) را بر اساس نام و دسته‌بندی به طور هوشمند تشخیص می‌دهد تا فیلترهای صفحه products.html بدون کوچک‌ترین خطایی کار کنند.

اکشن دوم: action=add_to_cart (مدیریت سبد خرید سمت سرور)

هنگامی که کاربر روی دکمه «افزودن به سبد» کلیک می‌کند، شناسه محصول با متد POST به این اکشن ارسال می‌شود. وجود محصول در دیتابیس چک شده و اطلاعات آن در آرایه سشن سرور ($_SESSION['nexro_cart']) با طول عمر ۷ روز ذخیره می‌گردد و مجموع کل اقلام سبد (cart_count) برای نمایش در بج بالای هدر بازگردانده می‌شود.

فایل شماره ۱۰ · وب‌سرویس صفحات عمومی، محتوای داینامیک و فایروال فرم تماس

/home/jprttapf/public_html/nexro/api/public_api.php

Anti-Spam Rate Limiter
اکشن اول: action=init (تغذیه صفحات عمومی)
  • خواندن تنظیمات عمومی و محتوای CMS از جدول site_settings.
  • واکشی ۴ محصول منتخب صفحه اصلی بر اساس آرایه featuredProducts که مدیر در پنل ادمین انتخاب کرده است.
  • واکشی ۳ دیدگاه تاییدشده مشتریان (WHERE status_label = 'تأییدشده') از جدول reviews.
  • محاسبه تعداد اقلام موجود در سبد خرید سشن و صدور توکن امنیتی $_SESSION['public_csrf_token'].
اکشن دوم: action=submit_contact (ضد اسپم و ضد ربات)
  • لایه ۱ (CSRF Verification): مقایسه توکن ارسالی فرم با سشن توسط hash_equals().
  • لایه ۲ (IP Rate Limiting): بررسی جدول security_rate_limits برای اکشن contact_form_submit؛ اگر یک IP بیش از ۳ پیام در یک ساعت بفرستد، به مدت ۱ ساعت قفل شده و کد 429 Too Many Requests دریافت می‌کند.
  • لایه ۳ (Validation & Insert): اعتبارسنجی فرمت ایمیل با FILTER_VALIDATE_EMAIL، درج پیام در جدول contact_messages و چرخش توکن CSRF برای درخواست بعدی.
فایل شماره ۱۱ · پل ارتباطی بلادرنگ پنل ادمین با دیتابیس

/home/jprttapf/public_html/nexro/js/admin-backend-bridge.js

Event-Driven Sync + Debounce

چرا این فایل را ساختیم؟ برای اینکه فایل اصلی js/admin.js شما دست‌نخورده بماند و تنها با فراخوانی window.NexroAdminBackend.pushState(state.data) در تابع saveData()، تمام ۱۳ بخش پنل با دیتابیس MySQL همگام شوند.

۱. loadFromDatabase(): در لحظه DOMContentLoaded داده‌ها را از admin_api.php?action=load_state گرفته و رویداد سفارشی nexro:db-hydrated را صادر می‌کند تا admin.js جداول را با دیتای واقعی سرور رندر کند.
۲. pushState() با Debounce 120ms: هنگام ویرایش‌های سریع مدیر، درخواست‌ها را به مدت ۱۲۰ میلی‌ثانیه تجمیع کرده و با هدر X-CSRF-Token به اکشن sync_state می‌فرستد.
۳. مدیریت انقضای نشست (401): اگر در حین کار مدیر نشست ۸ ساعته منقضی شود، کد وضعیت 401 را دریافت کرده و به صورت خودکار کاربر را به admin-login.php هدایت می‌کند.
فایل شماره ۱۲ · کنترلر کاتالوگ محصولات متصل به دیتابیس

/home/jprttapf/public_html/nexro/js/products.js

Dynamic Filter & Cart Hydration
۱. fetchProductsFromDatabase(): واکشی زنده آرایه محصولات از api/products_api.php?action=list، جایگزینی آرایه products و ثبت خودکار برندهای جدید اضافه‌شده در پنل ادمین درون آرایه brandOptions.
۲. handleAddToCart(productId): ارسال شناسه محصول با متد POST به products_api.php?action=add_to_cart، دریافت تعداد واقعی سبد خرید از سشن سرور و بروزرسانی .cart-badge و نمایش Toast.
۳. escapeHtml(value) (ضد XSS): پاکسازی تمامی رشته‌های نام محصول، برند و توضیحات پیش از قرارگیری در productGrid.innerHTML با حفظ کامل کلاس‌های .product-card و .product-visual.
فایل شماره ۱۳ · کنترلر ارسال امن فرم تماس با ما به دیتابیس

/home/jprttapf/public_html/nexro/js/contact.js

Async POST + CSRF Rotation

تغییرات مهندسی اعمال‌شده نسبت به نسخه نمایشی اولیه: در نسخه اولیه، فرم تماس صرفاً یک window.setTimeout ۶۰۰ میلی‌ثانیه‌ای داشت که هیچ داده‌ای به سرور نمی‌فرستاد. در نسخه جدید، اعتبارسنجی کلاینت (validateField) حفظ شد، اما در رویداد submit، مقادیر نام، ایمیل، تلفن، موضوع و متن پیام به همراه window.NEXRO_PUBLIC_CSRF در قالب JSON به api/public_api.php?action=submit_contact ارسال می‌شوند. پس از ثبت در جدول contact_messages، توکن جدید CSRF (result.newCsrf) جایگزین شده و پیام موفقیت در تگ #form-status نمایش می‌یابد.

فایل شماره ۱۴ · موتور Hydration صفحات عمومی (خانه، درباره ما، تماس با ما)

/home/jprttapf/public_html/nexro/js/storefront.js

Zero-Layout-Shift Hydration

وظیفه و عملکرد دقیق: این اسکریپت در انتهای صفحات index.html، about.html و contact.html بارگذاری شده و با فراخوانی api/public_api.php?action=init، پنج عملیات همگام‌سازی را بدون تغییر در استایل‌ها انجام می‌دهد:

  1. ذخیره توکن CSRF عمومی در window.NEXRO_PUBLIC_CSRF برای استفاده در فرم‌ها.
  2. بروزرسانی شمارنده سبد خرید (.cart-badge) در هدر تمامی صفحات بر اساس سشن سرور.
  3. بروزرسانی اطلاعات تماس در فوتر (.footer-contact) و کارت‌های صفحه تماس (.contact-placeholder و .contact-hours) از روی تنظیمات ثبت‌شده در پنل ادمین.
  4. بروزرسانی تیتر اصلی (#hero-title)، توضیحات هیرو (.hero-description) و ۴ کارت محصول منتخب (.product-grid) در صفحه اول با حفظ کلاس‌های گرافیکی بطری مکمل‌ها (visual-whey، visual-creatine، visual-bcaa).
  5. بروزرسانی بخش نظرات مشتریان (.review-grid) در صفحه اول با دیدگاه‌های تاییدشده در دیتابیس.
بخش چهارم · آمادگی ۱۰۰٪ برای جلسه دفاع

۱۲ سوال چالشی استاد در جلسه دفاع + پاسخ‌های علمی و مهندسی

Defense Cheat-Sheet

۱. «چرا فایل‌های HTML فرانت‌اند را مستقیم به کدهای درهم‌تنیده PHP تبدیل نکردید و از معماری API + JS Bridge استفاده کردید؟»

پاسخ دفاعیه: «استاد، در مهندسی نرم‌افزار مدرن بر اساس اصل Separation of Concerns (تفکیک دغدغه‌ها)، تزریق مستقیم کوئری‌های SQL و کدهای PHP در میان تگ‌های HTML باعث ایجاد وابستگی شدید (Tight Coupling) و ریسک بالای به‌هم‌ریختگی کلاس‌های CSS می‌شود. ما با پیاده‌سازی معماری RESTful JSON API + Client-Side Hydration، لایه نمایش را ۱۰۰٪ دست‌نخورده نگه داشتیم و منطق تجاری و دیتابیس را در سرویس‌های ایزوله (admin_api.php، products_api.php و public_api.php) متمرکز کردیم. تنها استثنا، فایل admin.php است که به عنوان Server-Side Gatekeeper عمل می‌کند تا هیچ کاربری بدون احراز هویت نتواند حتی ساختار DOM پنل ادمین را دریافت کند.»

۲. «چگونه در این پروژه به صورت قطعی جلوی حملات SQL Injection را گرفته‌اید؟»

پاسخ دفاعیه: «ما در فایل config/database.php فلگ حیاتی PDO::ATTR_EMULATE_PREPARES => false را تنظیم کرده‌ایم و تمامی کوئری‌های پروژه با استفاده از $pdo->prepare() و پارامترهای مقید (Bound Parameters) اجرا می‌شوند. با غیرفعال بودن Emulated Prepares، رشته دستور SQL و داده‌های ورودی کاربر در دو بسته کاملاً مجزا در سطح پروتکل باینری MySQL ارسال می‌شوند؛ بنابراین موتور دیتابیس درخت سینتکس کوئری (Execution Plan) را پیش از دریافت ورودی کاربر کامپایل می‌کند و هیچ ورودی مخربی نمی‌تواند به عنوان دستور SQL تفسیر شود.»

۳. «اگر کلاس DatabaseBootstrapper.php جداول را خودکار می‌سازد، آیا در هر بار باز شدن سایت ۱۹ دستور CREATE TABLE اجرا می‌شود و سرعت سایت پایین نمی‌آید؟»

پاسخ دفاعیه: «خیر استاد، پیچیدگی زمانی این مکانیزم در حالت عادی $\mathcal{O}(1)$ است. ما از الگوی Fast-Path Version Lock استفاده کرده‌ایم. در اولین بارگذاری که جداول ساخته و داده‌های پایه تزریق می‌شوند، متد writeSchemaLock() یک فایل قفل به نام storage/schema.lock حاوی نسخه فعلی (1.2.0) روی دیسک ایجاد می‌کند. در تمام درخواست‌های بعدی، متد isSchemaUpToDate() قبل از ارسال هرگونه دستور DDL به دیتابیس، این فایل را چک کرده و بلافاصله نمونه PDO را برمی‌گرداند.»

۴. «اگر در اولین لحظه‌ای که سایت روی سرور قرار می‌گیرد، همزمان ۲۰ کاربر وارد سایت شوند، آیا ۲۰ بار دستور ساخت جداول و تزریق داده‌های اولیه با هم تداخل (Race Condition) پیدا نمی‌کنند؟»

پاسخ دفاعیه: «برای جلوگیری از این مشکل، الگوی Double-Checked Locking با قفل انحصاری سطح دیتابیس (MySQL Distributed Advisory Lock) را پیاده‌سازی کردیم. پیش از شروع ساخت جداول، دستور SELECT GET_LOCK('nexro_schema_migration_lock', 10) اجرا می‌شود. فقط اولین پردازه قفل را دریافت کرده و جداول و فایل schema.lock را می‌سازد؛ پردازه‌های دیگر منتظر آزاد شدن قفل در بلوک finally (RELEASE_LOCK) می‌مانند و به محض ورود به بخش بحرانی، متوجه وجود فایل قفل شده و از اجرای مجدد مایگریشن صرف‌نظر می‌کنند.»

۵. «چرا توکن نشست ادمین را در جدول admin_sessions به صورت هش SHA-256 ذخیره کردید؟ چرا خود توکن را ذخیره نکردید؟»

پاسخ دفاعیه: «اگر توکن نشست به صورت متن خام (Plaintext) در دیتابیس ذخیره شود، در صورت نشت فایل بکاپ دیتابیس یا دسترسی خواندنی مهاجم به دیتابیس، او می‌تواند توکن‌های فعال مدیران را بردارد و در مرورگر خود ست کند (Session Replay). اما در معماری ما، توکن ۶۴ کاراکتری تولیدشده توسط random_bytes(32) فقط در کوکی HttpOnly مرورگر مدیر قرار می‌گیرد و در ستون token_hash دیتابیس صرفاً هش یک‌طرفه SHA-256 آن ذخیره می‌شود.»

۶. «حمله Timing Attack (حمله زمان‌سنجی) در صفحه لاگین چیست و چطور در AdminSecurityGuard.php جلوی آن را گرفتید؟»

پاسخ دفاعیه: «الگوریتم هش رمز عبور Bcrypt (cost=12) عمداً حدود ۱۰۰ تا ۲۰۰ میلی‌ثانیه زمان پردازش CPU مصرف می‌کند. در سیستم‌های معمولی، اگر ایمیل واردشده در دیتابیس وجود نداشته باشد، سرور در ۱ میلی‌ثانیه خطا برمی‌گرداند، اما اگر ایمیل وجود داشته باشد و رمز غلط باشد، ۲۰۰ میلی‌ثانیه طول می‌کشد. هکر با اندازه‌گیری این اختلاف زمان متوجه می‌شود کدام ایمیل‌ها در سیستم ثبت‌نام کرده‌اند (User Enumeration). ما در متد attemptLogin()، در صورتی که کاربر در دیتابیس یافت نشود، متغیر DUMMY_BCRYPT_HASH را با password_verify() پردازش می‌کنیم تا زمان پاسخ سرور در هر دو حالت دقیقاً یکسان باشد.»

۷. «اگر کوکی نشست مدیر توسط بدافزار از روی سیستم او سرقت شود، سیستم چگونه جلوی استفاده هکر از آن کوکی را می‌گیرد؟»

پاسخ دفاعیه: «در لحظه لاگین، هش امضای مرورگر مدیر (user_agent_hash با نمک اختصاصی) در جدول admin_sessions ثبت می‌شود. در هر درخواست بعدی، متد validateCurrentRequestSession() با تابع hash_equals() امضای مرورگر فعلی را با دیتابیس تطبیق می‌دهد. به محض تشخیص عدم تطابق، سیستم به صورت خودکار ستون is_revoked = 1 را در دیتابیس ثبت کرده، نشست را باطل می‌کند و رخداد SESSION_HIJACK_PREVENTED_UA_MISMATCH را در جدول audit_logs ثبت می‌نماید.»

۸. «چگونه جلوی حملات CSRF (Cross-Site Request Forgery) و XSS را گرفته‌اید؟»

پاسخ دفاعیه: «برای مقابله با CSRF، علاوه بر تنظیم کوکی نشست روی حالت SameSite=Strict، برای هر نشست یک توکن تصادفی ۲۵۶ بیتی csrf_token تولید می‌شود که در تمامی درخواست‌های POST/PUT/DELETE باید در هدر X-CSRF-Token ارسال شود. برای مقابله با XSS نیز در سمت سرور از htmlspecialchars(..., ENT_QUOTES, 'UTF-8') به همراه هدر Content-Security-Policy و در سمت کلاینت از تابع escapeHtml() پیش از تزریق هرگونه داده به DOM استفاده شده است.»

۹. «چرا برای حذف محصولات از الگوی Soft Delete (ستون deleted_at) استفاده کردید به جای DELETE FROM products؟»

پاسخ دفاعیه: «در سیستم‌های فروشگاهی، محصولات با سفارش‌های قبلی مشتریان و لاگ‌های انبار در ارتباط هستند. اگر یک محصول به صورت فیزیکی (Hard Delete) پاک شود، تاریخچه سفارش‌ها و گزارش‌های مالی دچار نقص مرجع (Orphaned Records) می‌شوند. با استفاده از ستون deleted_at، هنگام حذف محصول فقط زمان حذف ثبت می‌شود؛ در نتیجه محصول از کاتالوگ فروشگاه (WHERE deleted_at IS NULL) مخفی می‌گردد اما تاریخچه مالی و انبارداری دست‌نخورده باقی می‌ماند.»

۱۰. «تراکنش ACID در اکشن sync_state فایل admin_api.php چه نقشی دارد؟»

پاسخ دفاعیه: «زمانی که داده‌های پنل مدیریت همگام‌سازی می‌شوند، چندین جدول (برندها، دسته‌بندی‌ها، محصولات، سفارش‌ها و لاگ ممیزی) باید با هم آپدیت شوند. با قرار دادن کل این فرآیند درون بلوک $pdo->beginTransaction() و $pdo->commit()، خاصیت Atomicity (اتمیک بودن - همه یا هیچ) تضمین می‌شود؛ یعنی اگر در میانه کار یکی از کوئری‌ها با خطا مواجه شود، در بلوک catch دستور $pdo->rollBack() اجرا شده و دیتابیس به وضعیت کاملاً سالم قبلی بازمی‌گردد.»

۱۱. «چگونه جلوی اسپم شدن فرم تماس با ما (contact.html) توسط ربات‌ها را بدون استفاده از کپچای مزاحم کاربری گرفتید؟»

پاسخ دفاعیه: «ما در api/public_api.php یک فایروال دولایه شامل توکن CSRF چرخشی (Rotating CSRF Token) و Rate Limiter سطح دیتابیس پیاده‌سازی کردیم. در جدول security_rate_limits تعداد پیام‌های ارسالی هر IP تحت کلید contact_form_submit شمارش می‌شود. به محض اینکه یک IP بیش از ۳ پیام در ساعت ارسال کند، ستون locked_until برای ۱ ساعت آینده تنظیم شده و سرور کد استاندارد 429 Too Many Requests را برمی‌گرداند.»

۱۲. «چگونه سبد خرید در صفحه products.html بین صفحات مختلف سایت (index.html، about.html، contact.html) هماهنگ می‌ماند؟»

پاسخ دفاعیه: «هنگام کلیک روی دکمه افزودن به سبد در products.js، درخواست به api/products_api.php?action=add_to_cart ارسال شده و محصول پس از تایید موجودی در دیتابیس، درون سشن سرور ($_SESSION['nexro_cart']) با کوکی ۷ روزه ذخیره می‌شود. سپس در سایر صفحات سایت، اسکریپت js/storefront.js تعداد واقعی اقلام سشن را از سرور خوانده و درون بج .cart-badge هدر نمایش می‌دهد.»