Build, Boot, and Test
The commands below are the current local workflow for the x86_64 QEMU target.
The root Cargo configuration defaults to x86_64-unknown-none, so host tests
must use the repo aliases instead of bare cargo test.
Prerequisites
Expected host tools:
- Rust nightly from
rust-toolchain.toml makeqemu-system-x86_64xorrisocurl,sha256sum, and standard build tools for pinned tool downloads- Go, used by the Makefile to install the pinned CUE compiler when needed
- A Telnet client for the optional focused loopback shell demo
- Chromium, Chromium Browser, or Google Chrome for the optional remote-session CapSet browser UI automation
- Optional policy and proof tools for extended checks:
cargo-deny,cargo-audit,cargo-fuzz,cargo-miri, andcargo-kani
The Makefile pins and verifies:
- Limine at the commit recorded in
Makefile - Cap’n Proto compiler version
1.2.0 - CUE version
0.16.0
Pinned repo-selected tools are installed under CAPOS_TOOLS_ROOT, which
defaults to the per-user $HOME/.capos-tools cache. Override
CAPOS_TOOLS_ROOT=/path/to/cache when a host needs a different cache
location.
Build the ISO
Use the default target when you need the current bootable capOS image.
make
This builds:
- the kernel with the default bare-metal target;
- the standalone
inituserspace binary used by focused spawn proofs; - release-built demo service binaries under
demos/; - the
capos-rtuserspace binaries, including the shell proof; manifest.binfromsystem.cue;capos.isowith Limine boot files.
Relevant files: Makefile, limine.conf, system.cue, tools/mkmanifest/.
Compare Build Provenance
Use make build-provenance to write the local build record at
target/build-provenance.txt. To compare two retained records locally:
make build-provenance-compare \
BASE_PROVENANCE=path/to/base-build-provenance.txt \
CANDIDATE_PROVENANCE=path/to/candidate-build-provenance.txt
The comparison ignores the generated timestamp and allowed local path-root
movement under worktree target/ directories or .capos-tools/ caches. It
fails for material provenance drift, including source commit changes, manifest
or artifact hash changes, embedded binary hash changes, OVMF identity/hash
changes, Rust compiler date/commit changes, host-tool version or package
identity changes, and operating-system identity changes.
For PR base-vs-head CI comparison, use the environment policy:
make build-provenance-compare \
BUILD_PROVENANCE_COMPARE_POLICY=ci-environment \
BASE_PROVENANCE=path/to/base-build-provenance.txt \
CANDIDATE_PROVENANCE=path/to/candidate-build-provenance.txt
That mode allows expected source and artifact hash changes while still failing for runner, GitHub-hosted image, Rust, selected-tool, package-identity, OVMF selection, and OVMF hash drift. It is a PR environment gate, not a production reproducibility claim.
Local synthetic comparison checks may create scratch records under
target/provenance-fixtures/ or Python bytecode caches under tools/. Clean
those scratch artifacts with:
make build-provenance-compare-clean
Boot QEMU
Use the default run targets to boot either the operator-facing system or the scripted login-path smoke.
make run
make run-smoke
make run is the operator-facing boot path. It builds the ISO with the qemu
feature, boots QEMU with the interactive terminal UART on stdio, attaches
virtio-net with host-local remote CapSet forwarding, and writes the separate
kernel/debug UART log to target/qemu-console.log. The run output prints the
actual forwarded port as remote CapSet: tcp 127.0.0.1 <port> -> guest :2327.
The plaintext loopback Telnet research demo was a Phase B fixture, not part of
the default operator path. make run-telnet and make run-telnet-vm are now
retired because they depended on the removed qemu-only kernel TCP listener. Use
the SSH gateway smokes for current remote-shell coverage and rebuild any
socket-backed terminal proof on the Phase C userspace network stack before using
it as validation.
The same make run boot starts the remote-session CapSet gateway. To run the
host CLI against it, use the printed port:
cargo run --manifest-path tools/remote-session-client/Cargo.toml \
--target x86_64-unknown-linux-gnu \
--bin remote-session-client -- --host 127.0.0.1 --port <port>
Add --launch-adventure to that command when you want the CLI to start the
default-manifest Adventure service graph through serviceLaunch and require a
running status.
To run the trusted local web bridge against the same QEMU instance:
CAPOS_REMOTE_SESSION_PORT=<port> make remote-session-ui
Then open http://127.0.0.1:3337/. The Rust bridge holds the TCP stream,
remote session state, and backend-held remote CapSet; the browser receives
only view models, launch/status descriptors, denial diagnostics, call results,
and redacted transcript rows. The former automated focused proof,
make run-remote-session-capset-ui, is retired because it depended on the
removed qemu-only kernel TCP listener. The replacement browser proof belongs to
the future Phase C Web UI L4 gate.
A Tauri desktop wrapper is available as a repo-local check/dev layer over the
same Rust backend. The repo-local make remote-session-tauri target first
runs a policy preflight over the reviewed scaffold, then checks for the Tauri
CLI and Linux build prerequisites, reports dependency and scaffold status, and
runs a deterministic wrapper check when those prerequisites are present. It
follows the official Tauri v2 Linux prerequisite shape, including WebKitGTK
4.1, libxdo, OpenSSL, AppIndicator, and Rsvg development packages where
applicable. Missing dependencies fail with explicit diagnostics and point back
to the supported local web bridge. The operator command shape is:
CAPOS_REMOTE_SESSION_PORT=<port> make remote-session-tauri
Set CAPOS_REMOTE_SESSION_TAURI_MODE=dev to launch cargo tauri dev.
CAPOS_REMOTE_SESSION_TAURI_MODE=policy tools/remote-session-tauri.sh runs
only the scaffold guardrail and does not require Tauri system packages or a
desktop session. CAPOS_REMOTE_SESSION_TAURI_MODE=package and
CAPOS_REMOTE_SESSION_TAURI_MODE=automation are intentionally blocked with
diagnostics describing the remaining packaging and desktop-automation review
work. This policy preflight proves only that the current wrapper remains a
check/dev scaffold with packaging disabled, the loopback URL pinned, a single
main window, default core:default permission scope, and no app-specific
Tauri command/plugin authority. It is not a distributable packaging or desktop
automation proof. make remote-session-ui remains the supported fallback host
UI path and uses the same backend-held authority boundary.
Default make run starts chat, the remote-session gateway, and shell
services. It embeds Adventure server/NPC/client binaries and the terminal
Paperclips binary. The current remote-session Adventure slice makes
serviceLaunch a real restricted backend launch in that default manifest:
the trusted backend/gateway starts adventure-server plus simple NPC
companions through an approved service-runner profile and attaches or retains
backend-held descriptors/caps for the Adventure/chat-facing services. Run it
by starting make run, noting the printed remote CapSet forwarding port, and
then using either the host CLI or
CAPOS_REMOTE_SESSION_PORT=<printed-port> make remote-session-ui.
make run-paperclips remains the focused authoritative Paperclips server
proof; default-manifest Paperclips launch is not implemented by this slice.
Raw ProcessSpawner, process owner handles, endpoint owner caps, local cap
ids, result-cap slots, and browser-held capOS caps are non-goals for this UI
path. Process handles stay backend-local.
GCE Web UI Proof Target Map
Use the selected-milestone proof targets below to choose the narrowest evidence gate for the GCE self-hosted Web UI ladder. Local QEMU/cloudboot targets do not prove live provider reachability, and private GCE targets do not authorize public ingress or TLS exposure.
| Proof class | Target or command shape | Proves | Closest non-goal |
|---|---|---|---|
| Landed local Phase C L4 substrate | make run-cloud-prod-userspace-network-stack-smoltcp | A non-qemu cloudboot kernel under QEMU starts the userspace smoltcp network-stack process and completes one hostfwd TCP request/response through a userspace-served TcpListenAuthority. See cloud-prod-userspace-network-stack-smoltcp-local-proof. | Does not prove DHCP/IPv4 configuration, remote-session-web-ui, live GCE reachability, or public ingress. |
| Landed local IPv4 configuration | make run-cloud-prod-network-stack-dhcp-ipv4-config | The userspace network-stack process acquires the QEMU SLIRP DHCPv4 lease, serves NetworkManager.getConfig, installs the default route, and resolves gateway plus same-subnet ARP neighbors. See cloud-prod-network-stack-dhcp-ipv4-config-local-proof. | Does not prove a Web UI listener bound through that route, live GCE reachability, DNS, TLS, or public exposure. |
| Retired legacy local self-served Web UI | make run-remote-session-self-served-web-ui | Pre-Phase-C proof that served the immutable full UI bundle from a focused QEMU manifest through the kernel tcp_listen_authority socket owner. The target is not current production L4 evidence after cloud-prod-phase-c-kernel-smoltcp-virtio-net-removal retires that kernel owner. | Does not prove the non-qemu cloudboot Phase C L4 path, and should not be used as a passing selected-milestone gate until rebuilt on the userspace network-stack substrate. |
| Landed cloudboot Web UI authority inventory | No run target; docs-status contract | The Gate 1B inventory records the required and forbidden remote-session-web-ui grants, trusted listener/source metadata, browser-visible forbidden markers, and expected local L4 proof markers. See remote-session-webui-cloudboot-authority-inventory. | Does not prove runtime listening, browser automation, GCE reachability, or public operator access. |
| Landed local cloudboot Web UI L4 proof | make run-cloud-prod-remote-session-web-ui-l4 owned by cloud-prod-remote-session-web-ui-l4-local-proof | Proves remote-session-web-ui listens on guest port 8080 through the Phase C L4 path on the non-qemu cloudboot kernel under QEMU: the userspace network-stack process serves the scoped TcpListenAuthority, the Web UI serves the full fixed-name bundle, login, one backend-held capability call, logout, stale-call failure, the manual viewer, and a cloudboot-evidence: remote-session-web-ui-l4 marker. | Local cloudboot/QEMU evidence only; it does not prove live GCE NIC reachability, private provider probing, public ingress, TLS, or production release authority. |
| On-hold private GCE Web UI proof | Future tools/cloudboot/run-test.sh --require-web-ui-proof gate owned by cloud-gce-private-self-hosted-webui-proof | Must launch the self-hosted Web UI cloudboot image in the no-public-IP GCE posture, use a reviewed private probe that crosses the live GCE virtual network boundary, record the private endpoint and Web UI/L4 markers, and tear down all created resources. | On hold (2026-06-09): the cloudtest credential lacks the firewall IAM a private same-VPC probe needs against GCE default-deny ingress, and the live legacy virtio 0.9 GCE NIC has no reviewed userspace-stack serving story. It will not create public IPs, public firewall rules, DNS, TLS certificates, or browser-facing public operator ingress. |
| On-hold public ingress/TLS proof | Future tools/cloudboot/run-test.sh --require-public-web-ui-proof gate owned by cloud-gce-public-self-hosted-webui-ingress-tls | After explicit authorization, must prove the selected GCE external HTTPS load-balancer ingress posture, Google-managed certificate termination, browser-session hardening, and teardown evidence. | On hold. No local target, private proof, or selected milestone status grants public exposure, broad firewall changes, certificate issuance, TLS key custody, or release authority. |
make run-smoke preserves the focused legacy shell-led system-smoke.cue
verification path. It drives the login and shell session through the terminal
UART, captures the kernel log and terminal transcript separately, and checks
that the kernel boot-launched only the first init service (capos-shell),
granted only the shell bootstrap cap bundle, and then reached the expected
audit, shell-bundle, child-isolation, stale-handle, and no-password-echo
assertions before QEMU exits. This is distinct from the default system.cue
path, where the kernel boot-launches standalone init and init starts
operator-facing services.
Spawn Smoke
Use the spawn smoke when changes affect manifest-owned process creation, ProcessSpawner behavior, or bootstrap capability wiring.
make run-spawn
This boots with system-spawn.cue, the focused init-owned manifest retained
for ProcessSpawner checks. Only init is boot-launched by the kernel; init
uses ProcessSpawner to launch endpoint, IPC, VirtualMemory, Timer,
ThreadControl, the single-thread runtime checkpoint, FrameAllocator cleanup,
and hostile spawn demo children, wait for ProcessHandles, and exercise hostile
spawn inputs. The target captures the kernel log separately and runs
tools/qemu-spawn-smoke.sh to assert the single-init boot markers,
BootPackage validation, child spawn/exit records, Timer now/sleep and
per-process sleep quota proof lines, runtime FS-base proof lines, the
single-thread runtime map/protect/unmap plus park-fallback checkpoint,
manifest child waits, and clean halt.
Shell and Terminal Smokes
Use these focused QEMU smokes for shell, terminal, credential, and login paths.
make run-shell
make run-terminal
make run-credential
make run-login
make run-login-setup
make run-shellboots the focusedsystem-shell.cuemanifest (no pre-provisioned verifier) and exercises the shell entirely in its anonymous session: CapSet listing, typed capability inspection, typed application-error display, anonymous-session metadata, the anonymous launcher rejectingspawn-testbecause its allowlist is empty, and clean exit.make run-terminalboots the focusedsystem-terminal.cuemanifest and exercises theTerminalSessionsubstrate: visible and hidden echo input, boundedreadLine, structured cancellation, and stale-input scrubbing between prompts.make run-credentialboots the focused CredentialStore proof manifest.make run-loginboots the focused password-login manifest and proves the shell’slogincommand prompting forusername>before hiddenpassword>, failing generically on a wrong password, succeeding for the demo account, swapping from the anonymous bundle to the operator bundle, and performing exact-grant child launch plus stale-handle release.make run-login-setupboots the no-password first-boot setup manifest and proves thatsetupcreates a volatile credential, discloses that volatility, chains into the login upgrade path, and reaches the same narrow operator shell bundle.
Durable account storage and multi-verifier local accounts are still future
work; the current username-aware login path selects the manifest-seeded
operator-kind account and any volatile first-boot credential record that
setup creates.
Focused Service Smokes
Use these targets to prove resident services and demo clients still launch through the intended shell-granted authorities.
make run-chat
make run-adventure
make run-paperclips
make run-revocable-read
make run-memoryobject-shared
make run-ringtap-failing-call
make run-chatboots the focused First Chat manifest and proves a shell-spawned client can send a line through the resident singleton chat service using the broker-issued operatorchatendpoint and observe the resident bot reply.make run-adventureboots the focused adventure manifest and proves the shell-spawned client can drive the current scripted mission through explicitStdIO,adventure, andchatendpoint grants.make run-paperclipsboots the focused Paperclips terminal demo manifest, authenticates the shell, starts Paperclips server services, first launches the clean-room terminal client with explicitStdIOplus the normalPaperclipsGameendpoint, proves normal server authority cannot invokerun <ms>, rejects a forgedproof_accelerator: @timergrant, then relaunches against the proof server endpoint with the explicitproof_acceleratorproof authority for the accelerated transcript. The server owns generated content, game state, regular timer cadence, unlock checks, and game-rule mutation, and server-mode client help is rendered from structured server command specs. That transcript rejects an early locked autoclipper purchase, rejects an over-budget wire purchase, rejects bulk manual production, rejects a high-price sale with zero current demand, rejects manual production after automation drains wire, drives one-at-a-time manual production, explicit sales, repeatable marketing, autoclipper unlock, real-time automation, generated typed Cap’n Proto content loading, scaled business-phase production,precision-rollers,design-search,forecast-engine, thesurvey-dronestransition to== autonomous phase ==, representative autonomous drone/factory scaling with local-matter conversion and additional clip production, themesh-coordinationandseed-probescosmic transition, bounded probe replication and production, lockedfinal-conversion, and clean client/shell exit.make run-revocable-readexercises the revocation transcript for endpoint and boot-package authority loss.make run-memoryobject-sharedproves MemoryObject-backed parent/child sharing and cleanup.make run-ringtap-failing-callenablesdebug_tap, drives a known typed launcher failure, and runs the ringtap viewer over the captured log.
Networking and Measurement Targets
Use these targets for the current network proof path and benchmark-only measurement image.
make run-net
make qemu-net-harness
make run-measure
make run-netattaches a QEMU virtio-net PCI device and exercises current PCI enumeration, virtio transport setup, and TX descriptor completion diagnostics, plus ARP resolution and ICMP echo validation against the QEMU user-mode gateway.make qemu-net-harnessruns the scripted net smoke path.make run-measureenables the separatemeasurefeature for benchmark-only counters and cycle measurements. It bootssystem-measure.cue, where init spawnsring-nopand grants the measurement-only NullCap and ParkBench caps through ProcessSpawner. The demo prints ring/NullCap baselines plus a park-shaped comparison between compact authority-checked SQEs and generic Cap’n Proto methods. The kernel summary includes per-segment dispatch counts, total cycles, and averages for SQE processing, validation, cap lookup, capnp decode, method body dispatch, CQE posting, and waiter wake/check. Do not treat it as the normal dispatch build.
Formatting and Generated Code
Use these local checks before claiming source formatting or generated artifacts are current.
make fmt
make fmt-check
make generated-code-check
make fmtformats the kernel workspace plus standaloneinit,demos, andcapos-rtcrates.make fmt-checkverifies formatting without modifying files.make generated-code-checkverifies checked-in Cap’n Proto generated code against the repo-pinned compiler path and checks generated adventure plus Paperclips content against their CUE sources.
Host Tests
Use these host-side checks for shared logic and userspace build surfaces that do not require a QEMU boot.
cargo test-config
cargo test-ring-loom
cargo test-lib
cargo test-mkmanifest
tools/check-userspace-runtime-surface.sh
make capos-rt-check
make init-capos-build
make demos-capos-build
make shell-capos-build
make capos-rt-capos-build
cargo test-configruns shared config, manifest, ring, and CapSet tests on the host target.cargo test-ring-loomruns the bounded Loom model for SQ/CQ protocol invariants.cargo test-libruns host tests for pure shared logic such as ELF parsing, capability tables, frame allocation, and related property tests.cargo test-mkmanifestruns host tests for manifest generation.tools/check-userspace-runtime-surface.shverifiescapos-rtowns the userspace entry, panic, allocator, and raw syscall surface.make capos-rt-checkbuilds the standalone runtime smoke binary againsttargets/x86_64-unknown-capos.json, matching the userspace target used by the boot image.make init-capos-build,make demos-capos-build,make shell-capos-build, andmake capos-rt-capos-buildexpose focused custom-target build wrappers for the booted userspace crates and runtime smoke binary.
Extended Verification
Use the extended verification set for shared logic, dependency policy, fuzz targets, and bounded proof gates that are heavier than the normal host-test loop.
make dependency-policy-check
make fuzz-build
make fuzz-smoke
make kani-lib
cargo miri-lib
These require optional tools. Use them when changing dependency policy,
manifest parsing, ELF parsing, capability-table/frame logic, or proof-covered
shared code. make dependency-policy-check covers Rust deny/audit checks and
the docs Node lockfile/audit gate with npm lifecycle scripts disabled. See the
Security and Verification Proposal
for the rationale behind the extended verification tiers. make kani-lib
runs the bounded mandatory cap-table/frame gate.
Validation Rule
For behavior changes, a clean build is not enough. The relevant QEMU process
must exercise the behavior and print observable output that proves the path
works. make run-smoke is the default login-path gate; make run-spawn,
make run-shell, make run-terminal, make run-credential,
make run-login, make run-login-setup, make run-chat,
make run-adventure, make run-paperclips, make run-revocable-read,
make run-memoryobject-shared, make run-net, make qemu-net-harness,
make run-ringtap-failing-call, or make run-measure are additional gates
for their specific features.