///|
/// Control class used to describe how a field may leave a trust boundary.
pub(all) enum ComplianceClass {
Public
Internal
Sensitive
Restricted
Prohibited
} derive(Debug, Eq, Compare)
///|
pub(all) enum RetentionDecision {
RetainUntil
DeleteNow
LegalHold
UnknownRetention
} derive(Debug, Eq)
///|
pub(all) struct ComplianceRetentionPolicy {
name : String
days : Int
decision : RetentionDecision
legal_hold : Bool
reason : String
} derive(Debug, Eq)
///|
pub(all) struct AccessEvent {
actor : String
operation : String
document_id : String
scope : String
allowed : Bool
reason : String
sequence : Int
} derive(Debug, Eq)
///|
pub(all) struct ComplianceControl {
control_id : String
description : String
passed : Bool
class : ComplianceClass
evidence : String
} derive(Debug, Eq)
///|
pub(all) struct ComplianceReport {
document_id : String
controls : Array[ComplianceControl]
access_events : Array[AccessEvent]
passed : Bool
checksum : String
} derive(Debug)
///|
pub fn compliance_class_name(value : ComplianceClass) -> String {
match value {
Public => "public"
Internal => "internal"
Sensitive => "sensitive"
Restricted => "restricted"
Prohibited => "prohibited"
}
}
///|
pub fn retention_decision_name(value : RetentionDecision) -> String {
match value {
RetainUntil => "retain_until"
DeleteNow => "delete_now"
LegalHold => "legal_hold"
UnknownRetention => "unknown"
}
}
///|
pub fn compliance_class_for_kind(kind : PhiKind) -> ComplianceClass {
match kind {
IdNumber | MedicalRecord | Insurance => Restricted
PersonName | Phone | Email | Address | Date => Sensitive
Organization => Internal
Custom(_) => Internal
}
}
///|
pub fn compliance_class_for_path(path : String) -> ComplianceClass {
let value = path.to_lower()
if value.contains("password") ||
value.contains("secret") ||
value.contains("token") {
Prohibited
} else if value.contains("identifier") ||
value.contains("medical") ||
value.contains("insurance") {
Restricted
} else if value.contains("name") ||
value.contains("phone") ||
value.contains("email") ||
value.contains("address") {
Sensitive
} else if value.contains("organization") || value.contains("department") {
Internal
} else {
Public
}
}
///|
pub fn compliance_retention_policy(
name : String,
days : Int,
reason : String,
) -> ComplianceRetentionPolicy {
{
name,
days,
decision: if days <= 0 {
DeleteNow
} else {
RetainUntil
},
legal_hold: false,
reason,
}
}
///|
pub fn compliance_retention_legal_hold(
policy : ComplianceRetentionPolicy,
) -> ComplianceRetentionPolicy {
{ ..policy, legal_hold: true, decision: LegalHold }
}
///|
pub fn compliance_retention_is_safe(policy : ComplianceRetentionPolicy) -> Bool {
policy.days >= 0 &&
policy.reason.trim().length() > 0 &&
!(policy.decision == DeleteNow && policy.legal_hold)
}
///|
pub fn retention_bucket(days : Int) -> String {
if days <= 0 {
"immediate"
} else if days <= 7 {
"one-week"
} else if days <= 30 {
"one-month"
} else if days <= 365 {
"one-year"
} else {
"long-term"
}
}
///|
pub fn compliance_retention_summary(
policy : ComplianceRetentionPolicy,
) -> String {
[
"name=\{policy.name}",
"days=\{policy.days}",
"bucket=\{retention_bucket(policy.days)}",
"decision=\{retention_decision_name(policy.decision)}",
"legal_hold=\{policy.legal_hold}",
"safe=\{compliance_retention_is_safe(policy)}",
"reason=\{policy.reason}",
].join("\n")
}
///|
pub fn access_event(
actor : String,
operation : String,
document_id : String,
scope : String,
allowed : Bool,
reason : String,
sequence : Int,
) -> AccessEvent {
{ actor, operation, document_id, scope, allowed, reason, sequence }
}
///|
pub fn access_event_is_valid(event : AccessEvent) -> Bool {
event.actor.trim().length() > 0 &&
event.operation.trim().length() > 0 &&
event.document_id.trim().length() > 0 &&
event.sequence >= 0
}
///|
pub fn access_event_summary(event : AccessEvent) -> String {
[
"actor=\{event.actor}",
"operation=\{event.operation}",
"document=\{event.document_id}",
"scope=\{event.scope}",
"allowed=\{event.allowed}",
"sequence=\{event.sequence}",
"reason=\{event.reason}",
].join(" ")
}
///|
pub fn compliance_control(
control_id : String,
description : String,
passed : Bool,
class : ComplianceClass,
evidence : String,
) -> ComplianceControl {
{ control_id, description, passed, class, evidence }
}
///|
pub fn ComplianceReport::failed_controls(
self : ComplianceReport,
) -> Array[ComplianceControl] {
self.controls.filter(fn(control) { !control.passed })
}
///|
pub fn ComplianceReport::restricted_failures(
self : ComplianceReport,
) -> Array[ComplianceControl] {
self.failed_controls().filter(fn(control) { control.class >= Restricted })
}
///|
pub fn ComplianceReport::access_denials(
self : ComplianceReport,
) -> Array[AccessEvent] {
self.access_events.filter(fn(event) { !event.allowed })
}
///|
pub fn ComplianceReport::is_ready(self : ComplianceReport) -> Bool {
self.passed &&
self.failed_controls().is_empty() &&
self.access_denials().is_empty()
}
///|
pub fn ComplianceReport::summary(self : ComplianceReport) -> String {
[
"document=\{self.document_id}",
"controls=\{self.controls.length()}",
"failed=\{self.failed_controls().length()}",
"restricted_failures=\{self.restricted_failures().length()}",
"access_events=\{self.access_events.length()}",
"denials=\{self.access_denials().length()}",
"passed=\{self.passed}",
"checksum=\{self.checksum}",
].join("\n")
}
///|
pub fn control_for_field(field : ResourceField) -> ComplianceControl {
let class = compliance_class_for_kind(field.kind)
let passed = (field.action == Retain && class <= Internal) ||
(field.action != Retain && class >= Sensitive)
compliance_control(
"FIELD_" + field.path,
"structured field handling",
passed,
class,
"action=\{resource_action_name(field.action)}",
)
}
///|
pub fn controls_for_resource(
document : ResourceDocument,
) -> Array[ComplianceControl] {
document.fields.map(control_for_field)
}
///|
pub fn compliance_check_resource(
document : ResourceDocument,
report : ResourceReport,
) -> Array[ComplianceControl] {
let controls = controls_for_resource(document)
controls.push(
compliance_control(
"RESOURCE_REPORT",
"resource report has no error-level issues",
!report.issues.any(fn(issue) { issue.severity == Error }),
Internal,
"issues=\{report.issues.length()}",
),
)
controls
}
///|
pub fn compliance_check_output(
input : String,
result : DeidResult,
) -> Array[ComplianceControl] {
[
compliance_control(
"OUTPUT_NO_ORIGINAL",
"detected values are not present in output",
quality_no_original_phi(result.text, result.findings),
Restricted,
"findings=\{result.findings.length()}",
),
compliance_control(
"OUTPUT_CONTRACT",
"output contract is internally consistent",
output_contract_passes(input, result),
Restricted,
"output_length=\{result.text.length()}",
),
compliance_control(
"AUDIT_PRESENT",
"audit contains the selected findings",
result.audit.finding_count == result.findings.length(),
Internal,
"audit_findings=\{result.audit.finding_count}",
),
]
}
///|
pub fn build_compliance_report(
document_id : String,
controls : Array[ComplianceControl],
access_events : Array[AccessEvent],
) -> ComplianceReport {
let passed = controls.all(fn(control) { control.passed }) &&
access_events.all(fn(event) { event.allowed })
{
document_id,
controls,
access_events,
passed,
checksum: stable_hash(
controls
.map(fn(control) {
control.control_id + ":\{control.passed}:" + control.evidence
})
.join("\n"),
),
}
}
///|
pub fn compliance_control_json(control : ComplianceControl) -> String {
"{" +
"\"id\":\{json_escape(control.control_id)}," +
"\"description\":\{json_escape(control.description)}," +
"\"passed\":\{control.passed}," +
"\"class\":\{json_escape(compliance_class_name(control.class))}," +
"\"evidence\":\{json_escape(control.evidence)}" +
"}"
}
///|
pub fn access_event_json(event : AccessEvent) -> String {
"{" +
"\"actor\":\{json_escape(event.actor)}," +
"\"operation\":\{json_escape(event.operation)}," +
"\"document_id\":\{json_escape(event.document_id)}," +
"\"scope\":\{json_escape(event.scope)}," +
"\"allowed\":\{event.allowed}," +
"\"reason\":\{json_escape(event.reason)}," +
"\"sequence\":\{event.sequence}" +
"}"
}
///|
pub fn ComplianceReport::to_json(self : ComplianceReport) -> String {
"{" +
"\"document_id\":\{json_escape(self.document_id)}," +
"\"passed\":\{self.passed}," +
"\"checksum\":\{json_escape(self.checksum)}," +
"\"controls\":[" +
self.controls.map(compliance_control_json).join(",") +
"],\"access_events\":[" +
self.access_events.map(access_event_json).join(",") +
"]}"
}
///|
pub fn ComplianceReport::to_markdown(self : ComplianceReport) -> String {
let lines = [
"| Control | Class | Status | Evidence |", "| --- | --- | --- | --- |",
]
for control in self.controls {
lines.push(
"| \{control.control_id} | \{compliance_class_name(control.class)} | \{control.passed} | \{control.evidence} |",
)
}
lines.push("")
lines.push("passed=\{self.passed}; checksum=\{self.checksum}")
lines.join("\n")
}
///|
pub fn compliance_class_counts(
controls : Array[ComplianceControl],
) -> Map[String, Int] {
let counts : Map[String, Int] = Map([])
for control in controls {
let key = compliance_class_name(control.class)
counts[key] = counts.get_or_default(key, 0) + 1
}
counts
}
///|
pub fn compliance_failed_ids(
controls : Array[ComplianceControl],
) -> Array[String] {
controls
.filter(fn(control) { !control.passed })
.map(fn(control) { control.control_id })
}
///|
pub fn compliance_has_prohibited(controls : Array[ComplianceControl]) -> Bool {
controls.any(fn(control) { control.class == Prohibited })
}
///|
pub fn compliance_has_restricted_failure(
controls : Array[ComplianceControl],
) -> Bool {
controls.any(fn(control) { control.class >= Restricted && !control.passed })
}
///|
pub fn compliance_requires_human_review(
controls : Array[ComplianceControl],
) -> Bool {
compliance_has_prohibited(controls) ||
compliance_has_restricted_failure(controls)
}
///|
pub fn compliance_access_is_monotonic(events : Array[AccessEvent]) -> Bool {
let mut valid = true
for i in 1..= events[i].sequence {
valid = false
}
}
valid
}
///|
pub fn compliance_access_denial_rate(events : Array[AccessEvent]) -> Float {
if events.is_empty() {
0.0
} else {
Float::from_int(events.filter(fn(event) { !event.allowed }).length()) /
Float::from_int(events.length())
}
}
///|
pub fn compliance_report_checksum(report : ComplianceReport) -> String {
stable_hash(report.to_json())
}