# Rust Code Health ## Цель В Community-репозитории нужно удерживать Rust-код в состоянии, где модули можно безопасно менять без разрастания скрытых связей. Основные риски сейчас: - крупные production-файлы с тестами внутри; - интеграционные сценарии, написанные рядом с кодом; - смешение HTTP, registry, runtime и test fixtures в одном модуле; - отсутствие автоматического контроля размера файлов. ## Инструменты В Rust нет одного прямого аналога Python `import-linter`, который закрывает cohesion, coupling и connascence на уровне workspace. Используемая база: - `cargo fmt` — единый стиль. - `cargo clippy --workspace --all-targets --all-features -- -D warnings` — локальные ошибки, smell-и и часть API-антипаттернов. - `cargo test --workspace --all-targets` — unit и integration-style тесты. - `scripts/check-rust-code-health.sh` — локальный repo-level gate для размера Rust-файлов. - `scripts/check-rust-boundaries.sh` — crate-level dependency direction и module-level import rules. - `scripts/check-rust-module-boundaries.sh` — запрет на опасные imports внутри слоев. - `cargo deny --locked check advisories bans licenses sources` — обязательная проверка лицензий, известных уязвимостей и источников зависимостей. - `scripts/check-dependencies.sh` — единая локальная проверка Rust- и npm-зависимостей. Что можно добавить позже: - `cargo-machete` для поиска неиспользуемых зависимостей. - `cargo-udeps` для более строгой проверки зависимостей, если nightly допустим в отдельной job. - `cargo-modules` или `cargo-guppy` для анализа графа модулей и зависимостей между crate-ами. ## Политика лицензий зависимостей По умолчанию разрешены `MIT`, `BSD-2-Clause`, `BSD-3-Clause`, `Apache-2.0`, `ISC` и `0BSD`. `MPL-2.0`, `LGPL`, `EPL` и `CDDL` требуют отдельного технического и юридического рассмотрения до добавления зависимости. `GPL`, `AGPL`, `SSPL`, `Commons Clause`, `BUSL` и зависимости с неизвестной лицензией запрещены без юридического согласования. Лицензия самого Community-продукта не считается внешней зависимостью и проверяется отдельно. Точечные исключения для обязательных транзитивных зависимостей фиксируются в `deny.toml` по имени пакета и конкретной лицензии. Безымянные или глобальные исключения запрещены. ## Правила размера Новые Rust-файлы не должны быть больше `1000` строк. Существующие крупные файлы зафиксированы baseline-ом в `scripts/check-rust-code-health.sh`. Они не должны расти дальше. При изменении таких файлов предпочтительно: - выносить вложенный `mod tests` в `tests/`, если тест проверяет публичное поведение, БД, HTTP или несколько модулей сразу; - выделять route/service/runtime helper в отдельный модуль; - оставлять рядом с production-кодом только короткие unit-тесты приватной логики. Текущие крупные production-файлы считаются debt baseline. Они не должны расти, а при изменении их нужно постепенно разбирать: - `apps/admin-api/src/service.rs` - `crates/crank-registry/src/postgres/mod.rs` - `crates/crank-community-mcp/src/app.rs` - `crates/crank-registry/src/postgres/operation.rs` Уже выделенные направления: - `apps/admin-api/src/dto.rs` содержит HTTP payloads и view models. - `crates/crank-registry/src/postgres/pool_config.rs` содержит env parsing и validation pool settings. - `crates/crank-registry/src/postgres/connection.rs` содержит connection/migration wiring. - `crates/crank-community-mcp/src/transport.rs` содержит Streamable HTTP transport helpers. - `crates/crank-runtime::RuntimeExecutionRequest` является основным способом передавать execution параметры. ## Правила тестов Рядом с кодом допустимы: - маленькие pure unit tests; - проверки приватных parser/mapper/helper-функций; - тесты без сети, БД и поднятых серверов. В `tests/` нужно выносить: - PostgreSQL integration tests; - admin-api HTTP сценарии; - fake upstream servers; - publish/test-run/YAML roundtrip flow; - MCP Streamable HTTP сценарии. Целевая структура: ```text apps/admin-api/tests/ crates/crank-registry/tests/ crates/crank-runtime/tests/ crates/crank-community-mcp/tests/ ``` ## Архитектурные границы Базовое правило направления зависимостей: ```text apps/* -> crates/* crank-community-mcp -> crank-registry + crank-runtime + crank-core crank-runtime -> crank-core + crank-mapping + crank-schema + adapters crank-registry -> crank-core crank-adapter-rest -> crank-core + crank-mapping + crank-schema crank-core -> no app crates ``` Если потребуется строгая автоматическая проверка границ, добавим отдельный script на основе `cargo metadata` или `cargo-guppy`. Module-level правила уже проверяются: - `apps/admin-api/src/service*` не импортирует `axum`; - `apps/admin-api/src/routes*` не импортирует `crank_runtime`; - `crank-core/src` не импортирует framework/storage/network runtime crates; - `crank-registry/src` не импортирует HTTP framework/client crates; - `crank-runtime/src` не импортирует HTTP framework или SQL storage crates.