'array', 'failure_summary' => 'array', 'context' => 'array', 'started_at' => 'datetime', 'completed_at' => 'datetime', ]; protected static function booted(): void { static::creating(function (self $operationRun): void { if ($operationRun->workspace_id !== null) { return; } if ($operationRun->tenant_id === null) { return; } $tenant = Tenant::query()->whereKey((int) $operationRun->tenant_id)->first(); if (! $tenant instanceof Tenant) { return; } if ($tenant->workspace_id === null) { return; } $operationRun->workspace_id = (int) $tenant->workspace_id; }); } public function tenant(): BelongsTo { return $this->belongsTo(Tenant::class)->withTrashed(); } public function workspace(): BelongsTo { return $this->belongsTo(Workspace::class); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function scopeActive(Builder $query): Builder { return $query->whereIn('status', ['queued', 'running']); } public function getSelectionHashAttribute(): ?string { $context = is_array($this->context) ? $this->context : []; return isset($context['selection_hash']) && is_string($context['selection_hash']) ? $context['selection_hash'] : null; } public function setSelectionHashAttribute(?string $value): void { $context = is_array($this->context) ? $this->context : []; $context['selection_hash'] = $value; $this->context = $context; } /** * @return array */ public function getSelectionPayloadAttribute(): array { $context = is_array($this->context) ? $this->context : []; return Arr::only($context, [ 'policy_types', 'categories', 'include_foundations', 'include_dependencies', ]); } /** * @param array|null $value */ public function setSelectionPayloadAttribute(?array $value): void { $context = is_array($this->context) ? $this->context : []; if (is_array($value)) { $context = array_merge($context, Arr::only($value, [ 'policy_types', 'categories', 'include_foundations', 'include_dependencies', ])); } $this->context = $context; } public function getFinishedAtAttribute(): mixed { return $this->completed_at; } public function setFinishedAtAttribute(mixed $value): void { $this->completed_at = $value; } public function isGovernanceArtifactOperation(): bool { return OperationCatalog::isGovernanceArtifactOperation((string) $this->type); } public function governanceArtifactFamily(): ?string { return OperationCatalog::governanceArtifactFamily((string) $this->type); } /** * @return array */ public function artifactResultContext(): array { $context = is_array($this->context) ? $this->context : []; $result = is_array($context['result'] ?? null) ? $context['result'] : []; return array_merge($context, ['result' => $result]); } public function relatedArtifactId(): ?int { return match ($this->governanceArtifactFamily()) { 'baseline_snapshot' => is_numeric(data_get($this->context, 'result.snapshot_id')) ? (int) data_get($this->context, 'result.snapshot_id') : null, default => null, }; } }