132 lines
4.4 KiB
Markdown
132 lines
4.4 KiB
Markdown
# Data Model (Spec 086)
|
|
|
|
This feature consolidates execution tracking into `operation_runs` while keeping legacy run tables as read-only history.
|
|
|
|
## Entities
|
|
|
|
### 1) OperationRun (canonical)
|
|
|
|
**Table:** `operation_runs`
|
|
|
|
**Purpose:** Single source of truth for execution tracking: status/progress, results (counts), failures, provenance/context.
|
|
|
|
**Fields (current):**
|
|
- `id`
|
|
- `workspace_id` (FK, required)
|
|
- `tenant_id` (FK, nullable)
|
|
- `user_id` (FK, nullable)
|
|
- `initiator_name` (string)
|
|
- `type` (string; see OperationRunType registry)
|
|
- `status` (string; queued|running|completed)
|
|
- `outcome` (string; pending|succeeded|partially_succeeded|failed|blocked…)
|
|
- `run_identity_hash` (string; deterministic hash for idempotency)
|
|
- `summary_counts` (json/array; normalized counts + key metadata)
|
|
- `failure_summary` (json/array; structured failures, sanitized)
|
|
- `context` (json/array; provenance + inputs + target scope)
|
|
- `started_at`, `completed_at`, `created_at`, `updated_at`
|
|
|
|
**Indexes / constraints (current):**
|
|
- `(workspace_id, type, created_at)` and `(workspace_id, created_at)`
|
|
- `(tenant_id, type, created_at)` and `(tenant_id, created_at)`
|
|
- Partial unique indexes for active runs:
|
|
- tenant-scoped: unique `(tenant_id, run_identity_hash)` where `tenant_id IS NOT NULL` and `status IN ('queued','running')`
|
|
- workspace-scoped: unique `(workspace_id, run_identity_hash)` where `tenant_id IS NULL` and `status IN ('queued','running')`
|
|
|
|
**Context contract (current patterns):**
|
|
The `context` JSON is used for “related links” and display. Existing keys include (non-exhaustive):
|
|
- `provider_connection_id`
|
|
- `backup_schedule_id`
|
|
- `backup_schedule_run_id`
|
|
- `backup_set_id`
|
|
- `policy_id`
|
|
- `restore_run_id`
|
|
- `target_scope` (nested object)
|
|
- `selection` and `idempotency` objects for bulk operations
|
|
|
|
**Required additions for Spec 086 (planned):**
|
|
- New `type` values:
|
|
- `backup_schedule.scheduled`
|
|
- `directory_role_definitions.sync`
|
|
- Scheduled backup context keys:
|
|
- `backup_schedule_id`
|
|
- `scheduled_for` (UTC timestamp/minute)
|
|
- Optional `backup_schedule_run_id` if the legacy table remains for history during transition
|
|
|
|
### 2) InventorySyncRun (legacy)
|
|
|
|
**Table:** `inventory_sync_runs`
|
|
|
|
**Purpose:** Historical record (read-only) for pre-cutover tracking.
|
|
|
|
**Key fields:**
|
|
- `tenant_id`
|
|
- `selection_hash`
|
|
- `selection_payload` (nullable)
|
|
- status + timestamps + counters
|
|
|
|
**Planned optional mapping:**
|
|
- Add nullable `operation_run_id` FK to enable deterministic redirect to canonical viewer when present. No backfill required.
|
|
|
|
### 3) EntraGroupSyncRun (legacy)
|
|
|
|
**Table:** `entra_group_sync_runs`
|
|
|
|
**Purpose:** Historical record (read-only) for pre-cutover group sync tracking.
|
|
|
|
**Key fields:**
|
|
- `tenant_id`
|
|
- `selection_key`, `slot_key`
|
|
- status + error fields + counters
|
|
|
|
**Planned optional mapping:**
|
|
- Add nullable `operation_run_id` FK to enable deterministic redirect when present.
|
|
|
|
### 4) BackupScheduleRun (legacy)
|
|
|
|
**Table:** `backup_schedule_runs`
|
|
|
|
**Purpose:** Historical record of backup schedule executions.
|
|
|
|
**Planned behavior change:**
|
|
- Distinguish scheduled fires vs manual/retry at the OperationRun level by introducing `backup_schedule.scheduled` type.
|
|
|
|
**Planned optional mapping:**
|
|
- Add nullable `operation_run_id` FK to enable deterministic redirect when present.
|
|
|
|
### 5) RestoreRun (domain)
|
|
|
|
**Table:** `restore_runs`
|
|
|
|
**Purpose:** Domain workflow record (requested items, dry-run, preview/results). Execution tracking and “View run” uses `operation_runs`.
|
|
|
|
**Current linkage approach:**
|
|
- Canonical runs store `restore_run_id` in `operation_runs.context` (used by `OperationRunLinks::related`).
|
|
|
|
## Enumerations / Registries
|
|
|
|
### OperationRunType
|
|
|
|
**Location:** `app/Support/OperationRunType.php`
|
|
|
|
**Planned additions:**
|
|
- `BackupScheduleScheduled = 'backup_schedule.scheduled'`
|
|
- `DirectoryRoleDefinitionsSync = 'directory_role_definitions.sync'`
|
|
|
|
### OperationCatalog
|
|
|
|
**Location:** `app/Support/OperationCatalog.php`
|
|
|
|
**Planned additions:**
|
|
- Human label for `backup_schedule.scheduled`
|
|
- Human label for `directory_role_definitions.sync`
|
|
- Optional expected durations (if known)
|
|
|
|
## State transitions
|
|
|
|
### OperationRun
|
|
|
|
- `queued` → `running` → `completed`
|
|
- `outcome` starts as `pending`, transitions to one of: `succeeded`, `partially_succeeded`, `failed`, `blocked`.
|
|
|
|
The canonical update surface is `OperationRunService` (`dispatchOrFail`, `updateRun`, `appendFailures`, `incrementSummaryCounts`, etc.).
|