*/ private array $known = []; public function remember(string $secret): void { if (strlen($secret) >= 8) { $this->known[$secret] = true; } } public function redact(string $text): string { foreach (array_keys($this->known) as $secret) { $text = str_replace((string) $secret, self::MASK, $text); } $patterns = [ '/\b(Bearer|Basic)\s+[A-Za-z0-9._~+\/=-]{8,}/i' => '$1 ' . self::MASK, '/\b(sk|pk|rk|xai|gsk|key)-[A-Za-z0-9_-]{12,}/' => self::MASK, '/\bAIza[0-9A-Za-z_-]{20,}/' => self::MASK, '/((?:api[_-]?key|token|secret|password|authorization)["\']?\s*[:=]\s*["\']?)[^\s"\'&,}]{6,}/i' => '$1' . self::MASK, '/\baw1\.\d+\.[A-Za-z0-9+\/=]{20,}/' => self::MASK, ]; return (string) preg_replace(array_keys($patterns), array_values($patterns), $text); } /** Redacts and bounds length, for storage in short diagnostic columns. */ public function summary(string $text, int $max = 500): string { $text = $this->redact($text); return mb_strlen($text) > $max ? mb_substr($text, 0, $max - 1) . '…' : $text; } }