From d236f71bd3227a7db9f001a39dc7c2577a6857ae Mon Sep 17 00:00:00 2001 From: japabu Date: Sat, 26 Sep 2026 17:12:45 +0200 Subject: [PATCH 1/7] The layout as ruled, and its first stage: /home/toy, /config, /state, HOME from init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The owner ruled where everything lives on 2026-09-26, and issues/filesystem/where-everything-lives.md records it: the tree, the rules (no dotfiles, English names, a path is one file in every view with /tmp the one exception, locations through environment variables init sets), and the stages with their exits. The storage track's `## Paths` and the users track now point at it instead of carrying their own `.config/` layout. The first stage, the part that needs no isolation: - `/config` and `/state` are two more names DATA answers to (`ROOT_ENTRIES`, `DATA_PATHS`). - The kernel makes no home. init makes `/home/toy` and Apps, Desktop, Documents, Downloads, Fonts, Music, Pictures and Videos at boot, and a service's `/state/` before each start. - A `system.toml` row says `service = true` for a system service, the manifest carries it as a `service` record, and `Program::home` answers `/state/` for one and `/home/toy` for every other row. init sets `HOME` from it on every start, over whatever a launching caller carried. - std's `home_dir` answers `$HOME`, or `None` when it is unset or empty. The runtime used to overwrite `HOME` with `/home/root` and set `XDG_CONFIG_HOME` at every process start, so nothing a parent passed could survive; that seeding is gone (fork commits on wt-toyos-layout). - The keyboard layout is `/config/keyboard-layout`, a machine setting in no user's home (`surface::LAYOUT_CONFIG`; toyos 0.14.0 and toyos-window 0.15.0, every pin and lockfile with them). - sshd keeps its identity and key list in its own `HOME`, `/state/sshd`. - The shell keeps its history in `$HOME/Apps/shell/State/history` and invents no `HOME`; the files app starts in `home_dir()`. - JetBrains Mono ships as a TTF in `/system/share/fonts`, where the toolkits look, with its OFL text in `/system/share/licenses`; NOTICE says so. - The 26 SDK doc lines naming `/bin` name `/system/bin`, and the Rights::LOG doc gate strips that prefix: the issue that tracked them is closed. `/log/lease.txt` does not move. It is not netd's lease but the `--exit-with-lease` bench report the metal loop reads off the stick's FAT log volume, which cannot read DATA; the track says so. Found on the way and filed: a directory on DATA is the VFS's in-memory record, absent from every listing of its parent and from the next boot, and it is taken with no parent — which is why init makes each level in turn. `layout_fresh_boot` boots tests/sshdcase on a blank DATA volume and asks a session program's child where everything is. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_014iqcj4jDKpaiDX8B7CMvmK --- NOTICE | 10 +- console/system.toml | 1 + diag/system.toml | 1 + ...-home-no-earlier-boot-of-its-lane-wrote.md | 4 +- ...-sdk-doc-lines-name-a-path-that-is-gone.md | 43 -------- ...-on-data-is-in-no-listing-and-no-reboot.md | 41 +++++++ .../a-user-is-a-home-tree-and-a-login-row.md | 8 +- ...l-c-discards-the-cwd-its-launch-carried.md | 2 +- ...ge-is-layers-and-a-role-is-a-filesystem.md | 32 ++---- issues/filesystem/where-everything-lives.md | 100 ++++++++++++++++++ .../sshd-authorized-keys-unprotected.md | 4 +- kernel/src/main.rs | 29 ++--- kernel/src/vfs.rs | 3 +- rust | 2 +- src/assets.rs | 59 ++++++++++- src/build.rs | 11 +- system.toml | 9 ++ tests/common/pkg.rs | 2 +- tests/common/storage.rs | 8 +- tests/desktopaudiocase/system.toml | 3 + tests/desktopcase/system.toml | 2 + tests/doomcase/system.toml | 2 + tests/doommusiccase/system.toml | 2 + tests/e1000case/system.toml | 2 + tests/e1000leasecase/system.toml | 2 + tests/e1000talkcase/system.toml | 3 + tests/flrswapcase/system.toml | 3 + tests/inspectcase/system.toml | 4 + tests/jobcase/system.toml | 1 + tests/jobdeadlinecase/system.toml | 1 + tests/lancase/system.toml | 2 + tests/lanicscase/system.toml | 2 + tests/lanleasecase/system.toml | 2 + tests/lantalkcase/system.toml | 3 + tests/latencycase/system.toml | 1 + tests/logholdcase/system.toml | 1 + tests/logrotatecase/system.toml | 5 + tests/logstallcase/system.toml | 2 + tests/logstreamcase/system.toml | 2 + tests/logstreame1000case/system.toml | 2 + tests/metalcase/system.toml | 5 + tests/metaldevicecase/system.toml | 2 + tests/netcase/system.toml | 2 + tests/partclaimcase/system.toml | 2 + tests/pkgcase/system.toml | 3 + tests/quiescecase/system.toml | 1 + tests/quiescelastcase/system.toml | 1 + tests/quiescetwicecase/system.toml | 1 + tests/sshdcase/system.toml | 3 + tests/swapcase/system.toml | 3 + tests/testcases/system.toml | 2 + tests/toyos-rust-tests/Cargo.lock | 8 +- .../src/bin/hierarchy_paths.rs | 5 +- tests/toyos-rust-tests/src/bin/home_absent.rs | 35 +++--- .../toyos-rust-tests/src/bin/layout_paths.rs | 86 +++++++++++++++ .../src/bin/pkg_launch_gbae.rs | 4 +- tests/toyos.rs | 54 ++++++++-- toyos-abi/src/handle.rs | 8 +- toyos-abi/src/lib.rs | 2 +- toyos-abi/src/part.rs | 2 +- toyos-abi/src/syscall.rs | 10 +- toyos-manifest/src/lib.rs | 41 +++++++ toyos-manifest/src/package.rs | 10 +- toyos/Cargo.lock | 2 +- toyos/Cargo.toml | 2 +- toyos/src/device.rs | 2 +- toyos/src/launch.rs | 8 +- toyos/src/lib.rs | 2 +- toyos/src/log.rs | 2 +- toyos/src/namespace.rs | 2 +- toyos/src/net.rs | 4 +- toyos/src/surface.rs | 9 +- toyos/src/syscap.rs | 6 +- userland/Cargo.lock | 52 ++++----- userland/files/src/main.rs | 2 +- userland/init/src/main.rs | 45 ++++++++ userland/libc/Cargo.lock | 2 +- userland/shell/src/main.rs | 25 +++-- userland/sshd/src/main.rs | 49 +++++---- userland/toyos-window/Cargo.toml | 4 +- userland/toyos-window/src/lib.rs | 2 +- 81 files changed, 689 insertions(+), 237 deletions(-) delete mode 100644 issues/build/twenty-seven-sdk-doc-lines-name-a-path-that-is-gone.md create mode 100644 issues/filesystem/a-directory-on-data-is-in-no-listing-and-no-reboot.md create mode 100644 issues/filesystem/where-everything-lives.md create mode 100644 tests/toyos-rust-tests/src/bin/layout_paths.rs diff --git a/NOTICE b/NOTICE index b97394572a8..7619294b8b1 100644 --- a/NOTICE +++ b/NOTICE @@ -157,8 +157,14 @@ Two derived artifacts come from it, and whether a 1-bit rasterization is still - `share/fonts/JetBrainsMono-Regular-8x16.font` on every ROOT that ships `assets/`, rasterized at build time by `src/assets.rs`. -The OFL's reserved-name clause is not engaged: neither artifact is distributed -as a font under the JetBrains Mono name. +The OFL's reserved-name clause is not engaged: neither derived artifact is +distributed as a font under the JetBrains Mono name. + +The font itself ships unmodified as `share/fonts/jetbrainsmono-regular.ttf` on +every ROOT that ships `assets/`, the system's monospace family where fontdb and +fontique look, with its licence text beside it as +`share/licenses/OFL-1.1-JetBrainsMono.txt`: the OFL permits bundling and +redistributing it with any software, provided that text travels with it. assets/icons/*.svg — Phosphor Icons, MIT diff --git a/console/system.toml b/console/system.toml index e4a9393a78f..64a7407a57f 100644 --- a/console/system.toml +++ b/console/system.toml @@ -27,6 +27,7 @@ start = ["logd", "console"] # reads the kernel's records with `logread`, which is `Rights::LOG | # Rights::WAIT` on a `SysCap` duplicate, and serves `log` to the console. [programs.logd] +service = true syscap = ["logread"] serves = ["log"] diff --git a/diag/system.toml b/diag/system.toml index 47b87060ebe..7892237af94 100644 --- a/diag/system.toml +++ b/diag/system.toml @@ -36,6 +36,7 @@ start = ["logd", "toybox"] # `Rights::LOG | Rights::WAIT` on a `SysCap` duplicate, and init hands it every # program's output beside that. [programs.logd] +service = true syscap = ["logread"] [programs.toybox] diff --git a/issues/build/sshd-fail-closed-assumes-a-home-no-earlier-boot-of-its-lane-wrote.md b/issues/build/sshd-fail-closed-assumes-a-home-no-earlier-boot-of-its-lane-wrote.md index 890e24edf3e..3edec411602 100644 --- a/issues/build/sshd-fail-closed-assumes-a-home-no-earlier-boot-of-its-lane-wrote.md +++ b/issues/build/sshd-fail-closed-assumes-a-home-no-earlier-boot-of-its-lane-wrote.md @@ -4,10 +4,10 @@ kind: tooling opened: 2026-09-24 --- -# `sshd_fail_closed` assumes a `/home` no earlier boot of its lane wrote +# `sshd_fail_closed` assumes a `/state/sshd` no earlier boot of its lane wrote `sshd_fail_closed` owes `sshd: minted a new host identity at -/home/root/.ssh/host_ed25519`, and boots `tests/sshdcase` on the lane's shared +/state/sshd/host_ed25519`, and boots `tests/sshdcase` on the lane's shared scratch disk (`tests/common/qemu.rs`: "Reused across the boots of one lane"). Any earlier boot of the same lane whose sshd ran leaves its identity on that disk, and this boot then reads it and mints nothing. diff --git a/issues/build/twenty-seven-sdk-doc-lines-name-a-path-that-is-gone.md b/issues/build/twenty-seven-sdk-doc-lines-name-a-path-that-is-gone.md deleted file mode 100644 index 0d2df595059..00000000000 --- a/issues/build/twenty-seven-sdk-doc-lines-name-a-path-that-is-gone.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -status: open -kind: tooling -opened: 2026-09-04 ---- - -# Twenty-seven SDK doc lines name `/bin`, which no longer exists - -## Reproduction - -``` -rg -n --pcre2 '(?`, a directory on DATA holding Documents, -Downloads, `.config/` and `.local/`; and a row in the manifest from +A user is two things: `/home/`, a directory on DATA laid out as +`issues/filesystem/where-everything-lives.md` rules; and a row in the manifest from which init builds a login session's namespace, the way it builds every system program's from `system.toml`. Nothing else names a user: no numeric id the kernel checks, no password file, no ambient "current user" a process can ask for. A session holds its home tree because init moved that directory's handle into it, and a program launched inside the session holds what the session's -launcher row grants it. Until this lands there is one implicit user and a -package writes under `/apps//` only. +launcher row grants it. Until this lands there is one user, `toy`, whose home +init makes at boot. Stage 3 of `issues/isolation/every-program-sees-only-the-files-it-was-given.md`, and blocked on its first two stages: a user is isolated only once a session's view is all it can name. The mount protocol and real bcachefs diff --git a/issues/filesystem/shell-c-discards-the-cwd-its-launch-carried.md b/issues/filesystem/shell-c-discards-the-cwd-its-launch-carried.md index 2664f9f715b..42ce55239fb 100644 --- a/issues/filesystem/shell-c-discards-the-cwd-its-launch-carried.md +++ b/issues/filesystem/shell-c-discards-the-cwd-its-launch-carried.md @@ -24,7 +24,7 @@ down, where `set_current_dir(&home)` is at least a stated policy. ## Reproduction -Spawn `/system/bin/shell` with `Command::current_dir("/home/root")` and the +Spawn `/system/bin/shell` with `Command::current_dir("/home/toy")` and the arguments `-c`, `pwd`. It answers `/`. Read from the source rather than measured: `pkg_install_gbae`'s diff --git a/issues/filesystem/storage-is-layers-and-a-role-is-a-filesystem.md b/issues/filesystem/storage-is-layers-and-a-role-is-a-filesystem.md index d7bbac20df5..073bee18eac 100644 --- a/issues/filesystem/storage-is-layers-and-a-role-is-a-filesystem.md +++ b/issues/filesystem/storage-is-layers-and-a-role-is-a-filesystem.md @@ -41,7 +41,7 @@ volume, handed to whichever driver recognises its superblock. |---|---|---|---| | ESP | FAT32, firmware's rule | `/boot` | kernel only | | ROOT | bcachefs image the build writes | `/system` | no; versioned per release | -| DATA | bcachefs, formatted on first boot | `/apps`, `/home` | yes | +| DATA | bcachefs, formatted on first boot | `/apps`, `/config`, `/home`, `/state` | yes | | LOG | FAT32 while a Mac has to read the dev stick | `/log` | yes | `/tmp` has no backing. The dev loop keeps the ESP and ROOT on the stick and @@ -66,8 +66,8 @@ kernel's `root=` argument, mounted read-only through `ReadOnlyBcacheFsAdapter` **Every other filesystem is a userland server** behind the VFS's existing trait (`kernel/src/vfs.rs`, `FileSystem`, one access mode per mount) through a mount protocol: init's manifest row moves the DATA members' device handles -into the storage server, which links the whole crate and mounts `/home` and -`/apps` read-write. A server that crashes loses its mounts and nothing else, +into the storage server, which links the whole crate and mounts DATA's four +names read-write. A server that crashes loses its mounts and nothing else, and no foreign parser runs in the kernel on bytes another OS wrote. This is `issues/kernel/every-driver-is-still-in-the-kernel.md` applied to storage; FAT32 moves out first, being a pure crate already whose two volumes are the cheapest @@ -96,25 +96,13 @@ shape if wanted. ## Paths -No drive letters, no `/usr`, `/var`, `/opt`, `/dev`, `/proc` or `/sys`: -devices and processes are capabilities and syscalls here, not files. Each -process sees the part of this hierarchy its parent gave it -(`issues/isolation/every-program-sees-only-the-files-it-was-given.md`); today paths are still ambient and `/boot`'s mount guard is the one -restriction. - -- `/boot` — bootloader, kernel, kernel arguments. -- `/system` — the OS image, read-only, versioned: today's `bin`, `lib`, `share` - and the manifest. -- `/apps/` — each installed program in its own directory with its own - binaries, data and manifest row; doom moves here with its WAD. -- `/home/` — Documents, Downloads, `.config/` for settings, - `.local/` for saves and caches. -- `/log`, `/tmp` — as today. -- `/media/