Skip to content
Open
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
11 changes: 11 additions & 0 deletions 03_PROTO/Cargo.lock

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

6 changes: 6 additions & 0 deletions 03_PROTO/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ members = [
"crates/riina-pkg",
"crates/riina-wasm",
"crates/riina-runtime",
"crates/riina-ui",
"crates/riina-os",
"crates/riinac",
]

Expand Down Expand Up @@ -50,6 +52,10 @@ riina-runtime = { path = "crates/riina-runtime" }
riina-typechecker = { path = "crates/riina-typechecker" }
riina-wasm = { path = "crates/riina-wasm" }

# Internal dependencies - Platform crates
riina-ui = { path = "crates/riina-ui" }
riina-os = { path = "crates/riina-os" }

# No external dependencies (Law 8)

[workspace.lints.rust]
Expand Down
12 changes: 12 additions & 0 deletions 03_PROTO/crates/riina-os/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "riina-os"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
description = "RIINA OS primitives — TERAS kernel abstractions"

[dependencies]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(test)'] }
134 changes: 134 additions & 0 deletions 03_PROTO/crates/riina-os/src/capability.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//! Capability-based security system.
//!
//! Hardware capabilities with delegation and linear revocation.

/// Permission flags for a capability.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Permissions {
pub read: bool,
pub write: bool,
pub execute: bool,
}

impl Permissions {
pub const NONE: Self = Self { read: false, write: false, execute: false };
pub const READ_ONLY: Self = Self { read: true, write: false, execute: false };
pub const READ_WRITE: Self = Self { read: true, write: true, execute: false };
pub const ALL: Self = Self { read: true, write: true, execute: true };
}

/// A capability granting access to a resource.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Capability {
pub resource: u64,
pub permissions: Permissions,
pub delegatable: bool,
}

impl Capability {
pub fn new(resource: u64, permissions: Permissions, delegatable: bool) -> Self {
Self { resource, permissions, delegatable }
}

pub fn can_read(&self) -> bool {
self.permissions.read
}

pub fn can_write(&self) -> bool {
self.permissions.write
}

pub fn can_execute(&self) -> bool {
self.permissions.execute
}

/// Delegate this capability to another entity.
/// Returns `None` if the capability is not delegatable.
pub fn delegate(&self) -> Option<Capability> {
if self.delegatable {
Some(self.clone())
} else {
None
}
}

/// Revoke this capability by consuming it (linear ownership).
/// The capability is moved into this function and cannot be used afterward.
pub fn revoke(self) {
// Consuming self ensures the capability cannot be used after revocation.
// No explicit drop needed — Rust's ownership system handles it.
}
}

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

#[test]
fn capability_read_permission() {
let cap = Capability::new(1, Permissions::READ_ONLY, false);
assert!(cap.can_read());
assert!(!cap.can_write());
assert!(!cap.can_execute());
}

#[test]
fn capability_all_permissions() {
let cap = Capability::new(1, Permissions::ALL, false);
assert!(cap.can_read());
assert!(cap.can_write());
assert!(cap.can_execute());
}

#[test]
fn capability_no_permissions() {
let cap = Capability::new(1, Permissions::NONE, false);
assert!(!cap.can_read());
assert!(!cap.can_write());
assert!(!cap.can_execute());
}

#[test]
fn delegatable_capability_delegates() {
let cap = Capability::new(42, Permissions::READ_WRITE, true);
let delegated = cap.delegate();
assert!(delegated.is_some());
let d = delegated.unwrap();
assert_eq!(d.resource, 42);
assert_eq!(d.permissions, Permissions::READ_WRITE);
}

#[test]
fn non_delegatable_capability_fails() {
let cap = Capability::new(42, Permissions::READ_WRITE, false);
assert!(cap.delegate().is_none());
}

#[test]
fn revoke_consumes_capability() {
let cap = Capability::new(1, Permissions::ALL, true);
cap.revoke();
// cap is moved — cannot use after revoke (enforced by Rust's ownership)
}

#[test]
fn capability_equality() {
let a = Capability::new(1, Permissions::READ_ONLY, false);
let b = Capability::new(1, Permissions::READ_ONLY, false);
assert_eq!(a, b);
}

#[test]
fn capability_inequality_resource() {
let a = Capability::new(1, Permissions::READ_ONLY, false);
let b = Capability::new(2, Permissions::READ_ONLY, false);
assert_ne!(a, b);
}

#[test]
fn capability_inequality_permissions() {
let a = Capability::new(1, Permissions::READ_ONLY, false);
let b = Capability::new(1, Permissions::READ_WRITE, false);
assert_ne!(a, b);
}
}
124 changes: 124 additions & 0 deletions 03_PROTO/crates/riina-os/src/ipc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//! IPC — Inter-process communication.
//!
//! Simple message-passing between endpoints.

use std::collections::VecDeque;

/// An IPC endpoint identifier.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Endpoint {
pub id: u64,
}

/// A message sent between endpoints.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Message {
pub sender: u64,
pub payload: Vec<u8>,
}

/// IPC error types.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IpcError {
EndpointNotFound,
ChannelFull,
ChannelEmpty,
PermissionDenied,
}

/// A simple IPC channel backed by a bounded queue.
#[derive(Debug)]
pub struct Channel {
pub endpoint: Endpoint,
buffer: VecDeque<Message>,
capacity: usize,
}

impl Channel {
pub fn new(endpoint: Endpoint, capacity: usize) -> Self {
Self {
endpoint,
buffer: VecDeque::with_capacity(capacity),
capacity,
}
}

/// Send a message to this channel.
pub fn send(&mut self, msg: Message) -> Result<(), IpcError> {
if self.buffer.len() >= self.capacity {
return Err(IpcError::ChannelFull);
}
self.buffer.push_back(msg);
Ok(())
}

/// Receive the next message from this channel.
pub fn recv(&mut self) -> Result<Message, IpcError> {
self.buffer.pop_front().ok_or(IpcError::ChannelEmpty)
}

/// Check if the channel is empty.
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}

/// Number of pending messages.
pub fn len(&self) -> usize {
self.buffer.len()
}
}

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

fn make_channel(cap: usize) -> Channel {
Channel::new(Endpoint { id: 1 }, cap)
}

fn make_msg(sender: u64, data: &[u8]) -> Message {
Message { sender, payload: data.to_vec() }
}

#[test]
fn send_and_recv() {
let mut ch = make_channel(10);
ch.send(make_msg(1, b"hello")).unwrap();
let msg = ch.recv().unwrap();
assert_eq!(msg.sender, 1);
assert_eq!(msg.payload, b"hello");
}

#[test]
fn recv_empty_channel() {
let mut ch = make_channel(10);
assert_eq!(ch.recv(), Err(IpcError::ChannelEmpty));
}

#[test]
fn send_full_channel() {
let mut ch = make_channel(2);
ch.send(make_msg(1, b"a")).unwrap();
ch.send(make_msg(1, b"b")).unwrap();
assert_eq!(ch.send(make_msg(1, b"c")), Err(IpcError::ChannelFull));
}

#[test]
fn fifo_ordering() {
let mut ch = make_channel(10);
ch.send(make_msg(1, b"first")).unwrap();
ch.send(make_msg(2, b"second")).unwrap();
assert_eq!(ch.recv().unwrap().payload, b"first");
assert_eq!(ch.recv().unwrap().payload, b"second");
}

#[test]
fn len_and_is_empty() {
let mut ch = make_channel(10);
assert!(ch.is_empty());
assert_eq!(ch.len(), 0);
ch.send(make_msg(1, b"x")).unwrap();
assert!(!ch.is_empty());
assert_eq!(ch.len(), 1);
}
}
8 changes: 8 additions & 0 deletions 03_PROTO/crates/riina-os/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//! RIINA OS primitives — TERAS kernel abstractions
//!
//! Phase 9: OS-level capability system, IPC, memory management.

pub mod capability;
pub mod syscall;
pub mod ipc;
pub mod memory;
Loading