Feat/app store release prep#3
Open
matija wants to merge 8 commits into
Open
Conversation
…days compute_status_pure was silently suppressing the Commercial Banner for 14 days after commercial_detected_at was set. The grace_end gate served no purpose — banner should appear as soon as commercial usage is detected, subject only to the per-session banner_dismissed flag. grace_period_ends on LicenseStatus is kept (always None) so the frontend LicenseBadge popover continues to work unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
Prepare the build infrastructure for Mac App Store distribution as a parallel target to the existing GitHub Releases / Homebrew (Direct) build. Pure config + entitlements plumbing; no runtime behaviour change. - Strip macOS-only fields from base tauri.conf.json (titleBarStyle, hiddenTitle, windowEffects, macOSPrivateApi). - Add tauri.macos.conf.json — Direct overlay, auto-merged on macOS. - Add tauri.mas.conf.json — MAS overlay (passed via --config). Disables macOSPrivateApi, drops the sidebar windowEffect, restricts bundle to .app, points at the MAS signing identity / provisioning profile / entitlements, and turns off the updater plugin + updater artifacts. - Add Esploro-MAS.entitlements (app-sandbox + network.client only). - Add Cargo `mas` feature flag for upcoming P2 source-code gating. Note: tauri-build reads `tauri`'s features list in Cargo.toml literally and ignores feature aliases (tauri-apps/tauri#11142, #7940), so `macos-private-api` stays literally listed to keep the default Direct build working. Producing a MAS-compliant binary requires the release pipeline to strip that feature from Cargo.toml before building, then restore it — documented in Cargo.toml and PRD's Submission Flow. Co-authored-by: Cursor <cursoragent@cursor.com>
…eature flag Introduces src-tauri/src/commands/iap.rs behind #[cfg(feature = "mas")] with the four StoreKit command stubs (iap_get_products, iap_purchase, iap_restore, iap_check_entitlement), wire types, and StoredEntitlement keychain helpers. lib.rs now feature-gates the Dodo Payments commands, the tauri-plugin-updater plugin, and the revalidate_license_background spawn behind not(feature = "mas"). The IAP command registrations are behind feature = "mas". This makes cargo check --features mas succeed for the first time and prepares the surface that the StoreKit integration (next step) will fill in. No frontend changes; no behaviour change in the Direct build. Co-authored-by: Cursor <cursoragent@cursor.com>
Complete the source-level split between the Direct and MAS license layers started in the IAP scaffold. All Dodo Payments code paths in license.rs — constants, StoredLicense + keychain helpers, call_dodo_validate / DodoError, the dodo_*_message helpers, the revalidate_license_background task, and the activate_license / deactivate_license / open_customer_portal commands — now live behind #[cfg(not(feature = "mas"))], so the MAS binary stops compiling them in. Introduce a small CachedLicense enum as the cross-build abstraction for "is there a valid cached commercial license?" and have compute_status_pure take Option<CachedLicense> instead of a Dodo-shaped Option<&StoredLicense>. Two cfg-gated translator helpers feed the same status state machine: direct_cached_license maps StoredLicense by validated-at age (14-day offline grace, fail-closed on unparseable timestamps), and mas_cached_license maps the StoreKit StoredEntitlement by expires_at. The LicenseStatus wire shape stays identical so the frontend builds against either flavour unchanged. Tests reorganised into build-agnostic (5), Direct-only (7), and MAS-only (4) groups. cargo clippy / cargo test pass on both flavours; cargo check --features mas now has zero warnings (down from 12). Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces the four iap_* command stubs with a real StoreKit 1 implementation in a new iap_storekit module behind --features mas. A custom Obj-C delegate class (EsploroStoreKitDelegate) defined via objc2::define_class! conforms to SKProductsRequestDelegate, SKRequestDelegate, and SKPaymentTransactionObserver, and is registered as the default SKPaymentQueue observer at app launch. Tauri commands bridge to it via tokio::sync::oneshot channels. Direct (GitHub/Homebrew) build is unchanged; objc2 / objc2-foundation / objc2-store-kit are target-gated to macOS and pulled in only when the mas feature is active. Co-authored-by: Cursor <cursoragent@cursor.com>
The MAS frontend needed three things that the Direct UI didn't: a StoreKit-driven purchase sheet, a Restore Purchases path, and a Manage Subscription deep link to the Mac App Store. Rather than fork the Vite bundle, the React tree now branches at runtime on a new `get_build_flavor` Tauri command that returns "direct" or "mas" based on cfg!(feature = "mas"). - New `get_build_flavor` Tauri command (always-on, doc-commented as `staleTime: Infinity` material on the frontend) + two cfg-gated tests pinning the return value per build. - New `PurchaseSheet` component renders the three IAP products fetched live, runs purchases through `iap_purchase`, and refreshes both LICENSE_STATUS_KEY and a new IAP_ENTITLEMENT_KEY cache on success. - LicenseBanner now shows "Get a license" on MAS (opens PurchaseSheet) and keeps the existing "Purchase license" + "I have a license key" on Direct. The revalidation-required banner is gated behind !isMas since revalidation_required is always false on MAS. - LicenseSettings has a MAS commercial panel that resolves the active product ID to a friendly plan label, shows renewal/purchase date, and exposes Manage subscription (subscriptions only) + Restore purchases. The MAS unlicensed panel offers Get a license + Restore. Direct UI is unchanged byte-for-byte. - New `licenseApi` wrappers: getProducts, purchase, restore, checkEntitlement, getBuildFlavor, openManageSubscription (deep-links to macappstore://apps.apple.com/account/subscriptions). - New types: BuildFlavor, IapProduct, IapPurchaseResult, IapPurchaseStatus, IapRestoreResult, IapEntitlement. Verification: cargo clippy + test clean on Direct (22 passing) and MAS (27 passing); npm run type-check and npm run lint clean. Co-authored-by: Cursor <cursoragent@cursor.com>
Wraps the Cargo.toml patch + cargo tauri build + restore sequence (per PRD P1 note) in a single script so the developer can run `npm run tauri:build:mas` instead of remembering the three-step dance. Trap on EXIT guarantees Cargo.toml is restored even on Ctrl+C mid-build. Co-authored-by: Cursor <cursoragent@cursor.com>
…scaffold) Adds store-listing/ with the App Store-compliant 1024x1024 icon (no alpha, no rounded corners — generator script lives alongside for reproducibility), the full metadata block ready to paste into App Store Connect, and a screenshots scaffold documenting the capture procedure for the remaining manual step. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.