# Mac App Store Setup

Presenton’s Electron app is configured for Mac App Store (MAS) distribution with App Sandbox. MAS builds must be produced on macOS because Apple’s signing tools are required.

This guide covers Apple Developer setup, local provisioning files, and the npm scripts in `electron/package.json` on `main`.

## Overview

| Target | Purpose | npm script |
|--------|---------|------------|
| `dmg` | Direct download outside the App Store | `npm run build:all:mac:signed` |
| `mas-dev` | Sandbox testing on registered Macs | `npm run build:all:mas-dev` |
| `mas` | App Store submission | `npm run build:all:mas` |

Build configuration lives in `electron/build.js`. Key identifiers:

- **Bundle ID:** `com.presenton.presenton`
- **Team ID:** `S6W5C54KL6` (set in `extendInfo.ElectronTeamID`)

## MAS files in the repo

These are checked in under `electron/build/`:

| File | Role |
|------|------|
| `entitlements.mas.plist` | Main app entitlements (sandbox, network, JIT, user-selected files) |
| `entitlements.mas.inherit.plist` | Inherited entitlements for helper processes and bundled binaries |
| `MacAppStore.provisionprofile.replace_me` | Placeholder — replace with your real App Store profile (see below) |

`build.js` validates provisioning profiles with `security cms -D` before building. Invalid or placeholder files will fail the build with a clear error.

## What you need from Apple

### 1. Apple Development certificate

Xcode → **Settings** → **Accounts** → your team → **Manage Certificates** → **+** → **Apple Development**.

Used for `mas-dev` builds and local sandbox testing.

### 2. Apple Distribution certificate

Same path as above, but choose **Apple Distribution**.

Used for `mas` (App Store submission) builds.

### 3. App ID (Bundle ID)

[Apple Developer Portal](https://developer.apple.com/account) → **Certificates, Identifiers & Profiles** → **Identifiers** → **App IDs**.

Create a macOS App ID that matches `com.presenton.presenton` (or update `APP_ID` in `electron/build.js` if you use a different ID).

### 4. Provisioning profiles

Create **two** macOS profiles and download each `.provisionprofile` file into `electron/build/`:

#### AppleDevelopment (MAS development)

- Portal → **Profiles** → **+**
- Type: **macOS App Development**
- App ID: your Presenton app ID
- Certificate: **Apple Development**
- Save as `electron/build/AppleDevelopment.provisionprofile`

`build.js` also accepts `AppleDev.provisionprofile` or `AppDev.provisionprofile` as fallbacks.

#### MacAppStore (MAS distribution)

- Portal → **Profiles** → **+**
- Type: **Mac App Store**
- App ID: your Presenton app ID
- Certificate: **Apple Distribution**
- Save as `electron/build/MacAppStore.provisionprofile`

Verify profiles decode correctly:

```bash
cd electron
security cms -D -i build/AppleDevelopment.provisionprofile
security cms -D -i build/MacAppStore.provisionprofile
```

Provisioning profiles expire (typically yearly). Regenerate and replace the local files when they do.

## Environment variables

| Variable | Used for | Description |
|----------|----------|-------------|
| `PRESENTON_MAC_TARGET` | Set by npm scripts | `mas-dev` or `mas` (do not set manually when using the scripts below) |
| `PRESENTON_MAS_DEV_IDENTITY` | `mas-dev` | Signing identity, e.g. `Apple Development: Your Name (TEAMID)` |
| `PRESENTON_MAS_DISTRIBUTION_IDENTITY` | `mas` | Distribution identity, e.g. `Apple Distribution: Your Org (TEAMID)` |
| `PRESENTON_MAS_IDENTITY` | `mas` | Alias for distribution identity |
| `CSC_NAME` | Either target | Fallback if the target-specific identity vars are unset |
| `PRESENTON_APP_STORE_VERSION` | `mas` | App Store **version** (`x.y.z`). Required when `package.json` version contains a suffix like `-beta` |
| `PRESENTON_APP_STORE_BUILD` | `mas` | App Store **build** number. Defaults to the short version if unset |

Example for a beta package version:

```bash
export PRESENTON_APP_STORE_VERSION=1.0.0
export PRESENTON_APP_STORE_BUILD=42
```

## Build commands

Run from `electron/` after `npm run setup:env` (first time only).

### Full build (recommended)

Rebuilds Next.js, FastAPI, export runtime, and packages the app:

```bash
# MAS development — runs on Macs in your dev provisioning profile
PRESENTON_MAS_DEV_IDENTITY="Apple Development: Your Name (TEAMID)" \
  npm run build:all:mas-dev

# MAS distribution — for App Store Connect upload
PRESENTON_MAS_DISTRIBUTION_IDENTITY="Apple Distribution: Your Org (TEAMID)" \
  PRESENTON_APP_STORE_VERSION=1.0.0 \
  npm run build:all:mas
```

### Package only (resources already built)

If you already ran `build:all` and only need to re-run the Electron packager:

```bash
PRESENTON_MAS_DEV_IDENTITY="Apple Development: Your Name (TEAMID)" \
  npm run dist:mac:mas-dev

PRESENTON_MAS_DISTRIBUTION_IDENTITY="Apple Distribution: Your Org (TEAMID)" \
  PRESENTON_APP_STORE_VERSION=1.0.0 \
  npm run dist:mac:mas
```

### Direct DMG (not App Store)

For a signed and notarized macOS disk image that does not go through App Store approval:

```bash
npm run build:all:mac:signed
```

See [Direct distribution](./direct-distribution.md) for the Developer ID certificate, notarization, and verification flow.

Artifacts land in `electron/dist/`.

## Output locations

Exact paths depend on architecture (`arm64` vs `x64`). Typical layouts:

```text
electron/dist/
  mas-dev-arm64/          # unsigned or dev-signed .app (mas-dev)
  mas-arm64/              # distribution-signed .app (mas)
  Presenton-<version>.pkg # MAS installer for upload
  Presenton-<version>.dmg # signed and notarized direct distribution DMG
```

Upload the `.pkg` from the `mas` build to [App Store Connect](https://appstoreconnect.apple.com).

## Icons

The default macOS icon is `electron/resources/ui/assets/images/presenton_short_filled.png`.

For App Store packaging you can provide a proper `.icns` at `electron/build/icon.icns` and update the `mac.icon` field in `electron/build.js` if you want a custom store icon.

Source PNGs for generating an icon set are in `electron/build/icon.iconset/`.

## Testing notes

- **MAS-signed apps** require the MAS Electron build (`mas` or `mas-dev` targets). A normal DMG build is not sandbox-compatible in the same way.
- **`mas-dev` builds** run only on Macs registered in your development provisioning profile.
- **`mas` (distribution) builds** usually do not launch locally; they are meant for App Store Connect processing and release.
- **`mas-dev` signing** uses `--timestamp=none` in `build.js` so local signing works without a network timestamp server.

## Troubleshooting

**“Missing MAS development/distribution provisioning profile”**

Place the correct `.provisionprofile` in `electron/build/` (see [Provisioning profiles](#4-provisioning-profiles)).

**“macOS could not decode” a profile**

Re-download the profile from the Developer Portal. Do not commit real profiles to git.

**“Cannot derive an App Store version from package version”**

Set `PRESENTON_APP_STORE_VERSION` to three integers, e.g. `1.0.0`.

**“MAS builds must be run on macOS”**

Run the build on a Mac with Xcode command-line tools installed (`xcode-select --install`).

**FastAPI or export binary not executable inside the .app**

`build.js` runs an `afterPack` hook that sets executable permissions on bundled binaries. If signing fails afterward, check that entitlements allow the sandboxed app to execute helpers in `Contents/Resources/app/resources/`.

## See also

- [macOS dev README](./README.md) — quick reference for all macOS build targets
- [Electron dependency strategy](../../electron-dependency-strategy.md) — what gets bundled in the app
