rust-arch-test-kit (0.2.0)
Installation
[registry]
default = "gitea"
[registries.gitea]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add rust-arch-test-kit@0.2.0About this package
rust-arch-test-kit
Shared architecture test engine published to the Gitea Cargo registry at git.mialemrobicnic.pl.
Each consumer adds the crate as a dev-dependency from the Gitea registry and keeps policy in architecture-test.toml.
Installation
Add the Gitea registry to .cargo/config.toml:
[registries.gitea]
index = "sparse+https://git.mialemrobicnic.pl/api/packages/mat/cargo/"
Add the dependency to your project's Cargo.toml:
[dev-dependencies]
rust-arch-test-kit = { version = "0.1.0", registry = "gitea" }
Then run architecture tests via tests/architecture.rs.
Authentication (local development)
Cargo needs a token to pull from the private Gitea registry. Use Bitwarden CLI to keep the token out of files.
-
Store your Gitea API token in Bitwarden as an item named
gitea-cargo-token(use the password field). -
Add to your
~/.zshrc:
# Gitea Cargo registry auth (loaded from Bitwarden)
export CARGO_REGISTRIES_GITEA_TOKEN="Bearer $(bw get password 'gitea-cargo-token' 2>/dev/null)"
- Reload your shell:
source ~/.zshrc
Note: bw get requires an unlocked session. If the token is empty, unlock first:
export BW_SESSION="$(bw unlock --raw)"
source ~/.zshrc
For CI (Gitea Actions), the workflow uses secrets.REGISTRY_PASS — no extra setup needed.
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
- Push to
main/main2to publish a new version to Gitea.
Where to edit
- Engine logic:
rust-arch-test-kit/src/lib.rs - Engine behavior tests:
rust-arch-test-kit/tests/rules.rs - Project policy:
agent-dev-tools/agent-cli/architecture-test.tomlvoice-tools/voice-lib/architecture-test.toml
- Project test entrypoint:
agent-dev-tools/agent-cli/tests/architecture.rsvoice-tools/voice-lib/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
agent-dev-tools/agent-clihas an existingorchestration <-> sessionscycle, so itsno_cyclesrule currently targets foundational modules only.
Keep these intentional constraints explicit in config comments when they change.
Dependencies
| ID | Version |
|---|---|
| serde | ^1 |
| syn | ^2 |
| toml | ^0.8 |
| walkdir | ^2.5 |
| tempfile | ^3.24.0 |