Skip to main content

capsule_runtime/
artifact_supply.rs

1//! Where a runtime pull finds an artifact the session's stores do not hold.
2//!
3//! A capsule granted `capabilities.install.from: [stores, sources]` may have a pull answered by
4//! the GitHub source of the artifact's scope. The runtime has no source client of its own: the
5//! launcher hands staging a [`SourceSupply`] (`StageRequest::source_supply`), and the pull path
6//! asks it for an index and then for one exact payload. Every refusal the supply returns is a
7//! sentence the pull passes on after its own leading token.
8//!
9//! A supply writes nothing. What a source pull installs reaches `tools/<tool>/`, `murmur.lock`
10//! and the compiled-form cache through the same writes a store pull makes, and no store.
11
12use std::fmt;
13
14use murmur_artifact::{ArtifactIndex, ArtifactName, MurmurLock, ResolvedArtifact};
15
16/// The scope sources a session may fetch from.
17pub trait SourceSupply: Send + Sync {
18    /// `github:<owner>/<repo>` of the source serving `scope`, or `None` when no source serves it.
19    fn source_label(&self, scope: &str) -> Option<String>;
20    /// Every scope a source serves, for a `*` listing.
21    fn scopes(&self) -> Vec<String>;
22    /// The index on the latest release of `scope`'s source.
23    fn index(&self, scope: &str) -> Result<ArtifactIndex, String>;
24    /// `name@version`'s payload, fetched from its scope's source and checked against the index
25    /// (SHA-256, packed name and version) and the scope's owner id against `lock`. Writes nothing.
26    fn fetch(
27        &self,
28        name: &ArtifactName,
29        version: &str,
30        lock: &MurmurLock,
31    ) -> Result<SourcedArtifact, String>;
32}
33
34impl fmt::Debug for dyn SourceSupply {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        f.debug_struct("SourceSupply")
37            .field("scopes", &self.scopes())
38            .finish()
39    }
40}
41
42/// A payload a [`SourceSupply`] fetched and checked.
43#[derive(Debug, Clone)]
44pub struct SourcedArtifact {
45    /// The payload as a store resolve returns one: its `meta` is built from the packed manifest
46    /// and carries [`Self::owner_id`].
47    pub resolved: ResolvedArtifact,
48    /// `github:<owner>/<repo>`.
49    pub source: String,
50    /// GitHub's numeric id of the source repository's owner, already checked.
51    pub owner_id: u64,
52}