ahrightos-fs 0.1.0

Portable filesystem, block-device, and IPC primitives for the AhRightOS teaching kernel.
Documentation
//! Component metadata registry for AhRightOS.
//!
//! Commercial deployments need a stable way to answer a simple question:
//! "which platform capabilities are present, and which interfaces may users
//! rely on?"  This module keeps that answer data-driven and independent from
//! syscall code.  The registry is intentionally small, static, and `no_std`
//! friendly; future loaders can replace the static slice with signed component
//! manifests without changing the public inspection API.

use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Write;

/// Coarse placement of a component in the AhRightOS product architecture.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentLayer {
    Core,
    Filesystem,
    Device,
    Observability,
    Platform,
}

impl ComponentLayer {
    pub const fn as_str(self) -> &'static str {
        match self {
            ComponentLayer::Core => "core",
            ComponentLayer::Filesystem => "filesystem",
            ComponentLayer::Device => "device",
            ComponentLayer::Observability => "observability",
            ComponentLayer::Platform => "platform",
        }
    }
}

/// Public contract stability for a component.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentStability {
    /// Intended to remain backward compatible for users of the public ABI.
    Stable,
    /// Usable for experiments, but not a long-term compatibility promise.
    Experimental,
    /// Implementation detail; do not rely on it from applications or labs.
    Internal,
}

impl ComponentStability {
    pub const fn as_str(self) -> &'static str {
        match self {
            ComponentStability::Stable => "stable",
            ComponentStability::Experimental => "experimental",
            ComponentStability::Internal => "internal",
        }
    }
}

/// Static manifest for one AhRightOS component.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ComponentManifest {
    pub id: &'static str,
    pub version: &'static str,
    pub layer: ComponentLayer,
    pub stability: ComponentStability,
    pub description: &'static str,
    pub capabilities: &'static [&'static str],
    pub requires: &'static [&'static str],
    pub provides: &'static [&'static str],
}

impl ComponentManifest {
    pub const fn is_stable_public_interface(&self) -> bool {
        matches!(self.stability, ComponentStability::Stable)
    }
}

/// Registry validation failure.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentRegistryError {
    MissingDependency {
        component: &'static str,
        dependency: &'static str,
    },
}

/// Read-only component registry.
#[derive(Debug)]
pub struct ComponentRegistry {
    components: &'static [ComponentManifest],
}

impl ComponentRegistry {
    pub const fn new(components: &'static [ComponentManifest]) -> Self {
        Self { components }
    }

    pub const fn components(&self) -> &'static [ComponentManifest] {
        self.components
    }

    pub const fn len(&self) -> usize {
        self.components.len()
    }

    pub const fn is_empty(&self) -> bool {
        self.components.is_empty()
    }

    pub fn find(&self, id: &str) -> Option<&'static ComponentManifest> {
        self.components.iter().find(|component| component.id == id)
    }

    pub fn validate_dependencies(&self) -> Result<(), ComponentRegistryError> {
        for component in self.components.iter() {
            for dependency in component.requires.iter() {
                if self.find(dependency).is_none() {
                    return Err(ComponentRegistryError::MissingDependency {
                        component: component.id,
                        dependency,
                    });
                }
            }
        }
        Ok(())
    }

    /// Render a compact ASCII listing suitable for `/sys/fs/ahrightos/components`.
    pub fn render_sysfs_listing(&self) -> Vec<u8> {
        let mut out = String::from("id version layer stability capabilities requires provides\n");
        for component in self.components.iter() {
            let _ = write!(
                out,
                "{} {} {} {} ",
                component.id,
                component.version,
                component.layer.as_str(),
                component.stability.as_str()
            );
            write_csv(&mut out, component.capabilities);
            out.push(' ');
            write_csv(&mut out, component.requires);
            out.push(' ');
            write_csv(&mut out, component.provides);
            out.push('\n');
        }
        out.into_bytes()
    }
}

fn write_csv(out: &mut String, values: &[&str]) {
    if values.is_empty() {
        out.push('-');
        return;
    }

    for (idx, value) in values.iter().enumerate() {
        if idx > 0 {
            out.push(',');
        }
        out.push_str(value);
    }
}

const VERSION: &str = env!("CARGO_PKG_VERSION");

const BUILTIN_COMPONENTS: &[ComponentManifest] = &[
    ComponentManifest {
        id: "ahrightos-core",
        version: VERSION,
        layer: ComponentLayer::Core,
        stability: ComponentStability::Stable,
        description: "Kernel bootstrap, heap initialization, and base runtime contracts.",
        capabilities: &["kernel.boot", "heap.init", "runtime.base"],
        requires: &[],
        provides: &["abi.ahrightos-core.v0"],
    },
    ComponentManifest {
        id: "ahrightos-vfs",
        version: VERSION,
        layer: ComponentLayer::Filesystem,
        stability: ComponentStability::Stable,
        description: "Unified path resolution and mount dispatch for filesystem components.",
        capabilities: &[
            "vfs.mount-table",
            "vfs.path-resolution",
            "vfs.file-dispatch",
        ],
        requires: &["ahrightos-core"],
        provides: &["api.vfs.v0"],
    },
    ComponentManifest {
        id: "ahrightos-ramfs",
        version: VERSION,
        layer: ComponentLayer::Filesystem,
        stability: ComponentStability::Stable,
        description: "Volatile in-memory filesystem used for root paths and /run.",
        capabilities: &["fs.ramfs", "fs.volatile-runtime"],
        requires: &["ahrightos-vfs"],
        provides: &["/run", "fs.ramfs.v0"],
    },
    ComponentManifest {
        id: "ahrightos-blkfs",
        version: VERSION,
        layer: ComponentLayer::Filesystem,
        stability: ComponentStability::Experimental,
        description: "Block-backed filesystem for persistent teaching experiments.",
        capabilities: &["fs.blkfs", "block-cache", "mount.blkfs"],
        requires: &["ahrightos-vfs"],
        provides: &["fs.blkfs.v0"],
    },
    ComponentManifest {
        id: "ahrightos-procfs",
        version: VERSION,
        layer: ComponentLayer::Observability,
        stability: ComponentStability::Experimental,
        description: "Linux-inspired read-only process/system information pseudo filesystem.",
        capabilities: &["proc.version", "proc.meminfo", "proc.mounts"],
        requires: &["ahrightos-vfs"],
        provides: &["/proc/version", "/proc/meminfo", "/proc/mounts"],
    },
    ComponentManifest {
        id: "ahrightos-sysfs",
        version: VERSION,
        layer: ComponentLayer::Observability,
        stability: ComponentStability::Experimental,
        description: "Linux-inspired system attribute pseudo filesystem.",
        capabilities: &["sys.kernel", "sys.component-inspection"],
        requires: &["ahrightos-vfs"],
        provides: &["/sys/kernel/name", "/sys/fs/ahrightos/components"],
    },
    ComponentManifest {
        id: "ahrightos-devtmpfs",
        version: VERSION,
        layer: ComponentLayer::Device,
        stability: ComponentStability::Experimental,
        description: "Device-node entry point for built-in teaching character devices.",
        capabilities: &["dev.null", "dev.zero"],
        requires: &["ahrightos-vfs"],
        provides: &["/dev/null", "/dev/zero"],
    },
    ComponentManifest {
        id: "ahrightos-component-platform",
        version: VERSION,
        layer: ComponentLayer::Platform,
        stability: ComponentStability::Experimental,
        description: "Manifest and registry foundation for commercial extensions.",
        capabilities: &[
            "component.registry",
            "component.manifest.v0",
            "component.sysfs-export",
        ],
        requires: &["ahrightos-sysfs"],
        provides: &["/sys/fs/ahrightos/components", "component.manifest.v0"],
    },
];

static BUILTIN_COMPONENT_REGISTRY: ComponentRegistry = ComponentRegistry::new(BUILTIN_COMPONENTS);

pub fn builtin_component_registry() -> &'static ComponentRegistry {
    &BUILTIN_COMPONENT_REGISTRY
}

pub fn render_builtin_component_listing() -> Vec<u8> {
    BUILTIN_COMPONENT_REGISTRY.render_sysfs_listing()
}