# macOS Platform Guide

MPV Manager v1.3 ships raw Go executables for Intel and Apple Silicon and
requires macOS 13 or later, matching Go 1.27's supported Darwin floor. The
planned v1.4 primary product is a signed and notarized Wails `.app` delivered
in a DMG.

## Build

```bash
make build-macos-intel
make build-macos-arm
# or both
make build-macos
```

Outputs:

- `dist/mpv-manager-macos-intel`
- `dist/mpv-manager-macos-arm`

The v1.3 Makefile does not create a universal binary or `.app` bundle. Do not
document either as a current artifact. Verify a native artifact with:

```bash
./mpv-manager-macos-arm --version --json
```

Confirm the exact normalized release, `goos=darwin`, and the expected
architecture.

## Run and Gatekeeper

```bash
chmod +x ./mpv-manager-macos-arm
./mpv-manager-macos-arm
./mpv-manager-macos-arm tui
./mpv-manager-macos-arm --debug
```

Unsigned development builds may be blocked or quarantined. Inspect before
changing attributes:

```bash
xattr -l ./mpv-manager-macos-arm
codesign -dv --verbose=4 ./mpv-manager-macos-arm
spctl --assess --verbose ./mpv-manager-macos-arm
```

Only remove quarantine from a development artifact whose origin and checksum
you have verified. Developer ID signing/notarization is planned for v1.4.0. The raw
v1.3 artifacts therefore require actual unsigned download/launch acceptance
and reviewed launch instructions before release. The planned v1.4 desktop
artifacts must be signed, hardened, notarized and stapled.

## Install methods and credentials

Supported macOS choices include MPV, IINA, and Homebrew-backed installations
where exposed by the detected platform. Test Apple Silicon and Intel-specific
download selection separately.

IINA installation is bound to the verified DMG that was just downloaded. The
installer mounts read-only beneath a private temporary root, parses
`hdiutil attach -plist`, and copies only from the returned device/mount pair.
It rejects mounts outside that root, ambiguous `IINA.app` bundles, symlinks,
the wrong bundle identifier or architecture, and invalid/missing Developer ID
signatures. Cleanup detaches the returned device rather than a global
`/Volumes/IINA` name, including a best-effort exact-device cleanup if attach
output cannot be parsed.

Secrets use macOS Keychain. There is no plaintext credential fallback.
System-wide locations such as `/Applications` can require user approval or
elevation depending on ownership.

## v1.3 native update gate

Test on Apple Silicon hardware. Native Intel Mac coverage is waived for v1.3.0
by the release owner; Intel cross-builds remain required and are not native
execution evidence. Cover:

- N-2 and N-1 updates;
- writable and unwritable raw-binary locations;
- quarantine and code-signature policy;
- wrong hash/product/component/version/architecture;
- rollback and stale update cleanup;
- Web restart notice, backend-owned close, and exit status 0;
- TUI relaunch and relaunch failure;
- IINA volume-name collisions, signature/bundle-ID/architecture rejection, and exact-device detach;
- package-owned/Homebrew behavior with raw self-update disabled.

The v1.3 updater operates on the raw binary artifact only. It must never patch
an executable inside a signed `.app`; that would invalidate the bundle.

On 2026-08-30, the development-only synthetic-version qualifier passed commit,
forced partial rollback, lock contention, healthy relaunch, and failed-health
rollback natively on `macos-dev` (Apple Silicon, macOS 26.6.2). The run used
Darwin arm64 artifacts built from the current Go 1.27 source and confirmed that
replacement targets remain executable. Historical N-1/N-2 artifacts, Intel
hardware, unwritable destinations, quarantine/signature policy, package-owned
behavior, and the complete Web lifecycle remain release gates.

## v1.4 `.app` direction

The Wails migration treats the complete signed/notarized `.app` as the update
unit. A zipped copy of that app can preserve bundle bytes for updater staging,
while the user download is normally a DMG. The existing templates, htmx,
Alpine components, CSS, and route behavior should remain one shared frontend.
See [Self-update and Wails Review](../SELF_UPDATE_AND_WAILS_REVIEW_2026-08-28.md).

---

See also: [Build and Deployment](../BUILD_DEPLOYMENT.md) · [Testing](../TESTING.md) · [Troubleshooting](../TROUBLESHOOTING.md)
