Фреймворк качества¶
Полный справочник по типам правил, уровням критичности, конфигурации и модели безопасности Kruma Quality Validator.
Версия: 1.0.1 | Владелец: Kruma Platform Team
Маппинг на DMBOK¶
Quality Validator реализует 6 измерений качества данных по DAMA-DMBOK:
| Измерение DMBOK | Определение | Типы правил Kruma |
|---|---|---|
| Полнота | Доля данных от потенциально возможных 100% | NOT_NULL |
| Уникальность | Ни один экземпляр не записан дважды | UNIQUE |
| Своевременность | Данные отражают реальность на нужный момент | FRESHNESS |
| Корректность | Данные соответствуют синтаксису определения | RANGE, REGEX, FORMAT, ENUM |
| Точность | Данные верно описывают реальный объект | CUSTOM, SQL, REFERENCE |
| Согласованность | Нет различий при сравнении представлений | CUSTOM (кросс-поля) |
Справочник типов правил¶
NOT_NULL¶
Проверяет, что поле присутствует и не null.
- name: order_id_required
field: order_id
type: not_null
severity: error
message: "order_id is required"
- Возвращает ошибку, если значение
Noneили отсутствует - Не проверяет пустые строки (используйте REGEX)
UNIQUE¶
Уникальность в рамках текущего батча.
- name: order_id_unique_in_batch
field: order_id
type: unique
severity: error
message: "Duplicate order_id in batch"
- Отслеживает виденные значения в
RuleEngine._unique_values - Первое вхождение проходит, дубликаты — нет
- Состояние сбрасывается между батчами (настраивается через
reset_unique_tracking) Noneпропускается (используйте NOT_NULL)
RANGE¶
Числовой диапазон значений.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
min | float | Нет | Минимальное значение (включительно) |
max | float | Нет | Максимальное значение (включительно) |
- name: amount_positive
field: total_amount
type: range
min: 0
max: 10000000
severity: error
message: "Amount must be between 0 and 10,000,000"
- Преобразует значение в float
- Поддерживает односторонние границы (только min или только max)
- Нечисловые значения — ошибка
REGEX¶
Соответствие регулярному выражению.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
pattern | str | Да | Python regex-паттерн |
- name: order_id_format
field: order_id
type: regex
pattern: "^ord_[a-z0-9]{12}$"
severity: error
message: "order_id must match format ord_xxxxxxxxxxxx"
- Использует
re.match()(привязка к началу) - Конвертирует значение в строку перед проверкой
Noneпропускается
ENUM¶
Значение из предопределённого набора.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
values | list | Да | Список допустимых значений |
- name: status_valid
field: status
type: enum
values: [draft, pending, confirmed, shipped, delivered, cancelled]
severity: error
message: "Invalid order status"
- Точное сравнение (case-sensitive)
- Поддерживает строки, числа и другие сравнимые типы
FRESHNESS¶
Свежесть временной метки.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
max_age_minutes | int | Да | Максимальный возраст в минутах |
- name: created_at_fresh
field: created_at
type: freshness
max_age_minutes: 60
severity: error
message: "Data is stale (older than 1 hour)"
Поддерживаемые форматы:
- ISO 8601:
"2026-01-23T10:30:00Z","2026-01-23T10:30:00+03:00" - Unix timestamp (секунды):
1737625800 - Python
datetime
FORMAT¶
Предопределённые форматы.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
format | str | Да | Имя формата |
Доступные форматы:
| Формат | Пример |
|---|---|
email | user@example.com |
uri | https://api.example.com |
uuid | 550e8400-e29b-41d4-a716-446655440000 |
ipv4 | 192.168.1.1 |
phone | +71234567890 |
- name: email_format_valid
field: customer_email
type: format
format: email
severity: warning
message: "Invalid email format"
CUSTOM¶
Python-выражение с доступом к полям записи.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
expression | str | Да | Python boolean-выражение |
- name: discount_not_exceeds_total
field: discount_amount
type: custom
expression: "discount_amount is None or discount_amount <= total_amount"
severity: error
message: "Discount cannot exceed total amount"
Доступно в контексте выражения:
- Все поля записи как переменные
- Безопасные функции:
len,str,int,float,bool,abs,min,max,sum,round - Константы:
True,False,None,null(алиас для None) - Отсутствующие поля →
None(не KeyError)
Примеры выражений:
# Кросс-полевая валидация
expression: "discount_amount is None or discount_amount <= total_amount"
# Проверка массива
expression: "len(items) > 0"
# Условная логика
expression: "status != 'shipped' or shipped_at is not None"
# Null-safe сравнение
expression: "shipped_at is null or shipped_at >= created_at"
SQL (Планируется)¶
Не реализовано в v1.0.1
Валидация через SQL-запросы к базе данных. Доступна заглушка с информативным сообщением.
- name: customer_exists
field: customer_id
type: sql
sql_query: "SELECT 1 FROM customers WHERE id = :customer_id"
severity: error
REFERENCE (Планируется)¶
Не реализовано в v1.0.1
Валидация ссылочной целостности через lookup-таблицы.
- name: currency_valid
field: currency
type: reference
reference_table: currencies
reference_field: code
severity: error
Уровни критичности¶
| Severity | Эффект | Когда использовать |
|---|---|---|
| error | Запись → DLQ | Критичные: отсутствие обязательных полей, нарушение бизнес-правил |
| warning | Лог, запись → PROD | Некритичные: формат email, редкие значения |
| info | Только метрики | Мониторинг: крупные заказы, аномалии |
Логика маршрутизации¶
graph TD
A[Запись] --> B{Есть ERROR?}
B -->|Да| C[DLQ]
B -->|Нет| D{Есть WARNING?}
D -->|Да| E[Лог + PROD]
D -->|Нет| F[PROD] Дерево решений по severity¶
Поле обязательно для downstream?
ДА → severity: error
Плохие данные лучше, чем нет данных?
ДА → severity: warning
Только для мониторинга?
ДА → severity: info
Модель безопасности custom-выражений¶
Custom-выражения выполняются в sandbox-окружении:
| Контроль | Реализация |
|---|---|
| Нет импортов | __import__ удалён из builtins |
| Нет файлового I/O | open, exec, eval недоступны |
| Нет системного доступа | os, sys, subprocess недоступны |
| Ограниченные builtins | Только безопасные функции |
Разрешённые функции:
_SAFE_BUILTINS = {
"len", "str", "int", "float", "bool",
"abs", "min", "max", "sum", "round",
"True", "False", "None", "null",
}
Конфигурация правил (YAML)¶
# quality_rules.yml
rules:
- name: rule_identifier # snake_case идентификатор
field: field_name # Путь к полю (поддержка dot notation)
type: rule_type # not_null|unique|range|regex|enum|freshness|format|custom
severity: error # error|warning|info (по умолчанию: error)
message: "Human message" # Сообщение для отладки
# Параметры по типу
min: 0 # range
max: 1000 # range
pattern: "^[a-z]+$" # regex
values: [a, b, c] # enum
max_age_minutes: 60 # freshness
format: email # format
expression: "x > 0" # custom
Вложенные поля (dot notation)¶
Обращается к record["customer"]["contact"]["email"].
Формат DLQ-записи¶
Невалидные записи оборачиваются в DLQRecord с полным контекстом:
{
"original_record": { ... },
"validation_errors": [
{
"rule_name": "order_id_required",
"field": "order_id",
"expected": "non-null value",
"actual": null,
"severity": "error",
"message": "order_id is required"
}
],
"metadata": {
"contract_namespace": "sales",
"contract_name": "orders",
"contract_version": "2.1.0",
"source_topic": "sales.orders.raw",
"timestamp": "2026-01-23T10:30:00.123456+00:00",
"validator_version": "1.0.1",
"trace_id": null
}
}
Шпаргалка¶
| Тип | Параметры | DMBOK |
|---|---|---|
not_null | — | Полнота |
unique | — | Уникальность |
range | min, max | Корректность |
regex | pattern | Корректность |
enum | values | Корректность |
freshness | max_age_minutes | Своевременность |
format | format | Корректность |
custom | expression | Точность |
sql | sql_query | Точность (план) |
reference | reference_table, reference_field | Точность (план) |