Signet Forge 0.1.0
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 <mutex>
34#include <string>
35#include <unordered_map>
36#include <vector>
37
38namespace signet::forge {
39
40// ---------------------------------------------------------------------------
41// Enumerations
42// ---------------------------------------------------------------------------
43
45enum class RegulatoryChangeType : int32_t {
46 NEW_REGULATION = 0,
47 AMENDMENT = 1,
48 GUIDANCE = 2,
50 ENFORCEMENT = 4,
51 DEPRECATION = 5
52};
53
55enum class RegulatoryImpact : int32_t {
56 NONE = 0,
57 INFORMATIONAL = 1,
58 LOW = 2,
59 MEDIUM = 3,
60 HIGH = 4,
61 CRITICAL = 5
62};
63
65enum class ChangeComplianceStatus : int32_t {
66 NOT_ASSESSED = 0,
67 ASSESSED = 1,
68 IN_PROGRESS = 2,
69 IMPLEMENTED = 3,
70 VERIFIED = 4,
72};
73
74// ---------------------------------------------------------------------------
75// RegulatoryChange
76// ---------------------------------------------------------------------------
77
81 std::string change_id;
82 std::string regulation;
83 std::string title;
84 std::string description;
88
89 std::string effective_date;
90 std::string assessment_date;
91 std::string completion_date;
92 std::string assessor;
93 std::string owner;
94
95 std::vector<std::string> affected_modules;
96 std::vector<std::string> action_items;
97 std::vector<std::string> references;
98};
99
100// ---------------------------------------------------------------------------
101// RegulatoryChangeMonitor
102// ---------------------------------------------------------------------------
103
110public:
112 explicit RegulatoryChangeMonitor(const std::string& org_id = "")
113 : org_id_(org_id) {
114 (void)commercial::require_feature("RegulatoryChangeMonitor");
115 }
116
118 : org_id_(std::move(other.org_id_))
119 , changes_(std::move(other.changes_)) {}
121 if (this != &other) {
122 org_id_ = std::move(other.org_id_);
123 changes_ = std::move(other.changes_);
124 }
125 return *this;
126 }
129
131 void track_change(const RegulatoryChange& change) {
132 std::lock_guard<std::mutex> lock(mutex_);
133 changes_[change.change_id] = change;
134 }
135
138 const std::string& change_id,
139 ChangeComplianceStatus new_status)
140 {
141 std::lock_guard<std::mutex> lock(mutex_);
142 auto it = changes_.find(change_id);
143 if (it == changes_.end()) {
145 "Regulatory change not found: " + change_id};
146 }
147 it->second.status = new_status;
148 return {};
149 }
150
153 const std::string& change_id,
154 RegulatoryImpact impact,
155 const std::string& assessor,
156 const std::string& assessment_date)
157 {
158 std::lock_guard<std::mutex> lock(mutex_);
159 auto it = changes_.find(change_id);
160 if (it == changes_.end()) {
162 "Regulatory change not found: " + change_id};
163 }
164 it->second.impact = impact;
165 it->second.assessor = assessor;
166 it->second.assessment_date = assessment_date;
167 if (it->second.status == ChangeComplianceStatus::NOT_ASSESSED)
168 it->second.status = ChangeComplianceStatus::ASSESSED;
169 return {};
170 }
171
173 [[nodiscard]] expected<RegulatoryChange> lookup(const std::string& change_id) const {
174 std::lock_guard<std::mutex> lock(mutex_);
175 auto it = changes_.find(change_id);
176 if (it == changes_.end()) {
178 "Regulatory change not found: " + change_id};
179 }
180 return it->second;
181 }
182
184 [[nodiscard]] std::vector<RegulatoryChange> all_changes() const {
185 std::lock_guard<std::mutex> lock(mutex_);
186 std::vector<RegulatoryChange> out;
187 out.reserve(changes_.size());
188 for (const auto& [_, c] : changes_) out.push_back(c);
189 return out;
190 }
191
193 [[nodiscard]] std::vector<RegulatoryChange> changes_for_regulation(
194 const std::string& regulation) const
195 {
196 std::lock_guard<std::mutex> lock(mutex_);
197 std::vector<RegulatoryChange> out;
198 for (const auto& [_, c] : changes_) {
199 if (c.regulation == regulation) out.push_back(c);
200 }
201 return out;
202 }
203
205 [[nodiscard]] std::vector<RegulatoryChange> pending_changes() const {
206 std::lock_guard<std::mutex> lock(mutex_);
207 std::vector<RegulatoryChange> out;
208 for (const auto& [_, c] : changes_) {
209 if (c.status != ChangeComplianceStatus::VERIFIED &&
211 out.push_back(c);
212 }
213 }
214 return out;
215 }
216
218 [[nodiscard]] std::vector<RegulatoryChange> changes_above_impact(
219 RegulatoryImpact threshold) const
220 {
221 std::lock_guard<std::mutex> lock(mutex_);
222 std::vector<RegulatoryChange> out;
223 for (const auto& [_, c] : changes_) {
224 if (c.impact >= threshold) out.push_back(c);
225 }
226 return out;
227 }
228
230 [[nodiscard]] size_t size() const {
231 std::lock_guard<std::mutex> lock(mutex_);
232 return changes_.size();
233 }
234
236 [[nodiscard]] size_t pending_count() const {
237 std::lock_guard<std::mutex> lock(mutex_);
238 size_t n = 0;
239 for (const auto& [_, c] : changes_) {
240 if (c.status != ChangeComplianceStatus::VERIFIED &&
242 ++n;
243 }
244 }
245 return n;
246 }
247
249 [[nodiscard]] const std::string& org_id() const { return org_id_; }
250
253 const std::string& org_id = "SIGNET")
254 {
256
257 // DORA — effective January 17, 2025
259 "RC-DORA-2025", "DORA",
260 "Digital Operational Resilience Act enters into force",
261 "Regulation (EU) 2022/2554 — ICT risk management, incident reporting, "
262 "resilience testing, third-party risk management for financial entities.",
266 "2025-01-17", "2024-06-01", "2025-12-01", "Security Team", "Engineering",
267 {"ai/compliance/", "ai/incident_response.hpp", "ai/human_oversight.hpp"},
268 {"Implement DORA Art.5-19 compliance modules",
269 "ICT incident management", "Resilience testing framework"},
270 {"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022R2554"}
271 });
272
273 // EU AI Act — phased effective dates 2024-2027
275 "RC-EUAIA-2024", "EU AI Act",
276 "EU Artificial Intelligence Act phased implementation",
277 "Regulation (EU) 2024/1689 — risk-based AI regulation. "
278 "Art.6 high-risk classification, Art.9 risk management, "
279 "Art.11 technical documentation, Art.12 record-keeping, "
280 "Art.13 transparency, Art.14 human oversight, Art.62 incident reporting.",
284 "2026-08-02", "2024-08-01", "2026-01-15", "Compliance", "Engineering",
285 {"ai/compliance/eu_ai_act_reporter.hpp", "ai/human_oversight.hpp",
286 "ai/decision_log.hpp", "ai/inference_log.hpp"},
287 {"Implement Art.12/13/19 compliance reporters",
288 "Human oversight with stop button (Art.14)",
289 "Training data provenance logging"},
290 {"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689"}
291 });
292
293 // NIST SP 800-227 — finalized 2025
295 "RC-NIST-800-227", "NIST SP 800-227",
296 "NIST SP 800-227 recommendations for Parquet encryption",
297 "Recommendations for key management in column-oriented data formats. "
298 "Covers AES-256-GCM, key hierarchy (DEK/KEK), rotation schedules.",
302 "2025-03-15", "2025-04-01", "2025-11-01", "Crypto Team", "Engineering",
303 {"crypto/pme.hpp", "crypto/key_metadata.hpp", "crypto/aes_gcm.hpp"},
304 {"Verify AES-256-GCM compliance", "Document key hierarchy"},
305 {"NIST SP 800-227"}
306 });
307
308 return mon;
309 }
310
311private:
312 std::string org_id_;
313 std::unordered_map<std::string, RegulatoryChange> changes_;
314 mutable std::mutex mutex_;
315};
316
317} // 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:145
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:101
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.