# ممیزی، پشتیبان‌گیری و بازیابی

## مدل ممیزی

جدول `audit_events` append-only است و trigger پایگاه UPDATE/DELETE را منع می‌کند. actor، نقش، IP، user-agent، نوع عمل، entity، مقادیر قدیم/جدید و زمان UTC ذخیره می‌شوند. `invoice_versions`، ردیف نسخه‌ها، `delivery_events` و اقلام درخواست تحویل نیز پس از درج تغییرناپذیرند.

خود audit جای backup را نمی‌گیرد. دسترسی خواندن آن فقط به مجوزهای ممیزی داده شود و دسترسی مستقیم database محدود بماند.

## برنامهٔ backup پیشنهادی

- هر شب dump سفارشی PostgreSQL با `pg_dump -Fc`.
- نگهداری روزانه ۱۴ روز، هفتگی ۸ هفته و ماهانه ۱۲ ماه مطابق سیاست سازمان.
- backup جداگانه از volume `app-storage` برای فایل‌های import و گزارش‌ها.
- رمزنگاری در انتقال/سکون و یک نسخه خارج از میزبان اصلی.
- تست restore حداقل فصلی و ثبت RPO/RTO واقعی.

نمونه:

```bash
stamp=$(date +%Y%m%d-%H%M%S)
docker compose exec -T postgres pg_dump -U mandegar -d mandegar -Fc > "mandegar-$stamp.dump"
docker run --rm -v mandegar-delivery_app-storage:/source:ro -v "$PWD/backups:/backup" alpine \
  tar -czf "/backup/storage-$stamp.tar.gz" -C /source .
sha256sum "mandegar-$stamp.dump" "backups/storage-$stamp.tar.gz" > "backups/checksums-$stamp.txt"
```

نام volume را با `docker volume ls` تأیید کنید؛ هرگز فرمان حذف volume را در اسکریپت backup قرار ندهید.

## restore آزمایشی

روی database جدا:

```bash
createdb mandegar_restore_test
pg_restore --clean --if-exists --no-owner -d mandegar_restore_test mandegar-YYYYMMDD-HHMMSS.dump
psql -d mandegar_restore_test -c "select count(*) from audit_events;"
```

سپس checksum فایل‌های storage، تعداد فاکتور/نسخه/رویداد و ورود read-only را کنترل کنید. restore production باید change window، backup جدید از وضعیت فعلی و تأیید دو نفره داشته باشد.

## بازیابی job

scheduler قفل job پردازش‌شدهٔ بیش از ۱۵ دقیقه را آزاد می‌کند و backoff نمایی دارد. پس از رسیدن به `max_attempts` job failed می‌شود و نیاز به بررسی علت دارد. قبل از retry دستی، idempotency و وضعیت import/report را کنترل کنید.

## رخداد امنیتی

1. نشست‌های مشکوک را با reset رمز یا افزایش `session_version` باطل کنید.
2. `APP_KEY`/`SESSION_SECRET` و رمزهای DB/Redis را در صورت افشا rotate کنید؛ rotation session همه کاربران را منقضی می‌کند.
3. بازهٔ audit و log Nginx/application را read-only استخراج و checksum کنید.
4. زمان، actor، IP و entityهای متاثر را مستند کنید؛ رویدادها را ویرایش نکنید.
5. پس از رفع علت، restore یا اصلاح جبرانی را با audit جدید انجام دهید، نه بازنویسی سابقه.
