Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ authors = ["Danil Silantyev / NDDev"]
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["preserve_order"] }
sha2 = "0.11"
# DEFLATE only. The gzip framing and the tar reading are ours (see
# `setup-core::archive`); an inflate loop is not, because its bugs are
# memory-safety bugs and it is not improved by being hand-written here.
miniz_oxide = "0.9"
setup-core = { path = "crates/setup-core", version = "0.0.1" }
provider-v3 = { path = "crates/provider-v3", version = "0.0.1" }
harness-runtime = { path = "crates/harness-runtime", version = "0.0.1" }
Expand Down
31 changes: 30 additions & 1 deletion crates/harness-runtime/src/facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use provider_v3::{
Command, ComponentKind, Declaration, Operation, ProjectionKind, ProjectionProfile, ProviderInfo,
};
use setup_core::digest;
use setup_core::software::{Delivery, Software};

/// One harness, as the runtime needs to know it.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -67,6 +68,13 @@ pub struct Harness {
pub max_bytes: u64,
/// The exact provider-kit revision this build was compiled against.
pub kit_identity: &'static str,
/// How the product's own software is installed, when this build can do it.
///
/// `None` means the software lifecycle is not offered at all. So does a
/// [`Delivery::Manager`], which is a different statement -- the product is
/// installable, but not by fetching bytes whose digest was fixed in advance
/// -- and the refusal says which.
pub software: Option<Software>,
}

/// How many backup slots a target keeps.
Expand Down Expand Up @@ -180,6 +188,24 @@ impl Harness {
/// implement them — declaring one would let a consumer call an operation
/// that cannot be honoured, which is worse than not offering it.
///
/// The operations this build actually performs.
///
/// The software lifecycle is optional in the contract, and declaring an
/// operation a build cannot perform lets a consumer ask for something that
/// cannot be honoured. So it appears here only when this harness carries an
/// artifact table -- never when the product is delivered by a package
/// manager this provider does not run.
#[must_use]
pub fn operations(&self) -> &'static [Operation] {
match self.software {
Some(Software {
delivery: Delivery::Artifacts(_),
..
}) => Operation::CORE_AND_SOFTWARE,
_ => Operation::CORE,
}
}

/// # Errors
///
/// Propagates a declaration refusal.
Expand All @@ -191,7 +217,7 @@ impl Harness {
provider_version: self.version,
provider_build_digest: &build_digest,
commands: Command::CORE,
operations: Operation::CORE,
operations: self.operations(),
supported_os: &["linux", "macos", "windows"],
supported_arch: &["x86_64", "arm64"],
permission_profiles: self.permission_profiles,
Expand All @@ -206,7 +232,10 @@ mod tests {

use super::*;

/// A harness that offers no software lifecycle, which is most of what the
/// declaration tests are about.
pub(crate) const SAMPLE: Harness = Harness {
software: None,
harness_id: "sample",
provider_id: "sample-setup-system",
version: "0.1.0",
Expand Down
4 changes: 4 additions & 0 deletions crates/harness-runtime/src/human.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,10 @@ fn mutate(
restore_target_digest,
permission_profile: None,
expires_at: &expiry::deadline_in(PLAN_WINDOW_SECONDS, SystemTime::now()),
// The human surface drives configuration, never the product's own
// install: that arrives over the wire, with artifacts somebody else
// downloaded between planning and applying.
software_artifacts: Vec::new(),
effects: effect_lines(harness, &effect, applied.setup_id.as_deref()),
})?;
let plan_digest = artifact.digest()?;
Expand Down
16 changes: 12 additions & 4 deletions crates/harness-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,27 @@
//! `replace` materialize an `ai-stp-bundle/1` the consumer sends, or a complete
//! setup from the local catalog when the owner asks for one by name.
//!
//! The software lifecycle and `launch` are optional in the contract and are not
//! declared at all. Declaring an optional operation this runtime cannot perform
//! would let a consumer call something that cannot be honoured, which is worse
//! than not offering it.
//! The software lifecycle is optional in the contract, and a harness declares
//! it only when it carries an artifact table -- so six of the seven do, and pi
//! does not, because npm resolves its dependency closure at install time and
//! there is no single artifact whose digest can be fixed in advance. `launch`
//! is declared by none. Declaring an optional operation this runtime cannot
//! perform would let a consumer call something that cannot be honoured, which
//! is worse than not offering it.

pub mod catalog;
pub mod expiry;
pub mod facts;
pub mod human;
pub(crate) mod software;
pub mod wire;

pub use catalog::{Catalog, Setup};
// The software types belong to the kernel, but a setup system declares its
// artifact table and depends only on this crate. Re-exported so that stays
// true rather than widening seven dependency lists to reach past it.
pub use facts::{BACKUP_SLOTS, BUNDLE_FORMAT, Harness};
pub use setup_core::software::{Artifact, Delivery, Shape, Software};
pub use wire::dispatch;

use std::process::ExitCode;
Expand Down
Loading
Loading