Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
# CI invokes these same targets rather than re-implementing them in YAML, which is
# what prevents a gate silently degrading into a warning. There is no warning tier.

.PHONY: check check-provider-alignment check-native-catalog check-licensing check-public-claims check-deb-ordering check-reproducible check-sbom check-tests check-python-floor check-packaging check-storage-vocabulary check-native-catalog check-licensing check-public-claims check-privacy check-docs-truth check-current-state check-headers check-docs check-scope check-shell check-refs check-paths check-index check-freeze check-vectors check-vectors-negative check-vectors-crossversion check-gate-coverage check-falsifiable help
.PHONY: check check-provider-alignment check-native-catalog check-licensing check-public-claims check-deb-ordering check-reproducible check-sbom check-tests check-python-floor check-packaging check-storage-vocabulary check-native-catalog check-licensing check-public-claims check-privacy check-docs-truth check-current-state check-sample-report check-headers check-docs check-scope check-shell check-refs check-paths check-index check-freeze check-vectors check-vectors-negative check-vectors-crossversion check-gate-coverage check-falsifiable help

check: check-scope check-headers check-python-floor check-packaging check-storage-vocabulary check-native-catalog check-licensing check-public-claims check-privacy check-docs-truth check-current-state check-shell check-refs check-paths check-index check-freeze check-vectors check-vectors-negative check-vectors-crossversion check-tests check-docs
check: check-scope check-headers check-python-floor check-packaging check-storage-vocabulary check-native-catalog check-licensing check-public-claims check-privacy check-docs-truth check-current-state check-sample-report check-shell check-refs check-paths check-index check-freeze check-vectors check-vectors-negative check-vectors-crossversion check-tests check-docs
@echo "make check: all gates passed"

## check-scope D-96: no product implementation before architecture freeze
Expand Down Expand Up @@ -85,6 +85,10 @@ check-python-floor:
check-packaging:
@python3 scripts/ci/check_packaging.py

## check-sample-report IQ-011: the published sample regenerates from committed evidence
check-sample-report:
@python3 scripts/docs/sample_report.py check

## check-storage-vocabulary D-114: a retired inference does not return as vocabulary
check-storage-vocabulary:
@python3 scripts/ci/check_storage_vocabulary.py --self-test
Expand Down
4 changes: 2 additions & 2 deletions docs/CURRENT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ Not asserted. Each number is counted at generation time.

| | |
|---|---|
| Gates | 19 |
| Falsification injections | 111 |
| Gates | 20 |
| Falsification injections | 113 |
| Golden vector cases | 15 |
| Frozen artifacts | 7 |
| Test files | 3 |
Expand Down
2 changes: 1 addition & 1 deletion docs/IMPLEMENTATION_QUESTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ Assumptions only — **never authority**. The owner resolves; resolutions become
| IQ-008 | CONFLICT | STORE-001 | `/run/isedraf/` | Implemented the lock at `/var/lib/isedraf/.lock` | The sketch placed the lock at `/run/isedraf/isedraf.lock`. `STORE-001` puts `.lock` inside the state root, which also makes the lock and the store it protects share a filesystem — a lock on a different filesystem cannot guarantee exclusion if the store is mounted elsewhere. `/run/isedraf/` remains available for future ephemeral state. | `STORE-001` | OPEN |
| IQ-009 | GAP | SCOPE-077, SNAP-015 | `lib/isedraf/cli.py`, `lib/isedraf/verify.py` | Verification runs in-process at the end of `identity`; a failure exits `64` (engine error) | `SNAP-015` assigns `exit 5` to `integrity_failure`, and `SCOPE-077` states `5` is not reachable in W1-A. A standalone `isedraf verify` therefore has **no frozen exit code for "verification failed"**. No exit code was invented: verification stays in-process, and the standalone command is deferred until the W1-A exit set is extended or `verify` is scoped to a later set. | discovered implementing W1-B | OPEN |
| IQ-010 | CONFLICT | SCOPE-070, SCOPE-071, SCOPE-072, STORE-001, PRIV-005 | `lib/isedraf/stateroot.py` | `resolve()` refuses to fall back to a production root this slice cannot reach, and names the requirements | **Not a contradiction between frozen rules — an implementation defect.** `SCOPE-070` already states W1 *"runs under `ISEDRAF_STATE_ROOT`"*, and `PRIV-005`'s Mode A — `sudo isedraf`, root supervisor inside a sandbox, state-root writability preflight — is the only execution topology that ever owns `/var/lib/isedraf`. Mode A is `DEFERRED_TO_FREEZE_SET_2` by `SCOPE-072`, so **W1 has no production mode by design**. The implementation was offering one and failing with a bare permission error. Answers for Freeze Set 2, when Mode A lands: the **root supervisor** creates and owns the root at mode `0700`; packaging creates it at install time; no group-readable relaxation, since `STORE-001` freezes `0700`; `sudo -u` is not a path, because `SCOPE-071` refuses anything reached through sudo and `PRIV-004` refuses when `SUDO_USER` is set | `env -u ISEDRAF_STATE_ROOT isedraf identity` now explains rather than failing on `EACCES` | **CLOSED_IMPLEMENTATION_FIX** |
| IQ-011 | GAP | D-114, STORAGE-SEMANTICS-001 | `docs/reference/samples/` (withdrawn), `docs/reference/CONTROL_EVIDENCE_MAP.md` | The rendered sample report was **withdrawn** rather than edited. It was real output from disposable lab VM `isd-a9` (AlmaLinux 9.7, KVM) and reported a storage device `type` of `ROTATIONAL` / `OPTICAL` — the exact inference D-114 retired, published as an example of what the tool claims. | It could not be regenerated: `isd-a9` no longer exists, the surviving lab corpus belongs to another project and is read-only, and `kernel_subsystem`, `queue_rotational`, `kernel_removable` and `scsi_peripheral_type` were never collected from that host, so re-rendering the old collection cannot produce them. Writing plausible values would be inventing evidence for a machine nobody can re-observe, which is the one failure this project exists to prevent. **Proposal:** regenerate after the RC on a disposable VM created for the purpose, and add a documentation generator so the sample is reproducible from committed bytes rather than from a VM that only one person ever had. A `check_storage_vocabulary` gate now rejects the retired vocabulary if it returns. | `git log 6ca913e`; storage semantics proofs, this milestone | OPEN |
| IQ-011 | GAP | D-114, STORAGE-SEMANTICS-001 | `docs/reference/samples/` (withdrawn), `docs/reference/CONTROL_EVIDENCE_MAP.md` | The rendered sample report was **withdrawn** rather than edited. It was real output from disposable lab VM `isd-a9` (AlmaLinux 9.7, KVM) and reported a storage device `type` of `ROTATIONAL` / `OPTICAL` — the exact inference D-114 retired, published as an example of what the tool claims. | It could not be regenerated: `isd-a9` no longer exists, the surviving lab corpus belongs to another project and is read-only, and `kernel_subsystem`, `queue_rotational`, `kernel_removable` and `scsi_peripheral_type` were never collected from that host, so re-rendering the old collection cannot produce them. Writing plausible values would be inventing evidence for a machine nobody can re-observe, which is the one failure this project exists to prevent. **Proposal:** regenerate after the RC on a disposable VM created for the purpose, and add a documentation generator so the sample is reproducible from committed bytes rather than from a VM that only one person ever had. A `check_storage_vocabulary` gate now rejects the retired vocabulary if it returns. | `git log 6ca913e`; storage semantics proofs, this milestone | **CLOSED_IMPLEMENTED** — a disposable Debian 12 VM was built for the purpose, the released 0.1.0-alpha1 package was installed on it, and an unprivileged collection produced the sample. The evidence is committed under `docs/reference/samples/evidence/` and the sample is generated from it by `scripts/docs/sample_report.py`, gated by `make check-sample-report` and two falsification injections. No value was supplied by hand. **Lab disclosure review, owner decision 2026-09-20:** the sample is kept exactly as captured. The QEMU machine description (`Ubuntu 24.04 PC (Q35 + ICH9, 2009)`), the CPU model string (`Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz`) and the libvirt default network `192.168.122.0/24` are ACCEPTED: disposable lab observations, containing no credentials, customer data, unique private addressing, restricted content or secret infrastructure information. No re-capture. Re-collecting behind `--cpu qemu64` and a synthetic machine type purely to make the output less specific would make the sample a cosmetically sanitized synthetic host, which is not what it is for: it demonstrates what ISEDRAF actually observes. The virtio result is the clearest evidence of that - `kernel_subsystem=virtio` with `queue_rotational=true` over SSD-backed storage is a real-world demonstration of why D-114 was necessary, because the queue flag is evidence and "HDD" would have been interpretation beyond it. |
23 changes: 16 additions & 7 deletions docs/reference/CONTROL_EVIDENCE_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,22 @@ Report
| Collection completeness | both | per-subdomain status |
| Limitations | both | what the evidence does not support |

A rendered sample of the real output is **not published with this preview**. The previous sample was
generated on a disposable lab VM that no longer exists, and it describes the retired storage schema:
it reports a device `type` of `ROTATIONAL` or `OPTICAL`, which is exactly the inference the storage
observation model now refuses to make. It could not be migrated, because the fields that replaced
that one - `kernel_subsystem`, `queue_rotational`, `kernel_removable`, `scsi_peripheral_type` - were
never collected from that host, and writing plausible values for them would be inventing evidence.
A sample returns when it can be produced by running the tool, not by editing a document.
A rendered sample of the real output is in [`samples/SAMPLE_REPORT.md`](samples/SAMPLE_REPORT.md),
with the same report as JSON beside it. It is real `isedraf report` output, collected by an
unprivileged user on a disposable Debian 12 VM using the released `0.1.0-alpha1` package.

It is **generated from committed evidence**, not pasted in. The collection it came from is in
[`samples/evidence/`](samples/evidence/) — the inventory as collected, and the snapshot, manifest
and ledger as written — and `python3 scripts/docs/sample_report.py generate` rebuilds both
documents from those bytes. Regenerating re-verifies the ledger chain as it goes, so the sample
demonstrates the verification rather than asserting it. `make check` fails if the published
sample and its evidence disagree.

The previous sample was withdrawn because it described a retired storage schema and its source
machine no longer existed, so it could not be regenerated. That cannot happen again: the sample
no longer depends on anyone still having the host. What committed bytes cannot reproduce is the
collection itself — reading `/sys` and `/proc` needs the machine — so the evidence is captured
once and the report is reproducible from it.

## Domains not yet mapped

Expand Down
Loading
Loading