# macOS Signing Model — Phase C.4

## Status

| Layer | Status |
|-------|--------|
| Full agent packaging (`.tar.gz` / staged `.pkg`) | ✅ |
| Native Console `.app` (C.3) | ✅ |
| Developer ID Application / Installer signing | ⏳ Mac host + Apple Developer account |
| Notarization (`notarytool`) + staple | ⏳ `sign_and_notarize.sh` |
| Gatekeeper EV → `state: AVAILABLE` | ⏳ after notarization receipt |

## Scripts

| Script | Role |
|--------|------|
| `packaging/macos/build_pkg.sh` | Stage + `pkgbuild`/`productbuild` on Mac; Linux stages only |
| `packaging/macos/sign_and_notarize.sh` | `codesign` / `productsign` / `notarytool` / `stapler` |
| `packaging/macos/env.macos-notarize.example` | Credential template (do not commit secrets) |

## Trust layers

1. **Apple Developer ID** — signs Console `.app` + installer `.pkg`
2. **Apple notarization** — Gatekeeper acceptance on Sequoia 15+
3. **Ed25519** — optional cross-platform integrity for tarball/`SHA256SUMS` (Linux parity); `.pkg` Gatekeeper path uses Apple signatures

## Publication policy

- Unsigned / un-notarized `.pkg` → publish as `INTERNAL_ONLY` by default
- Override: `IUVE_MAC_ALLOW_UNSIGNED_AVAILABLE=1` (internal testers only)
- After `*.notarization.json` with `apple_notarized: true` → `AVAILABLE` + `gatekeeper_ready: true`

## Security posture

- No privileged remote shell; LaunchAgent runs local `launcher.sh run` only
- Console UI is loopback `ui_bridge` (`127.0.0.1`) with bearer token
- Do not embed Apple app-specific passwords in the repository
