Skip to content

Fix the #405 boot regressions, add the Launchpad, and install the crates.io tool suite - #430

Merged
eKisNonos merged 11 commits into
mainfrom
Launchpad-Boot-Fixes
Jul 27, 2026
Merged

Fix the #405 boot regressions, add the Launchpad, and install the crates.io tool suite#430
eKisNonos merged 11 commits into
mainfrom
Launchpad-Boot-Fixes

Conversation

@eKisNonos

@eKisNonos eKisNonos commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

A clean checkout of main does not reach the desktop: two changes from #405 broke the boot path. This branch fixes both, adds the Launchpad, and installs seven unmodified crates.io command-line tools as signed, STARK-attested capsules.

Boot fixes

registry: boot-time service registration

The #405 service-squat hardening dropped the pid <= 64 caller shortcut. Init spawns every capsule with only the ambient capability set and no RegisterService, so the kernel's own spawn-time register_endpoint began refusing each one and no capsule reached the run queue. The system froze on the verified-boot splash.

register_endpoint now enforces only that the owner holds the capabilities the endpoint advertises, which is all the trusted spawn path needs. The MkServiceRegister syscall keeps the register-right check for a genuinely new name and lets a capsule re-assert the endpoint the kernel already published for it. A runtime squat is still refused.

ipc: reply correlation

mk_ipc_reply took its correlation token from a per-client queue kept separately from the pending-reply table it validated the reply against. With several callers waiting on one server the two orders diverged, replies went out under the wrong token, and callers discarded them and blocked. Every desktop client stalled at the compositor handshake, so after the registration fix the screen came up black.

The pending-reply entry, matched by the caller's own inbox, already carries that call's token. remove() returns it and the reply is stamped from it directly. The separate correlation table is gone. A forged mk_ipc_send reply still carries token 0 with no pending entry, so it is still dropped.

Launchpad

A dock button opens a full-screen grid of every desktop app and installed tool, so the dock stays short instead of growing a tile per app. The grid is built from the launcher and tool tables, so adding an app or installing a tool fills a cell with no layout change. A click launches the service or focuses it when it is already open. Each tool ships a 48x48 line-art glyph drawn in the same cyan tile language as the desktop apps.

Installed tools

grex, dotenv-linter, pastel, jsonxf, tokei, huniq and csview: unmodified crates.io source cross-compiled for x86_64-nonos against the std PAL, each signed with its own publisher keys and enrolled under the transparent STARK policy root. userland/apps.list is the single source of truth; tools/nonos-app cross-compiles a crate, mints its keys, writes its Capsule.mk, and regenerates both the kernel registry and the Launchpad table from it. Every tool source is byte-identical to its crates.io release; only the foundational-crate shims under upstream-src add the nonos target arm (getrandom over the CRND syscall, byte-based OsStr, a thread-local errno, advisory fd-lock, HOME-based dirs).

A new MkToolRun syscall runs a baked tool by name, parented to the caller so it drives the tool's stdin and stdout through the existing MkProcInput and MkProcOutput path. The shell recognizes each tool as a bare command and streams its output the same way a store install does.

Testing

Boots to the full desktop in QEMU at 1920x1080 over virtio-gpu. All capsules reach the run queue, the compositor handshake completes, app windows spawn, and every tool cross-compiles from vendored source in CI. Before the fixes the run-queue count was zero; the registration fix alone left a black screen until the ipc fix landed.

Display

The virtio-vga device advertised its resolution through xres/yres but without an EDID, so OVMF negotiated an oversized fallback mode on a fresh boot and the desktop came up scaled up. Turning on the device EDID makes the firmware read the advertised mode and settle on the native size every boot.

Screenshots

The Launchpad grid, with the installed tools next to the desktop apps, each drawn in the same cyan line-art tile language:

Launchpad

The desktop with the app dock:

Desktop

eKisNonos added 10 commits July 27, 2026 15:30
Dropping the pid<=64 caller shortcut left init unable to register the endpoints it publishes for each capsule at spawn. It holds only the ambient caps and no RegisterService, so register_endpoint refused every one and no capsule reached the run queue.

register_endpoint now checks only that the owner holds the caps the endpoint advertises, which is all the trusted spawn path needs. MkServiceRegister keeps the register-right gate for a new name and lets a capsule re-assert the endpoint the kernel already published for it, so a runtime squat is still refused.
mk_ipc_reply took the correlation token from a per-client queue kept separately from the pending-reply table it validated the reply against. With several callers waiting on one server the two orders diverged, replies went out under the wrong token, and callers discarded them and blocked forever. The whole desktop stalled at the compositor handshake.

The pending-reply entry, matched by the caller's own inbox, already carries that call's token, so return it from remove() and use it directly. The separate correlation table is gone. A forged mk_ipc_send reply still carries token 0 and no pending entry, so it is still dropped.
A dock button opens a full-screen grid of every desktop app and installed tool, so the dock stays short instead of growing a tile per app. The grid is built from the launcher and tool tables, so adding an app or installing a tool fills a cell with no layout change.

A click launches the service, or focuses the window when it is already open. Tools that ship no artwork get an icon drawn from the name.
grex, dotenv-linter, pastel, jsonxf, choose, tokei, huniq and csview, cross-compiled unmodified for x86_64-nonos against the std PAL, each signed and enrolled under the transparent STARK policy root and spawned after the desktop. userland/apps.list is the single source of truth: tools/nonos-app cross-compiles a crate, mints its publisher keys, writes its Capsule.mk and regenerates both the kernel registry and the Launchpad tool table from it.

The vendored shims under upstream-src carry the target arms these crates need on nonos: getrandom over the CRND syscall, byte-based OsStr, a thread-local errno, advisory fd-lock, HOME-based dirs.
The eight tools shipped a hued letter-tile from the generator; give each a 48x48 glyph mask drawn in the same cyan line-art language as the desktop apps (a regex star for grex, a bar chart for tokei, a table for csview, braces for jsonxf, and so on). A tool with no shipped artwork still falls back to the generated tile.

Also wire the tool_capsules module the generated registry needs: the macro and the spec were present but never declared, so the embedded-tool list did not compile.
A command-line tool has nothing to do until it is invoked, so the eight tools no longer spawn at boot. A new MkToolRun syscall runs one baked, attested tool by name, parented to the caller so the caller feeds its stdin and drains its stdout through the existing MkProcInput and MkProcOutput path. Only the baked set can be named, and the gate is IPC, so an ordinary capsule cannot point it at an arbitrary binary.

The shell recognizes each tool as a bare command (tokei, grex foo, ...) and streams its output through the same async drain job the store installs use. A Launchpad tool tile opens the terminal, where the tool runs by name.
The nonos-app pipeline left grex, dotenv-linter, jsonxf and csview as prebuilt binaries with no rule to rebuild them, so a clean checkout (and CI) could not reproduce them. Vendor the byte-identical crates.io source for the four under upstream-src, like sd and choose, and add one templated rule that cross-compiles every installed tool to target/upstream-<bin>/bin/<bin>.

grex and tokei gate their binary behind a cli feature, so those two re-enable it; the rest strip default features (unix-only pagers, update checks) the same way the shimmed tools already did.
Gate the baked tool set behind a nonos-tool-capsules feature so a core kernel check, which does not cross-compile the tool binaries, no longer tries to include_bytes them; the desktop profile turns it on.

Drop the os_str_bytes shim's dependency on std::os::unix: the byte-based OsStr round-trips losslessly through the stable encoded-bytes API, so the four clap-based tools (huniq, choose, pastel, tokei) build against the plain byte std without the unix module being present.
choose pins clap 2.34, which reaches for OsStr::as_bytes through os::unix::ffi::OsStrExt behind a cfg(unix) that the os=none nonos target does not satisfy, so it cannot cross-compile without a real clap port. The other seven tools use clap 4 (encoded-bytes), clap 3 through the fixed os_str_bytes shim, or getopts, and all build from vendored source hermetically.

Also make tools/nonos-app regenerate the registry with the nonos-tool-capsules feature gate and the run_named entry point, so a future add no longer clobbers them, and add an off-by-default nonos-tool-selftest that spawns each tool at boot (output capture through a waiting parent is a follow-up).
# Conflicts:
#	src/syscall/microkernel/ipc/pending_reply/remove.rs
#	userland/capsule_desktop_shell/src/server/handlers/launcher_request.rs
@eKisNonos eKisNonos changed the title Fix the #405 boot regressions and add the Launchpad Fix the #405 boot regressions, add the Launchpad, and install the crates.io tool suite Jul 27, 2026
The virtio-vga device advertised its resolution through xres/yres but without an EDID, so OVMF kept negotiating an oversized fallback mode after a fresh boot and the desktop came up scaled up. Turning on the device EDID (edid=on) makes the firmware read the advertised mode and settle on the native size every boot.

Add two screenshots of the booted desktop: the Launchpad grid with the installed tools and their line-art icons, and the desktop with the app dock.
@eKisNonos
eKisNonos merged commit 711c33b into main Jul 27, 2026
65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant