FTStore Manager

A tiny companion app that installs and updates FTStore from a private FTStore Admin — after you import a signing certificate.

--- FTStore Manager is a stripped-down fork of [FTStore](https://github.com/FTStuff/FTStore) (itself a fork of [Feather](https://github.com/claration/Feather), GPL-3.0). It keeps **only** the parts needed to: 1. **Import a signing certificate** (`.p12` + `.mobileprovision`). 2. **Download FTStore** from a **private** FTStore Admin, sign it with your certificate, and **install it on-device (OTA)** — no computer, no pairing file. 3. **Keep FTStore up to date** on a **Stable** or **Developer** channel. Everything else from FTStore (the store browser, the app library, tweaks, advanced signing options, the device-pairing install method) has been removed. ## The PAT never ships in the app FTStore lives in a **private** GitHub repo (`FTStuff/FTStore Admin`), so downloading it needs a GitHub token. Embedding a token in an iOS app is **not** secure — anyone with the `.ipa` can recover an embedded secret at runtime, no matter how it's obfuscated. So the Manager **never contains the token**. Instead, FTStore Admin (the Next.js server you already run) exposes a small proxy that holds the token **server-side** and streams FTStore back to the app: ``` FTStore Manager ──HTTPS──▶ FTStore Admin proxy ──token (server-side)──▶ GitHub (private repo) (no token) /api/ftstore-app/* FTStuff/FTStore Admin ``` The only thing the app needs is your **FTStore Admin address**. The GitHub token stays server-side in FTStore Admin and is never exposed to the Manager. ## Part 1 — FTStore Admin proxy (server) Two endpoints were added to FTStore Admin (`src/app/api/ftstore-app/`). They reuse FTStore Admin's existing server-side GitHub token (`GITHUB_TOKEN` / DB setting): | Endpoint | Purpose | |----------|---------| | `GET /api/ftstore-app/manifest?channel=stable\|dev` | Returns `{ version, updatedAt, size, downloadURL }` for the channel. | | `GET /api/ftstore-app/download?channel=stable\|dev` | Streams the FTStore IPA bytes (the only path that touches the token). | **Channels** - **stable** → the newest non-`dev` release of `FTStuff/FTStore Admin` that has an `FTStore*.ipa` asset. Version = the release tag (e.g. `v2.8.2`). - **dev** → the release tagged `dev`. The version string never changes, so freshness is tracked by the asset's `updated_at` timestamp. **Prerequisites:** FTStore Admin must be reachable from your device, have `GITHUB_TOKEN` / `GITHUB_OWNER` / `GITHUB_REPO` configured, and contain an `FTStore*.ipa` asset on a stable release and/or on the `dev` release. ## Part 2 — the app - **Identity:** display name `FTStore Manager`, bundle id `app.ftstore.manager` (distinct from `app.ftstore`, so installing FTStore is never a self-install — that's why OTA works without a pairing file). - **Config:** inject the FTStore Admin address at build time via the `FTSTORE_ADMIN_BASE_URL` user-defined setting in `FTStore.xcconfig` (it flows into `Info.plist` as `FTStoreAdminBaseURL`), or use the built-in default. Nothing secret is committed. - **Flow:** the home screen shows FTStore's state (Not installed / Up to date / Update available) and one button. Tapping it downloads via the proxy, auto-signs with your certificate (prompting you to import one the first time), and installs over the air. ### New / changed source (everything else is unmodified FTStore engine) ``` FTStore/Manager/ ManagerConfig.swift FTStore Admin base URL (Info.plist + override) FTStoreAdminClient.swift Calls the FTStore Admin manifest endpoint FTStoreUpdateManager.swift Decides install vs update (stable=version, dev=updatedAt) ManagerHomeView.swift The single-screen UI ManagerSettingsView.swift FTStore Admin address, channel, install method, certificates FTStore/FTStoreManagerApp.swift @main entry (replaces FTStoreApp.swift) ``` Small edits: `AppInstallManager` gained an `install(InstallRequest)` entry point and `DownloadManager` gained an optional auth-header parameter; `ServerPackModel` moved into `Backend/Server/Models/`. ## Building macOS + Xcode required (this is a Swift/Xcode project — it can't build on Linux/Windows). Dependencies are **vendored** (no submodule init needed): ```sh git clone --recurse-submodules https://github.com/FTStuff/FTStore.git cd FTStore/manager make # builds packages/FTStore-Manager.ipa (the Manager) ``` Or open `FTStore.xcworkspace` in Xcode, or run the **Manager Release** GitHub Action (`workflow_dispatch` or push a `v*` tag). > The optional `LicensePlist` / `AltSourceKit` / `IDeviceKitten` Swift packages remain > linked (the OTA installer reuses a couple of helpers from them). They can be pruned in > Xcode if you want a leaner build. ## License & credits GPL-3.0, inherited from FTStore / Feather. The original Feather copyright notices are preserved (`LICENSE`). Huge thanks to: - [Samara / claration](https://github.com/claration) — Feather, which FTStore (and this) builds on. - [Felitendo](https://github.com/Felitendo) — FTStore and FTStore Admin. - [Zsign](https://github.com/zhlynn/zsign), [idevice](https://github.com/jkcoxson/idevice), [Vapor](https://github.com/vapor/vapor), [Nuke](https://github.com/kean/Nuke), [*.backloop.dev](https://backloop.dev/), [plistserver](https://github.com/nekohaxx/plistserver).