بستهٔ میزبانی میرزای حرم — نسخهٔ 235

مسیر فعلی هر شخص: ورود فردی ← نیت چاپ و پخش برگه ← اعلام مبلغ ← آمادهٔ حرکت.
دعوت و تکمیل گروه شرط ادامه نیست. مبلغ فقط نیت شخص است؛ پول به میزبان یا مدیر
پرداخت نمی‌شود. اصلاح نیت با امضای همان شخص انجام می‌شود. سابقهٔ معتبر قبلی
حفظ می‌شود؛ میزبان اجازهٔ ساخت عضو، مبلغ، خبر مدیریتی یا کلید مرجع جدید ندارد.

کدام فایل را نصب کنم؟
public-rescue-host-kit.zip بستهٔ کد و ابزار نصب است. خود APK داخل آن نیست.
بستهٔ قابل‌حملِ خروجی برنامه، علاوه بر همین ZIP، این فایل‌ها را کنار هم دارد:
portable235/
  public-rescue-host-kit.zip
  public-rescue-package.json
  public-files/app-release.apk
  public-files/public-android-release.json
  public-files/app-release-ar.apk              (اختیاری؛ همراه فایل بعدی)
  public-files/public-android-release-ar.json  (اختیاری؛ فقط نسخهٔ عربی)
ZIP کد را باز کنید و فقط یکی از shared-host.zip یا vps-host.zip را انتخاب کنید.
پوشهٔ نهایی shared-host یا vps-host را مستقیم زیر portable235 قرار دهید، تا
public-files همسایهٔ آن باشد. پوشهٔ رمزها، پایگاه داده و فایل تنظیمات خصوصی
نباید به پوشهٔ عمومی یا ZIP قابل‌انتشار اضافه شود.
اگر محل استخراج متفاوت است، سازندهٔ میزبان می‌تواند متغیر محیطی ثابت
CHARITY_PUBLIC_ASSETS_DIR را روی مسیر مطلق portable235 تنظیم کند.
نشانی یا مسیر ارسال‌شده از یک درخواست عمومی هرگز جای این تنظیم را نمی‌گیرد.

نصب‌کننده، امضای Root روی معرفی‌نامهٔ APK و هش کامل APK را بررسی می‌کند؛ سپس
کلید عمومی و مشخصات ZIP کدِ داخل همان APK را با ZIP و فرادادهٔ بیرونی تطبیق
می‌دهد. چهار فایل عمومیِ فارسی الزامی‌اند؛ اگر هر دو فایل عربی هم حاضر و معتبر باشند،
آن دو نیز در مسیرهای جدا کپی می‌شوند. یک فایل عربیِ بدون جفت پذیرفته نمی‌شود. فایل معرفی نسخه نیز لازم است؛
صرف وجود APK برای به‌روزرسانی گوشی کافی نیست. نسخهٔ صرفاً کد می‌تواند سرویس
میزبانی را فعال کند، ولی تا آماده‌شدن چهار فایل، دانلود برنامه و بسته آماده نیست.
نشان سلامت سرویس و نشان آمادگی دانلود دو بررسی جدا هستند.

نصب روی VPS
1. یک Linux x86_64 دارای systemd و دسترسی sudo لازم است؛ Node و Caddy در ZIP هستند.
2. رکورد A دامنه را به IP همان VPS بدهید. درگاه‌های TCP 80 و443 باید باز باشند.
3. در پوشهٔ vps-host دستور زیر را اجرا کنید:
sudo bash install-vps.sh
4. دامنهٔ شخصی خود و نشانی کامل یک میزبان زندهٔ شناخته‌شده را وارد کنید، مانند:
https://host-a.example/index.php
5. اگر اولین و تنها میزبان هستید، نشانی همتا می‌تواند خالی باشد. تک‌میزبانی
ممکن است، اما در این حالت آزمون میان میزبان‌ها کامل نمی‌شود.
6. نصب‌کننده سایت قبلی را خاموش نمی‌کند. درگاه‌های80،443،17177 باید آزاد باشند
و /opt/charity-sealed-relay از قبل وجود نداشته باشد. اجرای دوباره روی نصب قبلی
به معنی مجوز پاک‌کردن داده‌های آن نیست.
7. مرورگر را روی https://YOUR-DOMAIN/developers.html باز کنید. صدور HTTPS به
DNS درست، دسترسی ورودی80/443 و ساعت صحیح سرور نیاز دارد. دادهٔ سرویس در پوشهٔ
خصوصی systemd می‌ماند و با راه‌اندازی مجدد پاک نمی‌شود.

نصب روی هاست PHP
1. پوشهٔ shared-host را در سایت شخصی دارای HTTPS قرار دهید. نشانی کامل سرویس
باید به index.php برسد؛ مانند https://YOUR-DOMAIN/shared-host/index.php.
2. PHP8.2 یا جدیدتر،64-bit، OpenSSL، PDO SQLite، cURL و Zlib لازم است. cURL برای
معرفی امن میزبان و اتصال IP ثابت با اعتبارسنجی TLS لازم است؛ جایگزین ناامن ندارد.
3. index.php?action=health را باز کنید. پوشهٔ خصوصی .charity-sealed-* به‌طور
خودکار خارج از DOCUMENT_ROOT ایجاد می‌شود. اگر هاست اجازه نمی‌دهد، سازگار نیست؛
دیتابیس را به پوشهٔ عمومی منتقل نکنید.
4. کنار دیتابیس خصوصی، replication-peers.json را با نشانی واقعی خود بسازید:
{"selfUrl":"https://host-b.example/index.php","peers":["https://host-b.example/index.php","https://host-a.example/index.php"]}
5. دسترسی HTTPS خروجی، post_max_size دست‌کم20M و حافظه و فضای کافی PHP لازم است.
برای دانلودها، PHP باید اجازهٔ نوشتن چهار فایل عمومی تأییدشده را داشته باشد.
6. در زمان‌بند هاست، هر دقیقه این فرمان را با مسیر واقعی PHP، فایل و DOCUMENT_ROOT بگذارید:
php /ABSOLUTE/shared-host/relay-cron.php /ABSOLUTE/DOCUMENT_ROOT
این دستور فقط از CLI اجرا می‌شود. یک نوبت، کار را محدود به16چرخه و حدود20ثانیه
ادامه می‌دهد؛ کندی شبکه می‌تواند انتهای آخرین درخواست سه‌ثانیه‌ای را به آن اضافه کند.
در هاست تک‌کارگری، همین CLI جداگانه برای معرفی خودکار مطمئن لازم است؛ فراخوانی
HTTP سلامت از همان تک‌کارگر جای آن را نمی‌گیرد، چون بررسی برگشتی HTTPS منتظر
آزادشدن همان کارگر می‌ماند. در هاست چندکارگری، پس از درخواست‌ها هم صف پیش می‌رود.
اگر IP عمومی میزبان در SERVER_ADDR درست نیست، در فایل تنظیمات خصوصی می‌توانید
selfAddresses را با یک تا چهار IP عمومی واقعی و قابل‌دسترسی تنظیم کنید. اولین
نشانی اولویت دارد؛ در نسخهٔ فعلی برای نشانی معرفی‌شده جایگزینی خودکار IP دوم
انجام نمی‌شود. این گزینه مجوز استفاده از IP داخلی یا خاموش‌کردن TLS نیست.

میزبان‌ها چگونه با هم کار می‌کنند؟
مثلاً الف و ب فعال‌اند. شما ج را نصب می‌کنید و نشانی الف را در تنظیمش می‌گذارید.
ج خودش را به الف معرفی می‌کند. الف با اتصال HTTPS برگشتی، نام دامنه، پین کلید
Root، شناسهٔ شبکه، سیاست عضویت و شاخص سوابق قبلی را تطبیق می‌دهد. این فقط شناخت
یک مسیر انتقال است؛ میزبان جدید اختیار مدیریت یا تولید آمار دریافت نمی‌کند.
نشانی‌های بررسی‌شده به‌صورت محدود و چرخشی بین میزبان‌ها معرفی می‌شوند؛ ب هم
می‌تواند ج را بشناسد. هر نامزد تازه دوباره مستقل بررسی می‌شود. این روند فوری
و سراسری نیست؛ قطع شبکه، محدودیت نرخ و تعداد میزبان‌ها روی زمان آن اثر دارند.
هر میزبان حداکثر64نشانی آموخته‌شدهٔ24ساعته نگه می‌دارد؛ نشانی‌های تنظیم‌شدهٔ
اپراتور جدا هستند. هر پاسخ حداکثر8نشانی چرخشی به گوشی پیشنهاد می‌دهد؛ این
نشانی‌ها کلید اعتماد یا مجوز مدیریت نیستند. گوشی باید پاسخ و امضاها را بررسی کند.
نشانی منقضی‌شده از مسیرهای فعال کنار می‌رود ولی در سقف64رکورد حفظ می‌شود؛ زمان‌بند با همان IP قبلی و TLS و هویت شبکه دوباره آن را می‌آزماید و فقط پس از موفقیت اعتبارش را تمدید می‌کند. خطا با مکث دوباره بررسی می‌شود. نشانی‌های آموخته‌شده با IP عمومی بررسی‌شده می‌مانند؛ انقضا یا خطا باعث اتصال
به IP دلخواه یا برگشت پنهانی به DNS ناامن نمی‌شود. پس از تغییر IP، معرفی تازه
و اعتبارسنجی دوباره لازم است. پیشنهاد نامعتبر، IP خصوصی یا تغییر Root رد می‌شود.

اصل گواهی‌های عمومیِ امضاشده، از طریق individual-sync بین همتایان دریافت می‌شود.
نشان دریافت در SQLite ماندگار است. هر صفحه پیش از پیشروی نشان، دقیقاً با امضا،
سیاست و قواعد اصلی بررسی می‌شود. قطع مقصد، صفحهٔ نامعتبر یا کمبود فضا نشان را
جلو نمی‌برد. تکرار بر اساس هش حذف می‌شود. پس از تعویض مخزن در همان نشانی،
بازخوانی از اول انجام می‌شود و گواهی معتبر قبلی حذف نمی‌شود. اصلاح مبلغی که
پیش از گواهی والد برسد، نگه داشته می‌شود تا وابستگی معتبر برسد؛ عضو یا مبلغ
ساختگی ایجاد نمی‌کند. یک میزبان نمی‌تواند با ارسال عدد خام آمار را بالا ببرد.
گواهی‌های عمومی دارای شناسهٔ مستعار ثابت و مبلغ‌اند؛ نام و شماره نیستند، ولی
سوابق یک شناسه قابل ارتباط‌دادن‌اند. این مجوز انتشار شامل متن خبر، رمز یا
پیام خصوصی نمی‌شود. individual-authority.json و individual-bootstrap.json فقط
اطلاعات عمومیِ مجاز دارند؛ کلید خصوصی مرجع داخل بسته نیست.

پشتیبان شخصی و پیام گیرنده با گواهی عمومی فرق دارند. آنها رمزگذاری‌شده‌اند و
فقط در مسیرهای خصوصیِ تنظیم‌شدهٔ قبلی با جایگذاری محدود تا3نسخه ارسال می‌شوند؛
به همهٔ میزبان‌های تازهٔ عمومی پخش نمی‌شوند. گیرنده امضای اصلی و مجوز نویسنده
را بررسی می‌کند. اصل داده و کلید هویت را روی گوشی نگه دارید؛ رسید سرور مجوز
حذف دادهٔ گوشی نیست. امضای معتبر، نگهداری و پاسخ‌دادن یک میزبان خرابکار را
تضمین نمی‌کند. نسخهٔ سالم و چند میزبان مستقل همچنان لازم است.

اگر همهٔ میزبان‌ها قطع شدند
گوشی‌ها دادهٔ محلی را نگه می‌دارند. یک دامنهٔ کاملاً تازه خودبه‌خود برای گوشی
بدون هیچ مسیر ارتباطی شناخته نمی‌شود. سازندهٔ میزبان، HTTPS را از developers.html
به اولین گوشی در «کارت احیا / معرفی میزبان» معرفی می‌کند. گوشی‌های دارای مجوز
و ارتباط نزدیک واقعی می‌توانند نشانی را با بلوتوث دریافت و بازپخش کنند. این
ارتباط شبکه‌ای است؛ لازم نیست همه با اولین گوشی روبه‌رو شوند. بلوتوث خاموش
چیزی دریافت نمی‌کند و تحویل پیش از روشن‌شدن آن قابل تضمین نیست. آزمون روی
گوشی واقعی و چند میزبان مستقل جداگانه لازم است؛ سلامت سرور به معنی احیای همه نیست.

آزمون‌ها روی دامنهٔ خودتان
پس از نصب developers.html را باز کنید. هر آزمون نتیجه، علت و راه‌حل جدا دارد:
1. محیط اجرا و SQLite همین میزبان.
2. نوشتن/خواندن موقت با rollback و آزمون P-256 و AES-GCM.
3. سلامت، سازگاری و شناخت متقابل نمونهٔ حداکثر3همتای شناخته‌شده.
4. رفت‌وبرگشت پیام امضاشدهٔ رمزگذاری‌شدهٔ موقت؛ عضو یا خبر ساخته نمی‌شود.
5. گزارش فقط‌خواندنی آخرین چرخهٔ واقعی دریافت گواهی: زمان آخرین موفقیت، نشان
دریافت، صفحهٔ باقی‌مانده و تلاش دوباره در نمونهٔ حداکثر3همتا. همتای هرگز دیده‌نشده،
چرخهٔ قدیمی‌تر از3دقیقه، صفحهٔ باقی‌مانده، کمبود فضا یا نبود گواهی مشاهده‌شده
نتیجهٔ کامل نمی‌گیرد. این آزمون کاربر آزمایشی نمی‌سازد و داده‌ای را پاک نمی‌کند.
سبزشدن آزمون5 فقط تازگی چرخهٔ مشاهده‌شدهٔ همان نمونه را نشان می‌دهد؛ اثبات
برابری همهٔ گوشی‌ها، تمام تاریخچهٔ جهان یا احیای کامل نیست. آمادگی فایل‌های
دانلود برنامه، معرفی نسخه و ZIP جداگانه با HEAD روی همان دامنه بررسی می‌شود.

مسیرهای عمومی
GET index.php?action=health
GET index.php?action=host-info
GET index.php?action=host-test&test=1 تا5
POST index.php?action=host-introduce — معرفی محدود مسیر عمومی با بررسی برگشتی
POST index.php?action=individual-sync — دریافت/بازپخش گواهی عمومی امضاشده
POST index.php?action=store و fetch — پشتیبان امضاشدهٔ مالک
POST index.php?action=send-events و fetch-events — پیام رمزگذاری‌شدهٔ گیرنده
GET/HEAD index.php?action=download&file=... — فقط فایل‌های عمومی مجاز
درخواست individual-sync حداکثر256KiB/64گواهی و پاسخ حداکثر32گواهی/128KiB است.
تغییر سیاست یا شاخص اصلی نیاز به مهاجرت نسخه‌دار دارد؛ حذف مخزن راه مهاجرت نیست.

محدودیت و مرز بسته
سقف پیش‌فرض سرویس1GiB،10هزار پشتیبان مالک و320هزار پیام گیرنده است. سقف مخزن
گواهی عمومی20هزار رکورد/16MiB است. این اعداد به معنی آزمون ظرفیت چند میلیون
گوشی یا10هزار میزبان نیستند. پرشدن ظرفیت نیاز به بررسی واقعی دارد و دادهٔ
معتبر با حدس یا عددسازی جبران نمی‌شود. اندازه و زمان ترافیک و شناسه‌های مستعار
برای میزبان قابل مشاهده‌اند. بدون کلید هویت، ZIP هویت گمشده را بازنمی‌سازد.
مدیریت همان یک مدیر با رمز فعلی است؛ این بسته اختیار جدیدی برای میزبان نمی‌سازد.
بسته هیچ گذرواژه، کلید خصوصی، رمز مدیر یا شمارهٔ اعضا ندارد. گزارش آزمون‌ها باید
همراه نسخه ارائه شود؛ هیچ آزمون محلی به‌تنهایی تضمین نبودن هر نوع قطعی نیست.
کد این پوشه MIT است؛ Node و Caddy مجوزهای مستقل دارند.

تصویر برگهٔ A5 — انتقال عمومیِ امضاشده
GET index.php?action=public-artwork معرفی‌نامهٔ امضاشدهٔ آخرین جفت تصویر را می‌دهد.
POST همین نشانی فقط جفت کاملِ دارای اجازهٔ امضاشدهٔ مدیر اصلی را می‌پذیرد.
گوشیِ دارای نسخهٔ معتبر می‌تواند آن را به میزبان تازه معرفی کند؛ میزبان خودش
اجازهٔ تغییر تصویر، صدور امضا یا تغییر عضو و مبلغ را ندارد. تصویرها JPEG با
ابعاد 740×768 و حداکثر 160KiB برای هر رو و پشت هستند؛ کد QR و تاریخ تازه
در برنامه جداگانه ساخته می‌شوند. هر فایل چاپ‌شدهٔ قبلی همان نسخهٔ قبلی می‌ماند.
این مخزن فقط دو جفت کاملِ آخر را، در public-artwork.sqlite داخل پوشهٔ خصوصی
کنار sealed-snapshots.sqlite نگه می‌دارد. هر پشتیبان‌گیری، انتقال یا بازگشت
نسخه باید public-artwork.sqlite را هم جداگانه حفظ کند؛ هیچ‌کدام از پایگاه‌های
داده برای ارتقا پاک نمی‌شوند. خود پایگاه‌های داده وارد ZIP عمومی نمی‌شوند.
میزبان نو تا رسیدن یک جفت معتبر از گوشی، تصویر اختصاصی ندارد؛ برنامه از برگهٔ
استاندارد استفاده می‌کند. این قابلیت به معنی شناسایی نشانی ناشناخته یا اتصال
فوری همهٔ گوشی‌های آفلاین نیست. تنظیم قبلی شبکه و مرجع امضا همچنان حفظ می‌شود.

نسخهٔ عربی در کنار فارسی
مسیر عمومی عربی index.php?lang=ar است. فایل app-release-ar.apk و معرفی‌نامهٔ
public-android-release-ar.json جدا از فایل‌های فارسی‌اند؛ هیچ‌کدام را جای فایل
فارسی نگذارید. هر دو برنامه همان مرجع، شبکه و آمار واقعی را دارند. هر نصب
شناسهٔ مستقل خود را دارد؛ دو برنامهٔ نصب‌شده روی یک گوشی، هویت مشترک خودکار ندارند.
خبرهای عربی فقط با همان رمز و مجوز مدیر در کانال مجزای عربی منتشر می‌شوند.
میزبان مستقل اختیار انتشار خبر یا ویرایش متن ندارد. کانالِ تصویر برگهٔ عربی
public-artwork-ar نیز جداست؛ دیتابیس خصوصی public-artwork-ar.sqlite و فایل
public-artwork.sqlite فارسی را در ارتقا یا بازگشت پاک یا جایگزین نکنید.
نام‌ها، رمز مدیر و کلید خصوصی نباید به ZIP عمومی وارد شوند. داده و مرجعِ شمارش
همچنان همان دادهٔ واقعی و امضاهای اصلی‌اند؛ تفاوت زبان، شبکهٔ تازه ایجاد نمی‌کند.
در Apache، میان‌بر app-ar.apk در صورت وجود mod_rewrite کار می‌کند؛ لینک اصلی
index.php?action=download&file=app-release-ar.apk به این افزونه وابسته نیست.
