using System.Collections.Concurrent; using System.Text.RegularExpressions; namespace Nexus.Api.Services; public static class AgentActivityText { private static readonly (Regex Pattern, string Replacement)[] InlineRedactions = [ (new Regex(@"(?i)(authorization\s*:\s*bearer)\s+\S+", RegexOptions.CultureInvariant), "$1 [redacted]"), (new Regex(@"(?i)(x-nexus-api-key\s*:\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(api[_-]?key\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(token\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(password\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(secret\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(jwt\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"), (new Regex(@"(?i)(private[_-]?key\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]") ]; private static readonly Regex[] ResidualSensitivePatterns = [ new(@"(?i)bearer\s+(?!\[redacted\])\S+", RegexOptions.CultureInvariant), new(@"(?i)x-nexus-api-key\s*:\s*(?!\[redacted\])\S+", RegexOptions.CultureInvariant), new(@"(?i)private[_-]?key\s*[:=]\s*(?!\[redacted\])\S+", RegexOptions.CultureInvariant) ]; private static readonly string[] KnownActorIds = [ .. AgentIdentityCatalog.DefaultConfiguredAgentIds, "bao", "nexus-system" ]; public static string RedactForDisplay(string? content) { if (string.IsNullOrWhiteSpace(content)) return content ?? string.Empty; var lines = content.Split('\n'); for (var i = 0; i < lines.Length; i++) { var sanitized = lines[i]; foreach (var (pattern, replacement) in InlineRedactions) { sanitized = pattern.Replace(sanitized, replacement); } if (ResidualSensitivePatterns.Any(pattern => pattern.IsMatch(sanitized))) sanitized = "[redacted sensitive line]"; lines[i] = sanitized; } return string.Join('\n', lines).Trim(); } public static bool MatchesAgent(string? content, string agentId) { if (string.IsNullOrWhiteSpace(agentId)) return false; var normalized = agentId.Trim().ToLowerInvariant(); return ExtractAgentIds(content).Contains(normalized, StringComparer.OrdinalIgnoreCase); } public static string[] ExtractAgentIds(string? content) { if (string.IsNullOrWhiteSpace(content)) return []; var matches = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var actorId in KnownActorIds) { if (BuildActorRegex(actorId).IsMatch(content)) matches.Add(actorId); } return matches .Select(actorId => actorId.ToLowerInvariant()) .OrderBy(actorId => actorId, StringComparer.Ordinal) .ToArray(); } private static Regex BuildActorRegex(string actorId) => ActorPatternCache.GetOrAdd(actorId, static key => new Regex($@"(? ActorPatternCache = new(StringComparer.OrdinalIgnoreCase); }