///|
fn audit_tree(
value : Value,
path : String,
origins : Value,
masked : Array[String],
entries : Array[Value],
) -> Unit raise {
let secret = masked.contains(path)
let history = get(origins, path)
entries.push(
record([
("path", String(path)),
("type", String(if secret { "redacted" } else { kind(value) })),
("masked", Bool(secret)),
("layers", if history == Null { Array([]) } else { history }),
]),
)
if secret {
return
}
match value {
Object(fields) => {
let keys = fields.keys().collect()
sort_lexical(keys)
for key in keys {
audit_tree(
fields[key],
path + "/" + escape_key(key),
origins,
masked,
entries,
)
}
}
Array(items) =>
for i = 0; i < items.length(); i = i + 1 {
audit_tree(
items[i],
path + "/" + i.to_string(),
origins,
masked,
entries,
)
}
_ => ()
}
}
///|
fn audit_report(request : Value) -> Value raise {
let report = merge_report(request)
let entries : Array[Value] = []
let masked = string_list(get(report, "masked"))
audit_tree(
get(report, "redacted"),
"",
get(report, "origins"),
masked,
entries,
)
record([
("paths", Array(entries)),
("path_count", Number(entries.length().to_double())),
("masked", strings(masked)),
("issues", get(report, "issues")),
("valid", get(report, "valid")),
("values_included", Bool(false)),
])
}