New Deterministic queryable ciphertext, scheduled compliance reports, and environment-aware licence enforcement. See what's included →
Audit evidence

The answer to "prove it".

DPDP Act 2023 and GDPR Article 32 both require appropriate technical measures — and the ability to demonstrate them. A screenshot of your code isn't evidence. The compliance report is a dated, signed-off inventory of exactly which fields are protected, which aren't, who accepted the risk, and what fired recently — and it writes itself on your schedule.

Formats HTML + JSON Cadence daily · weekly · monthly Coverage computed, not claimed Print-to-PDF ready
The evidence pack

Which fields are protected, which aren't, and who signed off.

One generated document answers the questions your security review and auditor will actually ask — from the model's real state at generation time, not a policy claiming coverage.

compliance-AppDbContext-2026-07-23.html 82.9% coverage HTML JSON

Encryption Compliance Report

Context AppDbContext · generated 2026-07-23 09:20:11Z · license: Enterprise (Contoso Finance)
82.9%
Encryption coverage
34
Encrypted properties
41
Candidate properties
1
Critical findings
2
Accepted risks
14
Recent alerts
1. Encryption configuration
AES-GCM 256-bit, keys in Azure Key Vault, rotated 2026-06-01 (key id 2)
2. Encrypted property inventory
Entity Property Column CLR type Storage format
Customer AadhaarNumber aadhaar_number String Base64
Customer PanNumber pan_number String Base64
Payment CardNumber card_number String Binary
Payee SettlementAccount settlement_acct String Base64
3. Outstanding scan findings
Severity Entity.Property Column Evidence & recommendation
Critical Customer.AadhaarNumber aadhaar_bak 94% of 100 samples pattern-verified. Encrypt or drop the backup column.
Warning Lead.Notes notes ML-classified free-text PII in 21% of samples.
4. Accepted risks (scan exemptions)
Entity Property Justification Approved by
Payout AccountLast4 Masked at ingestion; only last 4 digits stored CISO 2026-07-01
5. Recent security alerts
Time (UTC) Severity Kind Source
2026-07-23 03:14:07 Critical AnomalyDetected entity:Customer
2026-07-23 09:00:05 Warning ScanFinding scan:AppDbContext
EntityFrameworkCore.Crypto.DataEncryption.ML · evidence for DPDP Act 2023 & GDPR Art. 32
Rendered by generator.ToHtml(report) — A4 page rules included, so print-to-PDF is the whole workflow.
"Which personal data do you encrypt?"
Section 2 lists every encrypted column by name, with its storage format — not a policy claiming coverage, the model's actual state at generation time.
"How do you know you didn't miss any?"
The coverage figure is computed, not asserted: encrypted columns over candidate columns the scanner found. Section 3 names what's still outstanding, so a gap is disclosed rather than discovered.
"This field is unprotected. Why?"
Section 4 turns that from a finding into a documented decision — the justification and the name of the person who signed it off, captured in code at the point the exemption was made.
"Has anything happened?"
Section 5 is the incident trail with timestamps and severity — and the dead-letter count, so you can show that alerts were delivered, not merely raised.
"Can we ingest this?"
Same report, two formats. HTML for the audit binder, JSON for your GRC platform or a coverage gate in CI.
Scheduled delivery

It arrives on its own.

Set the cadence and it generates and emails itself, with the report attached. Recipients are separate from your alert list by default — the report names every unprotected column in your schema, so it belongs with compliance rather than the on-call rota.

[acme/prod] Encryption compliance report — AppDbContext — 2026-08-01 (82.9% coverage, 1 critical)
From
Crypto Sentinel <security@yourapp.example>
To
dpo@yourapp.example, audit@yourapp.example
Sent
1 Aug 2026, 06:00 — monthly, on the 1st
Encryption compliance report
AppDbContext · generated 2026-08-01 06:00:04Z · Enterprise licence
Encryption coverage 82.9%
Encrypted properties 34 of 41 candidates
Critical findings 1
Accepted risks 2
Alerts in window 14
Dead-lettered deliveries 0
Outstanding critical findings: Customer.AadhaarNumber
📎 compliance-AppDbContext-2026-08-01.html 📎 compliance-AppDbContext-2026-08-01.json
The full report is attached. It lists every encrypted column and every one still unprotected — treat it as confidential.

Your cadence, your clock

Daily, weekly on a chosen weekday, or monthly on a chosen date — at your time of day, in your time zone. Configured in appsettings.json, so changing it isn't a redeploy.

Unconfigured, it's the 1st of each month at 06:00 UTC.

A missed window isn't lost

Deploying at 06:00 on the 1st used to mean no report that month. Now the run is recorded, and a window missed while the process was down is sent late instead of skipped.

One report, not one per replica

Instances sharing a volume claim the run atomically, so three pods send one report between them. A failed send releases the claim so it retries rather than consuming the month.

// appsettings.json
"Report": {
  "Enabled": true,
  "Cadence": "Weekly",            // Daily | Weekly | Monthly | Custom
  "DayOfWeek": "Monday",
  "TimeOfDay": "09:00:00",
  "TimeZoneId": "Asia/Kolkata",
  "Recipients": [ "dpo@acme.example" ]
}

Or generate one on demand

// Scan the live model and data, then render the evidence pack.
ScanReport scan = await scanner.ScanAsync(context);

ComplianceReport report = generator.Generate(
    context,
    "AES-GCM 256-bit, keys in Azure Key Vault, rotated 2026-06-01",
    scan,
    recentAlerts);

await File.WriteAllTextAsync("compliance.html", generator.ToHtml(report));
await File.WriteAllTextAsync("compliance.json", generator.ToJson(report));
Runs on demand — wire it to a monthly job, or fail your build when CoveragePercent drops.

Evidence, not assertions.

The report is generated from your live model and data — so what you hand the auditor is what's actually true at that moment. Pairs with the alerting layer that tells you the moment something changes.