# October 3 installer remediation handoff

Implementation owner: installer agent. Parent owns commit/push, Atlas, maintained documentation, broad validation and native coordination. No commits/pushes or Atlas changes by this agent. Root-owned F02 shortcut edits in linux.go/windows_shortcuts.go and new manager_shortcut files were preserved.

## Finding disposition and implementation

| Finding | Implementation | Regression evidence |
|---|---|---|
| F01 journal trust | Installer schema 2 signs complete structured intent with HMAC-SHA256 using a separate per-user 32-byte private key. Authoritative journals live ONLY under protected config/.mpv-manager-installer-recovery, named by SHA256 backup identity; application-parent sibling journals never grant recovery authority, even with a valid MAC. Recovery checks protected directory+parent, private journal ownership/permissions, HMAC, requested destination identity, filename binding, structural bounds and protected backup ownership before destructive actions. Key creation is preparation-only; recovery refuses a missing key and does not recreate it. Journals are atomically published from protected files before bytes are written, including Windows DACLs. | transaction_auth_test.go: forged same-target signature, forged sibling destination, signed tampering, legacy applying/committed journals, repeated rejection, missing key, legitimate recovery in shared0775 parent, writable backup/private inventory; captured authenticated applying record+backup replay after commit is rejected in public parent; exact private-inventory destination scoping. Windows inherited EveryoneRX regression. Existing repeated recovery and missing-backup tests continue passing. |
| F03 private FFmpeg staging | Download and extracted payload use operation-owned sibling MkdirTemp directories; existing ffmpeg.7z and ffmpeg_temp are never scratch candidates. Only the reserved stage is removed. | ffmpeg_staging_test.go: successful replacement, bad hash, download failure, cancellation preserve unrelated names; concurrent canceled downloads have two distinct0700 stages and remove only those stages. |
| F04 bounded/contextual Flathub | Read-only discovery uses process.Output with caller deadline and five-second upper bound. Owned process trees are reaped and stdout/stderr retention bounded. Exact remote names are read using --columns=name. Existing-tool discovery occurs before commit guard; post-prerequisite-install discovery is independently bounded and errors reconcile as partial setup. | flathub_cancellation_linux_test.go: stalled child returns deadline before commit within2s; noisy output returns ErrOutputLimit and no enabled result. Existing Linux executor/install/update tests pass. |
| F08 restore/rollback/default metadata | RestoreBackup and rollback publish with AtomicWritePreserve, retaining existing target mode/Unix owner/Windows owner+DACL. Missing restore/rollback targets inherit the validated snapshot mode, avoiding widening a private backup. Fresh recommended config still uses0644. Hardware-default compatibility editor also uses AtomicWritePreserve and shared mpvconf renderer, preserving comments/profiles. | config_permissions_test.go: private0600 restored and rolled back; private snapshot restoring missing target remains0600; recommended hardware default preserves mode, comments and profile override. Root owns native Windows fileops ACL tests. |
| F12 Windows ARM64 FFmpeg | Windows mpv and FFmpeg share the architecture selector. ARM64 always selects Aarch64 manifest asset, irrespective of x86 CPU flags; matching ARM64 PE machine is required. Unsupported architectures fail explicitly. | ffmpeg_staging_test.go exercises all three manifest architecture paths with synthetic archived AMD64/ARM64 PE payloads, rejects opposite machine and unsupported386; no executable fixture is run. |
| F17 canceled/late-budget tar inspection | Caller context checked before inspection, before each header and beneath/above gzip/xz decompression; expanded-size budget applied immediately when each header is read, before Next can skip its payload. Artifact BLAKE3 reads also use operation context; public background wrapper retained. Full two-pass preflight remains intentionally intact. | archive_cancellation_test.go: oversized header with no body fails budget rather than EOF; body-skip cancellation is observed; already-canceled malformed compressed extraction/hash preserves live sentinel and creates no stages. |
| Additional IINA mount cleanup candidate | Mount cleanup registered before attach side effects; discovers owned mounts even on failed/canceled/malformed attach. Uses bounded owned processes and an independent cleanup lifetime. Detaches only mounts inside this operation root, once per device. Cleanup failure is returned and staging retained rather than removed through a mounted filesystem; committed install plus cleanup failure is PartialInstallError. Empty hdiutil info is valid. | dmg_mount_cleanup_test.go exercises post-mount failure/cancellation, unrelated mount exclusion, duplicate device and cleanup failure. Gated Darwin native test creates/attaches disposable empty DMG then emulates failed output after attach and proves owned mounts disappear. |

F01 compatibility/security policy: **All public application-parent journals, including unsigned schema1 and signed schema2/terminal committed records, are retained for manual recovery; none grants authority for automatic rollback or cleanup.** This is an intentional migration boundary. New journals require the same original authentication key during recovery. Trusted administrative/root principals remain privileged; private keys do not defend against malware already running as the same user. A shared application parent such as native macOS /Applications root:admin0775 is permitted. HMAC alone would allow opaque record+backup capture/replay through that writable parent; authoritative intent therefore resides in a protected private config inventory and is retired durably on commit. Signed public replay never recreates private authority. The application parent is only a coordination/backup location, while journal directory and its config parent must resist replacement. Updater's stricter ancestor trust policy is unchanged.

Trust extraction: internal/recoverytrust contains the shared Unix owner/mode and Windows owner/DACL validation. Existing version trust functions are thin adapters preserving updater behavior/error context. Root moved protected file creation into internal/fileops to support Windows metadata-preserving writes without an import cycle; recoverytrust delegates. WritePrivateFile reserves a private temp before any signed journal bytes are written, syncs it, then renames durably.

Authentication-key preservation: Windows managed overlay explicitly preserves portable_config and manager paths; uninstall consumes only ownership-manifest payload regular files and leaves portable_config intact. UI journals use exact managedUIPaths/transientUIPaths inventories and do not claim either installer or updater authentication key, private recovery inventory, manager config, or unknown scripts. Installer does not reuse/delete the updater key. Generic arbitrary-target low-level replacement remains caller-controlled and is not a reason to claim native lifecycle verification.

## Consolidation and dead-code candidate disposition

These are the installer entries from docs/qa/2026-10-03/audit/deadcode-common.json. Deadcode runs omit test roots; absence from a shipped call graph alone does not make public test/integration APIs safe deletions.

| Symbol | Disposition |
|---|---|
| InstallationHandler.CreateInstallerShortcutWithOutput | Retained supported public platform shortcut adapter, exercised by Linux handler/native shortcut tests. It dispatches to the platform interface rather than carrying a second implementation. |
| InstallationHandler.ExecuteUpdate | Retained documented public convenience adapter to ExecuteInstall with isUpdate=true. Handler tests verify update selection. No second update algorithm. |
| ApplyUserSettings | Retained public compatibility editor; delegates to the same applyUserSettingsContent/mpvconf renderer as shipped staged install and preserves metadata. |
| SetRecommendedHWADecoderIfEmpty | Retained public compatibility editor; uses the same applyRecommendedHWADecoderContent renderer as shipped staged install. Consolidated manual profile-insensitive parser into mpvconf.Parse/Set and corrected metadata publication. |
| SyncInstalledApps | Retained public positive-observation compatibility adapter to canonical typed reconciliation. Existing adoption/discovery persistence tests use it; no destructive absence inference. |
| isPackageManagerMethod | Removed unused substring-policy helper and its implementation-mirroring test. Canonical constants.IsPackageManaged now owns that application policy (root). |
| WithDownloader | Retained explicit injected dependency seam used in meaningful canceled/error download tests; option documented as context-download dependency. |
| WithExecutor | Retained platform-command injection seam used to test package mutation command selection and failure outcomes without native destructive operations. Comment corrected: native archive extraction never executes external tools. |
| WithFileSystem | Retained filesystem failure-injection seam for rollback/preservation/error-path tests. Production defaults remain OSFileSystem. |
| WithHTTPClient | Retained HTTP fixture seam for hash/size/cancellation/error/staging preservation tests; all direct progress artifact downloads share HTTPDownloader. |
| detectMPVInstallsInDirs | Removed redundant test-only core wrapper; directory/PATH/no-execution tests now call the canonical detectWindowsMPVInstallsCore with nil registry provider. |

Additional cleanup: both duplicated direct-download implementations/progressWriter were removed in favor of bounded HTTPDownloader. The separate Downloader seam still serves context-aware injected callers. Four installer Linux installed-version parsers and Flatpak parser were removed; discovery now shares internal/packagequery's canonical bounded locale-stable installed-version logic. InstalledLinux is the substantive selected-family query API used by autodiscovery when os-release needs a tool fallback. Pacman discovery now retains the package epoch consistently with version checking; alternative names are attempted only after definitive absence. Installer backup pruning now shares fileops.PruneBackups with hotkeys/scriptopts. Duplicated legacy Linux nonstreaming package install/uninstall/interactive paths and their implementation-only tests were removed; shipped WithOutput paths/tests remain. Unused macOS nonstreaming uninstall variants were also removed; supported WithOutput lifecycle remains.

## Repository validation performed

- Full `go test ./pkg/installer ./pkg/version ./internal/recoverytrust ./internal/packagequery -count=1` passed (version ~15s).
- `go test -race ./pkg/installer ./internal/packagequery ./internal/recoverytrust -count=1` passed. New concurrency scratch test subsequently included in another passing installer/query race run.
- Native gate binaries cross-compiled successfully with CGO_ENABLED=0: Darwin arm64 `/tmp/installer-darwin-remediation`; Windows amd64 `/tmp/installer-windows-remediation.exe`. This is compile evidence only, not native behavior acceptance.
- `go vet ./pkg/installer ./internal/recoverytrust ./internal/packagequery ./pkg/version` passed.
- `git diff --check` passed. All edited Go files formatted.

## Native gates for parent

Darwin arm64 disposable QA: `MPV_MANAGER_NATIVE_DMG_QA=1 <test-binary> -test.run 'TestNative(InterruptedDMGAttachDetachesOwnedMount|InstallerRecoveryInApplications)' -test.v`. This mounts only a disposable empty image and changes only uniquely named disposable files in /Applications; existing bundles remain untouched. It verifies actual mount cleanup after accepted post-mount simulated cancellation/deadline errors; it does not assert physically interrupting hdiutil mid-system-call is universally atomic. Existing Mac denied-permission lifecycle test should run on mpvqa; actual app install/update/uninstall/config-preservation on owner-authorized mac-dev remains a separate gate.

Windows amd64 disposable agent-account QA: `<test-binary> -test.run 'Test(InstallerJournalPrivateInInheritedReadableWindowsParent|RecoveryRejectsForgedInstallerAuthority|InstallerRecoveryDoesNotRecreateMissingAuthenticationKey|AuthenticatedInstallerRecoverySupportsSharedApplicationParent|FFmpeg)' -test.v`. Journal test grants EveryoneRX only on disposable temp parent and proves protected journal/key creation and real recovery. Root's fileops owner/DACL regression must also pass. Full real app lifecycle and signed release artifact checks are separate.

Windows ARM64 remains accepted open-beta coverage gap; Intel Mac native execution waived per AGENTS. ARM64 synthetic PE/manifest tests and cross-compilation do not replace native Windows ARM64 FFmpeg execution.

## Second-review follow-up

Protected journal inventory was added after parent second review identified signed-record opaque capture/replay via writable sibling parents. Native binaries were refreshed afterward; parent must use the refreshed binaries and rerun native journal/recovery tests. Existing ARM64 native old FFmpeg error-path fixtures were corrected to populate ARM assets rather than implicitly assume X8664. The original standalone audit probes intentionally exercise old unsafe behavior and are historical evidence, not post-fix regression assertions.

## Independent root-code follow-up

Reviewed root Windows fileops private creation/ACL preservation and F02 no-overwrite shortcut changes. No blocking issue found in those changes. Protected native temp files are created before bytes, existing owner/ordered DACL ACEs and protection are cloned before publication, and same-volume MoveFileEx replacement retries only sharing/lock/access conflicts for at most1s without a copy fallback. Native exact SDDL comparison normalizes only the informational AUTO_INHERITED DACL token: [Microsoft documents that SetNamedSecurityInfo converts to the current inheritance model while retaining ACL semantics](https://learn.microsoft.com/en-us/windows/win32/secauthz/automatic-propagation-of-inheritable-aces); [SE_DACL_PROTECTED continues to block inherited ACL changes](https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/security-descriptor-control). Root owns actual native test results. Suggested a nonblocking owner comparison refinement for elevated tokens whose default owner can be Administrators, and a fixed timeout/owned process for the existing raw Windows shortcut cscript command. No edits to root-owned files from this review.

Shared PruneBackups now receives a literal directory separately from the basename pattern, avoiding directory glob metacharacters. Installer call updated to that API; TestCreateFullBackupPrunesInsideLiteralBracketedProfile passes and verifies pruning plus unrelated-file preservation with a `[test]` profile path. Only docs/ARCHITECTURE.md private journal-inventory wording was updated by this agent; remediation/audit reports remain parent-owned.
