5. Trust without a central server
A central package registry gives three guarantees: the package is still there tomorrow, its versions never change, and known security problems are announced. Without a registry, the same guarantees come from content hashes in the lock, mirrors, advisories published by each package, and several copies that can be compared.
A mirror
The lab mirrors kinds and says so in its index. add copies the mirror into the fobos with the source:
$ grep -A4 "^\[package.kinds\]" ~/lab-index/index.toml
[package.kinds]
source = "file://~/remotes/kinds.git"
mirrors = ["file://~/mirror/kinds.git"]
description = "Portable real kinds"
license = "MIT"$ fobis add lab:kinds --semver "^1.0.0" --force
Replaced kinds = file://~/remotes/kinds.git :: semver=^1.0.0 :: mirror=file://~/mirror/kinds.git
Run 'fobis fetch' to fetch it.The source goes down, and a fresh clone is needed. The versions are listed from the mirror, and the clone comes from it:
$ fobis fetch
Listing the tags of file://~/remotes/kinds.git from mirror file://~/mirror/kinds.git
Cloning kinds from file://~/remotes/kinds.git
Error cloning kinds from file://~/remotes/kinds.git:
Cloning into '.fobis_deps/kinds'...
fatal: '~/remotes/kinds.git' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Cloning kinds from mirror file://~/mirror/kinds.git
Checking out v1.0.0 for kinds
Dependency vectors already fetched (use --update to refresh)
Checking out v0.2.0 for vectors
Dependency vectors already fetched (use --update to refresh)
Checking out v0.2.0 for vectors
Saved deps config to .fobis_deps/.deps_config.ini
Saved lock file to .fobis_deps/fobos.lockA mirror needs little trust: the lock recorded the tree hash of each version's content, and a tag that names other content is reported when it is fetched (a release archive whose sha256 changed is refused). The clone keeps the source as its origin: once the source is back, updates come from it.
Advisories
kinds publishes advisories about its own versions in a file on its default branch, fortran-advisories.toml:
# kinds publishes advisories about its own versions, on its default branch
schema = 1
[[advisory]]
id = "KINDS-2026-001"
affected = ">=1.1.0, <1.1.1"
severity = "medium"
summary = "R4P selected 6 digits but a range too narrow for single-precision data"
url = "https://example.org/lab/kinds/issues/1"fobis audit reads the advisories of every dependency for the version the lock records:
$ fobis audit
kinds v1.1.0 AFFECTED
KINDS-2026-001 [medium] R4P selected 6 digits but a range too narrow for single-precision data https://example.org/lab/kinds/issues/1
vectors v0.2.0 ok
[exit status 1]The lab publishes the fix as 1.1.1. fetch --update does not take it:
$ fobis fetch --update && fobis audit
Dependency kinds already fetched (use --update to refresh)
Checking out v1.0.0 for kinds
Dependency vectors already fetched (use --update to refresh)
Checking out v0.2.0 for vectors
Dependency kinds already fetched (use --update to refresh)
Checking out v1.1.0 for kinds
Updating kinds
Checking out v1.1.0 for kinds
Updating vectors
Checking out v0.2.0 for vectors
Saved deps config to .fobis_deps/.deps_config.ini
Saved lock file to .fobis_deps/fobos.lock
kinds v1.1.0 AFFECTED
KINDS-2026-001 [medium] R4P selected 6 digits but a range too narrow for single-precision data https://example.org/lab/kinds/issues/1
vectors v0.2.0 ok
[exit status 1]With transitive = true the versions are chosen by minimal version selection: 1.1.0 is still the lowest version every range accepts. The project states what it needs, by raising its minimum:
$ fobis add lab:kinds --semver "^1.1.1" --force && fobis fetch && fobis audit
Replaced kinds = file://~/remotes/kinds.git :: semver=^1.1.1 :: mirror=file://~/mirror/kinds.git
Run 'fobis fetch' to fetch it.
Dependency kinds already fetched (use --update to refresh)
Fetching kinds: v1.1.1 is not in its clone yet
Checking out v1.1.1 for kinds
Dependency vectors already fetched (use --update to refresh)
Checking out v0.2.0 for vectors
Dependency kinds already fetched (use --update to refresh)
Checking out v1.1.1 for kinds
Warning: dependency 'kinds' HEAD (928a5bfd4b09) does not match fobos.lock (46a1fb569bcb). Run 'fobis fetch --update' to refresh.
Dependency vectors already fetched (use --update to refresh)
Checking out v0.2.0 for vectors
Saved deps config to .fobis_deps/.deps_config.ini
Saved lock file to .fobis_deps/fobos.lock
kinds v1.1.1 ok
vectors v0.2.0 okWitnesses
A tag can be moved after the fact, on the source or on a mirror, to point at other content. --witness compares, for every locked tag, the commit the source and each mirror name with the commit in the lock:
$ fobis audit --witness
kinds v1.1.1 ok
witness file://~/remotes/kinds.git: agrees
witness file://~/mirror/kinds.git: lacks v1.1.1
vectors v0.2.0 ok
witness file://~/remotes/vectors.git: agreesThe mirror has not received 1.1.1 yet: it gives no testimony, which is not a disagreement. Once it is synchronised, the copies agree:
$ fobis audit --witness
kinds v1.1.1 ok
witness file://~/remotes/kinds.git: agrees
witness file://~/mirror/kinds.git: agrees
vectors v0.2.0 ok
witness file://~/remotes/vectors.git: agreesSomeone moves the tag on the mirror:
$ fobis audit --witness
kinds v1.1.1 ok
witness file://~/remotes/kinds.git: agrees
witness file://~/mirror/kinds.git: DIFFERS
vectors v0.2.0 ok
witness file://~/remotes/vectors.git: agrees
[exit status 1]Several independent copies agreeing replace a central checksum database: no single server has to be trusted, and a change on one of them is seen by everyone who audits.
When the source and every mirror are gone, :: archive=swh lets fetch take the version from Software Heritage, accepted only when its tree is the one in the lock (see the cookbook).
What you learned
mirrors in an index and :: mirror= in a fobos, the tree hashes of the lock, fortran-advisories.toml, fobis audit, raising a minimum under minimal version selection, fobis audit --witness. Reference: audit.