Skip to main content

require_lifecycle

Function require_lifecycle 

Source
pub(crate) fn require_lifecycle(
    state: &AppState,
    capability: impl FnOnce(&ServerPolicy) -> bool,
    route: &str,
) -> Result<(), ApiError>
Expand description

The one place this server’s own lifecycle refuses a request.

capability selects a field of ServerPolicy; route names what was asked for, so the refusal says which surface deferred rather than only that something did. Every caller is one line (require_lifecycle(&state, |p| p.serves_reads, "…")?), which is the point: a surface that consults the lifecycle by matching on the state itself would be a second, drifting copy of didbot_pds::server_state’s policy table.

§Where the read gate is applied, and where it is not

ServerPolicy::serves_reads is false only in booting and provisioning, which last a store read and a keypair mint respectively and during which no agent account can exist. So it is applied where an absent or empty answer would be misread — listAccounts answering [], subscribeRepos opening an empty stream, did.json answering 404 — and not on the per-repository reads, where the natural RepoNotFound is already the true answer and a 503 would say less.

The refusal is ApiError::not_ready — a 503 carrying a Retry-After, never a 404 and never an empty answer. See that constructor and didbot_pds::RETRY_AFTER_SECONDS for how a relay is meant to tell “try later” from “broken” from “nothing here.”