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
9 changes: 4 additions & 5 deletions .github/actions/setup-rust/action.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: 'Setup Rust Environment'
description: 'Sets up Rust toolchain with caching'
name: "Setup Rust Environment"
description: "Sets up Rust toolchain with caching"

runs:
using: 'composite'
using: "composite"
steps:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@c5a29ddb4d9d194e7c84ec8c3fba61b1c31fee8c
uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561
with:
toolchain: stable

Expand All @@ -19,4 +19,3 @@ runs:
with:
# Optional: cache dependencies as well
cache-on-failure: true

2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ on:
branches:
- master
- main
- dev
pull_request:
branches:
- master
- main
- dev

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Release

permissions:
pull-requests: write
contents: write

on:
push:
branches:
- main

jobs:
release-plz:
name: Release-plz
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@f7ccc83f9ed1e5b9c81d8a67d7ad1a747e22a561 # stable as of 2026-01-19

- name: Run release-plz
uses: MarcoIeni/release-plz-action@5ab144c9d67d4346240190d0f95ed08668677928
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_PUBLISH }}
45 changes: 39 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,47 @@ execution model while preserving the familiar POSIX/Linux syscall interface.

## Design Principles

ZeroOS is guided by a set of foundational principles aimed at delivering maximum security, transparency, and trust for developers building verifiable applications.
ZeroOS is guided by a set of foundational principles aimed at delivering maximum
security, transparency, and trust for developers building verifiable
applications.

### Fail-Fast Engineering
ZeroOS follows a fail-fast philosophy: rather than masking incomplete features behind silent stubs, the kernel immediately returns an error or halts when encountering unsupported requests (such as certain mmap flags or malloc options). This approach guarantees that every execution path in a zkVM trace is both intentional and fully supported.

ZeroOS follows a fail-fast philosophy: rather than masking incomplete features
behind silent stubs, the kernel immediately returns an error or halts when
encountering unsupported requests (such as certain mmap flags or malloc
options). This approach guarantees that every execution path in a zkVM trace is
both intentional and fully supported.

### Toolchain Integrity
Developers can rely on standard toolchains without modification. ZeroOS works seamlessly with off-the-shelf musl-libc and Rust std, keeping the Trusted Computing Base (TCB) lean. By avoiding custom compiler patches or altered libraries, audit efforts remain focused on the ZeroOS kernel and application logic, not sprawling toolchain changes.

Developers can rely on standard toolchains without modification. ZeroOS works
seamlessly with off-the-shelf musl-libc and Rust std, keeping the Trusted
Computing Base (TCB) lean. By avoiding custom compiler patches or altered
libraries, audit efforts remain focused on the ZeroOS kernel and application
logic, not sprawling toolchain changes.

### Surgical Modularity
The kernel is built from modular, compile-time configurable components. This design lets developers include only the functionality they truly need, reducing binary size and zkVM trace length. With less code to review, audits become more straightforward and effective.

The kernel is built from modular, compile-time configurable components. This
design lets developers include only the functionality they truly need, reducing
binary size and zkVM trace length. With less code to review, audits become more
straightforward and effective.

### Architectural Transparency
ZeroOS prioritizes clarity over abstraction. Core operations—such as thread creation, trap handling, and context switching—are implemented with explicit initialization and visible resource ownership. This transparency makes it easier to inspect critical paths for vulnerabilities and ensures deterministic behavior.

ZeroOS prioritizes clarity over abstraction. Core operations—such as thread
creation, trap handling, and context switching—are implemented with explicit
initialization and visible resource ownership. This transparency makes it easier
to inspect critical paths for vulnerabilities and ensures deterministic
behavior.

### Unikernel Simplicity
Operating as a statically linked unikernel in a single address space, ZeroOS avoids the complexity of multiple privilege levels and MMU management. In zkVM environments, these mechanisms often add unnecessary overhead and subtle risks. By stripping them away, ZeroOS achieves a simpler, more secure execution model.

Operating as a statically linked unikernel in a single address space, ZeroOS
avoids the complexity of multiple privilege levels and MMU management. In zkVM
environments, these mechanisms often add unnecessary overhead and subtle risks.
By stripping them away, ZeroOS achieves a simpler, more secure execution model.

## Getting Started

Expand Down Expand Up @@ -128,6 +153,14 @@ or
cargo massage
```

### Run CI locally (act)

To install `act`, visit <https://nektosact.com/> for installation instructions.

```bash
cargo act pull_request
```

## License

See `LICENSE-MIT` and `LICENSE-APACHE` for details.
1 change: 1 addition & 0 deletions bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ EOF
log "Shell integration installed into ~/.bashrc and/or ~/.zshrc"
fi
log "Please restart your shell or run 'direnv allow' to activate the environment."
log " or run 'exec \$SHELL -l' to reload your shell."
}

main "$@"
185 changes: 103 additions & 82 deletions crates/cargo-matrix/src/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,19 @@ enum FeatureSpec {
OneOf(Vec<String>),
}

#[derive(serde::Deserialize)]
#[serde(untagged)]
pub enum Packages {
One(String),
Many(Vec<String>),
}

#[derive(serde::Deserialize)]
struct MatrixEntry {
#[serde(default)]
commands: BTreeMap<String, String>,
command: Option<String>,
package: String,
package: Packages,
target: Targets,
#[serde(default)]
features: Vec<FeatureSpec>,
Expand Down Expand Up @@ -225,103 +232,117 @@ pub fn run(args: MatrixArgs) -> Result<(), String> {
}

for entry in &cfg.entries {
if !args.packages.is_empty() && !args.packages.iter().any(|p| p == &entry.package) {
continue;
}
let entry_packages = match &entry.package {
Packages::One(s) => vec![s.as_str()],
Packages::Many(v) => v.iter().map(|s| s.as_str()).collect(),
};

for package in entry_packages {
if !args.packages.is_empty() && !args.packages.iter().any(|p| p == package) {
continue;
}

let cmd_name = entry
.command
.as_ref()
.or(command.as_ref())
.ok_or_else(|| "no command selected (pass --command <name>)".to_string())?;

let template = entry
.commands
.get(cmd_name)
.or_else(|| cfg.commands.get(cmd_name));

let template: &str = if let Some(t) = template {
t.as_str()
} else {
// Strict Structural Resolution.
// If a command is not defined in the package-local or global commands map,
// the package is considered to not support this command and is skipped.
continue;
};

let cmd_name = entry
.command
.as_ref()
.or(command.as_ref())
.ok_or_else(|| "no command selected (pass --command <name>)".to_string())?;

let template: &str = entry
.commands
.get(cmd_name)
.or_else(|| cfg.commands.get(cmd_name))
.map(|s| s.as_str())
.unwrap_or(cmd_name);

let mut combos: Vec<Vec<String>> = vec![Vec::new()];
for spec in &entry.features {
match spec {
FeatureSpec::One(f) => {
for c in &mut combos {
c.push(f.clone());
let mut combos: Vec<Vec<String>> = vec![Vec::new()];
for spec in &entry.features {
match spec {
FeatureSpec::One(f) => {
for c in &mut combos {
c.push(f.clone());
}
}
}
FeatureSpec::OneOf(group) => {
let mut next: Vec<Vec<String>> = Vec::new();
for opt in group {
for c in &combos {
let mut nc = c.clone();
nc.push(opt.clone());
next.push(nc);
FeatureSpec::OneOf(group) => {
let mut next: Vec<Vec<String>> = Vec::new();
for opt in group {
for c in &combos {
let mut nc = c.clone();
nc.push(opt.clone());
next.push(nc);
}
}
combos = next;
}
combos = next;
}
}
}

fn flatten_targets<'a>(t: &'a TargetElem, out: &mut Vec<&'a str>) {
match t {
TargetElem::One(s) => out.push(s.as_str()),
TargetElem::Many(v) => {
for inner in v {
flatten_targets(inner, out);
fn flatten_targets<'a>(t: &'a TargetElem, out: &mut Vec<&'a str>) {
match t {
TargetElem::One(s) => out.push(s.as_str()),
TargetElem::Many(v) => {
for inner in v {
flatten_targets(inner, out);
}
}
}
}
}

let targets: Vec<&str> = match &entry.target {
Targets::One(t) => vec![t.as_str()],
Targets::Many(ts) => {
let mut out: Vec<&str> = Vec::new();
for t in ts {
flatten_targets(t, &mut out);
let targets: Vec<&str> = match &entry.target {
Targets::One(t) => vec![t.as_str()],
Targets::Many(ts) => {
let mut out: Vec<&str> = Vec::new();
for t in ts {
flatten_targets(t, &mut out);
}
out
}
out
}
};

for target in targets {
let target = if target == "host" {
host.as_str()
} else {
target
};
let total = combos.len();
for (idx, mut feats) in combos.iter().cloned().enumerate() {
feats.sort();
feats.dedup();
let feat_str = feats.join(",");
let features_flag = if feat_str.is_empty() {
String::new()
} else {
format!(r##"--features "{feat_str}""##)
};

let cmd = render_template(
template,
&workspace,
&entry.package,
target,
&feat_str,
&features_flag,
);

let suffix = if total > 1 {
format!(" #{}/{}", idx + 1, total)
for target in targets {
let target = if target == "host" {
host.as_str()
} else {
String::new()
target
};

steps.push(Step {
name: format!("{} [{target}] ({cmd_name}){suffix}", entry.package),
cmd,
});
let total = combos.len();
for (idx, mut feats) in combos.iter().cloned().enumerate() {
feats.sort();
feats.dedup();
let feat_str = feats.join(",");
let features_flag = if feat_str.is_empty() {
String::new()
} else {
format!(r##"--features "{feat_str}""##)
};

let cmd = render_template(
template,
&workspace,
package,
target,
&feat_str,
&features_flag,
);

let suffix = if total > 1 {
format!(" #{}/{}", idx + 1, total)
} else {
String::new()
};

steps.push(Step {
name: format!("{package} [{target}] ({cmd_name}){suffix}"),
cmd,
});
}
}
}
}
Expand Down
Loading
Loading