16 min read

Every October, Verdant Bank's Risk Committee received a comprehensive compliance technology report. Maya Osei had inherited this requirement from her predecessor, who had instituted it as a way to demonstrate to the board that the investment in...

Chapter 40: Integrating the RegTech Stack — A Full Program Review

The Annual Review

Every October, Verdant Bank's Risk Committee received a comprehensive compliance technology report. Maya Osei had inherited this requirement from her predecessor, who had instituted it as a way to demonstrate to the board that the investment in regulatory technology was being tracked and justified.

Maya's first such report, in October 2024, had been difficult to write. She had a collection of systems — some working well, some underperforming, some recently acquired, some overdue for replacement — and no single framework to present them as a coherent program rather than a list of tools. The Risk Committee had noted the gap. "What we really need," said the Chair, "is to understand how all of this fits together. Not each system separately — the whole thing."

Maya had spent the year since building toward that understanding. Chapter 40 is the framework she arrived at.


Section 1: The Stack vs. The Program

The compliance technology landscape in financial services is typically described as a "stack" — layers of technology, each addressing a specific compliance function, sitting one atop another. The metaphor is useful: it conveys the idea that there is architecture here, that the layers relate to each other, that you cannot add the top layer before the foundation is stable.

But the stack metaphor is incomplete in an important way. A stack implies that if each layer works, the whole thing works. In practice, the layers of a compliance technology program interact in ways that make each layer dependent not just on the layer below it, but on how it communicates with every other layer. A transaction monitoring system that generates alerts cannot function as intended if it cannot access customer risk data from the KYC system, transaction history from the payment processing system, and case management capability from the SAR workflow system. These connections — the data flows between systems — are as important as the systems themselves.

The shift from "I have a compliance technology stack" to "I have a compliance technology program" requires asking a different set of questions:

Stack questions: Does each system perform its intended function? Does it meet its SLA? Is it used by the team? Is it within budget?

Program questions: Do the systems share data in the ways the compliance workflows require? Is there a single, authoritative view of customer risk across all systems? When an alert is generated by one system, can another system provide context? Is the audit trail that regulators would expect complete and coherent across the whole program, or is it fragmented across individually complete but collectively incoherent systems?

The program questions are harder. They require architectural thinking — understanding not just what each system does but what flows between systems and how those flows are governed.


Section 2: The Five Domains of the RegTech Program

A complete RegTech program for a financial institution covers five interconnected domains:

Domain 1: Identity and Know Your Customer

Identity verification and KYC is the foundation of the compliance program. Before any other compliance analysis is possible, the institution must know who it is dealing with. The data established in KYC — customer identity, beneficial ownership, risk classification, source of wealth, PEP/sanctions status — flows into and conditions every subsequent compliance system.

The architecture challenge: KYC data must be accessible to every downstream system — transaction monitoring, sanctions screening, case management, regulatory reporting. This requires a master customer data repository that serves as the single authoritative source for customer information, with clear protocols for how that data is updated and how updates propagate to dependent systems.

The integration failure mode: KYC data is stored in the KYC system and not effectively accessible to other systems. The transaction monitoring system makes decisions based on transaction data without customer risk context. Alert rates are higher than necessary because the monitoring system cannot distinguish between a flagged transaction from a low-risk customer and the same transaction from a high-risk one.

Domain 2: Financial Crime — AML, Fraud, and Sanctions

The financial crime compliance layer comprises transaction monitoring (AML and fraud), sanctions screening, and case management (suspicious activity investigation and SAR filing). These three components must work as a coordinated system, not as independent tools.

The architecture challenge: Alerts generated by transaction monitoring must be enriched with customer data before reaching the analyst. Case management must be able to receive escalated alerts from any monitoring component. SAR filings must draw on customer data, transaction history, and case analysis — all from different systems. The analyst should never need to retrieve information from multiple separate systems to complete an investigation.

The integration failure mode: Each system has its own alert queue, its own data model, and its own user interface. Analysts switch between three systems during a single alert review. Alert context is assembled manually rather than automatically. Case management is a separate tool that does not receive structured data from the monitoring systems — analysts must re-enter information they have already reviewed.

Domain 3: Regulatory Reporting

Regulatory reporting is the mechanism by which the institution communicates its compliance data to regulators — capital ratios, transaction reports, suspicious activity reports, large transaction reports, position reports, and many others. Each report has a specific regulatory obligation, a specific format, a specific deadline, and a specific data source.

The architecture challenge: Regulatory reports draw data from across the institution — trading systems, payment systems, lending systems, risk systems. The data must be aggregated, normalized, validated, and packaged in regulator-specified formats. A regulatory reporting system that cannot reliably access all the required source data will produce inaccurate or incomplete reports.

The integration failure mode: Each regulatory report is produced by a separate manual process. Data is extracted by a different person for each report, using different queries, at different times. There is no single canonical data source; each report uses data that is slightly different from every other report. When a regulator queries a discrepancy between two reports, the institution cannot explain it.

Domain 4: Market Surveillance and Trading Compliance

For financial institutions with trading activity, market surveillance — monitoring for market manipulation, best execution violations, and trading control failures — is an additional compliance domain. This domain requires access to trading data at high granularity (individual orders, quotes, executions) and the ability to correlate trading behavior across time, markets, and instruments.

The architecture challenge: Market surveillance requires a different data model than financial crime monitoring — trading data is granular, time-precise, and often structured differently from payment transaction data. Yet it must be correlated with customer data (who is the trader? what is their risk profile?) and with case management (when a suspicious trading pattern is identified, it must flow into the same case management workflow used for financial crime alerts).

The integration failure mode: Market surveillance is entirely siloed from financial crime monitoring. A customer who is the subject of an AML alert and a market surveillance alert is investigated twice, by different teams, using different systems, with no visibility between the two investigations. The combined pattern — if it is significant — is never seen by anyone.

Domain 5: Governance, Risk, and Control

The governance layer sits above the four operational domains. It encompasses: model risk management (validating that the models underlying monitoring and decisioning systems are performing correctly); audit trail management (maintaining the complete, immutable records of compliance decisions and their data inputs); management information (providing leadership with the metrics needed to govern the program); and regulatory relationship management (maintaining the documentation and preparation needed for regulatory examinations).

The architecture challenge: The governance layer requires data from all operational domains — monitoring rates, false positive rates, SAR metrics, report accuracy, model performance indicators. This requires a data infrastructure that aggregates operational data from across the program into a consistent management information layer.

The integration failure mode: Each domain has its own reporting. The Head of Financial Crime gets financial crime metrics. The Head of Reporting gets reporting metrics. The CCO gets them separately and cannot see cross-domain patterns. A model that is simultaneously showing signs of drift in its AML monitoring and in its fraud detection — a pattern that might indicate a common data quality problem — is not identified because no one is looking at both sets of metrics simultaneously.


Section 3: The Data Architecture That Enables Integration

The five domains described above cannot be integrated without a supporting data architecture. The most common integration failures in RegTech programs are not failures of the systems themselves — they are failures of the data infrastructure that the systems depend on.

A program-level data architecture for a financial institution's compliance function requires:

The Customer Master Record

A single, authoritative record of each customer that contains: identity information (verified), risk classification (current), beneficial ownership structure (verified), relationship history, screening status (sanctions, PEP, adverse media), and any flags from ongoing monitoring. This record must be the single source of truth for all downstream systems. When the KYC system updates a customer's risk classification, that update must propagate — with a clear versioning mechanism — to every system that uses that data.

The Transaction Data Lake

A consolidated store of all transaction data, available to compliance systems for historical analysis and pattern detection. The transaction data lake must contain data from all transaction processing systems — retail payments, corporate payments, trading, lending — in a normalized format. Transaction monitoring systems should not access raw transaction data directly from source systems; they should access it from the consolidated, normalized, governed transaction data lake.

The Alert and Case Registry

A unified registry of all alerts generated by any monitoring system — AML, fraud, sanctions, market surveillance — in a consistent format. The registry links each alert to the customer record, to the underlying transaction(s), and to any prior alerts involving the same customer. When an analyst opens an alert for review, they see its context: not just the transaction that generated the alert, but the customer's full alert history across all monitoring systems.

The Audit Log

A complete, tamper-evident log of every compliance decision — every alert disposition, every case escalation or closure, every SAR submission, every regulatory report submitted. The audit log is the evidence base for regulatory examinations. It must be structured enough to be queried systematically and must be maintained for the full duration required by applicable record-keeping regulations.


Section 4: Building the Integrated Program — Architecture Code

The following Python illustration models a simplified RegTech program orchestrator — a coordinator that manages the relationships between the program's major components and provides a unified management information view.

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Optional

# ─────────────────────────────────────────────────────────────
# Core Data Types
# ─────────────────────────────────────────────────────────────

class RiskTier(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    VERY_HIGH = "very_high"

class AlertDomain(Enum):
    AML = "aml"
    FRAUD = "fraud"
    SANCTIONS = "sanctions"
    MARKET_SURVEILLANCE = "market_surveillance"

class AlertStatus(Enum):
    OPEN = "open"
    UNDER_REVIEW = "under_review"
    ESCALATED = "escalated"
    CLOSED_FALSE_POSITIVE = "closed_false_positive"
    CLOSED_SAR_FILED = "closed_sar_filed"
    CLOSED_NO_ACTION = "closed_no_action"

@dataclass
class CustomerRecord:
    """Master customer record — single source of truth for all systems."""
    customer_id: str
    full_name: str
    risk_tier: RiskTier
    kyc_verified_at: datetime
    kyc_next_review: datetime
    is_pep: bool = False
    sanctions_status: str = "clear"  # "clear", "potential_match", "confirmed_match"
    edd_required: bool = False
    alert_count_90d: int = 0
    sar_count_lifetime: int = 0

    def requires_enhanced_review(self) -> bool:
        return (
            self.risk_tier in (RiskTier.HIGH, RiskTier.VERY_HIGH)
            or self.is_pep
            or self.edd_required
            or self.sar_count_lifetime > 0
        )

    def is_kyc_current(self) -> bool:
        return datetime.now() < self.kyc_next_review

@dataclass
class TransactionRecord:
    """Canonical transaction record from the consolidated data lake."""
    transaction_id: str
    customer_id: str
    amount: float
    currency: str
    counterparty: str
    channel: str  # "online", "branch", "atm", "card"
    timestamp: datetime
    transaction_type: str  # "payment", "withdrawal", "deposit", "trade"

@dataclass
class ComplianceAlert:
    """Unified alert record across all monitoring domains."""
    alert_id: str
    domain: AlertDomain
    customer_id: str
    transaction_ids: list[str]
    risk_score: float  # 0.0 to 1.0
    generated_at: datetime
    status: AlertStatus = AlertStatus.OPEN
    analyst_id: Optional[str] = None
    disposition_at: Optional[datetime] = None
    disposition_notes: Optional[str] = None
    case_id: Optional[str] = None  # Links to case if escalated

    def days_open(self) -> int:
        end = self.disposition_at or datetime.now()
        return (end - self.generated_at).days

    def is_overdue(self, sla_days: int = 5) -> bool:
        return (
            self.status in (AlertStatus.OPEN, AlertStatus.UNDER_REVIEW)
            and self.days_open() > sla_days
        )

@dataclass
class ProgramMetrics:
    """Cross-domain management information for compliance leadership."""
    report_date: datetime
    alert_volume_by_domain: dict[str, int] = field(default_factory=dict)
    false_positive_rate_by_domain: dict[str, float] = field(default_factory=dict)
    overdue_alerts_by_domain: dict[str, int] = field(default_factory=dict)
    sars_filed_30d: int = 0
    kyc_reviews_overdue: int = 0
    model_drift_flags: list[str] = field(default_factory=list)
    regulatory_reports_on_time_rate: float = 1.0

    def overall_health_score(self) -> float:
        """
        Simplified health score: 1.0 is excellent, 0.0 is critical.
        Based on: SLA compliance, model health, reporting accuracy.
        """
        scores = []

        # False positive rates (lower is better; score 1.0 if <20%, 0.0 if >50%)
        for domain, fpr in self.false_positive_rate_by_domain.items():
            if fpr < 0.20:
                scores.append(1.0)
            elif fpr > 0.50:
                scores.append(0.0)
            else:
                scores.append(1.0 - ((fpr - 0.20) / 0.30))

        # Overdue alerts (0.0 if any domain has >10 overdue)
        total_overdue = sum(self.overdue_alerts_by_domain.values())
        if total_overdue == 0:
            scores.append(1.0)
        elif total_overdue < 10:
            scores.append(0.5)
        else:
            scores.append(0.0)

        # Model drift (penalize for each domain with drift)
        drift_penalty = len(self.model_drift_flags) * 0.15
        scores.append(max(0.0, 1.0 - drift_penalty))

        # Reporting on-time rate
        scores.append(self.regulatory_reports_on_time_rate)

        return sum(scores) / len(scores) if scores else 0.0

    def executive_summary(self) -> str:
        health = self.overall_health_score()
        health_str = "GOOD" if health >= 0.8 else ("ATTENTION NEEDED" if health >= 0.6 else "CRITICAL")

        lines = [
            f"Compliance Program Health Report — {self.report_date.strftime('%B %Y')}",
            f"Overall Health: {health_str} ({health:.0%})",
            "",
            "Alert Volumes (30 days):",
        ]
        for domain, vol in self.alert_volume_by_domain.items():
            fpr = self.false_positive_rate_by_domain.get(domain, 0)
            lines.append(f"  {domain}: {vol} alerts, {fpr:.0%} false positive rate")

        lines.extend([
            "",
            f"SARs Filed (30 days): {self.sars_filed_30d}",
            f"KYC Reviews Overdue: {self.kyc_reviews_overdue}",
            f"Regulatory Reporting On-Time: {self.regulatory_reports_on_time_rate:.0%}",
        ])

        if self.model_drift_flags:
            lines.append(f"\nModel Governance Flags: {', '.join(self.model_drift_flags)}")

        if any(v > 0 for v in self.overdue_alerts_by_domain.values()):
            overdue = {k: v for k, v in self.overdue_alerts_by_domain.items() if v > 0}
            lines.append(f"\nSLA Breaches: {overdue}")

        return "\n".join(lines)


# ─────────────────────────────────────────────────────────────
# Program Orchestrator
# ─────────────────────────────────────────────────────────────

class RegTechProgramOrchestrator:
    """
    Coordinates the five domains of the compliance technology program
    and produces integrated management information.

    In a production system, each domain would be a separate service.
    This orchestrator models their interfaces and interactions.
    """

    def __init__(self):
        # In production: these would be client references to domain services
        self._customer_store: dict[str, CustomerRecord] = {}
        self._alert_registry: list[ComplianceAlert] = []
        self._transaction_count_30d: dict[str, int] = {}

    def register_customer(self, customer: CustomerRecord) -> None:
        self._customer_store[customer.customer_id] = customer

    def register_alert(self, alert: ComplianceAlert) -> None:
        self._alert_registry.append(alert)
        # Update customer's alert count
        if alert.customer_id in self._customer_store:
            self._customer_store[alert.customer_id].alert_count_90d += 1

    def enrich_alert(self, alert: ComplianceAlert) -> dict:
        """
        Return an enriched alert view combining alert data with customer context.
        This is the 'single pane of glass' view for analysts.
        """
        customer = self._customer_store.get(alert.customer_id)

        # Get all prior alerts for this customer
        prior_alerts = [
            a for a in self._alert_registry
            if a.customer_id == alert.customer_id and a.alert_id != alert.alert_id
        ]

        return {
            "alert": alert,
            "customer": customer,
            "customer_context": {
                "risk_tier": customer.risk_tier.value if customer else "unknown",
                "is_pep": customer.is_pep if customer else False,
                "requires_edd": customer.edd_required if customer else False,
                "prior_alerts_count": len(prior_alerts),
                "prior_sar_count": customer.sar_count_lifetime if customer else 0,
                "kyc_current": customer.is_kyc_current() if customer else False,
            },
            "cross_domain_flags": [
                f"Prior {a.domain.value} alert: {a.alert_id}"
                for a in prior_alerts
                if a.status == AlertStatus.ESCALATED
            ],
        }

    def compute_program_metrics(self, report_date: datetime) -> ProgramMetrics:
        """Aggregate metrics across all domains for the management information report."""
        metrics = ProgramMetrics(report_date=report_date)

        # Count alerts by domain (all alerts, not just 30-day)
        for alert in self._alert_registry:
            domain_str = alert.domain.value
            metrics.alert_volume_by_domain[domain_str] = (
                metrics.alert_volume_by_domain.get(domain_str, 0) + 1
            )
            if alert.status == AlertStatus.CLOSED_FALSE_POSITIVE:
                # Track for false positive rate calculation
                pass  # Simplified: full implementation would track per-domain

        # Overdue alerts by domain
        for alert in self._alert_registry:
            if alert.is_overdue():
                domain_str = alert.domain.value
                metrics.overdue_alerts_by_domain[domain_str] = (
                    metrics.overdue_alerts_by_domain.get(domain_str, 0) + 1
                )

        # KYC overdue
        metrics.kyc_reviews_overdue = sum(
            1 for c in self._customer_store.values()
            if not c.is_kyc_current()
        )

        # SARs filed — count closed with SAR in last 30 days
        cutoff = datetime.now()
        metrics.sars_filed_30d = sum(
            1 for a in self._alert_registry
            if a.status == AlertStatus.CLOSED_SAR_FILED
            and a.disposition_at
            and (cutoff - a.disposition_at).days <= 30
        )

        return metrics


# ─────────────────────────────────────────────────────────────
# Example: Verdant Bank's Program at Month 18
# ─────────────────────────────────────────────────────────────

def demonstrate_integrated_program():
    orchestrator = RegTechProgramOrchestrator()

    # Register some customers
    customers = [
        CustomerRecord(
            customer_id="VB-001",
            full_name="Sarah Clarke",
            risk_tier=RiskTier.LOW,
            kyc_verified_at=datetime(2023, 6, 15),
            kyc_next_review=datetime(2026, 6, 15),
        ),
        CustomerRecord(
            customer_id="VB-002",
            full_name="Meridian Trading Ltd",
            risk_tier=RiskTier.HIGH,
            kyc_verified_at=datetime(2023, 9, 1),
            kyc_next_review=datetime(2024, 9, 1),  # Overdue
            edd_required=True,
            sar_count_lifetime=1,
        ),
        CustomerRecord(
            customer_id="VB-003",
            full_name="James Okonkwo",
            risk_tier=RiskTier.MEDIUM,
            kyc_verified_at=datetime(2024, 1, 10),
            kyc_next_review=datetime(2026, 1, 10),
            is_pep=True,
        ),
    ]
    for customer in customers:
        orchestrator.register_customer(customer)

    # Register alerts from multiple domains
    alerts = [
        ComplianceAlert(
            alert_id="AML-2024-001",
            domain=AlertDomain.AML,
            customer_id="VB-002",
            transaction_ids=["TXN-45231", "TXN-45232"],
            risk_score=0.82,
            generated_at=datetime(2024, 10, 1),
            status=AlertStatus.ESCALATED,
        ),
        ComplianceAlert(
            alert_id="FRAUD-2024-098",
            domain=AlertDomain.FRAUD,
            customer_id="VB-002",  # Same customer — cross-domain pattern
            transaction_ids=["TXN-45890"],
            risk_score=0.71,
            generated_at=datetime(2024, 10, 3),
            status=AlertStatus.UNDER_REVIEW,
        ),
        ComplianceAlert(
            alert_id="AML-2024-045",
            domain=AlertDomain.AML,
            customer_id="VB-003",
            transaction_ids=["TXN-46102"],
            risk_score=0.55,
            generated_at=datetime(2024, 9, 20),
            status=AlertStatus.OPEN,
        ),
    ]
    for alert in alerts:
        orchestrator.register_alert(alert)

    # Get enriched view of the cross-domain alert
    fraud_alert = alerts[1]
    enriched = orchestrator.enrich_alert(fraud_alert)

    print("=== ENRICHED ALERT VIEW ===")
    print(f"Alert: {enriched['alert'].alert_id} ({enriched['alert'].domain.value})")
    print(f"Customer: {enriched['customer'].full_name}")
    print(f"Risk tier: {enriched['customer_context']['risk_tier']}")
    print(f"Prior alerts (all domains): {enriched['customer_context']['prior_alerts_count']}")
    print(f"Cross-domain flags: {enriched['cross_domain_flags']}")
    print()

    # Compute program metrics
    metrics = orchestrator.compute_program_metrics(datetime(2024, 10, 15))
    # Add some illustration data
    metrics.false_positive_rate_by_domain = {"aml": 0.18, "fraud": 0.22, "sanctions": 0.31}
    metrics.regulatory_reports_on_time_rate = 0.97
    metrics.model_drift_flags = ["sanctions_screening: PSI_score=0.28"]

    print("=== PROGRAM HEALTH REPORT ===")
    print(metrics.executive_summary())
    print(f"\nOverall Health Score: {metrics.overall_health_score():.0%}")

if __name__ == "__main__":
    demonstrate_integrated_program()

The orchestrator above illustrates the key architectural principle: integration is achieved through shared data models and defined interfaces, not through monolithic systems. The CustomerRecord flows into ComplianceAlert enrichment. Alert enrichment surfaces cross-domain patterns. ProgramMetrics aggregates across domains. The CCO who sees executive_summary() is seeing an integrated view of the compliance program — not a collection of separate reports.


Section 5: The Governance Framework That Holds It Together

A sophisticated technology stack can fail as a compliance program if the governance framework that sits above it is inadequate. The governance framework encompasses five elements:

Model Risk Management

Every analytical model in the compliance program — transaction monitoring models, fraud detection models, customer risk scoring models, sanctions screening matching algorithms — must be subject to ongoing validation. This means: documented model purpose and methodology; validation against holdout data; ongoing performance monitoring; drift detection; documented escalation thresholds; and a clear process for retraining or replacing underperforming models.

SR 11-7 in the US and the EU AI Act's high-risk AI governance requirements both establish that model risk management is not a one-time exercise at deployment — it is a continuous obligation. The CCO who does not have a model inventory and monitoring program is flying blind about whether her compliance systems are performing as intended.

Audit Trail Integrity

The audit trail is the evidence that the compliance program is working. It must cover every significant compliance decision: every alert disposition, every case escalation, every SAR filing, every KYC risk classification, every monitoring configuration change. These records must be: complete (all required fields populated), accurate (reflecting what actually happened), timely (recorded at or near the time of the action), and retained for the required regulatory period.

An audit trail that is complete within each system but fragmented across systems creates examination risk: a regulator who asks "show me everything you knew about this customer and every decision you made" cannot get that picture from any single system. The integration challenge for audit trail management is the same as for operations: the governance layer must aggregate audit data from across the program into a coherent whole.

Management Information Architecture

The management information that compliance leadership uses to govern the program must be derived from operational systems, not assembled manually. If the Head of Financial Crime has to ask four different systems for data to compile their monthly management pack, the management information is both delayed and potentially inconsistent. The governance layer must provide automated, consistent management information that reflects the program's actual performance — not a curated selection of favorable metrics.

Change Management for Ongoing Operations

The RegTech program is not static. Regulations change. Typologies evolve. Vendors release new versions. Staff turn over. Each change creates risk: a configuration change in the transaction monitoring system that inadvertently narrows its detection coverage; a vendor upgrade that changes the sanctions screening algorithm's matching thresholds; a staff turnover that leaves institutional knowledge embedded in a single analyst who has left.

The governance framework must include a defined change management process: how changes to systems are tested before production; who approves configuration changes; how the audit trail reflects what the system was configured to do at any point in time; how institutional knowledge is documented rather than carried in individual heads.

Regulatory Relationship Management

The compliance program's relationship with its regulators is itself a governance matter. The program must maintain the documentation needed to respond to examination requests: model documentation, validation records, governance policies, audit trails, evidence of ongoing monitoring. It must track and respond to regulatory developments that affect the program — new regulations, Dear CEO letters, supervisory guidance. And it must manage its communications with regulators — examination responses, voluntary disclosures, regulatory notifications — as a coordinated activity rather than a series of ad hoc responses.


Section 6: What Integration Actually Looks Like

Integration is one of those concepts that is easy to describe in principle and difficult to achieve in practice. The following four tests distinguish genuine integration from the appearance of it.

Test 1: The single customer view test. Can any analyst or manager, in any compliance system, see everything the institution knows about a specific customer — their risk classification, their alert history across all domains, their regulatory reports, their case history — in a single view? If the answer is "mostly, but you have to check the KYC system separately" or "yes, but it takes 20 minutes," genuine integration has not been achieved.

Test 2: The cross-domain alert correlation test. When a customer has an open AML alert, an active fraud alert, and a positive sanctions match simultaneously, does any system or process surface that correlation? If the sanctions team is investigating their match without knowing the AML team has an open case, cross-domain correlation is not happening.

Test 3: The audit trail continuity test. If a regulator asks for the complete history of a specific suspicious activity — what triggered it, what was reviewed, what decision was made at each step, who made it, what supporting information they had — can that history be produced from a single system or query? If the answer requires reconstruction from multiple systems, the audit trail is not integrated.

Test 4: The management information consistency test. Does the compliance report presented to the Board say the same thing as the operational metrics visible to the compliance team? If numbers differ between reports because they are drawing from different systems at different times, the management information architecture is not integrated.

These four tests are practical diagnostics that any compliance professional can apply to their existing program. Where the tests fail, they identify specific integration work to be done.


Section 7: The Full Program Review — Maya's Annual Report

By October 2025, Maya had built the framework described in this chapter. The Risk Committee received a report that covered, for the first time, all five domains as a coherent program:

Identity and KYC: 178,000 active customers; 99.4% KYC-current; 2,340 periodic reviews completed in the quarter; 0.6% false acceptance rate in automated document verification.

Financial Crime: AML alerts 1,847 for the quarter; false positive rate 21% (down from 34% at the prior year); 12 SARs filed; 0 SAR filing deadline breaches. Sanctions: 4,231 screening alerts; 6 confirmed matches (all escalated and managed). Fraud: 892 alerts; false positive rate 18%; 3 confirmed fraud cases blocked.

Regulatory Reporting: 14 report types submitted; 97.2% on-time rate; 2 late submissions (both with prior FCA communication); 0 rejected submissions.

Market Surveillance: Not applicable (Verdant does not have a trading book).

Governance: Model validation completed for all 4 operational models; 1 model flagged for recalibration (sanctions screening — PSI score 0.28, above 0.25 threshold); 0 unresolved model governance findings; audit trail completeness 99.8%.

Program health score: 87% (GOOD, up from 61% in October 2024).

The Risk Committee Chair leaned back and said: "That's the report I've been asking for."

Maya had built not a stack of tools, but a program.


Conclusion: The Compliance Professional in the Age of RegTech

Thirty-nine chapters ago, this book opened with the question of what RegTech is. The answer given then — technology applied to regulatory compliance challenges in financial services — remains accurate. But it is incomplete.

RegTech is technology applied to compliance challenges. But the technology alone is not RegTech. The regulatory knowledge that defines what the technology must achieve is not RegTech. The organizational capability to deploy the technology effectively is not RegTech. The ethical judgment that governs how the technology treats the people it affects is not RegTech.

RegTech is all of these things together. It is a field that spans computer science and law, statistics and organizational psychology, commercial strategy and professional ethics. No single chapter of this book, and no single capability, is sufficient on its own.

What is sufficient, in practice, is the professional who can hold all these dimensions simultaneously — who can read a technical report and understand its regulatory implications, who can evaluate a vendor contract and identify its governance gaps, who can design a monitoring system and worry about its fairness, who can present a business case to a board and make it meaningful to both the CFO and the non-executive who has never worked in financial services.

That professional is the goal of this book. The RegTech stack is the means. The compliance program is the output. The protection of the financial system, and the people who use it, is the purpose.

The work continues.