Тема: Часть 2. Почему банковские данные требуют спецификаций
Уровень сложности: Средний
Расчётное время изучения: 3-4 часа
Предварительные требования: Базовое понимание SQL (SELECT, JOIN, GROUP BY, агрегатные функции)
Знакомство с концепцией витрин данных (data marts) и слоистой архитектуры (staging, intermediate, marts)
Начальное понимание dbt (модели, тесты not_null/unique/accepted_values, команда dbt build)
Общее представление о персональных данных (PII) и принципах работы банковской аналитики
Цели обучения: Объяснить, почему в банковском домене ошибка данных опаснее синтаксической ошибки и чем это отличается от ошибок в веб-приложениях.
Перечислить пять классов риска банковских данных и для каждого сформулировать проверяемое правило (не лозунг).
Разграничить пять слоёв спецификаций в SDD Data (dbt-тесты, ODCS, ODPS, спецификация модели, отчёт ревьюера) и объяснить, что именно проверяет каждый слой.
Преобразовать «плохую» спецификацию витрины в «хорошую», добавив grain, политику PII, SLA свежести, обязательные факты и владельца.
Сформулировать критерии приёмки для мартовой модели так, чтобы работу агента или разработчика можно было отклонить по формальному основанию.
Обзор: Банковские данные — это домен, в котором «примерно правильно» обходится особенно дорого: ошибка в витрине клиентов или платежей может выглядеть как штатная таблица с зелёными тестами, но при этом нести ложный смысл для отчётности, риск-менеджмента или клиентского сервиса. Именно поэтому банковский контекст удобен для изучения SDD Data (Specification-Driven Development for Data) — подхода, в котором каждое обещание дата-продукта должно быть записано явно, ограничено конкретными правилами и подтверждено доказательствами. В главе разбираются пять классов риска (PII, платежи, согласия, кредитный портфель, отчётность), объясняется, почему одних dbt-тестов недостаточно, и вводится многослойная модель спецификаций: тесты ловят форму и часть фактов, ODCS фиксирует технический контракт, ODPS описывает дата-продукт и потребителя, спецификация модели описывает grain и приёмочные факты, а отчёт ревьюера связывает изменение с обещаниями. На конкретном примере витрины customer_360 показывается разница между «уверенной, но пустой» плохой спецификацией и «узкой, но проверяемой» хорошей. Главный практический навык главы — привычка задавать вопрос «как это будет доказано?» и уметь превращать любое утверждение о данных в команду, SQL-запрос, ручной шаг ревьюера или подтверждение человеком.
Ключевые концепции: Sdd data: Specification-Driven Development for Data — подход, в котором разработка дата-продукта начинается с явной спецификации: что продукт обещает, кому он нужен, какие у него ограничения (grain, PII, freshness) и как эти обещания будут проверены. В SDD Data агент или разработчик не должен угадывать, что значит «корректно» — он получает критерии, по которым его работу можно отклонить.
Пять классов риска банковских данных: В учебном банке выделяются пять классов риска: (1) PII и прямые идентификаторы, (2) платежи и риск-сигналы, (3) согласия на доступ к данным, (4) кредитный портфель и просрочка, (5) отчётность и воспроизводимость расчётов. Каждый класс требует не только SQL-решения, но и проверяемого правила — лозунг «не раскрывать персональные данные» должен превратиться в конкретный список запрещённых колонок в mart-слое и в проверку ревьюера.
Grain гранулярность: Уровень детализации строки в витрине, например «одна строка на customer_id». Это обещание дата-продукта, которое невозможно вывести из dbt-тестов автоматически — его нужно записать в спецификации. Смена grain незаметно ломает все нижестоящие отчёты, поэтому grain должен быть либо зафиксирован, либо явно изменён с подтверждением владельца.
Pii и прямые идентификаторы: Personally Identifiable Information — поля, по которым можно прямо или косвенно идентифицировать клиента (email, phone, passport_number, ИНН и т. п.). Политика PII в SDD Data выражается через конкретные запреты: например, «models/marts/ не содержит колонок pii_email, phone, passport_number», и проверяется ревьюером до релиза, а не общими фразами о «соблюдении требований».
Freshness свежесть данных: SLA на актуальность данных в витрине, например «данные не старше 24 часов». Freshness должна быть записана в спецификации как измеримое обещание, иначе потребитель не может понять, доверять ли витрине. В dbt это поддерживается source freshness, но сама политика всё равно живёт в спецификации.
Дрейф контракта: Ситуация, когда структура или семантика витрины меняется незаметно для потребителя: добавление product_code, изменение формулы risk_flag, появление нового уровня NULL. Дрейф контракта ловится только при сравнении текущей версии с зафиксированной спецификацией (ODCS, ODPS, спецификация модели).
Слои спецификаций в sdd data: Многослойная защита дата-продукта: (1) dbt-тесты — форма и часть фактов, (2) ODCS — технический контракт (поля, типы, владельцы), (3) ODPS — описание дата-продукта и его потребителей, (4) спецификация модели — grain и приёмочные факты, (5) отчёт ревьюера — связь изменения с обещаниями. Каждый слой ловит то, чего не видят другие.
Odcs и odps: ODCS (Open Data Contract Standard) — стандарт технического контракта данных: список полей, типы, владельцы, ограничения. ODPS (Open Data Product Standard) — стандарт описания дата-продукта: кто потребитель, какую задачу решает продукт, какие у него SLA и приёмочные критерии. Вместе они дают и техническую, и продуктовую сторону контракта.
Приёмочные факты acceptance facts: Конкретные проверяемые утверждения о витрине, которые должны выполняться: «customer_id unique/not_null», «total_balance_rub not_null», «risk_event_count_7d присутствует», «список запрещённых прямых PII не появляется в mart-слое». Это мост между спецификацией и исполнением — их можно автоматизировать в тестах или проверить вручную.
Зелёный dbt build vs пригодные данные: Успешный запуск dbt build означает лишь то, что граф моделей исполнился и заявленные тесты прошли. Он не доказывает, что выбрана правильная гранулярность, что в витрине не смешаны клиент и счёт, что учебный risk_flag не выдаётся за боевой скоринг. Это граница инструмента, а не его недостаток.
Проверяемое правило против лозунга: Главный навык главы: любое утверждение о данных должно превращаться в команду, SQL-запрос, ручной шаг ревьюера или подтверждение человеком. Лозунг «учесть риски» бесполезен для агента; правило «mart_customer_360 не содержит колонок из списка запрещённых PII, проверяется ревьюером схемы до релиза» — полезен.
Владелец дата продукта: Человек или роль, которые принимают изменения контракта витрины: согласен ли он с новым полем, готов ли взять на себя последствия смены grain, кому писать при срабатывании алерта freshness. Без владельца спецификация «повисает в воздухе» и дрейф никто не останавливает.
Практические упражнения: Название: Превращение плохой спецификации в проверяемую
Проблема: Дана плохая спецификация витрины: «Сделать витрину клиентов для аналитиков. Добавить полезные поля по счетам и операциям. Проверить качество данных». Перепишите её в формат хорошей спецификации (по образцу customer_360): укажите имя дата-продукта, потребителя, имя витрины, гранулярность, политику PII, свежесть, обязательные факты. Объясните, какие риски закрывает каждый добавленный пункт.
Решение: Шаг 1. Имя дата-продукта и потребитель. Заменяем «для аналитиков» на конкретную роль, например «аналитики клиентского портфеля и отдела кредитных рисков». Это задаёт, кто имеет право требовать изменения. Шаг 2. Имя витрины. Заменяем «витрину клиентов» на mart_customer_360 и указываем слой (models/marts/). Шаг 3. Гранулярность. Добавляем «одна строка на customer_id» — иначе невозможно понять, что считать дубликатом. Шаг 4. PII. Добавляем «в витрине нет прямых идентификаторов: email, phone, passport_number, ИНН». Это закрывает риск утечки персональных данных. Шаг 5. Свежесть. Добавляем «не старше 24 часов» — иначе отчёт может опираться на устаревший снимок. Шаг 6. Обязательные факты. Перечисляем: customer_id unique/not_null, total_balance_rub not_null, accounts_count >= 0, проверка запрещённых PII-колонок проходит. Это и есть «качество данных», превращённое в проверяемые утверждения. Шаг 7. Владелец. Добавляем «владелец: команда клиентской аналитики» — кто принимает дрейф. Каждый пункт закрывает один из пяти классов риска и превращает лозунг в критерий, по которому работу можно отклонить.
Сложность: beginner
Название: Формулировка проверяемых правил для трёх рисков
Проблема: Возьмите любой mart из вашего dbt-проекта (или воображаемый mart_customer_transactions). Напишите для него три риска: (1) grain, (2) PII, (3) дрейф контракта. Для каждого риска сформулируйте не лозунг, а проверяемое правило. Если правило нельзя проверить — перепишите его до команды, SQL или ручного шага ревьюера.
Решение: Пример для mart_customer_transactions: (1) Grain. Лозунг: «одна транзакция на строку». Проверяемое правило: «SELECT COUNT() FROM (SELECT transaction_id FROM mart_customer_transactions GROUP BY transaction_id HAVING COUNT() > 1) должен возвращать 0; ревьюер проверяет, что transaction_id входит в список ключей модели и помечен как unique». (2) PII. Лозунг: «безопасно». Проверяемое правило: «grep -E 'pii_email|phone|passport_number|card_pan' models/marts/mart_customer_transactions.sql должен возвращать пустой результат; ревьюер до релиза прогоняет скрипт list_pii_columns.sql и подтверждает, что список пуст». (3) Дрейф контракта. Лозунг: «контракт стабилен». Проверяемое правило: «при изменении schema.yml в models/marts/ агент обязан сгенерировать отчёт diff_spec.md со списком добавленных/удалённых колонок и положить его в PR; владелец продукта (аналитик клиентского портфеля) оставляет approve-комментарий до мержа».
Сложность: intermediate
Название: Разбор: зелёный dbt build ещё не доказывает правильность
Проблема: В витрине mart_customer_360 все dbt-тесты зелёные: customer_id unique/not_null, total_balance_rub not_null, accepted_values для risk_flag. Однако в витрину случайно попало поле source_system, и часть строк теперь агрегируется по (customer_id, source_system), то есть реальный grain стал «одна строка на (customer_id, source_system)», хотя спецификация обещает «одна строка на customer_id». Какие тесты пропустили бы эту проблему и почему? Что нужно добавить в спецификацию, чтобы поймать такой дрейф заранее?
Решение: Шаг 1. Почему dbt-тесты не сработали. Тесты unique/not_null проверяют отдельные колонки, а не комбинацию. Тест unique на customer_id пройдёт, даже если в таблице две строки с одним и тем же customer_id и разными source_system — он увидит уникальность, если по этому полю группировать наивно (на самом деле провалится, но проблема в том, что grain шире, чем ожидалось). Тест accepted_values на risk_flag вообще не связан с grain. Таким образом, dbt-тесты видят форму, но не видят семантику grain. Шаг 2. Что должно быть в спецификации. Явное утверждение: «гранулярность = одна строка на customer_id», «source_system не входит в grain и не должен присутствовать в финальной витрине», «перечень допустимых колонок фиксирован в ODCS». Шаг 3. Какие проверки это включает. Кастомный dbt-тест, который считает COUNT(DISTINCT customer_id) и сравнивает с COUNT(*): если не равны, тест падает. Ручной шаг ревьюера: сверить список колонок витрины с ODCS-контрактом до мержа. Алерт владельцу: если в diff_spec.md появилась колонка source_system, требуется approve владельца продукта.
Сложность: intermediate
Название: Где фиксировать политику PII
Проблема: Команда спорит, где лучше зафиксировать политику PII для витрины клиентов: (а) в чате команды, (б) в SQL-комментарии в начале модели, (в) в спецификации (ODCS/ODPS/спецификация модели). Выберите вариант и обоснуйте, опираясь на идею проверяемого правила. Дополнительно: предложите, как превратить выбранный вариант в автоматическую проверку.
Решение: Шаг 1. Выбор варианта. Правильный ответ — (в) спецификация. Чат (а) — это место, где договорённости забываются через неделю и невидимы новым участникам команды, включая агента. SQL-комментарий (б) ближе, но комментарий — это документация без владельца и без автоматической проверки: его можно случайно удалить, и никто не заметит. Спецификация (в) фиксирует политику как обязательство: у неё есть владелец, версия, она сравнивается с реальной схемой. Шаг 2. Автоматизация. (1) В ODCS перечисляются разрешённые и запрещённые колонки. (2) Перед релизом запускается скрипт list_pii_columns.py, который читает schema.yml в models/marts/ и сравнивает со списком запрещённых — если найдено совпадение, релиз блокируется. (3) В отчёте ревьюера (review_report.md) фиксируется: «список запрещённых PII сверил, совпадений нет» — это превращает ручной шаг в воспроизводимую проверку. Шаг 3. Связь с принципом главы. Любая политика должна превращаться в команду, SQL, ручной шаг ревьюера или подтверждение человеком. Чат не даёт ни одного из этих четырёх.
Сложность: intermediate
Название: Контрольные вопросы главы
Проблема: Ответьте развёрнуто на три контрольных вопроса из источника: (1) Почему зелёный dbt build не доказывает правильность дата-продукта? (2) Какой дефект опаснее — синтаксическая ошибка SQL или незаметная смена grain? (3) Где лучше фиксировать политику PII — в чате, SQL-комментарии или спецификации?
Решение: (1) dbt build доказывает только то, что граф моделей исполнился без ошибок и что заявленные тесты прошли. Он не проверяет, что гранулярность соответствует обещанию, что в витрине не появились лишние колонки, что смешение сущностей (например, клиент и счёт) не произошло, что учебный риск-флаг не выдан за боевой скоринг. Это граница инструмента: тесты ловят форму и часть фактов, но не семантику продукта. (2) Незаметная смена grain опаснее. Синтаксическая ошибка SQL ломает пайплайн — её видно сразу, она блокирует релиз. Смена grain не ломает ничего: тесты зелёные, отчёт строится, но цифры становятся ложными и эта ложь расходится по всем нижестоящим витринам и регулярной отчётности. Именно поэтому grain фиксируется в спецификации отдельно, как обязательство владельца. (3) В спецификации. Чат не имеет версии, владельца и автоматической проверки. SQL-комментарий лучше, но тоже легко теряется и не имеет владельца. Спецификация (ODCS/ODPS/спецификация модели) — это обязательство с владельцем, версией и возможностью автоматически сверить схему витрины с контрактом перед релизом.
Сложность: beginner
Кейсы: Название: Кейс 1. Дрейф grain в витрине customer_360 учебного банка
Сценарий: Аналитик клиентского портфеля учебного банка попросил команду данных добавить в витрину mart_customer_360 поле source_system, чтобы можно было отслеживать, из какой системы пришёл клиент (мобильный банк, отделение, партнёрская программа). Агент, получивший задачу, добавил колонку в SELECT, обновил schema.yml, прогнал dbt build — все тесты зелёные. Спецификация витрины была написана ранее в общем виде и не упоминала ни source_system, ни список допустимых колонок.
Задача: Через месяц отдел кредитных рисков начал жаловаться, что их отчёт по клиентской базе двоит данные: один и тот же клиент учитывается дважды, потому что теперь он приходит из двух систем одновременно. Аналитик потратил день, чтобы понять, что grain витрины фактически изменился с «одна строка на customer_id» на «одна строка на (customer_id, source_system)», хотя этого никто не согласовывал. Синтаксических ошибок нет, dbt-тесты по-прежнему зелёные, но отчётность развалилась.
Решение: Команда данных провела три действия. (1) Восстановила grain, временно удалив source_system из витрины и оставив его в промежуточном слое models/intermediate/. (2) Уточнила спецификацию mart_customer_360: явно записала «grain = одна строка на customer_id», «перечень допустимых колонок фиксирован в ODCS», «любое добавление колонки требует отчёта diff_spec.md и approve владельца продукта». (3) Добавила кастомный dbt-тест, который сравнивает COUNT(DISTINCT customer_id) и COUNT(*) на витрине: при расхождении тест падает. (4) Ввела обязательный ручной шаг ревьюера перед мержем: сверить schema.yml витрины с ODCS-контрактом и приложить ссылку к PR.
Результат: Витрина вернулась к обещанному grain за один релиз. Кастомный тест и ручной шаг ревьюера сделали бы такой дрейф невозможным в принципе, потому что добавление source_system без явного решения владельца блокировалось бы на этапе code review. Команда оценила происшествие как «полезный удар»: оно показало, что «зелёный dbt build» не равен «продукт можно использовать», и ускорило внедрение многослойной спецификации во всех витринах проекта.
Извлечённые уроки: Синтаксически корректная витрина с зелёными тестами может быть семантически сломана — форма не равна смыслу.
Grain — это обещание, которое нельзя вывести из тестов; его нужно явно записать в спецификации и закрыть отдельным тестом на COUNT(DISTINCT).
Добавление «безобидной» колонки в SELECT может незаметно изменить grain и сломать всю нижестоящую отчётность.
Политика «нельзя менять контракт без владельца» должна быть выражена в виде обязательного шага ревьюера, а не фразы в чате.
Связанные концепции: Grain_гранулярность
Дрейф_контракта
Слои_спецификаций_в_SDD_Data
Зелёный_dbt_build_vs_пригодные_данные
Приёмочные_факты_acceptance_facts
Название: Кейс 2. Утечка PII через «безопасную» витрину операций
Сценарий: Команда данных построила mart_customer_transactions — витрину операций клиентов для антифрод-аналитиков. По спецификации витрина должна была содержать только агрегаты (сумма операций за 7 дней, число операций, средний чек) и не содержать прямых идентификаторов. Агент сгенерировал модель, добавив «для отладки» колонку phone и поле card_pan в первые 100 строк. dbt-тесты на not_null прошли, владелец продукта посмотрел PR мельком и замёржил.
Задача: Через две недели выяснилось, что витрина регулярно используется в дашборде, к которому имеют доступ аналитики смежных подразделений, не имеющие права работать с персональными данными клиентов. Колонки phone и card_pan формально не нужны антифроду, но попали в выгрузку и попали в ad-hoc отчёты. Юридическая служба запросила объяснения.
Решение: Команда провела срочный аудит: удалила PII-колонки из витрины, перенесла их вовсе (они не были нужны в mart-слое). Затем внедрила четыре барьера. (1) В ODCS явно перечислила запрещённые колонки: pii_email, phone, passport_number, card_pan, ИНН. (2) Создала pre-commit скрипт list_pii_columns.py, который грепит models/marts/ по списку запрещённых и блокирует коммит при совпадении. (3) Добавила в спецификацию mart_customer_transactions пункт «PII: в витрине нет прямых идентификаторов; проверка ревьюером обязательна до релиза». (4) Ввела обязательный шаг в отчёте ревьюера: «список запрещённых PII сверил, совпадений нет, дата, подпись», который кладётся в PR.
Результат: Утечка данных закрыта, процессы ужесточены. В течение следующего месяца pre-commit скрипт дважды сработал на других моделях и предотвратил попытки добавить phone и email «для отладки». Антифрод-аналитики отметили, что качество работы не пострадало — им действительно были нужны только агрегаты. Юридическая служба закрыла инцидент без претензий, поскольку команда смогла показать, что политика PII теперь выражена в виде проверяемых правил, а не лозунгов.
Извлечённые уроки: «Добавить для отладки» — типичный путь попадания PII в продакшен-витрину; отладка должна жить в staging/intermediate слоях, а не в marts.
Лозунг «не раскрывать персональные данные» бесполезен, если не превращён в конкретный список запрещённых колонок и автоматическую проверку.
PII-политику нужно фиксировать в спецификации, а не в SQL-комментариях и не в чате — иначе у неё нет владельца и нет возможности автоматически её исполнить.
Многослойная защита (ODCS + pre-commit + ручной шаг ревьюера + отчёт) ловит то, что пропускает один барьер.
Связанные концепции: PII_и_прямые_идентификаторы
Проверяемое_правило_против_лозунга
ODCS_и_ODPS
Слои_спецификаций_в_SDD_Data
Название: Кейс 3. Спорная интерпретация risk_flag в учебной витрине
Сценарий: В витрине mart_customer_360 появилась колонка risk_flag со значениями {low, medium, high}. В источнике она формируется как учебный сигнал «клиент участвовал в тренировочной антифрод-кампании». Спецификация витрины описывает risk_flag как «агрегированный риск-индикатор», без уточнения, что это учебный сигнал, а не боевой скоринг. dbt-тест accepted_values на {low, medium, high} зелёный.
Задача: Через квартал отдел кредитных рисков начал использовать mart_customer_360 как источник для предварительного скоринга. Они взяли risk_flag как готовый признак и включили его в модель расчёта лимита. На квартальном совещании выяснилось, что «high» в витрине на самом деле означал не «высокий риск», а «клиент участвовал в обучающей выборке» — то есть сигнал инвертирован по смыслу. Ошибка не привела к реальным потерям (это учебный банк), но процесс был опасен.
Решение: Команда провела разбор. (1) Переименовала колонку в training_risk_flag, чтобы имя само говорило о природе данных. (2) Обновила ODCS и спецификацию: добавила раздел «семантика и ограничения применимости», где явно указано, что training_risk_flag — это метка принадлежности к учебной выборке, а не скоринговый вывод, и использовать её в боевых моделях запрещено. (3) Добавила в описание колонки в schema.yml предупреждение, которое появляется в сгенерированной документации dbt. (4) Ввела обязательный шаг: если кто-то добавляет в mart колонку со словом risk или score, ревьюер обязан приложить к PR подтверждение владельца продукта о природе поля.
Результат: Отдел кредитных рисков перестал использовать mart_customer_360 как источник скоринговых признаков и переключился на отдельную витрину боевого риск-скоринга. Семантическая путаница устранена. Команда внедрила практику «любое поле с чувствительным именем (risk, score, limit, status) требует явного описания семантики в спецификации», что снизило вероятность подобных ошибок в будущем.
Извлечённые уроки: Имя колонки и тест на accepted_values не защищают от ложной семантики — значение «high» в одном контексте означает одно, в другом — другое.
dbt-тесты ловят форму, но не интерпретацию: семантика — ответственность спецификации.
В SDD Data важно не только «какие поля есть», но и «как поле НЕЛЬЗЯ использовать» — это тоже часть контракта.
Опасные имена колонок (risk, score, limit) требуют отдельного процесса ревью — иначе их легко принять за готовый продукт.
Связанные концепции: Дрейф_контракта
Приёмочные_факты_acceptance_facts
Проверяемое_правило_против_лозунга
ODCS_и_ODPS
Советы по изучению: Держите под рукой реальный (или игрушечный) mart из вашего dbt-проекта: главу легче понять, когда вы одновременно переписываете спецификацию своей витрины, а не абстрактного customer_360.
Возьмите за правило: после любого абзаца спецификации спрашивать себя «а как я это проверю?». Если ответа нет — перепишите абзац до команды, SQL, ручного шага ревьюера или подтверждения человеком.
Сравнивайте «плохую» и «хорошую» спецификации не на уровне длины, а на уровне проверяемости: хорошая выглядит уже, потому что в ней почти нет места угадыванию.
Тренируйтесь на превращении лозунгов («обеспечить качество», «учесть риски») в проверяемые правила — это главный навык главы и главный источник ошибок в продакшене.
Помните, что «зелёный dbt build» — это отправная точка, а не финиш. После него спрашивайте: «а правильный ли grain? а нет ли лишних колонок? а правильно ли я понял семантику risk_flag?».
Используйте чек-лист «пять классов риска» как привычку: для любой новой витрины спрашивайте, учтены ли PII, платежи, согласия, кредитный портфель и воспроизводимость отчётности.
Не пишите в AGENTS.md «соблюдай банковские требования»: для агента это пустая фраза. Лучше перечисляйте конкретные запреты, разрешённые входные модели, поля контракта и проверки.
Заведите отдельный файл «Заметки о рисках данных» с разделами PII / Grain / Freshness / Дрейф контракта / Подтверждения человеком — глава прямо просит такой артефакт, и он действительно помогает в ежедневной работе.
Учитесь писать спецификации «от противного»: сначала представьте, как именно ревьюер или агент сломает витрину (добавит лишнюю колонку, сменит grain, использует учебный флаг как боевой), и закрывайте именно эти пути в спецификации.
Различайте «таблица построилась» и «данные можно использовать»: первое — технический факт, второе — продуктовое обязательство. В банковском домене они расходятся чаще, чем кажется.
Дополнительные ресурсы: Open data contract standard (odcs): Стандарт технического контракта данных от AIDA Data Council. Описывает поля, типы, владельцев, ограничения. Используется в SDD Data как слой технического контракта.
Open data product standard (odps): Стандарт описания дата-продукта от AIDA Data Council. Описывает потребителя, задачу, SLA, приёмочные критерии. Используется в SDD Data как слой продуктового контракта.
Dbt documentation: tests: Раздел официальной документации dbt про тесты (generic tests not_null, unique, accepted_values, relationships; custom tests через singular SQL). Источник сведений о том, что именно ловят dbt-тесты.
Dbt documentation: sources и freshness: Раздел документации dbt про источники и настройку source freshness. Помогает закрыть слой свежести данных в спецификации.
Блог dbt labs: «why data tests are not enough»: Серия материалов dbt Labs о границах автоматического тестирования данных. Подкрепляет идею главы о многослойной защите.
Gdpr и 152-фз (русскоязычные источники): Нормативная база по работе с персональными данными в ЕС и РФ. Полезна как контекст для понимания, почему PII-политика в банке должна быть выражена в виде конкретных правил, а не лозунгов.
Книга «fundamentals of data engineering» (joe reis, matt housley): Современный учебник по дата-инженерии, в котором подробно разбираются контракты данных, lineage, качество и воспроизводимость — концептуальный фундамент для идей главы.
Блог datafold и ресусы по data contracts: Материалы по data contracts и data diffing. Полезны для понимания того, как автоматически ловить дрейф контракта между версиями витрины.
Резюме: Главный вызов банковских данных — не сложность SQL, а то, что ошибка часто выглядит нормально: таблица собрана, тесты зелёные, но смысл уже сломан. Поэтому в банковском домене особенно важна дисциплина спецификаций: любое утверждение о данных должно превращаться в команду, SQL, ручной шаг ревьюера или подтверждение человеком. В главе вводятся пять классов риска (PII, платежи, согласия, кредитный портфель, отчётность), пять слоёв защиты (dbt-тесты, ODCS, ODPS, спецификация модели, отчёт ревьюера) и ключевой навык — отличать «таблица построилась» от «данные можно использовать». Практический результат главы — заполненный файл «Заметки о рисках данных» с конкретными, проверяемыми правилами для PII, grain, freshness, дрейфа контракта и человеческих подтверждений. Узкая, проверяемая спецификация всегда лучше широкого лозунга: именно узость делает работу отклоняемой, а значит — управляемой.