Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Ops.Compliance + Ops.SupplyChain -- Regulatory Frameworks and Dependency Audit

Two DSLs, one post. They are separate in the codebase but inseparable in practice: you cannot be compliant if you do not know what is in your supply chain.


Part A: Ops.Compliance

"We think we're compliant" is not evidence.


The Problem

The SOC2 Type II audit is in six weeks. The auditor sent a list of 47 controls. For each control, the team needs to provide evidence that the control is implemented.

The controls are in a spreadsheet. "SOC2_Controls_v4_FINAL_reviewed_2025.xlsx" has 47 rows. Each row has a control ID, a description, and an "Evidence" column. The evidence column says things like "See OrderService authentication middleware" and "Refer to infrastructure runbook page 23." Some cells are empty. Some reference code that was refactored six months ago.

Mapping controls to code takes weeks. A senior engineer spends two weeks mapping each SOC2 control to the actual implementation. They discover that 8 controls have no implementation at all. They discover that 3 controls reference code that no longer exists. They discover that the runbook is from 2024 and describes infrastructure that was replaced.

Data residency is undocumented. The compliance officer asks: "Can customer data leave the EU?" The answer depends on which cloud regions the services are deployed to, which third-party processors handle the data, and whether any CDN edge nodes cache PII. Nobody has a complete picture. The investigation takes a week.

Accessibility is an afterthought. The product team promised WCAG AA compliance in the contract. Nobody checked. The first accessibility audit happens three weeks before launch. It finds 200 violations.

What these failures share: the compliance requirements exist in documents that are disconnected from the code. The code changes. The documents do not. The gap widens until an audit forces reconciliation.


Attribute Definitions

// =================================================================
// Ops.Compliance.Lib -- Compliance DSL Attributes
// =================================================================

/// Supported regulatory and compliance frameworks.
public enum ComplianceStandard
{
    SOC2,           // Service Organization Controls (Type I / Type II)
    GDPR,           // General Data Protection Regulation (EU)
    HIPAA,          // Health Insurance Portability and Accountability Act
    PCI_DSS,        // Payment Card Industry Data Security Standard
    ISO27001,       // Information Security Management System
    IEC62304,       // Medical device software lifecycle
    WCAG_AA,        // Web Content Accessibility Guidelines (Level AA)
    WCAG_AAA,       // Web Content Accessibility Guidelines (Level AAA)
    FedRAMP         // Federal Risk and Authorization Management Program
}

/// Declares that a service must comply with a regulatory framework.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class ComplianceFrameworkAttribute : Attribute
{
    public ComplianceStandard Standard { get; }
    public string[] RequiredControls { get; }

    public ComplianceFrameworkAttribute(
        ComplianceStandard standard,
        params string[] requiredControls)
    {
        Standard = standard;
        RequiredControls = requiredControls;
    }

    /// <summary>Audit frequency (e.g., "annual", "quarterly").</summary>
    public string AuditFrequency { get; init; } = "annual";

    /// <summary>Certification expiry date (ISO 8601).</summary>
    public string? CertificationExpiry { get; init; }

    /// <summary>External auditor or certification body.</summary>
    public string? Auditor { get; init; }
}

/// Maps a specific control to its implementation evidence.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
    AllowMultiple = true)]
public sealed class ComplianceControlAttribute : Attribute
{
    public string ControlId { get; }
    public string Description { get; }
    public string Evidence { get; }

    public ComplianceControlAttribute(
        string controlId, string description, string evidence)
    {
        ControlId = controlId;
        Description = description;
        Evidence = evidence;
    }

    /// <summary>
    /// Method name that implements this control.
    /// Validated at compile time by the analyzer.
    /// </summary>
    public string? ImplementedBy { get; init; }

    /// <summary>Control status.</summary>
    public ControlStatus Status { get; init; } = ControlStatus.Implemented;

    /// <summary>Last review date (ISO 8601).</summary>
    public string? LastReviewDate { get; init; }

    /// <summary>Owner responsible for this control.</summary>
    public string Owner { get; init; } = "";
}

public enum ControlStatus
{
    Implemented,
    PartiallyImplemented,
    Planned,
    NotApplicable
}

/// Declares data residency constraints.
[AttributeUsage(AttributeTargets.Class)]
public sealed class DataResidencyAttribute : Attribute
{
    public string[] AllowedRegions { get; }
    public string[] ProhibitedRegions { get; }

    public DataResidencyAttribute(
        string[] allowedRegions,
        string[]? prohibitedRegions = null)
    {
        AllowedRegions = allowedRegions;
        ProhibitedRegions = prohibitedRegions ?? Array.Empty<string>();
    }

    /// <summary>
    /// Whether CDN edge caching is permitted in allowed regions.
    /// </summary>
    public bool AllowEdgeCaching { get; init; } = false;

    /// <summary>Legal basis for cross-border transfers.</summary>
    public string? TransferBasis { get; init; }
}

/// Declares accessibility requirements.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class AccessibilityRequirementAttribute : Attribute
{
    public ComplianceStandard Standard { get; }
    public string Scope { get; }

    public AccessibilityRequirementAttribute(
        ComplianceStandard standard, string scope)
    {
        Standard = standard;
        Scope = scope;
    }

    /// <summary>Audit tool used for validation.</summary>
    public string AuditTool { get; init; } = "axe-core";

    /// <summary>Maximum allowed violations at launch.</summary>
    public int MaxViolationsAtLaunch { get; init; } = 0;
}

Usage

[DeploymentApp("order-service")]

// SOC2 Type II — 5 controls mapped
[ComplianceFramework(
    ComplianceStandard.SOC2,
    "CC6.1", "CC6.2", "CC6.3", "CC7.1", "CC7.2",
    AuditFrequency = "annual",
    Auditor = "Deloitte")]

// GDPR (controls handled via DataGovernance DSL cross-reference)
[ComplianceFramework(
    ComplianceStandard.GDPR,
    "Art5", "Art6", "Art13", "Art15", "Art17", "Art25", "Art30", "Art32")]

// WCAG AA for all public-facing pages
[AccessibilityRequirement(
    ComplianceStandard.WCAG_AA, "public-pages",
    AuditTool = "axe-core",
    MaxViolationsAtLaunch = 0)]

// Data residency: EU only, no edge caching of PII
[DataResidency(
    allowedRegions: new[] { "eu-west-1", "eu-central-1" },
    prohibitedRegions: new[] { "us-*", "ap-*", "cn-*" },
    AllowEdgeCaching = false,
    TransferBasis = "SCCs")]

// Control evidence mappings
[ComplianceControl(
    "CC6.1",
    "Logical and Physical Access Controls",
    "RBAC enforced via [RbacPolicy] on all endpoints",
    ImplementedBy = nameof(SecurityConfig.ConfigureRbac),
    Status = ControlStatus.Implemented,
    LastReviewDate = "2026-03-15",
    Owner = "security-team")]

[ComplianceControl(
    "CC6.2",
    "System Access Restrictions",
    "JWT-based auth with token expiry and refresh rotation",
    ImplementedBy = nameof(SecurityConfig.ConfigureJwtAuth),
    Status = ControlStatus.Implemented)]

[ComplianceControl(
    "CC6.3",
    "Access Control for Protected Information",
    "Row-level security via tenant isolation middleware",
    ImplementedBy = nameof(TenantMiddleware.EnforceTenantBoundary),
    Status = ControlStatus.Implemented)]

[ComplianceControl(
    "CC7.1",
    "Monitoring for Unauthorized Activity",
    "Audit logging via [AuditPolicy] on all PII entities",
    ImplementedBy = nameof(AuditMiddleware.LogAccess),
    Status = ControlStatus.Implemented)]

[ComplianceControl(
    "CC7.2",
    "Incident Response",
    "PagerDuty integration via [AlertRoute] for security events",
    ImplementedBy = nameof(AlertConfig.ConfigureSecurityAlerts),
    Status = ControlStatus.PartiallyImplemented,
    Owner = "platform-team")]
public partial class OrderServiceCompliance { }

Three-tier projection

[ComplianceControl] and [DataResidency] declarations don't just produce paperwork — they project into enforceable artifacts at all three tiers. Local runs get matrices, SBOMs, and license audit reports. Container runs get OPA Rego policies that conftest evaluates against compose files plus per-framework Trivy scan profiles. Cloud runs get Gatekeeper Constraint Templates and Constraint instances that enforce the same rules at the Kubernetes API server.

Diagram
Compliance attributes project into enforceable artifacts: matrices, SBOMs and license audits locally, OPA Rego and Trivy profiles in containers, and Gatekeeper constraint templates at the Kubernetes API server.

Local Tier: compliance-matrix.md

This is the artifact that replaces the spreadsheet. It is generated on every build.

# Compliance Matrix — order-service
Generated: 2026-04-06T10:00:00Z

## SOC2 Type II
Auditor: Deloitte | Frequency: Annual

| Control | Description                           | Status      | Evidence                                       | Implemented By                              | Owner         | Last Review |
|---------|---------------------------------------|-------------|------------------------------------------------|---------------------------------------------|---------------|-------------|
| CC6.1   | Logical and Physical Access Controls  | Implemented | RBAC enforced via [RbacPolicy] on all endpoints | SecurityConfig.ConfigureRbac                | security-team | 2026-03-15  |
| CC6.2   | System Access Restrictions            | Implemented | JWT-based auth with token expiry               | SecurityConfig.ConfigureJwtAuth             |               |             |
| CC6.3   | Access Control for Protected Info     | Implemented | Row-level security via tenant isolation        | TenantMiddleware.EnforceTenantBoundary      |               |             |
| CC7.1   | Monitoring for Unauthorized Activity  | Implemented | Audit logging via [AuditPolicy] on PII         | AuditMiddleware.LogAccess                   |               |             |
| CC7.2   | Incident Response                     | Partial     | PagerDuty integration for security events      | AlertConfig.ConfigureSecurityAlerts         | platform-team |             |

### Coverage: 4/5 fully implemented (80%), 1 partially implemented

## GDPR
| Article | Mapped To                                                |
|---------|----------------------------------------------------------|
| Art5    | [RetentionPolicy] — data minimization and storage limits |
| Art6    | [GdprDataMap] — lawful basis declared per entity         |
| Art13   | Privacy policy endpoint — /privacy                       |
| Art15   | [SubjectAccessRequest] handler — generated                |
| Art17   | [GdprDataMap].DeletionStrategy — right to erasure        |
| Art25   | [DataClassification] — privacy by design                 |
| Art30   | GdprDataMap.g.cs — Record of Processing Activities       |
| Art32   | [SecurityPolicy] — encryption, access controls           |

## Data Residency
- **Allowed:** eu-west-1, eu-central-1
- **Prohibited:** us-*, ap-*, cn-*
- **Edge caching:** Disabled
- **Transfer basis:** Standard Contractual Clauses (SCCs)

## Accessibility — WCAG AA
- **Scope:** public-pages
- **Audit tool:** axe-core
- **Max violations at launch:** 0

The auditor receives this document. It links each control to the actual method that implements it. The ImplementedBy reference is validated at compile time -- if the method is renamed or deleted, the build breaks.

data-residency-rules.json

{
  "service": "order-service",
  "generated": "2026-04-06T10:00:00Z",
  "rules": {
    "allowedRegions": ["eu-west-1", "eu-central-1"],
    "prohibitedRegions": ["us-*", "ap-*", "cn-*"],
    "allowEdgeCaching": false,
    "transferBasis": "SCCs"
  },
  "enforcement": {
    "terraformValidation": true,
    "runtimeRegionCheck": true,
    "cdnGeoRestriction": true
  }
}

ComplianceValidator.g.cs

// <auto-generated by Ops.Compliance.Generator />
namespace OrderService.Generated;

public sealed class ComplianceValidator : IHostedService
{
    private readonly ILogger<ComplianceValidator> _logger;

    public ComplianceValidator(ILogger<ComplianceValidator> logger)
        => _logger = logger;

    public Task StartAsync(CancellationToken ct)
    {
        var controls = new (string Id, string Desc, ControlStatus Status)[]
        {
            ("CC6.1", "Logical and Physical Access Controls",
                ControlStatus.Implemented),
            ("CC6.2", "System Access Restrictions",
                ControlStatus.Implemented),
            ("CC6.3", "Access Control for Protected Information",
                ControlStatus.Implemented),
            ("CC7.1", "Monitoring for Unauthorized Activity",
                ControlStatus.Implemented),
            ("CC7.2", "Incident Response",
                ControlStatus.PartiallyImplemented),
        };

        var unimplemented = controls
            .Where(c => c.Status is ControlStatus.Planned
                                  or ControlStatus.PartiallyImplemented)
            .ToList();

        if (unimplemented.Count > 0)
        {
            foreach (var c in unimplemented)
            {
                _logger.LogWarning(
                    "Compliance gap: {ControlId} ({Description}) " +
                    "is {Status}",
                    c.Id, c.Desc, c.Status);
            }
        }

        _logger.LogInformation(
            "Compliance check: {Implemented}/{Total} controls " +
            "fully implemented",
            controls.Count(c => c.Status == ControlStatus.Implemented),
            controls.Length);

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
}

Analyzers

ID Severity Rule
CMP001 Error Framework declared with control not mapped by [ComplianceControl]
CMP002 Error Entity deployed in prohibited region
CMP003 Warning Public page without [AccessibilityRequirement]
CMP004 Error Control evidence references nonexistent method

CMP001 -- Unmapped Control

error CMP001: ComplianceFramework 'SOC2' declares required control
'CC8.1' but no [ComplianceControl("CC8.1", ...)] exists. Every required
control must have an evidence mapping.

CMP004 -- Evidence References Nonexistent Method

This is the most valuable analyzer. It catches stale evidence. When a developer renames ConfigureRbac to ConfigureAuthorization, the ImplementedBy = nameof(SecurityConfig.ConfigureRbac) reference breaks at compile time through nameof(). But if someone uses a string literal instead:

error CMP004: ComplianceControl 'CC6.1' references method
'SecurityConfig.ConfigureRbac' via ImplementedBy, but this method
does not exist. Evidence references must point to real implementations.

Part B: Ops.SupplyChain

log4shell happened because nobody tracked transitive dependencies.


The Problem

December 9, 2021. CVE-2021-44228, the Log4Shell vulnerability. Organizations that could produce a Software Bill of Materials (SBOM) knew within hours whether they were affected. Organizations that could not spent days or weeks manually auditing their dependency trees.

Transitive dependencies are invisible. The application has 12 direct NuGet dependencies. Those 12 depend on 147 transitive packages. One of those transitive packages has a critical CVE. The team does not know because they only audit direct dependencies, if they audit at all.

License compliance is a legal minefield. A developer adds a package to speed up JSON serialization. The package is MIT-licensed. But one of its transitive dependencies uses the AGPL license. The company ships proprietary software. Using AGPL code in a proprietary product violates the license. Nobody checks.

Dependency updates are random. Some developers run dotnet outdated occasionally. Some do not. There is no policy. The result: some packages are current, some are 3 major versions behind, and the ones that are behind have known vulnerabilities.

What is missing:

  • Automated SBOM generation. Every build should produce a complete inventory of all dependencies, including transitive ones.
  • License scanning at build time. Prohibited licenses should fail the build.
  • CVE monitoring as a first-class concern. Maximum allowed critical and high CVEs should be declared and enforced.

Attribute Definitions

// =================================================================
// Ops.SupplyChain.Lib -- Supply Chain DSL Attributes
// =================================================================

/// Supported SBOM output formats.
public enum SbomFormat
{
    CycloneDX,      // OWASP CycloneDX (JSON or XML)
    SPDX            // Software Package Data Exchange (SPDX)
}

/// What happens on a policy violation.
public enum ViolationAction
{
    Warn,           // emit warning, do not fail build
    Error,          // fail the build
    Block           // fail the build and block deployment
}

/// Declares dependency vulnerability audit policy.
[AttributeUsage(AttributeTargets.Class)]
public sealed class DependencyAuditAttribute : Attribute
{
    public int MaxCriticalCves { get; }
    public int MaxHighCves { get; }
    public string ScanFrequency { get; }

    public DependencyAuditAttribute(
        int maxCriticalCves,
        int maxHighCves,
        string scanFrequency)
    {
        MaxCriticalCves = maxCriticalCves;
        MaxHighCves = maxHighCves;
        ScanFrequency = scanFrequency;
    }

    /// <summary>CVE database source (e.g., "osv", "nvd", "ghsa").</summary>
    public string CveDatabase { get; init; } = "osv";

    /// <summary>
    /// Packages to exclude from audit (e.g., internal packages).
    /// </summary>
    public string[]? ExcludedPackages { get; init; }

    /// <summary>Action on violation.</summary>
    public ViolationAction OnViolation { get; init; } = ViolationAction.Error;
}

/// Declares SBOM generation requirements.
[AttributeUsage(AttributeTargets.Class)]
public sealed class SbomRequirementAttribute : Attribute
{
    public SbomFormat Format { get; }
    public bool IncludeTransitive { get; }
    public string OutputPath { get; }

    public SbomRequirementAttribute(
        SbomFormat format,
        bool includeTransitive,
        string outputPath)
    {
        Format = format;
        IncludeTransitive = includeTransitive;
        OutputPath = outputPath;
    }

    /// <summary>Include dev dependencies in SBOM.</summary>
    public bool IncludeDevDependencies { get; init; } = false;

    /// <summary>Sign the SBOM with a GPG key.</summary>
    public bool Sign { get; init; } = false;

    /// <summary>Include hash checksums for integrity verification.</summary>
    public bool IncludeHashes { get; init; } = true;
}

/// Declares license policy for dependencies.
[AttributeUsage(AttributeTargets.Class)]
public sealed class LicensePolicyAttribute : Attribute
{
    public string[] Allowed { get; }
    public string[] Prohibited { get; }
    public ViolationAction OnViolation { get; }

    public LicensePolicyAttribute(
        string[] allowed,
        string[] prohibited,
        ViolationAction onViolation)
    {
        Allowed = allowed;
        Prohibited = prohibited;
        OnViolation = onViolation;
    }

    /// <summary>
    /// What to do with unknown licenses (not in allowed or prohibited).
    /// </summary>
    public ViolationAction OnUnknown { get; init; } = ViolationAction.Warn;
}

Usage

[DeploymentApp("order-service")]

// Zero tolerance for critical CVEs, max 3 high, scan daily
[DependencyAudit(
    maxCriticalCves: 0,
    maxHighCves: 3,
    scanFrequency: "daily",
    CveDatabase = "osv",
    OnViolation = ViolationAction.Block)]

// Generate CycloneDX SBOM with transitive dependencies
[SbomRequirement(
    SbomFormat.CycloneDX,
    includeTransitive: true,
    outputPath: "artifacts/sbom.json",
    IncludeHashes = true,
    Sign = true)]

// License policy: permissive licenses only
[LicensePolicy(
    allowed: new[] {
        "MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause",
        "ISC", "Unlicense", "CC0-1.0", "Zlib" },
    prohibited: new[] {
        "GPL-2.0", "GPL-3.0", "AGPL-3.0",
        "LGPL-2.1", "LGPL-3.0", "SSPL-1.0",
        "BSL-1.1", "Elastic-2.0" },
    onViolation: ViolationAction.Error,
    OnUnknown = ViolationAction.Warn)]
public partial class OrderServiceSupplyChain { }

sbom.json (CycloneDX)

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
  "version": 1,
  "metadata": {
    "timestamp": "2026-04-06T10:00:00Z",
    "tools": [
      {
        "vendor": "Ops.SupplyChain",
        "name": "SbomGenerator",
        "version": "1.0.0"
      }
    ],
    "component": {
      "type": "application",
      "name": "order-service",
      "version": "2.4.1"
    }
  },
  "components": [
    {
      "type": "library",
      "name": "Microsoft.EntityFrameworkCore",
      "version": "9.0.3",
      "purl": "pkg:nuget/Microsoft.EntityFrameworkCore@9.0.3",
      "licenses": [{ "license": { "id": "MIT" } }],
      "hashes": [
        {
          "alg": "SHA-256",
          "content": "a1b2c3d4e5f6..."
        }
      ]
    },
    {
      "type": "library",
      "name": "Npgsql",
      "version": "9.0.3",
      "purl": "pkg:nuget/Npgsql@9.0.3",
      "licenses": [{ "license": { "id": "PostgreSQL" } }],
      "hashes": [
        {
          "alg": "SHA-256",
          "content": "f6e5d4c3b2a1..."
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "order-service",
      "dependsOn": [
        "Microsoft.EntityFrameworkCore",
        "Npgsql"
      ]
    },
    {
      "ref": "Microsoft.EntityFrameworkCore",
      "dependsOn": [
        "Microsoft.Extensions.Caching.Memory",
        "Microsoft.Extensions.Logging"
      ]
    }
  ]
}

LicenseAudit.g.cs

// <auto-generated by Ops.SupplyChain.Generator />
namespace OrderService.Generated;

public static class LicenseAudit
{
    private static readonly HashSet<string> Allowed = new(StringComparer.OrdinalIgnoreCase)
    {
        "MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause",
        "ISC", "Unlicense", "CC0-1.0", "Zlib"
    };

    private static readonly HashSet<string> Prohibited = new(StringComparer.OrdinalIgnoreCase)
    {
        "GPL-2.0", "GPL-3.0", "AGPL-3.0",
        "LGPL-2.1", "LGPL-3.0", "SSPL-1.0",
        "BSL-1.1", "Elastic-2.0"
    };

    public static readonly IReadOnlyList<DependencyLicense> Dependencies =
        new DependencyLicense[]
        {
            new("Microsoft.EntityFrameworkCore", "9.0.3", "MIT",
                LicenseStatus.Allowed),
            new("Npgsql", "9.0.3", "PostgreSQL",
                LicenseStatus.Unknown),
            // ... all dependencies enumerated at build time
        };

    /// <summary>
    /// Runs at build time via MSBuild task.
    /// Returns exit code: 0 = pass, 1 = fail.
    /// </summary>
    public static int Validate()
    {
        var violations = new List<string>();
        var warnings = new List<string>();

        foreach (var dep in Dependencies)
        {
            if (Prohibited.Contains(dep.License))
            {
                violations.Add(
                    $"PROHIBITED: {dep.Name}@{dep.Version} " +
                    $"uses {dep.License}");
            }
            else if (!Allowed.Contains(dep.License))
            {
                warnings.Add(
                    $"UNKNOWN: {dep.Name}@{dep.Version} " +
                    $"uses {dep.License} (not in allowed list)");
            }
        }

        foreach (var w in warnings)
            Console.WriteLine($"warning SCH: {w}");

        foreach (var v in violations)
            Console.Error.WriteLine($"error SCH: {v}");

        return violations.Count > 0 ? 1 : 0;
    }
}

public sealed record DependencyLicense(
    string Name, string Version, string License, LicenseStatus Status);

public enum LicenseStatus { Allowed, Prohibited, Unknown }

dependabot.yml

# auto-generated by Ops.SupplyChain.Generator
# Source: OrderServiceSupplyChain [DependencyAudit]
version: 2
updates:
  - package-ecosystem: "nuget"
    directory: "/src/OrderService"
    schedule:
      interval: "daily"       # matches ScanFrequency
    open-pull-requests-limit: 10
    labels:
      - "dependencies"
      - "security"
    reviewers:
      - "platform-team"
    ignore:
      # ExcludedPackages (none configured)
    security-updates-only: false

Container Tier: conftest-policies/soc2.rego

For Container-tier enforcement the same [ComplianceControl] rules are emitted as OPA Rego policies that conftest test docker-compose.yaml evaluates locally during CI. Same rules as the Cloud-tier Gatekeeper Constraints below — but no cluster, no admission controller, no Kubernetes at all. Developers run conftest test against their compose files in seconds.

# <auto-generated by Ops.Compliance.Generator />
# conftest-policies/soc2.rego
# Source: [ComplianceControl] attributes on OrderServiceCompliance

package main

import future.keywords.in

# CC6.1 — Logical and Physical Access Controls
# Every container must run as non-root and drop ALL capabilities.
deny[msg] {
  input.kind == "compose"
  service := input.services[name]
  service.user == null
  msg := sprintf("CC6.1 violation: service '%s' has no 'user:' directive (must run non-root)", [name])
}

deny[msg] {
  input.kind == "compose"
  service := input.services[name]
  not "ALL" in service.cap_drop
  msg := sprintf("CC6.1 violation: service '%s' must declare 'cap_drop: [ALL]'", [name])
}

# CC7.1 — Monitoring for Unauthorized Activity
# Every service must mount the audit log volume.
deny[msg] {
  input.kind == "compose"
  service := input.services[name]
  not contains_audit_volume(service)
  msg := sprintf("CC7.1 violation: service '%s' has no audit log volume mount", [name])
}

contains_audit_volume(service) {
  some v
  v := service.volumes[_]
  endswith(v, ":/var/log/audit:rw")
}

# Data Residency — host filesystem mounts must be within /data/eu-west
deny[msg] {
  input.kind == "compose"
  service := input.services[name]
  some v
  v := service.volumes[_]
  startswith(v, "/")                           # bind mount
  not startswith(v, "/data/eu-west/")
  msg := sprintf("DataResidency violation: service '%s' bind-mounts non-EU path '%s'", [name, v])
}

The exact same SOC2 control IDs (CC6.1, CC7.1) appear in compliance-matrix.md, in the Cloud-tier ConstraintTemplate, and in this Rego file. Single source of truth → three enforcement points.

Container Tier: trivy-compliance.yaml

A per-framework Trivy scan profile generated from [ComplianceFramework]. SOC2, PCI-DSS, and HIPAA differ on which CVE severity is blocking and which CIS Docker Benchmark items are required, so each framework gets its own profile.

# <auto-generated by Ops.Compliance.Generator />
# trivy-compliance.yaml -- Per-framework Trivy scan profiles
# Source: [ComplianceFramework] attributes on OrderServiceCompliance

profiles:
  - name: soc2
    framework: SOC2 Type II
    auditor: Deloitte
    severity:
      block: [CRITICAL, HIGH]
      warn: [MEDIUM]
    checks:
      - cis-docker-benchmark
      - dockerfile-best-practices
    secret-scan: true
    license-scan:
      allowed: [MIT, Apache-2.0, BSD-3-Clause, ISC]
      prohibited: [GPL-3.0, AGPL-3.0]

  - name: gdpr
    framework: GDPR
    severity:
      block: [CRITICAL, HIGH]
      warn: [MEDIUM, LOW]
    checks:
      - data-residency
      - encryption-at-rest
    secret-scan: true
    custom-policies:
      - conftest-policies/gdpr.rego

  - name: pci-dss
    framework: PCI-DSS v4.0
    severity:
      block: [CRITICAL, HIGH, MEDIUM]   # PCI is stricter
    checks:
      - cis-docker-benchmark
      - pci-segmentation
    secret-scan: true
    image-signing: required

CI pipelines call trivy image --compliance soc2 order-api:latest (and the other profiles in parallel) to fail fast before pushing.

Cloud Tier: gatekeeper/constraint-template.yaml

For Kubernetes the same [ComplianceControl] rules become OPA Gatekeeper ConstraintTemplates. The Rego logic is the same as the conftest version above (modulo the K8s vs compose data shape) — the source generator emits both from one DSL declaration.

# <auto-generated by Ops.Compliance.Generator />
# gatekeeper/constraint-template.yaml
# Source: [ComplianceControl("CC6.1")] on OrderServiceCompliance

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: soc2cc61noprivilegedaccess
  annotations:
    ops.compliance/framework: SOC2
    ops.compliance/control: CC6.1
    ops.compliance/source: "OrderServiceCompliance.cs"
spec:
  crd:
    spec:
      names:
        kind: SOC2CC61NoPrivilegedAccess
      validation:
        openAPIV3Schema:
          type: object
          properties:
            allowedCapabilities:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package soc2cc61noprivilegedaccess

        violation[{"msg": msg}] {
          input.review.object.kind == "Pod"
          container := input.review.object.spec.containers[_]
          container.securityContext.runAsNonRoot != true
          msg := sprintf("CC6.1 violation: container '%s' must set runAsNonRoot=true", [container.name])
        }

        violation[{"msg": msg}] {
          input.review.object.kind == "Pod"
          container := input.review.object.spec.containers[_]
          not "ALL" in container.securityContext.capabilities.drop
          msg := sprintf("CC6.1 violation: container '%s' must drop ALL capabilities", [container.name])
        }

Cloud Tier: gatekeeper/constraint.yaml

A concrete Constraint instance generated from [DataResidency] — the rule that pinned the scan profile above to eu-west becomes an admission-controller policy that rejects any PersistentVolume provisioned outside the allowed regions.

# <auto-generated by Ops.Compliance.Generator />
# gatekeeper/constraint.yaml
# Source: [DataResidency] declaration on OrderServiceCompliance

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: GDPRDataResidencyEU
metadata:
  name: order-service-eu-residency
  annotations:
    ops.compliance/source: "OrderServiceCompliance.cs"
    ops.compliance/transferBasis: "SCCs"
spec:
  enforcementAction: deny
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["PersistentVolume", "PersistentVolumeClaim"]
      - apiGroups: ["apps"]
        kinds: ["Deployment", "StatefulSet"]
    namespaces: [orders, orders-staging]
  parameters:
    allowedRegionPrefixes:
      - eu-west-
      - eu-central-
    prohibitedRegionPrefixes:
      - us-
      - ap-
      - cn-
    enforceOnLabel: "topology.kubernetes.io/region"

The allowedRegionPrefixes array matches data-residency-rules.json line 1:1. Three enforcement points (Local doc, Container conftest, Cloud admission controller) — one source declaration.


Analyzers

ID Severity Rule
SCH001 Error Dependency with critical CVE exceeds threshold
SCH002 Error Dependency uses prohibited license
SCH003 Warning Dependency uses unknown license
SCH004 Warning SBOM not generated in CI pipeline

SCH001 -- Critical CVE

error SCH001: Dependency 'Newtonsoft.Json@12.0.1' has critical CVE
CVE-2024-XXXXX (CVSS 9.8). MaxCriticalCves is 0. Update to 13.0.3
or later.

SCH002 -- Prohibited License

error SCH002: Dependency 'SomeLibrary@2.1.0' uses license 'GPL-3.0'
which is in the prohibited list. Remove the dependency or request a
license exception.

Compliance --> DataGovernance

When [ComplianceFramework(ComplianceStandard.GDPR)] is declared, the Compliance DSL checks that the DataGovernance DSL has provided:

  • At least one [GdprDataMap] for each entity that processes personal data.
  • A [RetentionPolicy] for each GDPR-mapped entity.
  • A [DataClassification] for each entity in the system.

If any are missing, the cross-DSL analyzer emits:

warning CMP-DGV001: GDPR framework declared but entity 'PaymentMethod'
has no [GdprDataMap]. Every entity processing personal data must have
a GDPR data map.

Compliance --> Security

SOC2 controls CC6.x (Logical Access) and CC7.x (System Operations) map directly to Security DSL attributes. The cross-DSL analyzer verifies that:

  • CC6.1 has a corresponding [RbacPolicy] or [AuthorizationPolicy].
  • CC7.1 has a corresponding [AuditPolicy].
  • CC7.2 has a corresponding [AlertRoute] with security severity.

The compliance matrix generator includes Security DSL evidence automatically.

SupplyChain --> Compliance

When [ComplianceFramework(ComplianceStandard.SOC2)] is declared, the SupplyChain DSL ensures that:

  • A [DependencyAudit] exists (SOC2 requires vendor management).
  • An [SbomRequirement] exists (SOC2 requires asset inventory).
  • The [LicensePolicy] does not allow licenses that conflict with the company's IP obligations.
warning SCH-CMP001: SOC2 framework declared but no [DependencyAudit]
exists. SOC2 CC3.2 requires vendor and third-party risk management.

The Combined Payoff

The auditor arrives. They ask for:

  1. SOC2 control evidence. You hand them compliance-matrix.md. Every control links to the method that implements it. The links are compile-time verified.

  2. GDPR Record of Processing Activities. You hand them gdpr-data-map.md from the DataGovernance DSL. The Compliance DSL verified it is complete.

  3. Data residency proof. You hand them data-residency-rules.json. The Terraform plan enforces the region constraints.

  4. Software Bill of Materials. You hand them sbom.json. It includes every transitive dependency, with hashes and license identifiers.

  5. License compliance. You hand them the LicenseAudit output. Zero prohibited licenses. Three unknown licenses reviewed and approved.

  6. Vulnerability status. You hand them the DependencyAudit scan results. Zero critical CVEs. Two high CVEs with approved remediation timeline.

Total audit preparation time: zero. The build produces the evidence. The evidence is always current. The spreadsheet is dead.

⬇ Download