<?php
 namespace App\Traits; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; trait SealsAdminAttributes { protected static bool $sealingSuspended = false; protected static bool $resolvingAuth = false; public function fill(array $attributes) { if (! static::$sealingSuspended && ! empty(static::$sealedAdminAttributes) && ! $this->isTrustedSealingContext() ) { $hits = array_values(array_intersect( array_keys($attributes), static::$sealedAdminAttributes )); if (! empty($hits)) { Log::warning('SealsAdminAttributes: admin-only keys filled from non-admin context', [ 'model' => static::class, 'sealed_keys' => $hits, 'route' => optional(request()->route())->getName(), 'url' => request()->fullUrl(), 'caller' => $this->resolveCallerSnippet(), 'guard' => $this->resolveActiveGuardName(), ]); } } return parent::fill($attributes); } public static function unsealed(callable $callback) { $previous = static::$sealingSuspended; static::$sealingSuspended = true; try { return $callback(); } finally { static::$sealingSuspended = $previous; } } protected function isTrustedSealingContext(): bool { if (app()->runningInConsole()) { return true; } if (static::$resolvingAuth) { return true; } try { static::$resolvingAuth = true; if (Auth::guard('admin')->check()) { return true; } } catch (\Throwable $e) { } finally { static::$resolvingAuth = false; } return false; } protected function resolveActiveGuardName(): string { if (static::$resolvingAuth) { return 'unknown'; } try { static::$resolvingAuth = true; foreach (['admin', 'client', 'web'] as $name) { if (Auth::guard($name)->check()) { return $name; } } } catch (\Throwable $e) { } finally { static::$resolvingAuth = false; } return 'guest'; } protected function resolveCallerSnippet(): array { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 12); $snippet = []; foreach (array_slice($trace, 2) as $frame) { $file = $frame['file'] ?? '?'; $line = $frame['line'] ?? 0; if (str_contains($file, '/vendor/')) { continue; } $snippet[] = basename($file) . ':' . $line; if (count($snippet) >= 4) { break; } } return $snippet; } } 