kcode-rust-libs-v2 0.1.0

Manage, validate, and publish complete agent-authored Rust library snapshots
Documentation
//! Complete managed Rust-library snapshots without duplicated documentation.

mod model;
mod repository;
mod sandbox;

use std::fmt;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};

pub use model::{
    CheckResult, CheckStage, CheckStageResult, Error, Result, RustLibFile, RustLibPath,
};
use repository::{RepositorySnapshot, read_repository, validate_name, write_repository};

static WORK_COUNTER: AtomicU64 = AtomicU64::new(0);

/// Manager for a persistent root of small agent-authored Rust libraries.
#[derive(Clone)]
pub struct KcodeRustLibs {
    rust_libs_root: PathBuf,
    shared: Arc<Shared>,
}

impl KcodeRustLibs {
    /// Creates or opens the library root and retains the publication token privately.
    pub fn new(
        rust_libs_root: impl AsRef<Path>,
        crates_io_registry_token: impl AsRef<str>,
    ) -> Result<Self> {
        let token = RegistryToken::new(crates_io_registry_token.as_ref())?;
        let requested_root = absolute_path(rust_libs_root.as_ref())?;
        fs::create_dir_all(&requested_root)
            .map_err(|source| Error::io("create Rust libraries root", &requested_root, source))?;
        let rust_libs_root = fs::canonicalize(&requested_root).map_err(|source| {
            Error::io("canonicalize Rust libraries root", &requested_root, source)
        })?;
        if !fs::metadata(&rust_libs_root)
            .map_err(|source| Error::io("inspect Rust libraries root", &rust_libs_root, source))?
            .is_dir()
        {
            return Err(Error::RustLibIsNotDirectory(
                rust_libs_root.display().to_string(),
            ));
        }

        let work_root = WorkRoot::new()?;
        if paths_overlap(&rust_libs_root, work_root.path()) {
            return Err(Error::RootsOverlap {
                rust_libs_root,
                work_root: work_root.path().to_path_buf(),
            });
        }
        Ok(Self {
            rust_libs_root,
            shared: Arc::new(Shared { token, work_root }),
        })
    }

    /// Creates a new Rust 2024 library at version 0.1.0 and opens it.
    pub fn create_rust_lib(&self, name: &str) -> Result<OpenedRustLib> {
        validate_name(name)?;
        let root = self.rust_libs_root.join(name);
        match fs::symlink_metadata(&root) {
            Ok(_) => return Err(Error::RustLibAlreadyExists(name.to_owned())),
            Err(source) if source.kind() == io::ErrorKind::NotFound => {}
            Err(source) => {
                return Err(Error::io("inspect Rust library destination", &root, source));
            }
        }
        fs::create_dir(&root).map_err(|source| Error::io("create Rust library", &root, source))?;
        let creation = (|| {
            let source = root.join("src");
            fs::create_dir(&source)
                .map_err(|error| Error::io("create source directory", &source, error))?;
            let manifest = format!(
                "[package]\nname = \"{name}\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
            );
            fs::write(root.join("Cargo.toml"), manifest).map_err(|error| {
                Error::io("write initial manifest", root.join("Cargo.toml"), error)
            })?;
            fs::write(root.join("Documentation.md"), "").map_err(|error| {
                Error::io(
                    "write initial documentation",
                    root.join("Documentation.md"),
                    error,
                )
            })?;
            fs::write(source.join("lib.rs"), "")
                .map_err(|error| Error::io("write initial source", source.join("lib.rs"), error))?;
            self.open_rust_lib(name)
        })();
        if creation.is_err() {
            let _ = fs::remove_dir_all(&root);
        }
        creation
    }

    /// Opens and completely loads an existing managed Rust library.
    pub fn open_rust_lib(&self, name: &str) -> Result<OpenedRustLib> {
        validate_name(name)?;
        let root = self.rust_libs_root.join(name);
        let metadata = match fs::symlink_metadata(&root) {
            Ok(metadata) => metadata,
            Err(source) if source.kind() == io::ErrorKind::NotFound => {
                return Err(Error::RustLibNotFound(name.to_owned()));
            }
            Err(source) => return Err(Error::io("inspect Rust library", &root, source)),
        };
        if metadata.file_type().is_symlink() {
            return Err(Error::SymlinkNotAllowed(root));
        }
        if !metadata.is_dir() {
            return Err(Error::RustLibIsNotDirectory(name.to_owned()));
        }
        let snapshot = read_repository(&root)?;
        Ok(OpenedRustLib {
            name: name.to_owned(),
            root,
            snapshot,
            shared: Arc::clone(&self.shared),
        })
    }
}

impl fmt::Debug for KcodeRustLibs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("KcodeRustLibs")
            .field("rust_libs_root", &self.rust_libs_root)
            .field("registry_token", &"[REDACTED]")
            .finish_non_exhaustive()
    }
}

/// One fully loaded managed Rust library.
pub struct OpenedRustLib {
    name: String,
    root: PathBuf,
    snapshot: RepositorySnapshot,
    shared: Arc<Shared>,
}

impl OpenedRustLib {
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Returns the canonical root-package version.
    pub fn version(&self) -> &str {
        &self.snapshot.version
    }

    /// Returns every managed UTF-8 file exactly once, sorted by path.
    pub fn files(&self) -> &[RustLibFile] {
        &self.snapshot.files
    }

    /// Creates or completely replaces supplied files and refreshes the snapshot.
    pub fn write(&mut self, files: &[RustLibFile]) -> Result<()> {
        self.snapshot = write_repository(&self.root, &self.snapshot.files, files)?;
        Ok(())
    }

    /// Runs the complete six-stage validation pipeline.
    pub fn check(&self) -> Result<CheckResult> {
        sandbox::check_repository(&self.root, self.shared.work_root.path())
    }

    /// Rechecks and publishes the root package to crates.io.
    pub fn publish(&self) -> Result<()> {
        let check = self.check()?;
        if !check.passed() {
            return Err(Error::CheckFailed(check));
        }
        sandbox::publish_repository(
            &self.root,
            self.shared.work_root.path(),
            self.shared.token.expose(),
        )
    }
}

struct Shared {
    token: RegistryToken,
    work_root: WorkRoot,
}

struct RegistryToken(Arc<str>);

impl RegistryToken {
    fn new(value: &str) -> Result<Self> {
        let value = value.trim();
        if value.is_empty() {
            return Err(Error::InvalidRegistryToken);
        }
        Ok(Self(Arc::from(value)))
    }

    fn expose(&self) -> &str {
        &self.0
    }
}

impl fmt::Debug for RegistryToken {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("[REDACTED]")
    }
}

struct WorkRoot(PathBuf);

impl WorkRoot {
    fn new() -> Result<Self> {
        let parent = std::env::temp_dir().join("kcode-rust-libs-v2");
        fs::create_dir_all(&parent)
            .map_err(|source| Error::io("create temporary work parent", &parent, source))?;
        for _ in 0..100 {
            let timestamp = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos();
            let counter = WORK_COUNTER.fetch_add(1, Ordering::Relaxed);
            let path = parent.join(format!(
                "process-{}-{timestamp}-{counter}",
                std::process::id()
            ));
            match fs::create_dir(&path) {
                Ok(()) => {
                    let canonical = fs::canonicalize(&path).map_err(|source| {
                        Error::io("canonicalize temporary work root", &path, source)
                    })?;
                    return Ok(Self(canonical));
                }
                Err(source) if source.kind() == io::ErrorKind::AlreadyExists => continue,
                Err(source) => {
                    return Err(Error::io("create temporary work root", path, source));
                }
            }
        }
        Err(Error::Sandbox {
            stage: "prepare-work-root".to_owned(),
            message: "could not allocate a unique process work root".to_owned(),
        })
    }

    fn path(&self) -> &Path {
        &self.0
    }
}

impl Drop for WorkRoot {
    fn drop(&mut self) {
        let _ = fs::remove_dir_all(&self.0);
    }
}

fn absolute_path(path: &Path) -> Result<PathBuf> {
    if path.is_absolute() {
        Ok(path.to_path_buf())
    } else {
        let current = std::env::current_dir()
            .map_err(|source| Error::io("read current directory", ".", source))?;
        Ok(current.join(path))
    }
}

fn paths_overlap(left: &Path, right: &Path) -> bool {
    left.starts_with(right) || right.starts_with(left)
}