TenantAtlas/specs/086-retire-legacy-runs-into-operation-runs/data-model.md
ahmido 2bf5de4663 085-tenant-operate-hub (#103)
Summary

Consolidates the “Tenant Operate Hub” work (Spec 085) and the follow-up adjustments from the 086 session merge into a single branch ready to merge into dev.
Primary focus: stabilize Ops/Operate Hub UX flows, tighten/align authorization semantics, and make the full Sail test suite green.
Key Changes

Ops UX / Verification
Readonly members can view verification operation runs (reports) while starting verification remains restricted.
Normalized failure reason-code handling and aligned UX expectations with the provider reason-code taxonomy.
Onboarding wizard UX
“Start verification” CTA is hidden while a verification run is active; “Refresh” is shown during in-progress runs.
Treats provider_permission_denied as a blocking reason (while keeping legacy compatibility).
Test + fixture hardening
Standardized use of default provider connection fixtures in tests where sync/restore flows require it.
Fixed multiple Filament URL/tenant-context test cases to avoid 404s and reduce tenancy routing brittleness.
Policy sync / restore safety
Enrollment configuration type collision classification tests now exercise the real sync path (with required provider connection present).
Restore edge-case safety tests updated to reflect current provider-connection requirements.
Testing

vendor/bin/sail artisan test --compact (green)
vendor/bin/sail bin pint --dirty (green)
Notes

Includes merged 086 session work already (no separate PR needed).

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@ebc83aaa-d947-4a08-b88e-bd72ac9645f7.fritz.box>
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.fritz.box>
Reviewed-on: #103
2026-02-11 13:02:03 +00:00

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.).