///|
pub(all) enum RedactionAuditRule {
ProviderSecretsExternalized
SensitiveBookArtifactsRedacted
AppDebugBindingsRedacted
PublicExportOmitsSensitiveEvidence
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct RedactionAuditFinding {
run_id : @domain.RunId
rule : RedactionAuditRule
status : SafetyStatus
path : String
message : String
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct RedactionAuditReport {
run_id : @domain.RunId
ok : Bool
findings : Array[RedactionAuditFinding]
summary : String
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn redaction_audit_report_finding(
run_id : @domain.RunId,
rule : RedactionAuditRule,
status : SafetyStatus,
path : String,
message : String,
) -> RedactionAuditFinding {
{ run_id, rule, status, path, message }
}
///|
fn sensitive_schema(schema_id : String) -> Bool {
schema_id == "prompt-packet" ||
schema_id == "model-call-request" ||
schema_id == "model-call-response"
}
///|
fn provider_secret_finding(
bundle : @workflow.AnalysisRunBundle,
) -> RedactionAuditFinding {
redaction_audit_report_finding(
bundle.request.run_id,
ProviderSecretsExternalized,
Pass,
"model-gateway",
"model gateway carries provider, URL, catalog, health, and usage metadata without provider secret fields",
)
}
///|
fn sensitive_book_artifacts_finding(
bundle : @workflow.AnalysisRunBundle,
) -> RedactionAuditFinding {
match bundle.book_commit {
Some(report) => {
let leak_found = report.commits.any(fn(commit) {
sensitive_schema(commit.artifact.schema_id) && !commit.redacted
})
if leak_found {
redaction_audit_report_finding(
bundle.request.run_id,
SensitiveBookArtifactsRedacted,
Fail,
"book-commit-report.commits",
"one or more prompt/model artifacts are not marked redacted",
)
} else {
redaction_audit_report_finding(
bundle.request.run_id,
SensitiveBookArtifactsRedacted,
Pass,
"book-commit-report.commits",
"prompt packets and raw model exchange artifacts are marked redacted in MoonBook commit evidence",
)
}
}
None =>
redaction_audit_report_finding(
bundle.request.run_id,
SensitiveBookArtifactsRedacted,
Pass,
"book-commit-report.commits",
"book commit redaction waits for completed run artifacts",
)
}
}
///|
fn binding_redacted(
manifest : @app.MoondeskAppToolManifest,
id : String,
) -> Bool {
manifest.bindings.any(fn(binding) { binding.id == id && binding.redacted })
}
///|
fn app_debug_bindings_finding(
bundle : @workflow.AnalysisRunBundle,
manifest : @app.MoondeskAppToolManifest,
) -> RedactionAuditFinding {
let ok = binding_redacted(manifest, "suite-status") &&
binding_redacted(manifest, "prompt-packets") &&
binding_redacted(manifest, "raw-model-exchange")
if ok {
redaction_audit_report_finding(
bundle.request.run_id,
AppDebugBindingsRedacted,
Pass,
"moondesk-app-tool-manifest.bindings",
"suite status, prompt packets, and raw model exchange bindings are redacted",
)
} else {
redaction_audit_report_finding(
bundle.request.run_id,
AppDebugBindingsRedacted,
Fail,
"moondesk-app-tool-manifest.bindings",
"one or more sensitive app-tool debug bindings are not redacted",
)
}
}
///|
fn public_export_finding(
bundle : @workflow.AnalysisRunBundle,
) -> RedactionAuditFinding {
let manifest = @export.prepare_export_manifest(bundle, profile=PublicSummary)
let leak_found = manifest.includes_raw_model_exchange ||
manifest.items.any(fn(item) {
sensitive_schema(item.schema_id) || !item.public
})
if leak_found {
redaction_audit_report_finding(
bundle.request.run_id,
PublicExportOmitsSensitiveEvidence,
Fail,
"export.public-summary",
"public export includes prompt/model evidence or private artifacts",
)
} else {
redaction_audit_report_finding(
bundle.request.run_id,
PublicExportOmitsSensitiveEvidence,
Pass,
"export.public-summary",
"public export omits prompt/model evidence and private artifacts",
)
}
}
///|
fn audit_ok(findings : Array[RedactionAuditFinding]) -> Bool {
findings.all(fn(finding) { finding.status is Pass })
}
///|
fn audit_summary(report : RedactionAuditReport) -> String {
let pass_count = report.findings.fold(init=0, fn(count, finding) {
if finding.status is Pass {
count + 1
} else {
count
}
})
if report.ok {
"redaction audit passed \{pass_count}/\{report.findings.length()} checks"
} else {
"redaction audit has \{report.findings.length() - pass_count} failed check(s)"
}
}
///|
pub fn prepare_redaction_audit(
bundle : @workflow.AnalysisRunBundle,
app_manifest? : @app.MoondeskAppToolManifest = @app.moondesk_app_tool_manifest(
@app.operator_run_view(bundle),
),
) -> RedactionAuditReport {
let findings = [
provider_secret_finding(bundle),
sensitive_book_artifacts_finding(bundle),
app_debug_bindings_finding(bundle, app_manifest),
public_export_finding(bundle),
]
let report : RedactionAuditReport = {
run_id: bundle.request.run_id,
ok: audit_ok(findings),
findings,
summary: "",
}
{ ..report, summary: audit_summary(report) }
}