3.7 Cross-Repository Guards

Two relations let one repository act on another's packages, and both are gated.

3.7.1 Foreign replaces #

A replaces declared by a lower-priority repository, targeting a package originally installed from a higher-priority one, raises an authorization. The operator confirms it specifically; a general --yes does not satisfy it, and the authorising act is audited.

3.7.2 Foreign conflicts #

A conflicts declared by a lower-priority repository, which would cause a higher-priority package to be removed as a cascade, is the mirror image: a denial-of-availability rather than an escalation.

peipkg resolves a conflict by rejecting the plan outright rather than by cascading removals, so the situation the guard describes does not arise: the low-trust package simply fails to install, and the high-trust one stays where it is.

3.7.3 A low-trust provider filling a role #

When the candidate that satisfies a dependency does so through provides from a lower-priority repository, while a higher-priority repository holds a name-matching package whose constraint check failed, peipkg raises an authorization and requires explicit confirmation. This is the same shape as the foreign-replaces guard: a less-trusted package taking over a name a more-trusted one was expected to fill.

The check runs when resolving a dependency. It does not run for a package the operator named directly, where it cannot fire in practice because a directly named goal carries no constraint for the higher-priority candidate to fail.

3.7.4 Origin that no longer resolves #

Each of these guards compares the priority of the repository a package came from against the priority of the repository acting on it. A package whose originating repository has since been removed — an orphan — has no configured priority to compare, so it carries a priority below every configurable value instead. Every guard that compares priorities therefore treats an orphan as at least as trusted as anything still configured, with no special case of its own.

That direction is the only safe one. Skipping the comparison, which is what an unset priority produced, meant a newly added low-trust repository could declare replaces against an orphaned ex-official package and take it over with no confirmation — so removing a repository lowered the protection on the packages it left behind. Removing a repository because its keys were stolen is exactly when that must not happen.

An orphan is not the same as a package with no origin. A raw local-file install never had a repository to lose, and is not treated as maximally trusted.

3.7.5 Orphaned packages #

list marks an orphan and names the repository that is gone; info says so in the origin line. Neither is refreshed, and no trust state stands behind either any longer.

An upgrade of an orphan is refused unless a configured repository now serves a candidate under its own name. A named upgrade errors — the alternative is reporting success having done nothing, since an unclaimed orphan produces no upgrade operation at all. An every-package upgrade warns per orphan and carries on, because one orphan must not stop the rest of the system moving.

A replaces from another package can still move an orphan aside. That is a takeover rather than an upgrade, and it is gated as an elevated action by the rule above.

Edit this page