pub fn build_fetch_plan(ref_: &Ref, store_root: &Utf8Path) -> FetchPlanExpand description
Build the dry-run preview (FetchPlan) for the given ref and store
root, without contacting the network or filesystem.
Per-ref-kind shape (ADR-0022 §1, NORMATIVE):
- DOI →
metadata_sources = ["crossref", "unpaywall"],pdf_sources = [{ key: "oa-publisher", candidate_hosts: oa_publisher_allowlist hosts }]. - arXiv →
metadata_sources = [],pdf_sources = [{ key: "arxiv", candidate_hosts: tier_1 arxiv hosts }].
redirect_allowlists_loaded always contains the four source keys the
production HTTP client is built with (Tier 1 + the synthetic OA
publisher), reflecting doiget-cli::commands::fetch::build_http_client’s
composition.
§Errors
This infallible-looking wrapper never returns Err — it delegates to
try_build_fetch_plan and, on the (should-be-impossible) internal
allowlist-contract drift, falls back to an empty candidate_hosts
list for the affected PDF source rather than panicking (issue #156 ②:
a stray .expect() here crashed doiget plan if a source key was
ever renamed). Callers that want to observe the invariant violation
as a typed error should call try_build_fetch_plan directly; this
function’s signature is kept infallible because it is pub and has
non-doiget-core callers (doiget-mcp, doiget-cli) whose
signatures must not change in this batch.
The empty-candidate_hosts fallback is the lesser evil versus a
panic: a preview with an empty allowlist is visibly wrong (and is
what try_build_fetch_plan flags as SourceSchema), whereas a panic
takes down doiget plan entirely. This path is unreachable unless
oa_publisher_allowlist / tier_1_allowlist are edited to drop
the "oa-publisher" / "arxiv" keys, which the in-crate tests pin.