КОНТРОЛЬ КАЧЕСТВАP0L3

Сквозная lineage финансового показателя

Как связать ячейку выпуска отчёта с версиями проводок и событий, проверить вклады и явно ограничить детализацию drill-back.

Справочный материал. Контракты данных, архитектурные решения и ограничения применения. Источники приведены в материалах, где используются внешние основания.

Задача и границы#

Для выбранной ячейки выпущенного отчёта нужно объяснить, какие версии данных и преобразований дали её значение. Путь должен вести через статью отчётности к строкам проводок и исходным событиям, сохраняя контекст конкретного выпуска. Ссылка на текущую таблицу вместо исторического входа этой задачи не решает.

Здесь рассматривается аддитивный показатель движений одной валюты без распределений, конвертации и консолидационных исключений. Это предлагаемый инженерный контракт со статусом knowledge, а не описание опыта автора или новой лабораторной реализации. Правила выбора соответствий счетов уже разобраны в отдельной статье; здесь они используются как закреплённая зависимость.

Зерно, ключи и время#

Зерно результата - одна ячейка в конкретном выпуске: release_id, форма и её версия, статья, юридическое лицо, регистр, период, валюта и масштаб. Координаты строки и столбца интерфейса не являются устойчивым ключом: сортировка отчёта может измениться. Сумма задана целыми копейками RUB; дебет положительный, кредит отрицательный, множитель знака представления сохраняется отдельно.

Входное зерно - версия строки проводки. Логический ключ включает источник, юридическое лицо, регистр, документ и номер строки; line_version_id определяет выбранное состояние. Версия события определяется ключом источника и идентификатором версии. Одно событие может дать несколько строк, а одна строка может зависеть от нескольких событий: связь не следует считать взаимно однозначной.

business_date определяет включение в период, observed_at фиксирует получение версии EDWH. Выпуск сохраняет бизнес-границы периода, cutoff доступности и идентификатор входного снимка. Время запуска преобразования не заменяет эти координаты. Правила доступности и поздних изменений заданы контрактом закрытия периода.

Два вида связей#

Техническая lineage показывает зависимость набора или колонки от других наборов и преобразований. Финансовый drill-back дополнительно требует конкретных ключей записей и вкладов в выбранную ячейку. Знание, что таблица отчёта построена из журнала, не определяет, какие строки дали конкретную сумму.

W3C PROV-DM, рекомендация 2013 года, определяет сущности, деятельности и отношения происхождения. Снимок входа можно представить сущностью, расчёт - деятельностью, результат - созданной сущностью. Такая интерпретация не устанавливает бухгалтерские правила и не предписывает предлагаемую ниже структуру вкладов.

OpenLineage 1.53.0 описывает задания, запуски и наборы данных; column lineage facet описывает зависимости выходных полей от входных. Эти метаданные полезны для технического графа, но сами по себе не являются реестром вкладов отдельных проводок. Интеграция OpenLineage в проект здесь не добавляется.

Контракт происхождения выпуска#

Объект Что сохранять
Манифест выпуска Ключи ячеек, снимок входа, временные границы, валюту и масштаб
Преобразование Идентификатор запуска, неизменяемую версию кода, параметры и зависимости
Правила Версии соответствий, структуры отчёта, календаря и знаков
Вклад Ключ ячейки, версию строки, правило, сумму вклада и единицу
Происхождение строки Связи версии строки с версиями исходных событий и приёмными партиями
Контроль Проверенный набор, правило контроля, результат и обнаруженные нарушения

Реестр вкладов хранит одну запись на пару «ячейка - версия строки» в этой упрощённой модели. Связи с событиями хранятся отдельно: соединение вкладов со всеми событиями может размножить сумму. Суммируют реестр вкладов, а события используют для объяснения происхождения. Нельзя складывать сумму события с суммами его проводок.

Идентификатор версии или хеш не заменяет доступное содержимое. Для воспроизведения сохраняют входные данные и используемые правила либо обеспечивают их извлечение из неизменяемого хранилища. Версия кода без параметров и зависимостей также недостаточна. Сроки хранения и права доступа согласуются отдельно; эта статья не задаёт юридический срок хранения.

Построение и контроль вкладов#

Следующая последовательность - псевдокод, не исполняемый SQL или Python:

Закрепить выпуск, входной снимок и версии преобразований.
Выбрать строки по согласованным бизнес-границам и cutoff доступности.
Получить проверенную классификацию строк выбранным набором правил.
Сохранить вклады с ключами ячеек и версиями строк до агрегации.
Отдельно сохранить связи строк с исходными событиями.
Рассчитать ячейки из реестра вкладов с закреплённым правилом знака.
Сверить ключи, единицы, суммы вкладов и доступность цепочки происхождения.
Зафиксировать результат и контрольный протокол одного выпуска.

Синтетический пример: ячейка статьи A содержит две строки L1/v1 и L2/v1 с вкладами +10000 и -2000 копеек RUB. До применения множителя представления сумма равна 8000. Обе строки могут происходить из одного события E1/v1. В drill-back событие показывается один раз со связями к двум строкам; его сумма не прибавляется к 8000.

Проверяют уникальность пар вклада, существование каждой версии строки, соответствие валюты и масштаба, а также равенство суммы вкладов значению ячейки с учётом знака. Отдельно сравнивают ожидаемый набор классифицированных строк с набором вкладов. Равенство сумм не выявляет потерю двух взаимно погашающихся строк. Полнота исходных событий проверяется сверкой наборов, а не наличием технического графа.

Сохранять значение и происхождение желательно как один согласованный выпуск: готовая ячейка с недописанными связями не получает статус полного drill-back. Это общий принцип согласованности, не утверждение о поведении PostgreSQL, SQLite или Greenplum. Конкретная транзакционная реализация здесь не приводится и не тестировалась.

Ограничения drill-back и альтернативы#

Drill-back возвращает границу доступной детализации: до исходного события, только до проводки или только до агрегата. Если источник передал дневной итог, нельзя обещать восстановление отдельных операций. Недоступный архив, удалённые версии и ограничение прав должны давать явную причину, а не пустой список, похожий на отсутствие входов.

Постраничный просмотр показывает число разрешённых вкладов и разрешённый контрольный итог. Первые строки страницы не считаются полным объяснением суммы. Пользователь без прав на детали может видеть разрешённый агрегат и отметку об ограничении; происхождение не должно раскрывать конфиденциальные поля или пути с секретами. Полное число исходных строк тоже требует разрешения.

Материализованный реестр вкладов ускоряет расследование и сохраняет точный состав выпуска, но требует места. Восстановление связей по запросу уменьшает хранение, однако допустимо только при сохранённых входах, правилах и воспроизводимом алгоритме. Гибрид может хранить связи с разделами снимка и вычислять детали внутри них; это ограничение нужно раскрывать в контракте.

Для отношения, среднего или остатка простой суммы вкладов недостаточно. Отношение требует происхождения числителя и знаменателя; остаток - начального состояния и движений; распределение - весов и корректировок округления. Иерархические итоги могут повторно использовать те же строки, поэтому нельзя складывать конечные статьи с их итогами. Эти расширения требуют самостоятельного определения зерна вклада.

Полномочия в защищённом корпоративном контуре#

Следующий контракт относится к корпоративной системе с проверяемой идентичностью пользователя. Публичный статический сайт содержит только справочный текст и синтетические примеры: сюда не добавляются пользователи, авторизация или закрытые данные. Скрытие ссылки в интерфейсе не защищает файл, уже включённый в статическую сборку.

Решение о доступе связывает субъект, действие, объект и контекст запроса. Такой подход согласуется с определением ABAC в NIST SP 800-162, редакция с обновлением 2019 года. Документ описывает модель управления доступом, а не бухгалтерские требования; поля ниже являются проектным выбором.

Часть решения Предлагаемый контракт
Субъект Проверенная идентичность и актуальные полномочия по юридическим лицам
Действие Просмотр агрегата, проводки, исходного события или выгрузка проверяются отдельно
Объект Юридическое лицо, регистр, выпуск, уровень детализации и классификация полей
Контекст Время запроса, версия политики и доверенный контекст корпоративной сессии

Право на агрегат не означает права на проводки, payload события или экспорт. Полномочие для одного юридического лица не распространяется на его контрагента. Дату и снимок финансовых данных закрепляет выпуск, но доступ к старому выпуску проверяют по текущей политике: прежнее разрешение не должно переживать отзыв прав. Для воспроизводимости решения сохраняют версию политики и время проверки, не копируя секреты в журнал.

Проверка выполняется в доверенном контуре до выдачи данных и на каждом переходе от ячейки к строке и событию. Переданный пользователем идентификатор выпуска или строки не доказывает право доступа. Ссылки related и drill-back, поиск, подсказки, счётчики, сообщения об ошибках, выгрузки и кэш используют тот же контракт. Название документа, сниппет, ключ записи или число скрытых строк также могут раскрывать данные. Для отказа выбирают безопасное сообщение, не подтверждающее существование чужого документа. Кэш разделяют по эффективным полномочиям и версии политики; после отзыва нельзя отдавать сохранённый ответ с закрытыми деталями. Асинхронную выгрузку проверяют при формировании и получении; уже скачанный файл отозвать этим способом невозможно.

В PostgreSQL 18 включённая RLS без подходящей политики запрещает строки по умолчанию. Superuser и роли BYPASSRLS обходят RLS; владелец обычно тоже, если не применён FORCE ROW LEVEL SECURITY. Это поведение PostgreSQL, не переносимое обещание для Greenplum или SQLite. RLS сама по себе не задаёт права на поля, поиск или экспорт. Реализация здесь отсутствует.

Итог и доступная детализация#

Для аддитивной ячейки исходного зерна отдельно определяют разрешённый полный итог, сумму разрешённых вкладов и признак полноты объяснения. Сумма видимых строк равна полному итогу только при полном доступе ко всем вкладам того же выпуска, валюты, масштаба и правила знака. При ограничении нельзя обозначать видимую часть как полную сверку.

Синтетический пример: итог разрешённой ячейки равен 8000 копеек RUB, а доступный вклад - 10000. Разность -2000 раскрыла бы сумму скрытого вклада. Поэтому право на полный итог должно учитывать возможность такого вывода. Если сочетание итогов и деталей недопустимо, ограничивают сам итог или набор запросов; простое скрытие строки недостаточно. Разрешённый остаток можно показывать только по явно утверждённой политике, без обещания восстановить скрытые записи.

Внутренний контролёр с отдельным полномочием сверяет полный реестр с выпуском, а читателю выдаётся разрешённый статус контроля. Нельзя менять исторический итог из-за фильтра доступа: отфильтрованный расчёт является отдельным представлением с явно указанной областью. Пагинация не меняет эту область, и сумма одной страницы не равна сумме всех доступных вкладов.

При реализации потребуются отрицательные проверки: прямой запрос чужого ключа, переход к событию другого юридического лица, поиск по закрытому документу, выгрузка после отзыва прав и повтор из кэша. Отдельно проверяют отсутствие утечек через поля и счётчики и корректную маркировку частичного объяснения. Это план проверок, а не выполненные тесты. Исполняемый SQL/Python не добавлен; существующий алгоритм остаётся псевдокодом.

Мост изменений между выпусками#

Lineage объясняет один результат. Мост изменений отвечает на другой вопрос: почему одна и та же ячейка изменилась между выпусками A и B? Сравнивают устойчивый ключ ячейки, период, юридическое лицо или согласованный периметр группы, регистр, валюту, масштаб и знак представления. Если изменились определение показателя или состав компаний, сначала согласуют сопоставимую область либо выделяют отдельный эффект периметра. Без этого разность нельзя называть изменением одной сопоставимой величины.

Для аддитивного денежного показателя определим F(E, R, M, C; Z): E - версии входных событий и их cutoff, R - набор курсов, M - отображения счетов, C - правила корректировок, Z - календарь, код преобразования, параметры, порядок округления и остальные зависимости. Этот мост меняет только E, R, M и C; Z должен совпадать в обоих выпусках. Если изменился Z, его включают как отдельный фактор или признают данную декомпозицию недоступной. Никакое изменение нельзя молча отнести к входным событиям. Контракт курса описан в конвертации валют, классификация - в отображениях счетов, отдельный слой консолидационных корректировок - в исключениях оборотов.

Предлагаемый порядок подстановки - E, затем R, M и C. Сохраняют пять состояний:

Состояние Расчёт Эффект относительно предыдущего
S0 F(EA, RA, MA, CA; Z) Исходное значение выпуска A
S1 F(EB, RA, MA, CA; Z) Входные события
S2 F(EB, RB, MA, CA; Z) Курсы
S3 F(EB, RB, MB, CA; Z) Отображения
S4 F(EB, RB, MB, CB; Z) Правила корректировок

Это математическая схема, не исполняемый SQL/Python. Каждое промежуточное состояние - отдельный диагностический расчёт, а не утверждённый бухгалтерский выпуск. Нельзя просто соединить текущие таблицы с прежними версиями: старые правила могут не покрывать новые счета, а старый набор курсов - новые валюты. Несовместимость отмечают как невозможность данного шага, затем согласуют другую декомпозицию или совместимый периметр. Нулевой курс, пустое соответствие и автоматический выбор текущего правила не являются допустимыми заменами.

Синтетический пример задаёт одну ячейку в целых копейках RUB, дебет положительный, кредит отрицательный; знак представления фиксирован. Пусть диагностические значения S0..S4 равны 10000, 12000, 12600, 11600, 11300. Тогда эффекты равны +2000, +600, -1000, -300; сумма 1300 совпадает с 11300 - 10000. Значения придуманы только для демонстрации арифметики, не получены из лаборатории и не иллюстрируют требования стандарта учёта.

При изменении суммы и курса одновременно взаимодействие факторов попадает в более поздний шаг выбранного порядка. Обратный порядок может дать другие эффекты при том же конечном результате. Поэтому мост фиксирует порядок, а названия эффектов означают последовательные условные изменения, не единственную экономическую причинность. Альтернатива - усреднение по допустимым порядкам; оно требует дополнительных расчётов и отдельного правила распределения взаимодействий. Прямое сравнение реестров вкладов дешевле, но само по себе не отделяет совместное изменение курса и входа.

Контроль и воспроизводимость моста#

Манифест моста хранит ID обоих выпусков, сопоставимый ключ ячейки, порядок факторов, версии всех входов и правил, ID промежуточных расчётов, единицу, округление и контрольные результаты. S0 должен воспроизводить A, S4 - B, а сумма четырёх эффектов - разность B и A. Все сравнения выполняются в одной единице и на одном уровне округления. Если эффекты округляют отдельно для отображения, остаток показывают отдельной строкой по закреплённому правилу, а не прячут в выбранном факторе.

Разность ячеек не заменяет проверку состава: потерянные и добавленные взаимно погашающиеся строки могут дать нулевой эффект. Сравнивают ключи и версии вкладов, отдельно отмечают добавления, удаления и изменения; отсутствие ячейки не приравнивают к нулю без контракта полного покрытия. Перенос строки из статьи A в B объясняет обе ячейки; общий итог может не измениться. Нельзя суммировать эффекты детальных статей вместе с включающими их итогами.

W3C PROV-DM, Recommendation от 30 апреля 2013 года предоставляет сущности, деятельности и отношения происхождения. Применение этих понятий к снимкам и диагностическим расчётам - инженерная интерпретация. PROV не задаёт формулу финансовой атрибуции, порядок подстановки или бухгалтерские корректировки. Здесь также не утверждается конкретное поведение СУБД: транзакционная реализация и SQL не приведены, код не исполнялся.

При ограниченных полномочиях мост наследует контракт доступа обоих выпусков и промежуточных состояний. Даже разрешённая разность может раскрыть скрытый вклад; доступ к одному выпуску не означает доступа к другому. Невоспроизводимый вход, недоступный архив или несовместимые правила дают явное ограничение объяснения, а не статус полного моста.

Вопросы для подготовки: почему смена порядка меняет атрибуцию? Как обнаружить нулевой эффект при смене состава строк? Почему гибридный промежуточный расчёт может быть недопустим, хотя оба конечных выпуска корректны?

Граничные случаи и вопросы#

Проверяют нулевую ячейку с ненулевыми взаимно погашающимися вкладами, пустой вход, повторную загрузку связей, исправление версии события и новый запуск с теми же параметрами. Пустой вход отличают от неполной lineage. Повторная запись не создаёт дубли, а пересчёт создаёт новый выпуск; старые связи не переводятся на текущие версии. Успех задания сам по себе не доказывает полноту происхождения.

Независимые финансовые проверки описаны в сверке данных. Здесь дан проект контракта, а не результат испытания SQL или промышленного решения.

  1. Почему граф зависимостей колонок не позволяет объяснить состав одной ячейки?
  2. Как проверить полноту вкладов, если итог равен нулю?
  3. Что покажет drill-back старого выпуска после исправления исходного события?

Источники и документация

  1. NIST SP 800-162 - ABAC, updated 2019 ↗
  2. PostgreSQL 18 - Row Security Policies ↗
  3. W3C PROV-DM - Recommendation, 30 April 2013 ↗
  4. OpenLineage 1.53.0 - Object Model ↗
  5. OpenLineage 1.53.0 - Column Level Lineage Dataset Facet ↗

Источники нужны для самостоятельной проверки. Примеры и интерпретации на сайте могут быть учебными упрощениями.