0037. Формат экспорта досудебной претензии: DOCX (Unicode-native), а не PDF
Копия ADR из репозитория:
backend/docs/adr/0037-claim-export-format.md. Канонический текст — в репозитории; портал обновляется командойnpm run sync:adr.
- Статус: accepted (2026-07-09)
- Дата: 2026-07-09
- Связанные задачи: OP-137 (хранение истории + экспорт документа); соседи — OP-136 (подстановка/редактирование,
ClaimEntity), OP-134/135 (модель шаблонов, генерация текста) - Связанные ADR: —
Контекст и проблема
ТЗ 5.12 (AC OP-137) требует экспорт документа претензии «по умолчанию PDF/DOCX», формат «согласуется отдельно». Текст претензии — русскоязычный (кириллица). Нужен один формат для MVP: универсальный, корректно отображающий кириллицу, реализуемый без тяжёлой инфраструктуры и тестируемый детерминированно.
Ключевое техническое ограничение вскрылось на этапе реализации: PDF + кириллица требует
встраивания TTF-шрифта. Стандартные PDF-шрифты (pdfkit → Helvetica и т.п.) содержат только
латиницу; для кириллицы нужно поставлять и грузить в рантайме бинарный TTF-ассет (лицензия,
путь загрузки в prod-сборке dist/, усложнение юнит-тестов генерации). Изначальная
авто-рекомендация цикла (/op architectural-stop, авто-выбор по таймауту) называла PDF —
до обнаружения этой стоимости.
Решение
Экспорт — DOCX (OOXML), библиотека docx (pure-JS, без нативных зависимостей).
Причины предпочесть DOCX перед PDF:
- Unicode-native: OOXML хранит текст в UTF-8, кириллица работает без встраивания шрифтов и бинарных ассетов — Word/просмотрщик применяет системный шрифт.
- Редактируемость: досудебная претензия — черновик, который селлер дорабатывает и печатает; DOCX редактируем, в отличие от PDF.
- Простота и тестируемость: одна pure-JS зависимость; результат — валидный ZIP-контейнер
(
PK-сигнатура), детерминированно проверяется в юнит-тесте без шрифтовых ассетов. - Соответствие AC: DOCX явно указан в критериях приёмки как допустимый формат по умолчанию.
Сборка документа выделена в чистый модуль claim-docx.builder.ts
(buildClaimDocx/selectClaimText/claimDocxFilename). Итоговый текст — правка
(editedText), иначе исходная генерация (generatedText). Эндпоинт
GET /legal/claims/:id/export отдаёт вложение через StreamableFile
(Content-Disposition: attachment).
Последствия
- Положительные: нулевая стоимость поддержки кириллицы; редактируемый выход; лёгкая
зависимость; простые тесты; история и экспорт закрывают OP-137 без новой сущности
(переиспользуется
ClaimEntityиз OP-136). - Trade-offs: PDF (неизменяемый «финальный» вид) не поставляется в MVP. Если он понадобится (печать с фиксированной вёрсткой), добавляется отдельным форматом — тогда решается вопрос встраивания кириллического шрифта (OFL TTF) отдельным решением.
- Обратимость: формат инкапсулирован в билдере и MIME/имени файла контроллера; добавление
второго формата (query-параметр
format) не ломает контракт существующего эндпоинта.