# Changelog — mgf-vm-forensics

All notable changes land here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.9] - 2026-07-14

### Changed
- **Released what was stranded on `main`.** `main` had moved past `v0.1.8` while still
  declaring `0.1.8`, so the *published* `0.1.8` was different code under the same version
  number. Two things consumers never received:
  - the **Apache-2.0 relicence** (landed on main 2026-07-12; every published wheel still
    carried `License: MIT`, with no `NOTICE` — a relicence is not real until it is released);
  - the **widened `mgf-common` pin** (`<1.0`, was `<0.50`). The stale published cap
    backtracked the whole federation's co-install to `mgf-common` 0.49.2.

  `REL-13` could not see this: it compares declared version to *registry* version, and both
  said `0.1.8`. The drift was main-vs-tag content. `mgf/tools/verify_release_currency.py`
  now catches the class — *a fix that isn't released isn't shipped.*

## [0.1.8] - 2026-06-26

### Changed
- Release the **mgf-common 0.49** pin (`<0.50`) onto devpi so the full
  fleet co-installs at the 0.49 cornerstone (devpi backfill; no API change).

## [0.1.7] - 2026-06-16

### Changed
- Widened the `mgf-common` pin to `<0.48` — mgf-common 0.47 is the pure-library release (the end-user CLI moved to `mgf-fed[cli]`); the importable API is unchanged.

## [Unreleased]

## [0.1.6] - 2026-06-09

### Security
- **SC-15**: `CaseStore.case_dir` now resolves + containment-checks the case path (`resolve()` + `is_relative_to`) beyond the prior string-level check — defence-in-depth against traversal.

### Added
- Full Woodpecker CI (ruff + import-linter + mypy + pytest matrix + vuln/secret scans + tag-driven Codeberg publish chain + verify-codeberg + sbom); SCOPE.md; PUBLIC_API.json regenerated to HEAD + REL-03 banner; [standards] extra; doc-bucket READMEs; PR-01 UI-forbid import-linter contract.


## [0.1.5] — 2026-06-06 — federation cohort: mgf-common 0.46 walk

Walk the `mgf-common` pin ceiling `<0.46 → <0.47` to accept the
library-API-neutral `mgf-common 0.46.0` (CLI-only release: new
`federation`/`design` commands + a `doctor --standards` gate; no library
surface change).

---

## [0.1.4] — 2026-06-05 — drain off the mgf-vm umbrella

### Internal
- Drained entirely off the retiring **`mgf-vm` umbrella** — depends on
  `mgf-vm-core` only. A pure import retarget (no API change):
  `mgf.vm.{exceptions, common.shell, common.atomic_io, security.isolation}` →
  `mgf.vm.core.*`. `mgf-vm` removed from dependencies + `[tool.uv.sources]` +
  lockfile. (pcap analysis still uses `dpkt`, forensics' own dependency.) This
  was the **last federation consumer of the umbrella** — `mgf-vm` now has zero
  importers and can be deleted.

## [0.1.3] — 2026-06-05 — mgf-common 0.45 cohort-walk

### Changed
- Walk the `mgf-common` pin `>=0.41,<0.45` → `>=0.41,<0.46` (adopt 0.45.x; no
  library-API break) and add the PKG-06 `[[tool.uv.index]] codeberg-mgf` +
  `mgf-common` source mapping from the 0.45 Codeberg cutover. Clears the REL-13
  federation-consistency RED. Lockstep with the `mgf-vm-*` cohort.

## [0.1.2] — 2026-06-05 — capture drained off VMProvider (D-G22)

### Changed
- The three `capture/` modules no longer take a `VMProvider`: `memory` /
  `screenshot` take injected acquisition callables (`dump_fn` / `screenshot_fn`);
  `filesystem` baseline/diff take `vm_name` + `is_running` + `disk_paths`
  directly. The consumer (the app) binds these to the SDK client status + the
  libvirt acquisition escape hatch. `mgf.vm.forensics` is now provider-free.

## [0.1.1] - 2026-06-04

### Changed
- **`mgf-common` ceiling at `>=0.41,<0.45`** (REL-10/11 cohort-walk). The
  previously-published 0.1.0 pinned `<0.44`, now unsatisfiable (mgf-common is at
  `0.44.5`, older minors pruned); this release publishes the widened window so
  the umbrella + app dependency graph resolves. Ships alongside the D-G19
  sibling wave and the accumulated federation-conformance work below.

### Federation conformance (2026-05-29)
- **`PUBLIC_API.md` + `PUBLIC_API.json` added** (DOC-08 / AP-10) — the
  library shipped no public-API contract docs. Generated by
  `tools/generate_public_api_json.py` (static AST extraction over
  `src/`, robust against the umbrella import-shadow) and pinned by
  `tests/unit/.../test_public_api_pin.py`.
- **`.importlinter` contracts added** (DP-01) — the previous
  `[tool.importlinter]` stub in `pyproject.toml` had no contracts AND
  named a non-top-level root (`mgf.vm.forensics`), which grimp rejects;
  it was vacuously green. Replaced with a root-`.importlinter`
  (root package `mgf`) carrying a `forensics-is-a-leaf` forbidden
  contract + a `forensics-layers` layered contract. Both KEPT.
- **`.gitleaks.toml` added** — secret-scan config was missing (SC-*).
- **`SECURITY.md` Scope rewritten** — the prior text claimed the library
  "does NOT open files / parse untrusted input" (copy-paste from a
  state-machine library). Corrected to describe the real surface: pcap
  parsing of attacker-controllable bytes, file/dir walking, list-argv
  subprocesses (tcpdump / qemu-nbd), tar.gz writing, and the unsigned
  integrity-manifest threat model.
- **README pins corrected** — was `mgf-common>=0.38,<0.39` +
  `mgf-vm-core>=0.1,<0.2`; now matches `pyproject.toml`
  (`mgf-common>=0.41,<0.43` + `mgf-vm>=0.2,<0.3`). File-tree, "no live
  capture" claim, `USERS.md`→`DEPS.md`, and dev-dir name also fixed.
- **`DEPS.md` §1 pin corrected** to `mgf-common>=0.41,<0.43`.
- **`MGF_STANDARDS_CONFORMANCE.md` fully re-audited** — replaced the
  stale skeleton ledger (pin `0.38`, "modules not landed") with a
  real per-rule audit of the landed surface.
- **EH-07:** `render.py` network branch narrowed from `except Exception`
  to `(OSError, ValueError, VManagerError)` + a warning log.
- **Known blocker (supervisor):** the `mgf-vm` umbrella ships
  `mgf/vm/__init__.py` as a regular package, collapsing the `mgf.vm`
  namespace so `import mgf.vm.forensics` resolves to the umbrella's
  copy — the gate exercises that copy, not this repo's `src/`. Fix is
  Phase 0 Stream A (umbrella drops forensics → `mgf-vm-core`).

### Added
- **Module port from original vm-vmanager-app (2026-05-24).** The full
  forensics surface from `mgf-vm/src/mgf/vm/forensics/` is now in
  this repo: case management, pcap capture + analysis, filesystem
  baseline + diff, memory + screenshot capture, network/IOC/timeline
  analyzers, Markdown report renderer. 20 source files, 16 test
  modules; **242 tests passing** against the `mgf-vm` umbrella as a
  transitional dependency.
- `types-PyYAML` in dev deps for mypy strict.
- mypy override: `dpkt` + `dpkt.*` + `yara` marked
  `ignore_missing_imports = true` (no py.typed markers upstream).
- Tests permit `S108` (adversarial `/tmp/*` paths in
  path-traversal-defense tests), `E501` (long assertion strings),
  `N802` (test names that mirror CLI flags like
  `test_rotation_passes_minus_C`).
- Initial repo skeleton (earlier, same day): `pyproject.toml` +
  four-gate scaffolding, MIT license, README, federation discipline
  files (`DEPS.md`, `STANDARDS_NOTE.md`,
  `docs/inprogress/MGF_STANDARDS_CONFORMANCE.md`), `docs/claude/CLAUDE.md`.

### Transitional
- **Depends on `mgf-vm` umbrella, not `mgf-vm-core`.** The extracted
  modules reference `mgf.vm.{domain,exceptions,common,providers,security}`
  which currently live in the old `mgf-vm` umbrella. When Phase 0
  Stream A migrates that surface into `mgf-vm-core`, this repo's
  dependency flips. Tracked in `vm-vmanager-docs/ROADMAP.md` Stream F.
- **`mgf-vm` umbrella still ships `mgf/vm/forensics/`** for now to
  avoid destabilizing `vm-vmanager-app`'s imports. Removal from the
  umbrella happens when `vm-vmanager-app` rewires its imports
  (Phase 0 Stream E or later).

### Status
All four gates green on Python 3.12:
- pytest: 242 passed, 1 skipped
- `mypy --strict`: 20 files clean
- ruff: All checks passed
- lint-imports: exit 0
