# Phase 1 Design: Data Model (046)

## Entities

### InventorySyncRun
Existing table: `inventory_sync_runs`

**Purpose**: Observable record of one inventory sync execution for a tenant + selection.

**Existing fields (selected)**
- `id`
- `tenant_id` (FK)
- `selection_hash` (sha256)
- `selection_payload` (jsonb)
- `status` (`running|success|partial|failed|skipped`)
- `had_errors` (bool)
- `error_codes` (jsonb)
- `error_context` (jsonb)
- `started_at`, `finished_at`
- `items_observed_count`, `items_upserted_count`, `errors_count`

**Planned additions (to satisfy FR-008)**
- `user_id` (nullable FK to `users.id`)
  - Meaning: initiator of the run (UI-triggered). `null` allowed for system/scheduled runs.

**Relationships**
- `InventorySyncRun belongsTo Tenant`
- `InventorySyncRun belongsTo User` (new, nullable)

**Validation rules (selection payload)**
- `policy_types`: list of strings; filtered through `PolicyTypeResolver::filterRuntime(...)`
- `categories`: list of strings (optional; currently not used for the UI-triggered “full inventory” run)
- `include_foundations`: boolean
- `include_dependencies`: boolean

### BulkOperationRun
Existing table: `bulk_operation_runs`

**Purpose**: Generic progress tracking for background operations. Used by the bottom-right progress widget.

**Relevant fields**
- `tenant_id`, `user_id`
- `resource`, `action` (used for display)
- `status` (`pending|running|completed|completed_with_errors|failed|aborted`)
- Counters: `total_items`, `processed_items`, `succeeded`, `failed`, `skipped`
- `audit_log_id` (FK)

**Usage for Inventory Sync**
- `resource = 'inventory'`, `action = 'sync'`
- `total_items = 1`
- `item_ids = [selection_hash]` (or `[inventory_sync_run_id]` after creation)

### AuditLog
Existing table: `audit_logs`

**Purpose**: Immutable audit trail with actor identity snapshot.

**Usage for Inventory Sync**
- Emit `inventory.sync.dispatched` and a terminal event like `inventory.sync.completed` / `inventory.sync.failed`.
- `resource_type = 'inventory_sync_run'`, `resource_id = (string) $run->id`
- Actor fields filled from authenticated user.

## State transitions

### InventorySyncRun
- `running` → `success|partial|failed`
- `running` → `skipped` (lock/concurrency)

### BulkOperationRun
- `pending` → `running` → `completed|completed_with_errors|failed|aborted`

