CUBELinux · The Unseen Volume

Report · 2026-09-23 · a store on a USB dongle, and what the test found · kernel 6.19.3-cubelinux0.7+ build #96
device passed through gate-verified no filesystem named as a space

Abstract

An ordinary USB stick was given a CUBE store, and a machine was asked to use it the way this system uses any store: write a record at a coordinate, let the writer go away, and find the record again on the device. It worked — and it was checked by a gate rather than by hand, because a claim about removable media that nobody re-runs is a claim about one afternoon.

Three things came out of it that were not the point of the exercise. A device can be named the way this substrate names anything — by a space of its own, with a portal as the doorway — and that is now built and gated. The volume is invisible to the desktop, and that turned out to be a property worth keeping rather than a gap to close. And the test, plus the work to make the write durable on that shape, found three real defects — one of which had made the store acknowledge writes it had never flushed.

1. The test, exactly

The device is a USB 2.0 mass-storage stick: FC0432F30D90B, 15.7 GB, reported by lsblk as a removable disk with transport usb and nothing else — no partition table, no filesystem, no label. It arrived carrying a CUBE image of its own: a v1 packed image at offset zero, from which 182,698 records parse in the first 17.8 MB (147,380 of them in the root space with zero-length values, 17,658 carrying printable 26-byte values), with CUBE-carrying payloads well beyond that. It was read, and never written, until it was declared scratch; the first 32 MB are kept aside as evidence.

The store written onto it occupies the first 64 MB: a control block, two image slots of 16,773,120 bytes each, and a log beside them. Nothing claims the other 15.6 GB, and that matters — see §4.

Then the proof, which is the shape every gate in this project takes: write through the interface, take the machine away, read it back off the device. The kernel ran in a VM with the physical stick passed through as its store device (-drive file=/dev/sda,format=raw), which is the honest version of "the bytes went to the hardware" that a testbed can give without rebooting the box into it.

before    : store : /dev/sda  control : copy A  generation=1   active_slot=0  image_off=4096
wrote     : 4 record(s) through cube(2), refused: 0
walk      : walk: 4 space(s), 8 record(s)          <- a LATER boot, off the device
entity    : this device is the space f9095c7496565ae5bc86cb27099ba930bc507df8acd84d6c5711064b091f58fd
identity  : device=FC0432F30D90B model=ProductCode bytes=15728640000 class=0xf9 space=f9095c…
portal    : stored at fefefe…:0,0,0 (kind 0x10), entered from 000000…:0,0,0, leads to f9095c…:0,0,0
after     : store : /dev/sda  control : copy B  generation=6   active_slot=1  image_off=16777216
PASS

The four records are the ones the initramfs writes through cube(2) — three in the root space and one in a space of its own — and the second boot walks the device's store and finds each of them at its coordinate. The store folds on the way (the active slot alternates and the generation advances), which is the same fold any other store gets: the device is not a special case to the kernel, it is a store.

Two device shapes are now proven end to end. One store is a file on ext4, which is what this machine serves; another is a device that is not in the machine at all. The gate is kernel/verify-dongle.sh, and it is careful about what it will touch: the device is found by its own serial rather than by /dev/sdX — a gate that formats the wrong disk is worse than no gate — it refuses a device that is mounted or carries a filesystem, and laying out a store on it is a separate, explicit PREPARE=yes-device mode that prints what it is about to overwrite.

2. A device is an entity, and this substrate names entities with a space

The useful part of the exercise was not that a stick can hold bytes. It is that the stick could be named the way everything else here is named. A path, a mount point, or /dev/sdX is exactly the kind of name this system was built to remove; a space is what it puts in their place. The cube-edge design proposed this for microcontrollers — a device as a first-class coordinate space, its relationships as edges, reached through a Portal — and a USB stick is the smallest possible form of that: the embedded part done by a mass-storage controller instead of an MCU.

The reserved space tags are classes: 0x00 root, 0xFB events, 0xFC boot, 0xFD keystore, 0xFE portal, 0xFF edges. A boot record lives in 0xFCFC…, and any kernel that can write one knows where to look. A device is the first class whose instances have to be told apart — two sticks are two spaces — so the tag names the class and the rest of the id names the instance:

space = 0xF9 ‖ SHA-256("cubelinux.device.v1:" ‖ identity)[0..31]

where identity is the device's own identifier: its USB serial, a board's MAC, whatever name a human gave the volume. The digest is not decoration. A portal's contract rests on a space id that cannot be guessed; an instance id has to be unguessable from the class and from another instance's id, and a counter or a truncated serial is neither. That convention lives in cube-core (SpaceId::DEVICE_TAG, for_device) with the reasoning and a test beside it — and deliberately not the digest, because that crate is no_std, allocation-free and dependency-free by design and a hash is a dependency. The tool that declares a device derives it, and the gate holds the two sides together exactly as verify-boot-record holds the kernel's 0xFC and userspace's boot together: the tool derives the space from the serial, the record is written there, and the kernel's own walk has to find it.

Declaring a device writes two records, and both are needed for it to be addressable rather than merely present:

recordwherewhat it says
identitythe device's own space, at (0,0,0)device=… model=… bytes=… class=0xf9 space=… prepared=… — one line of k=v, in the shape the kernel's boot record uses
portal0xFE, keyed by its source spaceentered from this machine's root, leading to the device's space; class 0x10 (PORTAL_KIND_DEVICE)

Writer and reader share one encoder: cube-image device-declare writes the descriptor with cube-index's own PortalDesc, and device-show decodes it with the same code, so a declaration cannot be written in a shape only the writer understands. The gate requires all of it from outside: the kernel's walk must report the device's space and its identity record, and the portal space and its descriptor, and then the descriptor has to decode off the device itself.

What is not built, and this is the honest half of the section: the doorway is not enforced. A portal's traversal checks that the caller is standing on the near mouth and nothing else, so "reach the device, and nothing else on it" becomes true only when that check exists. Capability by construction is the model; capability by enforcement is still the work. Nor is a device a space of this store: the kernel serves one store at a time, so the stick's space and this machine's spaces are one address space by naming, not yet by machinery.

3. The volume nobody can see

Neither GNOME Files nor Dolphin shows the stick. That is measurable rather than mysterious: udisks2 — which both go through — reports it with no IdUsage, no IdType, no IdLabel and no mount points, and blkid and wipefs -n find no signature at all. There is no filesystem and no partition table, because there is not supposed to be: the bytes are the addressing scheme. The desktop sees a disk with nothing mountable on it, and shows nothing.

The first instinct is to call that a gap. It is worth noticing what it buys instead:

What it costs is honesty about the other side: nobody is told the device is there, and a failing device is silent. Both have the same answer, and it is not a desktop integration: the portal space is the registry of doorways, so "what can I reach from here" is a walk of one space through cube(2) — a question the kernel already answers, asked by whoever holds the catalogue and invisible to everyone else. Device health is the proper job of the event vocabulary: the substrate can carry a class on every record, so "the thing behind this portal is degrading" should become a flagged record rather than a discovery made during an outage.

4. What the test found

Three defects, none of them the thing being tested, all of them now closed and all of them recorded in the build record's defect list.

4.1 A store with no control block acknowledged writes it never flushed

The store now writes its log entry unsynced and lets the control block's fsync carry both — one durability boundary per append instead of two, and about half a write's latency. That reasoning is sound where its sentence is true, and the sentence assumes there is a control block to write. A store built by the CLI has none. So on that shape the count write never happened, nothing on the append path was flushed at all, and the caller was told a write the machine might never get back. Measured, same device and the same four acknowledged writes, the host's copy of the device read while the guest was still hung:

shapeafter the kill
no control blockthe log holds its header and zeros; the fold returns the base store — records=2 — after four acknowledged writes
a formatted devicethe entry is on the device and the fold reproduces the userspace store exactly — records=6, fnv1a64=6b679d39597a62b3

Fixed in build #96 with one boolean: the entry carries its own fsync exactly when no later write in the same operation will carry one. The box's shape keeps the single sync and its measured 4.962 ms; the bare shape pays its entry's flush, which is what it always did. The gate was wrong the same way the first diagnosis was — it ran its crash check over one device shape — and it now runs over both, folding each the way userspace reads it and comparing both against the same userspace store.

4.2 A walk with no store behind it served invented records

The defect that opened this work: with cube_store pointed at something that is not a store, the walk served about two hundred thousand invented records a minute and never ended — a garbage space, a zero-length value, and a cursor that kept moving. The cause was not where it looked. Thirty-eight error returns in the store driver were negating an error code that is already negative, so every refusal reached its caller as a success; and the one walk arm that advances its own cursor turned that into a loop with no end signal. Fixed at the cause, and bounded in the one arm where a bogus success could still become a space.

cube_store=/dev/null cubelinux.enum=1  ->  0 records, "walk: spaces failed: Invalid argument", boot finishes in 5 s
before:                                   364,994 invented record lines in the 90 s the instrument allowed

It is the third loop this project has met, the first in what the kernel answered, and it is a gate now — verify-no-store, over both shapes of "no store": a device that cannot be read, and a store device that is not there at all.

4.3 The tooling asked to hold a whole device — fixed

Pointing a userspace reader at the stick does not read slowly, it dies. The file-backed store holds the entire file it is given, so a 15.7 GB device becomes 15.7 GB of resident memory, and the machine's own log has the receipt:

Out of memory: Killed process 2595013 (cube-image) total-vm:8391912kB, anon-rss:5159680kB

Two different things were being confused — a userspace image (bytes at offset zero, extent from the header) and a device (a control block at zero, the image in a slot, the log beside it). The kernel reads a device through its control block and bounds every read; the userspace reader had no such bound. And the OOM was the lesser half. That backend does not only read: on flush it truncates the file and rewrites it, so a command that opened a store device as an image and then wrote anything — a put, a checkpoint, a delete — would have taken the layout with it. Silent data loss, from a tool that believed it was opening a file at offset zero.

The fix is a refusal, before any read: four bytes of control-block magic, then a `stat` to see whether the path is a block device at all. Refused means refused — a gate now requires the file to be byte-identical afterwards — and the message names the reason and the remedy, so the reader that can answer is one line away: cube-image store-info|digest|flag-scan for a device's live image, cube(2) (and the front-end) for the whole store, image and log together. The same gate reproduces the OOM shape safely, with a 16 GB sparse file carrying the control-block magic: refused in 0 s, under a memory cap so that a future regression fails with an allocation error instead of taking the machine down with it.

What is deliberately not built, and this is the honest remainder: userspace still cannot read a whole device store. A device's log is a region of the same device, not a file beside it, and the WAL in the store crate is file-based — so the reader that merges image and log for a device is the kernel, and userspace reads images. The CLI's answer to a device is now a refusal that says where to go instead, which is the difference between a tool that fails and a tool that lies.

The same shape of problem appears from the other end with a bare image: with no control block there is no extent to bound it, so a walk of one reads the device to end of file. The first attempt to walk the stick's original v1 image spent minutes reading 15.7 GB before it was cut off. A store that states its own layout is not a nicety; it is what makes the read bounded.

5. What is not claimed

6. Checking this yourself

kernel/verify-dongle.sh                     # the round trip, on whatever stick is attached
kernel/verify-store-readers.sh               # a device refused before it is read, and left alone
kernel/run-all-gates.sh verify-no-store.sh  # the walk with no store behind it
cube-image device-space FC0432F30D90B       # the space a device is named by, from its serial
cube-image device-show <store> <identity>    # the declaration, decoded

The wall names 28 gates; the run for build #96 reports 26 of 26 pass, none red, and the dongle and store-reader gates were added and run alongside it: pass. The workspace suite is 218 tests, 0 failures. Where something above is not proven, §5 says so rather than rounding it up.