NØNOS

Roadmap

The next six releases.

Gates, not dates. A release ships when its gate passes, and the gate is the only part that is fixed.

v0.9.3

Proof and numbers

real IPC cycle counts from named hardware on the published page, the authority theorem closed with no hand-waves in its chain, and the matrix carrying at least one row submitted by someone outside the project.

v0.9.4

Concurrent

a four-core boot surviving soak on real silicon, the refinement walk public, the installer writing a disk and proving by read-back what it wrote, and a file written on one boot and read on the next.

v0.9.5

Composed

a machine NONOS installed verified from its receipt by someone who was not in the room, a capsule published by an outside developer installed on a machine we do not control, and the AML corpus passing at a published rate.

v0.9.6

Power

a laptop on the matrix powers itself off from its own menu, reports a battery that falls while unplugged and rises while charging, throttles instead of cooking under sustained load, and updates to the next release without a person watching it.

v1.0-rc

Parity

an ARM board boots signed NONOS and verifies on the public page exactly as an x86_64 machine does, and a laptop closed at night is working the next morning with its resume attested.

v1.0

The machine

nothing in the release requires you to believe us, and one of us has already lived on it for a month in public.

Nothing here requires you to believe us.

Every release ships its attestation surface, its reproducibility result and, from v0.9.3, its measured performance. The day table is republished with every release, with the same rows and the state moved.

v0.9.3v0.9.4v0.9.5v0.9.6v1.0-rcv1.0

Scroll, or wait: the film plays on its own.

Six releases of the operating system, NOX Shield reaching mainnet, and the marketplace opening to developers outside the project.

The destination is a machine somebody uses. Not a demonstration, not an image you boot once to look at, not a research kernel with a screenshot. A laptop you install NONOS on, close the lid on, open the next morning and work on, where every byte that ran was verified before it ran.

That is the only claim in this document that matters. Everything below is the path to it, in the order the dependencies allow, and the evidence that says we got there.


How to read this

Every section states four things: what exists today and how you can check it, what is missing and precisely why, the work in the order it has to happen, and the artifact that proves it is done. Where the truth is a range it is written as a range. Where something is deferred it is named here rather than discovered later.

Nothing in the "today" columns is aspirational. All of it is verifiable against v0.9.2 as published.

A date is a promise about a calendar. A gate is a promise about a result.

There are no dates in this document, and that is deliberate rather than evasive. A date is a promise about a calendar. A gate is a promise about a result, and the gates here are specific enough that nobody has to wonder whether one was met: a four-core soak on real silicon, a file written on one boot and read on the next, a laptop that powers itself off, a stranger verifying a receipt from a machine we never touched. Dated roadmaps get met by moving the definition of done. This one cannot be, because the definition of done is the only part that is fixed.

What is fixed instead is the order, and the order is derived from dependencies that are stated and can be argued with. Releases ship when their gate passes and not before, and every long item carries a signal that says publicly whether it is moving.

Working rules

Full arcs, never partials

An arc opens when the previous one has public evidence. A feature that boots in bring-up and ships disabled is not finished, and it is listed as unfinished rather than as a highlight.

Evidence, or it did not happen

Every release ships its attestation surface, its reproducibility result, and from v0.9.3 its measured performance. A claim without a way to check it does not go in a release note.

Both architectures ride the same train

Shared code goes through the arch trait. From v1.0-rc, a feature is done when it is done twice, or the tree carries a dated exception explaining why not.

Population decides driver order

Once the hardware matrix exists, drivers are fixed in the order people actually boot NONOS on them.

Manifest changes batch into ceremonies

Anything touching a signed manifest costs a full enrollment: builder run, owner ceremony, ledger restamp. Two ceremonies are planned in this window and work that needs one waits for it rather than triggering a third.

Gates, not dates

A release ships when its gate passes. Until then it is not late, it is not finished, and those are different words. The weekly signals are what tell anyone watching which of the two it is, without anyone having to ask us.

One shape at a time

Where two designs could both work, we ship one and delete the other rather than keeping a flag. Two shapes mean two verifying keys, double the audit, and a switch that can choose wrong.

We do not schedule discovery

No item enters a release as "and then we find out". Before anything is dated it is decomposed into steps, each step has an observable that says whether it worked, and the whole sequence has a signal that moves weekly whether or not the feature is finished. Where the unknown is somebody else's hardware or firmware, the unknown becomes a corpus, and the corpus becomes a percentage. Every decomposition is written into this document, because a plan that only exists in the heads of the two people executing it is not a plan, it is a memory.

A number that stalls is a decision, not a mood

Every long item below carries the signal to watch and what happens when it stops moving for two weeks. The point of naming it in advance is that the call gets made on the number rather than on how anyone feels in week five.


What a day on NONOS requires

"Daily driver" is the vaguest word in operating systems, so here it is as a list. Every row is a thing a person does on a normal working day. The state column is what a running v0.9.2 does today, checkable by booting it. Nothing in it is rounded up.

A working day needsv0.9.2 todayLands
Install to an internal disk and boot from it3 of 7 installer steps real; it does not write0.9.4 writes, 0.9.5 completes
Your files still there tomorrowencrypted volume written and /data routed to it, but nothing mounts it, so nothing survives a reboot0.9.4
Shut the machine downrefuses; no AML evaluator to read _S50.9.6
Close the lid and open it laternot supported; same cause1.0-rc
Know your battery levelthe syscall answers a fixed 100 percent, marked in the source as a placeholder0.9.6
Restartreal, through the FADT reset registerdone
Update the system you installedno update path exists at all0.9.6
Wired networke1000 and RTL8169 real, DHCP, TLS 1.3done
Wi-FiRTL8821CE real on silicon with a WPA2 four-way; iwlwifi blocked on firmware packaging0.9.6
Storage you plug inUSB mass storage is a stub0.9.6
SoundHDA is a stub0.9.6
Trackpadi2c-hid partial, one touchpad family brought up by hand0.9.6
A screen at its own resolutionfirmware framebuffer only, no modesetting, one mode for the whole session1.0, native mode first
A second screen, and brightnessneither existsnamed below, unscheduled
The webreal pages render, HTTPS through the mixnet, and plenty does not renderoracle at 1.0
Terminal, editor, files, clipboard, six keyboard layoutsreal capsules, shippingdone

Four of those rows have one cause between them. NONOS reads ACPI tables and scans AML, but it does not execute AML, so it cannot ask the firmware to sleep, to power off, or what the battery is doing. That is written up in its own section, because it is the single largest piece of missing work between this system and a laptop, and no roadmap that skips it is being honest about the word "daily".

Two rows carry no date, deliberately. External displays and backlight control are real requirements for a real machine, they are not in this window, and inventing a release for them would be the exact thing this document says it does not do. They are named so nobody has to discover them.


Why the order is what it is

The sequence is not preference. Six dependencies force it.

The corpus precedes the evaluator

Firmware is a population rather than a standard, so the AML work sits behind the census that collects the tables it will be measured against. Writing an interpreter first and finding the machines afterwards is how you build something that passes its own tests and fails on the first real laptop.

Persistence precedes everything a person does twice

An installer that writes a system is pointless if the system it writes forgets your work at every reboot, and an update path is undefined until there is state worth carrying across it. The home volume mounts before the installer writes a disk, in the same release, because they are the same promise seen from two ends.

Measurement precedes optimisation

Nothing gets tuned before it is measured, so the cycle-accurate suite lands first and everything after it is judged against published numbers.

Proof precedes concurrency

The wake and reply paths get model checked before SMP is enabled, because a race found by a checker costs minutes and the same race found by a four-core hardware hang costs days and teaches nothing reusable.

Driver instancing precedes disk writes

The installer cannot write a disk safely until the target disk is served by its own driver instance; otherwise the only thing standing between the installer and the live medium it booted from is a region check, and a region check is not an isolation boundary.

The arch boundary precedes aarch64 parity

Signing a second target while architecture-specific code still leaks into shared paths would produce a signed target that drifts silently. The boundary closes first, CI enforces it on every pull request, and only then does the second architecture get a key.

Shield runs on its own dependency chain, described in its section, and touches the OS train at exactly one point: prover hardware.


The six releases

v0.9.3

Proof and numbers

Performance

  • Cycle-accurate microbenchmark suite covering the primitives that define a microkernel: IPC round trip, syscall entry and exit, context switch pair, spawn to first userspace instruction, and spawn-gate attestation verify per capsule.
  • Measured with rdtsc and serialising instructions, counter overhead measured and subtracted, reported as p50, p95, p99 and max over thousands of iterations rather than min and average over a handful.
  • Host-side criterion benches for the pure logic that does not need a kernel: certificate decode, manifest verify, capability table decode, trailer parse.
  • A published performance page per release with history, and a diff tool that compares two runs by percentile and names what moved.
  • QEMU runs gate structure only, meaning every benchmark ran and no metric collapsed by an order of magnitude. Numbers we publish come from named hardware.

Proof

  • The authority theorem: for any capsule the spawn gate accepts, the granted capability set equals the ceiling in its signed certificate. Proven over the real decode, verify and gate code, not a model of it.
  • The refinement document begins, walking spec to code with no gaps.

Hardware census

  • Per-driver census in the live image: what probed, what initialised, what linked, what refused, with the reason.
  • One consent screen. The report is signed, scrubbed to device identifiers and verdicts, and carries no serials or identity.
  • QR rendering, so a machine whose network driver did not come up can still report, which is exactly the machine we most need to hear from.
  • The public matrix those reports feed, with rows anyone can verify.

Concurrency groundwork

  • Wake path, reply correlation and run-queue handoff modelled as concurrent state machines, checked exhaustively across interleavings on the host, with the checker gating every change to those files.
  • First fixes landed, each carrying the interleaving that found it as a permanent regression case.

v0.9.4

Concurrent

SMP

  • Per-CPU run queues with work stealing, replacing the single queue.
  • IPI paths audited, including reschedule and TLB shootdown, which is itself a concurrency problem: a shootdown has to be correct against a capsule unmapping memory on another core at the same moment.
  • QEMU sweep at 2, 4, 8 and 16 cores as a CI lane rather than a manual run.
  • Hardware soak including an Intel hybrid part, because performance and efficiency cores expose scheduling assumptions symmetric emulation never will.
  • Enabled in every shipped profile.

Proof

  • Spine complete: the spawn gate accepts only enrolled bytes, granted authority equals the signed ceiling, walked end to end in one document, then extended over the concurrent paths so the SMP change does not invalidate it.

Isolation

  • Per-device IOMMU domains, so each driver capsule translates in its own domain and a compromised driver cannot reach another driver's buffers.
  • Interrupt remapping, closing the injection path a device otherwise has.

Installer

  • Step 4: the enrollment and consent service, exposed to capsules behind a physical-presence step, so a machine root is only minted by someone standing at the machine.
  • Step 5: per-device driver instancing and the write-authority ACL, then the write itself, streamed in 64-sector chunks with a flush, then read back and compared before the step reports success.

Persistence

  • The home volume mounted at boot: /data served by the encrypted blockfs volume that the VFS already routes to, rather than falling through to a ramfs that dies with the machine.
  • Volume key sealed to the TPM against the boot measurements, so the disk is readable by the system that was measured and by nothing else, and a machine that fails its own measurement fails to open its data rather than opening it and hoping.
  • Crash consistency proved the way everything else here is proved: kill power at every commit point in a loop, remount, and require the volume to come back either at the old state or the new one, never between.
  • Quota and capability separation, so a capsule granted the data capability reaches its own subtree and not another capsule's.

Also

  • Hardware measurements replace QEMU measurements on the performance page, with SMP scaling curves.
  • Threat model and side-channel posture published, including what is out of scope and why.
  • First enrollment ceremony of the window, carrying the manifest changes driver instancing requires.

v0.9.5

Composed

Installer completion

  • Step 6: enrolling the composed system, so the installed machine attests as itself rather than as the medium it came from.
  • Step 7: the receipt. Enrolled root, measurement set, slot labels: the numbers an owner writes down and later checks against the public page.
  • Rollback to the previously enrolled system.

Trace conformance

  • Recorded register and MMIO conversations from real machines replayed against every driver change in CI, plus hostile mutations of those traces. This lands a release before the driver wave it serves, because a conformance harness written after the drivers is a harness written to agree with them.

AML, phases 1 and 2

  • Namespace load over the corpus the census collected, and pure evaluation: opcodes, control flow, method invocation, no side effects.
  • Validated against the bounded extractor already in the tree, on the machines it supports, so the new path is checked against a known-good answer rather than against nothing.
  • Ships as a better resource extractor. No power management is claimed in this release and none appears in the release note.

Marketplace

  • Publisher enrollment for developers outside the project, with a namespace bound to their key.
  • Reproducible listings: commit and toolchain published, so anyone can rebuild a listed capsule and compare measurements.
  • Revocation honoured at spawn, not only at install.
  • Purchases settle through the payment authority, and the receipt is verifiable against the chain by anyone rather than only by the installer that asked for it.

Also

  • Wallet custody sealed to the TPM against the boot measurements, so key material unwraps only on a system that measured as expected and a tampered kernel gets a refusal instead of a key.
  • Documentation merged: every subsystem at depth, wire formats byte by byte, getting-started guides tested by someone who did not write them.
  • SDK project template: one command produces a buildable capsule with a manifest, a declared capability set and a test that runs.
  • The capability walkthrough, since declaring what your program may touch is the one unfamiliar thing about writing software here and it is currently learned by reading somebody else's capsule.

v0.9.6

Power

The one release built around a single subsystem, because the subsystem is worth a release, and folding it into a crowded one is how a plan becomes fiction while still looking full.

AML, phases 3 to 5

  • Operation regions: SystemIO and SystemMemory, then the embedded controller, each reachable only from the evaluator and only within the ranges the tables declare.
  • ACPI enable through SMI_CMD, _S5 evaluated, PM1 programmed. The machine turns off when you tell it to.
  • _BIF and _BST, replacing the placeholder that answers a fixed hundred percent today, surfaced in the shell.
  • Thermal zones with the passive trip point honoured, because a laptop that cannot read its own temperature has no business running for eight hours.
  • Hostile corpus: truncated tables, cyclic references, non-terminating methods, overrunning package lengths. Every one refused, not survived.

Updates

  • A/B system slots. An update writes the inactive slot, enrolls it, and only then makes it the boot target, so an interrupted update leaves a bootable machine rather than a brick.
  • The new slot verifies before first boot, not after, and rolls back on a failed boot without a person present.
  • Signed and measured on the same chain as everything else. An update is a capsule set with a manifest, not a special case with its own trust path.
  • Delta by capsule rather than whole images, since a system that ships 92 signed capsules should not need a gigabyte to change one of them.

The driver wave the matrix asked for

  • iwlwifi firmware packaging closed, USB mass storage and HDA to functional, i2c-hid completed, each landing against the trace conformance harness that shipped in v0.9.5.

NOX

  • Entitlements enforced at spawn. A tool capsule with a pay-per-use licence does not run without a grant the broker signed against a confirmed, unspent payment, checked where every other admission check already happens rather than by the tool on itself.
  • The plaintext window narrowed: key material handled inside the custody capsule and never crossing an IPC boundary in the clear.
  • Swap reserves wired to the quote, so a price comes from the pool it claims to come from.
  • A worked paid application end to end: written against the SDK, capabilities declared, published, purchased, running under an entitlement.
  • Reproducible listings, so a stranger rebuilds a listed capsule from the published commit and toolchain and compares measurements.
  • Stake-weighted route selection, and a CI assertion over a synthetic topology that no node appears in routes more often than its weight allows and no route repeats a node across layers.

Also

  • Volunteer hardware farm running with external machines.
  • C toolchain demonstration through relibc.

v1.0-rc

Parity

  • Arch boundary closed: no architecture-specific code outside the arch layer, enforced by a check rather than by review.
  • Dual-architecture CI: every pull request builds both targets, with a boot gate on QEMU virt, so parity cannot regress silently.
  • aarch64 desktop boots, with signing, enrollment and STARK attestation at parity, and the prover benchmarked on-board because prover cost on a small core is unknown until measured.
  • One named ARM board green on the public matrix.
  • Suspend to RAM and resume, on the evaluator that shipped in v0.9.6: device state saved and restored per driver capsule, the lid switch wired, and wake sources programmed.
  • Resume attestation, which is the part nobody else has to solve. A machine coming back from S3 has not been measured by its firmware again, so it re-establishes what it is on the way up: sealed state unsealed against the pre-suspend measurements, drivers re-attested as they resume, and a resume that cannot prove itself refusing to resume rather than continuing quietly.
  • AMD-Vi, behind the same interface as VT-d.
  • Third-party onboarding complete: an outside developer builds, declares capabilities, enrolls and ships using documentation alone.
  • Linux ABI translation capsule as a labelled preview.
  • Spend authority shown before consent, with limits, in the same surface that already shows capability bits before an install.
  • Second enrollment ceremony of the window.

v1.0

The machine

The residency

For thirty consecutive days before the release, one of us uses NONOS as their only machine. Not a second laptop on the desk, not a partition booted for testing. The only one. Every day of it is logged publicly: what broke, what was worked around, what could not be done at all and what had to be done on someone else's computer.

A version number is a claim about other people's time.

The log is published whatever it says, on the same principle as the audit. If the honest version of it is that thirty days was not survivable, then that is the release note, and v1.0 waits. A version number is a claim about other people's time, and we are not making that claim from a demonstration.


  • A developer we have never met ships a verified capsule and a stranger verifies it.
  • External audit of the crypto and attestation chain, published with our responses whatever it says.
  • Intel integrated graphics: modesetting and 2D acceleration to the standard the rest of the system is held to. One family properly rather than several announced.
  • Browser compatibility oracle: a measured statement of what renders and what does not, because "it browses the web" is a claim and a list of sites with verdicts is a fact.
  • Second matrix-driven driver wave.
  • Performance page carrying x86_64 SMP and aarch64 side by side.
  • Every row of the day table green, on a named laptop, with the census report from that machine published beside it.
  • The x402 rail configured and one agentic payment run end to end, where the paying binary's hash is on the public attestation page and the receipt is on chain.

Chapter

Subsystems

Subsystems

Concurrency

Today

The scheduler carries a lock-free wake generation table. Wakes are counted, so a task woken while preparing to sleep refuses to sleep through it, and both blocking paths that matter, receive and irq-wait, guard their sleeps with the wake token. Application processors come up without racing the bootstrap processor, load the IDT the kernel actually runs rather than whatever the early boot table was, and read their cpu number from the per-cpu block rather than a register that is not architecturally guaranteed to hold it. Every shipped profile is single-CPU.

The gap

Multi-core boot reaches secondary-processor bring-up and stalls there. Beyond that specific hang, the concurrent correctness of the paths capsules actually block on has been reasoned about but not proven.

Why it ships off

A kernel whose concurrency is unproven, in a system whose entire claim is that nobody should have to trust us, is not a trade we will make for a line in a feature list.

Method

Proof first. The wake path, reply correlation and run-queue handoff are modelled as concurrent state machines and checked exhaustively across interleavings on the host. What that finds is fixed before hardware is involved. The remaining hardware bring-up hang is then the last mile rather than the method.

What we are hunting, named before we start

Kernel concurrency is not an open field. It is five known classes, and each has a checker that finds it deterministically on a host in seconds.

  1. Lost wake. A task decides to sleep while another core wakes it. The wake generation table is the existing defence and the model proves it over every interleaving rather than over the ones we thought of.
  2. Reply misdelivery. A reply lands on the wrong caller when two callers on two cores are outstanding at once. This is the same shape as the correlation bug already fixed once on a single core, which is the reason it is first in the list rather than last.
  3. Shootdown against unmap. One core invalidates while another unmaps the same range. Ordering of the invalidation, the page table write and the IPI acknowledgement is the whole problem, and it is stated as an invariant the model checks rather than as care taken while writing it.
  4. Steal against exit. Work stealing picks up a task that is concurrently exiting. Bounded by making the queue's ownership transfer the only place a task changes cores.
  5. Per-CPU aliasing. Any read of per-CPU state from the wrong core. Mechanically checkable, and checked mechanically, because this is the class that hides for months and then presents as a hardware fault on one machine.

The four-core hang currently in bring-up is expected to be class 1 or 5 and the models say which before anyone attaches a debugger. That is the difference between a schedule and a hope.

Signal

Interleavings covered per week, and open findings against closed ones. If coverage stops moving for two weeks, per-CPU queues and work stealing split off to the following release and default-on SMP ships on the existing single queue, which is the fallback already recorded in the open decisions.

Work, in order

1. Interleaving models for wake, reply correlation, run-queue handoff. Checker gates every change to those files. 2. Fixes, each with its interleaving recorded as a regression. 3. Per-CPU run queues with work stealing. 4. IPI audit: reschedule and TLB shootdown. The shootdown is the dangerous one, because it must be correct against a capsule unmapping memory on another core concurrently. 5. QEMU sweep at 2, 4, 8, 16 cores in CI. 6. Hardware soak, including an Intel hybrid part. 7. Default on, with concurrency folded into the proof spine.

Evidence

the model checker in CI, a soak log from real silicon, and the extended spine. Ships: v0.9.4.

Isolation

Today

VT-d performs real translation with invalidation and fault reporting, and the fault queue is drained from the timer tick so a device-posted fault is visible rather than rotting in a ring. Ring-0 restrictions are put in force and read back, because firmware sometimes ignores the write and an assumed protection is worse than none. Fault stacks sit outside the kernel image with a guard page beneath each. Speculation mitigations run on kernel entry. sysretq rejects the entire non-canonical range rather than half of it. Every entry into the kernel is hand-written assembly: 18 trampolines, page fault and timer, and 56 numbered vector gates over a shared dispatch body, so swapgs placement is readable rather than macro-expanded.

The gap

Translation is enforced, but every driver capsule currently shares one domain. That means the IOMMU protects the system from devices and does not yet protect driver capsules from each other, which is the sharper half of the promise.

Work

1. Per-device domains, one per driver capsule. 2. Interrupt remapping, closing vector injection. 3. AMD-Vi behind the same interface, so nothing above the arch layer learns which vendor it runs on. 4. Failure posture: a device that faults repeatedly is stopped and its owning capsule told why, rather than tolerated indefinitely.

Evidence

a test in which one driver capsule attempts to reach another's DMA buffers and is refused by the hardware. Ships: domains and remapping in v0.9.4, AMD-Vi in v1.0-rc.

Persistence

Today

More is built than runs. There is a real filesystem in the tree: an encrypted block filesystem with a header ring, node serialisation, directory records, allocation and a commit path. The VFS already routes /data to it, and a raw block write path exists behind the StoreWrite capability, bounded above the header ring, which is what the package store persists through.

What is missing is the two calls that open it. Nothing in the kernel formats or mounts the volume, so /data resolves against a volume that was never mounted and everything a person writes lives in a ramfs that dies with the machine. This is precisely the pattern this project says it does not ship, written but unreachable from a running system, and it is listed here as unfinished rather than counted as a filesystem.

The work

Mount at boot, with the volume key sealed to the TPM against the boot measurements rather than held anywhere a reader could find it. That binding is the point: the disk opens for the system that measured as expected and for nothing else, so a tampered kernel does not get a decrypted home directory, it gets a refusal.

Then crash consistency, proved rather than asserted. Power cut at every commit point in a loop, remount, and the volume must come back at the old state or the new one and never at an invented one in between. A filesystem that has not been killed a few thousand times is a filesystem whose behaviour under power loss is unknown.

Then separation. The data capability grants a capsule its own subtree. The editor cannot read the wallet's files because it was never granted them, which is the same sentence as everywhere else in this system.

Proof it is done

A file written on one boot, read on the next, on real hardware, with the volume refusing to open under a deliberately altered kernel.

Power, and the firmware conversation

Today

NONOS reads ACPI tables and it scans AML, but it does not execute AML. There is a bounded resource extractor, around 1,600 lines, that walks the DSDT byte stream looking for device objects and parses _CRS resource templates to recover an I2C address and a GPIO interrupt for a touchpad. It never executes anything, and it returns nothing rather than guessing when an encoding surprises it. That was the right shape for the problem it was written for.

It is not enough for a laptop. Shutdown refuses, and the source says why: entering S5 means evaluating the _S5 object to get the sleep type values, which needs an interpreter. Sleep refuses for the same reason. The battery syscall returns a fixed hundred percent with a comment marking it as a placeholder until a real driver exists. Thermal is not read at all. Reboot works, because reboot is a register write the FADT hands you and needs no interpreter.

So four separate user-visible gaps are one missing component. One thing to build, built once, and four rows of the day table turn over together.

What the work actually is

AML is a bytecode with mutable namespace state, methods, control flow, integers of two widths depending on the table revision, region accessors that touch real hardware when read, and thirty years of firmware written against one reference implementation's bugs. Firmware in the field is not a specification, it is a corpus. An evaluator either handles what machines actually ship or it is a spec-conformant thing that fails on the first real laptop.

And it is firmware bytecode running inside an operating system whose entire argument is that nothing runs unverified. So it is bounded in every dimension that can run away, it refuses instead of guessing, it does not get kernel authority it does not need, and the firmware's opinion is treated as input rather than instruction.

The corpus comes first, and it is what makes this schedulable

Before a line of the evaluator is written, every machine on the hardware matrix contributes its DSDT and SSDTs, and that set is the specification we build against. Firmware is not a standard, it is a population, so we treat it as one: the target is a percentage of real tables handled, and that percentage is measurable from the first week, long before anything can power a machine off.

The census ships in v0.9.3 for this reason among others. By the time the evaluator starts, the corpus already exists.

The work, in five phases, each with a number that moves.

  1. Load and namespace. Walk the tables, build the namespace, resolve scopes and aliases, execute nothing. Signal: percentage of corpus tables that load with a complete namespace. Target 100, because a table that will not even load is a parser defect and not a firmware quirk.
  2. Pure evaluation. Integers of both widths, buffers, packages, control flow, method invocation, locals and arguments. Validated by evaluating objects with no side effects, _STA and _CRS and _HID, across the whole corpus and comparing against what the existing bounded extractor already recovers on the machines it supports. Signal: percentage of corpus methods that evaluate without hitting an unimplemented opcode. The opcode set is finite and the burn-down is literally a checklist.
  3. Operation regions. SystemIO and SystemMemory first, embedded controller after. This is where evaluation stops being pure and starts touching the machine, so it is gated: region access is allowed only from the evaluator, only to ranges the tables declare, and refused otherwise. Signal: corpus replay with regions mocked, then a single named machine with regions live.
  4. Power. ACPI enable through SMI_CMD, _S5 evaluated, PM1 programmed. Signal: the machine turns off. There is no partial credit on this one.
  5. Devices. _BIF and _BST for the battery, thermal zones and the passive trip point. Signal: a battery reading that tracks a discharge curve, and a throttle under sustained load.

Phases 1 and 2 are the bulk of it and both are measurable weekly against a corpus that already exists. Phases 3 through 5 are small once the evaluator is correct, which is the whole reason the order is this way round.

Signal for the phase, and the stall rule

Corpus pass rate, published weekly. If it stops moving for two weeks, phases 3 to 5 move to the next release and the evaluator ships as what it can already do: a better resource extractor, which is a real improvement to the touchpad and device enumeration paths even with no power management attached to it. The work does not become worthless if it runs long, and that is by design, not by luck.

Then hostility

Once the corpus passes, it gets mutated: truncated tables, cyclic references, methods that never return, package lengths that overrun. Every one must be refused rather than survived by accident. This is the same trace conformance idea already used for drivers, applied to the one input we do not get to choose.

Proof it is done

A laptop on the matrix powers off from its own menu, reports a battery that goes down while unplugged and up while charging, and throttles instead of cooking under sustained load. Ships: phases 1 and 2 in v0.9.5, phases 3 to 5 in v0.9.6, suspend and resume in v1.0-rc.

The installer

Today

capsule_nonos_install is assembly from _start to the exit syscall, signed and enrolled like every other capsule, and admitted by the same spawn gate. Three of seven steps are real.

  1. Surveys the machine through the hardware broker.
  2. Reads the install set over the ramfs wire protocol, bounds-checking every length, offset and handle the server returns, because the file server is outside the installer's trust line.
  3. Verifies each capsule's four artifacts through the same chain the spawn gate uses, printing the granted capability mask beside each verdict.

One verification failure ends the ritual. No path installs less and reports success.

The gap, and what each piece needs.

Step 4, mint the machine root. Needs the local-build root service exposed to capsules behind a physical-presence consent step, so a root is only minted by someone at the machine rather than by anything that can reach an IPC endpoint.

Step 5, write the boot partition. Needs two pieces, both specified and neither built.

Per-device driver instancing: the target disk must be served by its own driver instance, so the live medium is unreachable by construction. A region check is not an isolation boundary, and the store the boot chain trusts sits on that medium.

The write-authority ACL: the block driver answers mutating operations for the kernel client alone today. The installer earns that authority through the attested caller identity the kernel records at spawn, checked on every request and never cached, because a cached verdict outlives the installer's exit and would follow its pid to whatever runs next.

Step 6, enroll the composed system, so the machine attests as itself.

Step 7, the receipt: enrolled root, measurement set, slot labels. The numbers an owner writes down and later checks on the public page, closing the loop from a machine in a room to a verification anyone can repeat.

Then

rollback to the previous enrolled system, multi-disk targets, unattended installs from a signed answer file.

Evidence

a disk written and read back before success is reported (v0.9.4), and a receipt a stranger verifies (v0.9.5).

Drivers and hardware coverage

Today, on real machines

NVMe, AHCI, xHCI with USB HID, PS/2, GOP display, and the RTL8821CE wireless stack end to end including firmware download and the WPA2 four-way handshake on silicon. iwlwifi reaches secure boot and is blocked on firmware packaging. USB mass storage and HDA are stubs. i2c-hid is partial. Everything else is exercised under emulation.

The structural problem

Hardware coverage normally scales with the number of machines a project owns. We are two people. So coverage has to come from other people's machines without asking anyone to send us anything or trust what we say about the result.

The system, five parts.

Attested census. Any live boot can run a per-driver census: probe, initialise, link, refuse, with reasons. One consent screen produces a signed report scrubbed to device identifiers and verdicts. No serials, no identity. QR rendering means the machine whose network driver did not come up, the one we most need to hear from, can still report.

The public matrix. Reports feed a hardware page beside the verify page. Rows are cryptographically checkable. It tells us what to fix by real population and tells a stranger whether their laptop works before they download anything.

Trace conformance. Every real-hardware session records the register and MMIO conversation. Traces become drop-in files CI replays against every driver change, along with hostile mutations. One afternoon with one borrowed laptop becomes a permanent regression asset that outlives the laptop. This is how the RTL8821CE work was proven off-silicon.

Variety without silicon. A QEMU device sweep across storage controllers, NICs, USB controllers, PCI topologies and core counts, plus bare-metal cloud runners for real Intel and AMD variety, rented by the hour.

The volunteer farm. A contributor with a remote-boot setup attaches a machine as a nightly target. They keep the machine, the matrix gets an attested report from hardware we have never touched, and nobody has to trust the report because it proves itself.

Graphics, decomposed

The one driver that is a project rather than a wave. NONOS runs on the framebuffer the firmware hands it, in one mode, for the whole session. Modesetting on one Intel generation is the fix, and it is a documented sequence rather than an exploration, because Intel publishes the programming manuals and the register order is written down.

  1. Parse the VBT to learn which display outputs this board actually has, since the hardware exposes far more than any given laptop wires up.
  2. Read the EDID over the AUX channel, which is the first step with an observable: a panel's real mode list, printed.
  3. Program the clock, then the pipe, transcoder and DDI in the order the manual specifies. Every step reads back, because a display pipeline that is programmed but not verified fails as a black screen with no information in it.
  4. Page flip and vblank, so the compositor stops tearing.
  5. 2D acceleration on the blitter, last, because a correct slow screen beats a fast broken one.

Signal

Steps completed against a named panel, and mode list recovered against mode list expected. If step 3 stalls, v1.0 ships modesetting for the panel's native mode only, without external outputs, which is still every laptop running at its own resolution instead of a firmware default.

Evidence

matrix live with outside rows (v0.9.3), traces in CI and trace conformance in CI (v0.9.5), the first driver wave shipped (v0.9.6), a second wave and one Intel graphics family at its native resolution (v1.0).

The network, and the anonymity we actually have

Today

Traffic leaves NONOS through the Nym mixnet. The Sphinx layer is real against recovered protocol constants with 46 vectors green, the gateway and directory paths work end to end, a four-hop route carries HTTP and HTTPS, and TLS 1.3 completes through the mixnet against the full root store. Each packet draws a fresh random route, and the egress hop is pinned to the gateway the recipient actually holds a session with, which is the difference between a message that arrives and one that is acknowledged by a node that then drops it. Exit rotation is driven by delivery rather than by whether a node answered a lookup.

The client holds the whole active set. The directory endpoints answer with the rewarded set rather than every bonded node, currently 60 mix, 180 entry and 179 exit, and a node is 76 bytes on the wire, so all of it is under 40 KB and there is nothing to ration. Hop selection reads four bytes of the route seed through a multiply-shift reduction, which is uniform over the candidates to within one draw and reaches every candidate however long the list is.

What this replaced, recorded because it was not visible from outside

The store held 128 nodes and the gateway lists were cut to the first 34 of each. Every client truncated the same list the same way, so any two of them held the same gateways, and the cost of watching NONOS traffic specifically was presence at 34 gateways rather than 180. Underneath it, each hop was chosen with a single seed byte modulo the candidate count: that can never name an index above 255 however long the list is, and modulo 180 gives the first 76 candidates two chances against one for the rest, a measurable lean toward the front of the list. Both are fixed, and the biased shape is pinned by a regression proof so it cannot return quietly.

The gap that remains

The draw is uniform, and Nym's security argument is stake weighted: an adversary's chance of owning a path is meant to track their share of stake, and the network's parameters were chosen under that assumption. Uniform over the active set is a different distribution, and while it is a far better one than uniform over an arbitrary prefix, it is still not the one the design is written about. The skimmed directory view carries a performance figure but not stake, so weighting needs a view we do not currently read, and this document is not going to guess at a field nobody has looked at.

The work

1. Read a directory view that carries stake, and weight selection by it. 2. A route diversity assertion in CI over a synthetic topology: across many routes, no node appears more often than its weight allows, and no route repeats a node across layers. 3. Extend the same treatment to the older packet format, whose route header is still derived from a per-session seed rather than a per-packet one. It does not carry mixnet traffic today, and a deterministic route in the tree is a deterministic route somebody wires up later.

Evidence

a published distribution of selected nodes against published stake, from a real directory rather than a fixture. Ships: stake weighting and the diversity assertion in v0.9.6.

The marketplace

Today

The capsule store is a gated install path. The vfs carries dedicated operations: query returns a verified package summary, commit installs into /capsules only after the full artifact chain verifies, remove withdraws it. All are restricted to the installer service and the store is read-only outside them. The budget is enforced, silent overwrites refused, the install slug derived from the package's verified namespace rather than anything the package claims about itself, and a slug an existing service already answers is refused, which closes squatting.

The desktop scans /pkgs each tick, lists installable packages, and raises a consent screen showing requested capabilities by name before approve commits anything. It never hides a capability to look friendlier. The terminal has the same power in text.

First package through that path: a QR generator built from an unmodified crates.io crate, signed, verified, consented to, installed.

The gap

1. Publisher enrollment for outsiders. A developer generates a keypair, we enroll the public half under the trust anchor with a namespace bound to them, and their capsules then verify on any machine without us in the loop. The namespace binding makes impersonation structurally impossible rather than moderated. 2. Public capability review. Every listing shows the ceiling its certificate carries, and that is the same ceiling the kernel enforces at spawn, so a listing cannot promise less than the binary can do. 3. Reproducible listings. Commit and toolchain published, so anyone can rebuild and compare measurements. The discipline we hold ourselves to at release, applied to third parties. 4. Updates and revocation, with revocation honoured at spawn rather than only at install. 5. Payment, settled on NOX, deliberately last. A market where nothing is paid for still has to be safe.

Evidence

an outside developer publishing with documentation alone and their capsule installing on a machine we do not control (v0.9.5); a stranger verifying that capsule's proofs without asking us (v1.0).

Running the software people already have

Three ladders, in the order they become possible, each honest about what it gives you.

Rust, native, today

Unmodified crates compile against our std port and run as attested capsules: ripgrep, sd, grex, dotenv-linter, tokei, and an unmodified tokio runtime. This is not a compatibility layer. It is the platform being real enough that ordinary Rust targets it. The std port carries real threads, TLS keys, futex, environment, filesystem seek, and process spawning that launches signed capsules by name.

C, through relibc

A C library over our syscall surface brings the body of small C tools into reach without emulation and without trust. This ladder decides whether NONOS is a system you can work in daily, and it is why the syscall contract was published and mechanically checked first.

Linux binaries, in two clearly separated shapes

A translation capsule maps Linux syscalls onto ours and runs the binary inside a capsule with a declared capability ceiling, confined by the same model as everything else and labelled as unattested code under translation. For anything needing a real kernel, a measured guest: Linux in a VM whose image is measured and attested like any other artifact, isolated by the IOMMU work above, sharing nothing it was not granted.

The line we will not blur

A translated Linux binary is not verified software. It is unverified software that cannot exceed the authority you granted. That distinction is the product, and any wording that softens it is a claim we would have to defend later.

Evidence

a C toolchain running through relibc (v0.9.6), the translation capsule as a labelled preview (v1.0-rc), the measured guest after v1.0.


Chapter

NOX

NOX

Why an operating system is the missing layer

Hardware wallets exist because operating systems cannot be trusted. So does the seed phrase written on paper, the blind-signing screen on a second device, and the habit of keeping a separate laptop for anything that holds value. Every one of those is a workaround for a single fact: you do not know what is running on the machine in front of you.

Web3 has spent a decade engineering around that fact rather than at it. The keys moved off the computer because the computer was the problem. It worked, and it is why using a hardware wallet still feels like using a hardware wallet.

NONOS goes at the premise. If every byte that runs was verified before it ran, and the signing key is sealed to the measurement of the system that runs it, then the machine you are already using is the signer. Not a second device you carry, not a phrase in a drawer. The computer, because the computer can prove what it is.

That claim is not finished, and the honest position is written into the sections below. The custody path is real and the sealing that makes the claim true lands in v0.9.5. Until then this is an argument with the mechanism half built, and it is described that way.

The wallet

Today

capsule_wallet_nonos is a signed capsule admitted by the same spawn gate as everything else, speaking a sixteen-operation ABI: create, open sealed, unlock, lock, address, balance, build a send, sign it, broadcast it, history, proof, restore from keys, restore from seed, sync, status, close. BIP39 and BIP32 derivation, RFC6979 deterministic signatures, sealed at rest with ChaCha20-Poly1305, custody isolated in its own capsule rather than linked into whatever asks. Real sends on Ethereum and real NOX. Sixteen core Lean modules carry the crypto and custody proofs with no sorryAx in the chain.

The gap, stated plainly

Between unlock and lock, the key is plaintext in RAM. Sealing at rest is not sealing in use, and a document that argues the machine can be the signer has to say which half is built. The swap quote is the same shape: constant product with a 256-bit mul_div behind a QuoteProvider, correct arithmetic with no live reserve source wired to it, so it computes a real quote from numbers nothing supplies yet.

The work

Custody sealed to the TPM against the boot measurements, so the key material unwraps only on a system that measured as expected. That is the sentence that turns the whole positioning above from an argument into a mechanism: a tampered kernel does not get a decrypted key, it gets a refusal, and the owner finds out at unseal rather than after a transaction. Then the plaintext window itself narrows, with key material handled inside the custody capsule and never crossing an IPC boundary in the clear. Then reserves wired to the quote, so a swap price comes from the pool it claims to come from.

Evidence

a wallet that refuses to unlock under a deliberately altered kernel, and a signature produced on a machine whose measurements are published. Ships: sealing in v0.9.5, the narrowed window and live reserves in v0.9.6.

Payments, and why they are a capability

Today

capsule_payment is the payment authority, running at CPL=3 like any other capsule, declaring CAPSULE_REQUIRED_CAPS = 0x18 and nothing more. It settles an install, records the charge against a monotonic nonce, and returns a receipt signed by the keyring over secp256k1, so an installer can verify a payment without trusting whoever asked for it. It owns the nonce, the pending outbox and the per-publisher settlement state, and it terminates only through the exit syscall.

Behind it sit three crates that are pure logic and therefore provable on a host, which is where they are proven. nonos_nox_receipt accepts a chain receipt only when it shows a successful transaction carrying an ERC20 transfer from the buyer to the treasury, emitted by the NOX token, for at least the price. It reads only the fields the decision needs and never allocates, so a truncated or hostile receipt fails closed instead of reading as a payment. nonos_nox_broker prices the tool, checks the receipt, refuses a transaction already redeemed, and returns exactly the grant that was paid for. It never signs: the capsule holds the key. nonos_nox_license verifies the entitlement, with signature checking injected through a trait so the same code runs against the kernel's ed25519 in a capsule and against a host signer in tests.

Thirty-three tests and nine Kani proofs across the three.

The idea worth stating

Spending authority on NONOS is a capability bit, not an API key. A capsule that can pay was declared as such, signed with that declaration inside the manifest, and attested at spawn before it ran. So the question stops being whether some program should be allowed to spend, and becomes whether this binary is the one that was authorised, which is a question with a cryptographic answer rather than a policy answer.

That is also the answer to agentic payments, and it is the opposite of how the rest of the industry is approaching them. Handing an autonomous process a key and hoping the sandbox holds is a trust model. Requiring that the process spending money is a binary whose hash was enrolled, that declared spend authority in a signed manifest, and that a spawn gate admitted after checking eleven things, is a proof. The keyring already carries the x402 rail in its wallet rail registry, marked as requiring configuration, which is the correct state for something that must not work by accident.

The gap

These pieces are separately real and not yet one path. The broker and license crates are proven on a host and are not what a marketplace purchase currently traverses. The x402 rail is declared and unconfigured. No agentic payment has been demonstrated end to end, and this document does not imply one has.

And the honest hole, which is ours to name before someone else does

Verifying a receipt means somebody handed us the receipt. The scan is non-allocating and fails closed on anything malformed, which stops a hostile receipt from reading as a payment, and it does not stop a node from declining to mention a transaction that exists, or from answering for a chain state that is not canonical. An operating system whose whole argument is that you should not have to trust anyone has a payment path that currently trusts an endpoint. Header verification with inclusion proofs is the answer and it is not built. Until it is, the honest statement is that the payment check is sound about the receipt it was given and says nothing about who gave it.

The work, in order

1. Marketplace purchases settle through the payment authority, with the receipt verifiable by anyone against the chain rather than only by the installer that asked for it. 2. Entitlements enforced where everything else is enforced, at spawn. A tool capsule with a pay-per-use licence does not run without a grant the broker signed against a confirmed, unspent payment. Not a check the tool performs on itself, which is a check the tool could skip. 3. A consent surface for spend authority, showing what a capsule may spend and against what limit, in the same place capability bits are already shown before an install. 4. The x402 rail configured, and one agentic payment run end to end where the paying binary is attested and the receipt is public.

Evidence

a purchase whose receipt a stranger verifies on chain, a licensed tool that refuses to spawn without its grant, and a payment made by a program whose hash is on the public attestation page. Ships: settlement with the marketplace in v0.9.5, entitlements at spawn in v0.9.6, consent surface in v1.0-rc, the agentic run in v1.0.

The SDK, and the developer path

Today

Nine crates, 155 files, a shade under six thousand lines. nonos_sdk with the capability declaration module, nonos_app for the application shell, nonos_window, nonos_ui for canvas, colour, rect and widget, nonos_appkit for buttons, labels, panels and a theme, nonos_prelude so a program starts with one import, nonos_std and nonos_font. Two examples in the tree, one minimal and one exercising the widget set. Ninety-two capsules ship against it, which is the part that matters: the SDK is what the operating system itself is written with, not a layer bolted beside it.

marketplace_abi carries the index wire form as a length-prefixed binary codec against a canonical schema, deliberately not JSON, because a marketplace index arrives as a signed blob and a tight parser keeps the userland attack surface narrow.

The gap

Two examples is not a developer story. There is no project template, no declared-capability walkthrough, no worked example of an application that takes a payment, and no documented path from cargo new to a signed capsule on the marketplace. Everything needed to do it exists and the sequence is in our heads, which by this document's own rule means it is not a plan.

The work

1. A template: one command produces a buildable capsule with a manifest, a declared capability set and a test that runs. 2. The capability walkthrough. Declaring what your program may touch is the single unfamiliar thing about writing software here, and it is currently learned by reading someone else's capsule. 3. A worked paid application, end to end: written, capabilities declared, published, purchased, and running under an entitlement. 4. Reproducible listings, so a stranger rebuilds a listed capsule from the published commit and toolchain and compares measurements. 5. The onboarding gate: an outside developer does all of it from the documentation, with nobody from the project in the loop.

Evidence

a capsule built, published and sold by somebody we have never spoken to. Ships: template and walkthrough in v0.9.5, paid application and reproducible listings in v0.9.6, the onboarding gate in v1.0-rc.

Micro fees, and where they can actually settle

The marketplace wants per-use pricing. A tool that costs a fraction of a cent per invocation is the natural shape for a capsule that does one thing, and the licence and broker crates already implement exactly that: one use per price paid, replay refused, grant issued only against a confirmed payment.

That shape does not settle on Ethereum mainnet, and saying otherwise would be the first dishonest sentence in this document. A per-use fee worth a fraction of a cent cannot carry a mainnet transaction. The mechanism is right and the settlement layer is the open question.

Three answers exist and each has a real cost. A rollup, where fees are small enough for per-use settlement and the receipt verification we already have works essentially unchanged, at the price of a bridge and a second place where value lives. Payment channels, where a buyer opens once and settles a batch, cheapest per use and heaviest in state to manage. Batched settlement, where the broker aggregates and settles periodically on mainnet, simplest to build and the one that requires trusting the broker between settlements, which is the thing this project exists to avoid.

The answer is a decision rather than a discovery, it is recorded in the open decisions below, and it is answered before entitlements gate spawning rather than after. Whatever wins, the anchor stays Ethereum and the receipt stays something anyone can check.

What you see is what you sign

This is the oldest unsolved problem in crypto user experience and it is not a wallet problem. You approve a transaction because a window told you what it does. On a general purpose operating system, nothing establishes that the window is the wallet's, that the text in it matches the bytes being signed, or that a screenshot of a wallet is not simply a screenshot of a wallet. Hardware wallets exist to move the confirmation onto a screen the host cannot draw on, and the second screen is small and shows you an address.

NONOS has the pieces to close this properly, which is not a claim that it is closed. The compositor is an attested capsule with its own proofs. The wallet is an attested capsule. Capability bits are already shown to a person before an install, so a consent surface owned by the system rather than by the application is an existing pattern here rather than a new idea. What is missing is the binding: a confirmation surface the requesting application cannot draw, cannot read, and cannot dismiss, that displays the decoded transaction and returns a signature only for the bytes it displayed.

Done properly it means the confirmation is a trusted path from the capsule that decodes the transaction to the pixels the owner reads, on the machine they are already using, with the whole chain attested. That is the thing the second device was invented to approximate.

Ships

the spend authority surface in v1.0-rc is the first half. Full transaction confirmation over the trusted path is named here and not scheduled in this window, because doing it badly is worse than the current honest state, and doing it well is its own arc.

The chain side, and why Ethereum

Eight contracts are live on Ethereum mainnet under a three-of-five Safe, and the Rust claim path settles against the deployed pool rather than a local fixture. The off-chain rail has a frozen leaf format and five tools behind a single make target, which is what keeps the format from drifting under the thing that depends on it.

We build on Ethereum and we are not going to launch a chain. The reason is not diplomacy. A new chain would mean asking people to trust a new validator set in a document whose entire argument is that they should not have to trust anyone, and it would let us grade our own homework on the one part of the stack that already has adversaries paying attention. The settlement layer is the part of this system we most want to be somebody else's problem, audited by more people than we will ever have.

So Ethereum is the anchor and the verifier lives there. Shield's proofs verify in deployed bytecode. Payments are ERC20 transfers anyone can check. Where fees make mainnet the wrong venue, the answer is a layer above it that settles down to it, never a chain beside it.

The interesting claim was never on the chain anyway. It is that the machine holding the key can prove what it is, and every part of the stack above exists to make that provable rather than asserted.

What this makes possible, which we are not building

Not scheduled, not promised, not counted anywhere in this document. They are here because the primitive is real and somebody should build them, and because a roadmap that only lists our own work is a smaller document than it needs to be.

The primitive is one sentence: a machine that can prove which software it is running, holding a key that only exists while that proof holds. Trusted execution environments have promised this for a decade from inside vendor silicon whose failures are somebody else's disclosure timeline. This version is open, reproducible from a public commit, signed twice, and attested by a STARK anyone can verify.

Attested clients as an on-chain fact

A contract that accepts a signature only from an enrolled measurement set. The chain has spent years learning to verify computation and still cannot say anything about the machine that submitted it. What it needs from us: measurements published in a form a contract can consume, which the attestation surface almost is already.

Agents that can hold funds

Not because a sandbox held, but because the binary that spent was enrolled, declared spend authority in a signed manifest, and passed the spawn gate. What it needs from us: the x402 rail configured, which is in v1.0.

Device proof for physical networks

A machine proving it runs the software it claims is exactly what infrastructure networks pay for and currently approximate. NONOS already binds a device slot at install and refuses binding proofs against the unbound vendor sentinel. What it needs from us: nothing structural. It needs somebody with the network.

Validator and node operation

A signing key sealed to the measurements of the machine, so key extraction requires the attacker to first become a machine that measures correctly. What it needs from us: the sealing in v0.9.5 and a long soak.

Oracles and data feeds

The operator problem is that you trust them. A feed signed by an attested stack moves the question from who runs it to what runs on it. What it needs from us: nothing new.

Compute you can check

Rent a machine and receive a proof of what ran on it, rather than a service agreement. What it needs from us: the installer and remote enrollment, both in this window.

We are building the primitive and the OS around it. If a year from now somebody has built two of these on top, that is a better outcome than us having built one of them badly.

Chapter

NOX Shield

NOX Shield

Private transfers and anonymous swaps settling on Ethereum L1. A transparent STARK, no trusted setup, post-quantum, verified by contract rather than by committee.

Where it stands

The 2-in-2-out join-split circuit is built and gate-green. It proves note commitment under the deployed 32-round hash, membership in a depth-32 pool tree, that spent notes are proven notes, value conservation bound to committed limbs so neither mint nor burn is expressible, and ownership plus double-spend through keys derived from one witnessed spending key. Fourteen bindings each carry a forgery proving that binding fires, and a meta-test fails if a binding is added without one. The forgery suite runs against a minimal instance so it gates every change, with the full deployed depth as a release gate, because a minimal stand-in is only valid while it provably tracks the real one.

The key hierarchy is frozen and dual-reproduced. The recursion hash runs at the deployed round count.

On settlement, the split-transaction verifier is built and gated against the real L1 vector: accept-real plus the reject suite, with begin measured at 32.7M gas against a 36M block ceiling. Single-transaction verification at 128-bit security was measured at 121M gas and is therefore impossible on L1, which is why settlement is split across transactions with the first one binding every challenge and query index so later chunks cannot be crafted independently.

The pool contract carries a fail-closed beta gate: allowlist, per-asset caps, and refunds that always return to the recorded depositor, so governance can push funds to that person and to nobody else.

What is not done is the emit

The production vector still carries a plumbing stand-in rather than the live circuit, so the artifacts in spec/ attest structure and not notes. Closing that is the next milestone, and this document does not pretend otherwise.

The memory wall, and why it stopped being the blocker

Measured

The pre-shrink production shape came to roughly 11.6 TB of large-domain evaluation for a single prove, about 10.2 TB of it periodic columns, some ninety times what a 128 GB machine holds.

Measured, and public on main

The technique that changes this is already proven at a smaller scale. In the recursion circuit, half the rows were recomputing a schedule that depends on nothing but the circuit itself. That recompute was not optimised, it was removed: hoisted into a commitment baked once per circuit version, after which each prove carries one opened row per query instead of the recompute. The circuit halved. The same treatment applied to the periodic columns takes them out of proving entirely rather than making them smaller.

Projected, not yet measured

Applying that to the production shape, with the wide trace commitment and streaming, is expected to leave a working set of coefficients, one coset and pruned tree layers, in the region of 15 to 40 GB per prove, with a one-time bake streaming on the order of 10 TB without materialising it and running for hours once per circuit version.

Those last figures are projections from a shape nobody has yet built at full scale, and this document does not treat them as results. The first production bake receipt is what converts them, and until it exists the re-emit below is gated on that receipt and on nothing else.

Milestones

Production re-emit

The wide trace commitment merges, the periodic bake runs for the real join-split, and the emit pipeline is repointed from the stand-in to the live circuit with its real public words. Two to three weeks from the merge: roughly a week of emitter wiring and gates, one bake run, one prove run, and slack for the first-full-scale-run bug that history says to budget for. Gate: the bake receipt. Nothing downstream starts until it exists.

Contracts re-gate

One vector, one re-gate: accept-real plus fourteen forgeries rejecting individually through deployed bytecode, named one-to-one against the binding inventory so the two lists cannot drift.

Gauntlet and audit preparation.

External audit,

published with our responses whatever it says.

Live prover and custody

Three-of-five Safe. The custody line stays off until the audit closes.

Gated beta

Allowlist, per-asset caps, fail-closed by default so a fresh pool refuses every deposit until opened deliberately. Ending beta is one-way.

Public deposits.

Swaps after transfers,

on the same shape, with the Poseidon2 gas decision and the clearing statement below.

Decisions recorded

Association set: out of the launch shape, deleted rather than flagged

It doubles inner rows for every transfer, and that cost survives every outer optimisation because it is inner length rather than outer degree. begin has no headroom for the doubled recompute. It returns after launch as its own circuit with its own verifying key, which is the honest shape for selective disclosure: no user should pay four times the proving cost on every ordinary transfer for a feature most transfers never invoke.

Poseidon2: not a transfers decision

Its win is a cheaper linear layer rather than fewer rounds, so trace length and evaluation domain do not move. It is a gas question on the swaps verifying key and rides the swaps emit if a hotspot pass says the gas is worth a second audit surface. It stays out of this re-emit so contracts re-gate one shape.

Clearing

the launch statement enforces price uniformity; clearing correctness at that price is enforced at the swaps upgrade. Recorded here as a boundary rather than discovered later as a gap.


Chapter

Continuous tracks

Continuous tracks

Proof

The spine first: enrolled bytes and granted authority over the real code, then extended to concurrency. Full functional correctness of the kernel in the seL4 sense is not the goal, and pretending otherwise would waste everyone's time. Ours is the runtime claim, and it is the one nobody else is making.

Performance

Cycles, published per release, with history and a diff tool. A published number is one we can be held to.

Documentation

Continuous rather than a phase. Verified against the code it describes, with getting-started guides tested by someone who did not write them.

Security debt

The security clock moves off uptime onto attested time before v0.9.5.

Chapter

What we are not doing

What we are not doing

Announcing hardware as supported before the matrix shows it green.

Shipping a capability, a proof or a driver that is written but unwired. If a running system cannot reach it, it does not appear in a release note.

Claiming Shield attests properties the emitted vector does not carry. That gap closes at the production re-emit, and until it does this document says so.

Blurring verified software and confined software. A translated Linux binary is the second, never the first.

The word costs a month of somebody's life or it does not get used.

Calling anything a daily driver from a demonstration. The word costs a month of somebody's life or it does not get used.

The interesting claim is not on the chain.

Shipping a new chain, a new token standard or a new consensus. The interesting claim is not on the chain, and adding one would be a way of avoiding the claim rather than making it.

Chapter

Open decisions

Open decisions

Each of these changes the plan, each has someone who decides, and each has a point past which not deciding is itself a decision.

Prover hardware calendar

The Shield bakes and production proves want the same 56-core machine for hours-long runs that kernel CI and SMP stress also want. Whoever holds the kernel side names the weeks it is theirs, before the bake is scheduled. Not deciding means discovering the contention during the bake, which is the one moment it costs the most.

Association set, post-launch shape

Decided out of the launch shape and deleted rather than flagged. What remains open is whether it returns as its own circuit with its own verifying key, or not at all. Decide after the audit, on evidence about who actually wants selective disclosure, not before.

Poseidon2 on the swaps verifying key

A gas win against a second audit surface. Decided by a hotspot pass on the swaps emit, not by preference, and explicitly not part of the transfers re-emit.

SMP scope for v0.9.4

Whether per-CPU run queues with work stealing ship in the same release as default-on SMP, or whether default-on ships on the existing queue and stealing follows. Decided by what the interleaving models find. Landing both at once is the preference; splitting them is the fallback that keeps the release date.

Hardware matrix privacy floor

The census reports carry device identifiers and verdicts today. Whether they may ever carry firmware versions, which are more identifying, is a decision to make before the matrix is public rather than after people have submitted rows under one understanding.

Which machine the residency runs on, and whose

It has to be a laptop on the public matrix, because a residency on a machine nobody else can buy proves nothing transferable. Which of us gives up their working machine, and which model, is decided when the matrix has enough rows to choose from rather than by picking the one we happen to own. Not deciding until the release before it means the log starts after v1.0-rc is signed rather than with it, and v1.0 waits on the log.

How the chain gets read

The payment path verifies receipts and does not yet verify that the receipt came from the canonical chain. The options are a light client with header verification and inclusion proofs, which is the answer that matches everything else in this system and costs real work, or a declared trusted endpoint, which is honest but is a hole in the argument. Choosing the second and saying so is better than choosing it quietly. This has to be answered before entitlements gate spawning, because that is the moment a bad answer starts refusing to run software people paid for.

Where micro fees settle

Rollup, payment channels, or broker-batched mainnet settlement. Each is a real answer with a real cost, and the third one reintroduces exactly the trust this project exists to remove, so it is the one that needs the strongest argument if it wins. Decided before entitlements gate spawning, because changing the settlement layer after people have paid is not a migration anyone enjoys.

Third-party publisher policy

Namespace binding makes impersonation impossible, but nothing in the mechanism decides whether we review what a publisher ships or only that it is theirs. That is a governance choice with a technical consequence, and it has to be answered before the first outside publisher enrolls in v0.9.5.

Chapter

If something takes longer

If something takes longer

Nothing here is late, because nothing here is dated.

Nothing here is late, because nothing here is dated. What can still go wrong is order: a gate that does not pass when the work after it is ready. The train is arranged so that one held gate does not hold the others, and the moves are written down in advance so nobody improvises one under pressure.

If interleaving coverage stalls, default-on SMP still ships on the existing single queue and per-CPU queues with work stealing move to v0.9.5. The proof spine, the IOMMU domains and installer steps 4 and 5 are unaffected, because none of them depend on concurrency.

If the Shield bake overruns, the re-emit moves and everything downstream of it moves with it, in one block: contracts re-gate, audit, custody, beta. The OS train is untouched, because the only thing they share is the machine and that is calendared.

If the AML corpus pass rate stalls, phases 3 to 5 move to v1.0-rc and suspend moves out of this window. The evaluator still ships as what it already is at that point, a better resource extractor, which improves device enumeration whether or not power management is attached to it. The residency then runs on a machine that never sleeps and the log says so on every line, which is a worse result honestly reported rather than a quieter one. Nothing else in the train depends on it, which is why it sits where it does.

If the audit finds something structural, beta does not open. The fail-closed default means a pool that never opens is safe rather than broken, and we would rather explain a delay than a drained pool.

If aarch64 parity is not ready for v1.0-rc, it ships as a preview for one more release rather than as a signed target, and the release keeps its name because parity was never the thing that made v1.0 mean something.

What never moves

the evidence. A release that cannot publish its attestation surface, its reproducibility result and its performance numbers does not ship at all, whatever else is in it.

Chapter

Risks

Risks

The first production bake

The 15 to 40 GB projection is sound reasoning about a shape nobody has built at full scale. The bake receipt converts it, and it is why the re-emit is gated on the receipt rather than on a calendar.

AML's input belongs to other people

Every other piece of work here has an input we control. This one's is firmware written by other companies against another implementation's behaviour. The method answers it: the corpus turns unknown firmware into a measured pass rate from week one, and the census ships two releases ahead so the corpus exists before the evaluator does. What the method cannot fix is corpus width. If the matrix stays narrow, the pass rate is high against tables that do not represent the population, and the first honest test is somebody else's laptop.

The residency is a person's month

One of two people loses their working machine to it, on a system whose gaps we already know. It is scheduled where it is because a v1.0 that nobody has lived on is a version number and not a claim, but it is a real cost and it lands on a small team.

Prover hardware is shared

Bakes and production proves want the same machine for hours-long runs that kernel CI and SMP stress also want. Calendared in advance rather than discovered as contention.

External contributors move at their own pace

The v1.0 criterion depends on someone outside the project shipping a capsule. We can build the path and write the documentation. We cannot schedule a stranger.

Two people

The documentation program and the proof walk are the mitigation, and both ride the train rather than following it.

Chapter

How to hold us to this

How to hold us to this

Every release ships its attestation surface as an asset and on verify.nonos.software. From v0.9.3 the performance numbers ship with it. The hardware matrix is public and its rows are cryptographically verifiable. Shield's re-emit is gated on a bake receipt that either exists or does not.

A table you can only pass is not a test.

The day table at the top of this document is republished with every release, with the same rows and the state moved. A row that goes green names the release it went green in. A row that does not move stays on the page saying so, because a table you can only pass is not a test.

The residency log is public while it is happening, not summarised afterwards.

If a release lands without the evidence its section names, the honest conclusion is that we did not do what this document says.

verify.nonos.software