feat(system): bind cubefs+cubecode+cubecrypt into one running system (cubesys)
Integrates Packages 3-5 over a single shared CubeStore, the literal CUBELinux premise (data addressed by coordinate, not path). Adds the cubesys crate (lib + cube CLI + cube-demo) proving two end-to-end properties: a cubefs path IS a runnable code cell at the same coordinate, and a sealed record reopens and runs on the same store. Two latent cross-crate bugs surfaced and fixed while integrating: - cubecoords: refresh_flags() now preserves out-of-band flag bits (8..=15), so cubecrypt's HEADER_FLAG_ENCRYPTED survives refresh. - cubestore: record codec now serializes raw flag bits (TLV tag 12) so the encrypted bit survives the store round-trip. All gates green (./check, incl. cubefs --features mount).
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# CUBELinux-2 system integration (`cubesys`)
|
||||
|
||||
This crate is the composition layer the PDF implies but does not name as a
|
||||
"Package 6". It binds Packages 3-5 (cubefs, cubecode, cubecrypt) into one
|
||||
running system over a **single shared `CubeStore`**, which is the literal
|
||||
CUBELinux premise: *data addressed by coordinate, not path.*
|
||||
|
||||
## The one invariant
|
||||
|
||||
> The cube is the single source of truth. cubefs is a *view* of it, cubecode
|
||||
> is a *kind* of record in it, cubecrypt is a *transform* applied to records
|
||||
> in it. None of them own storage.
|
||||
|
||||
That is what makes the integration real instead of three crates side by side:
|
||||
every layer operates on the same backend, so a write through one is visible to
|
||||
the others at the same coordinate.
|
||||
|
||||
## What binds to what
|
||||
|
||||
| Layer | Role in the system | Shares via |
|
||||
|--------------|------------------------------------------------------|----------------------------------|
|
||||
| `cubefs` | POSIX namespace; a path `C/Z/Y/X` is a coordinate | `CubeStore`, `path_to_czyx` |
|
||||
| `cubecode` | code cells stored *as records*; VM runs them | `CubeStore`, `CodeCell` |
|
||||
| `cubecrypt` | seals records under a `CubeEnv`; key in Null cubes | `CubeStore`, `CubeEnv` |
|
||||
|
||||
Two primitives in this crate do the binding:
|
||||
|
||||
* `path_to_czyx(path)` — the single bijection (re-exported from `cubefs`) so
|
||||
path and coordinate never disagree.
|
||||
* `load_code_cell(store, path)` — reads the record at a path's coordinate and
|
||||
decodes it as cubevm bytecode. A cubefs file **is** a runnable VM cell.
|
||||
|
||||
## End-to-end properties proved by the tests
|
||||
|
||||
1. **A path is a function.** Writing bytecode at `/c012/z001/y001/x021` makes
|
||||
cubefs list it as a file *and* the VM run it at `Czyx::new(12,1,1,21)` —
|
||||
same coordinate, two views. (Note: an axis value of `0` is Null control
|
||||
space and is rejected as a path component, so every user path maps to a
|
||||
coordinate with all axes in `1..=255`; keys and metadata live in Null
|
||||
space and are addressed directly by `C.Z.Y.X`.)
|
||||
2. **Seal then run is the same record.** `CubeEnv::put_encrypted` at a
|
||||
coordinate leaves the cube carrying an encrypted body (encrypted flag set);
|
||||
the raw body no longer decodes as bytecode. To *execute* a sealed record the
|
||||
system decrypts it back into a plaintext record at the same coordinate, then
|
||||
runs the VM (the VM runs code located by coordinate; reading the envelope
|
||||
directly would fail decode). `open` + `CodeCell::from_record` + `Vm::run`
|
||||
recovers and executes it on the *same* store.
|
||||
|
||||
## Bugs found and fixed while integrating (real, cross-crate)
|
||||
|
||||
Building the integration turned up two latent cross-crate bugs that the
|
||||
per-package test suites never exercised:
|
||||
|
||||
* **`CubeHeader::refresh_flags()` dropped out-of-band flag bits.** It recomputed
|
||||
`flags` only from structured fields (bits 0–7), so `cubecrypt`'s
|
||||
`HEADER_FLAG_ENCRYPTED` (bit 12), which is set out-of-band, was wiped on every
|
||||
refresh. `put_encrypted` calls `refresh_flags` before storing, so an encrypted
|
||||
record lost its flag. Fixed by preserving spare bits (8..=15) in
|
||||
`refresh_flags`. (`cubecoords`)
|
||||
* **The record codec never serialized `flags`.** `record_codec::encode_header`
|
||||
wrote only structured fields, and `decode_header` rebuilt `flags` from them —
|
||||
so even a correctly-set encrypted bit was lost on the store round-trip. Added
|
||||
tag `12` (raw flag bits) to the TLV codec so out-of-band bits survive.
|
||||
(`cubestore`)
|
||||
|
||||
Both are now guarded by `cubesys` integration tests.
|
||||
|
||||
## Why this, and not a "Package 6"
|
||||
|
||||
The PDF arc ends at cubecrypt; the only named next package is `cubeai`, which
|
||||
the directive explicitly excluded (hardware cannot run it). Integration is the
|
||||
honest completion: it turns five isolated crates into the coherent
|
||||
coordinate-addressed system the design describes, without inventing a package
|
||||
the spec never defined.
|
||||
|
||||
## Binaries
|
||||
|
||||
* `cube-demo` — self-contained tour (write two linked cells, run; seal a
|
||||
record, reopen + run). Prints evidence at each step.
|
||||
* `cube` — CLI: `write`, `run`, `ls`, `stat`, `seal`, `open` over one store,
|
||||
interactively (`repl`), from a file (`script`), or as the demo (`demo`).
|
||||
|
||||
## Building / testing
|
||||
|
||||
```sh
|
||||
cd /home/CUBELinux/CUBELinux-2
|
||||
./check quick # fmt + clippy -D warnings + tests (the gate)
|
||||
./check mount # also builds cubefs --features mount (FUSE adapter)
|
||||
cargo run -p cubesys --bin cube-demo
|
||||
```
|
||||
Reference in New Issue
Block a user