Repository Checks
The checks that read the whole repository rather than one package's
code: its docs, its dependencies, its boundaries, its releases and its
root. All but one are Rust tests that run with every cargo test --workspace; each can also run alone.
Run them
Both packages hold every check but the shell scripts', and run with the workspace's tests; run them alone with:
cargo test -p link-repository-check
cargo test -p link-docs-check -p link-docs-check-codeThe docs and the layers
Each check below says what it enforces, what it reads, and how to run it alone. These three read the docs and the manifests.
Docs
Every rule in Writing
Docs:
links, shape, limits, history, commands, specs. It reads every Markdown
file, limits.toml and large-files.toml: cargo test -p link-docs-check.
Docs against Link's types
The commands and spec keys pages give exist, read from every page with
Link's own parsers: cargo test -p link-docs-check-code.
Layers
Each crate depends only on its own group or the groups its layer.toml
lists (Layout),
read from every Cargo.toml and layer.toml: cargo test -p link-docs-check.
Dependencies
What every locked crate and npm package must be: licensed, at one version, published by someone trusted, and free of advisories.
Licenses
Every crate of the lock file is permissively licensed, read from cargo metadata for every platform: cargo test -p link-repository-check dependencies::every_crate_is_permissively.
One version
A crate locked at two versions is listed under
[workspace.metadata.second-versions] with why, and a listed crate is
still at two, read from Cargo.lock and Cargo.toml: cargo test -p link-repository-check dependencies::every_crate_is_at_one.
Trusted publishers
Every crate has an owner under [workspace.metadata.trusted-owners] or
a million downloads, every npm package an owner under
[workspace.metadata.trusted-npm-owners] or 100,000 downloads a week,
and none calls itself unofficial or comes from elsewhere than its
registry. It reads Cargo.lock, every package-lock.json git tracks,
Cargo.toml and trust.toml: cargo test -p link-repository-check dependencies::every_crate_is_from.
Trusted trees
A lock file under [workspace.metadata.trusted-npm-trees] is trusted
whole, with why: its packages pass for its root's sake, for a tool
nothing Link ships or runs reads, installed only to work on it. That
never trusts their authors elsewhere: a package locked in any other
lock file too must pass on its own, and advisories apply to every one.
Advisories
The same test checks that every advisory against a locked version, an
unmaintained crate's among them, is listed under
[workspace.metadata.advisories] with why, and that every listed one
still applies.
Code and the repository
Where code may reach, which keys sign, and what the root holds.
Boundaries
The sandbox contract reaches no implementation, the default build no
connection, neither it nor Link memory a document parser, and the harness
and HMAC code stay in their owners, read from cargo metadata and
source files: cargo test -p link-repository-check architecture::.
Implementation libraries can be inspected by declared fixtures beneath
tests/; production consumers still use the sandbox contract.
Releases
One release key everywhere it's trusted, only main signs, and no
committed file holds a QA or dev build's key, read from install.sh,
the relay's bootstrap.sh, the workflows and every tracked file:
cargo test -p link-repository-check release::.
What a release ships
No released crate builds with one marked released = false, the
documentation index marks each held folder as its crate is, and a
release build's components.sh selects only the released plugins:
cargo test -p link-repository-check released::.
Root
The root holds only the workspaces, .github/, .agents/, .claude/
and the root's guides, read from git ls-files: cargo test -p link-repository-check root::.
Secrets
A secret leaves its type only where its package's secrets.toml or
audit.toml says, read from every package's source: cargo test -p link-secret-value --test audit.
Private state
Link-owned state belongs under .lnk in the relevant user or harness
home. The check rejects sibling roots in literal home-path declarations,
while recognizing native third-party paths, temporary probes and the
explicit old roots read by migration. It reads production Rust source,
and every path written in a page, script or setting under a home or a
session's /workspace/. Computed paths still need review: cargo test -p link-repository-check state_roots::. The rule is the package's
state_roots module, so another workspace runs it on its own root.
Files and folders too
A file or folder Link names its own, .lnk-… or .link-… or a
.lnk-… end such as x.service.lnk-off, is refused anywhere outside
.lnk in a literal path, but a temporary's, named anew each time. The
ones code still makes are listed in tests/repository/state-roots.toml,
each by its file and name: the list may shrink, never grow.
Tests keep to the testing kit
Where Clippy can't see a pattern, this check reads it from the source,
each rule a pattern and what to use instead, from the package's
test_kit module, which another workspace runs on its own root:
cargo test -p link-repository-check test_kit::.
The rules
Every file is read for a skip printed and returned, an LNK_REQUIRE_*
variable read outside the kit's gates, and a port found free by binding
127.0.0.1:0 and letting it go. A test's code is read for an #[ignore]
that says no reason, an assertion on elapsed(), a loop that sleeps
until something holds, a change to the test process's environment, a
folder made in the temp folder or /tmp by hand, and a program made
runnable by hand. Comments are left out, and a pattern over several
lines is read whole, however rustfmt splits it.
The lists that only shrink
test-kit.toml lists, under each rule's name, the files that still
break it. A list may shrink and never grow: a file that keeps the rule
must leave it, and a rule with no list is refused everywhere. Its
[promises] left counts the raw calls that say they move onto the
testing kit, and may only go down.
Lint levels
Each workspace's Cargo.toml sets its lint levels under
[workspace.lints], and every member's manifest takes them with
[lints] workspace = true and sets none of its own, so a new package
can't skip them (Conventions).
It reads only the manifests, from the package's lints module, which
another workspace runs on its own root: cargo test -p link-repository-check lints::.
Code for older versions
No code is kept for an older lnk, plugin, file or name: a tracked
source file (Rust, TypeScript, shell, Python, workflow or SQL) whose lines
say "from before", "legacy", "older than" or "migrate from", or hold an
alias, a migrat*, compat, deprecated or shim, is listed in
legacy.toml with at least as many such lines. What it lists is current:
a vendor's word, a standard's or a feature's own. The list may shrink,
never grow: cargo test -p link-repository-check legacy::.
One verb per meaning
Every command's last word is a lifecycle pair, list, show or one of
verbs.toml's [[allowed]] words, each group with its reason; a banned
word (give, take, new, forget, cancel, allow, deny and the
like) fails, so does a flag that spells one (--dry-run is --dry), and
so does a group with create and remove but no delete (or add and
delete but no remove).
Where the commands come from
The commands are each plugin's declared ones (actions.toml,
commands.json), hidden ones included, and for a plugin with none, the
variants of its Rust Subcommand enums. verbs.toml's held lists
commands still to be renamed, with their owner; it may shrink, never grow:
cargo test -p link-repository-check commands::.
HTTP clients
Every HTTP client is link-fetch's, or listed in its package's
clients.toml, read from every package's source: cargo test -p link-fetch --test clients.
Outside Rust
Two checks that aren't Rust tests: the shell scripts' and the website's.
Shell scripts
Every tracked .sh file passes shellcheck, which runs in CI, not as
a Rust test: git ls-files '*.sh' | xargs shellcheck.
The website's
The website's own checks are TypeScript, in web/: npm run lint,
npm test and npm run build there.
When a lock file changes
The trust check reads its evidence from trust.toml: who publishes
each crate and npm package, as crates.io and npm's registry say, and
the advisories against each locked version, as OSV says. It runs
offline. When a package is added or updated, it fails until the
evidence holds it: read them again, then review what changed.
LNK_TODAY=2026-10-19 cargo test -p link-repository-check -- --ignored refresh
git diff tests/repository/trust.tomlA package that is neither first-party nor widely used is replaced, or
its owner is added to its registry's trusted owners with why, in the
PR that adds it (Conventions).
An advisory is fixed by upgrading past it. One that no release fixes
is listed under [workspace.metadata.advisories], its id and why; an
unmaintained crate is listed only when it reads no input from outside
Link, such as a document or a network peer.
Every day
dependencies.yml reads the evidence again every day, on dev, and
runs the trust check on what it says now: it fails on a new advisory
against a locked version, or a package whose owners or downloads no
longer pass. It changes nothing; the fix is a PR that refreshes
trust.toml and does what the check says.