Repository navigation
archcheck: block new catch-all crate names (common, utils, core, ...) - #407
Merged
Merged
Conversation
ac-pplx
force-pushed
the
ac/archcheck-crate-names
branch
2 times, most recently
from
October 14, 2026 20:07
2ef4493 to
5989905
Compare
ac-pplx
marked this pull request as ready for review
October 14, 2026 20:28
mabdelraouf-pplx
approved these changes
Oct 15, 2026
Add a crate_names rule. Each workspace member's package name, and its library target's name, is lowercased and split on - and _; the crate matches if a whole part is a banned token (common, shared, util, utils, helper, helpers, misc, core), unless `allow` in [rules.crate_names] names the package exactly. `allow` starts empty; its names must be lowercase and unique, and a name both allowed and baselined exits 2. - no_new (required): a matching crate that the new [crate_names] baseline table does not list at its path, reported at the name = (or [lib] name) line of its Cargo.toml; and a [crate_names] entry a pull request may not list, reported at the entry's line. With --base-baseline, that is an entry whose name the base branch's table lacks; updating an existing entry's path is not a new entry. Without a base copy of the table (the base predates the rule, or can't be resolved), only a fixed set compiled into archcheck, the 16 crates that matched when the rule was added, may be listed. A base table that doesn't parse, or a base copy that isn't TOML, counts every entry as added. - stale_entries (advisory): an entry whose crate is gone, renamed or no longer matches, and an allow name that no longer applies. - policy_changed (advisory): with the new --base-architecture flag, every change to [rules.crate_names] compared with the base branch's ARCHITECTURE.toml (read leniently), on its line, so loosening the policy is visible in review. Workspace members now come from `cargo metadata --no-deps --offline`, run from the root, for every rule: Cargo also makes an in-workspace path dependency a member, so a crate added only that way was never checked. If cargo metadata fails, archcheck exits 2. This adds pplx-space-credential-injection-store, whose files are all under the file_size limit, so file_size findings are unchanged; pattern_ratchet reads the same inventory and finds nothing new either. The baseline lists the 16 crates that match today, in a [crate_names] table after the other tables. --write-baseline never adds an entry: it removes stale ones, leaves an entry whose crate moved for a deliberate edit, lists no entries to paste (a hand-added one fails no_new), and always writes the table, even when empty. --write-baseline=crate_names updates that table alone. crate_names fits the shared baseline structure of the count ratchet: it implements Rule directly, not CountRule, since its table maps names to member paths rather than capping a count. Rule::tables names its crate_names table, so the configured-table check and --write-baseline=<table> accept it, and Rule::baseline_rule makes Baseline::load_base read it: the base reader takes the [crate_names] key from the parsed document on its own, beside [file_size] and each [pattern_ratchet.<instance>] table, and records it as read. The in-memory Baseline keeps it beside the count tables and writes it last. NotAdded's path and count become an optional entry, so the crate_names lines offer nothing to paste. Rule::other_skips reports the --base-architecture skip line. Config is fail-closed: an empty token list, or a token that is empty, uppercase or contains - or _, exits 2. Module names are out of scope; the README explains why.
The archcheck step now also copies the base's ARCHITECTURE.toml, the same way as its baseline, for crate_names.policy_changed. Its warnings say exactly what is skipped when a base file can't be read: the no_new_entries and no_raised_caps comparisons and policy_changed are skipped, and crate_names.no_new allows only the crates listed when it was added. order-archcheck-findings.sh orders crate_names findings like the others. policy_changed compares with the base's ARCHITECTURE.toml, so it leads with no_new_entries and no_raised_caps instead of coming last in report order. A stale [crate_names] entry is the pull request's own when the pull request changes the Cargo.toml of the member path the entry maps to (the key is a package name, not a file). Required findings are still annotated from archcheck's own report, in the run that fails the job. The README says so, and that every listed crate is a root `members` entry, so moving one switches reviewdog to nofilter.
ac-pplx
force-pushed
the
ac/archcheck-crate-names
branch
from
October 15, 2026 22:35
5989905 to
1eb58d8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new
cargo archrule,crate_names, that stops new crates from getting catch-all names.What is checked.
Which crates: every workspace member as Cargo sees it, from
cargo metadata --no-deps --offlinerun from the root. That covers the rootCargo.toml'smembersplus every in-workspace path dependency, which Cargo also makes a member.Which names: each member's package name and its library target name (
[lib] nameor Cargo's default), lowercased and split on-and_.What matches: a crate matches if any whole part is in
banned_tokens:common,shared,util,utils,helper,helpers,misc,coreSo
pplx-space-common-io,foo_coreand a library namedutilsmatch;database,coreutilsandencoredon't.Fail-closed (exit 2):
cargo metadatafails;-/_);allowlist.file_sizeandpattern_ratchetuse the same member list.allow. A list in[rules.crate_names]of exact package names exempt from the rule (e.g. applx-space-shared-memory). It starts empty.Baseline. A new
[crate_names]table inarchitecture-baseline.tomlmaps package name → member path. It lists the 16 crates that match today:common-core,common-svc,common-cli,common-grpc,common-grpc-lb,common-io,common-jobs,common-lru-reaper,common-proto-build,common-work-coalescer,common-connection-admissionnet-common,execution-common,spaced-commonnode-runtime-core,credential-injection-core(all with the
pplx-space-prefix). An entry covers only the crate at its path. A listed crate that moves needs a one-line edit to its entry, and a removed crate's name can't be reused at another path. The baseline diff only appends this table.Behaviours.
no_new(required,ERROR):name =line of itsCargo.toml, or on the[lib] nameline when only the library name matches.[crate_names]entry the PR may not list, shown on the entry's line:--base-baseline), any name the base lacks. Updating an existing entry's path doesn't count as new.stale_entries(advisory): an entry whose crate is gone, renamed or no longer matches, or anallowname that no longer applies.policy_changed(advisory): with--base-architecture, each difference in[rules.crate_names]from the base'sARCHITECTURE.tomlis reported on its line: tokens orallownames added or removed, modes changed, or the whole table new. The base copy is read leniently. Without the flag, the behaviour is skipped, and one line says so.--write-baselinenever adds an entry. It removes stale ones, leaves an entry whose crate moved for a deliberate edit, and always writes[crate_names], even when empty, after the other tables. Unlikefile_sizeandpattern_ratchet, it prints no entries to paste, because a hand-added entry failsno_new.--write-baseline=crate_namesupdates that table alone.Enforcement
architecture-baseline.tomland the baseARCHITECTURE.toml. It uses an empty file if the base lacks one, and warns with exactly what is skipped if the base can't be resolved.no_newemitsERROR, so the-fail-level=errorrun fails the Rust clippy job inspace-pull-ci. Every case is annotated in either filter mode:Cargo.toml;Cargo.toml'smembers, where all 16 are, which switches reviewdog tonofilter;allowedit changes the baseline orARCHITECTURE.toml, which switches reviewdog tonofilter.order-archcheck-findings.shputscrate_names.policy_changedwith the other base comparisons (no_new_entries,no_raised_caps) at the front of the advisory run. A stale[crate_names]entry counts as the PR's own when the PR changes theCargo.tomlat the entry's member path. Required findings are still annotated from archcheck's own report, in the run that fails the job.tests/repository.rsfails on any required finding in the tree, including the one casefilemode wouldn't annotate: a listed crate that is only a path dependency, moved without editing its manifest.Why modules are out of scope
file_sizealready bounds how much a module can hold.util.rs→support.rs).Combined with the shared count ratchet (#494) and finding order (#493)
Rebased onto
mainafter #494, #493, #473 and the baseline and config edits (#504, #498, #417, #421, #413).CrateNamesimplementsRuledirectly, as the README's recipe says for a rule whose table isn't a count ratchet; its table maps names to member paths, not counts.Rule::tablesnamescrate_names, so the configured-table check and--write-baseline=<table>accept it.Rule::baseline_rulemakesBaseline::load_baseread it.load_basereads the[crate_names]key from the parsed document on its own, records the rule as read (or why it can't be read), andBaseBaseline::crate_names()reportsNotGiven,UnusableorNotReadliketable()does.Baselinekeeps[crate_names]beside its count tables.table_names()lists it last,table_lencounts it,replace_tablehandles it, andwriteadds it after the other tables with its comment.NotAdded'spath/countbecomeentry: Option<(String, usize)>, set inratchet.rs;file_size.rsandpattern_ratchet.rsare exactly as onmain.[rules.crate_names]and[crate_names]are appended aftermain's tables.[file_size]and the[pattern_ratchet.*]tables are byte-identical tomain, includingrootfs_copy's hand-written comments.no_new_entries and no_raised_caps(every table's).crate_nameslines: two skip-line assertions, the unit-test configs (crate_names config is required) andevery_configured_table_is_read_from_a_base_copy, which checks the[crate_names]names. Two new cases intest-order-archcheck-findings.shfail onmain's script.Commits
cargo metadatamember discovery, the bootstrap set, name-and-path matching, library names,allow,policy_changedand the README, fitted into archcheck: share one per-file count ratchet between file_size and pattern_ratchet #494's ratchet structure.ARCHITECTURE.toml, fixes the warning and comment text, and orderscrate_namesfindings inorder-archcheck-findings.sh, with tests.cargo metadataadds one member,pplx-space-credential-injection-store, a path dependency that isn't inmembers. Its files are all under thefile_sizelimit, so thefile_sizeandpattern_ratchetfindings are identical tomain's (1237 vs 1233 files checked).Validation
cargo fmt --all --check,cargo clippy -p pplx-space-archcheck --all-targets -- -D warnings,cargo test -p pplx-space-archcheck(5 unit, 42 CLI,tests/repository.rs),test-order-archcheck-findings.shandcheck-rust-error-policy.shall pass.mainalso reports. rustdoc-D warningsreports one error, a private intra-doc link toCountRulefrom archcheck: share one per-file count ratchet between file_size and pattern_ratchet #494, the same onmain.cargo archexits 0 with 77 advisory findings and no required ones:file_size2no_crossing, 69listed_no_growth, 6stale_entries. The rdjson diagnostics are identical tomain's binary onmain. With both base flags againstmain, the only addition is the advisorypolicy_changed(whole policy new), which the ordering script puts first.no_newERROR, both withmain's base copies and with no base:foo-utilscrate added only as a path dependency;common-jobsmoved to a new path under the same name;[lib] name = "utils".--write-baselinewrites the 16crate_namesentries.This PR was written with AI assistance (Claude Code) and reviewed against the repository's public-review checklist.
🤖 Generated with Claude Code