Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

holger-estate-front/src/sealed.rs

//! **The primary's sealed slot** (feature `metered`): where holger's front keeps what
//! only the estate may hold — its installer material, taken from the ONE monetize
//! (`SoldEstate.TakeMaterial`) — on holger's PRIMARY, over holger's own
//! `RepositoryService` (the client generated from holger's proto, [`crate::certify::proto`]).
//!
//! ONE raw repository on the primary, [`SEALED_REPOSITORY`], that the kit declares with
//! `ron_require_auth: true` and `ron_require_role: Some(Admin)`: every other repository of
//! the estate reads open, this one answers an ADMIN only (the console's bearer). The twin
//! follows it like every other, so a main laid again gets it back from its twin.
//!
//! The credential is the fed console bearer (`holger_console_token`, Admin). The primary is
//! the one the verdict names NOW: a main laid again is found at its new address.

use std::time::Duration;

use nordisk_pairing::join::JoinReply;

use crate::certify::proto;
use proto::repository_service_client::RepositoryServiceClient;

/// **The gated repository the kit declares** (private-holger-ops `install::BACKUP_REPOSITORY`,
/// the same word; the name predates G16, when the front's own monetize backed up there).
pub const SEALED_REPOSITORY: &str = "monetize-backup";
/// The material's name in it.
pub const MATERIAL_OBJECT: &str = "installer-material.json";
const MAX_MESSAGE: usize = 64 << 20;

/// holger's primary as the sealed slot. Blocking: call it from a thread that is not a
/// runtime worker (a jera job, `spawn_blocking`).
pub struct PrimarySlot {
    pub handle: tokio::runtime::Handle,
    /// `<utility>:50051`.
    pub control: String,
    pub bearer: String,
    pub repository: String,
    pub timeout: Duration,
}

/// Pure: **the slot the fed reply names** — the elected primary's control plane and the
/// console's bearer; `None` until both are fed.
pub fn slot_of(reply: &JoinReply, handle: &tokio::runtime::Handle) -> Option<PrimarySlot> {
    let control = crate::primary_control(reply)?;
    let bearer = crate::console_key::bearers(reply)
        .ok()
        .flatten()?
        .at(&control)?
        .to_string();
    Some(PrimarySlot {
        handle: handle.clone(),
        control,
        bearer,
        repository: SEALED_REPOSITORY.into(),
        timeout: Duration::from_secs(60),
    })
}

/// Pure: **does a `NotFound` say the REPOSITORY is unknown** (holger's frozen code
/// `holger-server-1`, "no such repository"), not the object?
pub fn repository_unknown(message: &str) -> bool {
    message.contains("[holger-server-1]")
}

fn said(s: tonic::Status) -> String {
    format!("{:?}: {}", s.code(), s.message())
}

/// Pure: the raw repository's id of an object (the path is the name).
pub fn id_of(name: &str) -> proto::ArtifactId {
    proto::ArtifactId {
        namespace: String::new(),
        name: name.to_string(),
        version: String::new(),
    }
}

impl PrimarySlot {
    fn req<T>(&self, body: T) -> Result<tonic::Request<T>, String> {
        let mut r = tonic::Request::new(body);
        r.set_timeout(self.timeout);
        r.metadata_mut().insert(
            "authorization",
            format!("Bearer {}", self.bearer)
                .parse()
                .map_err(|_| "the bearer is not a header value".to_string())?,
        );
        Ok(r)
    }

    async fn client(&self) -> Result<RepositoryServiceClient<tonic::transport::Channel>, String> {
        // The installer material goes to the primary over wg0 only on an estate (lane E1).
        crate::wg_only::check("the primary's sealed slot", &self.control)?;
        let ep = tonic::transport::Endpoint::from_shared(format!("http://{}", self.control))
            .map_err(|e| format!("{}: {e}", self.control))?
            .connect_timeout(self.timeout);
        Ok(RepositoryServiceClient::new(
            ep.connect()
                .await
                .map_err(|e| format!("{}: {e}", self.control))?,
        )
        .max_decoding_message_size(MAX_MESSAGE)
        .max_encoding_message_size(MAX_MESSAGE))
    }

    pub fn describe(&self) -> String {
        format!(
            "holger's primary {} repository {}",
            self.control, self.repository
        )
    }

    /// The object, or `None` when it was never kept. A primary that declares no such
    /// repository is an `Err` by name, never "not kept" (lane F9: test3-holger-rs's media
    /// declared no `monetize-backup`, so the front read "never kept" for ever and could store
    /// nothing).
    pub fn get(&self, name: &str) -> Result<Option<Vec<u8>>, String> {
        self.handle.block_on(async {
            match self
                .client()
                .await?
                .fetch_artifact(self.req(proto::FetchArtifactRequest {
                    repository: self.repository.clone(),
                    id: Some(id_of(name)),
                })?)
                .await
            {
                Ok(r) => Ok(Some(r.into_inner().data)),
                Err(s) if s.code() == tonic::Code::NotFound && repository_unknown(s.message()) => {
                    Err(format!(
                        "[sealed-slot-undeclared] {} declares no repository {}: {}",
                        self.control,
                        self.repository,
                        s.message()
                    ))
                }
                Err(s) if s.code() == tonic::Code::NotFound => Ok(None),
                Err(s) => Err(said(s)),
            }
        })
    }

    pub fn put(&self, name: &str, bytes: &[u8]) -> Result<(), String> {
        self.handle.block_on(async {
            let r = self
                .client()
                .await?
                .put_artifact(self.req(proto::PutArtifactRequest {
                    repository: self.repository.clone(),
                    id: Some(id_of(name)),
                    data: bytes.to_vec(),
                    async_job: false,
                })?)
                .await
                .map_err(said)?
                .into_inner();
            if r.success {
                Ok(())
            } else {
                Err(format!(
                    "PutArtifact answered success = false: {}",
                    r.message
                ))
            }
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    /// F9: a primary without the sealed repository is named, never read as "never kept".
    #[test]
    fn an_undeclared_sealed_repository_is_told_apart_from_a_missing_object() {
        assert!(repository_unknown(
            "[holger-server-1] Repository 'monetize-backup' not found"
        ));
        assert!(!repository_unknown(
            "[holger-server-2] Artifact 'installer-material.json' not found"
        ));
    }

    #[test]
    fn the_material_is_a_raw_path_with_no_namespace_or_version() {
        let id = id_of(MATERIAL_OBJECT);
        assert!(id.namespace.is_empty() && id.version.is_empty());
        assert_eq!(id.name, "installer-material.json");
    }
}