Directive

compliance

Directive

Definition

In European Union law, a directive is a legislative instrument that establishes binding objectives that member states must achieve, while granting each state flexibility in choosing the form and methods of implementation through national legislation. This process -- known as transposition -- is what distinguishes directives from regulations: whereas regulations (such as the GDPR, despite being commonly called a "directive") are directly applicable in all member states without national transposition, directives require each member state to enact national laws that achieve the directive's objectives within a specified transposition deadline.

The transposition requirement creates a complex compliance landscape where organizations operating across multiple EU member states must navigate not just the directive itself but also the specific national implementations in each jurisdiction where they operate. National transpositions may impose stricter requirements than the directive mandates (known as "gold-plating"), extend the scope to additional sectors, or interpret ambiguous provisions differently. This jurisdictional complexity is a primary challenge for multinational compliance programs and a rich source of intelligence for OSINT and due diligence operations.

Key cybersecurity and resilience directives currently shaping the European regulatory landscape include the NIS2 Directive (EU 2022/2555) on network and information security, the CER Directive (EU 2022/2557) on critical entity resilience, and the DORA Regulation (EU 2022/2554) on digital operational resilience for the financial sector. While DORA is technically a regulation rather than a directive, it is closely linked to NIS2 and CER in the EU's broader cybersecurity legislative framework. Together, these instruments significantly expand the scope of organizations subject to cybersecurity obligations, introduce harmonized incident reporting requirements, and establish management body accountability for cybersecurity governance.

Core Concepts

EU Legislative Instrument Types

Instrument TypeDirect ApplicabilityNational TranspositionBinding ForceKey Examples
RegulationYes -- applies directly in all member statesNot required (prohibited, in fact)Entirely bindingGDPR, DORA, eIDAS 2.0
DirectiveNo -- requires national transpositionRequired within deadlineBinding as to objectivesNIS2, CER, ePrivacy
DecisionYes -- applies to addresseesNot requiredBinding on addresseesAdequacy decisions
RecommendationNoNot applicableNon-bindingCybersecurity recommendations
OpinionNoNot applicableNon-bindingENISA opinions
InstrumentReferenceTypeScopeTransposition DeadlineKey Requirements
NIS2EU 2022/2555DirectiveEssential & important entities across 18 sectors17 October 2024Risk management, incident reporting (24h/72h), supply chain security, management accountability
CEREU 2022/2557DirectiveCritical entities in 11 sectors17 October 2024Risk assessment, resilience measures, incident notification, background checks
DORAEU 2022/2554RegulationFinancial entities & ICT third-party providers17 January 2025ICT risk management, incident reporting, digital operational resilience testing, third-party risk
GDPREU 2016/679RegulationAll data controllers/processors25 May 2018Data protection principles, consent, breach notification (72h), DPIAs, DPO appointment
ePrivacyEU 2002/58DirectiveElectronic communications providersTransposed (varies)Cookie consent, communication confidentiality, traffic data protection
REDEU 2014/53DirectiveRadio equipment manufacturersCybersecurity requirements from August 2025Cybersecurity for connected devices, personal data protection, fraud prevention

NIS2 Article Structure

Article GroupArticlesSubject MatterCompliance Impact
Scope & DefinitionsArt. 1-6Entities covered, size thresholdsDetermine applicability
National FrameworksArt. 7-13National strategies, CSIRTs, cooperationMember state obligations
Risk ManagementArt. 20-25Security measures, incident handlingDirect entity obligations
ReportingArt. 23Incident notification timelinesOperational procedures
Supply ChainArt. 21(2)(d)Third-party security assessmentProcurement processes
GovernanceArt. 20Management body training & accountabilityBoard-level responsibility
SupervisionArt. 31-37Enforcement, penalties, auditsCompliance risk
PenaltiesArt. 34-36Fines up to EUR 10M or 2% turnoverFinancial exposure

National Transposition Examples

Member StateNIS2 TranspositionReferenceNotable Differences from Directive
Czech RepublicZKB 264/2025 Sb.Zakon o kyberneticke bezpecnostiExtended scope to additional sectors; NUKIB as competent authority
GermanyNIS2UmsuCG (draft)NIS-2-Umsetzungs- und CybersicherheitsstarkungsgesetzBSI expanded role; stricter penalties
FranceTransposition pendingANSSI implementation decreeAdditional sectors; ANSSI supervision
NetherlandsCbw (Cyberbeveiligingswet)Cybersecurity ActNCSC-NL as CSIRT; sector-specific requirements
PolandKSC amendmentKrajowy System CyberbezpieczenstwaExtended to public administration entities

Directive vs Regulation Impact on Compliance

Compliance DimensionDirective (e.g., NIS2)Regulation (e.g., GDPR)
Legal text to followNational transposition lawEU regulation directly
Cross-border consistencyVaries by member stateUniform across EU
Compliance gap analysisMust check each national lawSingle gap analysis applicable
Enforcement authorityNational competent authorityNational DPA (but harmonized)
Penalty frameworkSet by national law (within directive limits)Directly specified (4%/EUR 20M)
Update cycleRequires re-transpositionDirectly effective

Technical Deep Dive

Compliance Assessment Architecture

Automated directive compliance assessment requires a multi-layered architecture that handles the inherent complexity of directive-based regulation: the directive itself defines objectives, national transpositions define specific requirements, and organizational compliance must be measured against the applicable national law.

EU Directive (NIS2)
    |
    +-- National Transposition (ZKB 264/2025)
    |       |
    |       +-- Specific Requirements (technical measures, incident reporting)
    |       |       |
    |       |       +-- Controls (implemented technical and organizational measures)
    |       |               |
    |       |               +-- Evidence (logs, configurations, policies, test results)
    |       |
    |       +-- Sector-Specific Requirements
    |               |
    |               +-- Controls + Evidence
    |
    +-- National Transposition (NIS2UmsuCG)
            |
            +-- (same structure, different requirements)

The assessment engine must support:

  1. Multi-directive assessment -- evaluating compliance against multiple directives simultaneously
  2. Multi-jurisdiction awareness -- mapping the same directive to different national transpositions
  3. Requirement decomposition -- breaking high-level directive articles into specific, assessable controls
  4. Evidence collection -- automated and manual evidence gathering linked to specific requirements
  5. Gap analysis -- identifying non-compliant and partially compliant areas with remediation guidance
  6. Continuous monitoring -- ongoing compliance posture tracking rather than point-in-time assessment

NIS2 Incident Reporting Timeline

PhaseDeadlineContent RequiredChannel
Early Warning24 hours from awarenessSuspected significant incident; initial impact assessmentNational CSIRT
Incident Notification72 hours from awarenessSeverity, impact, cross-border effectsNational CSIRT
Intermediate ReportUpon CSIRT requestStatus update, containment measuresNational CSIRT
Final Report1 month after notificationRoot cause, mitigation, cross-border impactNational CSIRT
Progress ReportIf incident ongoingUpdated timeline and measuresNational CSIRT

Usage in Prismatic Platform

The Prismatic Perimeter module implements automated compliance assessment against EU directives, with particular depth for the NIS2 Directive and the Czech ZKB 264/2025 Sb. transposition.

Directive Compliance Assessment Engine

defmodule PrismaticPerimeter.Compliance.DirectiveAssessor do
  @moduledoc """
  Automated compliance assessment engine that evaluates organizational
  posture against EU directive requirements and their national transpositions.

  Supports multi-directive, multi-jurisdiction assessment with requirement
  decomposition, evidence linkage, and remediation guidance. The engine
  operates as a component within the broader Perimeter compliance framework.

  ## Supported Directives

    - **NIS2** (EU 2022/2555) -- Network and Information Security
    - **ZKB** (264/2025 Sb.) -- Czech NIS2 transposition
    - **GDPR** (EU 2016/679) -- General Data Protection Regulation
    - **DORA** (EU 2022/2554) -- Digital Operational Resilience Act
    - **CER** (EU 2022/2557) -- Critical Entities Resilience

  ## Assessment Flow

    1. Determine applicable directives based on entity classification
    2. Load requirement sets for each applicable directive/transposition
    3. Evaluate each requirement against available evidence and controls
    4. Calculate compliance scores per directive and overall
    5. Generate gap analysis with prioritized remediation recommendations

  ## Examples

      iex> DirectiveAssessor.assess("example.cz", [:nis2, :zkb])
      {:ok, [%{directive: :nis2, score: 0.72, status: :partial}, ...]}

      iex> DirectiveAssessor.classify_entity("energy-provider.cz")
      {:ok, %{sector: :energy, category: :essential, directives: [:nis2, :cer]}}
  """

  require Logger

  @type directive :: :nis2 | :zkb | :gdpr | :dora | :cer
  @type compliance_status :: :compliant | :partial | :non_compliant | :not_assessed

  @type requirement :: %{
    id: String.t(),
    article: String.t(),
    description: String.t(),
    status: compliance_status(),
    evidence: list(String.t()),
    remediation: String.t() | nil,
    priority: :critical | :high | :medium | :low,
    category: :technical | :organizational | :governance
  }

  @type assessment :: %{
    directive: directive(),
    jurisdiction: String.t(),
    assessed_at: DateTime.t(),
    overall_status: compliance_status(),
    requirements: list(requirement()),
    score: float(),
    gap_count: non_neg_integer(),
    critical_gaps: list(requirement()),
    remediation_plan: list(map())
  }

  @type entity_classification :: %{
    domain: String.t(),
    sector: atom(),
    category: :essential | :important | :out_of_scope,
    size: :large | :medium | :small | :micro,
    applicable_directives: list(directive()),
    applicable_jurisdictions: list(String.t())
  }

  @doc """
  Performs comprehensive compliance assessment against specified directives.

  Evaluates the target domain against all requirements in each specified
  directive, collecting evidence, scoring compliance, and generating
  a prioritized remediation plan for identified gaps.

  ## Parameters

    - `domain` - Target domain to assess
    - `directives` - List of directives to assess against
    - `opts` - Assessment options
      - `:jurisdiction` - Specific jurisdiction (default: auto-detect from domain TLD)
      - `:depth` - Assessment depth (:quick | :standard | :comprehensive)
      - `:evidence_sources` - Additional evidence sources to consult

  ## Returns

    - `{:ok, list(assessment())}` - Assessment results per directive
    - `{:error, term()}` - Assessment execution failure
  """
  @spec assess(String.t(), list(directive()), keyword()) ::
    {:ok, list(assessment())} | {:error, term()}
  def assess(domain, directives, opts \\ []) do
    jurisdiction = Keyword.get(opts, :jurisdiction, detect_jurisdiction(domain))
    depth = Keyword.get(opts, :depth, :standard)

    assessments = Enum.map(directives, fn directive ->
      requirements = get_requirements(directive, jurisdiction)
      evaluated = Enum.map(requirements, &evaluate_requirement(&1, domain, depth))

      score = calculate_compliance_score(evaluated)
      gaps = Enum.filter(evaluated, &(&1.status in [:non_compliant, :not_assessed]))
      critical_gaps = Enum.filter(gaps, &(&1.priority == :critical))

      overall = cond do
        score >= 0.8 -> :compliant
        score >= 0.5 -> :partial
        true -> :non_compliant
      end

      assessment = %{
        directive: directive,
        jurisdiction: jurisdiction,
        assessed_at: DateTime.utc_now(),
        overall_status: overall,
        requirements: evaluated,
        score: score,
        gap_count: length(gaps),
        critical_gaps: critical_gaps,
        remediation_plan: generate_remediation_plan(gaps)
      }

      :telemetry.execute(
        [:prismatic, :perimeter, :compliance, :assessment],
        %{score: score, gap_count: length(gaps)},
        %{domain: domain, directive: directive, jurisdiction: jurisdiction}
      )

      Logger.info("Directive assessment completed",
        domain: domain,
        directive: directive,
        score: score,
        gap_count: length(gaps),
        critical_gap_count: length(critical_gaps)
      )

      assessment
    end)

    {:ok, assessments}
  end

  @doc """
  Classifies an entity to determine which directives apply.

  Based on the entity's sector, size, and jurisdiction, determines
  which EU directives and national transpositions are applicable.
  NIS2 applies to essential and important entities in 18 sectors;
  CER applies to critical entities in 11 sectors.

  ## Parameters

    - `domain` - Domain of the entity to classify
    - `opts` - Classification options
      - `:sector` - Override automatic sector detection
      - `:employee_count` - Entity size for threshold determination
      - `:annual_revenue` - Revenue for threshold determination

  ## Returns

    - `{:ok, entity_classification()}` - Classification result
    - `{:error, :insufficient_data}` - Cannot determine classification
  """
  @spec classify_entity(String.t(), keyword()) ::
    {:ok, entity_classification()} | {:error, term()}
  def classify_entity(domain, opts \\ []) do
    sector = Keyword.get(opts, :sector, detect_sector(domain))
    size = determine_size(opts)
    jurisdiction = detect_jurisdiction(domain)

    category = determine_nis2_category(sector, size)
    directives = determine_applicable_directives(sector, category)

    {:ok, %{
      domain: domain,
      sector: sector,
      category: category,
      size: size,
      applicable_directives: directives,
      applicable_jurisdictions: [jurisdiction]
    }}
  end

  @doc """
  Generates a compliance comparison report across multiple jurisdictions.

  Useful for multinational organizations that need to understand how
  the same directive is implemented differently across member states.

  ## Parameters

    - `directive` - The EU directive to compare
    - `jurisdictions` - List of jurisdiction codes to compare

  ## Returns

    - `{:ok, comparison_report}` - Cross-jurisdiction comparison
  """
  @spec compare_jurisdictions(directive(), list(String.t())) :: {:ok, map()}
  def compare_jurisdictions(directive, jurisdictions) do
    comparisons = Enum.map(jurisdictions, fn jurisdiction ->
      requirements = get_requirements(directive, jurisdiction)
      %{
        jurisdiction: jurisdiction,
        requirement_count: length(requirements),
        transposition_reference: get_transposition_reference(directive, jurisdiction),
        competent_authority: get_competent_authority(directive, jurisdiction),
        additional_requirements: get_gold_plating(directive, jurisdiction)
      }
    end)

    {:ok, %{
      directive: directive,
      jurisdictions: comparisons,
      compared_at: DateTime.utc_now()
    }}
  end

  # -- Private Functions --

  defp get_requirements(:nis2, _jurisdiction) do
    [
      %{id: "NIS2-21-1", article: "Article 21(1)", description: "Cybersecurity risk management measures",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :governance},
      %{id: "NIS2-21-2a", article: "Article 21(2)(a)", description: "Risk analysis and information security policies",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :organizational},
      %{id: "NIS2-21-2b", article: "Article 21(2)(b)", description: "Incident handling procedures",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :technical},
      %{id: "NIS2-21-2c", article: "Article 21(2)(c)", description: "Business continuity and crisis management",
        status: :not_assessed, evidence: [], remediation: nil, priority: :high, category: :organizational},
      %{id: "NIS2-21-2d", article: "Article 21(2)(d)", description: "Supply chain security assessment",
        status: :not_assessed, evidence: [], remediation: nil, priority: :high, category: :governance},
      %{id: "NIS2-21-2e", article: "Article 21(2)(e)", description: "Network and information system security",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :technical},
      %{id: "NIS2-23-1", article: "Article 23(1)", description: "Significant incident notification within 24 hours",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :organizational},
      %{id: "NIS2-23-2", article: "Article 23(2)", description: "Full incident notification within 72 hours",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :organizational},
      %{id: "NIS2-20-1", article: "Article 20(1)", description: "Management body cybersecurity training",
        status: :not_assessed, evidence: [], remediation: nil, priority: :high, category: :governance},
      %{id: "NIS2-21-2j", article: "Article 21(2)(j)", description: "Multi-factor authentication and encryption",
        status: :not_assessed, evidence: [], remediation: nil, priority: :high, category: :technical}
    ]
  end

  defp get_requirements(:zkb, _jurisdiction) do
    get_requirements(:nis2, "CZ") ++
      [
        %{id: "ZKB-NUKIB-1", article: "Section 4", description: "NUKIB registration obligation",
          status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :governance}
      ]
  end

  defp get_requirements(:cer, _jurisdiction) do
    [
      %{id: "CER-12-1", article: "Article 12(1)", description: "Risk assessment for critical entity resilience",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :governance},
      %{id: "CER-13-1", article: "Article 13(1)", description: "Technical, security, and organizational resilience measures",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :technical},
      %{id: "CER-15-1", article: "Article 15(1)", description: "Incident notification without undue delay",
        status: :not_assessed, evidence: [], remediation: nil, priority: :critical, category: :organizational}
    ]
  end

  defp get_requirements(:gdpr, _jurisdiction), do: []
  defp get_requirements(:dora, _jurisdiction), do: []

  defp evaluate_requirement(req, _domain, _depth) do
    %{req | status: :not_assessed}
  end

  defp calculate_compliance_score(requirements) do
    if requirements == [] do
      0.0
    else
      compliant = Enum.count(requirements, &(&1.status == :compliant))
      partial = Enum.count(requirements, &(&1.status == :partial))
      total = length(requirements)
      (compliant + partial * 0.5) / max(total, 1)
    end
  end

  defp generate_remediation_plan(gaps) do
    gaps
    |> Enum.sort_by(fn gap ->
      case gap.priority do
        :critical -> 0
        :high -> 1
        :medium -> 2
        :low -> 3
      end
    end)
    |> Enum.map(fn gap ->
      %{
        requirement_id: gap.id,
        priority: gap.priority,
        description: gap.description,
        recommended_actions: generate_actions(gap),
        estimated_effort: estimate_effort(gap)
      }
    end)
  end

  defp generate_actions(gap) do
    ["Review #{gap.article} requirements", "Implement #{gap.category} controls", "Document evidence"]
  end

  defp estimate_effort(%{priority: :critical}), do: "1-2 weeks"
  defp estimate_effort(%{priority: :high}), do: "2-4 weeks"
  defp estimate_effort(%{priority: :medium}), do: "1-2 months"
  defp estimate_effort(%{priority: :low}), do: "2-3 months"

  defp detect_jurisdiction(domain) do
    tld = domain |> String.split(".") |> List.last() |> String.downcase()
    case tld do
      "cz" -> "CZ"
      "de" -> "DE"
      "fr" -> "FR"
      "nl" -> "NL"
      "pl" -> "PL"
      _ -> "EU"
    end
  end

  defp detect_sector(_domain), do: :digital_infrastructure
  defp determine_size(opts) do
    count = Keyword.get(opts, :employee_count, 0)
    cond do
      count >= 250 -> :large
      count >= 50 -> :medium
      count >= 10 -> :small
      true -> :micro
    end
  end

  defp determine_nis2_category(sector, size) when sector in [:energy, :transport, :health, :digital_infrastructure] and size in [:large, :medium], do: :essential
  defp determine_nis2_category(_sector, size) when size in [:large, :medium], do: :important
  defp determine_nis2_category(_sector, _size), do: :out_of_scope

  defp determine_applicable_directives(sector, :out_of_scope), do: []
  defp determine_applicable_directives(sector, _category) do
    base = [:nis2]
    if sector in [:energy, :transport, :health, :water, :digital_infrastructure] do
      base ++ [:cer]
    else
      base
    end
  end

  defp get_transposition_reference(:nis2, "CZ"), do: "ZKB 264/2025 Sb."
  defp get_transposition_reference(:nis2, "DE"), do: "NIS2UmsuCG"
  defp get_transposition_reference(directive, jurisdiction), do: "#{directive}-#{jurisdiction}"

  defp get_competent_authority(:nis2, "CZ"), do: "NUKIB"
  defp get_competent_authority(:nis2, "DE"), do: "BSI"
  defp get_competent_authority(:nis2, "FR"), do: "ANSSI"
  defp get_competent_authority(_directive, _jurisdiction), do: "Unknown"

  defp get_gold_plating(_directive, _jurisdiction), do: []
end

Common Pitfalls

PitfallDescriptionImpactMitigation
Directive-Regulation ConfusionTreating directives as directly applicable like regulationsWrong legal text applied; compliance gapsAlways identify the applicable national transposition, not just the EU directive
Single-Jurisdiction AssumptionAssessing against one national transposition for multinational operationsNon-compliance in other member statesMap all operating jurisdictions and assess against each applicable transposition
Scope MisclassificationIncorrectly determining entity classification (essential vs important)Wrong requirements applied; under- or over-complianceUse formal sector and size threshold analysis per NIS2 Annex I/II
Transposition Deadline BlindnessAssuming directive is not yet applicable because transposition is pendingMember states may enforce directive objectives even before transpositionTrack both directive deadline and national transposition status
Article-Level AssessmentAssessing compliance at the article level without decomposing into controlsSuperficial compliance that misses specific technical requirementsDecompose each article into specific, assessable technical and organizational controls
Gold-Plating IgnoranceNot checking for stricter national requirements beyond the directiveNon-compliance with national additionsCompare national transposition against directive to identify additional obligations
Static AssessmentPoint-in-time compliance assessment without continuous monitoringCompliance drift between assessment cyclesImplement continuous compliance monitoring with alerting
Incident Timeline ConfusionMixing up NIS2 24h/72h deadlines with GDPR 72h deadlineLate notification triggering regulatory penaltiesMaintain separate incident notification workflows per directive
Management Accountability GapNot tracking NIS2 Article 20 management body training requirementsPersonal liability exposure for board membersTrack management cybersecurity training completion and certification
Supply Chain BlindnessIgnoring NIS2 Article 21(2)(d) supply chain security requirementsCompliance gap in third-party risk managementIntegrate directive requirements into vendor assessment workflows

Best Practices

  1. Map directive requirements to technical controls -- translate legal language into specific, measurable technical implementations that can be assessed and evidenced automatically.

  2. Automate compliance monitoring -- manual compliance assessment is point-in-time and rapidly becomes stale; continuous monitoring provides ongoing assurance and early gap detection.

  3. Track national transpositions per jurisdiction -- directives are implemented differently in each member state; maintain a registry of applicable national laws for each operating jurisdiction.

  4. Document evidence of compliance -- automated evidence collection supports audit readiness and regulatory inquiries; link evidence to specific directive requirements.

  5. Monitor directive evolution -- new directives and amendments regularly expand compliance obligations; subscribe to EUR-Lex notifications and ENISA guidance publications.

  6. Classify entities accurately -- NIS2 scope determination is based on sector (Annex I/II) and size thresholds; incorrect classification leads to wrong requirements.

  7. Implement parallel incident reporting -- maintain separate notification workflows for each applicable directive (NIS2 24h/72h, GDPR 72h, DORA 4h) to meet different deadlines.

  8. Track management body obligations -- NIS2 Article 20 requires management bodies to undergo cybersecurity training; track completion and schedule renewal.

  9. Assess supply chain compliance -- NIS2 Article 21(2)(d) requires supply chain security assessment; integrate directive requirements into vendor management processes.

  10. Emit telemetry for compliance operations -- instrument all assessment, classification, and reporting operations with :telemetry.execute/3 for monitoring compliance program effectiveness.

  • GDPR -- EU regulation (not directive) for data protection, often assessed alongside NIS2
  • NIS2 -- Network and Information Security Directive, the primary EU cybersecurity directive
  • EASM -- External attack surface management supporting directive compliance assessment
  • ISO 27001 -- Information security standard aligned with NIS2 risk management requirements
  • Incident Reporting -- Mandatory notification obligations under NIS2, CER, and DORA
  • Data Controller -- GDPR role with directive-intersecting compliance obligations
  • Compliance -- Broader regulatory compliance framework encompassing directive requirements
  • Critical Infrastructure -- Entities subject to CER and NIS2 essential entity classification
  • Risk Management -- Core requirement across NIS2, CER, and DORA
  • Certification -- ISO 27001 certification as evidence of NIS2 compliance
  • Regulation -- Directly applicable EU legislative instrument (contrast with directive)
  • CER -- Critical Entities Resilience Directive for physical and cyber resilience

See Also

  • Capabilities -- Compliance assessment and directive mapping capabilities
  • Architecture -- Compliance framework architecture and Perimeter integration
  • OSINT Tools -- Regulatory intelligence tools for directive monitoring
  • Technologies -- Compliance automation technologies and frameworks

Connect & Contribute

Created by Tomas Korcak (korczis) | Open Source under GHL