# Модуль: Документ **Ответственность**: владеет общей моделью документа, контрактом расширяемого профиля и режимами выпуска независимо от Typst-вёрстки. **Расположение**: `.template/lib/domain/document.typ` ## Публичный интерфейс | Символ | Тип | Описание | |--------|-----|----------| | `document-context()` | конструктор dictionary | Создаёт полный неизменяемый контекст после нормализации и валидации | | `document-profile()` | конструктор dictionary | Создаёт контракт профиля с `id`, `metadata`, `normalize`, `validate`, `render` | | `render-options()` | конструктор dictionary | Нормализует режим выпуска, watermark и media policy | | `validate-profile-contract()` | функция | Проверяет, что расширение содержит все обязательные функции и поля | | `merge-known()` | чистая функция | Объединяет defaults с пользовательскими значениями по явным правилам | ## Зависимости | Модуль | Что использует | |--------|----------------| | Нет | Модуль не импортирует infrastructure или presentation | ## Инварианты - `DocumentProfile.id` — непустая стабильная строка. - `normalize`, `validate` и `render` являются functions. - Режим выпуска принадлежит конечному набору `final`, `draft`, `clean-copy`. - `DocumentContext` создаётся только после успешной валидации company, profile metadata, parties и attachments. - Domain-значения не содержат вызовов `page`, `image`, `place`, `context`, `query` или глобального `state`. - Merge не принимает неизвестные ключи молча: профиль либо объявляет extension bucket, либо возвращает ошибку. ## Намеренно НЕ обрабатывает - Загрузку компании из JSON. - Пагинацию и выбор шрифта. - Физическое наличие файлов. - Состав обязательных полей конкретного отчёта или договора. ## Заметки для агента > `DocumentProfile` — основной extension contract. Не превращайте его в строковый enum со switch в application. Renderer-function является портом presentation, переданным профилем. Для простого пользователя profile constructors скрывают этот контракт; вручную он нужен только разработчику нового вида документа.