Skip to content

Compliance Reports

Tayra provides compliance report generation through ITayraCompliance for producing formatted, self-contained HTML reports that cover the key GDPR reporting requirements. Each report type renders as a complete HTML document with embedded CSS — no external dependencies, no JavaScript, ready to print or email.

Report Types

The generator supports five report types:

ReportMethodGDPR ArticleInput
Records of ProcessingGenerateArticle30ReportArt. 30PiiInventoryReport + Article30Options
Data Subject AccessGenerateAccessReportArt. 15DataSubjectAccessReport
Breach NotificationGenerateBreachReportArt. 33/34BreachNotificationReport
Encryption CoverageGenerateEncryptionCoverageReportArt. 32PiiInventoryReport
Key LifecycleGenerateKeyLifecycleReportArt. 5(1)(e)KeyLifecycleData

Setup

Package Requirement

This feature requires the Tayra.Compliance package and a Compliance edition license. Data protection itself is handled by Tayra.Core — this package provides the reporting tooling.

shell
dotnet add package Tayra.Compliance

Register the compliance services:

csharp
using Tayra.Compliance;

services.AddTayra(opts => opts.LicenseKey = licenseKey)
    // InMemoryKeyStore is used by default for development.
    // For production, chain a secrets manager: .UseVaultKeyStore(...)
    .AddCompliance(complianceOpts =>
    {
        complianceOpts.ApplicationName = "MyApp";
        complianceOpts.AddEntityType<Customer>();
    });

This registers ITayraCompliance, which provides report generation alongside PII inventory, data subject access, and breach notification.

INFO

The compliance report generator is stateless. It formats data that you supply from other Tayra services. You can also construct the input objects manually if needed.

Art. 30 Report -- Records of Processing Activities

The Art. 30 report combines PII inventory data with controller-level metadata to produce a formal Records of Processing Activities document. This is the report your DPO submits to the supervisory authority.

Article30Options

Configure the controller information that appears in the report header:

PropertyTypeDefaultDescription
ControllerNamestring"Organization"Name of the data controller
DpoContactstring?nullDPO contact details
ProcessingPurposestring"Service delivery and account management"Purpose of processing
LegalBasisstring"Contract performance (Art. 6(1)(b))"Legal basis for processing
RetentionPeriodstring"As defined by key retention policy"Data retention period description
RecipientsIList<string>[]Categories of data recipients
ThirdCountryTransfersboolfalseWhether data is transferred outside the EEA
SecurityMeasuresstring"AES-256-GCM field-level encryption, HMAC-SHA256 blind indexes, crypto-shredding"Description of security measures

Example

csharp
public class ComplianceService
{
    private readonly ITayraCompliance _compliance;

    public ComplianceService(ITayraCompliance compliance)
    {
        _compliance = compliance;
    }

    public async Task GenerateArt30ReportAsync()
    {
        var inventoryReport = _compliance.GenerateInventory();

        var options = new Article30Options
        {
            ControllerName = "Acme Corp",
            DpoContact = "dpo@acme.com",
            ProcessingPurpose = "Customer relationship management and order fulfillment",
            LegalBasis = "Contract performance (Art. 6(1)(b))",
            RetentionPeriod = "7 years after account closure",
            Recipients = ["Payment processor", "Shipping provider"],
            ThirdCountryTransfers = false,
            SecurityMeasures = "AES-256-GCM field-level encryption, HMAC-SHA256 blind indexes, "
                + "crypto-shredding, TLS 1.3 in transit",
        };

        var html = _compliance.RenderArticle30Report(inventoryReport, options);
        await File.WriteAllTextAsync("art30-report.html", html);
    }
}

The generated HTML includes:

  1. Controller Information -- Organization name, DPO contact, purpose, legal basis, retention period, security measures
  2. Categories of Personal Data -- Table of all entities with PII fields, encryption status, blind index count, and protecting integrations
  3. Summary -- Aggregate counts of entity types, PII fields, encrypted fields, and active integrations

Art. 15 Access Report -- Data Subject Access

The access report formats a DataSubjectAccessReport (from ITayraCompliance.ExportAccessAsync) into a presentable HTML document suitable for delivering to a data subject.

Example

csharp
public async Task GenerateAccessReportAsync(string subjectId)
{
    var accessReport = await _compliance.ExportAccessAsync(subjectId);
    var html = _compliance.RenderAccessReport(accessReport);

    await File.WriteAllTextAsync($"access-report-{subjectId}.html", html);
}

The generated HTML includes:

  • Subject ID and generation timestamp
  • Per-entity tables showing each field name, its decrypted value, and whether it has been redacted (crypto-shredded)
  • Fields where the encryption key has been shredded are marked with a visual "Redacted" indicator

Art. 33/34 Breach Report -- Breach Notification

The breach report formats a BreachNotificationReport (from ITayraCompliance.AssessBreachAsync) into a document that contains both the DPA notification content (Art. 33) and the data subject notification content (Art. 34).

Example

csharp
public async Task GenerateBreachReportAsync(BreachDetails details)
{
    var impact = await _compliance.AssessBreachAsync(details);
    var notification = await _compliance.GenerateBreachReportAsync(impact);
    var html = _compliance.RenderBreachReport(notification);

    await File.WriteAllTextAsync("breach-report.html", html);
}

The generated HTML includes:

  • DPA notification deadline with overdue warning if the 72-hour window has passed
  • Impact assessment -- severity level, affected subject count, affected key IDs, affected entity types
  • DPA Notification (Art. 33) -- Nature of breach, affected subjects summary, affected data summary, likely consequences, measures taken
  • Data Subject Notification (Art. 34) -- Description of what happened and recommended protective actions (only included when severity is High or Critical)

Encryption Coverage Report

The encryption coverage report shows which entities are fully encrypted, which are partially encrypted, and the overall coverage percentage. This is useful for internal security reviews and as evidence of Art. 32 compliance (security of processing).

Example

csharp
public async Task GenerateCoverageReportAsync()
{
    var inventoryReport = _compliance.GenerateInventory();
    var html = _compliance.RenderCoverageReport(inventoryReport);

    await File.WriteAllTextAsync("encryption-coverage.html", html);
}

The generated HTML includes:

  • Overview -- Total entities with PII, fully encrypted count, partially encrypted count, overall coverage percentage
  • Entity details table -- Each entity with its encryption status, total PII field count, encrypted field count, and per-entity coverage percentage

CI/CD Integration

Use the encryption coverage report as a deployment gate. Generate it during CI/CD and fail the pipeline if coverage drops below your threshold. See CLI Tool for command-line report generation.

Key Lifecycle Report

The key lifecycle report documents key management activity over a time period -- rotations, creations, deletions (shredding), and expirations. This supports Art. 5(1)(e) (storage limitation) and provides evidence that your key management practices are active and compliant.

KeyLifecycleData

Construct the input from your audit trail or key store events:

PropertyTypeDescription
ReportPeriodStartDateTimeOffsetStart of the reporting period
ReportPeriodEndDateTimeOffsetEnd of the reporting period
EventsIReadOnlyList<KeyLifecycleEvent>Key lifecycle events in the period

KeyLifecycleEvent

PropertyTypeDescription
TimestampDateTimeOffsetWhen the event occurred
EventTypestringEvent type (e.g., "KeyCreated", "KeyRotated", "KeyDeleted", "KeyExpired")
KeyIdstringThe key identifier involved
Detailsstring?Optional additional details

Example

csharp
public async Task GenerateKeyLifecycleReportAsync()
{
    var now = DateTimeOffset.UtcNow;
    var events = await _auditStore.GetKeyEventsAsync(
        now.AddDays(-30), now);

    var lifecycleData = new KeyLifecycleData
    {
        ReportPeriodStart = now.AddDays(-30),
        ReportPeriodEnd = now,
        Events = events.Select(e => new KeyLifecycleEvent
        {
            Timestamp = e.Timestamp,
            EventType = e.EventType,
            KeyId = e.KeyId,
            Details = e.Details,
        }).ToList(),
    };

    var html = _compliance.RenderKeyLifecycleReport(lifecycleData);
    await File.WriteAllTextAsync("key-lifecycle-report.html", html);
}

The generated HTML includes:

  • Report period displayed in the header
  • Event summary table -- Each event type with its count for the period
  • Event log -- Full chronological list with timestamp, event type, key ID, and details

HTML Output

All reports render as self-contained HTML documents with embedded CSS. The styling uses system fonts and a clean table layout that works well in browsers, print dialogs, and email clients. There are no external CSS files, JavaScript dependencies, or image references -- the HTML file is the complete report.

csharp
// Write to file
var html = _compliance.RenderArticle30Report(inventory, options);
await File.WriteAllTextAsync("report.html", html);

// Return from an API endpoint
[HttpGet("/compliance/art30")]
public IActionResult GetArt30Report()
{
    var inventory = _compliance.GenerateInventory();
    var html = _compliance.RenderArticle30Report(inventory);
    return Content(html, "text/html");
}

// Send via email
var html = _compliance.RenderBreachReport(notification);
await _emailService.SendAsync("dpo@acme.com", "Breach Report", html);

See Also