can('update', $destination)) { throw new AuthorizationException('You do not have permission to send test messages for this destination.'); } if (! $destination->is_enabled) { return [ 'success' => false, 'message' => 'This destination is currently disabled. Enable it before sending a test message.', 'delivery_id' => null, ]; } if ($this->isRateLimited($destination)) { return [ 'success' => false, 'message' => 'A test message was sent recently. Please wait before trying again.', 'delivery_id' => null, ]; } $delivery = $this->createTestDelivery($destination); $this->auditLog($destination, $actor); DeliverAlertsJob::dispatch((int) $destination->workspace_id); return [ 'success' => true, 'message' => 'Test message queued for delivery.', 'delivery_id' => (int) $delivery->getKey(), ]; } private function isRateLimited(AlertDestination $destination): bool { return AlertDelivery::query() ->where('workspace_id', (int) $destination->workspace_id) ->where('alert_destination_id', (int) $destination->getKey()) ->where('event_type', AlertDelivery::EVENT_TYPE_TEST) ->where('created_at', '>=', now()->subSeconds(self::RATE_LIMIT_SECONDS)) ->exists(); } private function createTestDelivery(AlertDestination $destination): AlertDelivery { return AlertDelivery::create([ 'workspace_id' => (int) $destination->workspace_id, 'tenant_id' => null, 'alert_rule_id' => null, 'alert_destination_id' => (int) $destination->getKey(), 'event_type' => AlertDelivery::EVENT_TYPE_TEST, 'status' => AlertDelivery::STATUS_QUEUED, 'severity' => null, 'fingerprint_hash' => 'test:'.(int) $destination->getKey(), 'attempt_count' => 0, 'payload' => [ 'title' => 'Test alert', 'body' => 'This is a test delivery for destination verification.', ], ]); } private function auditLog(AlertDestination $destination, User $actor): void { $workspace = $destination->workspace; if ($workspace === null) { return; } $this->auditLogger->log( workspace: $workspace, action: AuditActionId::AlertDestinationTestRequested->value, context: [ 'metadata' => [ 'alert_destination_id' => (int) $destination->getKey(), 'name' => (string) $destination->name, 'type' => (string) $destination->type, ], ], actor: $actor, resourceType: 'alert_destination', resourceId: (string) $destination->getKey(), ); } }