- JarvisLogChannel: four cases (agent, tools, ui, system)
- JarvisLogHandlerFactory.bootstrap wires MultiplexLogHandler that
fans out to FileLogHandler + OSLogHandler (D-17)
- FileLogHandler applies Redact.apply once (S-4 single call site)
- OSLogHandler does NOT redact (os.Logger handles %{private}@ at
system layer; callers redact untrusted input before logging)
- Redact covers exactly 5 patterns: sk-ant-, Authorization:Bearer,
sk- (OpenAI), AKIA, ghp_ (D-20, OBS-06); Anthropic branch ordered
before OpenAI so sk-ant- consumes the full prefix
- FileRotatingWriter: lazy midnight rotation via TestDateProvider-
injectable DateProvider; serial DispatchQueue; retain-7 GC on
rotate (D-18)
- LogPaths.channelDirectory = ~/Library/Logs/Jarvis/
- Swift 6 strict: ISO8601DateFormatter.jarvisShared uses
nonisolated(unsafe) since the formatter is documented thread-safe
after configuration but not Sendable-annotated by Apple
- OSLogHandler uses fully-qualified Logging.Logger to disambiguate
from os.Logger (both imported)
- Tests: 13/13 pass (7 Redact + 2 FileLogHandler rotate/retain +
4 bootstrap/factory/channels)
- Deletes Plan 01 placeholders
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
25 lines
957 B
Swift
25 lines
957 B
Swift
import Foundation
|
|
|
|
public enum Redact {
|
|
/// Compiled once. Alternation branches ordered by specificity so sk-ant- matches
|
|
/// branch 1 before sk- (OpenAI) branch 3.
|
|
/// 1. Anthropic sk-ant-<20+ tokens>
|
|
/// 2. Authorization: Bearer <token> (case-insensitive)
|
|
/// 3. OpenAI sk-<20+ tokens>
|
|
/// 4. AKIA<16 uppercase alphanumerics>
|
|
/// 5. ghp_<36 alphanumerics>
|
|
private static let pattern: NSRegularExpression = {
|
|
let raw = #"(sk-ant-[A-Za-z0-9_\-]{20,})|((?i:Authorization:\s*Bearer)\s+[A-Za-z0-9_\-\.=]+)|(\bsk-[A-Za-z0-9_\-]{20,})|(AKIA[0-9A-Z]{16})|(ghp_[A-Za-z0-9]{36})"#
|
|
return try! NSRegularExpression(pattern: raw)
|
|
}()
|
|
|
|
public static func apply(_ s: String) -> String {
|
|
let ns = s as NSString
|
|
return pattern.stringByReplacingMatches(
|
|
in: s,
|
|
range: NSRange(location: 0, length: ns.length),
|
|
withTemplate: "<redacted>"
|
|
)
|
|
}
|
|
}
|