# Domain 12 — Audit, Config & Reference

[← Database Model](index.md)

### `audit_logs` [CORE]
**Role:** Immutable, append-only record of every state change on sensitive entities — now explicitly **including `platform_configs`** (so finance can prove the commission rate at any moment). **Why:** compliance and accountability; `changed_fields_json` enables fast filtering. Plan month-partitioning + 2–3yr cold-storage archival before launch. Fields unchanged. **Relations:** polymorphic, append-only.

### `system_events` [MVP]
**Role:** High-volume behavioral/analytics event log. **Why kept but de-emphasized:** product analytics, not compliance. It grows unbounded — at scale, pipe it to an analytics sink/warehouse rather than the transactional DB. Fields unchanged.

### `platform_configs` [CORE]
**Role:** Key-value runtime business parameters — change without a deploy. **Why typed values:** `data_type` tells the app how to parse. **New keys** this revision: `dispute_window_hours` (default 72), `vat_rate` (0.10), `bnpl_merchant_of_record`, `bnpl_provider_commission_rate`, `bnpl_settlement_timing`, cancellation-tier defaults — alongside the existing `platform_fee_rate`, `booking_payment_deadline_minutes`, `nurse_response_deadline_hours`, `nurse_payout_interval_days`, `evv_location_tolerance_meters`, `min_rating_for_support_alert`. **Relations:** referenced everywhere; changes audited.

**Seeded defaults (as built, backend-phase-1).** The baseline migration seeds every key below. Values marked _provisional_ were chosen as safe defaults where the product docs did not pin a number — confirm before launch; each is config-driven so it changes without a deploy.

| Key | `data_type` | Seeded value | Source |
|---|---|---|---|
| `platform_fee_rate` | decimal | `0.15` | _provisional_ |
| `vat_rate` | decimal | `0.10` | doc (10%, commission line only) |
| `dispute_window_hours` | int | `72` | doc |
| `booking_payment_deadline_minutes` | int | `30` | doc |
| `nurse_response_deadline_hours` | int | `24` | _provisional_ |
| `nurse_payout_interval_days` | int | `7` | doc (weekly) |
| `evv_location_tolerance_meters` | int | `200` | _provisional_ |
| `min_rating_for_support_alert` | decimal | `2` | _provisional_ (review ≤ 2 raises an alert) |
| `bnpl_merchant_of_record` | string | `platform` | doc (Balinyaar is MoR) |
| `bnpl_provider_commission_rate` | decimal | `0.07` | _provisional_ |
| `bnpl_settlement_timing` | string | `immediate` | _provisional_ |
| `cancellation_tiers` | json | `[{"min_hours_before":48,"refund_percent":100},{"min_hours_before":24,"refund_percent":50},{"min_hours_before":0,"refund_percent":0}]` | _provisional_ |

Rates are `DECIMAL` fractions (not money); the IRR amounts they later multiply are `BIGINT`. **Read them at compute time (cached via `IPlatformConfig`), never hardcode**, and snapshot the rate used onto the priced booking/invoice so a later rate change never re-prices an existing row.

### `iranian_holidays` [MVP] — **NEW**
**Role:** Shared official/religious holiday calendar (movable, partly lunar-Hijri), with a `is_bank_closed` flag. **Why a real table:** Iran's holidays are numerous and partly movable, and they drive **payout bank-closure scheduling** (PAYA/SATNA closed → a weekly payout shifts to the next business day), optional holiday pricing, and business-hour deadline math — none of which a purely manual per-nurse availability exception can express.

| Field | Type | Notes |
|---|---|---|
| `id` | BIGINT PK | |
| `holiday_date` | DATE | |
| `name_fa` | NVARCHAR(200) | |
| `type` | NVARCHAR(20) | `official` / `religious` / `national` |
| `is_bank_closed` | BIT | Drives payout date shifting |

**Relations:** referenced by payout scheduling and (optionally) pricing.
