diff --git a/CLAUDE.md b/CLAUDE.md index c29c5e3d3b3..3c0bbd3d04a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ Modern x86-64 (2020+) and AArch64 are equal targets, UEFI only. Metal is first-c - **Existing Rust just works.** Programs build and run unchanged through proper platform support in ecosystem forks, not ToyOS-specific replacement crates. Apps use the same source on ToyOS, Linux under Wayland, macOS and Windows. A ToyOS-only program must do a ToyOS-only job; its manifest's `exempt` explains it (`build/userlandhost.rs`). X11 is legacy. - **No silent debt.** Remove a discovered compromise or record its evidence, owner and exit in `issues/`. Filing it does not make it acceptable or complete. Never weaken audible or visual quality without the owner's explicit agreement. -Never use a fixed delay where an event can be awaited. A wait has a failure timeout. A hardware-mandated delay with no notification is the exception, with the requirement cited at the operation. +Never use a fixed delay where an event can be awaited. Waits must expose stalled progress. On timeout, return an error where the operation permits it; otherwise report the stall and preserve state. A timeout alone does not authorize termination or restart. A hardware-mandated delay with no notification is the exception, with the requirement cited at the operation. ## Architecture and sources of truth @@ -27,7 +27,7 @@ Read the code for current behavior. `Cargo.toml` accounts for packages; `images/ The supervisor constructs process namespaces and endowments. The kernel enforces object authority; each userland protocol validates its own inputs and grants. The target is per-program filesystem views; inspect the storage track and code for the remaining shared kernel paths. -ToyOS trusts only what it cannot avoid trusting: the CPU and chipset vendor with its signed microcode, the platform firmware (UEFI, AML, SMM), which already controls the whole machine, and the signed image with its pinned toolchain and crates. Everything else is isolated: programs, users and sessions, the network, file contents, and external or hot-plug devices, whose DMA stays behind the IOMMU. The single exception is a privilege beyond a normal device claim, such as a reset line, DMA without an IOMMU or a firmware register window: it is granted only in the signed image's `system.toml`, to a program that image ships, and a package installed later never gets one, whoever signed it. Inside the trusted base a check is a bug fence, kept where it is cheap and catches our own mistakes, such as a write landing in RAM, the IOMMU, the interrupt controllers or another driver's device; it never withholds a feature for want of a vendor document. +ToyOS trusts only what it cannot avoid trusting: the CPU and chipset vendor with its signed microcode, the platform firmware (UEFI, AML, SMM), and the verified signed OS image with its pinned toolchain and crates. Programs, users, sessions and untrusted inputs remain isolated. Distro hardware drivers use isolation wherever the hardware provides it. When hardware genuinely lacks isolation, those drivers may operate as trusted system code under one distro-wide policy, without per-driver exceptions or machine-specific images. External DMA-capable devices still require isolation, even with a distro driver; separately installed drivers never acquire the bypass merely by being signed. Unknown isolation, unsupported isolation hardware and failed setup are errors, not evidence that isolation is absent. Other exceptional powers, such as reset lines or firmware register access, remain explicit grants in the signed image's `system.toml` to programs it ships. Inside the trusted base a check is a bug fence, kept where it is cheap and catches our own mistakes, such as a write landing in RAM, the IOMMU, the interrupt controllers or another driver's device; it never withholds a feature for want of a vendor document. Names and paths never establish trusted-driver identity. See `issues/a-machine-without-an-iommu-refuses-every-claim.md` for the remaining implementation. The loader owns every UEFI call, before ExitBootServices. CPU control registers come from one declaration, applied and asserted on every CPU. Input translation belongs in userland, per surface. The kernel's logging responsibility is its record ring and console; logkeeper owns the log file. POSIX compatibility belongs in `sdk/libc`, never in the kernel's native interface. @@ -39,11 +39,11 @@ Choose designs on their merits for modern hardware. Use vendor documentation, pu Read another implementation's code, whoever wrote it, only clean-room: one agent derives facts and keeps the provenance of each in its evidence, never in the repository; another implements from those facts without seeing the code. The derived specification goes in the implementation brief, not the repository. A vendor's document is still cited at the site. Editing an upstream fork is governed by the implementer's fork rules. No upstream pull request is sent for now. -Use general, widely used crates as published when they are the cleanest solution. Write ToyOS-specific functionality ourselves, including drivers; minimize kernel dependencies and keep libc out of the kernel. A security boundary may justify our own well-tested crate. A fork carries upstream-quality source changes and goes when upstream supplies them; packaging alone uses unmodified source pinned by hash. +Prefer ToyOS-owned implementations for core machinery, including the scheduler, cryptography and allocator; preserve security, correctness and measured performance requirements. Use general, widely used crates as published where they remain the cleanest solution. Write ToyOS-specific functionality ourselves, including drivers; minimize kernel dependencies and keep libc out of the kernel. A security boundary may justify our own well-tested crate. A fork carries upstream-quality source changes and goes when upstream supplies them; packaging alone uses unmodified source pinned by hash. Rust and QEMU are the development prerequisites. Other host tools must be buildable from C or C++ for eventual self-hosting, justified where Rust tools do not suffice, and declared in `issues/the-build-runs-host-tools-outside-rust-and-qemu.md`. No dependency on a binary for only one host OS. ToyOS's own maintained code is Rust, not Python, Perl or shell. Bootstrapping all the way from source without a binary seed is out of scope. -`NOTICE` records committed third-party files, hashes, origins and licences. Vendor-signed firmware may ship pinned by version and hash when redistribution permits it. Device firmware is loaded by its owning driver through its IOMMU domain; CPU microcode loading is privileged kernel work. Loading responsibility does not require embedding firmware payloads in the kernel binary. +`NOTICE` records committed third-party files, hashes, origins and licences. Vendor-signed firmware may ship pinned by version and hash when redistribution permits it. Device firmware is loaded by its owning driver through the DMA API under the isolation policy above; CPU microcode loading is privileged kernel work. Loading responsibility does not require embedding firmware payloads in the kernel binary. ## Testing and evidence @@ -66,12 +66,12 @@ One agent, one worktree, one branch. The primary checkout owns `main` and `rust/ Implement the agreed outcome across the components it requires; a file boundary is not an approval boundary. Ask the owner when a discovery changes an owner-approved architectural decision, or when the architectural choice is uncertain. Routine implementation choices belong to the agents. Record unrelated discoveries without letting them consume the task. -Keep full command output in logs when it is long; truncation loses evidence. Report observed results, and label estimates and unverified claims. Never put personal data, machine or network identifiers into network requests, commits or published evidence. The build user-agent is `toyos-build (https://github.com/ToyOSOrg/ToyOS)`; `build/sourcegate.rs` defines identifying shapes to exclude. +Keep full command output in logs when it is long; truncation loses evidence. Report observed results, and label estimates and unverified claims. Hardware model/product numbers and firmware versions may appear in published evidence for reproducibility. Never put personal data or machine-specific identifiers, such as serial numbers, MAC addresses or network endpoints, into network requests, commits or published evidence. The build user-agent is `toyos-build (https://github.com/ToyOSOrg/ToyOS)`; `build/sourcegate.rs` defines identifying shapes to exclude. ## Comments and instructions Comments are a maintenance cost. Prefer expressive code and names. Delete false, stale, redundant or unnecessarily long comments rather than polishing them. Keep concise boundary contracts, non-obvious invariants, unsafe preconditions and hardware requirements that code cannot express, such as why an MSR needs a particular value. A source citation is useful when it explains that constraint. History, investigations and measurements belong in commits or evidence. -A module header is not an essay or an inventory. Keep only what a reader needs to use or safely change the module. Durable rules belong at their relevant boundary; do not build a second specification in comments or private agent memory. +A module header is not an essay or an inventory. Keep only what a reader needs to use or safely change the module. Engineering work must stand on its own: do not cite private planning notes or requirement identifiers in code, comments, tests, plans or issue records. Give agents self-contained briefs. Durable rules belong at their relevant boundary; do not build a second specification in comments or private agent memory. Change instruction files when the owner briefs it or a change removes or renames something they instruct agents to use. Replace conflicting rules instead of appending exceptions. Keep these files short, give each rule one home, and prefer judgment over a procedure for every incident. Update issue records directly affected by the change so they remain accurate. Record unrelated discoveries without expanding the assignment into their implementation or a general tracker cleanup. diff --git a/issues/a-device-function-is-driven-from-its-arrival-to-its-end.md b/issues/a-device-function-is-driven-from-its-arrival-to-its-end.md index 015a924b8e5..bb28bdcff2d 100644 --- a/issues/a-device-function-is-driven-from-its-arrival-to-its-end.md +++ b/issues/a-device-function-is-driven-from-its-arrival-to-its-end.md @@ -17,8 +17,10 @@ started. Nothing reaches userland when a device arrives or leaves. **Ruled** (owner, 2026-10-13): 1. The kernel hands out only what the IOMMU can tell apart: PCI functions, ISA - rows, platform devices. The supervisor brokers those from `system.toml`, at - boot and whenever one arrives later, by moving the claim to a driver. A bus + rows, platform devices. The supervisor brokers those at boot and whenever + one arrives later, by moving the claim to a driver. Image drivers come from + `system.toml`; the owner's 2026-10-16 package decision below adds authorized + installed drivers. A bus service (usbd, one per xHCI controller) owns everything behind its controller, keeps its device classes (HID, mass storage) inside its process, and speaks the client protocols directly (input, block). The supervisor @@ -50,8 +52,7 @@ started. Nothing reaches userland when a device arrives or leaves. - A driver instance reaches its consumer as a client of the consumer's port, wired as ports are today. It never serves a name for connect-by-name. - The claim-slot limit is removed by stage 1 if cheap, otherwise by its own - pull request before stage 1's guest smoke - (`issues/a-cargo-run-boot-claims-every-pcidev-slot.md`). + pull request before stage 1's guest smoke. **Ruled** (orchestrator, 2026-10-20, on the step-10 brief; it replaces #901's `block@` ports, `each`, `pci@` and several block services): @@ -92,6 +93,25 @@ started. Nothing reaches userland when a device arrives or leaves. - With `ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off`, the delete completes at once. +## Installed driver integration + +The separate-driver-package decision is owned by +`issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md`. +The supervisor starts authorized installed drivers through the same +function-claim lifecycle and process/protocol boundaries above. usbd continues +to own its whole controller and device classes within one process. + +Privileges beyond normal isolated device claims remain restricted to +image-shipped programs under `CLAUDE.md`. Preserve the image-only exception in +`issues/a-machine-without-an-iommu-refuses-every-claim.md` and the external-device +DMA-isolation requirement and persistent firmware weakness in +`issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md`. + +Protected registration, matching conflicts, authorization scope and coordinated +device release, restart, update and uninstall remain design work. Drivers needed +to reach installed-package storage must be available before that storage mounts. +The target does not establish seamless live driver replacement. + ## Stages 1. **A holder's end is the event.** diff --git a/issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md b/issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md index 9137caf0b92..402dcf903ba 100644 --- a/issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md +++ b/issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md @@ -18,10 +18,11 @@ driver: the next holder, and the next boot's firmware before any IOMMU is on, drive what the last holder wrote. That reach is the IOMMU design's reading, not a measurement. -**Ruled** (owner, 2026-10-04, "Refuse external, record reflash"): -"External-port devices can't be claimed by userland drivers for now; -reflashing is a recorded weakness with an exit (firmware verification) to -design later." +Owner decision, 2026-10-17: external DMA-capable devices still require +isolation, even when operated by distro drivers. The no-isolation policy in +`issues/a-machine-without-an-iommu-refuses-every-claim.md` does not waive that +boundary or solve firmware persistence. Reflashing remains the recorded +weakness whose firmware-verification exit needs design. Owner: the orchestrator, under `issues/the-iommu-refuses-nothing-yet.md`. diff --git a/issues/a-file-held-across-a-file-servers-restart-answers-gone.md b/issues/a-file-held-across-a-file-servers-restart-answers-gone.md index d1232d748f9..e8f6ddc17db 100644 --- a/issues/a-file-held-across-a-file-servers-restart-answers-gone.md +++ b/issues/a-file-held-across-a-file-servers-restart-answers-gone.md @@ -11,7 +11,14 @@ put at its path since, and a file held across a restart answers `Gone` (`toyos::files`, so std's `File` and a C descriptor alike); `logd` loses `/log` for the boot if LOG's server restarts. -**Exit**: DATA's entry carries an object id and a generation that nothing -reuses, a held handle reopens only when both match, and a host test that -makes a same-length file in a held file's freed block within the second has -the reopen refused. +Owner decision, 2026-10-17: interrupted handles may report `Gone`; transparent +reopening is not a general first-release requirement. Do not require object +ids and generations solely to restore every held handle. See +`issues/the-supervisor-is-host-tested-and-owns-the-stop.md` for the recovery +policy. + +**Exit**: resolve the recorded loss of logging for the rest of the boot through +explicit, protocol-safe reconnection, or report that logging remains unavailable. +Do not silently bind an existing file handle to a replacement at the old path +or replay writes whose outcomes are uncertain. Verify the current logkeeper +behavior before implementation; the paths above predate its rename. diff --git a/issues/a-firmware-call-does-what-its-handler-chooses-and-the-kernel-bounds-only-the-call.md b/issues/a-firmware-call-does-what-its-handler-chooses-and-the-kernel-bounds-only-the-call.md index 7af3fadd705..765ea41b66d 100644 --- a/issues/a-firmware-call-does-what-its-handler-chooses-and-the-kernel-bounds-only-the-call.md +++ b/issues/a-firmware-call-does-what-its-handler-chooses-and-the-kernel-bounds-only-the-call.md @@ -120,14 +120,29 @@ is the slice's that evaluates the methods which call. Owned by `issues/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md`, beside `issues/the-acpi-servers-holder-drives-the-embedded-controller-unfiltered.md`. -**Exit**: a call is made only for a byte the machine's loaded tables store -to the port, checked by something other than the holder, or the owner rules -the bound above is the one ToyOS keeps; and the rate is held against the -calls a T14 row reads the machine's own AML making, with the time each held -the boot processor; and the span is ruled. -The T14 reading owed is the time each call its AML makes holds cpu0 (the -slice that passes those writes landed in `d2006cc65`, and no such reading or -ruling is recorded here), and the owner rules, against those readings, -whether a handler that returns after `DEAF_CPU` ends the machine. Where the -interrupt stops every CPU the kernel such a handler returns to is whole, so -the panic there is this kernel's choice. +## Owner decisions, 2026-10-21 + +Firmware is necessarily trusted on the supported machines; acpiserver is +trusted platform code. Keep explicit authority and inexpensive checks protecting +kernel-owned memory and registers. Do not add a second AML interpreter/checker +merely to independently approve its firmware requests. This does not make +firmware access available to ordinary programs or contain firmware behavior. + +Owner correction, 2026-10-21: retain the five-second fatal firmware-stall +policy, even if the call eventually returns. This supersedes the earlier +continue-after-return direction. Name the firmware call and elapsed duration in +the failure report. Five seconds is a catastrophic-stall threshold, not an +acceptable normal latency budget. Fatal handling is a chosen policy; elapsed +time alone does not prove corruption. Preserve independent safety checks and +review watchdog/completion interactions. The threshold cannot interrupt firmware +holding every CPU; enforcement requires kernel execution to resume or another +CPU still running. Never-returning firmware may leave no software recovery path. + +**Exit**: verify the approved fatal-stall policy and watchdog/completion +interactions, with accurate firmware attribution. Establish the command-rate +policy against actual platform needs and record the duration and frequency of +calls from the machine's AML. The existing eight-per-second figure is not +established as universally adequate and does not bound all possible sources of +SMI. Keep measurement scope and remaining non-returning-firmware limits explicit. +The trust/checker and five-second fatal-stall choices no longer await an owner +ruling. diff --git a/issues/a-machine-without-an-iommu-refuses-every-claim.md b/issues/a-machine-without-an-iommu-refuses-every-claim.md index b2ea7e87b5d..1b6aa93af94 100644 --- a/issues/a-machine-without-an-iommu-refuses-every-claim.md +++ b/issues/a-machine-without-an-iommu-refuses-every-claim.md @@ -6,28 +6,43 @@ opened: 2026-09-29 # A machine without an IOMMU refuses every claim; signed in-image drivers should claim there -Owner ruling, 2026-09-29: on a machine with no IOMMU unit a driver signed and -shipped in the ToyOS image may claim a device, and no other may. -It is the same driver code as on a machine with a unit, never a second -driver: the kernel's DMA layer hands it a physical address where there is no -unit and a domain address where there is. A claim's space is an -`iommu::OwnSpace` (`kernel/src/iommu/mod.rs`), which has no untranslated form -until the ruled path adds one. Such a machine states plainly that it has no -isolation — the full isolation guarantee needs an IOMMU, and there a bad -signed driver can still crash or corrupt the system. +Owner decision, 2026-10-17: distro hardware drivers may operate without +isolation when the hardware genuinely lacks it. This is one distro-wide rule, +not a per-driver exception list or a machine-specific image. Use available +isolation even for trusted distro drivers. Unknown isolation, unsupported +isolation hardware and failed setup remain errors; they do not enable a bypass. -**Not yet designed, and owed:** what "signed" is (what is signed, by whom, and -where it is checked) and so what the "identity check" compares. No signature -or image-identity mechanism exists in the kernel today. The exit below cannot -be written as a test until it is. +External DMA-capable devices require isolation regardless of which driver +controls them. A trusted driver does not make external hardware trustworthy. +Determine the actual hardware boundary, including inseparable groups; do not +claim isolation between devices the hardware cannot separate. Ordinary USB +peripherals are not independent host-memory DMA requesters: distinguish the +host controller's DMA authority from the untrusted protocol data it handles. + +Eligibility is authenticated distro hardware-driver identity and a legitimate +device grant, not merely being an executable in the image, a pathname, or a +signature on an independently installed package. The verified image covers +its drivers; separate driver signatures are not required. Establish how the +trusted launch path conveys that identity and authority to the kernel. Other +powers, including reset lines and firmware register access, remain explicit +grants and are not implied by this rule. + +Use the same driver and DMA API in both modes. The DMA layer supplies translated +addresses when isolated and platform-correct bus addresses otherwise. CPU +process isolation remains, but an unisolated DMA driver/device belongs to the +trusted base and can potentially compromise the whole machine. Report this +reduced protection accurately. This policy does not itself implement a new +board port or authorize bypassing existing isolation to accelerate one. + +The no-isolation claim path and its authenticated authority are not implemented. Today `pcidev`'s `bring_up` refuses every claim on such a machine first with `Refusal::NotRemapped`, whoever asks: no unit remaps its interrupts, and a claimed function is armed only through `iommu::claim_msi`, which takes a `Remapping` such a machine never mints. Behind that, `Refusal::Untranslated`: a slot's space is an `iommu::OwnSpace`, which has no untranslated form, so -there is no physical address for a grant to answer with. The signed driver's -claim is the path where `NotRemapped` and `Untranslated` both give way under +there is no untranslated device address for a grant to answer with. The distro +driver's claim is the path where `NotRemapped` and `Untranslated` both give way under the ruling. On such a machine whose image is on its NVMe disk, which @@ -51,17 +66,21 @@ refusal. Exit, in both arms of `iommu_virtio_platform` (`tests/common/iommu.rs`): -- On `Profile::HeadlessNoIommu` a claim by a driver the image ships and signs - is handed over, and a claim by any other is refused by a `Refusal` variant - of its own, named on the `pcidev: … NOT HANDED OVER —` line +- On `Profile::HeadlessNoIommu` an internal device claim by an authenticated + distro hardware driver is handed over, and an ineligible claim is refused by + a `Refusal` variant of its own, named on the `pcidev: … NOT HANDED OVER —` line `faults::refused_claim` reads, so a refusal for any other reason (no MSI-X, no BAR window) fails the arm. Deleting the identity check so that - every claim goes through reds it. The non-image claimant is a - `tests/guest/rust-tests` binary, to be added, that init hands the NIC - function under `netcase`; netd is the in-image claimant. -- The kernel says "no isolation on this machine" at boot on - `Profile::HeadlessNoIommu` and never on `Profile::Headless`. Printing it on - every profile reds the `Headless` arm; printing it on none reds the other. + every claim goes through reds it. An ordinary test executable must remain + ineligible even if shipped in the test image; it is not a distro hardware + driver. Cover separately installed drivers in the authority policy tests. +- Report the lack of DMA isolation on `Profile::HeadlessNoIommu`, without + implying that CPU process isolation is absent. The isolated profile must + retain isolation and not report the unisolated mode. +- Host policy tests cover external devices, unknown topology, setup failures + and driver eligibility: none acquires an unintended bypass. Relevant device + tests verify that external DMA remains blocked without established isolation. + Existing usable isolation must still be used for distro drivers. The refusal is named in `pcidev`'s `Refusal`, not as a new `ClaimError`: `ClaimError` splits only where a caller acts differently, and its one caller, diff --git a/issues/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md b/issues/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md deleted file mode 100644 index c6ccc1bec10..00000000000 --- a/issues/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -status: open -kind: defect -opened: 2026-10-04 ---- - -# A memory-overwrite request Ubuntu left set stays set under ToyOS - -The owner's ruling "Keep crash records" (2026-10-03, -`issues/toyos-explains-itself.md`) has ToyOS not ask the firmware -to wipe memory at reset. On the T14 the request is already made: under its -Ubuntu (`6.8.0-142-generic`), whose EFI stub sets it on every boot -(`issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`), - -``` -ls /sys/firmware/efi/efivars/ | grep -i -E "MemoryOverwrite|MOR" -for f in /sys/firmware/efi/efivars/MemoryOverwriteRequestControl*; do [ -e "$f" ] && { echo "$f"; od -An -tx1 "$f"; }; done -``` - -read `07 00 00 00 01` for `MemoryOverwriteRequestControl` and `07 00 00 00 00` -for `MemoryOverwriteRequestControlLock`: efivarfs's four attribute bytes -(non-volatile, boot-service and runtime access), then the value: the request -0x01, set, and its lock 0x00, unlocked. The variable is -non-volatile, so it stays set into every ToyOS boot that follows Ubuntu, and -`loader/src` neither reads nor writes it. Whether this firmware honours it -on the reset paths ToyOS takes is unmeasured: a black-box record has survived -two hours of Ubuntu, which does not say what an unclean reset does. Every -UEFI call ToyOS makes is the loader's, so the write belongs with -`issues/the-loader-does-only-what-must-precede-the-handover.md`. - -**Exit**: where the firmware defines `MemoryOverwriteRequestControl` and it -reads non-zero, the loader writes 0 before `ExitBootServices` and logs the -value it found; where the firmware defines none, it makes no `SetVariable` -call under that GUID. A guest test on a fresh OVMF variable store planted with -1 reads 0 after the loader's pass, and one planted with nothing finds no -variable under the GUID; deleting the write reds the first, and an -unconditional write reds the second. On the T14, a boot that finds it set -logs the 1 it found, and a black-box record sealed by a forced reset of that -boot is read by the next. diff --git a/issues/a-new-microcode-patch-reaches-a-machine-only-in-a-new-image.md b/issues/a-new-microcode-patch-reaches-a-machine-only-in-a-new-image.md index 4d46e349d91..f37b5f4f3fb 100644 --- a/issues/a-new-microcode-patch-reaches-a-machine-only-in-a-new-image.md +++ b/issues/a-new-microcode-patch-reaches-a-machine-only-in-a-new-image.md @@ -16,6 +16,15 @@ saying so. Owner: the orchestrator. -**Exit**: a new patch for a machine arrives as a file on ROOT through the -package path, and the loader hands it over on the next boot without a new -image. +Owner decision, 2026-10-18: the minimal base image carries no microcode-update +payloads. Updates come through package management, which recommends applicable +microcode for the actual CPU. CPU identification already exists in +`lib/microcode`; the package catalogue, installed/current revision handling and +recommendation path still need design. + +**Exit**: a compatible authenticated patch arrives through the package path, +and the loader hands it to the kernel on the next boot without a new OS image. +Define package storage available before personal-data unlock while preserving +the verified boot and immutable-system contracts; do not assume packages can +write arbitrary files into signed ROOT. Package distribution does not move +privileged CPU-update application into an ordinary package-manager process. diff --git a/issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md b/issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md index e49d25894e1..c917d1008f7 100644 --- a/issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md +++ b/issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md @@ -6,9 +6,48 @@ opened: 2026-09-04 # A package is a directory under /apps, and the installer is a program -The milestone the owner set on 2026-09-03: download and install -github.com/Japabu/gbae from its GitHub release and run it, in QEMU first, -with no shortcut past what an ordinary OS target does. +## Approved package behavior + +- Keep the base small. Ship package GUI and CLI with one catalogue/state/authority + model; download browsers, development tools, editor, SSH and additional drivers. + Bundle drivers needed to boot, install offline, use the desktop and reach packages. + Recommend applicable driver and CPU microcode packages; microcode payloads are + distributed separately from the OS image. +- Ordinary app-specific libraries travel with the app. No custom install, update + or uninstall scripts. Apps initialize/migrate private data on launch, including + selecting separately supplied game data. Driver/OS activation needs its own design. +- Support the distro catalogue and external package files; additional catalogues + are deferred. Unsigned packages require explicit approval and an unverified + publisher indication. No silent enrollment of an external update source. +- Personal installs require the user's approval; all-user installs and system + changes require system authority. An installer is an ordinary authorized + program, not a privileged executable name. Protect committed installed versions + from arbitrary writes, using private staging and authorized activation. +- Package identity comes from protected installation records and verified update + transitions. A name or digest alone grants nothing. Verified updates preserve + approvals and denials; unverified replacement cannot inherit them. +- Prepare verified app updates automatically, activate while stopped and allow + per-app pause. No automatic private-data recovery points or built-in backup product. +- Quit before uninstalling; offer keep/delete for private data, preserve unrelated + documents and forget saved permissions. Updates are not uninstall/reinstall. +- Allow unpackaged unsigned native programs. Direct approvals last only that run; + ordinary inherited/delegated access follows its existing lifetime. +- Apps manage plugins with general isolation tools; no OS extension framework. + Separately installed drivers require explicit device authority and supported + isolation; being signed does not confer the distro's isolation exception. +- Native source ports and libc are the compatibility path; Linux binary execution + is deferred. Stabilize the app contract within a defined support window when + ready; current development remains free to change interfaces. + +The final package metadata, protected identity and activation protocol remain to +design. Ordinary runtime permission requests require no manifest category list. +Network consent and delegation are owned by the permission-runtime track; do not +implement a separate package-specific policy. + +## Milestone + +Install and launch gbae as an ordinary package with authorized access to selected +game data. Use the same package behavior for DOOM and other native ports. ## What exists on the other side @@ -26,12 +65,11 @@ the binary in a ToyOS guest is this track's harness's job, not gbae's. fetching a source tree and building it on the machine waits for a hosted compiler and is no part of this track. - **A package is a directory.** `/apps//` holds the binaries, data and - licence the archive carried, unpacked as-is, plus one file the installer - writes: `manifest.toml` naming the package, version, the archive's digest, - and the program to launch. Nothing is registered anywhere else: the - desktop's launcher lists `/apps` and reads each manifest; init grants an - app its namespace from that row the same way `system.toml` grants a system - program's. Removal is deleting the directory. + licence the archive carried. Today's installer adds a `manifest.toml` naming + the package, version, archive digest and program to launch. The launcher can + discover packages by listing `/apps`; this does not exclude protected + installation/source identity records. Package metadata is not authority. + The final metadata format remains open. - **A package is a program, whole** (owner, 2026-10-02): self-contained and fixed at build time. No library packages, no dependency solver, no install scripts; a fix in what a package carries is a rebuild of the package. @@ -39,27 +77,27 @@ the binary in a ToyOS guest is this track's harness's job, not gbae's. library can be a build input named exactly by hash, never an installed thing; shared objects stay, only library packages go. - **`/apps/` is immutable by stage-then-commit** (owner, 2026-10-02). - `pkg` unpacks into a private staging directory and commits it in one step, - one operation the file server gains; nothing writes a committed package. + An authorized installer unpacks into private staging and activates the + verified version in one step. Follow the installed-code protection policy + above; the activation interface remains to be designed. - **A standalone C program's ToyOS changes are patch files in a recipe** (owner, 2026-10-02), against an upstream archive pinned by hash; a delta too large to read as patches moves to a fork repository pinned by commit. Forks stay for crates, `rust/` and LLVM. Recipes and patches live in this repository, where `NOTICE` and the licence gate carry them, not in a ports repository. -- **The installer is an ordinary program**, `/system/bin/pkg`, with no - authority a shell does not have: it fetches, verifies, unpacks and writes - under `/apps` because `/apps` is writable to it, and it asks the user - before it installs — at install, the moment the user typed the command, - never at first run, so a refusal leaves nothing on disk and no answer has - to be stored. `pkg install `, `pkg install `, `pkg remove +- **The installer is an ordinary program**, `/system/bin/pkg`, with explicit + installation authority as approved above. It fetches, verifies, stages and + activates packages. Manual installation keeps its confirmation, separate from + runtime resource consent. `pkg install `, `pkg install `, `pkg remove `, `pkg list`. - **Verification is by a signed repository** (owner ruling: `pkg install ` and the release's `SHA256SUMS` behind it are retired): a root pinned in the image, then a timestamp and a targets naming each archive by length and SHA-256 (`lib/update/src/repo.rs`, written by `build/publish.rs`). - `pkg install ` stays for local and offline installs, checked against - the `SHA256SUMS` beside it. + `pkg install ` stays for local and offline installs. Today's adjacent + `SHA256SUMS` check establishes consistency with that file, not an authenticated + source identity; it cannot confer an existing signed app's saved permissions. - **Fetching is HTTPS.** GitHub serves releases only over TLS, so `pkg` carries a TLS client; the network stack under it is netd's. A crate that does TLS is not our job to write and is widely used; it takes the fork @@ -92,8 +130,11 @@ The storage track's users and mount-protocol stages do not block this one. runs on the host in Rust; then once against GitHub itself, by hand, with the owner watching. No registered test fetches anything. 3. Updates: `pkg install` of a newer version replaces the directory whole - after the new archive verified; the old one is gone only after the new - one is in place. + after verification and through explicit installation authority. Implement + the installed-code protection and finished-distro activation policies above. + **Exit**: direct writes cannot change a committed version, failed verification + cannot activate one, and activation cannot mix old and new files in a running + application. The old version remains available until replacement succeeds. 4. The signed repository. Landed: the verifier and the publisher, on the host. Owed: `pkg install ` from a mirror list whose one kind is a local directory, the pinned root and its floors under `/system/etc/pkg/`, @@ -104,19 +145,18 @@ The storage track's users and mount-protocol stages do not block this one. the session user's home, `/home/toy/Apps/`, which is its `HOME` and the one part of the home it sees; its own `/apps/` is read-only to it (`toyos_manifest::Program::view`). -6. **An app's rights are its request ∩ the user's grant ∩ the image's - ceiling** (owner ruling, 2026-09-24; the ceiling's shape, 2026-09-26). The - package's manifest *requests* rights; the user *grants* them per user - (from a user action — the file picker hands over one file — or asked on - first use for the risky ones, remembered and revocable; harmless ones such - as a window, sound and the app's own data directory are free); the image - holds the *ceiling*. **The ceiling names rights, never apps**: it is the - set any installed app may be granted at all, so installing an app never - edits the image and the image never lists an app by name. The `[apps]` - row of stage 1 becomes that ceiling. **Exit**: an app installed by `pkg` - from a release runs with exactly the intersection, a request beyond the - ceiling is refused by name, and no file under `/apps` can widen what it - gets. +6. **New access needs authorization within the image's ceiling** (amended + owner ruling, 2026-10-16). Follow the runtime consent and delegation rules + in `issues/permissions-and-capabilities-need-one-runtime-contract.md`; + package declarations are no longer a prerequisite for a permission request. + Ordinary access such as a window, sound playback and the app's own data + directory remains part of the default app environment. **The ceiling names + rights, never apps**: it is the set any installed app may be granted at all, + so installing an app never edits the image and the image never lists an + installed app by name. The `[apps]` row of stage 1 becomes that ceiling. + **Exit**: an installed app obtains additional authority only through an + authorized grant or transfer; requests beyond the ceiling are refused by + name, and changing package metadata grants nothing. 7. **The apps leave this repository.** Each app (snake first, as the pilot: it builds unchanged for every OS) moves to its own repository, built with only the published SDK crates and the released toolchain, and published as @@ -132,6 +172,5 @@ The storage track's users and mount-protocol stages do not block this one. ## Open with the owner - The libraries the machine provides: GPU, video. -- A C program's optional requests. -- ABI stability. +- The future application compatibility boundary and support window. - Scale. diff --git a/issues/a-user-is-a-home-tree-and-a-login-row.md b/issues/a-user-is-a-home-tree-and-a-login-row.md index 8c3afc8213d..53c5b6f0ce0 100644 --- a/issues/a-user-is-a-home-tree-and-a-login-row.md +++ b/issues/a-user-is-a-home-tree-and-a-login-row.md @@ -9,15 +9,15 @@ opened: 2026-09-05 A stage of `issues/storage-is-layers-and-a-role-is-a-filesystem.md`; where a program's own data goes depends on it. -A user is two things: `/home/`, a directory on DATA laid out as -`issues/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 user, `toy`, whose home -init makes at boot. +A user has private storage, exposed as `/home/` under +`issues/where-everything-lives.md`, and a protected userland login record from +which the supervisor builds the session's view and grants. Authentication and +storage-key bindings belong in protected userland records too; their schema is +not settled. There is no numeric user id checked by the kernel or ambient +"current user" that grants authority. A session holds its home because the +supervisor supplied that directory capability; programs receive only their +authorized grants. Until this lands there is one user, `toy`, whose home the +supervisor makes at boot. Stage 3 of `issues/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 @@ -25,3 +25,26 @@ change what backs `/home`, not what a user is. Constraints a builder would otherwise re-derive: the sshd key path already has the login-row shape and is the first consumer; the ROOT image stays immutable, so the user list lives on DATA. + +## Authentication, unlock and session lifetime + +Passwords are allowed; prefer secure passwordless login where supported. Entirely +passwordless enrollment requires a recovery route. Offer a randomly generated +recovery key; password-based setup may explicitly skip saving one. No automatic +administrator escrow. Export of a shared-volume recovery key requires explicit +system authority beyond ordinary login; it does not bypass a locked volume. +Biometric templates must not be treated as reproducible encryption keys. + +Homes are directories on shared encrypted personal storage. Every regular user +may unlock it after reboot with their enrolled method; filesystem permissions +still separate users. Independent per-user encryption and shared-folder key +management are deferred. The storage service owns encryption and key lifetime; +authentication authorizes unlock. Once unlocked, storage remains available until +shutdown/restart, including screen lock, sleep and sign-out. + +Switching desktop users leaves their applications running and requires normal +authentication on return. Signing out ends that session's apps/helpers, not +system services or separate sessions. Allow cancellation or explicit force when +work is unsaved or unresponsive. Programs without windows remain ordinary apps; +there is no separate background-work permission. Session/device transitions and +pre-unlock identity storage remain engineering design work. diff --git a/issues/bcachefs-crate-is-not-bcachefs.md b/issues/bcachefs-crate-is-not-bcachefs.md index bfa39185346..430f05a1280 100644 --- a/issues/bcachefs-crate-is-not-bcachefs.md +++ b/issues/bcachefs-crate-is-not-bcachefs.md @@ -6,44 +6,30 @@ opened: 2026-08-01 # The `lib/bcachefs/` crate does not implement bcachefs -ToyOS's `lib/bcachefs/` crate implements a ToyOS-native on-disk format written from scratch. -It shares a name with Linux bcachefs and nothing else, and **the magics alone settle -it**: ours is a four-byte `MAGIC = b"BCFS"` plus -`DESIGNATION_MAGIC = b"TOYOS-FORMAT-ME\0"` (`superblock.rs:5,24`) and `NODE_MAGIC = b"BTND"` -(`btree.rs:7`), against upstream's 16-byte UUID `BCHFS_MAGIC`, its per-bset -`BSET_MAGIC ^ sb.uuid` and its `JSET_MAGIC`. Neither implementation could mount -what the other writes, and neither would get past the first block trying. - -That collision has already cost this project once: research into the *upstream* -format was filed under this crate's name and needed a warning at its top to stop -a reader taking it for documentation of what we ship. Warning the reader fixes -the document and not the collision — a crate that does not implement the format -it is named after is a hazard we keep paying for, in exactly this way. Renaming -it is the owner's call, not something to do in a docs pass. - -## Answered by the owner, 2026-08-15 - -> *"bcachefs is the default filesystem for toyos. the crate must be an -> implementation of the spec."* - -The resolution is neither a rename nor a deletion. **`lib/bcachefs/` must become a -real implementation of the bcachefs on-disk format, and that format is ToyOS's -default filesystem.** The name stops being wrong by the crate growing into it. - -This entry therefore stops being a question and becomes work: what is owed is the -implementation, and the gap between the two formats recorded above is the measure -of it. The upstream research this tree used to carry went with the documents, so -whoever picks this up reads the format out of upstream's own source and -specification again — that reading is part of the work now, not a head start on -it. - -The track itself is not planned here. - -One fact about the tree that a real-bcachefs track inherits whichever way it is -sequenced: the kernel must parse this format to reach `/system/bin/init` at all, so a -machine whose ROOT it cannot mount has no userland. The observation the ruling -inverts is the other half — a home-grown format has no second implementation to -be judged against, and upstream bcachefs is exactly such a judge. +The active ROOT/build and DATA paths still use the ToyOS-native format in +`lib/bcachefs/src/{fs,superblock,btree}.rs`. Its `BCFS` and `BTND` magics are not +the genuine bcachefs format. `lib/bcachefs/src/upstream/` now implements a +read-only subset of the real format; it has no journal writer or mutation path +and currently refuses encryption and snapshots. That reader does not make the +existing writable volume format interoperable. + +Owner decision, 2026-10-17: retain genuine bcachefs as the default filesystem, +implemented in Rust, with the shared-volume desktop model in +`issues/storage-is-layers-and-a-role-is-a-filesystem.md`. The format comparison +is settled. Independent per-user encryption is deferred; encrypted user storage +remains required for the first release. Implement the genuine single-drive +configuration first, including its required recovery and integrity protections. +This does not commission snapshots, compression or multi-drive implementation. + +The crate must grow into the real bcachefs on-disk format. This track owns the +remaining implementation work; the current ToyOS-native writable format does +not satisfy the decision. No replacement custom format or encryption-format +extension is approved. + +The loader supplies authenticated bootstrap executables explicitly. The +userland fileserver mounts ROOT; the kernel needs no filesystem reader to +start it. A genuine bcachefs implementation can be checked against upstream +tools, unlike the interim ToyOS-native format. **How that judge is used, since a judge is not a dependency:** upstream's `bcachefs-tools` is a *development* instrument, run by a builder on a volume ToyOS wrote, with its `fsck` and its diff --git a/issues/cpu-time-is-a-band-and-not-a-reservation.md b/issues/cpu-time-is-a-band-and-not-a-reservation.md index 4289f0c0e11..57f8ac0ac27 100644 --- a/issues/cpu-time-is-a-band-and-not-a-reservation.md +++ b/issues/cpu-time-is-a-band-and-not-a-reservation.md @@ -1,11 +1,21 @@ --- -status: open -kind: track +status: none +kind: rejected opened: 2026-08-14 --- # CPU time is a band, not a reservation, so nothing anyone is promised is priced +The owner rejected this reservation redesign on 2026-10-16. The current +direction and the unresolved starvation/blocking investigation live in +`issues/the-scheduler-and-the-clocks-never-talk.md`: realtime priority with +trusted-service authorization and runtime safeguards, without EDF/CBS. +None of the implementation stages or policy commitments below remains approved. +The historical measurements are retained as evidence to investigate, not proof +that the rejected design is necessary or that its replacement is implemented. + +## Historical proposal — not implementation instructions + Real-time work outranks normal work by right, fairness is a share of whatever is left, and no entity is promised anything a number can check. Measured consequence: **93.3 ms of audio starvation behind a fair storm**, in a 24-period diff --git a/issues/every-program-sees-only-the-files-it-was-given.md b/issues/every-program-sees-only-the-files-it-was-given.md index fa324aa2906..98529e16a04 100644 --- a/issues/every-program-sees-only-the-files-it-was-given.md +++ b/issues/every-program-sees-only-the-files-it-was-given.md @@ -22,9 +22,11 @@ was handed, so isolating people follows from isolating programs. parent: init builds every program's view from its `system.toml` row, the way it already builds the program's service namespace. Paths keep working, and a path names something only if it lies inside the caller's view. -- **A child's view is at most its parent's.** Nothing widens a view after - spawn, and nothing in it is inherited wider than the parent held it. The - swap port leaking to whatever sshd spawns (PR #484's review) is the same +- **A child's inherited view is at most its parent's.** A program cannot widen + its own authority; later access requires an authorized grant, such as a + document selected through the trusted picker. Nothing is inherited wider + than the parent held it. The swap port leaking to whatever sshd spawns + (PR #484's review) is the same shape of defect in the service namespace. **A launch is the exception, and its caller's row is the approval** (owner, 2026-10-03, "Restrict": each program may start only the programs its configuration row lists; swap and @@ -37,7 +39,10 @@ was handed, so isolating people follows from isolating programs. built into the resolver by construction and tested adversarially, not checked afterwards. - **Sharing is granted, never reached.** A file outside a program's view - reaches it only through the file picker, which hands over that one file. + reaches it through an authorized grant, such as a picker selection or a + transferable capability supplied by another program, never by naming an + otherwise inaccessible path. Delegation follows + `issues/permissions-and-capabilities-need-one-runtime-contract.md`. - **The special cases go.** `/boot` is in the updater's view and nobody else's. With that, the mount guard is deleted. Login data sits in the login authority's view alone. @@ -49,7 +54,8 @@ was handed, so isolating people follows from isolating programs. from the login session. - **Grants, "Adopt"**: a file grant is an unforgeable badge on a connection, written by whoever minted the connection; the kernel vouches for what was - granted, never for who connects. Revocation comes later. + granted, never for who connects. Permission changes follow the shared runtime + contract in `issues/permissions-and-capabilities-need-one-runtime-contract.md`. - **`/tmp`, "Per session"**: a session's programs share one `/tmp`, and each service and each app has its own. This amends the 2026-09-26 ruling of `issues/where-everything-lives.md` that `/tmp` is private per @@ -63,11 +69,60 @@ longer hold the launch right anyway, so excluding the desktop would mostly just block you." That premise holds while only the compositor, terminal, shell, toybox and sshserver rows list `starts` and no `/apps` row does. The compositor's `login = true` in `system.toml` is the whole of it. Whether the -desktop stays one once stage 3's local greeter exists is not ruled. +desktop keeps that pre-authentication authority once stage 3's local greeter +exists remains design work. The finished-distro passwordless authentication +target lives in `issues/a-user-is-a-home-tree-and-a-login-row.md`; this +development allowance is not a production authentication rule. Unix permission bits and numeric user ids are rejected: they leave every path nameable by every program and make confused-deputy bugs structural. +## Remembered file access + +The shared permission model and its approved delegation policy live in +`issues/permissions-and-capabilities-need-one-runtime-contract.md`. + +Owner decision, 2026-10-16: selecting a document for an application remembers +approval to issue access across application restarts until the user removes +that approval. Already-issued access follows the shared permission-change rule. This +does not grant the containing folder or widen the selected access rights. +Bind the stored grant to the user and protected application identity, consistent +with the verified-update policy in +`issues/permissions-and-capabilities-need-one-runtime-contract.md`. + +Owner decision, 2026-10-16: remember the authorized file location +under a trusted filesystem authority, rather than track a document's movement. +Renaming or moving the file requires a new selection to reopen it at its new +location, unless separately held scope already permits access. A different file +later placed at the approved location is also accessible with the approved +rights. This supersedes the earlier document-following and no-replacement +rules: no rename tracking or special permission transfer to an authorized +replacement. A path string alone is +still not authority, and resolving a grant must not allow symlink or mount +substitution to escape its authorized scope. Existing open handles retain +their object binding; they do not silently +retarget when the saved location changes contents. + +Permission removal follows the owner's revised rule in +`issues/permissions-and-capabilities-need-one-runtime-contract.md`: refuse +fresh direct grants while leaving already-issued capabilities usable within +their scope. Removing a remembered file permission does not interrupt open +files or streams, or invalidate delegated copies. A retained directory or +location capability can still authorize operations within its original scope. +Stopping an app is a separate user action, not part of changing permission. + +The current picker returns a path (`sdk/filepicker/src/lib.rs` and +`system/filepicker/src/main.rs`); that response alone does not establish a +persistent grant. The existing folder-grant store is not a selected-file grant +store. Secure reopening and replacement saves remain design +work. Dropping rename tracking removes document-following machinery; it does +not give an editor authority to create temporary files beside the selected +file. A document-only replacement needs scoped staging/commit support and +SDK integration; alternatively the app needs separately authorized folder +access. Do not infer that a location-based grant alone makes all existing +temporary-file-and-rename save patterns work unchanged. No persistent +document-identity registry is required for the remembered permission policy. + ## Stages 1. **The resolver is the file server's** (amended by the owner's storage @@ -102,8 +157,10 @@ nameable by every program and make confused-deputy bugs structural. It still reaches `/tmp` and `/system`, which the kernel serves to every program. Every row the image declares still sees the whole tree read-write, `/apps` included, so a shell and everything it starts can - rewrite an installed package; whether the installer alone writes `/apps` - is `issues/whether-pkg-alone-writes-apps.md`. + rewrite an installed package. Replace that access with protected committed + versions and capability-authorized installation/activation as approved in + `issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md`. + Being a shell or installer grants no authority by itself. `/dev/null` is a name only libc's `open` knows, answered with a kernel null handle (`SYS_NULL`): no view holds it, so `stat` of it and a program that does not open through libc find nothing. Whether views name it is @@ -117,11 +174,12 @@ nameable by every program and make confused-deputy bugs structural. single key list sits in the login authority's view. **Exit**: a program in one user's session cannot name a file in another's, and appending to the key list is inexpressible from any session. -4. **What is not a file.** netd names a socket by an id any - client can name, and memory and process count have no - per-session bound, so one session can starve another. Both close before - the stage exits. **Exit**: a hostile session can neither reach another - session's connections nor deny it memory or processes. +4. **What is not a file.** Connections require capability authority, not a + guessable id. Charge induced kernel allocations and protect control/cleanup + capacity. Applications share remaining memory without default per-session + quotas; allocation may fail when another job consumes it. **Exit**: one + session cannot access another's connections, and resource exhaustion leaves + system controls usable to inspect and stop jobs. ## Known weaknesses diff --git a/issues/idle-cpus-enter-the-c-states-cst-names.md b/issues/idle-cpus-enter-the-c-states-cst-names.md index 9bf02f9a298..4c4ef81c112 100644 --- a/issues/idle-cpus-enter-the-c-states-cst-names.md +++ b/issues/idle-cpus-enter-the-c-states-cst-names.md @@ -6,12 +6,21 @@ opened: 2026-09-29 # Idle CPUs enter the C-states `_CST` names -The kernel runs no `mwait` and reads no `_CST`. The states come from `_CST`, -as Linux takes the T14's, after the AML interpreter -`issues/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md` -records ToyOS lacks. +At primary revision `0e6716fc0`, idle entry is still `hlt`/`wfi`; firmware +idle-state publication and deeper entry remain to implement. `acpiserver` +already contains AML loading/evaluation, so do not treat absence of the whole +interpreter as a current prerequisite. Extend that service to publish validated +processor-state facts and check its actual coverage before dispatching. -**Exit**: on the T14, since a KVM guest's idle is its host's: the idle -minute's package energy, and timer lateness no worse than `hlt`'s by more than -the chosen state's exit latency. **Mutation**: always the deepest state. -**Oracle**: Linux's figures. +The owner-approved contract now lives in +`issues/the-scheduler-and-the-clocks-never-talk.md`. Reconcile #870 before +implementation. Its old machine-wide realtime tolerance and blanket permission +for timers to arrive one exit-latency late are superseded. + +**Exit:** supported hardware states, safe timer continuity and race-free entry +respect the actual wake-path latency requirements. Validate on the T14 and AMD +benches, recording available states and remaining hardware limitations. Host +tests establish selection policy; metal establishes entry and wake behavior. +Measure residency and package energy separately: correct core sleep does not +alone prove package power savings. Linux on the same machine is a comparison, +not a correctness oracle for every timing contract. diff --git a/issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md b/issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md new file mode 100644 index 00000000000..fdc7cdf0414 --- /dev/null +++ b/issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md @@ -0,0 +1,48 @@ +--- +status: open +kind: track +opened: 2026-10-16 +--- + +# Concurrent filesystem I/O and userland service lookup + +## Storage contract + +Use an asynchronous storage core with convenient blocking APIs over the same +path. Ordinary Rust programs retain their blocking APIs. Bulk transport and +protocol interpretation belong in userland; no universal kernel I/O executor. +Shared rings alone do not establish concurrent requests or eliminate copies. + +The design must carry tagged outstanding operations and explicit buffer +ownership through cache misses, the filesystem and block service. Preserve +write ordering, durability, bounded queues, cancellation and disconnect +semantics. Prefer client-provided reusable buffers; retain copies needed to +snapshot untrusted control data. Do not move serialization one layer down. + +Under contention, favor interactive responsiveness while background work keeps +progressing. Start with bounded fair dispatch; justify the smallest useful +classification mechanism. CPU priority alone cannot establish I/O priority. +Shared writeback and already-issued device operations constrain scheduling; +no hard storage deadline or generic kernel dependency graph is promised. + +After service failure, report uncertain outcomes. Retry only when the protocol +proves replay safe; a lost reply does not prove that a mutation did nothing. +Do not introduce persistent request/result records solely to make arbitrary +mutations recover transparently. Keep acknowledged writes awaiting durable +flush distinct from operations whose completion was never confirmed. + +## Service lookup + +Move service names and lookup to the supervisor and SDK. The supervisor supplies +authorized connectors; the SDK resolves their names locally. The kernel enforces +capability authority. Names themselves confer no access. Preserve narrowing, +controlled delegation and later authorized grants without giving children the +parent's entire lookup table. No separate resolver daemon or generic kernel +capability bundle is required. Filesystem path resolution is a separate concern. + +## Completion + +Review the request/buffer lifetime and safe retry contracts, then migrate callers +and delete superseded paths. Demonstrate concurrent independent requests, bounded +work and background progress, correct durability and honest failure reporting. +Measure before claiming reduced notification cost or improved throughput. diff --git a/issues/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md b/issues/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md index aa8f2cc8180..26f193fd4cc 100644 --- a/issues/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md +++ b/issues/logging-records-from-every-producer-and-a-kernel-that-waits-on-nobody.md @@ -22,6 +22,13 @@ The log is a pillar of `issues/toyos-explains-itself.md`. The orchestrator's plan, not ruled: step 1's ring is the reset-surviving region's, and step 2's keys are how a program writes an event. +## Storage topology remains unapproved + +Per-CPU and global storage are alternatives, not prerequisites of the CPU-count +migration. Keep log and trace contracts distinct. Settle bounded writer progress, +overflow, stalled readers and allocation-free panic handling before changing +ring topology. Firmware wiping takes precedence over retained RAM logs. + What is left, in order: **1. The kernel's ring, rebuilt as one lockless variable-length ring with a @@ -31,15 +38,11 @@ the firmware names today, `toyos_abi::log::CursorHead`); the k-way merge and the shard registry go, and with them the merge's per-record cost: a stamp read and a position store per CPU the firmware names, recomputed each record so no fatal path holds a per-CPU array; the loom models are -rewritten. The ring lives in persistent RAM, so a triple fault or a firmware -reset — which seal nothing today — leaves the last boot's tail, and the next -boot's `logd` reads it through `SYS_LOG_READ` under a flag and writes it to -`/log` rather than the loader copying a rendering of it. That is also what puts -a stopped boot's own last records — its stop record, its census, `Rebooting.` — -into `/log` rather than only the next loader pass's page. High-risk: a +rewritten. Firmware memory wiping takes priority over unsaved crash records. +Readers must tolerate an absent or invalid prior-boot tail. High-risk: a loom-checked primitive and the ABI. -*Exit:* one ring, one sequence, a `u64` cursor, and a guest test that resets a -machine mid-boot finding the tail in the next boot's `/log`. +*Exit:* one ring, one sequence, a `u64` cursor, and readers that handle absent +or invalid prior-boot records without requiring RAM retention. **2. Verdicts that match on fields instead of English.** A record carries its severity and origin; the tests and metal verdicts this change touched match on diff --git a/issues/no-physical-memory-fairness.md b/issues/no-physical-memory-fairness.md index 37f20e6d2a0..7bb27eaa704 100644 --- a/issues/no-physical-memory-fairness.md +++ b/issues/no-physical-memory-fairness.md @@ -4,11 +4,69 @@ kind: defect opened: 2026-07-30 --- -# No physical memory fairness +# Memory exhaustion must preserve system control -Any process can allocate unbounded physical memory until the system runs out. -No per-process limits, no memory pressure signals, no OOM killer. A single -misbehaving process starves everything. +## Agreed ownership and pressure behavior + +A job and its helpers share accounting. Independently launched jobs have separate +owners under explicit launch authority; ordinary spawn does not create extra +entitlement. Package identity, permissions and accounting remain distinct. +CPU fairness is flat across jobs with the approved per-CPU approximation. + +Protect control/cleanup capacity; applications share the remaining RAM without +default per-app quotas. One app may consume it, preventing another from starting. +Reclaim safe caches, then refuse new commitments. Do not kill unrelated apps for +pressure. Infallible application allocation may still end that application. +Account for kernel allocations induced by userland. Local finite bounds remain +until allocation refusal and protected capacity replace their safety function. +Swap and container resource hierarchies are deferred; avoid ownership escapes +through child creation without implementing those future facilities now. + +## Memory migration contract + +- Ordinary pages are 4 KiB. Large virtual ranges need no physically contiguous + backing. One mapping inventory supports subrange operations. +- Separate reservation, strict commitment and lazy population. Successful + anonymous commitment includes backing and later page-table/fault metadata + needs. Decommit may retain the reservation. Ordinary Rust contracts stay intact. +- Allocation charges have a fixed owner and survive its creator while another + holder retains the backing. Sharing counts once; copies are new allocations. + Mapping metadata/page tables are charged per mapper. Shared immutable file + backing has one shared-files account without its own fixed quota or reserve. +- Prefer client-provided bulk buffers. Services own/bound their internal state; + no automatic cross-account allocation or exact attribution of every service + byte to a client. Sharing grants no authority to create new owner charges. +- Commit selected stack capacity before thread start; populate lazily with guards. + Keep caller-selected sizes and normal thread-creation refusal. +- Support controlled executable-memory transitions without a separate user prompt, + including writable/executable alias protection and sealed shared executables. +- Coherent mutable shared-file mappings and files larger than RAM are required. + Demand-page, reclaim clean pages and write back dirty ones; never commit the + whole file or charge its backing again per mapper. Fileserver owns consistency + with ordinary I/O and durability; kernel supplies generic memory mechanisms. +- Unlink preserves existing handles/mappings until last release. Fileserver death + invalidates affected shared mappings; subsequent access may end the app. Fresh + opens use the restarted server. Unsaved writes may be lost, durable acknowledgments + must hold. No transparent orphan adoption or uncertain write replay. +- Irrecoverable mapped-page I/O failure may terminate the affected app with file/ + offset diagnostics. Slow storage/pressure alone do not. An overdue page request + remains waiting with visible progress diagnostics; no automatic hang restart. +- Explicit shared child mappings may request a virtual address before start; + refuse conflicts without replacing existing mappings or repeated spawn attempts. + Preserve authority, accounting and protection. PostgreSQL uses native spawn; + no address-space cloning solely for its port. SQLite uses its ordinary Unix + adaptation over libc, including shared-memory locking and durable flushes. + +The design must establish reclaim/writeback progress without spending protected +control capacity, including release only after every mapping and pin is gone. +No application-specific kernel paths or speculative swap/container machinery. + +## Current defect + +Application-driven allocation can exhaust memory needed for kernel work, +system controls and cleanup. Ownership accounting and protected reserve/refusal +paths are missing. Failure of another app's new allocation is allowed by the +policy; loss of the system's control and cleanup paths is the defect. Thread creation is one arm of it, carried out of the closed unbounded-list panic work: nothing caps the machine's live thread count @@ -26,17 +84,15 @@ which is the pair the class asks for: `toyos_desktop::max_windows` and netstack' costs and refuse past it, and a pipe allocates its ring page on first use rather than at `create`. **What a bound alone still does not answer is whose window to refuse.** The memory is charged to nobody, so a cap is the only thing between one -client and the machine — which is this entry, and is why both of those functions' -doc comments name a kernel memory limit as what deletes them. A third such cap +client and the machine. A third such cap is the kernel's directory numbering, `MAX_DIRECTORIES` in `kernel/pure/dirnodes.rs`, and its refusal crosses processes: once one process's `/tmp` names fill it, every process's `stat`, `access`, `opendir` or listing that reaches a directory not yet -numbered is refused `ResourceExhausted`. Charging each number to whoever made it -deletes the cap. - -**Promoted to `defect` 2026-08-25** (finding-lifecycle ruling: isolation -findings are security-adjacent and are promoted, never folded). One process -starving every other of physical memory is a denial of service across the -isolation boundary that needs no privilege and nothing crafted — it is real -today, not a possibility. Owed by whoever builds per-process physical -accounting; nothing in the tree measures or refuses it now. +numbered is refused `ResourceExhausted`. Attribute each allocation to its owner, +but remove a local cap only when actual allocation refusal and reserve +protection replace its function. Accounting alone removes no bound; retain +finite protocol and queue limits needed for bounded work. + +Completion requires allocation refusal before application-driven exhaustion +can disable system controls or cleanup, together with ownership accounting. +Accounting alone does not establish that protection. diff --git a/issues/nothing-charges-kernel-memory-to-a-process.md b/issues/nothing-charges-kernel-memory-to-a-process.md index 8dd2b4e577b..6bafcd76c87 100644 --- a/issues/nothing-charges-kernel-memory-to-a-process.md +++ b/issues/nothing-charges-kernel-memory-to-a-process.md @@ -25,6 +25,13 @@ each other. Accounting is a pillar of `issues/toyos-explains-itself.md`. +The approved attribution scope is now an application and its helper processes, +as recorded in `issues/no-physical-memory-fairness.md`. Per-process attribution +may remain useful for diagnosis, but it must roll up to that resource owner; +helpers remain charged to the same owner. Grouping does not impose a default +memory quota; reserve protection and refusal follow that track's policy. The +owner lifecycle and rules for shared allocations remain design work. + Blocked on nothing. Two things worth knowing before it is restarted, because both cost a day to discover: diff --git a/issues/permissions-and-capabilities-need-one-runtime-contract.md b/issues/permissions-and-capabilities-need-one-runtime-contract.md new file mode 100644 index 00000000000..5e3a2e4cef8 --- /dev/null +++ b/issues/permissions-and-capabilities-need-one-runtime-contract.md @@ -0,0 +1,56 @@ +--- +status: open +kind: track +opened: 2026-10-16 +--- + +# Permissions and capabilities need one runtime contract + +## Settled boundaries + +One userland permission service owns remembered decisions and consent. Supervisor +owns process/session lifecycle and trusted launch identity. Resource services +(fileserver, netstack, soundserver, compositor) authorize fresh grants through +that service and enforce issued capabilities locally. No per-operation permission +round trip, per-category daemon or kernel permission-policy engine. + +A capability carries authority; a name, app-supplied identity or connector badge +does not establish the identity of its current holder. Transfers narrow or retain +rights, never widen them. Ordinary helpers receive passed/inherited authority; +selecting an installed executable does not activate its saved approvals. +Independent app launch needs explicit launch authority and establishes its trusted +identity. The same rules apply to shells, editors, agents and other programs. + +## Consent and lifetime + +- Apps may request ordinary resources at runtime without a manifest permission + list. Trusted file selection grants a location, not automatic folder access or + rename tracking. Failed arbitrary path lookup does not itself summon consent. +- Network first use can prompt. Separate outgoing and unsolicited incoming + permission, per app, including local connections. No per-port consent; show + listeners and refused attempts. Replies to outgoing traffic need no incoming + approval; UDP classification still needs a concrete protocol design. +- Without an approval interface, refuse promptly. Explicit permission commands + support headless/SSH use; no automatic terminal-prompt coordination. +- Verified same-source updates preserve approvals and denials. Unverified + replacements do not inherit them; uninstall forgets decisions even if data stays. + Unpackaged programs receive direct approvals for that run only. +- Any program may pass transferable file/socket access without another prompt. + Show provenance. A recipient denied direct network access may use delegated + access. Copies retain the original grant's scope, not independent saved approval. +- Removing permission blocks future direct grants only. Existing broad grants may + still permit fresh operations/connections and further transfer. Do not implement + live revocation or automatic app termination for a changed saved decision. +- Ordinary resource-session lifetimes still apply: stopping screen sharing ends + its access. Existing capabilities survive permission-service failure; fresh + authorization cannot succeed while unavailable. Parent restart is bounded. + +## Work and exit + +Design protected installation/launch identity, authenticated request attribution, +helper consent, persistence, concurrent requests, bootstrap and crash handling. +Scope file replacement saves without silently widening a document grant. Keep +pending approval and resource failures explicit; no invented success or replay of +uncertain mutations. Apply ordinary Rust/C inheritance and native file/socket +semantics without shell-specific exceptions. Exit: those contracts are implemented +and verified through boundary tests and focused integration evidence. diff --git a/issues/storage-is-layers-and-a-role-is-a-filesystem.md b/issues/storage-is-layers-and-a-role-is-a-filesystem.md index 8d58c06fba6..6639f888a28 100644 --- a/issues/storage-is-layers-and-a-role-is-a-filesystem.md +++ b/issues/storage-is-layers-and-a-role-is-a-filesystem.md @@ -10,8 +10,7 @@ What the installed product's disks look like, from the block device up to a path. **Where each layer runs is the small-kernel track's** (`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`, stages 3 and 4, owner ruling 2026-09-26): block services and file servers are -userland programs, the VFS is a client library, and the kernel keeps ROOT's -in-memory read path and nothing else of storage. The plan this track carried +userland programs, the VFS is a client library, and the kernel keeps no filesystem implementation, including ROOT or tmpfs. The plan this track carried before that ruling — a kernel VFS forwarding to userland servers through a mount protocol — is superseded, and nothing here builds it. @@ -44,39 +43,84 @@ volume, handed to whichever server recognises its superblock. | partition | filesystem | mounts as | writable | |---|---|---|---| -| ESP | FAT32, firmware's rule | `/boot` | kernel only | +| ESP | FAT32, firmware's rule | `/boot` | authorized updater through the BOOT file server | | ROOT | bcachefs image the build writes | `/system` | no; versioned per release | | DATA | bcachefs, formatted on first boot | `/apps`, `/config`, `/home`, `/state` | yes | | LOG | FAT32 while a Mac has to read the dev stick | `/log` | yes | +This role layout is not a completed encrypted-storage layout: reconcile DATA +with personal storage that requires human unlock, separately auto-unlocked +server storage, and the shared-capacity requirement. + `/tmp` has no backing. The dev loop keeps the ESP and ROOT on the stick and DATA on the internal NVMe; the installed product carries all four on one disk. Roles come from partitions, so both shapes are the same code. ## Filesystem -**The kernel reads ROOT and nothing more.** The loader reads the selected -slot's ROOT into memory and the kernel mounts it read-only with bcachefs's read -half; no code that changes a disk is in the kernel. `/system` is immutable by -design: the installer and the updater write it offline, checkpoint it and mark -the journal clean; a kernel that finds a dirty journal under `/system` refuses -by name, because replay is a write-path job and a system image needing one is a -broken install. - -**Every other filesystem is a file server per role** — LOG, DATA, BOOT — over -its block service's sessions, linking the whole crate it serves: a server that -crashes loses its own role and nothing else, and no foreign parser runs in the -kernel on bytes another OS wrote. - -**Multi-device is a filesystem property, not a block-layer subsystem.** Pooling -across disks, replicas per subvolume, tiering with a fast foreground device, -erasure coding, snapshots, checksums and scrub, compression, encryption, -subvolume per user and per app: every one is a feature of upstream bcachefs's -format, which is why `issues/bcachefs-crate-is-not-bcachefs.md`'s -ruling — the crate becomes a real implementation — is what makes them -reachable. The block layer stays dumb. LVM- and md-shaped aggregation is -refused: it cannot tell metadata from data, place a file's replicas on -different disks, or snapshot. +### Filesystem and data policy + +- Implement genuine bcachefs in Rust, initially one drive. Preserve the format's + future pooling/mirroring path without implementing RAID now. Refuse unsupported + layouts; do not invent a substitute format. Snapshots and compression are deferred. +- Require crash recovery and the format's normal integrity/authentication + protections; no additional universal file-content checksum requirement. +- Use case-sensitive names. Share free capacity across users/apps, protect an OS + reserve, warn early and show growth. Cleanup is the user's choice, not automatic + cache deletion. Do not introduce default per-app storage quotas. +- Buffer ordinary writes. Explicit durable completion must survive the promised + failure model. If a mutation loses its reply, report an uncertain outcome and + retry only when proven safe. Favor interactive storage progress without starving + background work; queue policy remains engineering work. +- Personal storage is one encrypted shared volume, with encrypted contents and + names. Raw-disk sizes/timestamps may remain visible. Each regular user may unlock + it with their enrolled method; OS permissions separate users. Authentication, + recovery and screen/session lifetime are owned by the user track. +- Keep shared free space; independent per-user encryption is deferred. Explicitly + configured server data may later unlock after trusted boot without a user; + unattended-server acceptance is deferred. Do not conflate server keys with personal + unlock or require each application to implement storage encryption itself. +- Provide built-in local storage for app-owned tokens. Keep account access and + lifecycle explicit, without becoming a competing password-manager UI. Chromium + needs laptop-stored and USB-key passkeys; prefer direct credential-service + integration subject to design review. Passkey transfer/sync can wait. +- Support coherent shared file mappings, including files larger than RAM, through + generic memory mechanisms. Fileserver owns identity, contents, writeback and + naming. Unlink removes a name, not existing open handles or mappings. +- Read/write removable-file exchange needs a common Windows/macOS-compatible + format; selection and safe-eject behavior remain open. No promise of every + foreign format. No built-in backup product or automatic recovery snapshots. + +### Filesystem ownership + +**All filesystems are userland services.** The verified boot handoff supplies +self-contained supervisor and initial fileserver images plus opaque ROOT bytes, +bound to one release. The kernel validates extents and starts the supervisor by +image capability; it parses no filesystem or pathname. The supervisor starts +the ordinary fileserver in read-only in-memory ROOT mode before reading its +manifest. Neither bootstrap program depends on that filesystem or dynamic libraries. +Keep authenticated role/length bindings, immutable image lifetime and restart access. + +Serve per-session `/tmp` through a RAM-backed mode of the ordinary fileserver. +Do not require a disk format just to store temporary files. Coordinate coherent +mapping and client migration; delete kernel tmpfs, pathname service and file cache. +Other roles use their block-service sessions. Parent-supervised crash recovery +may interrupt a role; it does not make operations transparently replayable. + +**Multi-device is a filesystem property, not a block-layer subsystem.** +Owner decision, 2026-10-16: keep future drive pooling and mirroring as +filesystem-selection requirements, but implement single-drive operation first. +Use the selected format's genuine single-drive configuration; do not invent a +temporary format or implement unused RAID machinery. Unsupported layouts must +be refused. Account for the format's baseline complexity even with one drive. + +The later multi-drive work includes replica placement, reconstruction, degraded +operation and recovery from interrupted changes. Specific expansion and +conversion paths must be designed and verified; choosing a capable format alone +does not promise every layout can be converted without migrating data. These +responsibilities stay in the filesystem service. The block layer exposes the +devices; a separate LVM- or md-shaped aggregation layer is not selected. +Parity, tiering and the other features under review above are separate choices. **Foreign filesystems.** NTFS is postponed behind every other stage here by the owner's ruling, and when it comes it is read-only: Windows fast startup @@ -104,6 +148,11 @@ tree plus a login session whose view init builds from a per-user row. ## Dual boot +Owner release-scope decision, 2026-10-18: a dedicated ToyOS drive is sufficient +for release one. Same-drive coexistence validation and filesystem resizing are +deferred. The preservation rules below remain architectural constraints, not +an added release gate or permission to modify unrelated partitions. + Windows keeps its files under `EFI/Microsoft` on the shared ESP, ToyOS under `EFI/toyos`; ToyOS never writes Windows's. Boot choice is the firmware's menu or a two-entry ToyOS bootloader. The installer's whole obligation to the other @@ -116,16 +165,17 @@ The block services and the file servers are the small-kernel track's steps; what is left here is built on them. 1. The users track, `issues/a-user-is-a-home-tree-and-a-login-row.md`. -2. Real bcachefs under ROOT and DATA — the format swap; nothing above changes. +2. Implement genuine single-drive bcachefs with first-release encryption and + recovery, reconciling ROOT/DATA and the personal/server unlock boundaries. 3. The installer, written together with the layout it lays down: GPT, ESP, ROOT, a designated DATA, one boot entry. 4. Updates: one ROOT partition per release, a second beside the first, the - bootloader choosing — no snapshot logic in the kernel's read path. -5. Multi-device, replicas, tiering, snapshots, as the bcachefs crate grows into - them. + verified activation; no downgrade/rollback or snapshot requirement. +5. Drive pooling and mirroring. The remaining features await the requirements + review above before their scope and implementation order are settled. 6. A full secure boot chain, the end state of `/system`'s immutability: - firmware verifies the bootloader, the bootloader the kernel, the kernel the - ROOT image it mounts, and a link that fails is refused by name. + firmware verifies the loader, which authenticates the kernel, bootstrap + programs and ROOT as one release; failures are refused before handoff. 7. NTFS read-only, postponed here by the owner. LOG stays its own FAT32 partition through the dev phase, because a Mac has to diff --git a/issues/tearing-is-what-gop-cannot-give-back.md b/issues/tearing-is-what-gop-cannot-give-back.md index b8c7ecb5b18..dc591ec47be 100644 --- a/issues/tearing-is-what-gop-cannot-give-back.md +++ b/issues/tearing-is-what-gop-cannot-give-back.md @@ -18,8 +18,9 @@ blit, then every window, then the taskbar, then the cursor, each a separate pass over the mapping — to one `memcpy` of the damaged rows. Closing it needs to know where the beam is, and GOP does not say: there is no vblank interrupt, no scanline register and no page flip in the protocol. It is the display -driver's to close, and the owner's ruling is that the driver comes later and -whole. Double-buffering does not help without the flip either — with one +driver's to close. Owner refinement, 2026-10-18: userland display-control +drivers are allowed for the first release while rendering stays on the CPU; +the earlier blanket deferral of display drivers is superseded. Double-buffering does not help without the flip either — with one scanout and no way to swap it, a second buffer is what the back buffer already is. @@ -47,9 +48,9 @@ whoever next touches those clients' present path. ## The exit path for residual #2, worked out 2026-08-31 Residual #1 — the scanout blit against the beam — is untouched by any of this -and stays where the owner's ruling left it: GOP publishes no vblank, no scanline -register and no page flip, so the display driver closes it and the driver comes -later and whole. **Residual #2 is the tractable half**, and it is closer than a +because GOP publishes no vblank, no scanline register and no page flip. +A display-control driver can close it; the owner allowed these drivers on +2026-10-18 while retaining software rendering. **Residual #2 is the tractable half**, and it is closer than a reading of this file suggests. Recorded because a wave-4 skip claimed three things were missing and two of them ship today. diff --git a/issues/the-capability-end-state-is-twelve-answers.md b/issues/the-capability-end-state-is-twelve-answers.md index 99b4c3ee73c..bb5923b8b29 100644 --- a/issues/the-capability-end-state-is-twelve-answers.md +++ b/issues/the-capability-end-state-is-twelve-answers.md @@ -6,6 +6,16 @@ opened: 2026-08-20 # The capability end-state is twelve answers, written before APIs answer them accidentally +**Historical audit, not a current implementation brief.** The runtime +permission/capability consolidation is proposed in +`issues/permissions-and-capabilities-need-one-runtime-contract.md`. Later owner +decisions take precedence: filesystem isolation is required; service-name +lookup moves to supervisor/SDK; EDF/CBS reservations were rejected. Their +owning tracks are `issues/every-program-sees-only-the-files-it-was-given.md`, +`issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md`, and +`issues/the-scheduler-and-the-clocks-never-talk.md`. Counts, historical +recommendations and COMMITTED/OPEN labels below are not a present-day census. + From the external review of 2026-08-20, adopted by the owner: the tree is making strong capability commitments, and postponing the conceptual model lets dozens of local API decisions harden into architecture by accident. The diff --git a/issues/the-fair-band-orders-by-share-alone-and-a-woken-editor-waits.md b/issues/the-fair-band-orders-by-share-alone-and-a-woken-editor-waits.md index da18121db7e..a433b2ad75b 100644 --- a/issues/the-fair-band-orders-by-share-alone-and-a-woken-editor-waits.md +++ b/issues/the-fair-band-orders-by-share-alone-and-a-woken-editor-waits.md @@ -6,20 +6,17 @@ opened: 2026-08-16 # The fair band orders by share alone, and a just-woken editor waits for a compiler -Queued track from the 2026-08-16 owner conversation on scheduler direction; the -owner wants responsiveness over long-running compute, universally, not as an option. +The owner wants prompt interaction while long-running compute retains its fair +share. Window focus does not change sustained CPU entitlement. Per-CPU +job-group EEVDF is now integrated; preserve the approximate fairness contract. -Today the fair band orders purely by share. The state of the art (EEVDF, Linux's -default since 6.6, and the BORE line of work) keys on one insight: interactive -tasks betray themselves behaviorally — they sleep long and run in short bursts — -and the fair band can order by *lag and virtual deadline* so a just-woken task -gets the next slice without ever receiving more total CPU. A compiler loses the -race for the next 10 ms, never its share of the hour. +Preserve EEVDF eligibility, virtual deadlines and bounded default slices. +Explicit latency requests wait for their first caller. Preserve debt +across short sleeps and migration. No automatic burst-percentile estimator or +foreground priority ladder is required. Waking does not unconditionally grant +the next slice, and the algorithm's name is not a response-time guarantee. -This is the intended occupant of the intra-fair policy seam: the reservation -layer is mechanism and is untouched; an intra-fair policy may reorder fair tasks -freely but cannot affect any reservation guarantee, and the simulator's -invariants gate the swap. One policy in the tree at any time — the seam exists so -the swap is a bounded, sim-gated change, never an A/B in the OS. - -Blocked on: the reservation layer being built. +Jobs define entitlement; per-CPU placement approximates aggregate fairness. +The remaining wake-latency and caller-hint work must show prompt service beside +saturating jobs without extra sustained entitlement. Realtime safety limits +are separate. Validate policy on the host and timing on metal. diff --git a/issues/the-iommu-refuses-nothing-yet.md b/issues/the-iommu-refuses-nothing-yet.md index 131c9a09b23..58c4b28f6d0 100644 --- a/issues/the-iommu-refuses-nothing-yet.md +++ b/issues/the-iommu-refuses-nothing-yet.md @@ -29,11 +29,13 @@ What the harness cannot measure: so are cache-snooping walks, real access-control enforcement, and mid-DMA function reset on a real device. -**Ruled** (owner, 2026-10-04), on the threat model, **"Refuse external, -record reflash"**: "External-port devices can't be claimed by userland -drivers for now; reflashing is a recorded weakness with an exit (firmware -verification) to design later." The weakness is -`issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md`. +Owner decision, 2026-10-17: external DMA-capable devices require established +isolation even when their driver ships in the distro. The distro-wide +no-isolation policy applies only to eligible internal devices and drivers, +as recorded in `issues/a-machine-without-an-iommu-refuses-every-claim.md`. +The earlier blanket external-port refusal must not be relaxed until the +required isolation is established. Device reflashing remains a separate weakness +in `issues/a-driver-that-reflashes-its-device-escapes-its-isolation.md`. On the T14 the external ports are the Thunderbolt root ports `00:07.0` and `00:07.2`, under units 1 and 2 (the orchestrator's reading of that machine's `iommu:` lines). @@ -75,8 +77,8 @@ negative control: - the isolation-scope rule: a non-singleton scope is refused by name for a function behind a PCIe switch, and admitted for a root-complex-integrated function; -- a userland claim of a function below an external port (on the T14, - `00:07.0` or `00:07.2`) is refused by name; +- a claim below an external port (on the T14, `00:07.0` or `00:07.2`) + without established isolation is refused even for a distro driver; - a claim of a function an RMRR names is refused unless it is a display or USB controller that RMRR names alone, whose region is then mapped into its driver's domain (the T14's iGPU row); diff --git a/issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md b/issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md index 9c42ec14874..5b50fb0429f 100644 --- a/issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md +++ b/issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md @@ -15,14 +15,15 @@ security feature such a CPU offers. The proving machines are the T14 and AMD EPYC KVM guests; the PR gate's TCG model proves wiring only. A probe is a `boot-actuators` arm or a `test-actuators` `SYS_DEBUG` action. -One line of Linux's is declined, and ToyOS stays below it there: the -firmware's memory-overwrite request, by the owner's "Keep crash records" -(`issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`). +Owner decision, 2026-10-17: supported firmware memory wiping after unexpected +reset is required, even at the cost of unsaved crash records. Its implementation +is tracked in `issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`. **Exit**: every issue below is closed, in the order listed. The T14's Linux readings issue is not among them: since #915 it owes no reading this track's work needs. +- `issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md` - `issues/a-pure-function-decides-a-cpus-speculation-mitigations-from-its-vendors-guidance.md` - `issues/spec-ctrl-and-gds-stay-as-firmware-left-them.md` - `issues/no-program-runs-with-speculative-store-bypass-disabled.md` diff --git a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md index b5642a446ad..55b947a9a61 100644 --- a/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md +++ b/issues/the-kernel-is-small-interrupts-post-and-threads-wait.md @@ -92,8 +92,11 @@ Beside that order, each waiting on something outside it: zero-copy block I/O. FAT32 on `/log` in the installed product is deferred. **Owed**, the orchestrator's to dispatch, for the restart beyond the bytes stage 3 holds: a module test in `sdk/toyos/src/fs.rs` that a call - on an id from an ended connection answers `Gone` and a path call - reconnects once, red with the generation check removed; and a module + on an id from an ended connection answers `Gone`, red with the generation + check removed. Retry follows the approved recovery policy in + `issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md`: test safe + reconnection separately from repeating an operation, and ensure a lost + reply does not silently repeat a possibly completed mutation. Also a module test in `system/supervisor` that an ended role is started again until `toyos_manifest::RESTARTS` ends inside the window and is then closed with its clients answered `Gone`, red on a supervisor that restarts without @@ -161,8 +164,8 @@ Beside that order, each waiting on something outside it: ("Per session", 2026-10-03, in the isolation track), and `/system` is read over the file protocol, which std and libc both reach through `toyos::files`. **Exit**: `tmpfs.rs`, - `fs_rename.rs` and `file_cache.rs` are gone, `vfs.rs` resolves ROOT - for exec and `SYS_DLOPEN` alone, and `sdk/abi` has no `SYS_OPEN` (9), + `fs_rename.rs` and `file_cache.rs` are gone, `vfs.rs` is gone after authenticated bootstrap images and userland + linking replace its last callers, and `sdk/abi` has no `SYS_OPEN` (9), `SYS_STAT` (16), `SYS_READDIR` (17), `SYS_DELETE` (18), `SYS_CHDIR` (20), `SYS_GETCWD` (21), `SYS_RENAME` (52), `SYS_MKDIR` (53), `SYS_RMDIR` (54), `SYS_SYMLINK` (81) or `SYS_READLINK` (82). diff --git a/issues/the-kernel-still-parses-what-userland-writes.md b/issues/the-kernel-still-parses-what-userland-writes.md index f95d7df37bf..778d2dd0523 100644 --- a/issues/the-kernel-still-parses-what-userland-writes.md +++ b/issues/the-kernel-still-parses-what-userland-writes.md @@ -52,9 +52,11 @@ before that day. Independent of everything else; may run as soon as a slot frees **Move 2 — filesystem daemons**, sequenced after the completion architecture. A crafted image attacks the kernel rather than a sandboxed daemon. The FS daemon -needs the blocking story to be efficient, and the boot path needs its story told -first: the kernel mounts ROOT itself, but what mounts `/boot` and `/home`, and -with what authority, is the open question. +uses the asynchronous storage core with blocking adapters. The loader supplies +authenticated bootstrap executables explicitly; userland mounts ROOT and the +other volumes through granted device capabilities. Remove the remaining kernel +boot-filesystem reader and move temporary storage to a userland RAM filesystem. +The kernel provides generic mappings, capabilities and process startup. **Move 3 — the panic-time symbol resolver**, small and independent. Ruled (owner, 2026-10-03, `issues/toyos-explains-itself.md`): he chose @@ -88,9 +90,9 @@ only by explicit exit; the main thread stops being special either way. **Non-moves, recorded so nobody re-proposes them.** -- **2 MiB pages stay.** The fragmentation is a memory cost, not attack surface, - and the smaller mm it buys is itself security. Revisit only on measured memory - pressure, never for this. +- **Ordinary pages are 4 KiB.** The approved memory migration separates + reservation, commitment and population; large mappings do not require + physically contiguous backing. This supersedes the earlier 2 MiB-only rule. - **Invalid handles keep killing the caller.** A process naming a handle it does not hold is buggy or probing, and the kill stops handle-guessing cold. Compatibility lives in `sdk/libc`, which tracks its own fds. diff --git a/issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md b/issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md index 1c763d2572f..a4e609134e0 100644 --- a/issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md +++ b/issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md @@ -1,29 +1,41 @@ --- -status: none -kind: rejected +status: open +kind: defect opened: 2026-09-29 --- # The loader never sets the firmware's memory-overwrite request -At `Ubuntu-6.8.0-142.142`, the x86 EFI stub runs -`efi_enable_reset_attack_mitigation()` on every boot -(`drivers/firmware/efi/libstub/x86-stub.c:971`, -`CONFIG_RESET_ATTACK_MITIGATION=y`, config line 2457), which sets -`MemoryOverwriteRequestControl`=1 under vendor -`e20939be-32d4-41be-a150-897f85d49829` -(`drivers/firmware/efi/libstub/tpm.c:20-21`) so firmware wipes RAM -on the next boot after an unclean reset, where the firmware already defines -the variable (`tpm.c:36-40`). `loader/src` writes no variable under this -GUID. +Owner decision, 2026-10-17: request supported firmware memory wiping after an +unexpected reset, accepting the loss of unsaved crash evidence. This replaces +the earlier decision to preserve RAM for crash records. Do not clear a request +left by another OS to preserve logs, or exempt a diagnostic RAM region from +wiping. Saved diagnostics remain useful; reset-surviving RAM is not a required +source of evidence. -**Declined** (owner, 2026-10-03): **"Keep crash records"**. ToyOS does not ask -the firmware to wipe memory at reset; crash records survive a reset in RAM -(`issues/toyos-explains-itself.md`). So ToyOS stays below Linux on -this one line of -`issues/the-kernel-is-at-least-as-secure-as-linux-on-every-machine-toyos-supports.md`: -whoever resets a ToyOS machine into a boot medium of their own can read what -the last boot left in RAM. +The loader owns firmware access before `ExitBootServices`. Implement the +platform's supported memory-overwrite request and applicable protection against +unauthorized clearing. Unsupported firmware and failed requests must be reported +accurately, not represented as protected. This is reset-attack mitigation, not a +guarantee against every physical memory attack or power-loss scenario. -A request already set by another system is a different matter: -`issues/a-memory-overwrite-request-ubuntu-left-set-stays-set-under-toyos.md`. +`loader/src` currently does not handle `MemoryOverwriteRequestControl` under +GUID `e20939be-32d4-41be-a150-897f85d49829`. The existing T14 capture under +Ubuntu `6.8.0-142-generic` found the request value 1 and its lock value 0 +(efivarfs bytes `07 00 00 00 01` and `07 00 00 00 00`, respectively). Thus an +inherited request is evidence of a firmware interface, not evidence that ToyOS +sets it or that this firmware wipes RAM on each relevant reset path. + +Implementation and firmware behavior remain unverified. Use the governing +firmware specification for request and lock semantics; do not assume setting a +variable proves the wipe occurred. + +**Exit:** +- The loader requests wiping through the supported firmware interface, respects + its lock semantics, and never clears it merely for crash-record retention. +- Host tests cover supported, absent, locked and failed firmware responses. +- Relevant firmware tests check request state; batch a non-secret memory-marker + reset test on supported benches to verify actual wiping. Record the machine, + firmware and reset path. Unsupported or unverified paths remain explicit. +- Diagnostics and reset tests accept that unsaved RAM records can disappear; + no crash-retention requirement disables this mitigation. diff --git a/issues/the-machine-updates-itself-without-ubuntu.md b/issues/the-machine-updates-itself-without-ubuntu.md index aebe610eb48..ec3dba7e91a 100644 --- a/issues/the-machine-updates-itself-without-ubuntu.md +++ b/issues/the-machine-updates-itself-without-ubuntu.md @@ -12,6 +12,66 @@ playground, so a broken driver may wipe that NVMe and the next install writes it again. Updates are `ssh update < image` — a normal `exec`, the image on stdin — and the machine installs nothing the owner did not sign. +## Finished-distro update policy + +Owner decision, 2026-10-18: personally modified ToyOS system code is maintained +as the user's own build, with upstream merges and rebuilds through ordinary +development tools. The updater need not carry local source modifications across +distro updates. This does not change preservation of settings, data or installed +apps. Custom-build update-source selection and return to distro builds remain +to design under the existing image-verification and trust authority rules. + +Owner decision, 2026-10-18: maintain one current stable release. Ongoing +security fixes target it; users must upgrade to remain supported. +Release cadence and transition communication remain product requirements to +refine; this does not change postponement or the no-forced-restart policy. + +Owner decision, 2026-10-20: fix forward. No OS downgrades or rollbacks in the +current release scope, including automatic fallback to an older OS after an +activated update fails to boot. Ship a newer fixed version. This supersedes +the older-image recovery direction and the fallback target in stage 1 below. +That stage records prior implementation evidence, not the newly approved end +state. Reconcile loader selection, activation and version-floor rules; do not +claim the current fallback behavior satisfies this decision. Safe staging +remains required. A failed download or incomplete staging must not damage the +current installation. Owner confirmation, 2026-10-20: a boot-medium workflow +that applies a newer fixed release while preserving data remains deferred. +Manual rescue or fresh installation is acceptable initially after an unbootable +update. This does not authorize erasing data or claim fresh installation +preserves it. Implementation is not commissioned by this record. + +Owner decision, 2026-10-16: prepare verified OS updates automatically and +activate them at the next normal reboot, with an option to postpone. Never +force a restart. This is the product target, not a change to the current +development deployment loop or a claim that automatic fetching exists. + +Reuse the signed-image and inactive-slot installation path. Fetching, +scheduling and the user's choice belong in userland. The current `update` +command installs and selects the new slot in one operation; preparation and +next-boot selection must support postponement coherently, including a reboot +or interrupted download. A downloaded image is not an activated update. +Application updates remain a separate policy. + +## Authority to change OS trust + +Owner decision, 2026-10-20: first-release installation may require documented +one-time firmware trust setup. Verified boot must be active afterward; +unchanged factory trust settings are not a release gate. Validate enrollment, +key ownership and recovery on both benches. This installation allowance does +not change the separate authorization policy below. + +Owner decision, 2026-10-16: an explicitly authorized administrator may change +which OS signing keys the machine trusts remotely. Local presence is not a +ToyOS policy requirement for that operation. This authority is distinct from +permission to install an ordinary update signed by an already-trusted key; +remote login alone grants neither. + +Enrollment, key replacement, firmware support and coordination with encrypted +storage's key-release policy remain design work. Changing OS trust does not +itself grant recovery of a user's locked storage. A replacement OS can observe +data when subsequently unlocked; do not promise isolation from an OS the +machine has been authorized to run. + ## Stage 1 — slots, signatures and `update`, proven in QEMU (done) - **A signed image** (`toyos-update`): a header naming a monotonic version and @@ -38,6 +98,18 @@ stdin — and the machine installs nothing the owner did not sign. ## Stage 2 — the T14 installs ToyOS on its NVMe +Owner decision, revised 2026-10-18: the first-release installation medium boots +into ToyOS's desktop. A desktop entry opens a graphical installer, replacing +the earlier console/CLI requirement. It offers independent language, regional +format, keyboard and time-zone selection, also available later in settings. +Installation and first-account +setup must work offline from a small base image; optional applications are +downloaded separately. + +Owner decision, 2026-10-18: the boot-medium workflow for reinstalling a broken +system while preserving existing user data is deferred beyond the first +release. Safe installation and the update-failure contract remain required. + The machine boots the stick and installs onto its own NVMe, then takes `ssh t14 update < image` for every change after. It waits on stage 5 of `issues/the-loader-does-only-what-must-precede-the-handover.md`, diff --git a/issues/the-power-broker-authority-with-a-human-in-the-loop.md b/issues/the-power-broker-authority-with-a-human-in-the-loop.md index f5e4da0ddbe..8a4977cebc4 100644 --- a/issues/the-power-broker-authority-with-a-human-in-the-loop.md +++ b/issues/the-power-broker-authority-with-a-human-in-the-loop.md @@ -28,6 +28,31 @@ so the native shape is smaller: a connection, so a crashed registrant releases its inhibit by the same teardown that releases everything else. +## Whole-machine sleep + +Owner decision, 2026-10-17: the first release targets ordinary sleep with the +session retained in powered RAM. Defer hibernation and its encrypted session +image and authenticated-resume design. Ordinary sleep retains sensitive memory; +it does not cryptographically lock personal storage. This is separate from +idle CPU core sleep. Safe device suspend/resume and platform sleep support +remain implementation work. + +## Automatic sleep + +Owner decision, 2026-10-18: lid-close sleep behaviour is configurable, +including whether an app's keep-awake request may prevent it. The default and +setting scope remain to define; neither precedence is mandated as the sole +behaviour. This does not change the separate idle-sleep request rules below. + +Owner decision, 2026-10-16: applications may temporarily prevent automatic +whole-machine sleep while doing work without separate per-app approval or a +prompt for every request. Show the requesting application and its stated +reason, and let the user override the request. Tie each request to its +connection lifetime so disconnect releases it. The request does not grant +`POWER`, prevent idle CPU cores from sleeping, or authorize control over +shutdown or reboot. The broker protocol, override lifetime and whole-machine +suspend/resume implementation remain design work. + Unstaffed until the owner opens it; sequenced naturally with the userland/ product era. What must not happen meanwhile is the accident this track exists to prevent: `POWER` spreading to more manifest rows. diff --git a/issues/the-scheduler-and-the-clocks-never-talk.md b/issues/the-scheduler-and-the-clocks-never-talk.md index c94f808c109..badbc626c95 100644 --- a/issues/the-scheduler-and-the-clocks-never-talk.md +++ b/issues/the-scheduler-and-the-clocks-never-talk.md @@ -6,26 +6,30 @@ opened: 2026-08-16 # The scheduler and the clocks never talk -Queued track from the 2026-08-16 owner conversation on scheduler direction; the -furthest out of the set. +## Combined scheduler, audio and idle direction -Two couplings every production scheduler has and ours lacks: +Use per-CPU EEVDF job groups and bounded realtime audio. No EDF/CBS admission +or per-stream CPU reservation. Focus changes responsiveness, not sustained +shares; equal-weight jobs compete across users without an outer user hierarchy. +Independent jobs need launch authority; helpers share their existing job. -- **Frequency (DVFS)**: the scheduler knows every core's utilization and nobody - else does, so it should feed whoever sets clock speeds (the schedutil - arrangement) — including the race-to-idle question of whether finishing fast - and sleeping beats pacing slow. -- **Idle-state awareness**: a deeply sleeping core takes real microseconds to - wake. A latency-sensitive wake should prefer a shallow-idle core; a - throughput task can pay to wake a deep one. +Accept new audio streams best-effort. Genuine audio overload may cause dropouts; +a client missing a block contributes silence without delaying other clients. +Grant realtime authority only to the relevant workers, not every thread in an +application. Preallocate realtime work and avoid blocking/allocation in callbacks. +Owner-keyed abuse handling remains distinct from legitimate aggregate overload. -Both wait for an AML interpreter -(`issues/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md`), -because the kernel reads no C-state on metal and chooses no P-state: it -declares HWP's bounds (`kernel/src/arch/x86_64/control_regs.rs`), and the CPU -chooses within them. -Filed so the placement track (see `placement-has-no-migration-cost-or-wake-affinity.md`) -leaves room for an idle-state input when it designs wake placement. +Idle selection uses predicted idle duration, known next wake and permitted exit +latency. Placement considers wake cost without sacrificing ordinary progress. +Run batch work promptly with no power target; let idle cores sleep. Detailed +frequency optimization is later work. Scheduling, timer programming and the idle +entry recheck must prevent lost wakeups; firmware latency is not a hard guarantee. + +Reconcile the old CPU/idle drafts with this direction. Complete kernel scheduling, +then realtime authorization/limits and the soundserver client path, then idle-state +integration. Validate accounting on the host and actual wake/audio behavior on +metal in focused, batched runs. Do not require a new latency-hint API before its +first caller. Existing model results below do not establish hardware performance. ## Realtime exhaustion (owner decision J2, 2026-10-20; stage 4) diff --git a/issues/the-supervisor-is-host-tested-and-owns-the-stop.md b/issues/the-supervisor-is-host-tested-and-owns-the-stop.md index dcba3a744c8..42db47275f1 100644 --- a/issues/the-supervisor-is-host-tested-and-owns-the-stop.md +++ b/issues/the-supervisor-is-host-tested-and-owns-the-stop.md @@ -9,6 +9,33 @@ opened: 2026-09-28 Held by the orchestrator. Stage 1 landed before the latency work (`issues/toyos-beats-linuxs-latency-on-the-t14.md`; owner, 2026-10-03). +## First-release failure recovery + +Owner decision, 2026-10-17: service failures may interrupt the affected feature. +Recover safely and report failures; uninterrupted recovery is not a general +first-release requirement. Restarting a process does not restore its previous +connections, streams or client state. Keep bounded restart attempts and make +exhaustion visible. Reconnection is protocol-specific; retry only when proven +safe, and report uncertain outcomes rather than replaying arbitrary operations. +The filesystem contract is in +`issues/ipc-rings-do-not-yet-make-filesystem-io-concurrent.md`. + +Device reuse requires safe cleanup and reinitialization; not every device can +recover. Owner decision, 2026-10-17: if a failed device is safely contained but +cannot be restored, leave it unavailable, report the failure and let the user +choose when to reboot. Do not reboot automatically for that contained failure. +This does not settle failures whose effects cannot be contained or change the +separate whole-machine watchdog policy. + +Owner decision, 2026-10-17: first-release automatic recovery covers process +crashes, not general detection and restart of hung services. Bound waits and +report their failures; provide an authorized manual restart path for a stuck +service. A timeout alone does not authorize killing or restarting its process. +Defer general service-health monitoring and automatic hang recovery. Existing +protocol-specific timeout handling and whole-machine freeze protection remain +separate. The manual restart path must use the same safe teardown and device +reuse rules as crash recovery. + ## Stages Every guest test this track names is registered. A deleted test covers diff --git a/issues/there-is-no-wifi.md b/issues/there-is-no-wifi.md index d284a231280..2e9e1c25ed0 100644 --- a/issues/there-is-no-wifi.md +++ b/issues/there-is-no-wifi.md @@ -358,7 +358,11 @@ machine, the disk taken out, or a program holding the disk's claim or serving the file. With it they join that network, decrypt every handshake they saw under PSK, and hold the passphrase wherever else it is used. - **Owner:** the orchestrator. -- **Exit:** a ToyOS key store, a concept the owner rules on. +- **Exit:** protected credential storage with a defined Wi-Fi ownership and + unlock policy, including availability before login and migration from plain + text. The local app-credential facility approved in + `issues/storage-is-layers-and-a-role-is-a-filesystem.md` does not settle those + machine-service requirements. **A network's Transition Disable mark lasts only the boot until W11.** From W4's landing a reboot loses every mark. Until a network's first SAE join of diff --git a/issues/toyos-builds-itself.md b/issues/toyos-builds-itself.md index eb7dab5e8fb..05df046bd12 100644 --- a/issues/toyos-builds-itself.md +++ b/issues/toyos-builds-itself.md @@ -13,6 +13,24 @@ with lld, one build of one fork, `ToyOSOrg/llvm-project`. The C library stays `sdk/libc`, ours. Each stage lands on x86-64 first and on AArch64 one step behind, on `issues/toyos-runs-on-arm64.md`'s track. +Owner release-scope decision, 2026-10-18: reproducible OS builds are required +for release one. Published source and specified toolchain/inputs must reproduce +distributed system contents, excluding signatures and machine-specific +installation data. Define the payload boundary and repeatable comparison. +Owner refinement, 2026-10-18: rebuilding and modifying the Rust and C/C++ +compiler toolchain within ToyOS also gates release one, including its build +dependencies. The approved downloaded binary seed remains allowed. The existing +M5 fixed-point target remains on the roadmap; specify compiler reproducibility +acceptance separately from the now-required ability to rebuild the compilers. + +Owner release-performance requirement, 2026-10-18: ToyOS and toolchain builds +must be at least as fast as Linux on the same bench hardware with equivalent +inputs, settings, cache state and power/thermal conditions. Define repeatable +comparisons that account for measurement noise. The earlier make-it-work-first +engineering sequence remains; it is not a waiver of the release performance +requirement. Background builds intentionally slowed for video are assessed +separately from controlled throughput. + - **M2 — clang and lld as a package inside ToyOS.** clang, lld and their runtime built *for* ToyOS on the host and installed by `/system/bin/pkg`; `clang hello.c && ./a.out` works in the guest. *Exit*: diff --git a/issues/toyos-explains-itself.md b/issues/toyos-explains-itself.md index ab2bb2b0ab5..2629195ee1f 100644 --- a/issues/toyos-explains-itself.md +++ b/issues/toyos-explains-itself.md @@ -15,13 +15,42 @@ contention. Each pillar's own track carries its steps and its exits; this track holds the counters and sizes pillars, which no other track does. -## The owner's rulings (2026-10-03) +## The owner's rulings +- **AI-assisted troubleshooting** (2026-10-18): the owner expects an agent to + perform troubleshooting. Diagnostic and repair tools must be usable by an + ordinary authorized program, under the same capability rules as any other + program. This grants no special AI authority or automatic diagnostic upload. + Owner refinement, 2026-10-18: cloud AI is sufficient; offline AI and a local + model/inference runtime are not required. Local diagnostic and recovery tools + must remain usable without the agent, with explicit report export for analysis + elsewhere. Agent delivery and concrete failure paths remain design work in + the ordinary permission model; no bundled agent is + commissioned by this direction alone. + Owner refinement, 2026-10-20: files, terminals and diagnostic APIs suffice + for first-release development and troubleshooting. General desktop + automation is deferred; ordinary user-facing graphical controls remain. + +- **Basic graphical controls for release one** (2026-10-18): users must be + able to inspect resource use and stop apps through graphical system controls. + Detailed profiling may remain in developer tools. Respect inspection and + termination authority across user sessions; define metrics and overload + usability under pressure without requiring detailed profiling in the GUI. +- **Local reporting only for release one** (2026-10-18): diagnostics remain on + the machine unless the user explicitly exports and shares them. No automatic + crash reporting, including opt-in uploads, is required for the first release. + Owner refinement, 2026-10-18: smaller crash reports by default; capture a + program's memory only when detailed troubleshooting is explicitly enabled. + Smaller reports/logs may still contain sensitive data. Exact contents, opt-in + scope, retention and export/access controls remain to design. This does not + override the reset-memory-wiping rule below. - On the diary's reader: "its obvious that we want to be able to understand kernel metrics from within toyos ... thats an important and productive tool that should be shipped with toyos." -- **"Keep crash records"**: ToyOS does not ask the firmware to wipe memory at - reset, and crash records survive a reset in RAM +- **Memory wiping takes priority** (2026-10-17): request supported firmware + wiping after unexpected resets, accepting loss of unsaved crash records. + This replaces the earlier RAM-retention decision; diagnostics must not + disable or bypass the mitigation (`issues/the-loader-never-sets-the-firmwares-memory-overwrite-request.md`). - **"Only with permission"**, the option he chose: "A program needs a permission to read counters; the revealing ones (power, per-device diff --git a/issues/toyos-has-a-desktop.md b/issues/toyos-has-a-desktop.md index 86ad6691a5a..8cb20b64835 100644 --- a/issues/toyos-has-a-desktop.md +++ b/issues/toyos-has-a-desktop.md @@ -23,6 +23,12 @@ Owner rulings, 2026-09-26: - **Rendering:** CPU rendering is the first-class path; there is no CPU Vulkan. Later, a display-only driver for the T14's Iris Xe (Gen12 Xe-LP), then a Vulkan driver so wgpu apps get the GPU. + Owner release-scope ruling, revised 2026-10-18: one active monitor with + software rendering. Userland display-control drivers are allowed for refresh + synchronization, page flips and display power/resume, superseding GOP-only + output. GOP boot display and unaccelerated virtio-gpu remain supported. GPU + rendering and multi-monitor support remain later work; this does not authorize + hardware video decoding. Software-rendered Chromium and sleep/resume still need feasibility evidence. - **Window management:** both floating and tiling. - **Look and feel:** the familiar style every desktop shares — a taskbar with pinned and running apps together, one start menu with search, clear window @@ -38,6 +44,59 @@ Owner rulings, 2026-09-26: competitor to COSMIC, not a port of it. `cosmic-text` (MIT OR Apache-2.0) remains in use. +## Background work + +Owner release-scope decision, 2026-10-18: a desktop/display-service crash may +end the affected desktop session, potentially losing unsaved work. Application +reconnection and recovery across a desktop restart are deferred. Safe session +cleanup and reporting remain required; failure of the desktop alone is not +authorization to reboot or terminate unrelated work. Recovery controls when the +desktop is unavailable remain to design. + +Owner decision, 2026-10-16: programs may continue running without windows, +including after their last window closes, without separate background +permission. This applies to CLI jobs too; window count does not determine +execution authority. Make running applications and background work visible, +with clear controls to stop them. Closing a window and quitting an application +are distinct actions. Application resource accounting and existing capability +limits still apply; background execution grants no additional access. + +Owner decision, 2026-10-16: an installed application needs explicit user +approval to start automatically at sign-in. Remember the choice and let the +user change it in settings. Installation alone does not approve startup. +Requests and stored choices belong in the trusted userland permission and +session-launch path; the package manifest does not itself grant authority. +This policy does not govern the image's system services. + +Desktop sign-out ends that session's work under +`issues/a-user-is-a-home-tree-and-a-login-row.md`. Terminal job lifetimes and +the concrete app-wide quit mechanism still need design; allowing background +execution does not promise that every job survives those events. + +## Desktop notifications + +Owner decision, 2026-10-16: apps need approval before showing desktop +notifications. Ask through the common runtime-consent path and remember the +decision; a recorded denial does not trigger repeated prompts. The user can +change it in settings. Messages inside an app's own windows are unaffected. +Use the shared saved-decision lifecycle for verified updates and uninstall. + +## Camera and microphone privacy + +Owner decision, 2026-10-16: camera and microphone are separate per-app +permissions. Ask through the common runtime-consent path and remember each +approval until removed; do not ask again for every recording session. Removing +saved approval affects future direct grants and does not stop already-authorized +recording, following +`issues/permissions-and-capabilities-need-one-runtime-contract.md`. +Use its verified-update and uninstall rules for saved decisions too. + +The desktop shows which app is actively using each sensor, including background +use. Activity must come from the service enforcing capture access, not from an +app's claim to be recording or merely having saved permission. The capture and +activity-reporting protocols remain design work. This does not change the +separate per-session selection rule for screen sharing below. + ## Why CPU rendering, not a CPU Vulkan A 2026-09-26 probe (`../toyos-uiprobe`, cut from `main` at `03b1b4db`, since @@ -98,26 +157,46 @@ until the Rust target is upstream. 2. **A shell**, written in iced: the compositor's window management for floating and tiling with edge snapping; a taskbar or panel with pinned and running apps; a start menu or launcher with search. -3. **Core apps**: files, terminal, editor and settings. The login greeter +3. **Core apps**: files, terminal and settings. Owner refinement, 2026-10-18: + the minimal base omits a text editor and SSH, and includes graphical package + management as well as its CLI. Optional applications are downloadable; + the login greeter waits on the users track (`issues/a-user-is-a-home-tree-and-a-login-row.md`). 4. **Compositor services**: clipboard, drag and drop, notifications and - screenshots. Clipboard reads and screenshots are privileges granted under - the package track's request ∩ grant ∩ ceiling rule + screenshots. Owner decision, 2026-10-16: an ordinary application receives + clipboard contents when the user pastes them; focus alone does not authorize + a read. Background reading, including by clipboard managers, needs separate + approval under the package track's request ∩ grant ∩ ceiling rule (`issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md`). + The compositor's paste shortcut and separate clipboard-watcher connection + are foundations; trusted paste-menu actions and toolkit integration still + need a design. An application claiming a paste action is not proof of user + intent. Screenshot access also follows the package permission rule. + Owner decision, 2026-10-16: ordinary screen sharing and recording require + the user to choose a window or display through trusted UI each time sharing + starts. Grant capture of only that target for that sharing session; access + ends when sharing stops. Do not turn a prior session's approval into + remembered permission to start another. The capture protocol, target + lifetime, buffer ownership and stop semantics remain design work; this + ruling does not implement them or decide unattended remote access. 5. **Fractional scaling**: `issues/the-desktop-draws-at-the-panels-scale.md`. -6. **Accessibility**: accesskit, keyboard-only navigation, high contrast. +6. **Accessibility**: owner decision, 2026-10-18: keyboard-only navigation is + required for the first release. Screen-reader support, adjustable text size + and other accessibility features are outside that initial requirement. + Accesskit and high contrast remain later candidates, not release blockers. 7. **Input**: the T14 touchpad (`issues/the-t14-touchpad-is-i2c-hid-and-unbuilt.md`), scrolling and gestures, and input methods building on `toyos-keymap`. 8. **Laptop basics**: battery, lid, brightness and volume keys, suspend, - Wi-Fi status and multiple monitors. + Wi-Fi status; multiple monitors deferred beyond the first release. 9. **One visual design**: theme, icons (licence-clean sources) and spacing. 10. **A performance budget**: 60 fps at the T14's resolution with CPU rendering, measured by a test. 11. **Screenshot tests**: golden images per app. -12. **GPU**: a display-only Xe-LP (Gen12 Xe-LP, PCI ID 8086:9A49 on the - tree's own T14) driver, then a Vulkan driver so wgpu apps get the GPU. +12. **Display control and later GPU rendering**: display-only drivers may + support first-release refresh and power management. Vulkan and accelerated + rendering remain beyond the first release. ## Standing diff --git a/issues/toyos-has-its-own-allocator.md b/issues/toyos-has-its-own-allocator.md index a6a7a842f97..a5f25806997 100644 --- a/issues/toyos-has-its-own-allocator.md +++ b/issues/toyos-has-its-own-allocator.md @@ -14,12 +14,13 @@ std's front, for programs, comes later, after it is measured against the `dlmalloc` ToyOS's std allocates with (`sdk/std/sys/alloc.rs`). The 2 MiB heap-growth stall is fixed now, on `dlmalloc`, and waits for neither front. -The stall: when the kernel heap grows, `dlmalloc` calls -`KernelPageSource::alloc` (`kernel/src/mm/alloc.rs`) inside -`ALLOCATOR.dlmalloc.lock()`, and `pmm::alloc_page` (`kernel/src/mm/pmm.rs`) -scans the page bitmap and zeroes the whole 2 MiB page before it returns, so -every CPU that allocates from the heap meanwhile spins on its lock. How long -that takes on the T14 is unmeasured. +**Owner reaffirmed, 2026-10-22:** prioritize the backing-memory migration +(4 KiB ordinary pages, noncontiguous physical backing and lazy population +under the agreed commitment contract) and eliminate unbounded userland heap +spinning before evaluating the replacement heap's performance. Carry the lock +fix in the direct migration where practical; no temporary allocator or bridge +is required. Preserve ordinary Rust allocation contracts. The replacement +remains ToyOS-owned, with the kernel and std fronts above. **Ruled** (owner, 2026-10-04, "Yes, that bar"): "Within 10% of mimalloc for time and peak memory on a pinned benchmark set; faster than dlmalloc diff --git a/issues/toyos-hosts-hardware-accelerated-virtual-machines.md b/issues/toyos-hosts-hardware-accelerated-virtual-machines.md new file mode 100644 index 00000000000..f7e582cf0bf --- /dev/null +++ b/issues/toyos-hosts-hardware-accelerated-virtual-machines.md @@ -0,0 +1,22 @@ +--- +status: open +kind: track +opened: 2026-10-16 +--- + +# ToyOS hosts hardware-accelerated virtual machines + +Owner decision, 2026-10-16: hosting other operating systems, such as Linux, +in hardware-accelerated virtual machines is a later product goal. Native +ToyOS applications remain the priority. This does not schedule implementation +now or justify speculative virtualization hooks in current work. + +The kernel/userland boundary, supported hardware and guests, VM interfaces, +device models and resource isolation need a concrete design before +implementation. Apply the existing userland-first and capability principles; +no particular hypervisor implementation or API is selected. + +ToyOS running as a guest is owned by +`issues/toyos-runs-in-any-open-source-hypervisor.md`. Native Linux binary +compatibility remains a separate deferred target under +`issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md`. diff --git a/issues/toyos-runs-in-any-open-source-hypervisor.md b/issues/toyos-runs-in-any-open-source-hypervisor.md index b6beda4b991..bff6d7df3a0 100644 --- a/issues/toyos-runs-in-any-open-source-hypervisor.md +++ b/issues/toyos-runs-in-any-open-source-hypervisor.md @@ -6,6 +6,9 @@ opened: 2026-10-12 # ToyOS runs in any open-source hypervisor +Hosting guest operating systems on ToyOS is a separate later target in +`issues/toyos-hosts-hardware-accelerated-virtual-machines.md`. + The owner's aim, as the orchestrator briefed this audit: ToyOS runs in any popular open-source virtual machine — QEMU under KVM, HVF or TCG, Cloud Hypervisor, VirtualBox, bhyve and crosvm — with QEMU still the launcher and the diff --git a/issues/whether-pkg-alone-writes-apps.md b/issues/whether-pkg-alone-writes-apps.md deleted file mode 100644 index 8f442509735..00000000000 --- a/issues/whether-pkg-alone-writes-apps.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -status: owner -kind: question -opened: 2026-10-09 ---- - -# Whether pkg alone writes /apps - -Two of the owner's rulings in -`issues/a-package-is-a-directory-under-apps-and-the-installer-is-a-program.md` -pull against each other once a package's own directory is read-only to it: - -- **"The installer is an ordinary program … with no authority a shell does - not have"**: `pkg` writes under `/apps` because `/apps` is writable to it. -- **"`/apps/` is immutable by stage-then-commit … nothing writes a - committed package"** (2026-10-02). - -Today every row the image declares, `pkg` and the shell among them, holds -`/apps` read-write (`toyos_manifest::whole_tree`), so a shell and everything -it starts can rewrite an installed package. An installed package itself -holds its own directory read-only (`toyos_manifest::Program::view`). - -## The question - -Does `pkg` alone write `/apps`, which gives the installer an authority a -shell lacks, or does every row that may start `pkg` keep `/apps` writable, -which leaves a committed package writable by the shell? - -## Exit condition - -The owner's answer. If `pkg` alone writes `/apps`, every other declared row's -view holds `/apps` read-only, which needs the per-row views of -`issues/every-program-sees-only-the-files-it-was-given.md` stage 2.