Risk data aggregation and reporting compliance is normally a consulting engagement and a spreadsheet that goes stale the week after it is signed. In Qrly it is a module inside the BI platform that already holds the connections, the questions and the lineage — 14 principles held in code, executable data-quality rules, column-level lineage, sign-off and an audit trail over every state change.
What BCBS 239 asks for, and why the usual answer does not survive a supervisory visit.
BCBS 239 is the Basel Committee's set of principles for effective risk data aggregation and risk reporting. Principles 1 and 2 cover governance and data architecture. Principles 3 to 6 cover the aggregation capability itself — accuracy and integrity, completeness, timeliness, adaptability. Principles 7 to 11 cover the reporting practice built on top of it. Principles 12 to 14 are addressed to the supervisor rather than to the bank.
They are principles, not a control list, which is precisely what makes them hard to evidence. A supervisor does not want a policy document saying your data is accurate. They want to see the aggregation working, the definitions agreed, the failures counted and the remediation tracked.
The standard artefact is a workbook: one tab per principle, a maturity score, a paragraph of rationale, and a column of links to evidence stored somewhere else. It is authored once, reviewed by a committee, and is out of date before the next reporting period because nothing in it is connected to the data it describes.
The gap between the assessment and the data is the whole problem. If a critical data element loses its owner, or a feed starts arriving two days late, or a reference table drifts, the workbook does not notice. Someone has to notice, and then remember to update it.
Lineage is the part institutions most often buy separately, and it is the part a BI platform is uniquely placed to know for free. Qrly already tracks which connection feeds which table, which table feeds which question, which question feeds which dashboard, alert and subscription — as a graph rebuilt from the source-of-truth tables rather than maintained by hand.
The BCBS 239 module adds the layer above it: directed column-level edges between critical data elements, each carrying transformation text and a confidence of MANUAL, AI or INFERRED, rendered server-side as a Mermaid flowchart with every node coloured from its latest data-quality result.
AI will write a principle rationale faster and more consistently than a risk analyst under deadline. The question a supervisor asks is not whether you used it — it is whether you can still tell which sentences a model wrote.
Every AI assist in the module is recorded under its own audit code: drafting a rationale, suggesting a gap action, reviewing a report, proposing a score, auto-filling an assessment. They are five distinct codes, not one generic "AI" flag, so the trail says what was generated and where. That is the detail that decides whether the assist is an efficiency or a finding.
Not free text in a template. The principles are enumerated in the application, with translated labels, and every assessment scores against them.
A lifecycle with states that mean something, rather than a file named final_v3_signed.xlsx.
An assessment belongs to a project and a reporting period. Scoring is only possible while it is in DRAFT — once submitted, the numbers stop moving. Every state change is written to the audit trail with who made it and when.
Each rule is attached to a critical data element — a connection, table and column with a business term, definition, owner, risk category and materiality — and compiled to that connection's dialect. Rules run on a read-only connection with a statement timeout.
The regex check compiles to a negated regular-expression operator per engine: Postgres !~, MySQL NOT REGEXP, BigQuery NOT IS_REGEXP_MATCH. SQL Server has no native regular-expression operator, so on SQL Server the check degrades to NOT LIKE. It still executes, still counts failures and still reports them — it simply cannot express a full regular expression on that engine, and you should design the rule accordingly.
Every rule also carries a quality dimension (accuracy, completeness, timeliness, integrity, validity, uniqueness), a severity (info, warning, error, critical), an enable flag and its own statement timeout. A rule that is itself broken is reported as a failed result — it never aborts the sweep and takes the rest of the run down with it.
Every enabled rule, on every critical data element in the project, in one pass — synchronously, or asynchronously with polling for the large ones.
The three artefacts a supervisor asks for after the assessment itself.
The same work, done in the system that already holds the connections, the questions and the lineage.
BCBS 239 is the Basel Committee's set of principles for effective risk data aggregation and risk reporting. There are 14. Principles 1 and 2 cover governance and data architecture, 3 to 6 cover the aggregation capability, 7 to 11 cover reporting practice, and 12 to 14 are addressed to the supervisor.
Qrly holds all 14 in code, grouped GOVERNANCE, AGGREGATION, REPORTING and SUPERVISORY, with translated labels — so an assessment scores against enumerated principles rather than against free text in a template.
Yes. Seven check types — NOT_NULL, RANGE, REGEX, FRESHNESS, REFERENTIAL, UNIQUENESS and CUSTOM_SQL — are compiled to the dialect of the connection the critical data element sits on and run against the real table, on a read-only connection, with a per-rule statement timeout. A run is a project-wide sweep of every enabled rule on every CDE, persisting per-rule results with failed row counts and sample failing values.
Not equally, and we would rather say so here than have you find out in a review. The check compiles to a negated operator per engine — Postgres !~, MySQL NOT REGEXP, BigQuery NOT IS_REGEXP_MATCH. SQL Server has no native regular-expression operator, so there the check degrades to NOT LIKE. It still runs and still counts failures; it simply cannot express a full regular expression on that engine.
The run records the failure with its failed row count and sample failing values, and automatically opens an issue in the tracker with source DQ_RULE and a reference back to the rule that raised it. The issue then carries a severity, an owner, a due date and a status of OPEN, IN_PROGRESS, RESOLVED or ACCEPTED_RISK like any other.
Yes, and it is the detail an auditor will care about. The module can draft a principle rationale, suggest gap remediation, review a linked report's text against principles 7 to 9, propose a single principle score, and auto-fill an entire assessment. Each of those five assists is recorded under its own audit code — not one generic AI flag — so machine-drafted content stays distinguishable from human-authored content in the trail.
Only if you configure one. Qrly is provider-agnostic: Claude, OpenAI, Azure OpenAI, Gemini and Mistral are supported alongside local runtimes — Ollama, LM Studio, Jan.ai, LocalAI, GPT4All, LibreChat, Lobe Chat and Open WebUI. An institution that cannot send risk data outside its own network points the provider at a model running inside it. The AI assists are optional; the module works with them switched off.
Any connection Qrly supports — 40 connection types compiled through 12 SQL dialect strategies, including PostgreSQL, SQL Server, DB2, Snowflake, Redshift, BigQuery and the managed AWS, Azure and GCP variants. The CDE register points at a connection, a table and a column, so elements from different systems sit in the same register and the same lineage graph.
Yes. Qrly is self-hostable — Java 25 on Spring Boot with a PostgreSQL application database, GraalVM native-image capable, installed through an eight-step first-run wizard with systemd integration and pg_dump backups on an operator-editable cron. There is no phone-home requirement, and with a local model provider the AI assists stay inside the perimeter too.
Self-hosted, inside your own perimeter, with the lineage already built.