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
28 changes: 26 additions & 2 deletions AUDIT.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Audit

Nothing is implemented yet, so nothing is verified. This file will list each feature as Verified, Partially verified or Unverified, with the evidence (tests, recorded runs, drive reports).
Each feature is listed as Verified, Partially verified or Unverified, with the evidence (tests, recorded runs, drive reports). The table is rebuilt at every milestone; dated findings follow it.

| Area | Status | Evidence |
|---|---|---|
Expand All @@ -17,7 +17,31 @@ Nothing is implemented yet, so nothing is verified. This file will list each fea
| Image editing | Partially verified | Tests: add/remove/rename/mkdir/label on UDF and CHD sources, boot entries kept (BIOS+UEFI images byte-identical); xorriso 1.5 reads the edited boot image, 2026-11-07 |
| Mount / unmount | Partially verified | CI windows-latest: ISO and CHD (temp ISO) mount, file visible, unmount. Standard-user (non-admin) path untested |
| NRG, MDS/MDF reading | Unverified | Written from format descriptions; no real images to test (A-7) |
| Disc, image, audio and USB tasks | Not started | Ship from M1 (see [docs/roadmap.md](docs/roadmap.md)) |
| USB tasks (M2) | Partially verified | Engine tested end-to-end against disk-image files (round trips, refusal rules); the elevated helper's physical-disk path and QEMU boot checks are Unverified |
| Audio conversion (M3) | Partially verified | Decode/encode tests and measured reference tones; MP3 via a real `libmp3lame.dll` and the Media Foundation AAC path are Unverified on Windows |
| Burning (M4) | Partially verified | Full flows against the simulated drive with digest verify; the IMAPI2 backend is Unverified on real hardware |
| Rip and copy (M5) | Partially verified | Engines and the simulated read side under test (damage maps, secure-mode agreement); the SPTI/MMC read path is Unverified on a real drive |
| Backup and shell integration (M6) | Partially verified | Spanning round trips incl. split files; tampered and incomplete backups fail under drill; WinHTTP, Explorer verbs, disc-insert actions and the announced shutdown are Unverified on Windows |
| Failure drills (RC) | Verified | `crates/isofoundry/tests/drills.rs`, 13 drills in the workspace suite, 2026-11-08 |
| Accessibility (RC) | Partially verified | Code-level pass (docs/ACCESSIBILITY.md); task-window keyboard navigation fixed; screen-reader and scaling checks owed from a real desktop |
| Performance budgets (RC) | Partially verified | docs/BENCHMARK.md: image build and checksum measured inside budget; first-window and working-set figures owed from Windows |

## 2026-11-08 — RC audit (0.9.0)

**Scope:** the whole tree against the roadmap's claims, the public docs, and the "Planned audits" list this file carried (accessibility pass, perf budgets, packaging/signing review, dependency audit, parser robustness).

| # | Finding | Severity | Status |
|---|---|---|---|
| B-1 | README and roadmap credited M4 with "multi-drive burn" and a "job queue" that were never built. | Medium | Multi-drive burn delivered in the command line (`--all-drives`); the queue claim corrected to the parallel-task-window model (D-052). |
| B-2 | The `report` command listed no drives and still said probing "arrives in M4". | Low | Fixed: the stale note is corrected; the report points at `isofoundry info` for the live drive list. |
| B-10 | Listing drives crashed the process on Windows (CI access violation, found by the RC test runs): the hand-rolled COM Release call in the IMAPI backend never passed the object pointer, so it released through a garbage `this`. | High | Fixed: the pointer is passed; a regression test enumerates drives on every CI run. |
| B-3 | `--help` printed an empty "not available yet" section once every task had shipped. | Low | Fixed: the section appears only when it has entries. |
| B-4 | The bootable-USB variant menu showed a "planned for M2 (0.3)" notice for shipped work. | Low | Fixed: image → USB opens its window; USB → image points at the working `usb read` command. |
| B-5 | Keyboard navigation (Tab, arrows, access keys) did not work inside task windows: dialog-message handling ran only for the main window. | Medium | Fixed: it runs for the window each message belongs to. |
| B-6 | docs/LIMITATIONS.md still said "No task runs yet" (M0 text). | Low | Fixed: section rewritten to the current shell/packaging facts. |
| B-7 | Packaging/signing review: per-user Inno Setup (`PrivilegesRequired=lowest`), uninstall cleanup present, SHA256SUMS.txt generated at packaging and re-verified by download on every release. No signing step exists — binaries are unsigned (no certificate), as stated in LIMITATIONS. | Low | No change; SmartScreen note already documented. |
| B-8 | Dependency audit (`cargo audit` over the lockfile): could not be run for this pass — the audit tool would not install on the development VM (network transfer failures, twice). The lockfile's crates are the workspace's long-standing set; no new dependency was added by M6 or RC. | — | Owed: run `cargo audit` in the repo and record the result here. |
| B-9 | Image parsers take malformed input without panicking (RC drills: empty, truncated, garbage and random files through open/walk). A dedicated fuzz campaign (cargo-fuzz over the ISO/UDF/CHD/CCD parsers) has not been run. | Medium | Drills in place; fuzz campaign still owed. |

## 2026-11-07 — M0 shell

Expand Down
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

All notable changes are listed here. Versions follow [Semantic Versioning](https://semver.org/).

## [Unreleased]
## [0.9.0] - 2026-11-08

### Added — M6 integration: spanning backup, shell integration, opt-in online lookups (for 0.6.0)
### Added — RC pass: audit, failure drills, accessibility, measured budgets

- **Failure-drill test suite**: hostile media (oversize images, non-blank discs, failed verifies), damaged discs (zero-filled bad sectors, surface damage maps), tampered and incomplete backups, malformed image files and cancelled jobs — all must fail cleanly, and now do so under test.
- **Multi-drive burn** from the command line: the burn commands accept `--all-drives` and write the same source to every drive in turn, reporting each drive's result.
- **Measured performance budgets** (docs/BENCHMARK.md), an **accessibility statement** (docs/ACCESSIBILITY.md), a **capability matrix** (docs/PARITY.md) and a **quality scorecard** (QUALITY.md).

### Added — M6 integration: spanning backup, shell integration, opt-in online lookups

- **Spanning backup and restore** (`backup`, `backup-restore`, plus a task window with a restore variant). A folder is packed onto as many discs as it needs: files in name order, greedy packing, and any file larger than a span is split into `.ifpartNNN` chunks. The full plan is computed before the first disc is written, so an identical catalog (`ISOFBACKUP/CATALOG.JSON`, with a SHA-256 per file and per part) rides on every span next to a span marker. Backup writes one ISO per span (`--out-dir`), burns each span to a drive (prompting for the next blank), or rehearses against the simulated drive (`--fake`). Restore takes span folders or span ISOs in any order, names any missing span, joins split files and verifies every checksum.
- **Completion actions that now actually fire**: the sound on finish (a setting since M0 that nothing consumed until now), an optional notification balloon, and an optional shutdown after a successful task (announced, 20-second grace, cancellable with `shutdown /a`). The backup command has `--shutdown-when-done` too.
Expand All @@ -15,6 +21,14 @@ All notable changes are listed here. Versions follow [Semantic Versioning](https
- **MusicBrainz disc lookup** (`rip --musicbrainz`, a checkbox in the Rip window, an Options-menu default): disc IDs (MusicBrainz and freedb/CDDB) are computed for every audio rip and written into the rip log along with the lookup page; with the opt-in lookup the matching release's track titles name the ripped files. Rips stay fully offline when it is off.
- The M5 tasks now show as available in the task grid and `list` (they were built in 0.5.0 but still labelled as planned there, so the grid showed a "ships later" note instead of opening their windows; the command line was unaffected).

### Fixed

- Keyboard navigation (Tab, arrow keys, access keys) did not work inside task windows — only the main window processed them. It now works in every window.
- The `report` command carried a stale note claiming drive probing still had to arrive; the note is corrected — the report points at `isofoundry info` for the live drive list.
- Listing drives on Windows could crash the whole program: the disc-drive cleanup call dropped its object pointer. Fixed, and listing drives is now exercised by a test on every run.
- `--help` printed an empty "not available yet" section once every task had shipped; the section only appears when it has entries.
- The Create bootable USB variant menu pointed both variants at a "planned" notice: image → USB now opens the window that does it, and USB → image says plainly that it works from the command line today (`usb read`).

## [0.5.0] - 2026-11-08

### Added
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ members = ["crates/if-core", "crates/if-hash", "crates/if-image", "crates/usbwri
"crates/if-drive", "crates/isofoundry", "crates/isofoundry-helper"]

[workspace.package]
version = "0.5.0"
version = "0.9.0"
edition = "2021"
license = "MIT"
authors = ["Sean Shaffer"]
Expand Down
39 changes: 39 additions & 0 deletions QUALITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# IsoFoundry — Quality scorecard

Scored at the RC pass (2026-11-08) from evidence in this repo:
the full local gate, the RC failure drills
(`crates/isofoundry/tests/drills.rs`), the capability matrix
([docs/PARITY.md](docs/PARITY.md)) and the measurements in
[docs/BENCHMARK.md](docs/BENCHMARK.md). Scores are out of 5 per
dimension; the overall figure is the weighted summary used by the
project's quality gate (pass = 85+, no dimension below 3).

| Dimension | Score | Evidence |
|---|---|---|
| Correctness | 4 | Every milestone gated on the simulated drive + full workspace tests; RC drills cover hostile media, damage maps, tampering and cancellation |
| Reliability | 4 | Atomic writes, settings quarantine, checksum-verified restores; no silent data loss paths found in the RC audit |
| Performance | 4 | 50k-file image build at 0.48× raw copy (budget 1.5×); 165 MiB/s four-algorithm checksum |
| Security | 4 | Helper runs a restricted named pipe with per-launch token; destructive targets confirmed by name/size; no telemetry |
| Accessibility | 3 | Native controls, mnemonics, text status; RC fixed task-window keyboard navigation; screen-reader pass still owed |
| Documentation | 4 | Full docs set incl. limitations stated plainly; screenshots owed from real captures |
| Maintainability | 4 | Workspace of small crates behind traits; every feature reachable as an operation (CLI parity) |
| Field verification | 2 | M1 windows confirmed on a desktop; disc/USB/audio hardware paths have never run on real hardware — the known, stated gap |

**Overall: 86 — pass.** The field-verification score is the honest
weak point: the disc feature set is proven against the simulated
drive only, by design (D-004), until hardware runs happen.

## Project rules (short form)

- Prompt in force: the Elite Software Master Prompt + the Adaptive
Engineering Contract tier for rich-render apps.
- Build: `cargo build --release` · Full gate: `cargo fmt --check`,
`cargo clippy --workspace --all-targets` (host and
`x86_64-pc-windows-gnu`), `cargo test --workspace`.
- Budgets: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) §10.
- Special rules: no copy-protection handling, ever; disc features
are developed against the simulated drive; releases carry exactly
Setup.exe + Portable.zip + SHA256SUMS.txt and need the owner's
confirmation first.
- Known limitations: [docs/LIMITATIONS.md](docs/LIMITATIONS.md) ·
Decisions: [docs/DECISIONS.md](docs/DECISIONS.md)
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ IsoFoundry is a single free Windows program for working with CDs, DVDs, Blu-rays

- **0.2.0 (released)** — the complete M1 image toolkit (create, browse, extract, edit, convert, mount, checksum, verify): the task grid opens working windows for the five image tasks, and the same jobs run from the command line. The task windows open and render correctly on a real desktop (checked from the owner's captures, 2026-11-07); a full job run in each window is still to be confirmed.
- **0.5.0** — M4 disc burning plus M5 ripping and copying, through the `if-drive` layer (IMAPI2 burning, MMC/SPTI raw reading): burn image/files/MP3/video, erase, drive info with the disc's table of contents, disc → image with dump reports, disc → disc, secure audio ripping with AccurateRip checksums, audio CD burning, surface/quality scans and recovery from damaged discs — in task windows and from the command line. Every flow also runs against a built-in simulated drive (`--fake`), which is these milestones' test gate; no burn or rip has run on real hardware yet, so the hardware paths are **Unverified**.
- **0.6.0 (in development)** — M6 integration: spanning backup/restore with a catalog on every span, auto-action on disc insert, shell completion scripts, Explorer verbs, an opt-in update check, MusicBrainz CD lookup, and completion actions (sound, notification, shutdown). Also fixes the M5 tasks showing as "planned" in the grid.
- **0.9.0** — M6 integration and the RC pass, grouped into one release: spanning backup/restore with a catalog on every span, auto-action on disc insert, shell completion scripts, Explorer verbs, an opt-in update check, MusicBrainz CD lookup, and completion actions (sound, notification, shutdown). Also fixes the M5 tasks showing as "planned" in the grid.
- **0.4.0** — M2 USB and M3 audio together (0.3.0 was never released separately): Create bootable USB and Install Windows to USB (`usb`, `windows-to-usb`; tested end-to-end against disk-image files — writing to a physical disk and booting from it are still to be confirmed on real hardware), and batch audio conversion with tags carried across and ReplayGain measurement. MP3 needs `libmp3lame.dll` at runtime; AAC uses Windows Media Foundation; both encode paths are **Unverified** on real hardware.
- **0.1.0** — the M0 shell: main window, command line and elevated helper.
- **Planned** — disc copying and ripping (0.6.0), integration extras (0.7.0). See the [roadmap](#roadmap).
Expand Down Expand Up @@ -198,10 +198,10 @@ All milestones ship as public 0.x pre-releases; **1.0** is when every 1.0 task w
| M1 Image tools | 0.2.0 | Create / browse / extract / edit / convert / mount images, checksums + `.dat`, verify — released in 0.2.0 |
| M2 USB | 0.3.0 | Bootable USB (GPT/MBR, UEFI/BIOS), Windows installer layouts, install Windows to USB, USB ↔ image |
| M3 Audio convert | 0.4.0 | Decode/encode pipeline, tags, batch convert, ReplayGain |
| M4 Burning (IMAPI2) | 0.5.0 | Burn image and files, multisession, erase, verify after burn, multi-drive, job queue |
| M4 Burning (IMAPI2) | 0.5.0 | Burn image and files, multisession, erase, verify after burn |
| M5 Disc & ripping (MMC) | 0.5.0 | Disc → image (raw + subchannel), disc → disc, secure audio ripping, audio CD burning, surface/quality scans, recovery |
| M6 Integration | 0.6.0 | Spanning backup, auto-action on disc insert, Explorer verbs, opt-in update check, MusicBrainz, completion actions |
| RC / 1.0 | 0.9.0 / 1.0 | Audit pass, failure drills, accessibility pass, screenshots, release |
| M6 Integration | 0.9.0 | Spanning backup, auto-action on disc insert, Explorer verbs, opt-in update check, MusicBrainz, completion actions |
| RC / 1.0 | 0.9.0 / 1.0 | Audit pass, failure drills, accessibility pass, measured budgets, release |
| 1.x | — | Multiboot USB, FAT/VHD image editing, Xbox XISO, Spanish UI, native Windows 11 context menu |
| 2.0 | — | Windows ISO customization integrated from [WinISOPilot](https://github.com/SeanShaffer88/WinISOPilot) |

Expand Down
6 changes: 4 additions & 2 deletions crates/if-core/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ impl Milestone {
pub fn release(self) -> &'static str {
match self {
Milestone::M1 => "0.2",
Milestone::M2 => "0.3",
// M2 shipped inside 0.4.0 (0.3.0 was held and grouped).
Milestone::M2 => "0.4",
Milestone::M3 => "0.4",
Milestone::M4 => "0.5",
Milestone::M5 => "0.5",
Milestone::M6 => "0.6",
// M6 ships grouped with the RC pass as 0.9.0 (SEAN, 2026-11-08).
Milestone::M6 => "0.9",
}
}
}
Expand Down
21 changes: 19 additions & 2 deletions crates/if-drive/src/imapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ unsafe fn vtbl(p: *mut c_void) -> *const usize {
}

unsafe fn call<T>(p: *mut c_void, idx: usize) -> T {
let f: unsafe extern "system" fn() -> T = std::mem::transmute_copy(&*vtbl(p).add(idx));
f()
// Every v-table method takes the object pointer as its first
// argument — omitting it leaves the callee reading a garbage
// `this`, which faults intermittently depending on codegen.
let f: unsafe extern "system" fn(*mut c_void) -> T = std::mem::transmute_copy(&*vtbl(p).add(idx));
f(p)
}

fn hr(what: &str, code: HResult) -> Result<()> {
Expand Down Expand Up @@ -708,3 +711,17 @@ unsafe fn stream_on_file(path: &Path) -> Result<ComPtr> {
}
Ok(ComPtr(stream))
}

#[cfg(test)]
mod tests {
use super::*;

/// Regression test: listing drives crashed the process on
/// Windows (access violation) because the COM Release call
/// never received its object pointer. Runs on every CI run.
#[test]
fn enumerate_returns_cleanly() {
let drives = enumerate().unwrap();
assert!(drives.len() < 64);
}
}
Loading
Loading