Signet Forge 0.1.1
C++20 Parquet library with AI-native extensions
DEMO
Loading...
Searching...
No Matches
regulatory_monitor.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright 2026 Johnson Ogundeji
3// See LICENSE_COMMERCIAL for full terms.
4#pragma once
5
6#if !defined(SIGNET_ENABLE_COMMERCIAL) || !SIGNET_ENABLE_COMMERCIAL
7#error "signet/ai/regulatory_monitor.hpp requires SIGNET_ENABLE_COMMERCIAL=ON (AGPL-3.0 commercial tier). See LICENSE_COMMERCIAL."
8#endif
9
10// ---------------------------------------------------------------------------
11// regulatory_monitor.hpp -- Regulatory Change Monitoring Framework
12//
13// Gap R-20: Regulatory change monitoring for compliance lifecycle management.
14//
15// Provides a structured registry for tracking regulatory changes and their
16// impact on the system, conforming to:
17// - DORA Art.5(6): Ongoing regulatory landscape monitoring
18// - EU AI Act Art.61: Post-market monitoring obligations
19// - MiFID II Art.16(3): Organizational requirements — ongoing compliance
20// - ISO 27001 A.18.1: Identification of applicable legislation
21//
22// Components:
23// - RegulatoryChangeType / ImpactLevel / ComplianceStatus enums
24// - RegulatoryChange: individual change record
25// - RegulatoryChangeMonitor: registry + assessment tracker
26//
27// Header-only. Part of the signet::forge AI module.
28// ---------------------------------------------------------------------------
29
30#include "signet/error.hpp"
31
32#include <cstdint>
33#include <stdexcept>
34#include <mutex>
35#include <string>
36#include <unordered_map>
37#include <vector>
38
39namespace signet::forge {
40
41// ---------------------------------------------------------------------------
42// Enumerations
43// ---------------------------------------------------------------------------
44
46enum class RegulatoryChangeType : int32_t {
47 NEW_REGULATION = 0,
48 AMENDMENT = 1,
49 GUIDANCE = 2,
51 ENFORCEMENT = 4,
52 DEPRECATION = 5
53};
54
56enum class RegulatoryImpact : int32_t {
57 NONE = 0,
58 INFORMATIONAL = 1,
59 LOW = 2,
60 MEDIUM = 3,
61 HIGH = 4,
62 CRITICAL = 5
63};
64
66enum class ChangeComplianceStatus : int32_t {
67 NOT_ASSESSED = 0,
68 ASSESSED = 1,
69 IN_PROGRESS = 2,
70 IMPLEMENTED = 3,
71 VERIFIED = 4,
73};
74
75// ---------------------------------------------------------------------------
76// RegulatoryChange
77// ---------------------------------------------------------------------------
78
82 std::string change_id;
83 std::string regulation;
84 std::string title;
85 std::string description;
89
90 std::string effective_date;
91 std::string assessment_date;
92 std::string completion_date;
93 std::string assessor;
94 std::string owner;
95
96 std::vector<std::string> affected_modules;
97 std::vector<std::string> action_items;
98 std::vector<std::string> references;
99};
100
101// ---------------------------------------------------------------------------
102// RegulatoryChangeMonitor
103// ---------------------------------------------------------------------------
104
111public:
113 explicit RegulatoryChangeMonitor(const std::string& org_id = "")
114 : org_id_(org_id) {
115 auto gate = commercial::require_feature("RegulatoryChangeMonitor");
116 if (!gate) throw std::runtime_error(gate.error().message);
117 }
118
120 : org_id_(std::move(other.org_id_))
121 , changes_(std::move(other.changes_)) {}
123 if (this != &other) {
124 org_id_ = std::move(other.org_id_);
125 changes_ = std::move(other.changes_);
126 }
127 return *this;
128 }
131
133 void track_change(const RegulatoryChange& change) {
134 std::lock_guard<std::mutex> lock(mutex_);
135 changes_[change.change_id] = change;
136 }
137
140 const std::string& change_id,
141 ChangeComplianceStatus new_status)
142 {
143 std::lock_guard<std::mutex> lock(mutex_);
144 auto it = changes_.find(change_id);
145 if (it == changes_.end()) {
147 "Regulatory change not found: " + change_id};
148 }
149 it->second.status = new_status;
150 return {};
151 }
152
155 const std::string& change_id,
156 RegulatoryImpact impact,
157 const std::string& assessor,
158 const std::string& assessment_date)
159 {
160 std::lock_guard<std::mutex> lock(mutex_);
161 auto it = changes_.find(change_id);
162 if (it == changes_.end()) {
164 "Regulatory change not found: " + change_id};
165 }
166 it->second.impact = impact;
167 it->second.assessor = assessor;
168 it->second.assessment_date = assessment_date;
169 if (it->second.status == ChangeComplianceStatus::NOT_ASSESSED)
170 it->second.status = ChangeComplianceStatus::ASSESSED;
171 return {};
172 }
173
175 [[nodiscard]] expected<RegulatoryChange> lookup(const std::string& change_id) const {
176 std::lock_guard<std::mutex> lock(mutex_);
177 auto it = changes_.find(change_id);
178 if (it == changes_.end()) {
180 "Regulatory change not found: " + change_id};
181 }
182 return it->second;
183 }
184
186 [[nodiscard]] std::vector<RegulatoryChange> all_changes() const {
187 std::lock_guard<std::mutex> lock(mutex_);
188 std::vector<RegulatoryChange> out;
189 out.reserve(changes_.size());
190 for (const auto& [_, c] : changes_) out.push_back(c);
191 return out;
192 }
193
195 [[nodiscard]] std::vector<RegulatoryChange> changes_for_regulation(
196 const std::string& regulation) const
197 {
198 std::lock_guard<std::mutex> lock(mutex_);
199 std::vector<RegulatoryChange> out;
200 for (const auto& [_, c] : changes_) {
201 if (c.regulation == regulation) out.push_back(c);
202 }
203 return out;
204 }
205
207 [[nodiscard]] std::vector<RegulatoryChange> pending_changes() const {
208 std::lock_guard<std::mutex> lock(mutex_);
209 std::vector<RegulatoryChange> out;
210 for (const auto& [_, c] : changes_) {
211 if (c.status != ChangeComplianceStatus::VERIFIED &&
213 out.push_back(c);
214 }
215 }
216 return out;
217 }
218
220 [[nodiscard]] std::vector<RegulatoryChange> changes_above_impact(
221 RegulatoryImpact threshold) const
222 {
223 std::lock_guard<std::mutex> lock(mutex_);
224 std::vector<RegulatoryChange> out;
225 for (const auto& [_, c] : changes_) {
226 if (c.impact >= threshold) out.push_back(c);
227 }
228 return out;
229 }
230
232 [[nodiscard]] size_t size() const {
233 std::lock_guard<std::mutex> lock(mutex_);
234 return changes_.size();
235 }
236
238 [[nodiscard]] size_t pending_count() const {
239 std::lock_guard<std::mutex> lock(mutex_);
240 size_t n = 0;
241 for (const auto& [_, c] : changes_) {
242 if (c.status != ChangeComplianceStatus::VERIFIED &&
244 ++n;
245 }
246 }
247 return n;
248 }
249
251 [[nodiscard]] const std::string& org_id() const { return org_id_; }
252
255 const std::string& org_id = "SIGNET")
256 {
258
259 // DORA — effective January 17, 2025
261 "RC-DORA-2025", "DORA",
262 "Digital Operational Resilience Act enters into force",
263 "Regulation (EU) 2022/2554 — ICT risk management, incident reporting, "
264 "resilience testing, third-party risk management for financial entities.",
268 "2025-01-17", "2024-06-01", "2025-12-01", "Security Team", "Engineering",
269 {"ai/compliance/", "ai/incident_response.hpp", "ai/human_oversight.hpp"},
270 {"Implement DORA Art.5-19 compliance modules",
271 "ICT incident management", "Resilience testing framework"},
272 {"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022R2554"}
273 });
274
275 // EU AI Act — phased effective dates 2024-2027
277 "RC-EUAIA-2024", "EU AI Act",
278 "EU Artificial Intelligence Act phased implementation",
279 "Regulation (EU) 2024/1689 — risk-based AI regulation. "
280 "Art.6 high-risk classification, Art.9 risk management, "
281 "Art.11 technical documentation, Art.12 record-keeping, "
282 "Art.13 transparency, Art.14 human oversight, Art.62 incident reporting.",
286 "2026-08-02", "2024-08-01", "2026-01-15", "Compliance", "Engineering",
287 {"ai/compliance/eu_ai_act_reporter.hpp", "ai/human_oversight.hpp",
288 "ai/decision_log.hpp", "ai/inference_log.hpp"},
289 {"Implement Art.12/13/19 compliance reporters",
290 "Human oversight with stop button (Art.14)",
291 "Training data provenance logging"},
292 {"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689"}
293 });
294
295 // NIST SP 800-227 — finalized 2025
297 "RC-NIST-800-227", "NIST SP 800-227",
298 "NIST SP 800-227 recommendations for Parquet encryption",
299 "Recommendations for key management in column-oriented data formats. "
300 "Covers AES-256-GCM, key hierarchy (DEK/KEK), rotation schedules.",
304 "2025-03-15", "2025-04-01", "2025-11-01", "Crypto Team", "Engineering",
305 {"crypto/pme.hpp", "crypto/key_metadata.hpp", "crypto/aes_gcm.hpp"},
306 {"Verify AES-256-GCM compliance", "Document key hierarchy"},
307 {"NIST SP 800-227"}
308 });
309
310 return mon;
311 }
312
313private:
314 std::string org_id_;
315 std::unordered_map<std::string, RegulatoryChange> changes_;
316 mutable std::mutex mutex_;
317};
318
319} // namespace signet::forge
Registry and tracker for regulatory changes affecting the system.
RegulatoryChangeMonitor & operator=(const RegulatoryChangeMonitor &)=delete
std::vector< RegulatoryChange > pending_changes() const
Get all changes that still require action (not VERIFIED or NOT_APPLICABLE).
void track_change(const RegulatoryChange &change)
Register a new regulatory change for tracking.
RegulatoryChangeMonitor(const std::string &org_id="")
Construct a monitor with an organization identifier.
expected< RegulatoryChange > lookup(const std::string &change_id) const
Look up a specific change by ID.
RegulatoryChangeMonitor(const RegulatoryChangeMonitor &)=delete
RegulatoryChangeMonitor(RegulatoryChangeMonitor &&other) noexcept
std::vector< RegulatoryChange > changes_above_impact(RegulatoryImpact threshold) const
Get changes by impact level (at or above threshold).
static RegulatoryChangeMonitor signet_defaults(const std::string &org_id="SIGNET")
Build a monitor pre-populated with known regulatory changes for Signet.
size_t size() const
Number of tracked changes.
expected< void > assess_impact(const std::string &change_id, RegulatoryImpact impact, const std::string &assessor, const std::string &assessment_date)
Update the impact assessment for a tracked change.
std::vector< RegulatoryChange > changes_for_regulation(const std::string &regulation) const
Get changes filtered by regulation name.
expected< void > update_status(const std::string &change_id, ChangeComplianceStatus new_status)
Update the status of a tracked change.
size_t pending_count() const
Count of changes still pending action.
RegulatoryChangeMonitor & operator=(RegulatoryChangeMonitor &&other) noexcept
const std::string & org_id() const
Organization identifier.
std::vector< RegulatoryChange > all_changes() const
Get all tracked changes.
A lightweight result type that holds either a success value of type T or an Error.
Definition error.hpp:143
ChangeComplianceStatus
Compliance status for a tracked regulatory change.
@ VERIFIED
Compliance verified by review/testing.
@ NOT_ASSESSED
Impact assessment not yet performed.
@ ASSESSED
Impact assessed, action plan pending.
@ IN_PROGRESS
Implementation underway.
@ NOT_APPLICABLE
Change does not apply to this system.
RegulatoryChangeType
Type of regulatory change being tracked.
@ GUIDANCE
Supervisory guidance or interpretation.
@ DEPRECATION
Regulation repealed or superseded.
@ TECHNICAL_STANDARD
RTS/ITS (Regulatory/Implementing Technical Standards)
@ NEW_REGULATION
Entirely new regulation enacted.
@ ENFORCEMENT
Enforcement action or precedent.
@ AMENDMENT
Existing regulation amended.
RegulatoryImpact
Impact level of a regulatory change on the system.
@ LOW
Minor documentation update.
@ CRITICAL
Immediate action required (compliance deadline)
@ HIGH
Significant architectural changes.
@ MEDIUM
Code/configuration changes required.
@ INFORMATIONAL
Awareness only, no action needed.
@ INVALID_ARGUMENT
A caller-supplied argument is outside the valid range or violates a precondition.
Lightweight error value carrying an ErrorCode and a human-readable message.
Definition error.hpp:99
A tracked regulatory change record.
std::string regulation
Regulation name (e.g., "DORA", "EU AI Act")
std::string effective_date
When the change takes effect (ISO 8601)
std::string assessor
Who performed the impact assessment.
std::vector< std::string > affected_modules
Signet modules impacted.
std::string title
Short description of the change.
std::string assessment_date
When impact was assessed (ISO 8601)
std::vector< std::string > action_items
Required implementation steps.
std::string completion_date
When implementation was completed (ISO 8601)
std::string change_id
Unique identifier (e.g., "RC-2026-001")
std::vector< std::string > references
External references (URLs, docs)
std::string description
Detailed change narrative.
std::string owner
Responsible team/individual.