Phase 3 of the one-app pivot (DESIGN 12 ▸ The entitlement / Distribution, ruled 2026-07-30; card c3a3ddd5). New Kanban/Tier/: Tier (.free/.pro — deliberately no .lapsed case; unsubscribed and lapsed are one state) and the pure decision Tier.resolve(from:now:) over SubscriptionFacts (expiration + willAutoRenew), unit-tested through all five named states: free, active, lapsed, offline-grace, never-online. The facts are a persisted cache (standard defaults), not a live view: StoreKit ages an expired subscription out of currentEntitlements locally, so an offline device and a real lapse are indistinguishable from that property alone — the cache holds the last answer, empty entitlements read as silence, and holds end only on a definitive answer (revocation, or the subscription-group status read Settings performs). That is 12's offline-grace trade, resolved toward the paying user. ProEntitlement is the local adapter (currentEntitlements + Transaction.updates, started from launch, never from a test host); ProStorefront holds everything networked (product load, purchase, AppStore.sync) and only the Settings section ever constructs one — the split is the enforcement of "never network on the open path". beginSession reads the tier once at composition; BoardSession.tier is a let with no path back in, so a lapse never rebinds an open session. makeHistoryProvider now takes the tier; both tiers bind the native stack until pro-m1 builds the git provider — the seam's consumer is named, not invented early. Settings gains the Pro section (subscribe with localized price, manage, restore; a quiet unreachable line, no indefinite spinner) — the third of the exactly-three Pro mentions; the About line gains its "…in Settings" pointer now that there is a Settings to point at. A successful purchase or restore offers once to reopen open boards (close + reopen through the ordinary paths). Configuration.storekit wired into the scheme's run action for ASC-free exercise; RELEASE.md gains the pro-m1 store-side steps and the rule that the product must not be configured before then. 1901 tests in 319 suites green. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
40 lines
2.3 KiB
Swift
40 lines
2.3 KiB
Swift
import IndieAbout
|
|
|
|
/// **The About box's configuration — one of the three places the app names Lanework Pro.**
|
|
///
|
|
/// 12-editions.md ▸ Tier naming: "The free tier presents as a complete app, not a demo: Pro is
|
|
/// named in exactly three places — one line in the About box, the contextual popover line on
|
|
/// `.git` boards, and the Settings Pro section where the subscription actually lives. Nothing on
|
|
/// the welcome screen, nothing in banners." The popover line is `BoardGitNote`'s; this is the
|
|
/// About line, riding as the second line of the copyright text — `IndieAbout` renders
|
|
/// `copyrightText` as one multi-line `Text`, so the signpost is literally a line in the box, no
|
|
/// custom layout.
|
|
///
|
|
/// **One box for every tier.** The 2026-07-27 split gave Pro a twin of this file without the
|
|
/// signpost, on the reasoning that a separate Pro app pointing at itself would be noise; the
|
|
/// one-app collapse (12, re-ruled 2026-07-30) makes Pro a subscription, so the line is a pointer
|
|
/// to something a subscriber has already taken up rather than to another download — true either
|
|
/// way, and shown to everyone. It stays deliberately flat: what Pro adds, in one sentence, with
|
|
/// no call to action.
|
|
///
|
|
/// **The direction arrived with the section.** The line was written without its "…in Settings"
|
|
/// while there was no Settings Pro section to point at — a signpost to a dead end is worse than no
|
|
/// signpost. `ProSettingsSection` exists now, so the sentence ends where the subscription actually
|
|
/// lives. Still one sentence, still flat, still no verb aimed at the reader: it names the place, it
|
|
/// does not ask them to go there.
|
|
enum AboutBox {
|
|
|
|
/// The About window's content: version/build/date from the stamped Info.plist
|
|
/// (`update_build_info.sh` — CFBundleVersion, BuildDate, BuildHash), the version line
|
|
/// opening the bundled CHANGELOG.md, and the bundled ISC LICENSE.md as the one document
|
|
/// link. Both documents are authored to the Apple inline-Markdown subset — see the files'
|
|
/// own single-line paragraphs.
|
|
static var configuration: AppInfoConfiguration {
|
|
AppInfoConfiguration(
|
|
copyrightText: "© 2026 rzen\nLanework Pro adds git-backed board history and sync — see Settings.",
|
|
documents: [.license(extension: "md")],
|
|
changelogDocument: .changelog()
|
|
)
|
|
}
|
|
}
|