'array', 'was_trained' => 'boolean', 'trained_at' => 'datetime', ]; // Relationships public function entity(): BelongsTo { return $this->belongsTo(Entity::class, 'entity_id'); } public function user(): BelongsTo { return $this->belongsTo(User::class); } // Status helpers public function isAllowed(): bool { return $this->status === self::STATUS_ALLOWED; } public function isDenied(): bool { return $this->status === self::STATUS_DENIED; } public function isPending(): bool { return $this->status === self::STATUS_PENDING; } public function wasTrained(): bool { return $this->was_trained; } // Factory methods /** * Create a request log entry from an HTTP request. */ public static function fromRequest( Entity $entity, string $action, string $status, ?string $scope = null ): self { $request = request(); return static::create([ 'entity_id' => $entity->id, 'method' => $request->method(), 'route' => $request->path(), 'action' => $action, 'scope' => $scope, 'request_data' => self::sanitiseRequestData($request->all()), 'user_agent' => $request->userAgent(), 'ip_address' => $request->ip(), 'user_id' => auth()->id(), 'status' => $status, ]); } /** * Sanitise request data for storage (remove sensitive fields). */ protected static function sanitiseRequestData(array $data): array { $sensitiveKeys = [ 'password', 'password_confirmation', 'token', 'api_key', 'secret', 'credit_card', 'card_number', 'cvv', 'ssn', ]; foreach ($sensitiveKeys as $key) { unset($data[$key]); } // Limit size $json = json_encode($data); if (strlen($json) > 10000) { return ['_truncated' => true, '_size' => strlen($json)]; } return $data; } // Scopes public function scopeForEntity($query, int $entityId) { return $query->where('entity_id', $entityId); } public function scopeForAction($query, string $action) { return $query->where('action', $action); } public function scopePending($query) { return $query->where('status', self::STATUS_PENDING); } public function scopeUntrained($query) { return $query->where('was_trained', false); } public function scopeRecent($query, int $days = 7) { return $query->where('created_at', '>=', now()->subDays($days)); } }