getThreatScore()->getValue(); if ($threatScore > $maxRiskScore) { $maxRiskScore = $threatScore; } } return new self( layerName: $layerName, threatScore: Percentage::from($maxRiskScore), status: $status, detections: DetectionCollection::fromArray($detections), reason: $reason, executionDuration: $executionDuration, metadata: $metadata ?? ResultMetadata::empty() ); } /** * Create a result indicating the request is clean */ public static function clean(string $layerName, string $reason = '', ?Duration $executionDuration = null, ?ResultMetadata $metadata = null): self { return new self( layerName: $layerName, threatScore: Percentage::from(0.0), status: LayerStatus::CLEAN, detections: DetectionCollection::empty(), reason: $reason, executionDuration: $executionDuration, metadata: $metadata ?? ResultMetadata::empty() ); } /** * Create a neutral result (layer couldn't determine threat level) */ public static function neutral(string $layerName, string $reason = '', ?ResultMetadata $metadata = null): self { return new self( layerName: $layerName, threatScore: Percentage::from(50.0), // Neutral score status: LayerStatus::NEUTRAL, detections: DetectionCollection::empty(), reason: $reason, metadata: $metadata ?? ResultMetadata::empty() ); } /** * Create a result indicating suspicious activity (lower confidence threat) */ public static function suspicious(string $layerName, string $reason, array $detections = [], ?ResultMetadata $metadata = null): self { return new self( layerName: $layerName, threatScore: Percentage::from(60.0), // Moderate threat score status: LayerStatus::SUSPICIOUS, detections: DetectionCollection::fromArray($detections), reason: $reason, metadata: $metadata ?? ResultMetadata::empty() ); } /** * Create a result indicating layer error/failure */ public static function error(string $layerName, string $reason, ?Duration $executionDuration = null, ?ResultMetadata $metadata = null): self { return new self( layerName: $layerName, threatScore: Percentage::from(0.0), // Don't penalize on error status: LayerStatus::ERROR, detections: DetectionCollection::empty(), reason: $reason, executionDuration: $executionDuration, metadata: $metadata ?? ResultMetadata::empty() ); } /** * Check if this result indicates a threat */ public function isThreat(): bool { return $this->status === LayerStatus::THREAT_DETECTED; } /** * Check if this result is clean */ public function isClean(): bool { return $this->status === LayerStatus::CLEAN; } /** * Check if layer had an error */ public function hasError(): bool { return $this->status === LayerStatus::ERROR; } /** * Get recommended action based on layer result */ public function getAction(): string { return match ($this->status) { LayerStatus::THREAT_DETECTED => self::ACTION_BLOCK, LayerStatus::CLEAN => self::ACTION_PASS, LayerStatus::NEUTRAL => self::ACTION_SUSPICIOUS, LayerStatus::ERROR => self::ACTION_PASS, // Fail open LayerStatus::SKIPPED => self::ACTION_PASS, // Continue processing LayerStatus::TIMEOUT => self::ACTION_PASS, // Fail open on timeout }; } /** * Get the reason/message for this result */ public function getMessage(): string { return $this->reason; } /** * Get the layer name */ public function getLayerName(): string { return $this->layerName; } /** * Check if result has detections */ public function hasDetections(): bool { return ! $this->detections->isEmpty(); } /** * Get the detections collection */ public function getDetections(): DetectionCollection { return $this->detections; } /** * Create new result with execution duration */ public function withExecutionDuration(Duration $duration): self { return new self( layerName: $this->layerName, threatScore: $this->threatScore, status: $this->status, detections: $this->detections, reason: $this->reason, executionDuration: $duration, timestamp: $this->timestamp, metadata: $this->metadata ); } /** * Create new result with timestamp */ public function withTimestamp(Timestamp $timestamp): self { return new self( layerName: $this->layerName, threatScore: $this->threatScore, status: $this->status, detections: $this->detections, reason: $this->reason, executionDuration: $this->executionDuration, timestamp: $timestamp, metadata: $this->metadata ); } /** * Add metadata to result */ public function withMetadata(ResultMetadata $additionalMetadata): self { $combinedMetadata = $this->metadata?->merge($additionalMetadata) ?? $additionalMetadata; return new self( layerName: $this->layerName, threatScore: $this->threatScore, status: $this->status, detections: $this->detections, reason: $this->reason, executionDuration: $this->executionDuration, timestamp: $this->timestamp, metadata: $combinedMetadata ); } }