Repository navigation
Only the installer's view writes /apps - #1203
Conversation
Every declared row saw /apps read-write, so a shell and everything it spawned could rewrite an installed package. A row's view now holds /apps read-only unless the row declares `installs = true`, which in the image is pkg's alone (owner ruling, 2026-11-05: only the installer service writes /apps). pkg is that service, not a client of one. A launch already gives a row its own view, and who may launch pkg is the `starts` that list it, so the whole authority is in images/system.toml and nothing new runs: no port, protocol or daemon. `launch pkg install <file>` installs; a pkg spawned as a helper holds its parent's view, lists, and refuses install and remove by name. app_view's job writes its packages under /apps itself, so test-runner's row is that image's installer, and the job gains the exit's first arm: a shell's redirect into /tmp writes and into a package is refused. hosted_clang_hello launches pkg. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Review r1 of #1203 at 83f1abbRead: both commits, the full diff against ArchitectureThe change is the right size. One boolean on the row, one arm in Authority: who can still write
|
… say which control reds what app_view's positive arm redirects into /home, the same volume and server as /apps, and its refusal must carry the read-only reason. The record names which control reds which test and states the exit's check. The manual says the installer's view. Storage rows starting with the supervisor's namespace are recorded as their own defect. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Review r2 of #1203 at e78085eScope: the one commit since r1 (83f1abb..e78085e), against r1's findings and the orchestrator's four decisions. Read: that diff whole, ArchitectureUnchanged from r1. This round adds no production code: one doc line in r1's findings
Does the shell arm fail for the wrong reason? (by reading)Yes. The refusal arm passes only on a read-only grant.
The constant is a copy of std's wording, so a reworded message reds this row on the bench. That is the right direction to fail and the comment says where the text comes from. The new defect recordAccurate by inspection, and labelled as unverified.
The orchestrator's decisionsAll four are carried.
PR descriptionCorrected. It no longer calls the FindingsNo blocker.
Neither needs another round. Before landing (the orchestrator's)
LAND, on those two preconditions. |
… stale judge is recorded app_view's shell arm ran on the T14 at e78085e, so the isolation record no longer owes it. The same boot's process_tree job passed and its judge did not: it counts a kernel line no spawn prints since the spawner lays programs out itself, which is main's and gets its own record. Two wording suggestions taken. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Orchestrator verification at 3298f19, after review r2's LAND at e78085e.
Queueing. |
Problem
Every row the image declares saw
/appsread-write, so a shell and everything it spawned could rewrite an installed package. The owner ruled on 2026-11-05 that only the installer service writes/apps(stage 2 ofissues/every-program-sees-only-the-files-it-was-given.md).What changes
/appsread-only unless the row declaresinstalls = true(toyos_manifest::Program::installs, beside the/logarmkeeps_the_logselects). The supervisor is unchanged: it already mints a row's grants fromProgram::view, storage rows excepted (below), and the file server already refuses every changing request on a read-only grant.images/system.tomlgivesinstallstopkg's row and no other.pkgrefusesinstallandremoveby name where its/appscapability is read-only:pkg: /apps is read-only to this process; run it withlaunch pkg``.pkg liststill works anywhere./appsis writable to every row are gone frompkg's header, the manifest crate andsystem.toml.Decision:
pkgis the installer service, not its clientThe brief left this open.
pkgbecomes the service because that shape adds no parts:launch pkg install <file>holds/appsread-write while the shell that typed it does not.update,swap,grantsanddisksalready work this way.startslists namingpkg(the shell's and toybox's). Installed packages have nostarts, so none can reach it. The whole authority is inimages/system.toml.Consequence for users: a bare
pkg install xat the shell is a helper holding the shell's view and is now refused with the message above.launch pkg install xinstalls.No build gate restricts
installsto a row namedpkg. A test image needs another row to be its installer (below), and the field is one reviewed line in the image's own manifest. The build's new test states which row writes/appsin every committed config instead.The manual's files page now says "the installer's view" rather than "the installer service's view", matching "the updater's view" beside it: the holder is a launched program, not a daemon.
Tests
Host:
toyos_manifest::tests::only_the_installer_writes_apps: the row declaringinstallsholds/appsread-write; the shell that starts it, a service and a row merely namedpkghold it read-only; a package's own directory stays read-only.build::tests::only_the_installer_s_view_writes_apps: over every committed config, the rows whose rendered view writes/appsare exactlypkginimages/system.tomlandhostedclangcase.toml,test-runnerinproctreecase.toml, and none elsewhere.installs(main's behaviour): both new tests anda_declared_row_sees_the_whole_tree_but_state_and_of_state_its_ownare red;installsinimages/system.toml: the manifest crate's tests stay green (they read no config) and the build test is red with["pkg", "shell"]against["pkg"].Metal (
app_view, on the T14, because it needs a real file server, supervisor and launcher; it has no QEMU registration):proctreecase.tomlmakestest-runnerthat image's installer, because the job writes and rewrites its packages under/appsdirectly, which no installer does./home, which must write, and into/apps/appview, which must fail with the file server's read-only reason and leave no file./homeand/appsare one volume and one server and differ only in the grant, so the grant is what refused. This stands in for the exit's control boot (the shell's row granted/appsread-write), by the orchestrator's decision, recorded in the issue.hosted_clang_hellonow launchespkgrather than spawning it, and its image givestest-runnerstarts = ["pkg"]. It is on demand, needs a product no CI job or the guest runner holds, and was not run.Not established by this PR
pkgon a machine, andhosted_clang_helloas edited. Its judge is the owed metal rowpkg_install_gbae(issues/the-guest-suite-runs-only-what-no-cheaper-tier-reaches.md, stage D). Until it exists the claim rests on composition:pkg's host tests for the install itself, the view tests above for who holds/appsread-write, and the launcher and file server unchanged.pkg's own refusal message as a helper has no test: it is one branch onDir::writable(), which needs a file server.Recorded, not fixed here
By inspection,
diskserverand the file servers formemoryandsystemstart holding a duplicate of the supervisor's whole-tree namespace,/appsread-write included. They are the signed image's storage stack and open no path, so the shell-to-package boundary does not depend on it. It is unverified on a machine and filed asissues/storage-rows-start-holding-the-supervisors-whole-tree.md, with its exit tied to stage 2.A caller that can launch
pkganswers its question itself (--yes, or the stdin it supplies), so it can still replace a package whole. The boundary this PR adds is between launcher holders and everything else.Checks and evidence
Evidence: https://github.com/ToyOSOrg/evidence/tree/eff6d9e767dc90c4472908660613872f68f76dbb (
INDEX.mdlists each file). Host is macOS arm64.cargo run -- --ci hostinstalls): manifest tests, build testinstalls): manifest tests, build testproctreecase, run by the orchestratorpassedcargo test -p toyos-manifestcargo test --libT14.
app_view,launch_toctouandport_badgepass. The log holds both shell-arm lines:process_treefails its judge: "the loader refused the invalid executable 0 times, not once per B". The job itself endedexit=0. The judge counts a kernel line that no spawn has printed since the spawner began laying programs out itself (d40e9b3, on main): an image that is no ELF is refused in the caller before any syscall. This branch changes no kernel, spawn orprocess_treecode. Recorded asissues/process-trees-metal-judge-waits-for-a-kernel-line-no-spawn-prints.md; not fixed here.Host. The one red in the full run and in
cargo test --libisllvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_key, which fails on every macOS host and is recorded inissues/the-llvm-environment-test-breaks-git-on-macos.md. Since the full run the branch changed one manifest test, comments, theapp_viewguest job, records and one manual sentence; the full run and clippy were not repeated. Since the T14 boot it changed records and one test comment only.No guest row was dispatched. No QEMU-registered row writes
/appsor runspkgexcept the on-demandhosted_clang_hello.🤖 Generated with Claude Code