# P72 · 2024-02 · Модульный монолит — три прохода саморевью ## Рамка sidecar-партии - Slug: `editorial-2024-02-practice-modular-monolith`, `editorial-2024-02-mechanism-modular-monolith`, `editorial-2024-02-field-modular-monolith`. - Голос: M7, февраль 2024. Автор начинает с цены неявной межмодульной связи, затем ведёт короткую техническую цепочку «симптом → причина → проверка → действие». Тон системный и прагматичный: он называет owner, surface, разрешённое направление и границу доказательства, но не имитирует production-опыт. - Созданы ровно пять sidecar-файлов: этот review, один import-safe script и три локальные SVG. Overlay, README, `articles.json`, очередь, Git и файлы других агентов не менялись; пакет не интегрирован. - Fixture создаёт и проверяет только fixed synthetic JS-объекты в памяти. Он не читает проект, файлы, package graph, environment, CI, сеть, HTTP, trace, часы или production-конфигурацию. Его PASS не заявляет реальный import, границу репозитория, CI result, trace, release decision, надёжность или effect в production. ## Проход 1 — факты, источники и модель - Источники проверены 31.07.2026 и исторически доступны к февралю 2024: [Java Language Specification, Java SE 17, chapter 7](https://docs.oracle.com/javase/specs/jls/se17/html/jls-7.html) различает иерархию package names и доступ, а для named modules фиксирует exported packages и explicit dependencies; [Spring Modulith 1.1 Fundamentals](https://docs.spring.io/spring-modulith/reference/1.1/fundamentals.html) описывает public API, internal packages и allowed dependencies для Spring Boot; [release Spring Modulith 1.1.0](https://github.com/spring-projects/spring-modulith/releases/tag/1.1.0) опубликован 24.11.2023; [release ArchUnit 1.1.0](https://github.com/TNG/ArchUnit/releases/tag/v1.1.0) — 09.08.2023. - Ограничения источников названы в каждой статье. JLS не является моделью доменных модулей для любого языка; Spring Modulith — framework-specific пример, а не требование использовать Spring; ArchUnit release подтверждает доступность инструмента, но не доказывает запуск CI и не выбирает границы приложения. - `inspectSyntheticModuleBoundaries()` принимает только `synthetic-module-boundary-input-v1` с fixed картой четырёх условных модулей: `catalog`, `checkout`, `payments`, `notifications`. Карта не описывает реальный проект. Разрешены только `checkout → catalog.api`, `checkout → payments.api`, `payments → notifications.api`. - Модель проверяет тройку `from → to.surface`, а не имя папки: surface обязан совпасть с опубликованным `*.api`, direction — с fixed allow-list. Она отдельно классифицирует unknown module, non-public surface, forbidden direction, duplicate reference, malformed record, self-dependency и directed cycle. - На самостоятельном модельном проходе проверены отрицательные ветки. Лишний `repositoryUrl` отвергается до какой-либо работы с ним; поле `path` также отвергается, чтобы fixture не создавал впечатления source scan. Проверка цикла идёт только по уже переданным memory references. Функция возвращает `projectScan=not-performed`, `filesystem=not-read`, `ci=not-touched`, `network=not-used`, `releaseAuthority=not-granted`. - `restoreSyntheticBoundaryDraft()` принимает только report с точным обязательным набором полей и валидным versioned snapshot; он отвергает разрежённый список ссылок и внешний `accepted=true` report с неполным snapshot. Возвращается нормализованная копия synthetic договора, а не откат файлов, запуск CI или управление release. - `node --check` — PASS; `node web/scripts/upgrade-2024-02.mjs --verify-fixture` — PASS, 22/22 assertions. Это доказывает согласованность учебной модели и её ограничений, не состояние каких-либо внешних систем. ## Проход 2 — редактура, объём и голос - Practice отвечает на вопрос «как превратить папки в договорённость»: карта, owner, public surface, направление и первый обратимый перенос. Mechanism объясняет, почему зависимость — тройка `consumer → owner.surface`, как отличить technical public от архитектурного API и зачем проверять граф на цикл. Field разбирает три fixed synthetic imports и отделяет evidence реального review от результата fixture. Тексты не пересказывают один материал под разными заголовками. - В первых двух абзацах каждой статьи названы ситуация и цена: скрытые потребители внутренней детали, недоопределённое разрешение на import и накопление обратных ссылок. Затем каждый случай разбирается в порядке «симптом → причина → проверка → действие» без общих деклараций о важности архитектуры. - В каждой ревизии есть рабочая таблица, figure с содержательным `alt` и подписью, исполнимый fixed synthetic пример, упорядоченный маршрут, ограничения, источники и следующий проверяемый шаг. Код не утверждает, что прочёл source files или выполнил реальную архитектурную проверку. - `npm run audit:draft -- scripts/upgrade-2024-02.mjs` зафиксировал объём основного текста без источников: practice — **9 432**, mechanism — **9 709**, field — **9 743** знака. Это целевой коридор 8–11 тыс. и обязательный диапазон 5–15 тыс. знаков. - Убраны ложные operational утверждения: synthetic case не назван production-кейсом, fixture не назван CI, а зелёная связь не приравнена к корректности данных, latency, безопасности или продуктовой ценности. Голос M7 проявляется в границах ответственности и стоимости следующего изменения, а не в лозунге о «микросервисах». ## Проход 3 — визуал, безопасность и выпуск - Три SVG разделяют задачи: матрица показывает allowed cells, схема направлений — public API против internal, петля — границу fixed synthetic проверки и ручного review. В каждом изображении есть понятный заголовок и описательный `desc`. - После первого Sharp-render на ширине 375 px у подписи `checkout → payments.api` обнаружилось обрезание справа. Подпись разбита на две короткие строки слева от вертикальной стрелки; повторный render показывает полную читаемую надпись. В финальном ручном проходе нижняя смешанная подпись заменена на короткое русское правило: «не весь модуль, а его public API по правилу». Остальные карточки, стрелки, legend и ограничение модели не перекрываются. - `xmllint --noout` для трёх SVG — PASS. SVG safety scan не нашёл `script`, `foreignObject`, `javascript:`, `data:image` или event-handler attributes. В SVG нет внешних URL и пользовательского ввода. - Sharp-render всех трёх визуалов на 375 px открыт вручную: `dependency-matrix`, `allowed-directions`, `boundary-test-loop` — PASS. Матрица читается как таблица, направления оканчиваются на API, а петля отдельно сообщает, что filesystem, CI, сеть, trace и production не используются. - Выполнены проверки: `node --check web/scripts/upgrade-2024-02.mjs` — PASS; fixture — 22/22; `audit:draft` — PASS для трёх slug; XML — PASS; SVG safety — clean; Sharp 375 px — PASS. До интеграции sidecar не менял overlay, README, `articles.json`, очередь, Git или файлы других агентов; production build выполняется главным редактором после подключения ревизий. ## Выпуск после трёх проходов - Главный редактор подключил ровно три февральские ревизии в `web/data/editorial-revisions.mjs`, не меняя архивный `articles.json`, и обновил счётчик производства до 220 из 358 материалов. - После подключения `npm run audit:articles -- <три slug>` подтвердил для каждой статьи объём, одну figure, одну таблицу и один пример; registry содержит 211 уникальных ревизий без повторов slug. - `npm run build` завершился успешно: Next.js сгенерировал 374 статические страницы. Изменение подготовлено отдельным пакетом; файлы незавершённых апрельской и майской партий и пользовательские правки не входят в выпуск.