Skip to content

Architecture diagrams

These diagrams come from a single LikeC4 model in the alint repository. They stay in lockstep with the code: the crate elements and their dependency edges are gated against cargo metadata, the rule catalogue against docs/rules.md, the config keys against the JSON schema, and the whole model is checked by likec4 validate in CI. The same model is also exported to static Mermaid diagrams for viewing in the GitHub repository.

Drag to pan, scroll to zoom, and click an element to step into it.

Who and what alint interacts with: developers and CI, the linted repository, package registries, editors (via the LSP), GitHub Code Scanning, and alint.org.

The alint system as containers: the CLI, the LSP server, and the dev or build tooling.

The crates inside the CLI and their runtime relationships.

All workspace crates and their dependency edges, grouped by container: runtime dependencies solid, dev/build-only dashed. Generated from cargo metadata.

alint check: config load, facts, rule filtering, the single parallel walk, dispatch, evaluation, aggregation, optional fix, and output.

Config load and the extends trust boundary

Section titled “Config load and the extends trust boundary”

How extends: resolves (local path, https with SRI, bundled) and why process-spawning rule kinds and out-of-root access are rejected outside the top-level config (ADR-0004).

Rule-major versus per-file dispatch, and how each matched file is read at most once (ADR-0003).

The built-in rule families and the canonical kinds within them. Click a family to step in.

The .alint.yml entities and how they relate.

The engine’s core types: how a Rule (or PerFileRule), a Fixer, and the Violation / RuleResult / Report values relate.

Facts are evaluated once (in parallel, cached), then used to filter which rules run via their when: conditions.

alint fix: how auto-fixable violations are applied (including content-reading fix operations) and re-checked.

The single parallel directory walk: gitignore handling, include/exclude filtering, and the deterministic, sorted FileIndex.

How ${...} template variables in rule options are expanded before evaluation.

How nested .alint.yml files layer and scope rules across a monorepo.

How a Report is rendered into each output format (human, JSON, SARIF, and the rest).

The language server: how an editor’s open/change/save events drive a per-file check and publish diagnostics.

How the editor extensions (VS Code, JetBrains) connect to the alint LSP server.

The GitHub Action: how a CI run produces SARIF for GitHub Code Scanning.

How the pre-commit hook runs alint check on commit and blocks on errors, plus the manual alint-fix hook.

How a tagged release fans out to crates.io, npm, Homebrew, Docker, and the install script.

The touch-points for a new rule kind: the registry, the options struct and JSON schema, and the generated docs.

How the generated contracts (facts, schema, rules, this model) flow to alint.org and are gated against drift.

The load-immune, Valgrind-based performance check that guards the engine against regressions independently of machine load.

How an external rule plugin is declared, gated (spawning kinds rejected outside the top-level config), and invoked.

Security: path confinement and spawning-kind gating

Section titled “Security: path confinement and spawning-kind gating”

Two guards: keeping file access within the repository root, and rejecting process-spawning rule kinds pulled in via extends: (ADR-0004).

Security: Trojan-source and unicode hygiene

Section titled “Security: Trojan-source and unicode hygiene”

How bidirectional-override and invisible-character (Trojan-source) attacks are detected in scanned files.