7.6 Derived Dependencies

Most dependencies are declared. One is not.

A service whose Identity is anything but SYSTEM cannot start until the authority is listening, because peinit has to ask it for a token before there is a process at all (§4.3). That is a hard dependency in every sense Requires means one.

It used to be nobody's. peinit hardcodes the socket the authority listens on, so the requirement was real on every boot, but the ordering existed only if a definition happened to declare it — and all three LocalService definitions in the tree did not. Three of three is the number that makes it a defect in the mechanism rather than in three definitions: the requirement is created by Identity, so Identity is what should produce the edge.

7.6.1 Provides #

A service names the roles it fills:

Provides = ["authn"]

A role is a virtual name — a capability, not a service. Virtual and real names share one namespace, exactly as they do for packages (PSPU §5.4): a dependency on authn is satisfied by a service literally called authn, or by any service providing it.

The indirection is the point. peinit knows it needs an authority and knows which socket to speak to, but the authority's name is registry data and none of peinit's business — an image may ship a different one. So the derived edge names the role, and peinit resolves it to whoever declares it.

Provides entries use the service-name grammar and never carry a readiness level. netd:routed names a condition on a service, and a role is not a service, so there would be nothing for the level to qualify; a level on a Provides entry is rejected rather than ignored.

7.6.2 What peinit derives #

Before a definition set becomes a service table — at boot and on every reload, through the same code, because an edge that held until the first reload would be worse than no edge — peinit adds a Requires on each provider of authn to every service that needs the authority to launch.

A service needs it when its Identity is not SYSTEM, or when it has hooks and its HookIdentity is not SYSTEM. The second half matters: a SYSTEM service whose hooks run as LocalService materialises a token for them, and a definition that needs the authority for half its launch needs the ordering for all of it.

Three rules keep the derivation from doing damage:

  • A provider never gains a dependency on its own role. An authority declaring a non-SYSTEM identity would otherwise require itself, and a service that requires itself never starts.
  • An edge already declared is not added again, including one carrying a level. Requires = ["authd:ready"] already orders against the authority, and more strictly; adding a plain edge beside it would be a second edge to the same service saying less.
  • Nothing is derived when no service fills the role. See below.

Because the result is an ordinary Requires, it needs no new kind of edge and behaves exactly like a declared one everywhere else — in graph validation, in graph execution, at shutdown, and in svctl status, where it appears as the dependency it is rather than as a hidden ordering.

Several services MAY fill one role; each becomes its own Requires, so the dependent is ordered after all of them. For authn this cannot arise — PGSS Logon §2.1 requires at most one authority on a running system — and where a future role allows several, ordering after all of them is the conservative reading and needs nothing new. peinit deliberately does not offer "wait for any one of them": that would change the release rule from every edge satisfied to every group has one satisfied, and would contradict Requires's failure rule, under which a target entering Failed fails the dependent.

7.6.3 When nothing fills the role #

An image whose services need a token and which ships no authority is broken. A reload of it produces a validation warning naming every service that cannot start, and succeeds anyway.

It deliberately does not invent an edge to a name no service answers to. That would be a missing hard dependency, and a missing hard dependency rejects an entire reload transaction — so an operator could not reload the definition that installs the authority. The image would be unrecoverable by the one mechanism meant to recover it.

The individual launches still fail, loudly, where the fault actually is: at the service that asked for a token and could not have one.

7.6.4 A role is not an online target #

§7.5 opens by rejecting network-online.target, and the objection there does not reach this mechanism. It is worth being explicit about why, because the two look alike from a distance.

The complaint about network-online.target is that "online" has no single definition: a service needing a default route and a service needing a loopback address want different things, and one name cannot mean both. The abstraction is over a condition, and the condition is ambiguous.

authn abstracts over no condition at all. It means "whoever answers ServiceAttest on the logon socket" — a protocol role, specified by PGSS Logon §2.19, which §2.1 says MUST have at most one occupant. There is exactly one thing it can mean, and what a dependent gets is the same thing it would get by naming the service directly.

The rule the two share: peinit does not invent vocabulary for conditions inside another service. A readiness level is the publisher's own word for its own state; a role is a name for a position in a protocol peinit already speaks. Neither is a target.

Edit this page