import Foundation /// **The App Store Connect configuration this app mirrors in code** — the subscription's product /// identifier and the group it belongs to. /// /// ### These strings are configuration, not invention /// /// Nothing here is created at runtime. A subscription group and its products are made **by hand** in /// App Store Connect, against the record `dev.rzen.indie.Kanban` (12-editions.md ▸ Distribution; /// RELEASE.md ▸ Lanework Pro), and StoreKit will only ever return products whose identifiers match /// what that account actually declares. This file is the local half of that agreement: change a /// string here without changing it there and the Settings Pro section quietly reports that it cannot /// reach the App Store, which is exactly what a mismatched identifier looks like from inside the app. /// `Configuration.storekit` at the repo root is the third copy — the Xcode-local one — and it exists /// so the purchase flow can be exercised on a machine with no App Store Connect access at all. /// /// ### The identifier's shape /// /// `dev.rzen.indie.kanban.pro.monthly` follows the family's reverse-DNS style, the same one the three /// pasteboard types already use (`dev.rzen.indie.kanban.cards`, `…lanes`, `…clipboard` — /// `PasteboardTypes.swift`): the lowercase `kanban` codename segment, then what the thing *is*. The /// bundle id keeps its capital `K` because that is what the 1.x App Store record ships under; the /// identifiers the app coins for itself do not, and consistency inside that set is what matters. /// /// **One product to start.** A monthly subscription is the whole storefront until there is evidence /// for a second — an annual tier, a family plan and an introductory offer are all additions to the /// same group and none of them changes a line of the entitlement, which reads *whatever* transaction /// the group produced (`ProEntitlement`). `all` is the seam that keeps that true: everything that /// matches a transaction against this app's products asks this set, never the single constant. public enum ProProducts { /// Lanework Pro, billed monthly — the one auto-renewable subscription product. public static let monthly = "dev.rzen.indie.kanban.pro.monthly" /// The subscription group's **reference name** in App Store Connect: "Lanework Pro". /// /// Deliberately *not* the group's numeric id. That number is minted by App Store Connect when the /// group is created and cannot be known until then, so hardcoding one would be a value invented /// at the wrong end. Where StoreKit needs the numeric id — reading a group's subscription status /// — it is read off a loaded `Product` (`product.subscription?.subscriptionGroupID`), which is /// the account's own answer rather than this file's guess. public static let subscriptionGroupName = "Lanework Pro" /// Every product identifier this app's entitlement recognises. /// /// The set, rather than the constant, is what `ProEntitlement` matches transactions against and /// what `ProStorefront` loads — so adding an annual product is one line here and nothing else. public static let all: Set = [monthly] }