Phase 53
Headless Hardening
m3OS becomes a deliberately operable headless/reference system: the security floor is repaired, the service model is trustworthy, the basic developer workflow is boringly repeatable, and the project has explicit validation gates for what it now claims to support.
Learning goal
Understand the difference between "the feature exists" and "the feature is reliable enough to anchor a release claim."
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
Why this phase matters
m3OS becomes a deliberately operable headless/reference system: the security floor is repaired, the service model is trustworthy, the basic developer workflow is boringly repeatable, and the project has explicit validation gates for what it now claims to support.
How it works in m3OS
Phase 53 turns the current QEMU-first system into an explicit headless/reference-system promise. Instead of adding one brand-new subsystem, it converges the already-shipped security floor, service model, storage layout, logging path, build tooling, and validation harness into one supported operator workflow. The point of the phase is to make the release claim narrow, testable, and honest before the roadmap expands into broader hardware, GUI, or large runtime work. Phase 53 is also intentionally not “done” just because the workflow is written down. The workflow, gate bundle, and support boundary are published now, but the phase does not close until those gates pass on an image that includes the Phase 53a allocator changes.
How it builds on earlier phases
This phase builds on Kernel Completion And Roadmap Alignment and turns that foundation into Headless Hardening.
Implementation outline
- Define the supported headless/reference workflow, gate bundle, and support boundary (Track A — this document).
- Turn the gate bundle into repeatable automation and evidence capture (Track B).
- Audit the Rust std and ports flows for the release story and fix the rough edges that block routine use (Track C).
- Harden service/logging/admin workflows into documented normal operations (Track D).
- Update learning docs, subsystem docs, and evaluation docs to align with the new claim (Track E).
- Collect closure evidence after Phase 53a and align version references (Track F).
Task progress snapshot
0 of 78 tracked tasks are complete.
Documentation targets
- Documentation deliverables have not been listed yet.
Deferred follow-on work
- Broad outbound developer networking (HTTPS/TLS clients, DNS resolution, git remotes, GitHub tooling)
- GUI / display compositor / graphical session / local desktop
- Mouse input, audio output
- Large third-party runtime ecosystems (Python, Node.js, JVM)
- Broad hardware certification beyond QEMU x86_64 with OVMF
- Package feeds, remote package repositories, dynamic linking
- Full POSIX compliance testing
Source materials
Important code
Code spotlight cards
Code spotlight
Align smoke coverage with the published headless workflows
Align smoke coverage with the published headless workflows. Why it matters: The smoke test is the broadest end-to-end headless gate. If it does not match the workflows the docs claim to support, the release story is rhetorical instead of evidence-backed. Focus on `smoke_test_script` and `cmd_smoke_test` in `xtask/src/main.rs` while you trace the snippet.
/// Comprehensive smoke test: login, coreutils, TCC, Phase 32 build tools.
///
/// Replaces the Phase 31 smoke test with a more thorough script that validates
/// the full userspace stack including new utilities and the make build tool.
#[allow(unreachable_code)]
fn smoke_test_script(doom_wad_available: bool) -> Vec<SmokeStep> {
let _ = doom_wad_available;
let mut steps = Vec::new();
// -----------------------------------------------------------------------
// 1. Boot and login (handles both first-boot locked accounts and normal login)
// -----------------------------------------------------------------------
// First-boot: account is locked (hash "!"), login prompts to set password.
// Normal boot: account has a password, login prompts for it.
// Both paths use "root" as the password.
const FIRST_BOOT_LOGIN: &[SmokeStep] = &[
SmokeStep::Send {
input: "root\n",
label: "set initial password",
},
SmokeStep::Wait {
pattern: "Retype password:",
timeout_secs: 10,
label: "wait for password confirmation prompt", Code spotlight
Make service state inspection and control part of the normal path
Make service state inspection and control part of the normal path. Why it matters: A headless/reference system needs one documented way to inspect, restart, stop, and reason about services. If the normal path is still ad hoc, the service model is not trustworthy enough for a release claim. Focus on `ServiceManager` and `cmd_list` in `userspace/init/src/main.rs` while you trace the snippet.
struct ServiceManager {
services: [ServiceDef; MAX_SERVICES],
count: usize,
discovered_disabled: [FixedStr<MAX_NAME>; MAX_DISCOVERED_DISABLED],
discovered_disabled_count: usize,
pid_table: PidTable,
shutdown_requested: bool,
login_pid: i32,
/// File descriptor for the syslog socket (`/dev/log`), or -1 if unavailable.
syslog_fd: i32,
} Code spotlight
Make the storage workflow part of the supported headless path
Make the storage workflow part of the supported headless path. Why it matters: Phase 53's release story explicitly includes storage. Operators need a documented way to verify that the writable data path backing packages, logs, and user data is healthy and recoverable. Focus on `main` in `userspace/coreutils-rs/src/mount.rs` while you trace the snippet.
fn main(args: &[&str]) -> i32 {
// No arguments: print /proc/mounts.
if args.len() == 1 {
return show_mounts();
}
// Parse: mount -t TYPE SOURCE TARGET
let mut argi = 1usize;
let mut fstype: Option<&str> = None;
if argi < args.len() && args[argi] == "-t" {
argi += 1;
if argi >= args.len() {
write_str(STDERR_FILENO, "usage: mount -t TYPE SOURCE TARGET\n");
return 1;
}
fstype = Some(args[argi]);
argi += 1;
}
if args.len() - argi != 2 || fstype.is_none() {
write_str(STDERR_FILENO, "usage: mount -t TYPE SOURCE TARGET\n");
return 1;
} Key files
- kernel/Cargo.toml — Keep kernel/Cargo.toml and any roadmap-facing version references aligned at 0.53.0; the version tracks the roadmap phase number and does not by itself mark the phase complete before the post-53a evidence bundle passes.
- docs/roadmap/53-headless-hardening.md — Canonical phase scope, gate bundle, support boundary, and 53/53a closure contract
- xtask/src/main.rs — Implements smoke, regression, stress, and the headless workflow steps those commands drive
- docs/43c-regression-stress-ci.md — Maps automated gates, CI tiers, and artifact locations for the published bundle
- docs/24-persistent-storage.md — Explains the persistent ext2 root and the storage checks used in the operator workflow
- docs/46-system-services.md — Explains the service/logging/shutdown model that Phase 53 treats as normal operations
- docs/45-ports-system.md — Documents the bounded ports baseline and host-cache caveats that remain manual validation
- docs/44-rust-cross-compilation.md — Documents the supported Rust std demos and their host prerequisites
How real OSes differ
- Mature operating systems ship with far richer packaging, telemetry, and operator tooling than m3OS needs here.
- The key lesson to borrow is not feature count but discipline: release claims must map to validated workflows.
- m3OS should choose a narrow, supportable headless story rather than pretending to be a full server distribution.
Success criteria
- The supported headless/reference workflow (§ above) is a single documented normal-operator path covering boot/login, service inspection/control, storage verification, log inspection, package/build basics, failure recovery, and clean shutdown/reboot.
- The gate bundle names exact `cargo xtask` commands and manual checks, not generic references to smoke/regression.
- The docs state where the Phase 48 security floor is exercised in the normal boot/admin path (steps 1 and 7).
- SSH is the documented default remote-admin path; telnet is documented as a non-default testing posture only.
- Broad outbound developer tooling (HTTPS clients, git, DNS) is explicitly deferred as a non-goal.
- GUI/local-session features, broad hardware certification, and large runtime ecosystems are explicitly out of scope.
- The support boundary is narrow enough to feed Phase 58 without reopening Phase 53 scope.
- The Phase 53 / Phase 53a closure contract states which decisions are defined now versus satisfied only after the published gates pass on the allocator-sensitive baseline.
- The post-53a closure bundle names the exact final-close commands and manual checks, records where regression/stress evidence lives, and states that smoke output remains stdout-only until the harness writes a dedicated artifact.
- Nightly `cargo xtask stress --test ssh-overlap --iterations 50 --timeout 90` is explicitly classified as sustaining evidence rather than a per-PR or final-close rerun.
- No documentation implies that Phase 53 is already complete before the gate bundle passes on the post-53a image.
Related phases
Keep exploring the roadmap
Phase 52
CompleteKernel Completion And Roadmap Alignment
The Phase 52 follow-on work now matches reality: the roadmap truthfully describes what landed, syscall return state is task-owned end-to-end, keyboard input uses the kernel line discipline instead of a ring-3 clone, the integrated boot/login path survives the former `rt_sigaction` stall, generated initrd payloads no longer dirty the source tree, and the smoke/regression gates for login, fork, ion, and PTY flows are trustworthy again.
Phase 53
CompleteKernel Memory Modernization
The kernel memory subsystem becomes SMP-scalable and auditable: per-CPU page caching removes the global frame-allocator lock from the common single-page path, a magazine-based slab allocator with out-of-line slab metadata replaces the linked-list heap for small kernel objects, and the allocator preserves Phase 52b's zero-before-user-exposure guarantee while eliminating the double-lock and O(n) buddy removal paths.