rust-arch-test-kit (0.4.51)
Installation
[registry]
default = "gitea"
[registries.gitea]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add rust-arch-test-kit@0.4.51About this package
rust-arch-test-kit
Architecture test assertions for Rust projects. Ships the archspec CLI
(archspec help for the built-in manual, docs/archspec/ for guides).
archspec scans Rust structure against a policy file and enforces module
boundaries, dependency direction, cycle-freedom and external-crate usage via
typed rules (see Rule types).
Quick workflow (every architecture change)
- Change Rust code.
- Update the project
architecture-test.toml(if boundaries/API/dependencies changed). - Run architecture tests:
cargo test --test architecture
- If you changed this kit itself, also run:
cd rust-arch-test-kit && cargo test
Where to edit
- Engine logic:
rust-arch-test-kit/src/lib.rs - Engine behavior tests:
rust-arch-test-kit/tests/rules.rs - Project policy:
<project>/architecture-test.toml - Project test entrypoint:
<project>/tests/architecture.rs
Rule types (typed configuration)
Use [[rules]] with type = "...".
forbid_dependency
Blocks internal module dependency direction.
[[rules]]
type = "forbid_dependency"
from = ["core"]
forbid = ["tauri"]
allow_dependencies
Allowlist-style internal module dependencies.
[[rules]]
type = "allow_dependencies"
from = ["application"]
allow = ["domain", "shared"]
no_cycles
Fails when dependency cycle exists across selected top-level modules.
[[rules]]
type = "no_cycles"
modules = ["commands", "config", "projects"]
If modules is omitted/empty, it checks all discovered modules.
public_api_allowlist
Restricts public modules/re-exports from lib.rs / main.rs.
[[rules]]
type = "public_api_allowlist"
allowed = ["core", "tauri"]
forbid_external_crates
Blocks usage of specific external crates from selected modules.
[[rules]]
type = "forbid_external_crates"
from = ["core"]
forbid = ["tauri", "tauri_plugin_*"]
feature_boundary
Enforces feature-gated module boundaries.
[[rules]]
type = "feature_boundary"
feature = "tauri"
gated_modules = ["tauri"]
allowed_from = ["root", "tauri"]
Checks:
- selected modules may only be used by allowed modules
- selected module declarations in root files are guarded by
cfg(feature = "...")
manifest_integrity
Checks package-level policy from Cargo.toml.
[[rules]]
type = "manifest_integrity"
require_publish = false
forbidden_dependencies = ["tauri"]
required_features = ["tauri"]
Pattern matching rules
Patterns support:
- exact match:
"core" - wildcard all:
"*" - prefix match:
"tauri*"
Applies to module names and dependency names in rule fields.
Dependency graph visualization
Generate a visual dependency graph from the same config used by architecture tests.
use rust_arch_test_kit::dependency_graph;
use std::path::Path;
let graph = dependency_graph(Path::new("architecture-test.toml")).unwrap();
// Graphviz DOT output
println!("{}", graph.to_dot());
// Mermaid output
println!("{}", graph.to_mermaid());
The returned DependencyGraph contains:
modules— all discovered top-level modulesinternal_edges— module-to-module dependencies (crate::*)external_edges— module-to-external-crate dependenciesviolations— edges that violate configured rules (Vec<EdgeViolation>)
Violation edges are rendered as red/dashed in DOT and dashed arrows (-.->) in Mermaid. External crates appear in a separate cluster/subgraph.
Edge-level rules that produce violations: forbid_dependency, allow_dependencies, no_cycles, forbid_external_crates, feature_boundary. Node-level rules (public_api_allowlist, manifest_integrity) do not produce graph violations.
Important model limitation
The analyzer currently works on top-level module boundaries:
- internal dependency = first segment after
crate:: - file ownership = first folder under
src/(or root file stem)
Example: crate::core::asr_client::HttpAsrClient is treated as dependency on core.
Design policies should therefore be expressed at top-level module granularity.
Adding a new module (maintenance checklist)
When adding module X in a project:
- Add module in code (
mod/pub mod) and file structure. - Decide boundary direction:
- add/update
forbid_dependency(orallow_dependencies) rules.
- add/update
- Add module to cycle checks if it should stay acyclic (
no_cycles). - If
Xis public from root (pub modorpub use), updatepublic_api_allowlist. - If
Xis feature-gated:- guard declaration in root file with
#[cfg(feature = "...")] - update/add
feature_boundary - ensure feature exists in
Cargo.toml(manifest_integrity.required_features).
- guard declaration in root file with
- Run architecture test for that project.
Adding new public API (maintenance checklist)
When exposing new public API from root:
- Add
pub mod ...orpub use ...inlib.rs/main.rs. - Update
public_api_allowlist.allowed. - Ensure exported module does not violate dependency rules.
- Run architecture test.
If exposure is temporary/experimental, keep it behind a feature and enforce via feature_boundary.
Extending this kit with a new rule type
- Add variant in
TypedRuleConfig. - Implement checker function.
- Wire it in
apply_rule. - Add focused fixture test in
rust-arch-test-kit/tests/rules.rs. - Run
cargo testinrust-arch-test-kit.
Do not add project-specific behavior in the engine. Keep project differences in TOML config.
Current project notes
- Some consuming projects have an existing module cycle, so their
no_cyclesrule targets foundational modules only rather than the full module set.
Keep these intentional constraints explicit in config comments when they change.
Dependencies
| ID | Version |
|---|---|
| quick-xml | ^0.42 |
| serde | ^1 |
| serde_json | ^1 |
| syn | ^2 |
| toml | ^0.8 |
| walkdir | ^2.5 |
| tempfile | ^3.24.0 |