boot record: the kernel's own record supersedes the userspace marker

Resolves the open question the design doc carried since the boot record landed:
what do the two markers mean side by side. The answer is that there is one — the
kernel's. Both answered "when did this box boot", and the kernel's is self-authored
(the OS storing itself, not a client writing about the OS) and carries more (the
version banner and the resolved device). The userspace `last_boot` document is a
second mechanism beside the first, and "what did the agent see" is telemetry, not a
boot record. So the deployed marker — `deploy/cube-agent-boot.service` and
`deploy/boot_marker.sh` — is retired.

The switch does not become the compile-time default, for the reason it exists: the
gates' method is byte-for-byte comparability of a kernel-produced store against a
userspace-produced one, and an unconditional record would turn those comparisons
into non-comparisons. "The OS stores itself" ships by turning `cube_boot_record=1`
on at the box's command line, not by changing the kernel's default; teaching the
byte-comparison gates to expect the record is the separate follow-on if the default
is ever wanted.
This commit is contained in:
luulu
2026-09-21 20:40:18 -04:00
parent b9162d1a77
commit 08dbeb204c
3 changed files with 20 additions and 50 deletions
+20 -6
View File
@@ -363,9 +363,23 @@ Found while reconciling the record; all small, all worth doing before more is bu
exists and says the right things, the kernel serves it back through `cube(2)`, and userspace
reads the same bytes out of the folded image — a record only the kernel can read would be a side
channel, not a record.
* **Still ahead on the same claim, and worth keeping separate from the above:** the *deployed* boot
marker on the box is still a userspace write through the name tier
(`/home/luulu/.cubelinux-agent/boot_marker.sh`, §7.3). The kernel can now record its own boots, and
a gate proves it, but nothing yet runs with the flag on in production, and no one has decided what
the two markers mean side by side — whether the kernel's record replaces the client's, or both
stand for different questions ("which boot is this" versus "what did the agent see").
* **RESOLVED — what the two markers mean: the kernel's record replaces the client's.** The open
question just above ("whether the kernel's record replaces the client's, or both stand for different
questions") is now decided: **replace**. The two markers answer the same question — *when did this
box boot* — and the kernel's answer is the better one: it is self-authored (the OS storing itself,
not a client writing about the OS) and it carries more (the version banner and the store device the
kernel resolved). The client's `last_boot` document is a second mechanism beside the first — the
exact pattern §7.4 finds and removes — and "what did the agent see" is agent telemetry, not a boot
record, so it does not belong in the marker's slot. The userspace marker — the deployed
`cube-agent-boot.service` and its `last_boot` write through `cubed-names.sock` — is therefore
**retired**.
The switch does **not** become the compile-time default, and the reason is now recorded rather than
merely implied: the gates' method is that a store the kernel produces is comparable byte for byte
with a store userspace produces from the same mutations, and an unconditional record would turn
every such comparison into a non-comparison. "The OS stores itself" ships by turning the flag on in
production — `cube_boot_record=1` on the box's boot command line — not by changing the kernel's
default. If the default is ever wanted, the byte-comparison gates (`verify-syscall`,
`verify-kernel-append`, `verify-kernel-checkpoint`, `verify-enum`, `verify-range`) must first be
taught to expect and then verify the record; that is a separate, careful change, and it is the one
honest remaining item on this claim.
-17
View File
@@ -1,17 +0,0 @@
#!/usr/bin/env bash
# Boot marker writer for cube-agent-boot.service.
#
# Writes the boot timestamp through the `cubed` daemon via the Rust `cube-write` binary:
# one command, one socket, no second copy of the store image (two writers on one image
# silently overwrite each other, which is why everything goes through the daemon).
#
# The record is addressed by COORDINATE — `boot:0,0,0`, a space of its own so the marker
# cannot collide with anything else. There is no name option to fall back on: a name is not
# a coordinate, and turning one into the other belongs to whoever presents names.
# Overwriting the same cell every boot is the point: the value is the latest boot.
#
# Runs as luulu; needs XDG_RUNTIME_DIR so cube-write finds the cubed socket.
set -u
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/1000}"
TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
exec /home/CUBE-OS/target/release/cube-write --stdin "boot:0,0,0" <<< "${TS} BOOT"
-27
View File
@@ -1,27 +0,0 @@
[Unit]
Description=CUBELinux local agent boot self-check (writes last_boot marker via Rust cube-write)
Documentation=file:///home/CUBE-OS/INTEGRATION-cube-agent.md
After=network.target cubed.service llama-server.service
[Service]
Type=oneshot
WorkingDirectory=/home/luulu
# Wait for cubed Unix socket (the cube store) to be listening.
ExecStartPre=/bin/bash -c 'for i in $(seq 1 30); do [ -S /run/user/1000/cubelinux/cubed.sock ] && exit 0; sleep 1; done; exit 1'
# Wait for llama-server (local LLM) to be serving on :8080 (model load ~10s).
ExecStartPre=/bin/bash -c 'for i in $(seq 1 90); do (echo > /dev/tcp/127.0.0.1/8080) 2>/dev/null && exit 0; sleep 1; done; exit 1'
# Boot marker: deterministic write through the cubed socket via the Rust cube-write binary.
# UTC timestamp + BOOT word, at the coordinate boot:0,0,0 — a space of its own, so the
# marker is one cell that every boot overwrites. No LLM dependency -> always completes in
# under a second once services are up. Wrapped in a script so the timestamp is computed by
# bash, not systemd (which would mangle $(date ...) via its credential/env expansion).
ExecStart=/home/luulu/.cubelinux-agent/boot_marker.sh
Environment=XDG_RUNTIME_DIR=/run/user/1000
# The marker is written by name, so it goes through the name tier; the daemon
# itself serves coordinates only.
Environment=CUBED_SOCKET=/run/user/1000/cubelinux/cubed-names.sock
# Services up + instant write; small cap is plenty.
TimeoutStartSec=120
[Install]
WantedBy=default.target