From 4398eb7cc43d3269d5c624598448cc7288bc41df Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Sat, 8 Aug 2026 11:13:20 +0100 Subject: [PATCH] docs: scope the bounds track's unattended run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six steps an agent can execute: reclamation, the bounds build check, and the four user-space USB/xHCI bounds where the hardware already reports the number we guessed. Deliberately excluded: the authorisation gate and moving the device inventory to the manager. Both decide whether the OS is secure and both are a direction rather than a specification — what a device capability is, which syscalls change, what replaces device_claim for its seven callers. They want a design session, not an agent. Three open questions are written down rather than guessed: device_enumerate most likely narrows to the firmware-discovered roots rather than retiring (the manager cannot ask itself for the PCI host bridge); a manager restart has no re-enumerate handshake, so it comes back blind while its buses live; and "add adversarial tests" is not executable until the attacks are named. --- docs/bounds-track-plan.md | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/docs/bounds-track-plan.md b/docs/bounds-track-plan.md index a8a5017..8fd5754 100644 --- a/docs/bounds-track-plan.md +++ b/docs/bounds-track-plan.md @@ -3,6 +3,74 @@ *Plan, 2026-08-08. Follows [fixed-bounds-audit.md](fixed-bounds-audit.md) (235 ceilings, 139 on quantities we do not choose) and the AMD Ryzen that found the first one.* +--- + +## Live state — the unattended run + +*This table is the progress view. It is updated at the end of every step, before the +next one starts.* + +| Step | What | State | +|---|---|---| +| L1 | Reclamation: a dead task's registrations die with its claims | not started | +| L2 | Bounds build check + allowlist; declare what we have already touched | not started | +| L3 | xHCI: slot count from `HCSPARAMS1.MaxSlots`, not 8 | not started | +| L4 | USB: configuration descriptor sized by `wTotalLength`, not 512 | not started | +| L5 | USB: interfaces from the descriptor, and the misattributed-endpoint bug | not started | +| L6 | xHCI: a failed `allocateDevice` stops leaking an enabled slot | not started | + +**Suite:** 115/115 at the start of the run. +**Branch:** `claude/bounds-track`. + +### What this run deliberately does not touch + +Phases 2 and 3 below — the authorisation gate and moving the inventory to the device +manager — are **out of scope for unattended work**. They decide whether the OS is +secure, and they are currently a direction rather than a specification: what a device +capability *is*, which syscalls change, what replaces `device_claim` for its seven +callers, how a driver spawned bare behaves. Those want a design session, the way +`/protocol` had one. + +Also out of scope: anything touching `maximum_device_resources` (a wire struct, so a +trust-boundary change, not a resize), and the non-device bounds the audit found in FAT, +the VFS, logger, init, display and boot. + +### Open questions this run must not answer on its own + +Recorded here rather than guessed. If a step runs into one, it stops and writes the +question down instead of inventing an answer. + +1. **`device_enumerate` probably narrows rather than retires.** The device manager + calls it to find `pci_host_bridge` nodes — it cannot ask itself. The likely shape is + that the kernel keeps the *firmware-discovered roots* (which by principle 5 it holds + for real reasons, since they come from ACPI rather than a driver's say-so) and + everything a driver registered lives in the manager. Not decided. +2. **A device-manager restart has no re-enumerate handshake.** If only the manager + dies, the buses are alive and never re-send `child_added`, so a restarted manager + comes back blind. The manager is restartable by design; nothing implements this. +3. **Which adversarial tests I1–I3 need.** The audit's six real defects were all found + by asking what an attacker would do, and the suite had never asked. "Add adversarial + cases" is not executable until the attacks are named. + +### Working rules for the run + +- Work in `/Users/danielsamson/Gitea/daniel/danos` (not a worktree), on + `claude/bounds-track`. +- **Every step lands with a test that fails before the fix**, verified by temporarily + restoring the old behaviour and watching exactly the intended assertion flip. A test + that passes both ways is not a test. +- Full QEMU suite green before each commit. Never run two suites at once — check + `pgrep -f qemu_test.py` first; a second concurrent run produces false triple faults + because both share `zig-out`. +- Check at least 60 GiB free before starting a suite. +- Commit with `git commit -F `, never `-m` (a backtick in a message is executed + by the shell and silently eats a word). No `Co-Authored-By` trailers. +- Update the Live state table **before** starting the next step. +- If a step needs a decision that is not written down here, stop, add it to the open + questions above, and move to the next step. + +--- + ## The principles this is derived from 1. **danOS is a microkernel.** Minimise what the kernel is responsible for; move