///|
fn empty_summary(lines : Int) -> BatchSummary {
{
lines,
changed_lines: 0,
findings: 0,
access_tokens: 0,
bearer_tokens: 0,
jwts: 0,
credentials: 0,
emails: 0,
ipv4s: 0,
payment_cards: 0,
private_keys: 0,
url_credentials: 0,
custom_secrets: 0,
resident_ids: 0,
mac_addresses: 0,
uuids: 0,
ipv6s: 0,
phones: 0,
public_keys: 0,
wallet_addresses: 0,
webhook_urls: 0,
}
}
///|
/// Fold one line's findings into the aggregate summary.
fn tally(summary : BatchSummary, findings : Array[Finding]) -> Unit {
for finding in findings {
match finding.kind {
AccessToken => summary.access_tokens += 1
BearerToken => summary.bearer_tokens += 1
Jwt => summary.jwts += 1
CredentialAssignment => summary.credentials += 1
Email => summary.emails += 1
Ipv4 => summary.ipv4s += 1
PaymentCard => summary.payment_cards += 1
PrivateKey => summary.private_keys += 1
UrlCredential => summary.url_credentials += 1
CustomSecret => summary.custom_secrets += 1
ResidentId => summary.resident_ids += 1
MacAddress => summary.mac_addresses += 1
Uuid => summary.uuids += 1
Ipv6 => summary.ipv6s += 1
Phone => summary.phones += 1
PublicKey => summary.public_keys += 1
WalletAddress => summary.wallet_addresses += 1
WebhookUrl => summary.webhook_urls += 1
}
}
}
///|
/// Redact one line and fold its findings into the outputs and summary.
fn run_line(
line : String,
index : Int,
config : ScanConfig,
style~ : RedactionStyle,
output : Array[String],
changed_indices : Array[Int],
summary : BatchSummary,
) -> Unit {
let result = redact_with_config(line, config, style~)
output.push(result.text)
if result.changed {
changed_indices.push(index)
summary.changed_lines += 1
}
summary.findings += result.findings.length()
tally(summary, result.findings)
}
///|
/// Batch redaction under a full configuration, enabling post-0.1.0
/// families such as resident ids and MAC addresses in log pipelines.
pub fn redact_batch_with_config(
lines : Array[String],
config : ScanConfig,
style? : RedactionStyle = Typed,
) -> BatchResult {
let output : Array[String] = []
let changed_indices : Array[Int] = []
let summary = empty_summary(lines.length())
for index, line in lines {
run_line(line, index, config, style~, output, changed_indices, summary)
}
{ lines: output, summary, changed_indices, }
}
///|
/// Redact independent log/API/prompt lines and return aggregate counts. The
/// summary contains categories and counts only, never matched values.
pub fn redact_batch(
lines : Array[String],
style? : RedactionStyle = Typed,
policy? : ScanPolicy = ScanPolicy::standard(),
) -> BatchResult {
let output : Array[String] = []
let changed_indices : Array[Int] = []
let summary = empty_summary(lines.length())
let config = policy.to_config()
for index, line in lines {
run_line(line, index, config, style~, output, changed_indices, summary)
}
{ lines: output, summary, changed_indices, }
}