Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 383522450a | |||
| 1a8bed11e7 |
+20
-4
@@ -1,3 +1,19 @@
|
|||||||
|
## v0.158.1 — security review of v0.158.0: the mkfs wrapper trusts no sibling claim; the internal-place helper fails closed (2026-10-16)
|
||||||
|
|
||||||
|
**v0.158.0 is superseded — do not vouch it.** A security review of `912f7c1` found two defects; both fixed here, each test
|
||||||
|
seen failing against the 0.158.0 script:
|
||||||
|
- **`felhom-mkfs-guarded`**: 0.158.0 let a format through when a SIBLING part was mounted at /mnt/<name> AND under
|
||||||
|
/mnt/felhom-drives („Felhom's own drive"). That corroboration is a mount the agent can make itself, so a compromised agent
|
||||||
|
could unlock a host owner's disk — the exact case this root wrapper exists for. Removed: any mount of any node outside
|
||||||
|
/mnt/felhom-drives refuses again (now read from the kernel's mount table for every node; an unlistable disk refuses).
|
||||||
|
Consequence: the free part next to an in-use Felhom drive cannot be formatted — `CandidatePartition.Formattable` is false
|
||||||
|
for every part of a disk with a mounted node, and the controller does not offer it (a part with a filesystem can still be
|
||||||
|
USED). Pinned by configs/test_felhom_mkfs_guarded.py + partitions_test.go.
|
||||||
|
- **`felhom-internal-place`**: a failed `lvs` listing read as „nothing promised" (a too-large place) and a `blkid` error read
|
||||||
|
as „no signature" (the only gate before mkfs). Now: a failed listing, a listing without the pool, or any blkid exit other
|
||||||
|
than 0/2 REFUSES. Three new tests, all failing against 0.158.0.
|
||||||
|
- Released: tag `v0.158.1` (code `98f3cdd`), sha256 `20264df6…84b76a1`, bundle `c23c3d35…cb1c41b`. **Not vouched.**
|
||||||
|
|
||||||
## v0.158.0 — the internal data place; partitions as places; add_internal_place (2026-10-16)
|
## v0.158.0 — the internal data place; partitions as places; add_internal_place (2026-10-16)
|
||||||
|
|
||||||
Design: felhom.eu `architecture/16-storage-physical-identity.md` §5, §6, §7, §9 (operator rulings D3–D5; the D3 sizes
|
Design: felhom.eu `architecture/16-storage-physical-identity.md` §5, §6, §7, §9 (operator rulings D3–D5; the D3 sizes
|
||||||
@@ -17,12 +33,12 @@ ruled 2026-10-16 after the space check, felhom.eu `audits/storage-identity-build
|
|||||||
- **Partitions as places** (`internal/storage/partitions.go`): `GET /disks/candidates` lists each partition of a free
|
- **Partitions as places** (`internal/storage/partitions.go`): `GET /disks/candidates` lists each partition of a free
|
||||||
disk as empty / filesystem / in_use. A data-bearing part's wipe id binds disk id + part number + fs-UUID
|
disk as empty / filesystem / in_use. A data-bearing part's wipe id binds disk id + part number + fs-UUID
|
||||||
(`byid:<…-partN>+fsuuid:<uuid>`); both must name the same device at format time.
|
(`byid:<…-partN>+fsuuid:<uuid>`); both must name the same device at format time.
|
||||||
- **`felhom-mkfs-guarded`**: a SIBLING part that is Felhom's own drive (mounted raw at /mnt/<name> AND under
|
- **`felhom-mkfs-guarded`** (REVERTED in v0.158.1): a SIBLING part that is Felhom's own drive no longer blocked formatting
|
||||||
/mnt/felhom-drives) no longer blocks formatting the free part next to it; every other mount still refuses; an
|
the free part next to it. First tests of the wrapper: `configs/test_felhom_mkfs_guarded.py`.
|
||||||
unlistable disk now refuses (it passed before). First tests of the wrapper: `configs/test_felhom_mkfs_guarded.py`.
|
|
||||||
- `configs/` changed (sudoers `FELHOM_INTERNALPLACE`, the helper, the wrapper, the bundle list) — **a config-bundle job
|
- `configs/` changed (sudoers `FELHOM_INTERNALPLACE`, the helper, the wrapper, the bundle list) — **a config-bundle job
|
||||||
is needed** with the agent update. **Not vouched** (the operator's act).
|
is needed** with the agent update. **Not vouched** (the operator's act).
|
||||||
- Released: tag `v0.158.0` (code `912f7c1`), sha256 `a3589d1d…2caba`, bundle `17066273…fb5c76`.
|
- Released: tag `v0.158.0` (code `912f7c1`), sha256 `a3589d1d…2caba`, bundle `17066273…fb5c76`. **Superseded by v0.158.1 —
|
||||||
|
do not vouch** (its mkfs wrapper trusted a sibling claim the agent can fake; its helper failed open).
|
||||||
|
|
||||||
## v0.157.0 — every storage place knows its physical disk(s); POST /disks/same-disk (2026-10-15)
|
## v0.157.0 — every storage place knows its physical disk(s); POST /disks/same-disk (2026-10-15)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# CONTEXT — felhom-agent working state
|
# CONTEXT — felhom-agent working state
|
||||||
|
|
||||||
|
> **2026-10-16 — v0.158.1 RELEASED and VOUCHED (storage identity build B; 0.158.0 superseded, do not vouch).** The internal
|
||||||
|
> data place (root helper `felhom-internal-place`, the record in the state dir, mounted at /mnt/belso like a drive), the
|
||||||
|
> signed `add_internal_place`, partitions in `/disks/candidates` (`formattable` only while nothing on the disk is mounted),
|
||||||
|
> the partition wipe id `byid:<…-partN>+fsuuid:<uuid>`, the strict mkfs wrapper. Delivered through step bundle
|
||||||
|
> `0.158.1-step1` (a bundle that adds a path, R16). Next: R-1093 (an empty part's probe reads the parent's partition table).
|
||||||
|
|
||||||
> **2026-10-15 (night) — v0.157.0 RELEASED, NOT VOUCHED (storage identity build A, felhom.eu `16` §13).** Every storage
|
> **2026-10-15 (night) — v0.157.0 RELEASED, NOT VOUCHED (storage identity build A, felhom.eu `16` §13).** Every storage
|
||||||
> place carries `kind`, `physical_disks`, `identity` (+ reason) in `GET /disks` and the hub report; `POST /disks/same-disk`
|
> place carries `kind`, `physical_disks`, `identity` (+ reason) in `GET /disks` and the hub report; `POST /disks/same-disk`
|
||||||
> answers the controller (v0.317.0, MinAgent 0.157.0). Computed on every read, never cached. Delivered by signed jobs to
|
> answers the controller (v0.317.0, MinAgent 0.157.0). Computed on every read, never cached. Delivered by signed jobs to
|
||||||
|
|||||||
@@ -1,43 +1,42 @@
|
|||||||
# REPORT — v0.157.0: every storage place knows its physical disk(s); POST /disks/same-disk (2026-10-15)
|
# REPORT — v0.158.1: the internal data place, partitions as places, add_internal_place (2026-10-16)
|
||||||
|
|
||||||
Written in ASD-STE100 Simplified Technical English. Design read first: felhom.eu `architecture/16-storage-physical-identity.md`
|
Written in ASD-STE100 Simplified Technical English. Design read first: felhom.eu `architecture/16-storage-physical-identity.md`
|
||||||
(§3, §4, §8, §10; ACCEPTED 2026-10-15, §13 = what was built), `03-host-agent.md`. Task: storage identity build A (operator
|
(§5–§7, §9, §13), `03-host-agent.md`. Task: storage identity build B. v0.158.0 is superseded (security review) — do not vouch it.
|
||||||
rulings D1–D6). Controller counterpart: felhom-controller v0.317.0 (MinAgent 0.157.0); hub v0.154.0 shows the fields.
|
|
||||||
|
|
||||||
## What changed
|
## What changed
|
||||||
|
|
||||||
- `internal/storage/identity.go`: the physical disk(s) under a place, from `/sys`, `/run/udev/data`, `/proc/mounts` only
|
- `configs/felhom-internal-place` (bundle): the ruled size rule, the only lvcreate/mkfs of a system-disk volume; fails closed
|
||||||
(no block I/O). `proven`, or `unknown` with `vm` / `network` / `usb_bridge` / `weak_wwn` / `no_serial`.
|
on any failed read. Run by the installer (1.33.0 step 5b) and by the new signed op.
|
||||||
- `GET /disks` rows and the hub report's `storage_targets` gain `kind`, `physical_disks`, `identity`, `identity_reason`.
|
- `internal/localapi/internalplace.go`: the record → mount at `/mnt/belso` by fs-UUID like a drive, kind `internal`; never takes a
|
||||||
- `POST /disks/same-disk` `{a, b}` → `{different, proven, reason, a, b}`; scoped like every `/disks` call; a path the agent
|
household drive's `/mnt/belso`; eject/decommission/format refused.
|
||||||
did not mount itself is `unmapped`.
|
- `internal/signedjobs/internalplace.go`: `add_internal_place` (operator key, no parameters).
|
||||||
- `configs/` unchanged.
|
- `internal/storage/partitions.go`: each part of a free disk listed (empty / filesystem / in_use, `formattable`); a data-bearing
|
||||||
|
part's wipe id binds disk id + part number + fs-UUID (`durable_device.go`).
|
||||||
|
- `configs/felhom-mkfs-guarded.sh`: every mount of every node outside /mnt/felhom-drives refuses (kernel mount table); an
|
||||||
|
unlistable disk refuses; NO exemption for a sibling claiming to be Felhom's own (0.158.0 had one — removed).
|
||||||
|
- Sudoers `FELHOM_INTERNALPLACE` (`^(plan|create) 0$`); capability manifest + injection cases.
|
||||||
|
|
||||||
## Tests and red-proofs
|
## Tests and red-proofs
|
||||||
|
|
||||||
Fixture `/sys` + udev trees for every spike case and five same-disk handler tests. Seen failing first: the LVM thin
|
configs/test_felhom_internal_place.py (13), configs/test_felhom_mkfs_guarded.py (8 — first tests of the wrapper; the 0.158.0
|
||||||
„diamond" (tmeta/tdata under one pool) read as a failure — fixed by counting a seen node once. Broken on purpose and seen
|
wrapper and the old one measured against them), internalplace_test.go (9), internalplace (signedjobs, 4), partitions_test.go
|
||||||
failing: the VM rule, the vendor-less WWN rule, the own-mount rule (an absent drive), the `sys_drive` mapping.
|
(3), partition_durable_test.go (4), the sudo rule widened → caught. Every new test seen failing first. `agent_gates.py`: green.
|
||||||
`python3 scripts/agent_gates.py`: all OK.
|
|
||||||
|
|
||||||
## Release and delivery
|
## Release and delivery
|
||||||
|
|
||||||
- `scripts/release-agent.sh 0.157.0`: tag `v0.157.0`, sha256 `addd4041…0aef`, bundle `0604bc60…397a`.
|
`release-agent.sh 0.158.1`: sha256 `20264df6…84b76a1`, bundle `c23c3d35…cb1c41b`. The bundle ADDS a path, so boxes on an older
|
||||||
- Delivered by signed `agent_update` jobs to Tester 1, demo-hp and the N100 (the three test boxes). **NOT VOUCHED** — the
|
wrapper refuse it (R16): a step bundle `0.158.1-step1` (sha `fd968ee1…5c2eb9`, the 0.156.1 bundle with only `felhom-os-apply`
|
||||||
operator's act. Until the vouch, the global floor cannot declare MinAgent 0.157.0.
|
replaced) was published, then per box: agent_update 0.158.1 → step bundle → bundle 0.158.1. Done on Tester 1, demo-hp, the N100.
|
||||||
|
**Vouched by the operator** (with golden 0.318.0).
|
||||||
|
|
||||||
## Live proof (method: the agent's local API on each PVE host, with the guest's own token)
|
## Live proof
|
||||||
|
|
||||||
| Box | `GET /disks` | same-disk: drive vs system data |
|
A fresh one-disk install (512 GB VM, installer 1.33.0): the place made (213 GiB), mounted by the agent, registered by the
|
||||||
|---|---|---|
|
controller; nothing of it in a whole-box copy; same-disk internal vs sys_drive: same disk, proven; partitions listed, formatted,
|
||||||
| demo-hp | `local`/`local-lvm` proven (SATA SSD), NVMe drive proven (`eui:`), PBS `network` | different, proven |
|
used. Evidence: felhom.eu `audits/storage-identity-buildB-2026-10-15/live/`.
|
||||||
| N100 | system proven (SATA SSD serial), USB drive proven (the bridge passes the real serial) | different, proven |
|
|
||||||
| Tester 1 (VM) | every place `unknown/vm` | not proven (`vm`) |
|
|
||||||
|
|
||||||
On all three: system data vs `/var/lib/docker` → same disk, proven; a drive name that is not mounted → `unmapped`. The hub
|
|
||||||
stored the same fields (read from its database with the WAL). Evidence: felhom.eu `audits/storage-identity-buildA-2026-10-15/`.
|
|
||||||
|
|
||||||
## Observations
|
## Observations
|
||||||
|
|
||||||
1. FILED: R-1083 — scratch box 9202 has no `local_api` in its `bootstrap.json`, so it cannot use any agent call.
|
1. FILED: R-1093 — an empty part asks for the typed confirmation: the probe reads the PTTYPE a partition inherits from its disk.
|
||||||
2. NOT-A-FINDING: `usb_bridge` is built from the design's rule and was not seen on a real enclosure; that is R-1077, already open.
|
2. NOT-A-FINDING: the step bundle was needed and is the documented route (R-880); the first 0.158.0 bundle jobs were refused by
|
||||||
|
R16 as designed, nothing changed on the boxes.
|
||||||
|
|||||||
Reference in New Issue
Block a user