From 3038b23ec757061119a3f05547df6e83d63e8acd Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 15 Oct 2026 20:08:08 +0200 Subject: [PATCH] Storage that knows its physical disks: design draft 16 + spike; R-1074..R-1079; STATUS D10 Spike (read-only probe, tools/physdisk_probe.py): the agent-side walk (partition -> disk, dm/LVM slaves, loop -> backing file) names the right physical disk for one-disk boxes, two disks, two partitions of one disk and a pass-through USB bridge; inside a VM (Tester 1) every disk is "unknown". Today's agent lists whole disks only and calls an empty partition table "data-bearing"; the controller's Tier-2 "different disk" is st_dev. sys_drive is a folder of mp0 (backup=1), so the design gives one-disk boxes a separate internal data place outside the whole-guest copy instead. Draft only; waits on the operator's rulings D1-D6 (16 section 12). 07 section 6.1's stale mp1 cell corrected. Register 163 -> 169. Scratch loop disk and Tester 1 scratch disk removed. Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb --- REPORT-storage-identity-2026-10-15.md | 79 ++ STATUS.md | 1 + .../architecture/07-backup-architecture.md | 2 +- .../16-storage-physical-identity.md | 188 +++++ .../B-case3-loop.json | 540 ++++++++++++++ .../B-case3-loop.txt | 6 + .../B-case4b-partitions-empty.txt | 8 + .../B-case4b-partitions.txt | 9 + .../B-case56-agent-blank.txt | 8 + .../B-case56-host-truth.json | 598 +++++++++++++++ .../B-case56-host-truth.txt | 4 + .../B-case56-setup.txt | 31 + .../B-case56-teardown.txt | 6 + .../B-case56-tester1-inside.json | 682 ++++++++++++++++++ .../B-demo-hp.json | 480 ++++++++++++ .../storage-identity-2026-10-15/B-demo-hp.txt | 33 + .../storage-identity-2026-10-15/B-n100.json | 330 +++++++++ .../storage-identity-2026-10-15/B-n100.txt | 23 + .../B-tester1.json | 648 +++++++++++++++++ .../storage-identity-2026-10-15/B-tester1.txt | 37 + .../storage-identity-2026-10-15/README.md | 60 ++ .../tools/agent_read.sh | 7 + .../tools/physdisk_probe.py | 153 ++++ .../tools/summarize.py | 8 + documentation/backlog/OPEN-ITEMS.md | 14 +- 25 files changed, 3950 insertions(+), 5 deletions(-) create mode 100644 REPORT-storage-identity-2026-10-15.md create mode 100644 documentation/architecture/16-storage-physical-identity.md create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case3-loop.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case3-loop.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case4b-partitions-empty.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case4b-partitions.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-agent-blank.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-setup.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-teardown.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-case56-tester1-inside.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-demo-hp.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-demo-hp.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-n100.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-n100.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/B-tester1.json create mode 100644 documentation/audits/storage-identity-2026-10-15/B-tester1.txt create mode 100644 documentation/audits/storage-identity-2026-10-15/README.md create mode 100644 documentation/audits/storage-identity-2026-10-15/tools/agent_read.sh create mode 100644 documentation/audits/storage-identity-2026-10-15/tools/physdisk_probe.py create mode 100644 documentation/audits/storage-identity-2026-10-15/tools/summarize.py diff --git a/REPORT-storage-identity-2026-10-15.md b/REPORT-storage-identity-2026-10-15.md new file mode 100644 index 00000000..cac0b0e4 --- /dev/null +++ b/REPORT-storage-identity-2026-10-15.md @@ -0,0 +1,79 @@ +# REPORT — storage that knows its physical disks: design draft + spike (2026-10-15) + +Written in ASD-STE100 Simplified Technical English. Baselines read 19:50: felhom.eu `340804f9af`, felhom-controller +`83392064ae`, felhom-agent `d2053e7d47`. Read first: `03-host-agent.md`, `04-control-plane-authorization.md`, +`07-backup-architecture.md` §6 and §7.5, `15-media-library.md`, `02-controller-module-map.md`, the agent's `/disks` +code and classifier, the controller's drive model and Tier-2 choice, the installer's `step_grows`. +Design: `documentation/architecture/16-storage-physical-identity.md` (DRAFT). Evidence: `documentation/audits/storage-identity-2026-10-15/`. + +## What waits on you + +**Answer six questions: `16-storage-physical-identity.md` §12 (STATUS D10).** My picks: D1 (a), D2 (a), D3 (a), D4 (a), +D5 (a), D6 (a). If you do nothing: one-disk boxes keep refusing media apps, and boxes in a VM keep counting same-disk +copies as second copies. Nothing is built until you answer. + +## 1. Did the agent-side method name the right physical disk? (Part B) + +| Case | Right? | +|---|---| +| 1 One disk (N100, demo-hp): every system place → the one SSD | yes | +| 2 Two disks: system vs enrolled drive (demo-hp, N100) | yes | +| 3 Two partitions of one disk (a scratch loop disk) | yes — after one fix in my probe | +| 4a USB bridge that passes the identity (N100's backup drive) | yes | +| 4b USB bridge that hides the serial | not measured — no device (R-1077) | +| 5 / 6 Inside a VM: same host disk vs a different host disk | both „unknown" — correct | +| 7 Network share | „network, unknown" by rule (no live share mounted today) | + +**VM cases in one sentence:** inside a VM all virtual disks look the same, so the agent can only say „unknown". + +## 2. The design in eight lines + +1. Every storage place gets `physical_disks` and `identity: proven | unknown`, with a reason. +2. The agent computes it from `/sys` and udev; the controller only asks. The hub gets it in the report. +3. A disk's key is bus + model + serial; a vendor-less WWN is not trusted. +4. Tier-2 counts as a second copy only on proven different disks. Otherwise the page says „only one copy", in plain words. +5. A one-disk box gets an internal data place on the system disk, outside the whole-box copy. Media apps then install with no extra step. +6. Films never go into `sys_drive`: it is inside every whole-box copy. +7. A partition can be a storage place. The classifier judges the partition. Only the installer makes partitions. +8. A VM box is always „unknown". The OMV guide says: a second disk must be a different physical disk. + +## 3. The decisions (my pick first) + +- D1 same-disk second copy: **do not make it**; say „only one copy". +- D2 unknown disks: **never count them**; the copy is still made. +- D3 installer: **`mp0` 70/130/250 GiB, reserve max(16 GiB, 10 %), the rest is the internal place** (512 GB disk → ≈ 152 GiB, 1 TB → ≈ 438, 2 TB → ≈ 1,266). +- D4 old one-disk boxes: **a plain sentence**; the internal place only by a signed operator job. +- D5 partitions: **the installer only** this round. +- D6 NAS films (R-1071): **a separate decision**; this design makes it easier, not harder. + +## 4. What the build task will change + +- Agent: place identity in `/disks` and in the hub report; a „same disk?" call; partitions as candidates; the loop step. +- Controller: Tier-2 and the one-copy notice ask the agent; the sentences move to i18n (informal voice); the install refusal in words; the internal place registered as the default drive. +- Installer: `step_grows` with the new rule; the internal LV, mounted on the host like a drive. +- Hub: store and show the two new fields. +- Guides and website: the OMV guide's second-disk line; the backup explanation page. + +## 5. Claims in the brief that were wrong + +- „That volume is the guest's `mp1 /mnt/sys_drive`" — wrong. There is no `mp1`. `sys_drive` is a folder of `mp0` + (`/var/lib/felhom`, `backup=1`), next to Docker (all three boxes; `07` §7.5.1). This is why films must not go there. +- „The installer … data volume" — partly wrong: the installer computes the size; the agent grows `mp0`. +- „The classifier must judge the partition, not refuse the whole disk because it has a partition table" — today it + does not refuse: it marks the whole disk „data-bearing" and offers only „initialize" (wipe all, customer-confirmed). + An empty partition is never offered (measured). +- „Tier-2 = a mirror on the second drive" — incomplete: there is also a state-only fallback onto `sys_drive` (`tier2.go:157-178`). +- R-1068's „probable way through — attaching `sys_drive`" — it would work in code, but it puts films into every + whole-box copy. The design rejects it. + +## 6. Commits, register, STATUS + +- One commit to felhom.eu (design, evidence, rows, STATUS, this report). +- Doc fix without a row: `07-backup-architecture.md` §6.1 still named `mp1`; corrected (the document contradicted live source). +- **Register: 163 → 169.** Opened 6 (R-1074 to R-1079), closed 0. Updated R-1068 (now waits on D3/D4). +- STATUS: line D10 in „Waiting on you — decide". +- Boxes put back: the scratch loop disk on demo-hp and the scratch virtual disk on Tester 1 are removed; nothing that + held data was written; DooPlex and ep0 not touched. My first loop try left the loop device for about one minute (a + missing tool); I removed it at once. +- No product code changed. No changelog entry: this repo has changelogs only for hub, scripts, website and marketing. +- `unproven.py`: unchanged (35 of 55 not walked). diff --git a/STATUS.md b/STATUS.md index 67b534c4..669d5807 100644 --- a/STATUS.md +++ b/STATUS.md @@ -45,6 +45,7 @@ | D7 | R-990, R-989 | Rule yes / no / later on the forum ideas (`audits/forum-research-2026-10-12/FELHOM.md` §5) and the selfh.st ideas (`audits/selfhst-survey-2026-10-12/FELHOM.md` §6) | — | — | nothing changes; the research ages | — | | D8 | R-206 | Install DooPlex's Docker settings from git (restarts Docker), and prune the build cache weekly: yes or no? | **Yes, in a quiet window** | — | a rebuild of DooPlex still has the settings in git | — | | D9 | R-1062 | The N100's USB drive is also its whole-box backup drive. Split it in two anyway? | **No — keep one drive**; the lived-in box keeps its nightly whole-box backup | Split: the box loses its local whole-box backup (or add a second drive first) | it stays one drive; multi-drive tests stay on Tester 1 | — | +| D10 | R-1079 | Storage that knows its physical disks (`architecture/16-storage-physical-identity.md` §12, six questions D1–D6): a same-disk second copy, „unknown" disks (VMs), the one-disk internal place and its reserve, old one-disk boxes, partitions, NAS films | **D1 (a) no same-disk copy · D2 (a) never count unknown · D3 (a) internal place, reserve max(16 GiB, 10 %) · D4 (a) a plain sentence · D5 (a) installer only · D6 (a) separate** | Other picks: more space spent on false copies, or films inside the whole-box copies | One-disk boxes keep refusing media apps; VM boxes keep counting same-disk copies | the build task | ## Waiting on you — do - **Nézd meg az új alkalmazás oldalt a demo-hp-n (egy telepített és egy nem telepített app).** Egy alkalmazás mostantól egy oldal négy füllel (Beállítások · Adatok és mentés · Útmutató · Napló), az Indítás/Újraindítás/Leállítás a „Működés" kártyán van, és a „Vissza" az alkalmazáshoz visz, nem a listához. Mondd meg, jó-e így az elrendezés. Ha nem nézed meg: a felület él, csak senki nem látta még böngészőben — a robot a DooPlexen nem tud kattintani. diff --git a/documentation/architecture/07-backup-architecture.md b/documentation/architecture/07-backup-architecture.md index a49db457..de212402 100644 --- a/documentation/architecture/07-backup-architecture.md +++ b/documentation/architecture/07-backup-architecture.md @@ -383,7 +383,7 @@ never moved by an update or an undo, and the unit restore accepts it. | **Tier-1** recovery unit | `/backups/primary//` on the app's own drive | compose + `.felhom.yml` + **secret-stripped** `app.yaml`, `db-dumps/*.sql`, `volume-dumps/*.tar`, `manifest.json` | nightly at W, plus a checksum-gated refresh on the periodic status pass | one point per app (`restore_points.go:14-18`) | no | | **Tier-2** cross-drive | `/backups/secondary//` | **always** a full mirror of the unit (`tier2.go:368-369`) **plus** `mandatory + optional` file legs, v2 layout `hdd/` + `userdata/` | nightly at W+60m | mirror (rsync) | no | | **Tier-3** restic offsite | Hetzner Storage Box over SFTP, one multi-path snapshot per app per run | the unit **plus** `mandatory` legs only; a separate `_shares` snapshot | nightly at W+105m | `--keep-daily 7 --keep-weekly 4 --keep-monthly 6` | **yes** (restic) | -| **Plane-2** whole-guest, local | `local:` → `/var/lib/vz/dump` on the host | rootfs + `mp0 /var/lib/docker` + `mp1 /mnt/sys_drive` | **24 h** (`backup_cadence_seconds: 0`) | `local_backup_retention: 3` | **no** | +| **Plane-2** whole-guest, local | `local:` → `/var/lib/vz/dump` on the host | rootfs + `mp0 /var/lib/felhom` (its `docker/` and `sys_drive/` folders, bound in the guest to `/var/lib/docker` and `/mnt/sys_drive` — §7.5.1; `mp1` no longer exists, corrected 2026-10-15) | **24 h** (`backup_cadence_seconds: 0`) | `local_backup_retention: 3` | **no** | | **Plane-2** whole-guest, offsite | `felhom-pbs:` → ep0 datastore `felhom-offsite`, per-customer namespace, over WireGuard | same contents | **7 days** (`604800`) | server-side prune on ep0, `keep-last 2` at `03:30` — **and the box asks for none** (R-191) | **yes** (per-customer key) | > **[FACT] Tier-3 has a fifth state the table above does not show: PAUSED (R-543, controller diff --git a/documentation/architecture/16-storage-physical-identity.md b/documentation/architecture/16-storage-physical-identity.md new file mode 100644 index 00000000..2ba182dd --- /dev/null +++ b/documentation/architecture/16-storage-physical-identity.md @@ -0,0 +1,188 @@ +# 16 — Storage that knows its physical disks + +> **What this is:** the design that lets Felhom know, for every storage place, which physical disk(s) it sits on — and +> use that to make backup tiers honest, to give one-disk boxes a place for household data, and to allow partitions. +> Operator ruling 2026-10-15: „Felhom must support drives split into parts; the agent and the controller must know +> whether two storage places sit on the same physical disk." Triggered by the OMV test (`audits/omv-vm-2026-10-15/`, +> R-1068). Spike: `audits/storage-identity-2026-10-15/` (Part B there). Marks as in `01`: **[FACT]** read in a named +> file or measured; **[DESIGN]** a proposal. **Status: DRAFT — waits on the operator's rulings in §11. Nothing is built.** +> Paths: A = `felhom-agent/`, C = `felhom-controller/controller/`, E = `felhom.eu/`. + +## 1. Today, in one table (Part A) + +| Place | Found by | Identified by | Mounted | What lives there | The backup page says | +|---|---|---|---|---|---| +| Host root / PVE `local` | PVE storage `local` [FACT] A/internal/storage/observe.go:424; never a candidate [FACT] A/internal/storage/role.go:53-79 | `path:` / `store:local` [FACT] A/internal/storage/durableid.go:54-67; role system | host `/`, `/var/lib/vz` | the **local whole-guest copies** (vzdump, retention 3) [FACT] E/scripts/felhom-host-install.sh:730-734; `07` §6.1 | `backup.target.degraded` „…ugyanazon a lemezen van, mint a rendszer…" [FACT] C/internal/web/backup_target_offer.go:78-100 | +| Guest `mp0` `/var/lib/felhom` with folders `docker/` and `sys_drive/` (bound to `/var/lib/docker`, `/mnt/sys_drive`) | config default `system_data_path=/mnt/sys_drive` [FACT] C/internal/config/config.go:166 | path only; „same disk" = `st_dev` [FACT] C/internal/system/mounts_linux.go:225-245 | thin LV in `local-lvm`, `backup=1` [FACT] A/configs/build-golden.sh:105, :221-225; measured on all 3 boxes | app volumes; Tier-1 of apps with no drive [FACT] C/internal/backup/backup.go:429-438; Tier-2 state-only fallback [FACT] C/internal/backup/tier2.go:157-178; **inside every whole-guest copy** | „Csak egy másolat készül (nincs második meghajtó)…" — a Go constant, not i18n [FACT] backup.go:359-361, :1387-1410 | +| Enrolled drive (`/mnt/` on the host → `/mnt/felhom-drives/`) | `GET /disks/candidates`: **whole disks only** [FACT] A/internal/storage/candidates.go:33-53 | mount: `uuid:`; wipe: `byid:` wwn > nvme-eui > … [FACT] A/internal/storage/durable_device.go:32-51 | systemd unit by fs-UUID through `FELHOM_MOUNT` [FACT] A/internal/storage/mountunit.go:50-65; host bind into `mp8` | `HDD_PATH` apps, media binds [FACT] C/internal/stacks/media_library.go:24-33; Tier-1/Tier-2; optionally the whole-guest target `felhom-backup`; **not in vzdump** (`mp8` is a host bind) [FACT] `07`:477-480 | Tier-2 badges; „Nincs 2. (off-drive) másolat" [FACT] C/internal/i18n/locales/hu.json:303 | +| Network share | customer input [FACT] A/internal/localapi/netstorage.go:36-40 | none („no durable-id, no SMART") [FACT] netstorage.go:15-19 | `.automount` under `/mnt/felhom-drives/` [FACT] A/internal/storage/netmount.go:18-31 | browse only; never media, never Tier-2 [FACT] media_library.go:83; tier2.go:141-143 | `err.backup.halozati_tarolo_nem_lehet_a_2` [FACT] tier2.go:37-40 | +| USB disk | same as an enrolled drive; transport never decides [FACT] C/internal/settings/settings.go:609-614 | same; the bridge may pass the real identity (N100: yes) [FACT] spike case 4a | same | same | same; SMART may be missing → „Nincs adat" | + +**[FACT] What compares physical disks today:** the controller compares only paths and `st_dev` (its own comment: +„two partitions on one physical disk look "different" here", mounts_linux.go:240-242). The agent has a whole-disk +compare (`SameWholeDisk`, role.go:207-216) but uses it only for eject/decommission roles. **[FACT] What knows about +partitions:** the agent accepts `/dev/sdb1` for inspect and mkfs (A/internal/storage/validate.go:28-32) but judges the +whole disk (claim.go:144-163), lists only whole disks, and calls a disk with a partition table or any filesystem +„data-bearing" (candidates.go:66-85). Measured: an empty partition next to another is never offered (spike). + +## 2. The spike in five lines (Part B) + +**[FACT]** A read-only walk (partition → parent; dm/LVM → slaves; loop → backing file → its disk) named the right +physical disk in every case on real devices: one-disk N100 and demo-hp (every system place → the one SSD), two disks +(system vs enrolled drive), two partitions of one disk (both → the same disk), a USB bridge that passes the identity. +**Inside a VM (Tester 1) it can only say „unknown"**: virtual disks on the same host disk and on a different host disk +look identical (`QEMU HARDDISK`, serial = the slot name `drive-scsiN`). Not measured: a USB box that hides the serial +(R-1077). Seen: a cheap SSD with a vendor-less WWN (OUI 000000, R-1076). Full table: `audits/storage-identity-2026-10-15/README.md`. + +## 3. The model + +**[DESIGN]** A **storage place** is anything Felhom stores on: the system data (`mp0`), the new internal data place +(§5), an enrolled whole disk, an enrolled partition, a network share. Each place carries: + +| Field | Meaning | +|---|---| +| `kind` | `system` · `internal` · `disk` · `partition` · `network` | +| `physical_disks` | the ids of the whole physical disks under it, e.g. `["serial:ATA:SanDisk_X600:182195804614"]` | +| `identity` | `proven` — every disk under it has a stable id the agent trusts; `unknown` — otherwise, with a reason code: `vm`, `no_serial`, `weak_wwn`, `usb_bridge`, `network` | + +**Disk id rule [DESIGN]:** `serial:::` from udev (`ID_BUS`, `ID_MODEL`, `ID_SERIAL_SHORT`); NVMe +`eui`/`nguid` when present. A WWN is used only when its NAA OUI is not `000000` (spike case 4c). Model + serial, not WWN, +is the primary key: two disks are „the same" only when the key is equal. + +**Unknown rule [DESIGN]:** `systemd-detect-virt` ≠ `none` → every disk is `unknown/vm`. A disk with no serial → `no_serial`. +A USB disk whose serial is the bridge's (all the same digit, or equal to a known bridge list) → `usb_bridge`. A network +share → `network`, `physical_disks: []`. + +**How it is computed [DESIGN]:** by the **agent**, as root, from `/sys` and udev only (no controller input): the walk +the spike used, built on what exists — `walkSlaves`/`physicalDisksOf` (role.go:81-131), `parentDisk` +(A/internal/storage/hostread.go:183-201) — plus the loop step and the mapping guest path → host mount (`/mnt/felhom-drives/` → +`/mnt/` → device; `mp0` → its LV). + +**When [DESIGN]:** at agent start, on every disk hot-plug event the agent already reacts to, on enrol/attach, and +**again right before each Tier-2 run** (a disk swapped in the same bay must not inherit the old verdict). + +**Reported [DESIGN]:** `GET /disks` gains `physical_disks` + `identity` per place; the hub report's `storage_targets` +gains the same two fields (A/internal/hub/report.go:379-438), so the hub sees the agent's verdict directly. The controller +stores nothing of it; it asks. + +## 4. Backup tiers + +**[DESIGN] The rule:** a Tier-2 copy **counts as a second copy** only when the source place and the target place share +**no** physical disk **and** both identities are `proven`. The decision is the agent's (`POST /disks/same-disk` with the +two guest paths → `{different: bool, proven: bool, reason}`), replacing `sameDevice`/`st_dev` in `tier2.go:83-179` and +`hasOffDriveTarget` (backup.go:1390-1402). + +| Situation | Tier-2 | The one-copy notice | Household sentence (HU / EN) | +|---|---|---|---| +| Different disks, both proven | made, counted | hidden | — | +| Same disk (two partitions, internal place + system) | per decision D1 | shown | „Csak egy helyi másolat készül: nincs második lemez, vagy ugyanazon a lemezen van, mint az adatok. Ez a véletlen törlés ellen véd, lemezhiba ellen nem. Lemezhiba ellen egy másik lemez vagy a távoli mentés véd." / „Only one local copy is made: there is no second disk, or it is on the same disk as the data. This protects against mistakes, not against a disk failure. A different disk or the off-site copy protects against a disk failure." | +| Unknown (VM, hidden serial) | per decision D2 | shown | „A Felhom nem tudja ellenőrizni, hogy a második meghajtó valóban másik lemez-e (virtuális gépben és egyes USB-házakban ez nem látszik), ezért nem számolja második másolatnak." / „Felhom cannot check that the second drive is really a different disk (inside a virtual machine and behind some USB enclosures this is not visible), so it does not count it as a second copy." | +| Network share | never (unchanged) | shown | unchanged | + +The notice moves from a Go constant to i18n, in the informal voice (closes R-1072's half). Off-site (Tier-3, PBS) and +the local whole-guest copy are **unchanged**. **[FACT]** Today Tester 1 counts Tier-2 copies between virtual disks that +all sit on one host NVMe (R-1074). + +## 5. One-disk boxes — the internal data place + +**[FACT]** The install button for a data-folder app finds no drive on a one-disk box and refuses with the raw field +name (R-1068). **[FACT]** The only place on that disk today, `sys_drive`, is a folder of `mp0`, which is `backup=1`: +**anything put there rides in every local and off-site whole-guest copy** (`07` §6.1, §7.5.1). Films there would +overflow the local copy (R-548) and travel to ep0. + +**[DESIGN]** The installer (new installs) creates a second thin LV on `local-lvm`, the **internal data place** +(„Belső tárhely"), formats it, and the agent mounts it **on the host** by fs-UUID at `/mnt/belso`, bound to +`/mnt/felhom-drives/belso` — exactly like an enrolled drive. So: +- it is **not** in vzdump (a host mount, like every drive) and not in PBS; +- the controller registers it as the default drive (`kind: internal`), so media and `HDD_PATH` apps install with no + extra step — **no sentence at all**; the media binds cover it like any drive; +- its `physical_disks` = the system disk, so a Tier-2 copy between it and `sys_drive` never counts (§4); +- the agent's format/wipe guard keeps refusing it as a **system** disk (role system, claim.go:72) — only the installer + makes or removes it. + +On a one-disk box **without** an internal place (old boxes, §9), the install of a data-folder app answers in words: +„Ehhez az alkalmazáshoz egy adattároló kell. A Meghajtók oldalon adhatsz hozzá egyet." — never the field name. +Registering `sys_drive` as a drive (the „way through" R-1068 guessed) is **rejected** (§10). + +## 6. Partitions + +**[DESIGN]** A place may be one partition. The agent lists, under each whole disk, its partitions as separate +candidates with their own state: + +| Partition state | Offered as | Who may | +|---|---|---| +| empty (no signature, no children) | „format this part" | the household, self-serve (it holds nothing) | +| a filesystem with no files (agent mounts read-only, counts entries) | „use this part" or „format this part" | the household | +| a filesystem with files | „use this part" (attach) only; format = the customer-confirmed data-bearing path, bound to the partition's durable id | the household with confirmation (today's user-data rule, A/internal/localapi/disks.go:912-946) | +| LVM / RAID / LUKS / swap / mounted elsewhere / on the system disk | not offered | nobody (claim.go:72-103, unchanged) | + +The classifier judges **the partition** (its own signature, children, mounts) and still refuses on the whole disk's +system role and on any sibling that is foreign-mounted or a PV — those siblings make the **disk** unsafe, not the +partition. A partition's durable id = `:part` + its fs-UUID; the wipe re-resolve (wipe_reresolve.go:53-93) +binds both. **Creating or deleting partitions: never from the dashboard in this round — the installer only** (D5). + +## 7. The installer + +**[FACT]** Today `step_grows` gives the guest's one data volume (`mp0`) 70 / 130 / 250 GiB by the thin pool's free space +(<150 / ≥150 / ≥300 GiB), and nothing above 250 (E/scripts/felhom-host-install.sh:2261-2275). Measured pools: 128 GB +disk → 54 GiB, 200 GB → 113 GiB, 512 GB → 349 GiB (PVE default layout; root capped at 96 GiB). + +**[DESIGN] The rule:** `mp0` = 70 GiB (pool < 300), 130 (300–800), 250 (≥ 800). Reserve = **max(16 GiB, 10 % of the +pool)**, kept free for thin snapshots during a whole-guest copy, image pulls during updates, and the restore test (which +sizes itself, A19). Internal place = pool − 32 (rootfs) − `mp0` − reserve, made only when ≥ 20 GiB. The local +whole-guest copies stay on host `local` (root), which the data place does not touch — R-548 is not made worse: `mp0` +does not grow. + +| Disk | Thin pool (GiB) | Today: data volume / unused | Proposed `mp0` | Reserve | **Internal place** | +|---|---|---|---|---|---| +| 256 GB | ≈ 140 (estimate) | 70 / ≈ 38 | 70 | 16 | **≈ 22** (settings and small apps, not a film library) | +| 512 GB | 349 (N100, measured) | 250 / ≈ 67 | 130 | 35 | **≈ 152** | +| 1 TB | ≈ 800 (estimate) | 250 / ≈ 518 | 250 | 80 | **≈ 438** | +| 2 TB | ≈ 1,720 (estimate) | 250 / ≈ 1,438 | 250 | 172 | **≈ 1,266** | + +## 8. Virtual machines + +**[FACT]** Inside a VM the agent cannot tell virtual disks apart by host disk (spike cases 5–6). **[DESIGN]** Every place +on a VM box is `identity: unknown/vm`; Tier-2 there never counts (D2), and the page says why. The OMV guide tells the +household: a second disk given to the Felhom VM must be **a different physical disk on the host**, passed whole, on bus +`sata` (R-1069); otherwise it adds space, not safety. Disk health is OMV's job there (R-1073). + +## 9. Existing boxes + +**[DESIGN]** The agent computes identities on its next update — no migration, no change to what is stored. A box with two +real disks keeps every Tier-2 copy and every sentence (both proven, different). A box where two places share a disk +(none known in the field; Tester 1 in its VM) shows the honest notice. One-disk boxes get no internal place by +themselves; adding one later is a signed operator job (an LV in free thin space), not a household button. Hub: the two +new fields appear in reports; nothing is backfilled. + +## 10. Threat note + +**[DESIGN]** „Different disks" is agent-computed evidence, like the data-bearing verdict (`03` §6): the controller can +only ask, never assert. A compromised controller could show a false sentence on its own page, but cannot make the agent +call two places different, cannot change the hub's copy of the verdict, and cannot format a partition the agent judges +data-bearing. The agent never trusts a guest path it cannot map to a host mount it made. + +## 11. Rejected options (one line each) + +- **Register `sys_drive` as the media drive** — it is inside `mp0`, so films enter every whole-guest copy, local and off-site. +- **Grow `mp0` without a cap** — the same problem, at full size. +- **Keep `st_dev` and add a partition check in the controller** — the controller cannot see LVM, loop or the host; the agent can. +- **WWN as the primary disk key** — cheap disks ship vendor-less WWNs (N100). +- **Ask the hypervisor (OMV/libvirt) which host disk backs a virtual disk** — Felhom has no access there, and it would trust a party it does not control. +- **Let the dashboard create partitions** — a new destructive power for the household with no recovery; not needed for the cases in hand. + +## 12. Decisions for the operator (D1–D6) — STOP here + +| # | Question | Options | Recommendation | If you do nothing | +|---|---|---|---|---| +| D1 | A second copy on the **same** disk (two partitions, internal place → `sys_drive`)? | (a) do not make it; say „only one copy" honestly · (b) make it, label it „same disk: against mistakes, not against a disk failure" | **(a)** — the first copy already protects against mistakes; (b) spends space and invites a false sense of safety | today's `st_dev` rule stays: two partitions would count as two disks | +| D2 | **Unknown** identity (VM, hidden serial)? | (a) never count it; the copy is still made (it may be a real second disk) and the notice stays · (b) the household confirms „these are different disks" once, recorded with the disk ids | **(a)** for now; revisit (b) when a VM install is a supported shape | VM boxes keep counting same-disk copies as second copies (Tester 1 does today) | +| D3 | The installer's internal place on a one-disk box, and its reserve | (a) §7: `mp0` 70/130/250, reserve max(16 GiB, 10 %), the rest internal · (b) a larger reserve, 20 % · (c) no internal place; household adds a drive | **(a)** | new one-disk boxes keep refusing media apps (R-1068) and leave most of a big disk unused | +| D4 | Media and data-folder apps on a one-disk **old** box | (a) a plain sentence pointing to Meghajtók; internal place only by a signed operator job · (b) register `sys_drive` | **(a)** — (b) puts films into the whole-guest copies | the raw field error stays (R-1068) | +| D5 | Who creates or deletes partitions | (a) the installer only, this round · (b) also a dashboard wizard | **(a)** | — (nothing is built either way) | +| D6 | R-1071 — films from a NAS share, read-only, for Jellyfin | (a) a separate decision; this design only labels a NAS place `network`, never a copy target · (b) fold a read-only media bind kind into this build | **(a)** — the model makes it easier (a NAS becomes one more place kind with clear rules), but it is a media decision, not an identity one | stays open as R-1071 | + +**After the rulings, the build task changes:** agent (place identity in `/disks` and the report, the same-disk call, +partition candidates, the loop step) · controller (Tier-2 and the notice ask the agent; i18n sentences; the install +refusal in words; register the internal place) · installer (`step_grows` + the internal LV) · hub (store and show the two +fields) · website and guides (the OMV guide's second-disk line; the backup explanation page). diff --git a/documentation/audits/storage-identity-2026-10-15/B-case3-loop.json b/documentation/audits/storage-identity-2026-10-15/B-case3-loop.json new file mode 100644 index 00000000..7144b04b --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case3-loop.json @@ -0,0 +1,540 @@ +{ + "host": "demo-hp", + "virt": "none", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage nvme-scratch (dir)", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-1)", + "target": "/dev/pve/vm-9201-disk-1", + "source": "/dev/pve/vm-9201-disk-1", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-0)", + "target": "/dev/pve/vm-9201-disk-0", + "source": "/dev/pve/vm-9201-disk-0", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp0 /var/lib/felhom (nvme-scratch:9202/vm-9202-disk-3.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-3.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp8 /mnt/felhom-drives/scratch_hdd (host bind)", + "target": "/mnt/hdd_1/scratch-drives/scratch_hdd", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9202/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 rootfs / (nvme-scratch:9202/vm-9202-disk-2.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-2.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9401 rootfs / (nvme-scratch:9401/vm-9401-disk-0.raw)", + "target": "/mnt/hdd_1/images/9401/vm-9401-disk-0.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/hdd_1", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives/hdd_1", + "target": "/mnt/felhom-drives/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/hdd_1", + "source": "/dev/nvme0n1[/felhom-data]", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /tmp/scrA", + "target": "/tmp/scrA", + "fstype": "ext4", + "mountpoint": "/tmp/scrA", + "source": "/dev/loop2p1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "loop2p1 -> part loop2p1 -> loop[/mnt/hdd_1/scratch-storage-identity.img] on /dev/nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /tmp/scrB", + "target": "/tmp/scrB", + "fstype": "ext4", + "mountpoint": "/tmp/scrB", + "source": "/dev/loop2p2", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "loop2p2 -> part loop2p2 -> loop[/mnt/hdd_1/scratch-storage-identity.img] on /dev/nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-case3-loop.txt b/documentation/audits/storage-identity-2026-10-15/B-case3-loop.txt new file mode 100644 index 00000000..581cbbea --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case3-loop.txt @@ -0,0 +1,6 @@ +loop=/dev/loop2 +NAME PKNAME SIZE FSTYPE MOUNTPOINTS +loop2 4G +|-loop2p1 loop2 1G ext4 /tmp/scrA +`-loop2p2 loop2 3G ext4 /tmp/scrB +cleaned: loops=0 file=0 diff --git a/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions-empty.txt b/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions-empty.txt new file mode 100644 index 00000000..e4e6fd45 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions-empty.txt @@ -0,0 +1,8 @@ +NAME SIZE FSTYPE PARTLABEL +sdg 4G +|-sdg1 1G +`-sdg2 3G +=== GET /disks/candidates +{"ok":true,"data":{"attach":[{"device":"/dev/sdb","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdb","durable_id":"uuid:863c67fd-3e21-4d9f-9a74-3c5fa406f2a2"},{"device":"/dev/sdc","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdc","durable_id":"uuid:4ebfd36d-87d3-4b63-839e-a5a710fc799a"},{"device":"/dev/sdd","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdd","durable_id":"uuid:e15652d5-0aa7-4eb8-93a1-afb2839d527c"},{"device":"/dev/sde","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sde","durable_id":"uuid:86f33f9c-1022-43d8-95eb-f9a6ec9eb923"},{"device":"/dev/sdf","size_bytes":21474836480,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdf","durable_id":"uuid:8a31a462-ff15-4be2-9aeb-9620b99c7f77"},{"device":"/dev/sdg","size_bytes":4294967296,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdg2","durable_id":"uuid:76c29c14-c0a4-4ef4-869a-5a57edfd3a16"}],"initialize":[{"device":"/dev/sdb","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdb","durable_id":"uuid:863c67fd-3e21-4d9f-9a74-3c5fa406f2a2"},{"device":"/dev/sdc","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdc","durable_id":"uuid:4ebfd36d-87d3-4b63-839e-a5a710fc799a"},{"device":"/dev/sdd","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdd","durable_id":"uuid:e15652d5-0aa7-4eb8-93a1-afb2839d527c"},{"device":"/dev/sde","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sde","durable_id":"uuid:86f33f9c-1022-43d8-95eb-f9a6ec9eb923"},{"device":"/dev/sdf","size_bytes":21474836480,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdf","durable_id":"uuid:8a31a462-ff15-4be2-9aeb-9620b99c7f77"},{"device":"/dev/sdg","size_bytes":4294967296,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdg2","durable_id":"uuid:76c29c14-c0a4-4ef4-869a-5a57edfd3a16"}],"vmid":9201}} + +HTTP 200 diff --git a/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions.txt b/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions.txt new file mode 100644 index 00000000..c8eb89c8 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case4b-partitions.txt @@ -0,0 +1,9 @@ +NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS +sdg +|-sdg1 +`-sdg2 +/tmp/c1.txt {'attach': [{'device': '/dev/sdg', 'size_bytes': 4294967296, 'model': 'QEMU HARDDISK', 'fstype': 'ext4', 'data_bearing': True, 'mountable': True, 'mount_source': '/dev/sdg2', 'durable_id': 'uuid:76c29c14-c0a4-4ef4-869a-5a57edfd3a16'}], 'initialize': [{'device': '/dev/sdg', 'size_bytes': 4294967296, 'model': 'QEMU HARDDISK', 'fstype': 'ext4', 'data_bearing': True, 'mountable': True, 'mount_source': '/dev/sdg2', 'durable_id': 'uuid:76c29c14-c0a4-4ef4-869a-5a57edfd3a16'}]} +/tmp/c2.txt {'attach': [], 'initialize': [{'device': '/dev/sdg', 'size_bytes': 4294967296, 'model': 'QEMU HARDDISK', 'data_bearing': True, 'mountable': False}]} +/dev/sdg: calling ioctl to re-read partition table: Success +NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS +sdg diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-agent-blank.txt b/documentation/audits/storage-identity-2026-10-15/B-case56-agent-blank.txt new file mode 100644 index 00000000..f6b711d4 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-agent-blank.txt @@ -0,0 +1,8 @@ +=== GET /disks +{"ok":true,"data":{"disks":[{"name":"local","type":"local","state":"attached","backing_device":"","mount_path":"","class":"","role":"system","data_bearing":false,"total_bytes":62903865344,"used_bytes":15524790272,"used_fraction":0.246801848934086,"durable_id":"path:/var/lib/vz","guest_attached":false,"backup_target":true,"bound_under_parent":false,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"felhom-pbs","type":"pbs","state":"attached","backing_device":"","mount_path":"","class":"","role":"backup","data_bearing":false,"total_bytes":0,"used_bytes":0,"used_fraction":0,"durable_id":"10.77.0.1:felhom-offsite#c6:07:28:3f:5b:7b:5a:41:90:28:d7:ca:4f:37:14:70:56:39:2e:2f:0b:71:e8:06:ca:60:4a:d5:56:5f:3c:fd","guest_attached":false,"bound_under_parent":false,"smart":{"health":"UNKNOWN","temperature_c":null,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"local-lvm","type":"lvmthin","state":"attached","backing_device":"","mount_path":"","class":"","role":"system","data_bearing":false,"total_bytes":121521569792,"used_bytes":14619044845,"used_fraction":0.120299999991955,"durable_id":"pve/data","guest_attached":false,"bound_under_parent":false,"smart":{"health":"UNKNOWN","temperature_c":null,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"863c67fd-3e21-4d9f-9a74-3c5fa406f2a2","type":"usb","state":"attached","backing_device":"/dev/sdb","mount_path":"/mnt/adatlemez","class":"","role":"user-data","data_bearing":false,"total_bytes":52521566208,"used_bytes":572174336,"used_fraction":0.01089408365573164,"durable_id":"uuid:863c67fd-3e21-4d9f-9a74-3c5fa406f2a2","guest_attached":false,"guest_path":"/mnt/felhom-drives/adatlemez","bound_under_parent":true,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"4ebfd36d-87d3-4b63-839e-a5a710fc799a","type":"usb","state":"attached","backing_device":"/dev/sdc","mount_path":"/mnt/media_a","class":"","role":"user-data","data_bearing":false,"total_bytes":105089261568,"used_bytes":30231240704,"used_fraction":0.2876720252186595,"durable_id":"uuid:4ebfd36d-87d3-4b63-839e-a5a710fc799a","guest_attached":false,"guest_path":"/mnt/felhom-drives/media_a","bound_under_parent":true,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"e15652d5-0aa7-4eb8-93a1-afb2839d527c","type":"usb","state":"attached","backing_device":"/dev/sdd","mount_path":"/mnt/media_b","class":"","role":"user-data","data_bearing":false,"total_bytes":105089261568,"used_bytes":34149683200,"used_fraction":0.3249588272908626,"durable_id":"uuid:e15652d5-0aa7-4eb8-93a1-afb2839d527c","guest_attached":false,"guest_path":"/mnt/felhom-drives/media_b","bound_under_parent":true,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"86f33f9c-1022-43d8-95eb-f9a6ec9eb923","type":"usb","state":"attached","backing_device":"/dev/sde","mount_path":"/mnt/media_c","class":"","role":"user-data","data_bearing":false,"total_bytes":52521566208,"used_bytes":8544256,"used_fraction":0.00016268090647111267,"durable_id":"uuid:86f33f9c-1022-43d8-95eb-f9a6ec9eb923","guest_attached":false,"guest_path":"/mnt/felhom-drives/media_c","bound_under_parent":true,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}},{"name":"8a31a462-ff15-4be2-9aeb-9620b99c7f77","type":"usb","state":"attached","backing_device":"/dev/sdf","mount_path":"/mnt/media_d","class":"","role":"user-data","data_bearing":false,"total_bytes":20957446144,"used_bytes":8237056,"used_fraction":0.0003930372023099877,"durable_id":"uuid:8a31a462-ff15-4be2-9aeb-9620b99c7f77","guest_attached":false,"guest_path":"/mnt/felhom-drives/media_d","bound_under_parent":true,"smart":{"health":"UNKNOWN","model_name":"QEMU QEMU HARDDISK","temperature_c":0,"power_on_hours":null,"reallocated_sectors":null,"pending_sectors":null,"offline_uncorrectable":null,"critical_warning":null,"media_errors":null,"percentage_used":null}}],"guest_boot_id":"1792084598-1569","vmid":9201}} + +HTTP 200 +=== GET /disks/candidates +{"ok":true,"data":{"attach":[{"device":"/dev/sdb","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdb","durable_id":"uuid:863c67fd-3e21-4d9f-9a74-3c5fa406f2a2"},{"device":"/dev/sdc","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdc","durable_id":"uuid:4ebfd36d-87d3-4b63-839e-a5a710fc799a"},{"device":"/dev/sdd","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdd","durable_id":"uuid:e15652d5-0aa7-4eb8-93a1-afb2839d527c"},{"device":"/dev/sde","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sde","durable_id":"uuid:86f33f9c-1022-43d8-95eb-f9a6ec9eb923"},{"device":"/dev/sdf","size_bytes":21474836480,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdf","durable_id":"uuid:8a31a462-ff15-4be2-9aeb-9620b99c7f77"}],"initialize":[{"device":"/dev/sdb","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdb","durable_id":"uuid:863c67fd-3e21-4d9f-9a74-3c5fa406f2a2"},{"device":"/dev/sdc","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdc","durable_id":"uuid:4ebfd36d-87d3-4b63-839e-a5a710fc799a"},{"device":"/dev/sdd","size_bytes":107374182400,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdd","durable_id":"uuid:e15652d5-0aa7-4eb8-93a1-afb2839d527c"},{"device":"/dev/sde","size_bytes":53687091200,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sde","durable_id":"uuid:86f33f9c-1022-43d8-95eb-f9a6ec9eb923"},{"device":"/dev/sdf","size_bytes":21474836480,"model":"QEMU HARDDISK","fstype":"ext4","data_bearing":true,"mountable":true,"mount_source":"/dev/sdf","durable_id":"uuid:8a31a462-ff15-4be2-9aeb-9620b99c7f77"},{"device":"/dev/sdg","size_bytes":4294967296,"model":"QEMU HARDDISK","data_bearing":false,"mountable":false}],"vmid":9201}} + +HTTP 200 diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.json b/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.json new file mode 100644 index 00000000..a68234f5 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.json @@ -0,0 +1,598 @@ +{ + "host": "demo-hp", + "virt": "none", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage nvme-scratch (dir)", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-1)", + "target": "/dev/pve/vm-9201-disk-1", + "source": "/dev/pve/vm-9201-disk-1", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-0)", + "target": "/dev/pve/vm-9201-disk-0", + "source": "/dev/pve/vm-9201-disk-0", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp0 /var/lib/felhom (nvme-scratch:9202/vm-9202-disk-3.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-3.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp8 /mnt/felhom-drives/scratch_hdd (host bind)", + "target": "/mnt/hdd_1/scratch-drives/scratch_hdd", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9202/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 rootfs / (nvme-scratch:9202/vm-9202-disk-2.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-2.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9401 rootfs / (nvme-scratch:9401/vm-9401-disk-0.raw)", + "target": "/mnt/hdd_1/images/9401/vm-9401-disk-0.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/hdd_1", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives/hdd_1", + "target": "/mnt/felhom-drives/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/hdd_1", + "source": "/dev/nvme0n1[/felhom-data]", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /mnt/hdd_1/images/341/vm-341-disk-1.raw", + "target": "/mnt/hdd_1/images/341/vm-341-disk-1.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /mnt/hdd_1/images/341/vm-341-disk-2.raw", + "target": "/mnt/hdd_1/images/341/vm-341-disk-2.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /mnt/hdd_1/images/341/vm-341-disk-3.raw", + "target": "/mnt/hdd_1/images/341/vm-341-disk-3.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "arg /dev/pve/vm-341-disk-0", + "target": "/dev/pve/vm-341-disk-0", + "source": "/dev/pve/vm-341-disk-0", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-8 -> dm-8(pve-vm--341--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.txt b/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.txt new file mode 100644 index 00000000..54bd6560 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-host-truth.txt @@ -0,0 +1,4 @@ +scsi0 nvme-scratch:341/vm-341-disk-1.raw -> /mnt/hdd_1/images/341/vm-341-disk-1.raw +scsi1 nvme-scratch:341/vm-341-disk-2.raw -> /mnt/hdd_1/images/341/vm-341-disk-2.raw +scsi2 nvme-scratch:341/vm-341-disk-3.raw -> /mnt/hdd_1/images/341/vm-341-disk-3.raw +scsi6 local-lvm:vm-341-disk-0 -> /dev/pve/vm-341-disk-0 diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-setup.txt b/documentation/audits/storage-identity-2026-10-15/B-case56-setup.txt new file mode 100644 index 00000000..b44b4b6a --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-setup.txt @@ -0,0 +1,31 @@ +scsi6: successfully created disk 'local-lvm:vm-341-disk-0,serial=SCRATCHSID6,size=4G' +scsi6: local-lvm:vm-341-disk-0,serial=SCRATCHSID6,size=4G +NAME SIZE SERIAL MODEL FSTYPE MOUNTPOINTS +sda 200G drive-scsi0 QEMU HARDDISK +|-sda1 1007K +|-sda2 1G vfat /boot/efi +`-sda3 199G LVM2_member + |-pve-swap 7.7G swap [SWAP] + |-pve-root 59.8G ext4 /mnt/felhom-drives + | / + |-pve-data_tmeta 1.2G + | `-pve-data-tpool 113.2G + | |-pve-data 113.2G + | |-pve-vm--9201--disk--0 32G ext4 + | `-pve-vm--9201--disk--1 70G ext4 + `-pve-data_tdata 113.2G + `-pve-data-tpool 113.2G + |-pve-data 113.2G + |-pve-vm--9201--disk--0 32G ext4 + `-pve-vm--9201--disk--1 70G ext4 +sdb 50G drive-scsi1 QEMU HARDDISK ext4 /mnt/felhom-drives/adatlemez + /mnt/adatlemez +sdc 100G drive-scsi2 QEMU HARDDISK ext4 /mnt/felhom-drives/media_a + /mnt/media_a +sdd 100G drive-scsi3 QEMU HARDDISK ext4 /mnt/felhom-drives/media_b + /mnt/media_b +sde 50G drive-scsi4 QEMU HARDDISK ext4 /mnt/felhom-drives/media_c + /mnt/media_c +sdf 20G drive-scsi5 QEMU HARDDISK ext4 /mnt/felhom-drives/media_d + /mnt/media_d +sdg 4G SCRATCHSID6 QEMU HARDDISK diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-teardown.txt b/documentation/audits/storage-identity-2026-10-15/B-case56-teardown.txt new file mode 100644 index 00000000..b25a8f83 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-teardown.txt @@ -0,0 +1,6 @@ +update VM 341: -delete scsi6 +unused0: local-lvm:vm-341-disk-0 + Logical volume "vm-341-disk-0" successfully removed. +0 +0 +status: running diff --git a/documentation/audits/storage-identity-2026-10-15/B-case56-tester1-inside.json b/documentation/audits/storage-identity-2026-10-15/B-case56-tester1-inside.json new file mode 100644 index 00000000..a95d18ac --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-case56-tester1-inside.json @@ -0,0 +1,682 @@ +{ + "host": "felhom", + "virt": "kvm", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-1)", + "target": "/dev/pve/vm-9201-disk-1", + "source": "/dev/pve/vm-9201-disk-1", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-0)", + "target": "/dev/pve/vm-9201-disk-0", + "source": "/dev/pve/vm-9201-disk-0", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_c", + "target": "/mnt/media_c", + "fstype": "ext4", + "mountpoint": "/mnt/media_c", + "source": "/dev/sde", + "physical_disks": [ + "serial:drive-scsi4" + ], + "disks": [ + { + "disk": "sde", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi4", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:05.0-scsi-0:0:0:4", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi4", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sde" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/adatlemez", + "target": "/mnt/adatlemez", + "fstype": "ext4", + "mountpoint": "/mnt/adatlemez", + "source": "/dev/sdb", + "physical_disks": [ + "serial:drive-scsi1" + ], + "disks": [ + { + "disk": "sdb", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi1", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:02.0-scsi-0:0:0:1", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi1", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdb" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_b", + "target": "/mnt/media_b", + "fstype": "ext4", + "mountpoint": "/mnt/media_b", + "source": "/dev/sdd", + "physical_disks": [ + "serial:drive-scsi3" + ], + "disks": [ + { + "disk": "sdd", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi3", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:04.0-scsi-0:0:0:3", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi3", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdd" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_a", + "target": "/mnt/media_a", + "fstype": "ext4", + "mountpoint": "/mnt/media_a", + "source": "/dev/sdc", + "physical_disks": [ + "serial:drive-scsi2" + ], + "disks": [ + { + "disk": "sdc", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi2", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:03.0-scsi-0:0:0:2", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi2", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdc" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_d", + "target": "/mnt/media_d", + "fstype": "ext4", + "mountpoint": "/mnt/media_d", + "source": "/dev/sdf", + "physical_disks": [ + "serial:drive-scsi5" + ], + "disks": [ + { + "disk": "sdf", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi5", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:06.0-scsi-0:0:0:5", + "size_gb": 21.5, + "rotational": "1", + "id": "serial:drive-scsi5", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdf" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_a", + "target": "/mnt/felhom-drives/media_a", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_a", + "source": "/dev/sdc[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi2" + ], + "disks": [ + { + "disk": "sdc", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi2", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:03.0-scsi-0:0:0:2", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi2", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdc" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/adatlemez", + "target": "/mnt/felhom-drives/adatlemez", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/adatlemez", + "source": "/dev/sdb[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi1" + ], + "disks": [ + { + "disk": "sdb", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi1", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:02.0-scsi-0:0:0:1", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi1", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdb" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_c", + "target": "/mnt/felhom-drives/media_c", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_c", + "source": "/dev/sde[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi4" + ], + "disks": [ + { + "disk": "sde", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi4", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:05.0-scsi-0:0:0:4", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi4", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sde" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_d", + "target": "/mnt/felhom-drives/media_d", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_d", + "source": "/dev/sdf[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi5" + ], + "disks": [ + { + "disk": "sdf", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi5", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:06.0-scsi-0:0:0:5", + "size_gb": 21.5, + "rotational": "1", + "id": "serial:drive-scsi5", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdf" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_b", + "target": "/mnt/felhom-drives/media_b", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_b", + "source": "/dev/sdd[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi3" + ], + "disks": [ + { + "disk": "sdd", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi3", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:04.0-scsi-0:0:0:3", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi3", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdd" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "arg /dev/sdg", + "target": "/dev/sdg", + "source": "/dev/sdg", + "physical_disks": [ + "serial:drive-scsi6" + ], + "disks": [ + { + "disk": "sdg", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi6", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:07.0-scsi-0:0:0:6", + "size_gb": 4.3, + "rotational": "1", + "id": "serial:drive-scsi6", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdg" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-demo-hp.json b/documentation/audits/storage-identity-2026-10-15/B-demo-hp.json new file mode 100644 index 00000000..3b2578ae --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-demo-hp.json @@ -0,0 +1,480 @@ +{ + "host": "demo-hp", + "virt": "none", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage nvme-scratch (dir)", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-1)", + "target": "/dev/pve/vm-9201-disk-1", + "source": "/dev/pve/vm-9201-disk-1", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-0)", + "target": "/dev/pve/vm-9201-disk-0", + "source": "/dev/pve/vm-9201-disk-0", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp0 /var/lib/felhom (nvme-scratch:9202/vm-9202-disk-3.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-3.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp8 /mnt/felhom-drives/scratch_hdd (host bind)", + "target": "/mnt/hdd_1/scratch-drives/scratch_hdd", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9202/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9202 rootfs / (nvme-scratch:9202/vm-9202-disk-2.raw)", + "target": "/mnt/hdd_1/images/9202/vm-9202-disk-2.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9401 rootfs / (nvme-scratch:9401/vm-9401-disk-0.raw)", + "target": "/mnt/hdd_1/images/9401/vm-9401-disk-0.raw", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/hdd_1", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/nvme0n1", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5001b448b60a9d6e" + ], + "disks": [ + { + "disk": "sda", + "model": "SanDisk_X600_M.2_2280_SATA_128GB", + "vendor": "ATA", + "serial": "182195804614", + "wwn": "0x5001b448b60a9d6e", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:06:00.0-ata-1.0", + "size_gb": 128.0, + "rotational": "0", + "id": "wwn:0x5001b448b60a9d6e", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives/hdd_1", + "target": "/mnt/felhom-drives/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/hdd_1", + "source": "/dev/nvme0n1[/felhom-data]", + "physical_disks": [ + "wwn:eui.000000000000001000080d020046c07b" + ], + "disks": [ + { + "disk": "nvme0n1", + "model": "KXG50PNV1T02 NVMe TOSHIBA 1024GB", + "vendor": "", + "serial": "58BS11AFT8MQ", + "wwn": "eui.000000000000001000080d020046c07b", + "bus": "", + "usb_driver": "", + "path": "pci-0000:04:00.0-nvme-1", + "size_gb": 1024.2, + "rotational": "0", + "id": "wwn:eui.000000000000001000080d020046c07b", + "identity": "proven", + "why_unknown": [], + "via": "nvme0n1" + } + ], + "identity": "proven", + "why_unknown": [] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-demo-hp.txt b/documentation/audits/storage-identity-2026-10-15/B-demo-hp.txt new file mode 100644 index 00000000..313cab16 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-demo-hp.txt @@ -0,0 +1,33 @@ +# host demo-hp virt=none +host root / src=/dev/mapper/pve-root -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage local (dir) src=/dev/mapper/pve-root -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage local-lvm (lvmthin pve/data) src=/dev/mapper/pve-data-tpool -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +pve storage nvme-scratch (dir) src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk- src=/dev/pve/vm-9201-disk-1 -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9201 mp8 /mnt/felhom-drives (host bind) src=/dev/mapper/pve-root[/mnt/felhom-drives] -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 mp9 /etc/felhom-bootstrap (host bind) src=/dev/mapper/pve-root -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 rootfs / (local-lvm:vm-9201-disk-0) src=/dev/pve/vm-9201-disk-0 -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9202 mp0 /var/lib/felhom (nvme-scratch:9202/vm-92 src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +guest 9202 mp8 /mnt/felhom-drives/scratch_hdd (host bin src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +guest 9202 mp9 /etc/felhom-bootstrap (host bind) src=/dev/mapper/pve-root -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9202 rootfs / (nvme-scratch:9202/vm-9202-disk-2.r src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +guest 9401 rootfs / (nvme-scratch:9401/vm-9401-disk-0.r src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +host mount /mnt/hdd_1 src=/dev/nvme0n1 -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 +host mount /mnt/felhom-drives src=/dev/mapper/pve-root[/mnt/felhom-drives] -> wwn:0x5001b448b60a9d6e [proven] + sda ATA SanDisk_X600_M.2_2280_SATA_1 bus=ata 128.0GB via: dm-1 -> dm-1(pve-root) -> part sda3 +host mount /mnt/felhom-drives/hdd_1 src=/dev/nvme0n1[/felhom-data] -> wwn:eui.000000000000001000080d020046c07b [proven] + nvme0n1 KXG50PNV1T02 NVMe TOSHIBA 10 bus= 1024.2GB via: nvme0n1 diff --git a/documentation/audits/storage-identity-2026-10-15/B-n100.json b/documentation/audits/storage-identity-2026-10-15/B-n100.json new file mode 100644 index 00000000..aa5a30dc --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-n100.json @@ -0,0 +1,330 @@ +{ + "host": "demo-felhom", + "virt": "none", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage felhom-backup (dir)", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/sdb", + "physical_disks": [ + "wwn:0x5000039ddb108568" + ], + "disks": [ + { + "disk": "sdb", + "model": "TOSHIBA_MQ04ABF100", + "vendor": "ADATA", + "serial": "65NOP3HDT", + "wwn": "0x5000039ddb108568", + "bus": "ata", + "usb_driver": "usb-storage", + "path": "pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:0", + "size_gb": 1000.2, + "rotational": "1", + "id": "wwn:0x5000039ddb108568", + "identity": "proven", + "why_unknown": [], + "via": "sdb" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-3)", + "target": "/dev/pve/vm-9201-disk-3", + "source": "/dev/pve/vm-9201-disk-3", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--3) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-2)", + "target": "/dev/pve/vm-9201-disk-2", + "source": "/dev/pve/vm-9201-disk-2", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--2) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/hdd_1", + "target": "/mnt/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/hdd_1", + "source": "/dev/sdb", + "physical_disks": [ + "wwn:0x5000039ddb108568" + ], + "disks": [ + { + "disk": "sdb", + "model": "TOSHIBA_MQ04ABF100", + "vendor": "ADATA", + "serial": "65NOP3HDT", + "wwn": "0x5000039ddb108568", + "bus": "ata", + "usb_driver": "usb-storage", + "path": "pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:0", + "size_gb": 1000.2, + "rotational": "1", + "id": "wwn:0x5000039ddb108568", + "identity": "proven", + "why_unknown": [], + "via": "sdb" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "wwn:0x5000000123456f1f" + ], + "disks": [ + { + "disk": "sda", + "model": "AirDisk_512GB_SSD", + "vendor": "ATA", + "serial": "QDF922W009654S30EX", + "wwn": "0x5000000123456f1f", + "bus": "ata", + "usb_driver": "", + "path": "pci-0000:00:17.0-ata-2.0", + "size_gb": 512.1, + "rotational": "0", + "id": "wwn:0x5000000123456f1f", + "identity": "proven", + "why_unknown": [], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "proven", + "why_unknown": [] + }, + { + "place": "host mount /mnt/felhom-drives/hdd_1", + "target": "/mnt/felhom-drives/hdd_1", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/hdd_1", + "source": "/dev/sdb[/felhom-data]", + "physical_disks": [ + "wwn:0x5000039ddb108568" + ], + "disks": [ + { + "disk": "sdb", + "model": "TOSHIBA_MQ04ABF100", + "vendor": "ADATA", + "serial": "65NOP3HDT", + "wwn": "0x5000039ddb108568", + "bus": "ata", + "usb_driver": "usb-storage", + "path": "pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:0", + "size_gb": 1000.2, + "rotational": "1", + "id": "wwn:0x5000039ddb108568", + "identity": "proven", + "why_unknown": [], + "via": "sdb" + } + ], + "identity": "proven", + "why_unknown": [] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-n100.txt b/documentation/audits/storage-identity-2026-10-15/B-n100.txt new file mode 100644 index 00000000..71489440 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-n100.txt @@ -0,0 +1,23 @@ +# host demo-felhom virt=none +host root / src=/dev/mapper/pve-root -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage felhom-backup (dir) src=/dev/sdb -> wwn:0x5000039ddb108568 [proven] + sdb ADATA TOSHIBA_MQ04ABF100 bus=ata 1000.2GB via: sdb +pve storage local (dir) src=/dev/mapper/pve-root -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage local-lvm (lvmthin pve/data) src=/dev/mapper/pve-data-tpool -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk- src=/dev/pve/vm-9201-disk-3 -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-7 -> dm-7(pve-vm--9201--disk--3) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9201 mp8 /mnt/felhom-drives (host bind) src=/dev/mapper/pve-root[/mnt/felhom-drives] -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 mp9 /etc/felhom-bootstrap (host bind) src=/dev/mapper/pve-root -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 rootfs / (local-lvm:vm-9201-disk-2) src=/dev/pve/vm-9201-disk-2 -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-6 -> dm-6(pve-vm--9201--disk--2) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +host mount /mnt/hdd_1 src=/dev/sdb -> wwn:0x5000039ddb108568 [proven] + sdb ADATA TOSHIBA_MQ04ABF100 bus=ata 1000.2GB via: sdb +host mount /mnt/felhom-drives src=/dev/mapper/pve-root[/mnt/felhom-drives] -> wwn:0x5000000123456f1f [proven] + sda ATA AirDisk_512GB_SSD bus=ata 512.1GB via: dm-1 -> dm-1(pve-root) -> part sda3 +host mount /mnt/felhom-drives/hdd_1 src=/dev/sdb[/felhom-data] -> wwn:0x5000039ddb108568 [proven] + sdb ADATA TOSHIBA_MQ04ABF100 bus=ata 1000.2GB via: sdb diff --git a/documentation/audits/storage-identity-2026-10-15/B-tester1.json b/documentation/audits/storage-identity-2026-10-15/B-tester1.json new file mode 100644 index 00000000..58eaa38e --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-tester1.json @@ -0,0 +1,648 @@ +{ + "host": "felhom", + "virt": "kvm", + "places": [ + { + "place": "host root /", + "target": "/", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "pve storage local (dir)", + "target": "/var/lib/vz", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "pve storage local-lvm (lvmthin pve/data)", + "target": "/dev/mapper/pve-data-tpool", + "source": "/dev/mapper/pve-data-tpool", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk-1)", + "target": "/dev/pve/vm-9201-disk-1", + "source": "/dev/pve/vm-9201-disk-1", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp8 /mnt/felhom-drives (host bind)", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 mp9 /etc/felhom-bootstrap (host bind)", + "target": "/var/lib/felhom-agent/guests/9201/bootstrap", + "fstype": "ext4", + "mountpoint": "/", + "source": "/dev/mapper/pve-root", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "guest 9201 rootfs / (local-lvm:vm-9201-disk-0)", + "target": "/dev/pve/vm-9201-disk-0", + "source": "/dev/pve/vm-9201-disk-0", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_c", + "target": "/mnt/media_c", + "fstype": "ext4", + "mountpoint": "/mnt/media_c", + "source": "/dev/sde", + "physical_disks": [ + "serial:drive-scsi4" + ], + "disks": [ + { + "disk": "sde", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi4", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:05.0-scsi-0:0:0:4", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi4", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sde" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/adatlemez", + "target": "/mnt/adatlemez", + "fstype": "ext4", + "mountpoint": "/mnt/adatlemez", + "source": "/dev/sdb", + "physical_disks": [ + "serial:drive-scsi1" + ], + "disks": [ + { + "disk": "sdb", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi1", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:02.0-scsi-0:0:0:1", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi1", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdb" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_b", + "target": "/mnt/media_b", + "fstype": "ext4", + "mountpoint": "/mnt/media_b", + "source": "/dev/sdd", + "physical_disks": [ + "serial:drive-scsi3" + ], + "disks": [ + { + "disk": "sdd", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi3", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:04.0-scsi-0:0:0:3", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi3", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdd" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_a", + "target": "/mnt/media_a", + "fstype": "ext4", + "mountpoint": "/mnt/media_a", + "source": "/dev/sdc", + "physical_disks": [ + "serial:drive-scsi2" + ], + "disks": [ + { + "disk": "sdc", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi2", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:03.0-scsi-0:0:0:2", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi2", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdc" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/media_d", + "target": "/mnt/media_d", + "fstype": "ext4", + "mountpoint": "/mnt/media_d", + "source": "/dev/sdf", + "physical_disks": [ + "serial:drive-scsi5" + ], + "disks": [ + { + "disk": "sdf", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi5", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:06.0-scsi-0:0:0:5", + "size_gb": 21.5, + "rotational": "1", + "id": "serial:drive-scsi5", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdf" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives", + "target": "/mnt/felhom-drives", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives", + "source": "/dev/mapper/pve-root[/mnt/felhom-drives]", + "physical_disks": [ + "serial:drive-scsi0" + ], + "disks": [ + { + "disk": "sda", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi0", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:01.0-scsi-0:0:0:0", + "size_gb": 214.7, + "rotational": "1", + "id": "serial:drive-scsi0", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "dm-1 -> dm-1(pve-root) -> part sda3" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_a", + "target": "/mnt/felhom-drives/media_a", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_a", + "source": "/dev/sdc[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi2" + ], + "disks": [ + { + "disk": "sdc", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi2", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:03.0-scsi-0:0:0:2", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi2", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdc" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/adatlemez", + "target": "/mnt/felhom-drives/adatlemez", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/adatlemez", + "source": "/dev/sdb[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi1" + ], + "disks": [ + { + "disk": "sdb", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi1", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:02.0-scsi-0:0:0:1", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi1", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdb" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_c", + "target": "/mnt/felhom-drives/media_c", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_c", + "source": "/dev/sde[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi4" + ], + "disks": [ + { + "disk": "sde", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi4", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:05.0-scsi-0:0:0:4", + "size_gb": 53.7, + "rotational": "1", + "id": "serial:drive-scsi4", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sde" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_d", + "target": "/mnt/felhom-drives/media_d", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_d", + "source": "/dev/sdf[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi5" + ], + "disks": [ + { + "disk": "sdf", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi5", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:06.0-scsi-0:0:0:5", + "size_gb": 21.5, + "rotational": "1", + "id": "serial:drive-scsi5", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdf" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + }, + { + "place": "host mount /mnt/felhom-drives/media_b", + "target": "/mnt/felhom-drives/media_b", + "fstype": "ext4", + "mountpoint": "/mnt/felhom-drives/media_b", + "source": "/dev/sdd[/felhom-data]", + "physical_disks": [ + "serial:drive-scsi3" + ], + "disks": [ + { + "disk": "sdd", + "model": "QEMU_HARDDISK", + "vendor": "QEMU", + "serial": "drive-scsi3", + "wwn": "", + "bus": "scsi", + "usb_driver": "", + "path": "pci-0000:09:04.0-scsi-0:0:0:3", + "size_gb": 107.4, + "rotational": "1", + "id": "serial:drive-scsi3", + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ], + "via": "sdd" + } + ], + "identity": "unknown", + "why_unknown": [ + "inside a VM (kvm): a virtual disk says nothing about the host disk", + "virtual disk vendor/model" + ] + } + ] +} diff --git a/documentation/audits/storage-identity-2026-10-15/B-tester1.txt b/documentation/audits/storage-identity-2026-10-15/B-tester1.txt new file mode 100644 index 00000000..fffb8da0 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/B-tester1.txt @@ -0,0 +1,37 @@ +# host felhom virt=kvm +host root / src=/dev/mapper/pve-root -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage local (dir) src=/dev/mapper/pve-root -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-1 -> dm-1(pve-root) -> part sda3 +pve storage local-lvm (lvmthin pve/data) src=/dev/mapper/pve-data-tpool -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-4 -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9201 mp0 /var/lib/felhom (local-lvm:vm-9201-disk- src=/dev/pve/vm-9201-disk-1 -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-7 -> dm-7(pve-vm--9201--disk--1) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +guest 9201 mp8 /mnt/felhom-drives (host bind) src=/dev/mapper/pve-root[/mnt/felhom-drives] -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 mp9 /etc/felhom-bootstrap (host bind) src=/dev/mapper/pve-root -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-1 -> dm-1(pve-root) -> part sda3 +guest 9201 rootfs / (local-lvm:vm-9201-disk-0) src=/dev/pve/vm-9201-disk-0 -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-6 -> dm-6(pve-vm--9201--disk--0) -> dm-4(pve-data-tpool) -> dm-2(pve-data_tmeta) -> part sda3 +host mount /mnt/media_c src=/dev/sde -> serial:drive-scsi4 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sde QEMU QEMU_HARDDISK bus=scsi 53.7GB via: sde +host mount /mnt/adatlemez src=/dev/sdb -> serial:drive-scsi1 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdb QEMU QEMU_HARDDISK bus=scsi 53.7GB via: sdb +host mount /mnt/media_b src=/dev/sdd -> serial:drive-scsi3 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdd QEMU QEMU_HARDDISK bus=scsi 107.4GB via: sdd +host mount /mnt/media_a src=/dev/sdc -> serial:drive-scsi2 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdc QEMU QEMU_HARDDISK bus=scsi 107.4GB via: sdc +host mount /mnt/media_d src=/dev/sdf -> serial:drive-scsi5 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdf QEMU QEMU_HARDDISK bus=scsi 21.5GB via: sdf +host mount /mnt/felhom-drives src=/dev/mapper/pve-root[/mnt/felhom-drives] -> serial:drive-scsi0 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sda QEMU QEMU_HARDDISK bus=scsi 214.7GB via: dm-1 -> dm-1(pve-root) -> part sda3 +host mount /mnt/felhom-drives/media_a src=/dev/sdc[/felhom-data] -> serial:drive-scsi2 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdc QEMU QEMU_HARDDISK bus=scsi 107.4GB via: sdc +host mount /mnt/felhom-drives/adatlemez src=/dev/sdb[/felhom-data] -> serial:drive-scsi1 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdb QEMU QEMU_HARDDISK bus=scsi 53.7GB via: sdb +host mount /mnt/felhom-drives/media_c src=/dev/sde[/felhom-data] -> serial:drive-scsi4 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sde QEMU QEMU_HARDDISK bus=scsi 53.7GB via: sde +host mount /mnt/felhom-drives/media_d src=/dev/sdf[/felhom-data] -> serial:drive-scsi5 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdf QEMU QEMU_HARDDISK bus=scsi 21.5GB via: sdf +host mount /mnt/felhom-drives/media_b src=/dev/sdd[/felhom-data] -> serial:drive-scsi3 [unknown] inside a VM (kvm): a virtual disk says nothing about the host disk; virtual disk vendor/model + sdd QEMU QEMU_HARDDISK bus=scsi 107.4GB via: sdd diff --git a/documentation/audits/storage-identity-2026-10-15/README.md b/documentation/audits/storage-identity-2026-10-15/README.md new file mode 100644 index 00000000..5e2d248d --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/README.md @@ -0,0 +1,60 @@ +# Spike — can the agent name the physical disk under every storage place? (2026-10-15) + +For `architecture/16-storage-physical-identity.md` (draft). Method: `tools/physdisk_probe.py` — read-only, run as root +on each Proxmox host. It follows the block chain down to whole disks — partition → parent (`/sys/class/block/

/partition`, +the same as lsblk `PKNAME`), device-mapper / LVM thin → `/sys/class/block//slaves/*` recursively, loop → +`loop/backing_file` → the filesystem that holds the file — and reads each disk's `ID_WWN`, `ID_SERIAL_SHORT`, `ID_BUS`, +vendor and model from udev, plus `systemd-detect-virt`. `tools/summarize.py` prints the tables. The agent already +has most of this chain (`role.go` `walkSlaves`/`physicalDisksOf`, `hostread.go` `parentDisk`); it lacks the loop step +and a per-place report. + +## Results + +| # | Case | Where | The probe's answer | Truth | Right? | Evidence | +|---|---|---|---|---|---|---| +| 1 | One disk: host root, `local`, the thin pool, guest rootfs and `mp0` (`sys_drive` is a folder of `mp0`) | N100 | all → `wwn:0x5000000123456f1f` (AirDisk 512 GB SSD), proven | one SATA SSD | **yes** | `B-n100.txt` | +| 1b | The same on demo-hp | demo-hp | all system places → `wwn:0x5001b448b60a9d6e` (SanDisk 128 GB) | one SSD | **yes** | `B-demo-hp.txt` | +| 2 | Two disks: system + enrolled data drive | demo-hp, N100 | system → SanDisk / AirDisk; `/mnt/felhom-drives/hdd_1` → Toshiba NVMe (`eui…46c07b`) / Toshiba MQ04 on USB (`0x5000039ddb108568`) | two disks each | **yes** | `B-demo-hp.txt`, `B-n100.txt` | +| 3 | One disk, two partitions, two places | demo-hp, a 4 GB scratch file as a loop disk, `p1` and `p2` ext4, mounted | both → the NVMe that holds the file, via `loop2pN → loop2 → file on nvme0n1` | the same disk | **yes** (after a probe fix: the partition step must run before the loop step) | `B-case3-loop.*` | +| 4a | A USB enclosure that passes the disk's identity | N100's backup drive | `ID_BUS=ata`, real model, serial `65NOP3HDT`, WWN; `ID_USB_DRIVER=usb-storage` | the real Toshiba disk | **yes** | `B-n100.txt` | +| 4b | A USB enclosure that hides or fakes the serial | — | **not measured** — no such device at hand, none in earlier evidence (searched `documentation/`, agent, controller) | — | — | R-1077 | +| 4c | A cheap SSD with a generic WWN | N100 system SSD | `ID_WWN=0x5000000123456f1f`: NAA-5 with **OUI 000000** (no registered vendor) — the serial `QDF922W009654S30EX` looks real | unknown whether two units share the WWN | **probably weak** | R-1076 | +| 5 | Inside a VM: virtual disks on the **same** host disk | Tester 1 (VM 341): `scsi0`, `scsi1`, `scsi2` | inside: `QEMU HARDDISK`, serials `drive-scsi0/1/2`, `systemd-detect-virt=kvm` → **unknown** | host: all three are files on demo-hp's NVMe (`B-case56-host-truth.txt`) | **yes — „unknown"** | `B-tester1.txt`, `B-case56-*` | +| 6 | Inside a VM: a virtual disk on a **different** host disk | Tester 1, scratch `scsi6` (4 GB on `local-lvm` = demo-hp's SanDisk), hot-added and removed | inside: `QEMU HARDDISK`, `ID_SERIAL_SHORT=drive-scsi6` (the set serial `SCRATCHSID6` shows only as `ID_SCSI_SERIAL`) → **unknown** | host: the SanDisk | **yes — „unknown"** | `B-case56-*` | +| 7 | A network share | — (no box has one mounted now; the OMV run mounted one at `/mnt/felhom-drives/omv-filmek`) | the probe classes `cifs`/`nfs` sources as network → unknown, no disk | a disk on another machine | **yes by rule** (not run on a live share) | `../omv-vm-2026-10-15/B6-omv-share.txt` | + +**The VM cases in one sentence:** from inside a VM, two virtual disks on the same host disk and two on different host +disks look exactly alike (same vendor, same model, serial = the hypervisor's slot name), so the agent can only say +„unknown"; only the hypervisor's host knows. + +## What today's agent does with a partitioned disk (Tester 1, scratch `sdg`, read-only `GET /disks/candidates`) + +| Disk state | Agent answer | Evidence | +|---|---|---| +| blank | `initialize`: `/dev/sdg`, `data_bearing:false`, `mountable:false` | `B-case56-agent-blank.txt` | +| GPT, `p1` empty (no fs), `p2` empty ext4 | `attach` and `initialize`: one row `/dev/sdg`, `fstype ext4`, `mount_source /dev/sdg2`, `data_bearing:true`; **`p1` is not offered at all** | `B-case4b-partitions-empty.txt`, `B-case4b-partitions.txt` | +| GPT, both partitions empty | `initialize` only: `/dev/sdg`, `data_bearing:true`, `mountable:false` — the only way to use it is to wipe the whole disk | `B-case4b-partitions.txt` | + +So today a place is always a whole disk (or the one partition the agent picks), an empty filesystem counts as data, and +a partition table alone makes the whole disk „data-bearing". + +## Also found while reading (code, not run) + +- The controller's „same disk" test is `stat().st_dev` (`felhom-controller/controller/internal/system/mounts_linux.go:225-245`; + its own comment: „two partitions on one physical disk look "different" here"). Tier-2 target choice + (`internal/backup/tier2.go:83-179`) and the one-copy warning (`internal/backup/backup.go:1387-1410`) use it. +- Tester 1 today makes Tier-2 copies between `media_a` / `adatlemez` / … — all files on one host NVMe — and counts them as + off-drive copies (case 5). R-1074. +- `hasOffDriveTarget` (`backup.go:1390-1402`) does not skip network paths, and a NAS is registered `Schedulable:true` + (`internal/web/netstorage_job.go:267-273`), so adding a NAS would remove the „Csak egy másolat…" warning while Tier-2 + refuses a NAS (`tier2.go:141-143`). Read in code, not run. R-1075. +- `sys_drive` is a folder of `mp0` (`/var/lib/felhom`, `backup=1`), next to Docker — not a separate `mp1` (all three boxes, + `pct config 9201`; `07-backup-architecture.md` §7.5.1). Anything stored there rides in every whole-guest copy. + +## Put back + +- demo-hp: the 4 GB scratch file and its loop device removed (checked: `losetup -a` 0 lines, file absent). A first try left + them for ~1 minute (a missing `partprobe`); removed at once, nothing else touched. +- Tester 1: scratch `scsi6` partitioned, wiped (`wipefs -a`, `sgdisk -Z` — the scratch disk only, matched by its serial + before every write), hot-removed, its LV `vm-341-disk-0` destroyed; `sdg` gone; VM 341 still running. +- Probe files deleted from all hosts. No disk that holds anything was written. DooPlex and ep0 not touched. diff --git a/documentation/audits/storage-identity-2026-10-15/tools/agent_read.sh b/documentation/audits/storage-identity-2026-10-15/tools/agent_read.sh new file mode 100644 index 00000000..8d37fa99 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/tools/agent_read.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# agent_read.sh — READ-ONLY GETs to the agent local API, run ON the PVE host (token never leaves it) +export LC_ALL=C +B=/var/lib/felhom-agent/guests/9201/bootstrap/bootstrap.json +TOK=$(python3 -c "import json;print(json.load(open('$B'))['local_api']['token'])") +EP=$(python3 -c "import json;print(json.load(open('$B'))['local_api']['endpoint'])") +for p in "$@"; do echo "=== GET $p"; curl -sS -k -m 30 -w '\nHTTP %{http_code}\n' -H "Authorization: Bearer $TOK" "https://$EP$p"; done diff --git a/documentation/audits/storage-identity-2026-10-15/tools/physdisk_probe.py b/documentation/audits/storage-identity-2026-10-15/tools/physdisk_probe.py new file mode 100644 index 00000000..8de2cd66 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/tools/physdisk_probe.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +"""physdisk_probe.py — READ-ONLY spike for 16-storage-physical-identity.md (2026-10-15). + +For every storage place on a Proxmox host (host root, PVE storages, guest mount points, /mnt/* mounts, extra paths +or devices given as arguments) follow the block chain down to WHOLE physical disks: + partition -> parent disk (/sys/class/block/

/partition, the parent sysfs dir = lsblk PKNAME) + dm / lvm / md -> /sys/class/block//slaves/* (recursive; a thin pool reaches its tdata/tmeta PVs) + loop -> /sys/block/loopN/loop/backing_file -> the filesystem holding that file -> recurse +and read each disk's identity from udev (ID_WWN, ID_SERIAL_SHORT, ID_BUS, ID_VENDOR, ID_MODEL) + sysfs. +identity = proven | unknown, with the reason. Writes nothing; runs only lsblk/findmnt/udevadm/pct/pvesm reads. +""" +import json, os, subprocess, sys + +def sh(*a): + try: return subprocess.run(a, capture_output=True, text=True, timeout=20).stdout.strip() + except Exception: return '' + +VIRT = sh('systemd-detect-virt') or 'unknown' +VIRTUAL_VENDORS = ('QEMU', 'VBOX', 'VMware', 'Msft', 'Red Hat', 'Xen') +BLOCK = '/sys/class/block' + +def kname(dev): + return os.path.basename(os.path.realpath(dev)) + +def chain(name, via, depth=0): + """-> list of (disk_name, via-string)""" + if depth > 12: return [(name, via + ' !depth')] + p = os.path.join(BLOCK, name) + if not os.path.exists(p): return [(name, via + ' !nosysfs')] + if os.path.exists(os.path.join(p, 'partition')): + parent = os.path.basename(os.path.dirname(os.path.realpath(p))) + return chain(parent, via + f' -> part {name}', depth + 1) + if name.startswith('loop'): + bf = '' + try: bf = open(f'/sys/block/{name}/loop/backing_file').read().strip() + except Exception: pass + if bf: + src = sh('findmnt', '-n', '-o', 'SOURCE', '-T', bf) + if src.startswith('/dev/'): + return chain(kname(src), via + f' -> loop[{bf}] on {src}', depth + 1) + return [(name, via + ' -> loop(no backing)')] + sl = os.path.join(p, 'slaves') + if os.path.isdir(sl) and os.listdir(sl): + out = [] + dmname = '' + try: dmname = open(os.path.join(p, 'dm', 'name')).read().strip() + except Exception: pass + for s in sorted(os.listdir(sl)): + out += chain(s, via + f' -> {name}{"(" + dmname + ")" if dmname else ""}', depth + 1) + return out + return [(name, via)] + +def disk_identity(d): + props = {} + for line in sh('udevadm', 'info', '--query=property', f'/dev/{d}').splitlines(): + k, _, v = line.partition('=') + props[k] = v + def rd(f): + try: return open(f'/sys/block/{d}/{f}').read().strip() + except Exception: return '' + info = { + 'disk': d, + 'model': props.get('ID_MODEL', rd('device/model')), + 'vendor': props.get('ID_VENDOR', rd('device/vendor')), + 'serial': props.get('ID_SERIAL_SHORT', ''), + 'wwn': props.get('ID_WWN', rd('wwid') or rd('device/wwid')), + 'bus': props.get('ID_BUS', ''), + 'usb_driver': props.get('ID_USB_DRIVER', ''), + 'path': props.get('ID_PATH', ''), + 'size_gb': round(int(rd('size') or 0) * 512 / 1e9, 1), + 'rotational': rd('queue/rotational'), + } + why = [] + vend = (info['vendor'] + ' ' + info['model']).upper() + if VIRT not in ('none', ''): why.append(f'inside a VM ({VIRT}): a virtual disk says nothing about the host disk') + if any(v.upper() in vend for v in VIRTUAL_VENDORS): why.append('virtual disk vendor/model') + if d.startswith('vd') and not info['serial']: why.append('virtio disk without a serial') + if not (info['serial'] or info['wwn']): why.append('no serial and no wwn') + if info['bus'] == 'usb' and info['serial'] and len(set(info['serial'])) <= 2: why.append('USB bridge serial looks fake') + info['id'] = ('wwn:' + info['wwn']) if info['wwn'] else (('serial:' + info['serial']) if info['serial'] else '') + info['identity'] = 'unknown' if why else 'proven' + info['why_unknown'] = why + return info + +def place(label, target): + """target: a /dev path, a mounted path, or 'net:' prefix""" + rec = {'place': label, 'target': target} + src = target + if not target.startswith('/dev/'): + src = sh('findmnt', '-n', '-o', 'SOURCE', '-T', target) + rec['fstype'] = sh('findmnt', '-n', '-o', 'FSTYPE', '-T', target) + rec['mountpoint'] = sh('findmnt', '-n', '-o', 'TARGET', '-T', target) + rec['source'] = src + if rec.get('fstype') in ('cifs', 'nfs', 'nfs4', 'smb3', 'fuse.sshfs') or (src and not src.startswith('/dev/')): + rec['physical_disks'] = [] + rec['identity'] = 'unknown' + rec['why_unknown'] = [f'network or non-block source ({rec.get("fstype")}: {src})'] + return rec + src = src.split('[')[0] + ch = chain(kname(src), kname(src)) + disks = [] + seen = set() + for d, via in ch: + if d in seen: continue + seen.add(d) + di = disk_identity(d); di['via'] = via + disks.append(di) + rec['physical_disks'] = [d['id'] or ('dev:' + d['disk']) for d in disks] + rec['disks'] = disks + rec['identity'] = 'proven' if disks and all(d['identity'] == 'proven' for d in disks) else 'unknown' + rec['why_unknown'] = sorted({w for d in disks for w in d['why_unknown']}) + return rec + +def places(): + out = [('host root /', '/')] + if sh('which', 'pvesm'): + for line in sh('pvesm', 'status').splitlines()[1:]: + f = line.split() + if len(f) < 2 or f[2] != 'active': continue + name, typ = f[0], f[1] + cfg = sh('pvesh', 'get', f'/storage/{name}', '--output-format', 'json') + try: c = json.loads(cfg) + except Exception: c = {} + if typ == 'dir' and c.get('path'): out.append((f'pve storage {name} (dir)', c['path'])) + elif typ == 'lvmthin': out.append((f'pve storage {name} (lvmthin {c.get("vgname")}/{c.get("thinpool")})', '/dev/mapper/' + c.get('vgname','').replace('-','--') + '-' + c.get('thinpool','').replace('-','--') + '-tpool')) + elif typ == 'lvm': out.append((f'pve storage {name} (lvm)', f'/dev/{c.get("vgname")}')) + elif typ in ('nfs', 'cifs') and c.get('path'): out.append((f'pve storage {name} ({typ})', c['path'])) + for vmid in sh('pct', 'list').split('\n')[1:]: + v = vmid.split()[0] if vmid.split() else '' + if not v: continue + for line in sh('pct', 'config', v).splitlines(): + k, _, val = line.partition(': ') + if k == 'rootfs' or k.startswith('mp'): + vol = val.split(',')[0] + mp = [x.split('=')[1] for x in val.split(',') if x.startswith('mp=')] + lab = f'guest {v} {k} {mp[0] if mp else "/"}' + if vol.startswith('/'): + out.append((lab + ' (host bind)', vol)) + else: + pth = sh('pvesm', 'path', vol) + out.append((lab + f' ({vol})', pth if pth else vol)) + for m in sh('findmnt', '-rn', '-o', 'TARGET').splitlines(): + if m.startswith('/mnt/') and (m.count('/') == 2 or m.startswith('/mnt/felhom-drives/')): out.append((f'host mount {m}', m)) + return out + +if __name__ == '__main__': + extra = sys.argv[1:] + todo = places() + [(f'arg {a}', a) for a in extra] + res = {'host': sh('hostname'), 'virt': VIRT, 'places': []} + for lab, t in todo: + try: res['places'].append(place(lab, t)) + except Exception as e: res['places'].append({'place': lab, 'target': t, 'error': str(e)}) + print(json.dumps(res, indent=1)) diff --git a/documentation/audits/storage-identity-2026-10-15/tools/summarize.py b/documentation/audits/storage-identity-2026-10-15/tools/summarize.py new file mode 100644 index 00000000..dbcfefb0 --- /dev/null +++ b/documentation/audits/storage-identity-2026-10-15/tools/summarize.py @@ -0,0 +1,8 @@ +import json,sys +d=json.load(open(sys.argv[1])) +print(f"# host {d['host']} virt={d['virt']}") +for p in d['places']: + if 'error' in p: print(f"{p['place']:<55} ERROR {p['error']}"); continue + ds=p.get('disks',[]) + print(f"{p['place'][:55]:<55} src={p.get('source','')[:40]:<40} -> {','.join(p['physical_disks']) or '-'} [{p['identity']}] {'; '.join(p['why_unknown'])}") + for x in ds: print(f"{'':<8}{x['disk']:<8} {x['vendor'][:10]:<10} {x['model'][:28]:<28} bus={x['bus']:<5} {x['size_gb']}GB via: {x['via']}") diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index d27adb8b..42a8d34e 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -155,7 +155,7 @@ stopping line that lies. | **R-683** | App updates | P3 | **[P3-LOW] Watch: after a power cut during an update's health check, the hold named an HOUR-OLD second-drive copy, not the one the update's own backup should have just made.** 2026-09-24 chaos round 3 (nextcloud, `backup_max_age: 1m`): no `backing-up` phase was seen and the hold named Tier 2 at 13:04 for an update pressed at 14:04; the pre-cut controller log was lost with the container (the runner now saves it at arm time — R-320). Round 11, the same action without a power cut, named a fresh 14:34 copy and logged the Tier-2 copy. The sentence was TRUE (it named the copy it offered); the question is why the update did not back up first. Not reproduced; watch the next power-cut drill. `audits/night-2026-09-24/E/round-03*.json`, `E/round-11-controller-pre.log` | **OPEN — P3; owner: CC (watch)** | — | — | CC | | **R-785** | App updates | P3 | **[P3-LOW] SparkyFitness is pinned 11 releases and a major behind upstream (v0.17.3; upstream v1.7.3, v1.6.0 dated 2026-07-24).** READ 2026-10-01 (`audits/visitors-2026-10-01/C/bench/C1-previous-tag.txt`). **Needs:** an update walk 0.17 → 1.x through the ladder (bench + box), after R-784 is decided. | **OPEN — rank P3-LOW; owner: CC (after R-784)** | — | — | CC | -## Backup & restore — 31 rows (P2 3, P3 17, P4 11) +## Backup & restore — 33 rows (P2 3, P3 19, P4 11) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| @@ -179,6 +179,8 @@ stopping line that lies. | **R-921** | Backup & restore | P3 | **When the off-site tier answers BUSY, the household still gets a short stop of every app — with no copy.** MEASURED 2026-10-08 night on demo-hp (read-back 2026-10-09, `audits/dooplex-survival-2026-10-09/partE/R-518.txt`): local tier 20:20–20:25Z (own stop, < 2 min), then at 20:26:14Z the agent refused the off-site request (`backup refused — a heavy operation is already in flight`, `busy=backup:local` — the night OS step ran 20:27–20:29Z), yet the controller's metrics show all 15 app containers down at 20:26:19Z and back at 20:27:19Z; the retry ran the off-site tier at 20:34Z with its own short stop. So a two-tier night costs THREE stops, one of them for nothing. This was R-518's noted "unmeasured" risk. Fix shape: ask the agent whether it is free (or reserve the slot) BEFORE quiescing, and resume at once on BUSY. | **NARROWED 2026-10-09 — built; RELEASED 2026-10-10 (controller 0.305.0 on demo-hp, demo-felhom, Tester 1):** before stopping apps the controller asks the agent which tiers have a job in flight (`GET /backup/status`); another tier's job in flight → no stop, the tier stays due (red-proved: 3 apps stopped for a refused tier before); a refusal after the stop still resumes the apps at once (pinned). Also fixes a stop after a long upload or a restart mid-upload. **LEFT: the measured case itself** — the agent's host-wide busy lock (the night OS step, restore test, fstrim) is served on NO endpoint, so the controller cannot see it before stopping; needs one agent field (e.g. `busy` on `GET /backup/status`) + a controller pre-check behind a feature probe. `07` §6.4. | an agent change | Build the agent `busy` field + its controller check; read back a two-tier night | CC | | **R-933** | Backup & restore | P3 | **Mirror the images of every catalog app we support into our own registry, before scale.** Operator, 2026-10-12 (S8, `09` §3 decision 203): *„Will need to mirror the apps we support later, just to be sure."* Today a restore re-pulls each image from its maker; a version the maker deleted cannot start (the accepted limit, `07` §6.6, R-698 closed). Size it first: the supported catalog's images (every ladder version a box can hold) × their size; then where the copy lives (the DooPlex registry is Tier 2, precious — the copy must not make DooPlex a single point of failure for every household's restore) and how a restore falls back to it. | **OPEN** — NEW 2026-10-12 | the size measurement | Measure the total size of the supported catalog's images; then a one-page design (where, how a restore falls back, cost) | CC (measure + design), operator (the go) | | **R-1019** | Backup & restore | P3 | **The live download-client templates put downloads into two backup tiers nobody chose.** MEASURED 2026-10-14 with the controller's own classifier over the live templates (`audits/media-all-drives-2026-10-14/``A-drives/A6-3-capture-sets.txt`): Transmission's `${USERDATA_PATH}/media/transmission/watch` bind is not listed in its `backup:` block, so it is classed MANDATORY and goes into the OFF-SITE copy (a writable unlisted bind defaults to mandatory); and qBittorrent's `media/torrents` and Transmission's `media/transmission` are `optional`, so on a box with a second drive every download is mirrored there nightly (Tier 2 = mandatory + optional) — it can fill the backup drive with films. | **NARROWED** — filed 2026-10-14; the `watch` half FIXED 2026-10-14 (declared optional, app-catalog `bc54c01`); open: the `optional` download folders still get a nightly Tier-2 mirror on a box with a second drive | — | Declare the media binds `excluded` (the watch folder too) in the live-fix task; `15` §7 states the rule for the per-drive bind | CC | +| **R-1074** | Backup & restore | P3 | **Tier-2 decides „a different disk” by `st_dev`, so virtual disks on one host disk — and, later, two partitions of one disk — count as a real second copy.** MEASURED 2026-10-15: Tester 1 (a box inside a VM) has five data drives that are all files on demo-hp's one NVMe (`audits/storage-identity-2026-10-15/B-case56-host-truth.txt`); `selectTier2TargetFrom` (C/internal/backup/tier2.go:83-179) and `hasOffDriveTarget` (C/internal/backup/backup.go:1390-1402) use `SamePhysicalDevice` = `stat().st_dev` (C/internal/system/mounts_linux.go:225-245, whose comment names the partition gap). So Tier-2 copies there are counted as off-drive. On real hardware with whole-disk drives the answer is right. | WAITING-ON-OPERATOR | R-1079's rulings D1/D2. | Build per `architecture/16-storage-physical-identity.md` §4: the controller asks the agent. | CC | +| **R-1075** | Backup & restore | P3 | **Adding a NAS share would hide the „Csak egy másolat…” warning, although a NAS is never a Tier-2 target.** READ IN CODE 2026-10-15, not run: `hasOffDriveTarget` (C/internal/backup/backup.go:1390-1402) skips only the system path and same-`st_dev` paths, not `IsNetwork()`; a NAS is registered `Schedulable:true` (C/internal/web/netstorage_job.go:267-273) on a different `st_dev`; Tier-2 refuses it (tier2.go:141-143). Result: a one-disk box with a NAS would claim an off-drive copy is possible. Evidence: `audits/storage-identity-2026-10-15/README.md` „Also found”. | OPEN | — | Prove on a scratch box (add a NAS share, read `/backups`); then skip network paths in `hasOffDriveTarget` with a red-proved test — or fold into R-1079's build. | CC | | **R-91** | Backup & restore | P4 | Old 13 GB datastore copy at `/srv/pbs-felhom` on ep0's root disk **Checked from source 2026-10-05 (burn-down round 2):** Gate is long past (row waits on demo-felhom's first post-migration PBS backup, migration 2026-07-27). Last positive record of the copy: audits/CAMPAIGN-9-restore-proof-2026-07-28.md:759 'ep0 : /srv/pbs-felhom rollback copy intact (13G)'; CONTEXT.md:3666 still says it is 13 G of dead weight awaiting R-91. No later record of deletion found (grep srv/pbs-felhom across felhom.eu). Deleting is on ep0 (protected) and needs an operator word. | WATCHING | demo-felhom's first **post-migration** PBS backup | Delete once it lands; fix `CONTEXT.md:1018` same commit | CC | | **R-164** | Backup & restore | P4 | **C2's chain: the DB volume tar cannot be dropped until a SOUND dump predicate exists.** The unit carries both a volume tar and a SQL dump; the restore uses **both** — the dump is authoritative and replayed *after* the tar so it WINS (F17), with only the DB service up (R-47) — `internal/backup/restore_unit.go:262-266`. Dropping the DB container's tar would halve DB-app units **and** close the R-127(b) initdb-skip password trap (restored PGDATA ⇒ `POSTGRES_PASSWORD` ignored). | **BLOCKED** — on the predicate | a dump-validity predicate that is not `accounts has rows` | **The obvious gate is DEAD, measured:** `ValidateDump` warns when the `accounts` table is empty, and that warning was **correct** — the live DB genuinely had 0 accounts, and seeding one stopped the warning and put the row in the dump. But **a fresh appliance legitimately has zero accounts**, so promoting that predicate to a gate would **block every new customer's first backup**. Order: (1) a sound predicate — dump vs **live** per-table counts, not an absolute expectation; (2) warn→gate; (3) tar-drop. **Until (1), the tar is load-bearing** — not because dumps are bad, but because nothing can yet prove one is good. Pairs with **R-127** | CC | | **R-213** | Backup & restore | P4 | **Putting files back in place — the half the recovery screen deliberately does not do.** The screen (R-193, controller v0.200.0) unlocks the repository and LISTS what is in it; restoring is per-app and lives in the backups area, and the operator ruled the two separate on 2026-08-05: *a screen that unlocks and then offers to overwrite is two decisions wearing one button*. What is missing is the step after the listing — a customer who can now SEE their files still has to work out, per app, which restore to choose. **The operator named its requirement: a live-versus-backup comparison** — the customer must be able to see what would change before anything is overwritten | **DEFERRED** — operator ruling 2026-10-12 (S18, `09` §3 decision 213): designed after the first customers. Stays P4; re-dated: look again when the first paying household has run 30 days. **OPEN — not started, deliberately** | the comparison design (nothing exists for it yet) | After the first customers | Operator + CC | @@ -191,11 +193,12 @@ stopping line that lies. | **R-32** | Backup & restore | P4 | **[P2-HIGH] RESET must purge the customer base dir; the orphan card must stay honest; unattributed bytes must be visible.** The rehearsal's S7 said in advance that an orphan card would BE a finding — and one appeared (16:58:14). Cause: RESET's `"hetzner":"ok"` leg destroys the sub-account, but **a Hetzner sub-account is an access-control object, not a data object** — its directory survives, so re-enabling offsite recreated an account over the previous lifecycle's ciphertext, encrypted under a key that same RESET had destroyed. **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-21, size M, roadmap state `idea`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **2026-10-06 night: design written** (`audits/night-burndown-2026-10-06/design-R-32.md`) — pick A: purge the repo + set-aside copies through the sub-account's own password login BEFORE deleting it (no main-account credential); the „repo data destroyed" comment at `hub/internal/offsite/offsite.go:276-280` is false for the shared tier; part (3) waits on a read-only measurement (`du` on port 23). Operator: agree to route A. **2026-10-07 07:58: `09` §3 decision 167 — option A yes, and delete the old RESET leftovers once.** **2026-10-07 (Part D step 2, read only):** the hub shows bx11 holding 3.3 GB of data while the four live customers account for ~0.6 GB → **~2.7 GB belongs to no live customer**; no live customer shows a set-aside folder, so the leftovers are in homes whose sub-account is gone, reachable only by the pool box's MAIN account. **The one-time clean-up is STOPPED:** no main-account login for bx11 is held on DooPlex (the API token in the credentials file sees no box). Needs: the main-account login, or the operator lists and deletes in the Hetzner console (`audits/day-2026-10-07/D/D2-listing-readonly.txt`). **2026-10-07: option A DELIVERED (hub 0.142.0):** RESET purges the repo and every `.orphaned-*` through the sub-account's own login before deleting it, and keeps the sub-account if the purge fails (red-proved, `audits/day-2026-10-07/D/`). Not yet seen live (no scratch RESET today). **The one-time clean-up of the ~2.7 GB of leftovers is STOPPED:** it needs the pool box's main-account login (see above). **2026-10-07 14:43 — `09` §3 decision 173: leave the ~2.7 GB of old leftovers for now; re-ranked P2 → P4.** Option A itself is delivered (hub 0.142.0). What stays open is ONLY the leftovers: they were computed (box total minus live customers), never listed, and deleting them needs the pool box's MAIN login, which reaches every customer's data. **Blocker: a safe main-account path.** | — | **Ruling from the run (three parts, deliberately separate):** (1) because RESET destroys custody, the ciphertext it leaves behind is unrecoverable **BY DESIGN** → RESET gains a **main-account purge of the customer base dir** (the existing operator ack already covers it); (2) the **move-aside guard STAYS** for reinstall-*without*-RESET — there custody survives and the card's "history recoverable" promise is true (R-26 depends on exactly that); (3) the operator **Restic tab shows per-customer directory bytes vs attributed snapshot bytes**, so dead data cannot hide. Measured on the pool box that night: **49 M attributed** (2 snapshots, 48.717 MiB) against **1.4 G + 3.0 M unattributed** across TWO `.orphaned-*` dirs. Evidence `restic-and-pool.txt` | CC | | **R-1072** | Backup & restore | P4 | **The backup page speaks to the household in two registers in one card: „csatlakoztasson” (formal) and „Csatlakoztass” (informal).** MEASURED 2026-10-15 on controller 0.314.0, one-disk box, `/backups`: „Csak egy másolat készül (nincs második meghajtó) — a 3-2-1 mentéshez csatlakoztasson egy második meghajtót vagy offsite tárolót.” next to „… Csatlakoztass egy második meghajtót a teljes védelemhez.” The product's voice is informal (tegezés). Small; not fixed here because this run allowed no product change. Evidence: `audits/omv-vm-2026-10-15/B4-backup-pages.txt`. | READY | — | Change the first string to „csatlakoztass” (and „offsite tárolót” → „távoli tárhelyet”) in the controller's i18n file; the copy gates run. | CC | -## Storage & devices — 9 rows (P3 6, P4 3) +## Storage & devices — 12 rows (P2 1, P3 6, P4 5) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| -| **R-1068** | Storage & devices | P3 | **On a box with one disk, a media app's (or any data-folder app's) Install is refused with a raw field error, and the way through is nowhere near the button.** MEASURED 2026-10-15 on the OMV-VM copy of the pilot's box (one passed NVMe, controller 0.314.0): `POST /api/stacks/jellyfin/deploy` with DOMAIN+SUBDOMAIN → **400 „a(z) "Médiatár útvonal" (HDD_PATH) mező kitöltése kötelező”** — the env var name reaches the household. R-1031's default-drive rule finds no drive because none is registered. The box DOES offer one: `/api/disks/candidates` listed `/mnt/sys_drive` (the installer's data volume, `already_mounted`), and `handleStorageRegisterMounted` (R-280) registers it — **seen in the candidate list and the code, NOT pressed** (the box was removed). With a second disk attached through „Csatlakoztatás”, the same Install succeeded in 30 s. Evidence: `audits/omv-vm-2026-10-15/README.md` „What happened”, `B4-deploy.txt`. | OPEN | — | Prove the `sys_drive` route live on a one-disk box (Tester 1 or a scratch VM); then make the Install refusal name it in household words (a link to Meghajtók), or register `sys_drive` by default on a one-disk box. | CC | +| **R-1079** | Storage & devices | P2 | **Build „storage that knows its physical disks” (`architecture/16-storage-physical-identity.md`, DRAFT): every place carries `physical_disks` + `identity`, computed by the agent; Tier-2 counts only on proven different disks; a „Belső tárhely” internal place on one-disk boxes; partitions as places.** Operator ruling 2026-10-15 asked for it. Spike proved the agent-side walk on real devices (one disk, two disks, two partitions, USB pass-through) and showed a VM can only be `unknown` (`audits/storage-identity-2026-10-15/README.md`). Closes, when built: R-1068, R-1074, R-1075; touches R-1069, R-1071, R-1073, R-548. | WAITING-ON-OPERATOR | Operator: rulings D1–D6 in `architecture/16-storage-physical-identity.md` §12. | After the rulings, a build task: agent (place identity, same-disk call, partition candidates), controller (Tier-2 + notice ask the agent, i18n sentences, install refusal in words), installer (`step_grows` + internal LV), hub (two report fields), guides. | Operator | +| **R-1068** | Storage & devices | P3 | **On a box with one disk, a media app's (or any data-folder app's) Install is refused with a raw field error, and the way through is nowhere near the button.** MEASURED 2026-10-15 on the OMV-VM copy of the pilot's box (one passed NVMe, controller 0.314.0): `POST /api/stacks/jellyfin/deploy` with DOMAIN+SUBDOMAIN → **400 „a(z) "Médiatár útvonal" (HDD_PATH) mező kitöltése kötelező”** — the env var name reaches the household. R-1031's default-drive rule finds no drive because none is registered. The box DOES offer one: `/api/disks/candidates` listed `/mnt/sys_drive` (the installer's data volume, `already_mounted`), and `handleStorageRegisterMounted` (R-280) registers it — **seen in the candidate list and the code, NOT pressed** (the box was removed). With a second disk attached through „Csatlakoztatás”, the same Install succeeded in 30 s. Evidence: `audits/omv-vm-2026-10-15/README.md` „What happened”, `B4-deploy.txt`. **-- 2026-10-15 (storage-identity spike):** the `sys_drive` route is REJECTED by design — `sys_drive` is a folder of `mp0` (`backup=1`), so films there would ride in every whole-guest copy; the proposal is an internal data place outside vzdump, `architecture/16-storage-physical-identity.md` §5; folded into R-1079. | WAITING-ON-OPERATOR | R-1079's ruling D3/D4. | (Superseded:) prove the `sys_drive` route live on a one-disk box (Tester 1 or a scratch VM); then make the Install refusal name it in household words (a link to Meghajtók), or register `sys_drive` by default on a one-disk box. | CC | | **R-1069** | Storage & devices | P3 | **A disk passed into a Felhom VM on a virtio bus cannot be formatted, and the household reads the agent's raw English refusal.** MEASURED 2026-10-15 (OMV KVM plugin, „Add host disk”, default Bus `virtio`): `POST /api/disks/format` → 500 „agentapi: format: HTTP 409: format refused: device has no durable id to bind the format to (path-only formats are not permitted)”. A virtio-blk disk without a serial has no `/dev/disk/by-id` link inside the guest, so the anti-retarget guard refuses — correct and safe. The same disk on Bus `sata` got `byid:ata-QEMU_HARDDISK_QM00003` and formatted. Affects every hypervisor that passes disks as virtio without a serial (OMV KVM, Proxmox without `serial=`). The pilot guide says `sata`. Evidence: `audits/omv-vm-2026-10-15/B4c-second-disk-format.txt`. | OPEN | — | Translate the refusal for the household („Ezt a lemezt a Felhom nem tudja biztonságosan azonosítani — a virtuális gépben állítsd a lemez buszát SATA-ra”); optionally fall back to a filesystem-UUID binding after a blank-format. | CC | | **R-1073** | Storage & devices | P3 | **Felhom in a virtual machine sees no disk health: SMART is UNKNOWN for its own system disk and any passed disk.** MEASURED 2026-10-15 on the OMV-VM copy: every storage target reported `smart.health = UNKNOWN`, all counters null (the guest sees QEMU disks). On the pilot's box the NVMe and the „old, not stable” Toshiba would be watched by OMV only, and Felhom's drive-health alarms (R-330/R-332's whole point) cannot fire. Evidence: the host report in `audits/omv-vm-2026-10-15/README.md` (memory/disk section) and `C-hub-events-Tester4.txt`. | WAITING-ON-OPERATOR | Operator: is a VM install a supported shape, and if so, is „OMV watches SMART” acceptable or must Felhom say on the dashboard that it cannot watch the disks? | Operator rules; then CC adds a household line on the Meghajtók page when SMART is unavailable. | Operator | | **R-1062** | Storage & devices | P4 | **The N100's USB drive cannot be split in two without losing the box's whole-guest backup target.** The operator asked (2026-10-15 16:31) for two halves for multi-drive tests. Read first (`audits/n100-lived-in-2026-10-15/B/`): no family files — 2.7 GB nightly vzdumps of guest 9201 (`dump/`, PVE storage `felhom-backup` = the whole-guest backup target), 3.1 GB app backups + an off-site restore copy, 422 MB leftover app data of removed apps, empty media folders. The agent refuses a decommission of a backup target (`refuseIfBackupTarget`) and the N100 has no other drive to move that role to. Nothing changed. | **WAITING-ON-OPERATOR** — filed 2026-10-15 | operator decision | Keep one drive (CC's pick: the lived-in box keeps its local whole-guest backup), or give a word to drop that backup leg / add a second drive first | operator | @@ -204,6 +207,8 @@ stopping line that lies. | **R-330** | Storage & devices | P3 | **Disk health Phase 2 — the three SMART attributes the wire does not carry.** The failing drive's most telling counter was **187 `Reported_Uncorrect`**, sitting at normalized **1** against threshold **0** with a raw count of **1001** — one point from failing and structurally unable to get there. Also wanted: **199 `UDMA_CRC_Error_Count`** (cabling) and **188 `Command_Timeout`**. None are on the agent→controller wire today, so v0.215.0's ladder could not use them. Phase 2 also persists periodic SMART **samples** (the right home is `metrics.MetricsStore`, NOT the Phase-1 state file, which is one record per disk and must stay that way). **This is a declared WIRE change, so under the G-1 gate the hub must model the new fields in the SAME session** — that is precisely why it was kept out of Phase 1, where it would have turned a one-word severity fix into a three-repo change | **READY** — **2026-10-12: the wire half is CLOSED in this row** — released in agent v0.150.0 (boxes run 0.154.0), controller and hub decode 187/188/199. **Only open work:** the verdict slice (use the three counters in the disk verdict and the household's words) and persisting samples. **READY (M) — NEW 2026-08-14** **2026-10-06 night: the wire half BUILT on main (unreleased):** the agent sends SMART 187 `reported_uncorrect`, 188 `command_timeout` (raw, vendor-packed on some drives — carried as reported), 199 `udma_crc_errors` (pointer + omitempty: unknown is absent, never 0); the controller decodes them and the hub's host-report mirror models them (G-1 wire gate green; it convicted the agent half alone). **Carried only** — no verdict, banner, mail or alarm reads them (`TestR330_CountersChangeNoVerdictYet`); using them changes what a household is told and is the next slice, with persisting samples. Red-proofs `audits/night-burndown-2026-10-06/r330/`. Ships with agent v0.150.0 and the next controller and hub releases. | R-328 (closed) | The verdict slice: 187/188/199 into the disk verdict with tests; then persist samples | CC | | **R-332** | Storage & devices | P3 | **The new Hiba-from-counters path has never fired on real hardware.** v0.215.0's whole point is a verdict the product could not previously reach, and it is proven only against the committed fixture's values in unit tests (12 scenario groups, 11 of 12 red-proofs failing as required). The live validation on demo-hp proved the **negative** — three healthy disks still read Rendben across the deploy, no false alert — and the **severity wire** end to end, but no live disk has actually reached Hiba. **This is the honest gap and it must not be closed by pointing at the fixture tests**: the drive that produced the fixture is in DooPlex, which is Tier 2 and never a drill target, and the demo boxes are all-flash and healthy | **WATCHING — NEW 2026-08-14, NARROWED same day.** One item originally in this gap is now PROVEN LIVE: the **persisted state surviving a controller restart**. The v0.215.0→v0.216.0 redeploy destroyed and rebuilt the container, and the new one read back a `changed_at` written by the PREVIOUS version (`2026-08-14T07:23:14.640216851Z`, still intact at 09:31:35Z) instead of re-baselining — Scenario L on real hardware, not just the production-path unit test. **What remains unproven is the verdict itself, plus the stronger restart half: an already-ALERTED disk not re-alerting** | a real degrading disk, or an injection harness | **Closing condition:** a live disk reaching Hiba from counters, OR a deliberate injection through the REAL pipeline (agent `/disks` → controller check → hub event), not a hand-set verdict | CC | | **R-331** | Storage & devices | P4 | **Disk health Phase 3 — growth-rate detection, and retiring the static 64.** The v0.215.0 count backstop (64 unreadable sectors → Hiba) is **a judgement from ONE drive**: the observed benign excursion peaked at 16 and cleared inside an hour, and the terminal run passed 64 at 13 Aug 11:28 and never came back. It is deliberately a backstop BEHIND the sustain rule, not the primary signal, but it is still a magic number tuned on a single sample and it will be wrong for some drive. With Phase 2's history the box can ask the question that actually matters — *is this count climbing, and how fast* — which distinguishes a drive with eight stable aging sectors from one adding forty a day, something no static threshold can do. Revisit 64 when that exists | **READY (M) — NEW 2026-08-14** | R-330 | Growth-rate rule over persisted samples; re-derive or delete the static 64 | CC | +| **R-1076** | Storage & devices | P4 | **A cheap SSD reports a vendor-less WWN, so a WWN-first disk key may not be unique.** MEASURED 2026-10-15 on the N100's system SSD (AirDisk 512 GB): `ID_WWN=0x5000000123456f1f` — NAA-5 with OUI `000000`, a pattern that looks like a placeholder; its serial `QDF922W009654S30EX` looks real. The agent's wipe binding prefers `wwn-` links (A/internal/storage/durable_device.go:32). Not known whether two units share the WWN. Evidence: `audits/storage-identity-2026-10-15/B-n100.txt`. | OPEN | — | Check a second unit of the same model (or vendor data); if shared, make the agent skip OUI-000000 WWNs (the design already keys on model+serial, `architecture/16-storage-physical-identity.md` §3). | CC | +| **R-1077** | Storage & devices | P4 | **No USB enclosure that hides or fakes a disk's serial has been measured.** The storage-identity spike (2026-10-15) had none at hand and found none in earlier evidence; the design's `usb_bridge` unknown rule (`architecture/16-storage-physical-identity.md` §3) is therefore an assumption. Cheap single- and dual-bay bridges are known to report one bridge serial for any disk. Evidence: `audits/storage-identity-2026-10-15/README.md` case 4b. | OPEN | — | Buy or borrow one cheap USB enclosure (single and dual bay), run `tools/physdisk_probe.py` against it, and set the rule from what it reports. | Operator (a device) then CC | ## Security & access — 21 rows (P1 2, P2 3, P3 10, P4 6) @@ -303,7 +308,7 @@ stopping line that lies. | **R-990** | Business & legal | P4 | **Operator: read `documentation/audits/forum-research-2026-10-12/FELHOM.md` §5 and rule on each recommendation.** READ-ONLY research 2026-10-12: three years (#7943–#11092, 2,908 posts, 195 people, 82 beginner threads) of the public PROHARDVER! topic „Home server / házi szerver építése”, tagged and counted by person (`FINDINGS.md`, method and spot-check in `METHOD.md`; no username or post text in git). Ten ranked recommendations, none acted on; the top three: a „which machine works” page (8 of 33 beginners who name their hardware own only a Synology, a router disk or a Raspberry Pi — the installer cannot run there; the same gap is R-989's first recommendation from a different source, and the shipped-page half is R-991), „you do not choose an operating system — we do” (the biggest beginner question, 20 of 82 threads), and „bring your old office PC” as the cheap entry. Catalog gap (≥ 3 people): a DLNA server (7), an ad/DNS blocker (5), a camera recorder (5). | **WAITING-ON-OPERATOR** — filed 2026-10-12 | the operator's reading | Operator: rule on each of the ten (yes / no / later). If nothing is done: nothing changes; the research ages | operator | | **R-1035** | Business & legal | P4 | **Did the „felhő tárhely” page earn anything? Two dated checks.** **Baseline (reported by the operator from Search Console, 2026-10-14, last 3 months):** 1 click, 48 impressions, CTR 2.1 %, average position **73.6**; „felhő tárhely” 19 impressions, „felhőtárhely” 5, „felhő alapú tárhely” 3. CC measured separately that the phrase „felhő tárhely” appeared **0 times** on the home, FAQ and backup pages — Google was showing the home page for those queries by accident. `/sajat-felho-tarhely` + `/en/own-cloud-storage` published **2026-10-14**; full baseline, price sources and the power provenance in `audits/seo-2026-10-14/BASELINE.md`. **What to measure, both times:** impressions and average position for „felhő tárhely” and „saját felhő tárhely”, plus the new page's own impressions, clicks and position. **A null result at +4 weeks means nothing on its own** — a new page on a site at position 73.6 takes weeks to months to move, and „felhő tárhely” alone is held by Microsoft, Google and the big list sites; the page aims at the two longer phrases. That is why there are two checks and not one, and why neither should be read as a verdict on the copy. **There is no Search Console connector in this project, so CC cannot read these numbers** — the operator reads them, CC records and compares. **Blocked until the operator asks for indexing** (Search Console → URL-ellenőrzés → the URL → „Indexelés kérése”): until that happens, or Google finds the page itself, both checks read zero for a reason that is not the page. **This is a slow channel and does not replace talking to people.** | **WATCHING** | operator: request indexing, then supply the Search Console read | 2026-11-11: first read (+4 weeks); 2026-12-09: second (+8 weeks), compared with the first | operator + CC | -## Process & tooling — 26 rows (P3 10, P4 16) +## Process & tooling — 27 rows (P3 10, P4 17) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| @@ -333,6 +338,7 @@ stopping line that lies. | **R-996** | Process & tooling | P4 | **`scripts/dooplex-offsite/test_dooplex_offsite.py` fails 28 of 30 tests when the push comes from a git WORKTREE, so the pre-push hook refuses a correct push.** MEASURED 2026-10-13 (sizing session): git runs the hook with `GIT_DIR` set; in a worktree that is an absolute path (`.git/worktrees/`), and the test's own scratch repos inherit it — its `git commit` fails. Standalone: 30/30 OK; with `GIT_DIR=`: 28 errors; main clone with `GIT_DIR=.git` (relative): OK. Workaround used: push from a full clone. | **READY** — filed 2026-10-13 | — | Drop `GIT_DIR`/`GIT_WORK_TREE`/`GIT_INDEX_FILE` from the env the test's git calls use; red-proof with the absolute GIT_DIR | CC | | **R-1025** | Process & tooling | P4 | **A power drill on demo-hp cuts Tester 1 too, and nothing warns the session using it.** 2026-10-14 17:25 CEST another session cut demo-hp's plug (`plugcut.py --plug hp`, the Immich drill) while this session ran downloads on Tester 1 (VM 341 runs on demo-hp); Tester 1 rebooted and came back by itself. The drill's fence checks Tester 1 for backups and package jobs only. | **OPEN** — filed 2026-10-14 | — | Add „a test runs on Tester 1” to the fence (a marker file the testing session writes), or name the rule in `runbooks/target-selection.md` | CC | | **R-1039** | Process & tooling | P4 | **qBittorrent stalls on the LAST piece of an archive.org torrent; Transmission does not.** Seen three times on 2026-10-14 (Tester 1 S2 and S3, demo-hp 9201 live read-back): the film reaches 99.994 %, the piece shared with archive.org's side files (`__ia_thumb.jpg`, `_meta.sqlite`, `_meta.xml`) never arrives, qBittorrent's log shows „500 Internal Server Error” from the archive.org web seed, while Transmission finishes the same torrent and curl range requests on the same files answer 206. A household that uses archive.org torrents with qBittorrent hits it too; our tests finish only with a local peer. | **OPEN** — filed 2026-10-14 | — | Note it in qBittorrent's onboarding record; for test films use Transmission, or a public-domain torrent with real peers | CC | +| **R-1078** | Process & tooling | P4 | **A controller comment still describes `mp1 /mnt/sys_drive` as a separate volume.** `C/cmd/controller/main.go:2546` („the SYSTEM-DATA volume (`mp1`, `/mnt/sys_drive`)…”) — `mp1` was removed by R-165; `sys_drive` is a folder of `mp0` (measured on all three boxes, `audits/storage-identity-2026-10-15/README.md`). The same stale cell in `07-backup-architecture.md` §6.1 was corrected in this session. Not fixed here: this run allowed no product-repo change. | READY | — | Correct the comment in the next controller change. | CC |