where('status', OperationRunStatus::Completed->value) ->where('outcome', OperationRunOutcome::Failed->value) ->count(); return $count > 0 ? (string) $count : null; } public static function getNavigationBadgeColor(): string|array|null { return 'danger'; } public static function canAccess(): bool { $user = auth('platform')->user(); if (! $user instanceof PlatformUser) { return false; } return $user->hasCapability(PlatformCapabilities::OPERATIONS_VIEW) || ($user->hasCapability(PlatformCapabilities::OPS_VIEW) && $user->hasCapability(PlatformCapabilities::RUNBOOKS_VIEW)); } public function mount(): void { $this->mountInteractsWithTable(); } public function table(Table $table): Table { return $table ->defaultSort('id', 'desc') ->query(function (): Builder { return OperationRun::query() ->with(['tenant', 'workspace']) ->where('status', OperationRunStatus::Completed->value) ->where('outcome', OperationRunOutcome::Failed->value); }) ->columns([ TextColumn::make('id') ->label('Run') ->state(fn (OperationRun $record): string => '#'.$record->getKey()), TextColumn::make('status') ->badge() ->formatStateUsing(BadgeRenderer::label(BadgeDomain::OperationRunStatus)) ->color(BadgeRenderer::color(BadgeDomain::OperationRunStatus)) ->icon(BadgeRenderer::icon(BadgeDomain::OperationRunStatus)) ->iconColor(BadgeRenderer::iconColor(BadgeDomain::OperationRunStatus)), TextColumn::make('outcome') ->badge() ->formatStateUsing(BadgeRenderer::label(BadgeDomain::OperationRunOutcome)) ->color(BadgeRenderer::color(BadgeDomain::OperationRunOutcome)) ->icon(BadgeRenderer::icon(BadgeDomain::OperationRunOutcome)) ->iconColor(BadgeRenderer::iconColor(BadgeDomain::OperationRunOutcome)), TextColumn::make('type') ->label('Operation') ->formatStateUsing(fn (?string $state): string => OperationCatalog::label((string) $state)) ->searchable(), TextColumn::make('workspace.name') ->label('Workspace') ->toggleable(), TextColumn::make('tenant.name') ->label('Tenant') ->formatStateUsing(fn (?string $state): string => $state ?: 'Tenantless') ->toggleable(), TextColumn::make('created_at')->label('Started')->since(), ]) ->recordUrl(fn (OperationRun $record): string => SystemOperationRunLinks::view($record)) ->actions([ Action::make('retry') ->label('Retry') ->requiresConfirmation() ->visible(fn (OperationRun $record): bool => $this->canManageOperations() && app(OperationRunTriageService::class)->canRetry($record)) ->action(function (OperationRun $record, OperationRunTriageService $triageService): void { $user = $this->requireManageUser(); $retryRun = $triageService->retry($record, $user); OperationUxPresenter::queuedToast((string) $retryRun->type) ->actions([ \Filament\Actions\Action::make('view_run') ->label('View run') ->url(SystemOperationRunLinks::view($retryRun)), ]) ->send(); }), Action::make('cancel') ->label('Cancel') ->color('danger') ->requiresConfirmation() ->visible(fn (OperationRun $record): bool => $this->canManageOperations() && app(OperationRunTriageService::class)->canCancel($record)) ->action(function (OperationRun $record, OperationRunTriageService $triageService): void { $user = $this->requireManageUser(); $triageService->cancel($record, $user); Notification::make() ->title('Run cancelled') ->success() ->send(); }), Action::make('mark_investigated') ->label('Mark investigated') ->requiresConfirmation() ->visible(fn (): bool => $this->canManageOperations()) ->form([ Textarea::make('reason') ->label('Reason') ->required() ->minLength(5) ->maxLength(500) ->rows(4), ]) ->action(function (OperationRun $record, array $data, OperationRunTriageService $triageService): void { $user = $this->requireManageUser(); $triageService->markInvestigated($record, $user, (string) ($data['reason'] ?? '')); Notification::make() ->title('Run marked as investigated') ->success() ->send(); }), ]) ->emptyStateHeading('No failed runs found') ->emptyStateDescription('Failed operations will appear here for triage.') ->bulkActions([]); } private function canManageOperations(): bool { $user = auth('platform')->user(); return $user instanceof PlatformUser && $user->hasCapability(PlatformCapabilities::OPERATIONS_MANAGE); } private function requireManageUser(): PlatformUser { $user = auth('platform')->user(); if (! $user instanceof PlatformUser || ! $user->hasCapability(PlatformCapabilities::OPERATIONS_MANAGE)) { abort(403); } return $user; } }