|
| 1 | +--- |
| 2 | +title: Compliance reports |
| 3 | +description: >- |
| 4 | + Map a freshdata CleanReport onto regulatory control frameworks — 21 CFR Part 11, |
| 5 | + GDPR, ALCOA+, SOX-404, and HIPAA Safe Harbor — and emit standards-grade audit |
| 6 | + artifacts. |
| 7 | +keywords: compliance report python, 21 cfr part 11 audit trail, gdpr article 30, hipaa safe harbor, sox 404 data controls, alcoa+ |
| 8 | +--- |
| 9 | + |
| 10 | +# Compliance reports |
| 11 | + |
| 12 | +The `freshdata.compliance` subpackage turns a [`CleanReport`](cleaning-engine.md) |
| 13 | +into a regulatory audit artifact. Each *generator* maps the transformations |
| 14 | +freshdata applied — imputations, outlier handling, normalisations, deduplication, |
| 15 | +PII masking — onto a named control framework and emits a structured report you can |
| 16 | +attach to a data-governance workflow. |
| 17 | + |
| 18 | +The generators are **purely additive**: they never mutate the input report or |
| 19 | +DataFrame. They read what freshdata already recorded and re-express it against a |
| 20 | +framework's controls. |
| 21 | + |
| 22 | +!!! warning "Report generation, not certification" |
| 23 | + A compliance artifact **supports** a compliance workflow; it does not |
| 24 | + **constitute** a legal determination of compliance. Every report carries a |
| 25 | + verbatim caveat ([`GENERAL_CAVEAT`](#caveat)) to that effect, and review by a |
| 26 | + qualified compliance professional is required. |
| 27 | + |
| 28 | +## Quickstart |
| 29 | + |
| 30 | +```python |
| 31 | +import freshdata as fd |
| 32 | +from freshdata.compliance import generate_compliance_report, ComplianceConfig |
| 33 | + |
| 34 | +cleaned, report = fd.clean(df, return_report=True) |
| 35 | + |
| 36 | +bundle = generate_compliance_report( |
| 37 | + report, |
| 38 | + frameworks=["21cfr_11", "hipaa_safe_harbor"], |
| 39 | + config=ComplianceConfig(operator_id="svc-1", retention_days=2555), |
| 40 | + dataframe=df, # optional: recovers column roles + missing ratios |
| 41 | +) |
| 42 | + |
| 43 | +bundle.summary() |
| 44 | +# {'21cfr_11': {'passed': True, 'warnings': [], 'errors': []}, |
| 45 | +# 'hipaa_safe_harbor': {'passed': True, 'warnings': [...], 'errors': []}} |
| 46 | + |
| 47 | +bundle["hipaa_safe_harbor"].passed # -> True / False |
| 48 | +print(bundle.to_json()) # full audit artifact as JSON |
| 49 | +``` |
| 50 | + |
| 51 | +`generate_compliance_report` also accepts an enterprise result directly: |
| 52 | +`generate_compliance_report(enterprise_result, frameworks=[...])` (or |
| 53 | +`report` exposing `clean_report` + `trust_after`) folds in the embedded report |
| 54 | +and trust/mask data automatically. |
| 55 | + |
| 56 | +## Frameworks |
| 57 | + |
| 58 | +Pass one or more of these keys in `frameworks=`: |
| 59 | + |
| 60 | +| Key | Framework | What it documents | |
| 61 | +| --- | --- | --- | |
| 62 | +| `21cfr_11` | 21 CFR §11.10(e) | A tamper-evident audit trail: one entry per action, each marked non-obscuring (a pre-image was retained or the change cannot hide prior data). | |
| 63 | +| `gdpr_30` | GDPR Article 30 + Article 17 | Record of processing activities plus erasure (right-to-be-forgotten) evidence. | |
| 64 | +| `alcoa_plus` | ALCOA+ | Data-integrity attributes (Attributable, Legible, Contemporaneous, Original, Accurate, +). | |
| 65 | +| `sox_404` | SOX-404 transformation control | Internal-control evidence over data transformations, gated on the Data Trust Score. | |
| 66 | +| `hipaa_safe_harbor` | HIPAA Safe Harbor | Coverage of the 18 Safe Harbor identifiers, flagging any that remain unmasked. | |
| 67 | + |
| 68 | +Unknown keys raise `ValueError` listing the valid keys. |
| 69 | + |
| 70 | +## Configuration |
| 71 | + |
| 72 | +`ComplianceConfig` carries the caller-supplied context; every field has a sensible |
| 73 | +default, so `ComplianceConfig()` is valid. The most useful knobs: |
| 74 | + |
| 75 | +| Field | Default | Purpose | |
| 76 | +| --- | --- | --- | |
| 77 | +| `operator_id` | `None` (`"system"`) | Operator recorded on each 21 CFR audit entry. | |
| 78 | +| `retention_days` | `2555` (7 years) | Retention period stamped on audit entries. | |
| 79 | +| `masked_columns` | `[]` | Columns known to be PII-masked (report-only path; merged with any enterprise mask report). | |
| 80 | +| `trust_score` | `None` | 0–100 trust score for the SOX / 21 CFR gates when no enterprise result is supplied. | |
| 81 | +| `fail_on_hipaa_gap` | `False` | Raise [`ComplianceGapError`](#errors) instead of warning when Safe Harbor gaps remain. | |
| 82 | +| `strict_cfr_normalization` | `False` | See below. | |
| 83 | +| `controller_name` / `controller_contact` / `processing_purpose` / `legal_basis` / `data_subject_categories` | — | GDPR Article 30 record fields. | |
| 84 | + |
| 85 | +### `strict_cfr_normalization` |
| 86 | + |
| 87 | +Controls how the 21 CFR audit classifies *normalising rewrites* (whitespace |
| 88 | +trims, sentinel canonicalisation): |
| 89 | + |
| 90 | +- **`False` (default)** — these lossless normalisations are treated as |
| 91 | + **non-obscuring**: trimming `" Ann "` to `"Ann"` cannot hide prior information, |
| 92 | + so the gate stays green. Only genuine value rewrites with no retained pre-image |
| 93 | + (outlier capping, fuzzy clustering) fail the gate. |
| 94 | +- **`True`** — any rewrite that did not retain a pre-image, *including* |
| 95 | + normalisation, is treated as **obscuring**: the entry's |
| 96 | + `original_value_class` becomes `"not_captured"`, `non_obscuring_guarantee` |
| 97 | + becomes `False`, a warning is emitted, and the gate fails. Use this when your SOP |
| 98 | + requires an independently recorded pre-image for every value change. |
| 99 | + |
| 100 | +## Richer evidence |
| 101 | + |
| 102 | +Two optional, keyword-only arguments add evidence when available: |
| 103 | + |
| 104 | +- **`dataframe=`** — the source frame. Recovers per-column roles and missing |
| 105 | + ratios via [`freshdata.infer_roles`](api-reference.md), sharpening the HIPAA and |
| 106 | + ALCOA reports. |
| 107 | +- **`enterprise_result=`** — an [enterprise](feature-overview.md) result supplying |
| 108 | + the 0–100 Data Trust Score, PII-masking events, and fuzzy-clustering lineage. |
| 109 | + |
| 110 | +## Output |
| 111 | + |
| 112 | +`generate_compliance_report` returns a `ComplianceBundle` — a mapping of framework |
| 113 | +key to `FrameworkReport`: |
| 114 | + |
| 115 | +| On `ComplianceBundle` | Returns | |
| 116 | +| --- | --- | |
| 117 | +| `bundle.summary()` | `{key: {"passed", "warnings", "errors"}}` for a quick gate check. | |
| 118 | +| `bundle[key]` | The `FrameworkReport` for one framework. | |
| 119 | +| `key in bundle`, `len(bundle)`, `list(bundle)` | Membership, count, and the framework keys. | |
| 120 | +| `bundle.to_dict()` / `bundle.to_json(indent=2)` | The full artifact as a dict / JSON string. | |
| 121 | +| `bundle.to_frame()` | All reports flattened into a single `pandas.DataFrame`. | |
| 122 | + |
| 123 | +Each `FrameworkReport` exposes `framework_key`, `framework_name`, `passed` (bool), |
| 124 | +`warnings`, `errors`, and `data` (the framework-specific payload, e.g. the 21 CFR |
| 125 | +`audit_entries` or the HIPAA identifier coverage), plus its own `to_dict()`, |
| 126 | +`to_json()`, and `to_frame()`. |
| 127 | + |
| 128 | +## Errors {#errors} |
| 129 | + |
| 130 | +- `ValueError` — an unknown framework key was requested. |
| 131 | +- `ComplianceGapError` — HIPAA Safe Harbor gaps remain **and** |
| 132 | + `config.fail_on_hipaa_gap=True`. Otherwise gaps surface as warnings on the |
| 133 | + report and `passed` is `False`. |
| 134 | + |
| 135 | +## Caveat {#caveat} |
| 136 | + |
| 137 | +Every report embeds `GENERAL_CAVEAT` (importable from `freshdata.compliance`) |
| 138 | +unless a framework defines its own verbatim caveat. It states plainly that the |
| 139 | +artifact documents freshdata's transformations and their mapping to the named |
| 140 | +control framework, but is not a certified compliance system and does not |
| 141 | +constitute a legal determination — professional review is required. |
0 commit comments