Обмен с ядром на core NATS: подписка queue group, ack status=processing сразу по получении, process-local LRU job_id против повторных запросов, публикация результата с повторами; удалены durable consumer / max_deliver / ack_wait. Dockerfile python:3.11-slim; make check / make check-full вместо CI; raisa_* фильтруются при dev-установке. Обновлены proposal, design (решения без обсуждения), specs, tasks, CLAUDE.md, openspec/config.yaml. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4.7 KiB
Spec Delta: data-model
Purpose
Схема базы данных ядра совпадает с моделью данных DBML v5.13 один в один: таблицы, колонки, типы, enum'ы, ключи и индексы; миграции применяются к пустой базе и полностью откатываются; расхождение между ORM и DBML невозможно пропустить.
ADDED Requirements
Requirement: Схема БД равна DBML v5.13
ORM-метаданные SHALL содержать ровно 43 таблицы и 27 enum'ов из ../docs/model/data-model-v5.13.dbml в схеме dkb;
имена таблиц, колонок, enum'ов и их значений SHALL совпадать с DBML буквально; nullability, PK, UNIQUE, FK, значения
по умолчанию и индексы SHALL соответствовать DBML, включая частичные уникальные индексы (related_group_member
WHERE is_current, consolidation_lock WHERE released_at IS NULL) и NULLS NOT DISTINCT на
document (stored_file_id, document_type, osv_account_code). Поля, отсутствующие в DBML, MUST NOT существовать.
Scenario: Сверка ORM с DBML
- WHEN выполняется
python scripts/check_dbml_vs_orm.py ../../docs/model/data-model-v5.13.dbml - THEN вывод пуст и код возврата 0
Scenario: Лишняя колонка в ORM
- WHEN в ORM добавлена колонка, которой нет в DBML (или удалена существующая)
- THEN скрипт печатает
таблица.колонка: отсутствует в DBML(илиотсутствует в ORM) и возвращает код 1
Scenario: Расхождение типа или nullability
- WHEN колонка
osv_entry.opening_debitобъявлена в ORM какNumeric(18, 4)илиNOT NULL - THEN скрипт сообщает
ожидалось numeric(18,2) NULL / фактически numeric(18,4) NOT NULLи возвращает код 1
Requirement: Миграции применяются с нуля и откатываются
Единственная ревизия 0001 SHALL создавать схему dkb (если нет), все enum'ы, таблицы, ограничения и индексы на пустой
базе PostgreSQL 16 (требуется ≥ 15); downgrade SHALL удалять всё созданное, оставляя пустую схему; повторный upgrade после downgrade
SHALL проходить без ошибок.
Scenario: Полный цикл
- WHEN на пустой БД выполняются
alembic upgrade head,alembic downgrade base,alembic upgrade head - THEN все три команды завершаются успешно, после последней в
information_schema.tablesсхемыdkb43 таблицы и вpg_type27 enum-типов
Scenario: Автогенерация ничего не находит
- WHEN после
upgrade headвыполняетсяalembic revision --autogenerateна той же БД - THEN сгенерированная ревизия не содержит операций (пустые
upgrade/downgrade)
Requirement: Версия DBML зафиксирована в коде
Пакет моделей SHALL объявлять константу версии DBML (5.13); скрипт сверки SHALL сравнивать её с версией в шапке файла
DBML и падать при расхождении — смена модели без осознанного обновления ORM невозможна.
Scenario: Новая версия DBML без обновления ORM
- WHEN в
docs/model/появляетсяdata-model-v5.14.dbml, а константа в ORM —5.13 - THEN сверка против нового файла падает с сообщением о версии до сравнения таблиц
Requirement: Деньги и проценты — точные типы
Все денежные колонки SHALL быть numeric(18,2), проценты — numeric(7,4)/numeric(9,4), уверенность — numeric(5,2);
ORM SHALL отдавать их как Decimal, float в моделях MUST NOT встречаться.
Scenario: Чтение денежной колонки
- WHEN из
osv_entryчитается строка соclosing_debit = 106311116.46 - THEN значение имеет тип
Decimalи равноDecimal("106311116.46")