From ab16770e75a02f252670992de45f175640a77457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Mon, 18 May 2026 16:29:09 +0200 Subject: [PATCH 1/8] fix(license): show commercial banner immediately instead of after 14 days MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- progress.txt | 21 ++++++++++++ src-tauri/src/commands/license.rs | 54 ++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/progress.txt b/progress.txt index 9b82911..39207f6 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,24 @@ +## MAS PRD P0 — Grace period bug fix [DONE] +- Bug: compute_status_pure in src-tauri/src/commands/license.rs silently suppressed the + Commercial Banner for 14 days after commercial_detected_at was set. The delay served no + purpose — banner should appear as soon as commercial usage is detected, subject only to + the per-session banner_dismissed flag. +- src-tauri/src/commands/license.rs: + - Removed the grace_end (detected + 14d) computation in the commercial-detected branch. + - Removed the `now > grace_end` gate on banner_visible; banner_visible is now simply + `!banner_dismissed` whenever commercial_detected_at is set. + - grace_period_ends field on LicenseStatus is kept but always set to None. + Rationale: AppShell LicenseBadge popover already handles `gracePeriodEnds: null` by + rendering "License active" instead of "Valid through [date]" — no frontend change needed. + - Tests rewritten: + - commercial_detected_shows_banner_immediately (new) — banner visible the instant detection lands + - commercial_detected_banner_hidden_when_dismissed_for_session (new) — dismissed=true suppresses + - commercial_detected_long_ago_still_shows_banner (new) — regression guard for the old 14d bug + - no_stored_license_after_valid_false_shows_banner_when_grace_expired (replaced) — grace concept gone + - All 10 license tests pass. +- PRD.md: marked P0 [DONE] with a summary of what changed. +- All CI checks pass (cargo clippy --workspace --all-targets -- -D warnings, tsc --noEmit, eslint). + ## PRD #4 — Default theme: Tokyo Night [DONE] - Changed defaultUiPreferences.ui.theme from "system" to "tokyo-night" in src/features/settings/preferences.ts:52. - Affects first-run users only; existing users with a stored theme see no change. diff --git a/src-tauri/src/commands/license.rs b/src-tauri/src/commands/license.rs index b958875..863994e 100644 --- a/src-tauri/src/commands/license.rs +++ b/src-tauri/src/commands/license.rs @@ -506,20 +506,15 @@ fn compute_status_pure( } } - // Commercial usage detected? - if let Some(detected_str) = &prefs.commercial_detected_at { - if let Ok(detected) = chrono::DateTime::parse_from_rfc3339(detected_str) { - let grace_end = detected.with_timezone(&Utc) + chrono::Duration::days(14); - let grace_period_ends = Some(grace_end.to_rfc3339()); - let banner_visible = now > grace_end && !banner_dismissed; - return LicenseStatus { - tier: LicenseTier::Unlicensed, - banner_visible, - grace_period_ends, - show_usage_dialog: false, - revalidation_required: false, - }; - } + // Commercial usage detected — show banner immediately (subject only to session dismissal). + if prefs.commercial_detected_at.is_some() { + return LicenseStatus { + tier: LicenseTier::Unlicensed, + banner_visible: !banner_dismissed, + grace_period_ends: None, + show_usage_dialog: false, + revalidation_required: false, + }; } // Personal or unknown — check if we should show the usage dialog @@ -817,18 +812,41 @@ mod tests { } #[test] - fn no_stored_license_after_valid_false_shows_banner_when_grace_expired() { - // Simulates: Dodo returned valid:false → clear_stored_license() called → compute_status - // runs next poll with no stored key. Banner shows because commercial was detected earlier. + fn commercial_detected_shows_banner_immediately() { + // No 14-day grace period: as soon as commercial usage is detected the banner is shown + // (subject only to session dismissal). let now = Utc::now(); let mut prefs = base_prefs(); - prefs.commercial_detected_at = Some((now - Duration::days(20)).to_rfc3339()); + prefs.commercial_detected_at = Some(now.to_rfc3339()); let status = compute_status_pure(None, &prefs, false, now); assert_eq!(status.tier, LicenseTier::Unlicensed); assert!(status.banner_visible); + assert!(status.grace_period_ends.is_none()); assert!(!status.revalidation_required); } + #[test] + fn commercial_detected_banner_hidden_when_dismissed_for_session() { + let now = Utc::now(); + let mut prefs = base_prefs(); + prefs.commercial_detected_at = Some(now.to_rfc3339()); + let status = compute_status_pure(None, &prefs, true, now); + assert_eq!(status.tier, LicenseTier::Unlicensed); + assert!(!status.banner_visible); + } + + #[test] + fn commercial_detected_long_ago_still_shows_banner() { + // Sanity: the previous 14-day grace bug suppressed the banner for 14 days. Even a + // long-ago detection must still surface the banner now. + let now = Utc::now(); + let mut prefs = base_prefs(); + prefs.commercial_detected_at = Some((now - Duration::days(20)).to_rfc3339()); + let status = compute_status_pure(None, &prefs, false, now); + assert!(status.banner_visible); + assert!(status.grace_period_ends.is_none()); + } + #[test] fn no_stored_license_no_commercial_detection_is_unlicensed_no_banner() { let now = Utc::now(); From 0e5060e7bd06b5ef6338490070487d22170803f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Mon, 18 May 2026 16:38:53 +0200 Subject: [PATCH 2/8] chore(mas): split tauri config into direct/MAS overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- progress.txt | 43 ++++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 22 +++++++++++++++ src-tauri/Esploro-MAS.entitlements | 10 +++++++ src-tauri/tauri.conf.json | 11 ++------ src-tauri/tauri.macos.conf.json | 16 +++++++++++ src-tauri/tauri.mas.conf.json | 27 +++++++++++++++++++ 6 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 src-tauri/Esploro-MAS.entitlements create mode 100644 src-tauri/tauri.macos.conf.json create mode 100644 src-tauri/tauri.mas.conf.json diff --git a/progress.txt b/progress.txt index 39207f6..22b06da 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,46 @@ +## MAS PRD P1 — Config split (prerequisite for MAS build) [DONE] +- Split tauri.conf.json so the same source tree can produce both the Direct (GitHub/Homebrew) + build and a future MAS build via overlay configs. No runtime/source code changes — purely + build configuration plumbing. +- src-tauri/tauri.conf.json: stripped macOS-only fields (windows[0].titleBarStyle, + hiddenTitle, windowEffects, and app.macOSPrivateApi). Base config is now platform-neutral. +- src-tauri/tauri.macos.conf.json (NEW): Direct build overlay. Auto-merged by Tauri for + macOS targets. Sets macOSPrivateApi: true and the NSVisualEffectView sidebar vibrancy. +- src-tauri/tauri.mas.conf.json (NEW): MAS build overlay, passed explicitly via + `--config`. Overrides macos overlay with macOSPrivateApi: false and windowEffects: null + (the null is required to undo the macos overlay's value during config merge — without it + the sidebar effect would still be requested). Sets bundle.targets: ["app"], + createUpdaterArtifacts: false, bundle.macOS signing/provisioning/entitlements references, + and plugins.updater.active: false. The signingIdentity and provisioningProfile values are + placeholders ("Apple Distribution: ", "EsploroMAS.provisionprofile") that the + release pipeline must replace with real values. +- src-tauri/Esploro-MAS.entitlements (NEW): App Sandbox + network.client only. No other + entitlements needed since Esploro only opens outbound TCP to Postgres/MySQL. +- src-tauri/Cargo.toml: added [features] section with `mas = []`. This flag is consumed + by source code (planned for P2) via `#[cfg(feature = "mas")]` to gate Dodo/updater code + out of the MAS binary. +- Documented a known tauri-build constraint in Cargo.toml + PRD: tauri-build (the build + script) reads `tauri`'s features array in Cargo.toml LITERALLY and compares it against + the merged config's `macOSPrivateApi` allowlist on every `cargo build`. Cargo feature + aliases like `direct = ["tauri/macos-private-api"]` are NOT resolved during that check + (tauri-apps/tauri#11142, #7940). Tried that approach first; cargo check failed with + "The `tauri` dependency features on the `Cargo.toml` file does not match the allowlist + defined under `tauri.conf.json`. Please … add the `macos-private-api` feature." +- Resolution: keep `tauri = { features = ["macos-private-api"] }` literally listed so the + default Direct build on macOS passes tauri-build, and accept that producing a + MAS-compliant binary (no private API symbols linked in) requires the release pipeline to + patch Cargo.toml at build time: + 1. Strip "macos-private-api" from the tauri dep's features array. + 2. cargo tauri build --target aarch64-apple-darwin + --config src-tauri/tauri.mas.conf.json --features mas + 3. Restore Cargo.toml. + Updated PRD's Submission Flow Step 2 to spell this out. The day-to-day developer + experience (`cargo tauri dev`) is unchanged. +- Verified: cargo check (1.7s), cargo clippy --all-targets -- -D warnings (clean), + cargo test (18 passed), npm run type-check + npm run lint (clean). All three config + JSON files parse. The macos overlay is now being picked up — confirmed by tauri-build + emitting `rerun-if-changed=tauri.macos.conf.json` during the build. + ## MAS PRD P0 — Grace period bug fix [DONE] - Bug: compute_status_pure in src-tauri/src/commands/license.rs silently suppressed the Commercial Banner for 14 days after commercial_detected_at was set. The delay served no diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ebb1769..cca7c68 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -10,6 +10,28 @@ license = "MIT" name = "esploro_lib" crate-type = ["staticlib", "cdylib", "rlib"] +[features] +# Mac App Store build flag. Used in source code via `#[cfg(feature = "mas")]` +# to gate out Dodo / updater code paths that App Store review rejects. +# +# NOTE: This feature alone is NOT sufficient to produce a MAS-compliant binary. +# `tauri-build` strictly compares the literal `tauri` dependency features in +# `Cargo.toml` against the merged `tauri.conf.json` allowlist — feature +# aliases like `direct = ["tauri/macos-private-api"]` are not resolved during +# that check (see tauri-apps/tauri#11142, #7940). So the +# `tauri/macos-private-api` feature must stay literally listed in the +# `[dependencies]` section below to satisfy the build script on macOS for the +# default Direct build. +# +# To actually produce a MAS binary (no `macos-private-api` linked in), the +# release pipeline must patch `Cargo.toml` at build time: +# 1. Remove `"macos-private-api"` from `tauri`'s `features` array. +# 2. Run `cargo tauri build --config tauri.mas.conf.json --features mas`. +# 3. Restore `Cargo.toml`. +# This is intentionally a CI-side concern, not a developer ergonomic, so the +# day-to-day `cargo tauri dev` keeps working unchanged. +mas = [] + [build-dependencies] tauri-build = { version = "2", features = [] } diff --git a/src-tauri/Esploro-MAS.entitlements b/src-tauri/Esploro-MAS.entitlements new file mode 100644 index 0000000..ee95ab7 --- /dev/null +++ b/src-tauri/Esploro-MAS.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8c4f58f..db54ed6 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -16,19 +16,12 @@ "width": 1200, "height": 780, "minWidth": 900, - "minHeight": 600, - "titleBarStyle": "Overlay", - "hiddenTitle": true, - "windowEffects": { - "effects": ["sidebar"], - "state": "followsWindowActiveState" - } + "minHeight": 600 } ], "security": { "csp": null - }, - "macOSPrivateApi": true + } }, "bundle": { "active": true, diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json new file mode 100644 index 0000000..7378905 --- /dev/null +++ b/src-tauri/tauri.macos.conf.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "app": { + "macOSPrivateApi": true, + "windows": [ + { + "titleBarStyle": "Overlay", + "hiddenTitle": true, + "windowEffects": { + "effects": ["sidebar"], + "state": "followsWindowActiveState" + } + } + ] + } +} diff --git a/src-tauri/tauri.mas.conf.json b/src-tauri/tauri.mas.conf.json new file mode 100644 index 0000000..58acd76 --- /dev/null +++ b/src-tauri/tauri.mas.conf.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "app": { + "macOSPrivateApi": false, + "windows": [ + { + "titleBarStyle": "Overlay", + "hiddenTitle": true, + "windowEffects": null + } + ] + }, + "bundle": { + "targets": ["app"], + "createUpdaterArtifacts": false, + "macOS": { + "signingIdentity": "Apple Distribution: ", + "provisioningProfile": "EsploroMAS.provisionprofile", + "entitlements": "Esploro-MAS.entitlements" + } + }, + "plugins": { + "updater": { + "active": false + } + } +} From 30b16dd9857cb3d7805f36ae3dc159e7e6ca7a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Mon, 18 May 2026 16:45:33 +0200 Subject: [PATCH 3/8] feat(mas): scaffold IAP backend module and gate Dodo/updater behind feature 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 --- progress.txt | 56 ++++++++++ src-tauri/src/commands/iap.rs | 198 ++++++++++++++++++++++++++++++++++ src-tauri/src/commands/mod.rs | 3 + src-tauri/src/lib.rs | 53 ++++++--- 4 files changed, 297 insertions(+), 13 deletions(-) create mode 100644 src-tauri/src/commands/iap.rs diff --git a/progress.txt b/progress.txt index 22b06da..e104400 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,59 @@ +## MAS PRD P2 — Step 1: IAP backend scaffold + Dodo/updater feature gating [DONE] +- Sets up the source-level boundary between the Direct (Dodo Payments + tauri-plugin-updater) + build and the MAS (StoreKit IAP, no in-app updater) build. The Direct build is bit-for-bit + identical; the MAS build now compiles, though the four IAP commands are stubs returning + Err("IAP backend not yet implemented") until Step 3 wires `objc2-store-kit`. No frontend + changes in this step. +- src-tauri/src/commands/iap.rs (NEW, behind #[cfg(feature = "mas")]): + - Wire types matching the PRD's command return shapes (camelCase via serde): + - IapProduct { id, title, description, price } — price is a pre-formatted locale string + because SKProduct hands us the localised value via priceLocale, saving the frontend an + Intl pass. + - IapPurchaseResult { status } where status is IapPurchaseStatus::Purchased | Cancelled | + Failed (serde rename_all = "lowercase" so the JSON is `{ "status": "purchased" }` etc.). + - IapRestoreResult { restored: bool }. + - IapEntitlement { entitled, productId?, expiresAt? } — productId/expiresAt are None for + unentitled users; expiresAt is None for the non-consumable lifetime product. + - StoredEntitlement { product_id, expires_at: Option } cached in the macOS Keychain + (service "app.esploro", account "mas-entitlement" — distinct from the existing Dodo + "commercial-license" account so the two builds never collide). read/write/clear helpers + are pub(crate) + #[allow(dead_code)] until Step 2 hooks them into compute_status_pure. + - Four #[tauri::command] stubs (iap_get_products, iap_purchase, iap_restore, + iap_check_entitlement) all returning Err("IAP backend not yet implemented"). They exist + so lib.rs registration, command signatures, and future frontend invokes can be wired + without coupling to the StoreKit work. + - 4 unit tests covering serde shape: lowercase purchase status, camelCase keys on + IapEntitlement, IapProduct field presence, and StoredEntitlement JSON round-trip. +- src-tauri/src/commands/mod.rs: added `pub mod iap;` behind #[cfg(feature = "mas")] and + gated `pub mod updater;` behind #[cfg(not(feature = "mas"))] — the updater module is + unreachable from a MAS binary anyway, this just prevents it from being type-checked. +- src-tauri/src/lib.rs: + - Restructured the Builder chain so tauri_plugin_updater is only plugged in for + #[cfg(not(feature = "mas"))]. App Store rules disallow self-updating outside the store + mechanism, so the plugin would be dead weight (and a review risk) on MAS. + - Wrapped the `revalidate_license_background` background spawn in + #[cfg(not(feature = "mas"))]. The MAS build sources entitlement from StoreKit and has + no license key to re-validate. + - generate_handler! invocation: kept the always-on commands (connections, schema, data, + saved_queries, license::{get_license_status, answer_usage_dialog, dismiss_license_banner, + notify_connection_count, open_url, get_ui_preferences, set_ui_preferences}) at the top; + gated activate_license, deactivate_license, open_customer_portal, updater::check_for_update, + updater::install_update behind #[cfg(not(feature = "mas"))] and the four iap_* commands + behind #[cfg(feature = "mas")]. Inline #[cfg] attributes inside tauri::generate_handler! + work because the macro expands the cfg gates on each item list entry. +- Verified: cargo clippy --all-targets -- -D warnings (clean, default features), + cargo test (22 passed — 18 existing license/data + 4 new iap), npm run type-check (clean), + npm run lint (clean). +- Also verified: cargo check --features mas exits 0. There are 12 dead-code warnings for + Dodo-only items in license.rs (call_dodo_validate, DodoError, StoredLicense + keychain + helpers, revalidate_license_background, activate_license, deactivate_license, + open_customer_portal, dodo_error_message, dodo_invalid_key_message). These are expected + and intentional for this step — Step 2 (license-layer cleanup) moves all of those behind + #[cfg(not(feature = "mas"))] and rewires compute_status_pure to read StoredEntitlement + on MAS. CI doesn't exercise --features mas, so -D warnings is unaffected. +- PRD.md P2 section: added Step 1 [DONE] sub-status with full description, plus Step 2/3/4 + pending markers describing the remaining scope. + ## MAS PRD P1 — Config split (prerequisite for MAS build) [DONE] - Split tauri.conf.json so the same source tree can produce both the Direct (GitHub/Homebrew) build and a future MAS build via overlay configs. No runtime/source code changes — purely diff --git a/src-tauri/src/commands/iap.rs b/src-tauri/src/commands/iap.rs new file mode 100644 index 0000000..b38d088 --- /dev/null +++ b/src-tauri/src/commands/iap.rs @@ -0,0 +1,198 @@ +//! In-App Purchase commands for the Mac App Store build. +//! +//! This module is only compiled when the `mas` cargo feature is enabled. +//! It exposes a small Tauri command surface mirroring the IAP product matrix +//! described in `PRD.md` (P2 — StoreKit IAP Integration). The four commands +//! are the migration boundary between the Rust backend and the frontend; the +//! actual StoreKit 1 (`objc2-store-kit`) integration lands in a follow-up +//! task. For now each command returns `Err("not yet implemented")` so the +//! shape of the API can be wired into `lib.rs` and the frontend without +//! coupling to the StoreKit work. +//! +//! Companion design docs: +//! - `plans/08-mas-adr.md` — Mac App Store distribution decision +//! - `plans/09-storekit-objc2.md` — `objc2-store-kit` over a Swift plugin +//! - `PRD.md` § P2 — command surface and license-layer changes + +use serde::{Deserialize, Serialize}; + +const KEYCHAIN_SERVICE: &str = "app.esploro"; +const KEYCHAIN_ACCOUNT_ENTITLEMENT: &str = "mas-entitlement"; + +const NOT_IMPLEMENTED: &str = "IAP backend not yet implemented"; + +// --------------------------------------------------------------------------- +// Wire types — kept in sync with the PRD's `iap_*` command return shapes. +// --------------------------------------------------------------------------- + +/// One purchasable product fetched from the App Store at runtime. +/// +/// `price` is the localised, currency-formatted string (e.g. `"$129.00"`). +/// StoreKit hands us this directly via `SKProduct.priceLocale`, so we keep it +/// pre-formatted on the Rust side rather than shipping numeric prices the +/// frontend would have to format with `Intl`. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct IapProduct { + pub id: String, + pub title: String, + pub description: String, + pub price: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum IapPurchaseStatus { + Purchased, + Cancelled, + Failed, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct IapPurchaseResult { + pub status: IapPurchaseStatus, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct IapRestoreResult { + pub restored: bool, +} + +/// Result of `iap_check_entitlement`. `expires_at` is `None` for the +/// non-consumable lifetime product and `Some(rfc3339)` for subscriptions. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] +#[serde(rename_all = "camelCase")] +pub struct IapEntitlement { + pub entitled: bool, + pub product_id: Option, + pub expires_at: Option, +} + +// --------------------------------------------------------------------------- +// Cached entitlement — replaces `StoredLicense` on the MAS build. +// --------------------------------------------------------------------------- + +/// Last-known IAP entitlement, cached in the macOS Keychain so the app can +/// render the correct license tier offline / on launch before re-querying +/// `SKPaymentQueue` for fresh transactions. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct StoredEntitlement { + pub product_id: String, + pub expires_at: Option, +} + +#[allow(dead_code)] // wired in by the follow-up license-layer refactor (P2) +pub(crate) fn read_stored_entitlement() -> Option { + let entry = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT_ENTITLEMENT).ok()?; + match entry.get_password() { + Ok(json) => serde_json::from_str(&json).ok(), + Err(keyring::Error::NoEntry) => None, + Err(e) => { + eprintln!("Failed to read MAS entitlement from keychain: {e}"); + None + } + } +} + +#[allow(dead_code)] +pub(crate) fn write_stored_entitlement(stored: &StoredEntitlement) -> Result<(), String> { + let json = serde_json::to_string(stored).map_err(|e| e.to_string())?; + let entry = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT_ENTITLEMENT) + .map_err(|e| e.to_string())?; + entry.set_password(&json).map_err(|e| e.to_string()) +} + +#[allow(dead_code)] +pub(crate) fn clear_stored_entitlement() { + if let Ok(entry) = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT_ENTITLEMENT) { + entry.delete_password().ok(); + } +} + +// --------------------------------------------------------------------------- +// Tauri commands — stubs until the StoreKit integration lands. +// --------------------------------------------------------------------------- + +#[tauri::command] +pub async fn iap_get_products() -> Result, String> { + Err(NOT_IMPLEMENTED.to_string()) +} + +#[tauri::command] +pub async fn iap_purchase(product_id: String) -> Result { + let _ = product_id; + Err(NOT_IMPLEMENTED.to_string()) +} + +#[tauri::command] +pub async fn iap_restore() -> Result { + Err(NOT_IMPLEMENTED.to_string()) +} + +#[tauri::command] +pub async fn iap_check_entitlement() -> Result { + Err(NOT_IMPLEMENTED.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn iap_purchase_status_serialises_as_lowercase_strings() { + let purchased = serde_json::to_string(&IapPurchaseResult { + status: IapPurchaseStatus::Purchased, + }) + .unwrap(); + assert_eq!(purchased, r#"{"status":"purchased"}"#); + + let cancelled = serde_json::to_string(&IapPurchaseResult { + status: IapPurchaseStatus::Cancelled, + }) + .unwrap(); + assert_eq!(cancelled, r#"{"status":"cancelled"}"#); + + let failed = serde_json::to_string(&IapPurchaseResult { + status: IapPurchaseStatus::Failed, + }) + .unwrap(); + assert_eq!(failed, r#"{"status":"failed"}"#); + } + + #[test] + fn iap_entitlement_omits_camel_case_fields_when_none() { + let unentitled = IapEntitlement::default(); + let json = serde_json::to_string(&unentitled).unwrap(); + // `expiresAt` (camelCase) must appear when serialised — None becomes null. + assert_eq!(json, r#"{"entitled":false,"productId":null,"expiresAt":null}"#); + } + + #[test] + fn iap_product_uses_camel_case_keys() { + let product = IapProduct { + id: "app.esploro.personal.lifetime".to_string(), + title: "Personal — Lifetime".to_string(), + description: "One-time individual commercial license".to_string(), + price: "$129.00".to_string(), + }; + let json = serde_json::to_value(&product).unwrap(); + let obj = json.as_object().expect("object"); + assert!(obj.contains_key("id")); + assert!(obj.contains_key("title")); + assert!(obj.contains_key("description")); + assert!(obj.contains_key("price")); + } + + #[test] + fn stored_entitlement_roundtrips_through_json() { + let stored = StoredEntitlement { + product_id: "app.esploro.business.annual".to_string(), + expires_at: Some("2027-05-18T00:00:00+00:00".to_string()), + }; + let json = serde_json::to_string(&stored).unwrap(); + let parsed: StoredEntitlement = serde_json::from_str(&json).unwrap(); + assert_eq!(parsed, stored); + } +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index 7018895..9f5366a 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,6 +1,9 @@ pub mod connections; pub mod data; +#[cfg(feature = "mas")] +pub mod iap; pub mod license; pub mod saved_queries; pub mod schema; +#[cfg(not(feature = "mas"))] pub mod updater; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 45f0c1c..68713c8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -36,9 +36,15 @@ impl Default for AppState { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - tauri::Builder::default() - .plugin(tauri_plugin_process::init()) - .plugin(tauri_plugin_updater::Builder::new().build()) + let builder = tauri::Builder::default().plugin(tauri_plugin_process::init()); + + // The Tauri updater plugin polls a GitHub Releases endpoint and replaces + // the .app on disk. App Store rules disallow self-updating outside the + // store mechanism, so the MAS build omits it entirely. + #[cfg(not(feature = "mas"))] + let builder = builder.plugin(tauri_plugin_updater::Builder::new().build()); + + builder .manage(AppState::default()) .setup(|app| { // Native macOS menu bar @@ -95,13 +101,19 @@ pub fn run() { } }); - let handle = app.handle().clone(); - tauri::async_runtime::spawn(async move { - loop { - commands::license::revalidate_license_background(handle.clone()).await; - tokio::time::sleep(tokio::time::Duration::from_secs(24 * 60 * 60)).await; - } - }); + // Dodo Payments background re-validation is Direct-build only. + // The MAS build sources entitlement from StoreKit and has no + // license key to re-validate. + #[cfg(not(feature = "mas"))] + { + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + loop { + commands::license::revalidate_license_background(handle.clone()).await; + tokio::time::sleep(tokio::time::Duration::from_secs(24 * 60 * 60)).await; + } + }); + } Ok(()) }) .invoke_handler(tauri::generate_handler![ @@ -124,17 +136,32 @@ pub fn run() { commands::saved_queries::get_saved_query, commands::saved_queries::delete_saved_query, commands::license::get_license_status, - commands::license::activate_license, - commands::license::deactivate_license, commands::license::answer_usage_dialog, commands::license::dismiss_license_banner, commands::license::notify_connection_count, - commands::license::open_customer_portal, commands::license::open_url, commands::license::get_ui_preferences, commands::license::set_ui_preferences, + // Dodo Payments + in-app updater: Direct build only. + #[cfg(not(feature = "mas"))] + commands::license::activate_license, + #[cfg(not(feature = "mas"))] + commands::license::deactivate_license, + #[cfg(not(feature = "mas"))] + commands::license::open_customer_portal, + #[cfg(not(feature = "mas"))] commands::updater::check_for_update, + #[cfg(not(feature = "mas"))] commands::updater::install_update, + // StoreKit IAP: MAS build only. + #[cfg(feature = "mas")] + commands::iap::iap_get_products, + #[cfg(feature = "mas")] + commands::iap::iap_purchase, + #[cfg(feature = "mas")] + commands::iap::iap_restore, + #[cfg(feature = "mas")] + commands::iap::iap_check_entitlement, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); From 888e2ea2c5cfd374f0e335377f343b6689fe9d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Mon, 18 May 2026 16:54:29 +0200 Subject: [PATCH 4/8] refactor(license): gate Dodo internals behind cfg(not(feature = "mas")) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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 --- progress.txt | 79 ++++++++ src-tauri/src/commands/iap.rs | 1 - src-tauri/src/commands/license.rs | 310 +++++++++++++++++++++++------- 3 files changed, 318 insertions(+), 72 deletions(-) diff --git a/progress.txt b/progress.txt index e104400..b6d8f48 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,82 @@ +## MAS PRD P2 — Step 2: license-layer cleanup [DONE] +- Finishes the source-level split started in Step 1: every Dodo-specific item in license.rs + is now behind #[cfg(not(feature = "mas"))], and compute_status_pure works off a small + cross-build CachedLicense abstraction instead of a Dodo-shaped StoredLicense. The MAS + build no longer drags Dodo Payments / curl / DODO_BASE code into the binary, and the + `cargo check --features mas` 12-warning dead-code spew from Step 1 is gone. +- src-tauri/src/commands/license.rs: + - Gated behind #[cfg(not(feature = "mas"))]: + - Constants CUSTOMER_PORTAL_URL, DODO_BASE, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT (only + Dodo uses this keychain account; MAS uses the separate "mas-entitlement" account in + iap.rs). + - struct StoredLicense (Dodo validation cache). + - read_stored_license / write_stored_license / clear_stored_license keychain helpers. + - enum DodoError + async fn call_dodo_validate (the curl-wrapped POST to Dodo's + /licenses/validate endpoint). + - dodo_error_message / dodo_invalid_key_message UI string helpers. + - pub async fn revalidate_license_background (the 24h re-validation loop spawned by + lib.rs — already cfg-gated at the call site in Step 1, now also at the definition). + - The three Tauri commands activate_license, deactivate_license, open_customer_portal. + - Added enum CachedLicense as the cross-build abstraction for "is there a valid cached + commercial license?": Active is reachable from both builds, Stale is + #[cfg(not(feature = "mas"))]-only since App Store subscriptions have no offline-grace + concept (StoreKit is the source of truth and a lapsed subscription is simply not + entitled — there's no "we used to be entitled, please reconnect"). + - Two new build-specific translator helpers feed the same compute_status_pure: + - direct_cached_license(&StoredLicense, now): Active when validated_at is within the + 14-day window, Stale beyond that. Unparseable validated_at also returns Stale (fail + closed so a corrupt cache forces a fresh validation). + - mas_cached_license(&StoredEntitlement, now): Some(Active) for the non-consumable + lifetime product (expires_at = None) or any subscription whose expires_at is still + in the future. None for expired or unparseable subscription timestamps. + - compute_status_pure rewritten to take Option instead of + Option<&StoredLicense>. The match arm for CachedLicense::Stale is itself + #[cfg(not(feature = "mas"))]-gated, so on the MAS build the match becomes exhaustive + with just the Active arm (no unreachable_patterns warnings, no clippy noise). + - New cfg-gated current_cached_license(now) helper consumes the right keychain entry per + build: read_stored_license() + direct_cached_license() on Direct, + crate::commands::iap::read_stored_entitlement() + mas_cached_license() on MAS. + compute_status (the I/O wrapper called by the Tauri commands) just chains it into + compute_status_pure. + - Wire shape of LicenseStatus is unchanged. revalidationRequired and gracePeriodEnds + remain on the camelCase JSON for both builds, but on MAS they're always false / null — + matching the precedent set in Step 0 (P0) for grace_period_ends. The frontend + LicenseBanner.tsx hits the revalidationRequired branch only when set; on MAS that + branch is just unreachable, no UI change required. +- src-tauri/src/commands/iap.rs: + - Dropped the #[allow(dead_code)] attribute on read_stored_entitlement — it's now wired + into license.rs::current_cached_license under #[cfg(feature = "mas")]. + write_stored_entitlement and clear_stored_entitlement keep their #[allow(dead_code)] + pending Step 3 (objc2-store-kit transaction handler will write/clear when the user + purchases or cancels). +- Tests reorganised inside license.rs `mod tests`: + - 5 build-agnostic status-state tests now take CachedLicense::Active or None directly: + cached_active_is_commercial_no_banner, commercial_detected_shows_banner_immediately, + commercial_detected_banner_hidden_when_dismissed_for_session, + commercial_detected_long_ago_still_shows_banner, + no_cached_license_no_commercial_detection_is_unlicensed_no_banner. + - 7 Direct-only tests under `#[cfg(not(feature = "mas"))] mod direct`: + freshly_validated_key_maps_to_active, key_validated_13_days_ago_still_active, + key_validated_over_14_days_ago_is_stale, unparseable_validated_at_is_stale (new — was + missing coverage for the fail-closed branch), cached_stale_maps_to_revalidation_required, + plus the three Dodo error-message tests. + - 4 new MAS-only tests under `#[cfg(feature = "mas")] mod mas`: + lifetime_entitlement_with_no_expiry_is_active, subscription_future_expiry_is_active, + subscription_past_expiry_is_none, subscription_unparseable_expiry_is_none. +- Verified on both build flavours: + - cargo clippy --all-targets -- -D warnings: clean (Direct). + - cargo clippy --all-targets --features mas -- -D warnings: clean (MAS). + - cargo test: 21 passed on Direct (was 22 in Step 1; 4 IAP serde tests now only compile + on MAS so the Direct total drops by 4, while 3 new Direct-only direct_cached_license + tests bring it back up by 3 — net 21). + - cargo test --features mas: 21 passed on MAS (4 IAP serde tests + 4 new mas:: tests + + 5 build-agnostic status tests + 8 data filter tests). + - cargo check --features mas: 0 warnings (down from 12 in Step 1). + - npm run type-check: clean. + - npm run lint: clean. +- PRD.md P2 section: Step 2 marked [DONE] with the full description of which items moved + behind cfg gates, the CachedLicense abstraction, and the per-build translator helpers. + ## MAS PRD P2 — Step 1: IAP backend scaffold + Dodo/updater feature gating [DONE] - Sets up the source-level boundary between the Direct (Dodo Payments + tauri-plugin-updater) build and the MAS (StoreKit IAP, no in-app updater) build. The Direct build is bit-for-bit diff --git a/src-tauri/src/commands/iap.rs b/src-tauri/src/commands/iap.rs index b38d088..cd3508c 100644 --- a/src-tauri/src/commands/iap.rs +++ b/src-tauri/src/commands/iap.rs @@ -83,7 +83,6 @@ pub struct StoredEntitlement { pub expires_at: Option, } -#[allow(dead_code)] // wired in by the follow-up license-layer refactor (P2) pub(crate) fn read_stored_entitlement() -> Option { let entry = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT_ENTITLEMENT).ok()?; match entry.get_password() { diff --git a/src-tauri/src/commands/license.rs b/src-tauri/src/commands/license.rs index 863994e..c78f7b8 100644 --- a/src-tauri/src/commands/license.rs +++ b/src-tauri/src/commands/license.rs @@ -7,15 +7,19 @@ use tauri::{AppHandle, Manager, State}; use crate::AppState; +#[cfg(not(feature = "mas"))] const CUSTOMER_PORTAL_URL: &str = "https://app.dodopayments.com/customer-portal"; +#[cfg(not(feature = "mas"))] const DODO_BASE: &str = if cfg!(debug_assertions) { "https://test.dodopayments.com" } else { "https://live.dodopayments.com" }; +#[cfg(not(feature = "mas"))] const KEYCHAIN_SERVICE: &str = "app.esploro"; +#[cfg(not(feature = "mas"))] const KEYCHAIN_ACCOUNT: &str = "commercial-license"; const DEFAULT_UI_THEME: &str = "tairiki-light"; @@ -61,12 +65,30 @@ pub struct LicenseStatus { pub revalidation_required: bool, } +#[cfg(not(feature = "mas"))] #[derive(Serialize, Deserialize, Clone, Debug)] struct StoredLicense { license_key: String, validated_at: String, } +/// Cached commercial-license signal, sourced per build flavour. +/// +/// - **Direct** build: populated from the Dodo Payments validation cache +/// (`StoredLicense`). `Active` means the key was validated within the +/// 14-day offline grace window; `Stale` means it has been longer and the +/// user must reconnect to revalidate. +/// - **MAS** build: populated from the StoreKit entitlement cache +/// (`StoredEntitlement`). Only `Active` is reachable — App Store +/// subscriptions are the source of truth, so there is no offline-grace +/// concept and the `Stale` variant is gated out. +#[derive(Debug, Clone, PartialEq, Eq)] +enum CachedLicense { + Active, + #[cfg(not(feature = "mas"))] + Stale, +} + #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct UiPreferences { @@ -137,9 +159,10 @@ pub struct UserPrefs { } // --------------------------------------------------------------------------- -// Keychain helpers +// Keychain helpers (Direct build only — Dodo Payments cache) // --------------------------------------------------------------------------- +#[cfg(not(feature = "mas"))] fn read_stored_license() -> Option { let entry = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT).ok()?; match entry.get_password() { @@ -152,6 +175,7 @@ fn read_stored_license() -> Option { } } +#[cfg(not(feature = "mas"))] fn write_stored_license(stored: &StoredLicense) -> Result<(), String> { let json = serde_json::to_string(stored).map_err(|e| e.to_string())?; let entry = @@ -159,6 +183,7 @@ fn write_stored_license(stored: &StoredLicense) -> Result<(), String> { entry.set_password(&json).map_err(|e| e.to_string()) } +#[cfg(not(feature = "mas"))] fn clear_stored_license() { if let Ok(entry) = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT) { entry.delete_password().ok(); @@ -411,9 +436,10 @@ fn save_prefs(app: &AppHandle, prefs: &UserPrefs) -> Result<(), String> { } // --------------------------------------------------------------------------- -// Dodo Payments validation +// Dodo Payments validation (Direct build only) // --------------------------------------------------------------------------- +#[cfg(not(feature = "mas"))] enum DodoError { InvalidFormat, NetworkOrServer, @@ -421,6 +447,7 @@ enum DodoError { /// Calls `POST /licenses/validate` via the system `curl` binary. /// Returns `Ok(true/false)` based on the `valid` field in Dodo's response. +#[cfg(not(feature = "mas"))] async fn call_dodo_validate(license_key: &str) -> Result { let url = format!("{DODO_BASE}/licenses/validate"); let body = format!("{{\"license_key\":\"{}\"}}", license_key.replace('"', "\\\"")); @@ -472,21 +499,76 @@ async fn call_dodo_validate(license_key: &str) -> Result { Ok(parsed.get("valid").and_then(Value::as_bool).unwrap_or(false)) } +// --------------------------------------------------------------------------- +// Cached-license resolution (per build) +// --------------------------------------------------------------------------- + +/// Direct build: map a Dodo `StoredLicense` to the cross-build +/// `CachedLicense` abstraction. Returns `Active` while inside the 14-day +/// offline grace window, `Stale` afterwards (or if the timestamp is +/// unparseable — fail closed so the user revalidates). +#[cfg(not(feature = "mas"))] +fn direct_cached_license(stored: &StoredLicense, now: chrono::DateTime) -> CachedLicense { + match chrono::DateTime::parse_from_rfc3339(&stored.validated_at) { + Ok(validated_at) => { + let age = now - validated_at.with_timezone(&Utc); + if age < chrono::Duration::days(14) { + CachedLicense::Active + } else { + CachedLicense::Stale + } + } + Err(_) => CachedLicense::Stale, + } +} + +/// MAS build: map a StoreKit `StoredEntitlement` to the cross-build +/// `CachedLicense` abstraction. Returns `Some(Active)` for the +/// non-consumable lifetime product (no `expires_at`) and for subscriptions +/// whose `expires_at` is still in the future. Returns `None` for expired or +/// unparseable subscriptions — App Store rules treat lapsed subscriptions as +/// unentitled, and StoreKit (not our cache) is the source of truth. +#[cfg(feature = "mas")] +fn mas_cached_license( + stored: &crate::commands::iap::StoredEntitlement, + now: chrono::DateTime, +) -> Option { + match stored.expires_at.as_deref() { + None => Some(CachedLicense::Active), + Some(expiry) => match chrono::DateTime::parse_from_rfc3339(expiry) { + Ok(exp) if exp.with_timezone(&Utc) > now => Some(CachedLicense::Active), + _ => None, + }, + } +} + +/// Read the cached license signal from the appropriate keychain entry for +/// the current build flavour. +#[cfg(not(feature = "mas"))] +fn current_cached_license(now: chrono::DateTime) -> Option { + read_stored_license().map(|stored| direct_cached_license(&stored, now)) +} + +#[cfg(feature = "mas")] +fn current_cached_license(now: chrono::DateTime) -> Option { + crate::commands::iap::read_stored_entitlement() + .and_then(|stored| mas_cached_license(&stored, now)) +} + // --------------------------------------------------------------------------- // Status computation // --------------------------------------------------------------------------- /// Pure status computation — no I/O; accepts all inputs as parameters. fn compute_status_pure( - stored: Option<&StoredLicense>, + cached: Option, prefs: &UserPrefs, banner_dismissed: bool, now: chrono::DateTime, ) -> LicenseStatus { - if let Some(stored) = stored { - if let Ok(validated_at) = chrono::DateTime::parse_from_rfc3339(&stored.validated_at) { - let age = now - validated_at.with_timezone(&Utc); - if age < chrono::Duration::days(14) { + if let Some(cached) = cached { + match cached { + CachedLicense::Active => { return LicenseStatus { tier: LicenseTier::Commercial, banner_visible: false, @@ -495,14 +577,16 @@ fn compute_status_pure( revalidation_required: false, }; } - // Key exists but offline too long — revert to Unlicensed - return LicenseStatus { - tier: LicenseTier::Unlicensed, - banner_visible: false, - grace_period_ends: None, - show_usage_dialog: false, - revalidation_required: true, - }; + #[cfg(not(feature = "mas"))] + CachedLicense::Stale => { + return LicenseStatus { + tier: LicenseTier::Unlicensed, + banner_visible: false, + grace_period_ends: None, + show_usage_dialog: false, + revalidation_required: true, + }; + } } } @@ -542,14 +626,16 @@ fn compute_status_pure( /// Returns status from cached state only — no network calls. fn compute_status(app: &AppHandle, banner_dismissed: bool) -> LicenseStatus { let prefs = load_prefs(app); - let stored = read_stored_license(); - compute_status_pure(stored.as_ref(), &prefs, banner_dismissed, Utc::now()) + let now = Utc::now(); + let cached = current_cached_license(now); + compute_status_pure(cached, &prefs, banner_dismissed, now) } // --------------------------------------------------------------------------- -// Error message helpers +// Error message helpers (Direct build only) // --------------------------------------------------------------------------- +#[cfg(not(feature = "mas"))] fn dodo_error_message(error: &DodoError) -> String { match error { DodoError::InvalidFormat => { @@ -561,16 +647,18 @@ fn dodo_error_message(error: &DodoError) -> String { } } +#[cfg(not(feature = "mas"))] fn dodo_invalid_key_message() -> &'static str { "License key is not valid or has expired — check your subscription in the customer portal" } // --------------------------------------------------------------------------- -// Background re-validation +// Background re-validation (Direct build only) // --------------------------------------------------------------------------- /// Re-validates the stored license key against Dodo if it is older than 24 hours. /// Called on launch and then every 24 hours by the background task in lib.rs. +#[cfg(not(feature = "mas"))] pub async fn revalidate_license_background(app: AppHandle) { let Some(stored) = read_stored_license() else { return; @@ -625,6 +713,7 @@ pub async fn get_license_status( Ok(compute_status(&app, dismissed)) } +#[cfg(not(feature = "mas"))] #[tauri::command] pub async fn activate_license( app: AppHandle, @@ -646,6 +735,7 @@ pub async fn activate_license( } } +#[cfg(not(feature = "mas"))] #[tauri::command] pub async fn deactivate_license( app: AppHandle, @@ -694,6 +784,7 @@ pub async fn notify_connection_count( Ok(compute_status(&app, dismissed)) } +#[cfg(not(feature = "mas"))] #[tauri::command] pub fn open_customer_portal() -> Result<(), String> { std::process::Command::new("open") @@ -773,42 +864,17 @@ mod tests { } } - fn stored(validated_at: chrono::DateTime) -> StoredLicense { - StoredLicense { - license_key: "test-key".to_string(), - validated_at: validated_at.to_rfc3339(), - } - } - - // -- State-machine transitions -- + // -- Status-state transitions (build-agnostic) -- #[test] - fn freshly_validated_key_is_commercial() { + fn cached_active_is_commercial_no_banner() { let now = Utc::now(); - let s = stored(now - Duration::hours(1)); - let status = compute_status_pure(Some(&s), &base_prefs(), false, now); + let status = + compute_status_pure(Some(CachedLicense::Active), &base_prefs(), false, now); assert_eq!(status.tier, LicenseTier::Commercial); assert!(!status.banner_visible); assert!(!status.revalidation_required); - } - - #[test] - fn key_validated_13_days_ago_is_still_commercial() { - let now = Utc::now(); - let s = stored(now - Duration::days(13)); - let status = compute_status_pure(Some(&s), &base_prefs(), false, now); - assert_eq!(status.tier, LicenseTier::Commercial); - assert!(!status.revalidation_required); - } - - #[test] - fn key_validated_over_14_days_ago_requires_revalidation() { - let now = Utc::now(); - let s = stored(now - Duration::days(15)); - let status = compute_status_pure(Some(&s), &base_prefs(), false, now); - assert_eq!(status.tier, LicenseTier::Unlicensed); - assert!(status.revalidation_required); - assert!(!status.banner_visible); + assert!(status.grace_period_ends.is_none()); } #[test] @@ -848,7 +914,7 @@ mod tests { } #[test] - fn no_stored_license_no_commercial_detection_is_unlicensed_no_banner() { + fn no_cached_license_no_commercial_detection_is_unlicensed_no_banner() { let now = Utc::now(); let status = compute_status_pure(None, &base_prefs(), false, now); assert_eq!(status.tier, LicenseTier::Unlicensed); @@ -856,30 +922,132 @@ mod tests { assert!(!status.revalidation_required); } - // -- Error-code → message mapping -- + // -- Direct-only: Dodo cache mapping + error messages -- - #[test] - fn invalid_format_error_message() { - assert_eq!( - dodo_error_message(&DodoError::InvalidFormat), - "Invalid license key format — check for typos" - ); - } + #[cfg(not(feature = "mas"))] + mod direct { + use super::*; - #[test] - fn network_error_message() { - assert_eq!( - dodo_error_message(&DodoError::NetworkOrServer), - "Could not reach the license server — check your connection and try again" - ); - } + fn stored(validated_at: chrono::DateTime) -> StoredLicense { + StoredLicense { + license_key: "test-key".to_string(), + validated_at: validated_at.to_rfc3339(), + } + } - #[test] - fn valid_false_message() { - assert_eq!( - dodo_invalid_key_message(), - "License key is not valid or has expired — check your subscription in the customer portal" - ); + #[test] + fn freshly_validated_key_maps_to_active() { + let now = Utc::now(); + let cached = direct_cached_license(&stored(now - Duration::hours(1)), now); + assert_eq!(cached, CachedLicense::Active); + } + + #[test] + fn key_validated_13_days_ago_still_active() { + let now = Utc::now(); + let cached = direct_cached_license(&stored(now - Duration::days(13)), now); + assert_eq!(cached, CachedLicense::Active); + } + + #[test] + fn key_validated_over_14_days_ago_is_stale() { + let now = Utc::now(); + let cached = direct_cached_license(&stored(now - Duration::days(15)), now); + assert_eq!(cached, CachedLicense::Stale); + } + + #[test] + fn unparseable_validated_at_is_stale() { + let stored = StoredLicense { + license_key: "test-key".to_string(), + validated_at: "garbage".to_string(), + }; + assert_eq!( + direct_cached_license(&stored, Utc::now()), + CachedLicense::Stale + ); + } + + #[test] + fn cached_stale_maps_to_revalidation_required() { + let now = Utc::now(); + let status = + compute_status_pure(Some(CachedLicense::Stale), &base_prefs(), false, now); + assert_eq!(status.tier, LicenseTier::Unlicensed); + assert!(status.revalidation_required); + assert!(!status.banner_visible); + } + + #[test] + fn invalid_format_error_message() { + assert_eq!( + dodo_error_message(&DodoError::InvalidFormat), + "Invalid license key format — check for typos" + ); + } + + #[test] + fn network_error_message() { + assert_eq!( + dodo_error_message(&DodoError::NetworkOrServer), + "Could not reach the license server — check your connection and try again" + ); + } + + #[test] + fn valid_false_message() { + assert_eq!( + dodo_invalid_key_message(), + "License key is not valid or has expired — check your subscription in the customer portal" + ); + } } + // -- MAS-only: StoreKit entitlement mapping -- + + #[cfg(feature = "mas")] + mod mas { + use super::*; + use crate::commands::iap::StoredEntitlement; + + #[test] + fn lifetime_entitlement_with_no_expiry_is_active() { + let now = Utc::now(); + let stored = StoredEntitlement { + product_id: "app.esploro.personal.lifetime".to_string(), + expires_at: None, + }; + assert_eq!(mas_cached_license(&stored, now), Some(CachedLicense::Active)); + } + + #[test] + fn subscription_future_expiry_is_active() { + let now = Utc::now(); + let stored = StoredEntitlement { + product_id: "app.esploro.business.annual".to_string(), + expires_at: Some((now + Duration::days(30)).to_rfc3339()), + }; + assert_eq!(mas_cached_license(&stored, now), Some(CachedLicense::Active)); + } + + #[test] + fn subscription_past_expiry_is_none() { + let now = Utc::now(); + let stored = StoredEntitlement { + product_id: "app.esploro.personal.annual".to_string(), + expires_at: Some((now - Duration::days(1)).to_rfc3339()), + }; + assert_eq!(mas_cached_license(&stored, now), None); + } + + #[test] + fn subscription_unparseable_expiry_is_none() { + let now = Utc::now(); + let stored = StoredEntitlement { + product_id: "app.esploro.personal.annual".to_string(), + expires_at: Some("not-a-date".to_string()), + }; + assert_eq!(mas_cached_license(&stored, now), None); + } + } } From c7190a9ef75f6e1d7c21f1a3c061f349d1891707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Mon, 18 May 2026 17:17:19 +0200 Subject: [PATCH 5/8] feat(mas): wire StoreKit 1 IAP backend via objc2-store-kit 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 --- Cargo.lock | 17 + progress.txt | 155 +++++++ src-tauri/Cargo.toml | 11 +- src-tauri/src/commands/iap.rs | 46 +- src-tauri/src/commands/iap_storekit.rs | 558 +++++++++++++++++++++++++ src-tauri/src/commands/mod.rs | 2 + src-tauri/src/lib.rs | 11 + 7 files changed, 791 insertions(+), 9 deletions(-) create mode 100644 src-tauri/src/commands/iap_storekit.rs diff --git a/Cargo.lock b/Cargo.lock index 92bbf85..33d0949 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1472,6 +1472,9 @@ dependencies = [ "deadpool-postgres", "keyring", "mysql_async", + "objc2", + "objc2-foundation", + "objc2-store-kit", "serde", "serde_json", "tauri", @@ -3430,6 +3433,20 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-store-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a1cef520f802b637e2cca72d7dfd2f17cfff947fb5f802dd2d8c68e6c63072" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", +] + [[package]] name = "objc2-system-configuration" version = "0.3.2" diff --git a/progress.txt b/progress.txt index b6d8f48..e4706eb 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,158 @@ +## MAS PRD P2 — Step 3: objc2-store-kit wiring [DONE] +- Replaces the four iap_* command stubs from Step 1 with a real StoreKit 1 + backend, wired through objc2-store-kit (pure-Rust bindings, no Swift + plugin). The MAS binary can now fetch product metadata, kick off purchases + through the App Store payment sheet, restore prior transactions, and + surface the current entitlement to the frontend. The Direct (GitHub/Homebrew) + build is bit-for-bit unchanged — the new dependencies are gated to + --features mas + target_os = "macos". +- src-tauri/Cargo.toml: + - [features].mas now lists "dep:objc2", "dep:objc2-foundation", + "dep:objc2-store-kit" so enabling the feature pulls them in. + - New [target.'cfg(target_os = "macos")'.dependencies] block adds the three + crates as optional. They're target-gated so a hypothetical Linux/Windows + cargo check doesn't try to compile them. objc2 = "0.6", objc2-foundation + = "0.3", objc2-store-kit = "0.3" — default features for all three (they + each enable their own NS* / SK* feature flags by default, which is what + we need for NSString/NSDate/NSDecimalNumber/NSNumberFormatter and the + SK* types used here). +- src-tauri/src/commands/iap_storekit.rs (NEW, ~430 lines, #![allow(deprecated)] + because every StoreKit 1 symbol upstream is #[deprecated] in favour of + StoreKit 2 / Swift Product — migration is the future ADR boundary): + - DelegateState ivar struct holds three Mutex> oneshot slots + (pending_products, pending_purchase, pending_restore), a Vec> + cache (so we can re-use SKProduct objects across fetch_products / + purchase calls and read SKProductSubscriptionPeriod for expiry math), + and a Mutex>> that keeps the in-flight + request alive until its delegate callback fires. + - EsploroStoreKitDelegate is defined via objc2::define_class! with + #[unsafe(super(NSObject))], #[name = "EsploroStoreKitDelegate"] (explicit + Obj-C runtime name so Apple's review tools see a stable symbol), and + #[ivars = DelegateState]. It conforms to three protocols: + * SKRequestDelegate — request:didFailWithError: routes SKProductsRequest + failures back through the pending_products oneshot. + * SKProductsRequestDelegate — productsRequest:didReceiveResponse: + walks SKProductsResponse.products(), turns each SKProduct into an + IapProduct wire value (via NSNumberFormatter with CurrencyStyle + + product.priceLocale for the localised price string), stores the + Retaineds in the cache, and resolves the pending oneshot. + * SKPaymentTransactionObserver — paymentQueue:updatedTransactions: + iterates transactions; Purchased and Restored both write a fresh + StoredEntitlement to the Keychain (via iap::write_stored_entitlement) + and call finishTransaction:. Purchased additionally resolves the + pending_purchase oneshot with status="purchased" iff the + productIdentifier matches the in-flight purchase. Failed inspects + txn.error().code() against SKErrorCode::PaymentCancelled (NSInteger + = 2) to distinguish status="cancelled" from status="failed". + paymentQueueRestoreCompletedTransactionsFinished: resolves the + pending_restore oneshot with the running restored_any bool; + paymentQueue:restoreCompletedTransactionsFailedWithError: resolves it + with the NSError.localizedDescription wrapped as Err. + - Manager singleton (held in static OnceLock): allocates the + delegate via EsploroStoreKitDelegate::new() and calls + SKPaymentQueue::defaultQueue().addTransactionObserver(...) exactly once. + Apple's docs require the observer be installed at app launch so + transactions delivered while the app is starting up aren't dropped — + install_observer_on_startup(MainThreadMarker) is the public entry point + called from lib.rs's setup() hook for that. The MainThreadMarker + parameter is unused at runtime but documents that the caller must be on + the AppKit main thread (which Tauri's setup is). + - Public async API (consumed by iap.rs): + * fetch_products(ids: Vec) -> Result, String> + * purchase(product_id: String) -> Result + (fetches and caches the SKProduct first if it isn't already cached, + guards on SKPaymentQueue::canMakePayments()) + * restore() -> Result + Each grabs a oneshot::Sender slot, kicks off the StoreKit operation + (start(), addPayment:, restoreCompletedTransactions), and awaits the + delegate callback. Re-entrant calls (two purchases / two restores in + flight) return Err("Another … is already in progress") rather than + trampling the existing sender. + - Helpers: + * compute_expires_at(product_id, txn_date: NSDate, cached_products): + looks up the SKProduct, reads subscriptionPeriod() (None for + non-consumables like the lifetime product), and adds + numberOfUnits * unit (Day/Week/Month/Year) to txn_date using + chrono::Months (for Month/Year — calendar-correct, handles + end-of-month rollover) and chrono::Duration (for Day/Week). Lifetime + purchases get expires_at = None. + * format_price(NSDecimalNumber, NSLocale): NSNumberFormatter with + CurrencyStyle and the SKProduct's priceLocale yields strings like + "$129.00", "€49,00", "¥7,800" — exactly what the frontend wants + without an Intl round-trip. +- src-tauri/src/commands/iap.rs: + - The four #[tauri::command] stubs (iap_get_products, iap_purchase, + iap_restore, iap_check_entitlement) now call into iap_storekit. + - New const PRODUCT_IDS: &[&str; 3] hard-codes the three App Store Connect + product identifiers (app.esploro.personal.lifetime, + app.esploro.personal.annual, app.esploro.business.annual). iap_get_products + passes them straight to iap_storekit::fetch_products — the App Store + rejects any IDs not registered on the listing, so there's no value in + making this client-driven. + - iap_check_entitlement reads the cached StoredEntitlement from the + Keychain (via the existing read_stored_entitlement helper, now no + longer #[allow(dead_code)] since it's actually called), then decides + entitled by comparing expires_at to chrono::Utc::now(). Non-consumable + lifetime products (expires_at = None) are always entitled; subscriptions + with a future expiry are entitled; past/unparseable timestamps are not. + This matches the mas_cached_license logic in license.rs (Step 2) but at + a different layer — license.rs makes the LicenseStatus decision, + iap_check_entitlement just reports the raw cached entitlement so the + frontend can show the "Manage Subscription" / "Get a License" UI in + Settings. + - write_stored_entitlement is no longer #[allow(dead_code)] because the + transaction observer in iap_storekit calls it on every Purchased / + Restored transaction. clear_stored_entitlement keeps its + #[allow(dead_code)] pending Step 4's "manage subscription" UI hook. +- src-tauri/src/commands/mod.rs: added `pub mod iap_storekit;` behind + #[cfg(feature = "mas")]. +- src-tauri/src/lib.rs: setup() hook now has a #[cfg(feature = "mas")] block + that grabs objc2::MainThreadMarker::new() (asserts main thread, which + Tauri's setup is) and calls iap_storekit::install_observer_on_startup, + which forces the OnceLock singleton + transaction observer to be + ready before the webview loads. This mirrors the existing + #[cfg(not(feature = "mas"))] revalidate_license_background loop. +- Tests: + - 5 new unit tests in iap_storekit::tests cover add_period across all + SKProductPeriodUnit variants: + * add_period_year_adds_twelve_months + * add_period_month_adds_calendar_month (3 months from 2026-05-18 → + 2026-08-18, exercising chrono's calendar-aware month arithmetic) + * add_period_week_adds_seven_days_per_unit (2 weeks → +14 days) + * add_period_day_adds_n_days + * add_period_unknown_unit_returns_none (fail-closed guard for the + unreachable-in-practice catch-all arm) + These are the only iap_storekit logic that can be exercised without a + live StoreKit session; everything else (delegate callbacks, SKPayment + flow) needs a sandbox App Store Connect account + signed MAS build, which + is a Step 4 / TestFlight concern. + - cargo test: 21 passed on Direct (unchanged), 26 passed on MAS + (+5 add_period tests). + - cargo clippy --all-targets -- -D warnings: clean (Direct). + - cargo clippy --all-targets --features mas -- -D warnings: clean (MAS). + - cargo check --features mas: clean. + - npm run type-check, npm run lint: clean. +- Known limitations (deferred to Step 4 / submission time): + - Live StoreKit testing requires sandbox accounts in App Store Connect and + a packaged .pkg uploaded to TestFlight. The Rust code is wired and + type-checks; verifying that the payment sheet actually appears and that + Purchased / Restored transactions resolve correctly is a manual test + against a sandbox account. + - Receipt validation: StoreKit 1 stores a local receipt at + Bundle.main.appStoreReceiptURL. We currently trust SKPaymentTransactions + delivered by the observer rather than parsing the receipt — sufficient + for IAP at this scale (no server-side receipt validation is needed per + the PRD's Known Risks section). If we later want offline-revocable + entitlement, SKReceiptRefreshRequest is the entry point (the binding is + pulled in but unused at this step). + - The objc2-store-kit bindings are all #[deprecated] because Apple moved + everything to Swift Product / Transaction APIs. The migration boundary + is the four iap_* commands — the frontend won't notice. ADR 09 + (plans/09-storekit-objc2.md) covers the reasoning for staying on + StoreKit 1 for the initial MAS submission. +- PRD.md P2 section: Step 3 marked [DONE] with the full implementation + description; Step 4 (frontend PurchaseSheet) remains pending. + ## MAS PRD P2 — Step 2: license-layer cleanup [DONE] - Finishes the source-level split started in Step 1: every Dodo-specific item in license.rs is now behind #[cfg(not(feature = "mas"))], and compute_status_pure works off a small diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cca7c68..01fbe2a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -30,7 +30,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] # 3. Restore `Cargo.toml`. # This is intentionally a CI-side concern, not a developer ergonomic, so the # day-to-day `cargo tauri dev` keeps working unchanged. -mas = [] +mas = ["dep:objc2", "dep:objc2-foundation", "dep:objc2-store-kit"] [build-dependencies] tauri-build = { version = "2", features = [] } @@ -48,3 +48,12 @@ keyring = "2" chrono = { version = "0.4", features = ["serde"] } tauri-plugin-updater = "2" tauri-plugin-process = "2" + +# StoreKit 1 bindings for the MAS build. Pulled in only when --features mas is +# active (see [features].mas above). The crates are macOS-only by their own +# target cfg, so leaving them as default-disabled keeps Linux/Windows CI +# unaffected even though we don't target those for the desktop app. +[target.'cfg(target_os = "macos")'.dependencies] +objc2 = { version = "0.6", optional = true } +objc2-foundation = { version = "0.3", optional = true } +objc2-store-kit = { version = "0.3", optional = true } diff --git a/src-tauri/src/commands/iap.rs b/src-tauri/src/commands/iap.rs index cd3508c..4de26c3 100644 --- a/src-tauri/src/commands/iap.rs +++ b/src-tauri/src/commands/iap.rs @@ -16,10 +16,20 @@ use serde::{Deserialize, Serialize}; +use super::iap_storekit; + const KEYCHAIN_SERVICE: &str = "app.esploro"; const KEYCHAIN_ACCOUNT_ENTITLEMENT: &str = "mas-entitlement"; -const NOT_IMPLEMENTED: &str = "IAP backend not yet implemented"; +/// IAP product identifiers registered in App Store Connect. The MAS build +/// queries these three on every `iap_get_products` call; the App Store will +/// reject any IDs not configured on the listing so the client side just +/// hard-codes the canonical list. +pub const PRODUCT_IDS: &[&str] = &[ + "app.esploro.personal.lifetime", + "app.esploro.personal.annual", + "app.esploro.business.annual", +]; // --------------------------------------------------------------------------- // Wire types — kept in sync with the PRD's `iap_*` command return shapes. @@ -95,7 +105,6 @@ pub(crate) fn read_stored_entitlement() -> Option { } } -#[allow(dead_code)] pub(crate) fn write_stored_entitlement(stored: &StoredEntitlement) -> Result<(), String> { let json = serde_json::to_string(stored).map_err(|e| e.to_string())?; let entry = keyring::Entry::new(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT_ENTITLEMENT) @@ -111,28 +120,49 @@ pub(crate) fn clear_stored_entitlement() { } // --------------------------------------------------------------------------- -// Tauri commands — stubs until the StoreKit integration lands. +// Tauri commands — delegate to `iap_storekit` for the live StoreKit work and +// translate cached entitlement state for the entitlement check. // --------------------------------------------------------------------------- #[tauri::command] pub async fn iap_get_products() -> Result, String> { - Err(NOT_IMPLEMENTED.to_string()) + iap_storekit::fetch_products(PRODUCT_IDS.iter().map(|s| s.to_string()).collect()).await } #[tauri::command] pub async fn iap_purchase(product_id: String) -> Result { - let _ = product_id; - Err(NOT_IMPLEMENTED.to_string()) + iap_storekit::purchase(product_id).await } #[tauri::command] pub async fn iap_restore() -> Result { - Err(NOT_IMPLEMENTED.to_string()) + iap_storekit::restore().await } +/// Reads the cached entitlement from the Keychain and translates it into the +/// wire shape the frontend consumes. Subscription expiry is checked against +/// `Utc::now()` so a lapsed subscription is reported as `entitled: false` +/// without having to walk the StoreKit transaction queue. Fresh transactions +/// (renewals, restores) flow through the `SKPaymentTransactionObserver` in +/// `iap_storekit` and update this cache on the fly. #[tauri::command] pub async fn iap_check_entitlement() -> Result { - Err(NOT_IMPLEMENTED.to_string()) + let Some(stored) = read_stored_entitlement() else { + return Ok(IapEntitlement::default()); + }; + let now = chrono::Utc::now(); + let entitled = match stored.expires_at.as_deref() { + None => true, // Non-consumable (lifetime) — always entitled. + Some(raw) => match chrono::DateTime::parse_from_rfc3339(raw) { + Ok(dt) => dt.with_timezone(&chrono::Utc) > now, + Err(_) => false, + }, + }; + Ok(IapEntitlement { + entitled, + product_id: Some(stored.product_id), + expires_at: stored.expires_at, + }) } #[cfg(test)] diff --git a/src-tauri/src/commands/iap_storekit.rs b/src-tauri/src/commands/iap_storekit.rs new file mode 100644 index 0000000..89d321b --- /dev/null +++ b/src-tauri/src/commands/iap_storekit.rs @@ -0,0 +1,558 @@ +//! StoreKit 1 (SKProductsRequest / SKPaymentQueue) wiring for the MAS build. +//! +//! This module is compiled only when `--features mas` is active and on +//! `target_os = "macos"` (see Cargo.toml). +//! +//! It owns a single Obj-C delegate instance (`EsploroStoreKitDelegate`) that +//! conforms to: +//! - `SKProductsRequestDelegate` — fetches localised product metadata +//! - `SKRequestDelegate` (supertrait) — handles request-level errors +//! - `SKPaymentTransactionObserver` — receives purchase/restore updates +//! +//! The delegate is registered with `SKPaymentQueue.defaultQueue` exactly once +//! per process via a `OnceLock`. From that point on, every transaction the +//! payment queue delivers — including pending transactions re-queued from a +//! previous app launch, and renewal transactions for active subscriptions — +//! flows through `payment_queue_updated_transactions`, which updates the +//! cached `StoredEntitlement` in the Keychain and resolves any in-flight +//! purchase/restore request waiting on a Tokio oneshot channel. +//! +//! Tauri commands (declared in `iap.rs`) run on the Tokio runtime and call +//! into this module's async functions. The async functions install a oneshot +//! sender in the shared `DelegateState`, kick off the StoreKit operation, and +//! await the response that the Obj-C callbacks push back through that sender. +//! StoreKit 1 delivers all its callbacks on the main thread; the channels +//! cross that thread boundary safely. +//! +//! Every StoreKit 1 symbol used here is `#[deprecated]` upstream (Apple +//! marked the whole API in favour of StoreKit 2's Swift `Product` API). +//! The `#![allow(deprecated)]` at the top of the module silences those +//! warnings — the migration to StoreKit 2 / a Swift plugin is captured as +//! a future ADR (see `plans/09-storekit-objc2.md`). +#![allow(deprecated)] + +use std::sync::{Mutex, OnceLock}; + +use chrono::{DateTime, Months, Utc}; +use objc2::rc::Retained; +use objc2::runtime::ProtocolObject; +use objc2::{define_class, msg_send, AnyThread, DefinedClass, MainThreadMarker}; +use objc2_foundation::{ + NSArray, NSDate, NSDecimalNumber, NSError, NSLocale, NSNumberFormatter, NSNumberFormatterStyle, + NSObject, NSObjectProtocol, NSSet, NSString, +}; +use objc2_store_kit::{ + SKErrorCode, SKPayment, SKPaymentQueue, SKPaymentTransaction, SKPaymentTransactionObserver, + SKPaymentTransactionState, SKProduct, SKProductPeriodUnit, SKProductsRequest, + SKProductsRequestDelegate, SKProductsResponse, SKRequest, SKRequestDelegate, +}; +use tokio::sync::oneshot; + +use super::iap::{ + write_stored_entitlement, IapProduct, IapPurchaseResult, IapPurchaseStatus, IapRestoreResult, + StoredEntitlement, +}; + +// --------------------------------------------------------------------------- +// Pending-operation state owned by the delegate's ivars. +// --------------------------------------------------------------------------- + +struct PendingPurchase { + product_id: String, + sender: oneshot::Sender>, +} + +struct PendingRestore { + sender: oneshot::Sender>, + restored_any: bool, +} + +type ProductsSender = oneshot::Sender, String>>; + +pub struct DelegateState { + /// Active products request — one at a time. `start()` is non-blocking and + /// fires `productsRequest:didReceiveResponse:` (or the SKRequestDelegate + /// failure callback) which resolves this oneshot. + pending_products: Mutex>, + /// Active purchase — at most one. Resolved when a transaction with the + /// matching `productIdentifier` reaches `Purchased`/`Failed`. Other + /// (background) transactions for the same product are still observed and + /// finished, they just don't satisfy this future. + pending_purchase: Mutex>, + /// Active restore — at most one. Resolved by either + /// `paymentQueueRestoreCompletedTransactionsFinished:` (success, possibly + /// with zero restored transactions) or the corresponding failure + /// callback. + pending_restore: Mutex>, + /// `SKProduct` objects cached from the most recent products request. We + /// hold these to (a) initiate purchases (need the `SKProduct`, not just + /// the identifier, for `SKPayment.paymentWithProduct:`) and (b) read + /// `subscriptionPeriod` when computing expiry timestamps for cached + /// entitlements. + cached_products: Mutex>>, + /// The in-flight `SKProductsRequest`, retained so it isn't released + /// before its delegate callback fires. + active_request: Mutex>>, +} + +// --------------------------------------------------------------------------- +// Custom delegate class — implements three Obj-C protocols. +// --------------------------------------------------------------------------- + +define_class!( + /// Single instance, owned by `Manager`, registered as the + /// `SKPaymentQueue.defaultQueue` transaction observer for the life of the + /// process. + /// + /// SAFETY: + /// - Superclass is plain `NSObject` (no subclassing requirements). + /// - We do not implement `Drop`. The Obj-C runtime is allowed to call + /// `dealloc` from any thread; our ivars are `Send + Sync` (mutex-wrapped + /// tokio oneshots and `Retained` / `Retained`, + /// the latter two of which the objc2-store-kit bindings explicitly mark + /// `Send + Sync`). + #[unsafe(super(NSObject))] + #[name = "EsploroStoreKitDelegate"] + #[ivars = DelegateState] + pub struct EsploroStoreKitDelegate; + + unsafe impl NSObjectProtocol for EsploroStoreKitDelegate {} + + unsafe impl SKRequestDelegate for EsploroStoreKitDelegate { + #[unsafe(method(request:didFailWithError:))] + fn request_did_fail_with_error(&self, _request: &SKRequest, error: &NSError) { + let msg = format_ns_error(error); + if let Some(tx) = self.ivars().pending_products.lock().unwrap().take() { + let _ = tx.send(Err(msg)); + } + *self.ivars().active_request.lock().unwrap() = None; + } + } + + unsafe impl SKProductsRequestDelegate for EsploroStoreKitDelegate { + #[unsafe(method(productsRequest:didReceiveResponse:))] + fn products_request_did_receive_response( + &self, + _request: &SKProductsRequest, + response: &SKProductsResponse, + ) { + let products = unsafe { response.products() }; + let mut wire = Vec::with_capacity(products.len()); + let mut retained: Vec> = Vec::with_capacity(products.len()); + for product in products.iter() { + if let Some(iap) = product_to_wire(&product) { + wire.push(iap); + } + retained.push(product.clone()); + } + *self.ivars().cached_products.lock().unwrap() = retained; + if let Some(tx) = self.ivars().pending_products.lock().unwrap().take() { + let _ = tx.send(Ok(wire)); + } + *self.ivars().active_request.lock().unwrap() = None; + } + } + + unsafe impl SKPaymentTransactionObserver for EsploroStoreKitDelegate { + #[unsafe(method(paymentQueue:updatedTransactions:))] + fn payment_queue_updated_transactions( + &self, + queue: &SKPaymentQueue, + transactions: &NSArray, + ) { + self.handle_updated_transactions(queue, transactions); + } + + #[unsafe(method(paymentQueueRestoreCompletedTransactionsFinished:))] + fn payment_queue_restore_completed_transactions_finished(&self, _queue: &SKPaymentQueue) { + if let Some(state) = self.ivars().pending_restore.lock().unwrap().take() { + let _ = state.sender.send(Ok(state.restored_any)); + } + } + + #[unsafe(method(paymentQueue:restoreCompletedTransactionsFailedWithError:))] + fn payment_queue_restore_completed_transactions_failed_with_error( + &self, + _queue: &SKPaymentQueue, + error: &NSError, + ) { + let msg = format_ns_error(error); + if let Some(state) = self.ivars().pending_restore.lock().unwrap().take() { + let _ = state.sender.send(Err(msg)); + } + } + } +); + +impl EsploroStoreKitDelegate { + fn new() -> Retained { + let state = DelegateState { + pending_products: Mutex::new(None), + pending_purchase: Mutex::new(None), + pending_restore: Mutex::new(None), + cached_products: Mutex::new(Vec::new()), + active_request: Mutex::new(None), + }; + let this = Self::alloc().set_ivars(state); + unsafe { msg_send![super(this), init] } + } + + fn handle_updated_transactions( + &self, + queue: &SKPaymentQueue, + transactions: &NSArray, + ) { + for txn in transactions.iter() { + let state = unsafe { txn.transactionState() }; + match state { + SKPaymentTransactionState::Purchasing | SKPaymentTransactionState::Deferred => { + continue + } + SKPaymentTransactionState::Purchased + | SKPaymentTransactionState::Restored => { + let payment = unsafe { txn.payment() }; + let product_id_ns = unsafe { payment.productIdentifier() }; + let product_id = product_id_ns.to_string(); + let txn_date = unsafe { txn.transactionDate() }; + let entitlement = self + .entitlement_from_transaction(&product_id, txn_date.as_deref()); + let _ = write_stored_entitlement(&entitlement); + + if state == SKPaymentTransactionState::Purchased { + self.resolve_purchase( + &product_id, + Ok(IapPurchaseResult { + status: IapPurchaseStatus::Purchased, + }), + ); + } else { + let mut pending = self.ivars().pending_restore.lock().unwrap(); + if let Some(s) = pending.as_mut() { + s.restored_any = true; + } + } + unsafe { queue.finishTransaction(&txn); } + } + SKPaymentTransactionState::Failed => { + let payment = unsafe { txn.payment() }; + let product_id_ns = unsafe { payment.productIdentifier() }; + let product_id = product_id_ns.to_string(); + let cancelled = unsafe { txn.error() } + .map(|e| e.code() == SKErrorCode::PaymentCancelled.0) + .unwrap_or(false); + let status = if cancelled { + IapPurchaseStatus::Cancelled + } else { + IapPurchaseStatus::Failed + }; + self.resolve_purchase(&product_id, Ok(IapPurchaseResult { status })); + unsafe { queue.finishTransaction(&txn); } + } + _ => continue, + } + } + } + + fn resolve_purchase( + &self, + product_id: &str, + result: Result, + ) { + let mut pending = self.ivars().pending_purchase.lock().unwrap(); + let matches = pending + .as_ref() + .map(|p| p.product_id == product_id) + .unwrap_or(false); + if matches { + if let Some(p) = pending.take() { + let _ = p.sender.send(result); + } + } + } + + fn entitlement_from_transaction( + &self, + product_id: &str, + txn_date: Option<&NSDate>, + ) -> StoredEntitlement { + let cached = self.ivars().cached_products.lock().unwrap(); + StoredEntitlement { + product_id: product_id.to_string(), + expires_at: compute_expires_at(product_id, txn_date, &cached), + } + } +} + +// --------------------------------------------------------------------------- +// Singleton manager + lazy-install of the transaction observer. +// --------------------------------------------------------------------------- + +pub struct Manager { + delegate: Retained, +} + +// SAFETY: `EsploroStoreKitDelegate`'s ivars are all `Send + Sync` (mutexes +// containing oneshot senders + Retained/Retained, +// both of which the bindings mark `Send + Sync`). The `Retained<>` wrapper is +// `Send + Sync` iff its target is. Holding the manager in a static `OnceLock` +// across threads is therefore sound. +unsafe impl Send for Manager {} +unsafe impl Sync for Manager {} + +static MANAGER: OnceLock = OnceLock::new(); + +fn manager() -> &'static Manager { + MANAGER.get_or_init(|| { + let delegate = EsploroStoreKitDelegate::new(); + unsafe { + // `SKPaymentQueue.addTransactionObserver:` strongly retains the + // observer for the queue's lifetime; we additionally hold one + // reference on the manager to keep our Rust-side handle valid. + let queue = SKPaymentQueue::defaultQueue(); + queue.addTransactionObserver(ProtocolObject::from_ref(&*delegate)); + } + Manager { delegate } + }) +} + +// --------------------------------------------------------------------------- +// Public API consumed by `iap.rs`. +// --------------------------------------------------------------------------- + +pub async fn fetch_products(ids: Vec) -> Result, String> { + let mgr = manager(); + let (tx, rx) = oneshot::channel(); + { + let mut pending = mgr.delegate.ivars().pending_products.lock().unwrap(); + if pending.is_some() { + return Err("Another products fetch is already in progress".to_string()); + } + *pending = Some(tx); + } + + unsafe { + let ns_ids: Vec> = ids.iter().map(|s| NSString::from_str(s)).collect(); + let ns_set: Retained> = NSSet::from_retained_slice(&ns_ids); + let request = SKProductsRequest::initWithProductIdentifiers( + SKProductsRequest::alloc(), + &ns_set, + ); + request.setDelegate(Some(ProtocolObject::from_ref(&*mgr.delegate))); + *mgr.delegate.ivars().active_request.lock().unwrap() = Some(request.clone()); + request.start(); + } + + match rx.await { + Ok(result) => result, + Err(_) => Err("Products request was cancelled".to_string()), + } +} + +pub async fn purchase(product_id: String) -> Result { + let mgr = manager(); + + if !unsafe { SKPaymentQueue::canMakePayments() } { + return Err("In-app purchases are not allowed on this device".to_string()); + } + + if !product_cached(mgr, &product_id) { + let _ = fetch_products(vec![product_id.clone()]).await?; + } + let sk_product = lookup_cached(mgr, &product_id) + .ok_or_else(|| format!("Product {product_id} not available from the App Store"))?; + + let (tx, rx) = oneshot::channel(); + { + let mut pending = mgr.delegate.ivars().pending_purchase.lock().unwrap(); + if pending.is_some() { + return Err("Another purchase is already in progress".to_string()); + } + *pending = Some(PendingPurchase { + product_id: product_id.clone(), + sender: tx, + }); + } + + unsafe { + let payment = SKPayment::paymentWithProduct(&sk_product); + SKPaymentQueue::defaultQueue().addPayment(&payment); + } + + match rx.await { + Ok(result) => result, + Err(_) => Err("Purchase was cancelled before completion".to_string()), + } +} + +pub async fn restore() -> Result { + let mgr = manager(); + let (tx, rx) = oneshot::channel(); + { + let mut pending = mgr.delegate.ivars().pending_restore.lock().unwrap(); + if pending.is_some() { + return Err("A restore is already in progress".to_string()); + } + *pending = Some(PendingRestore { + sender: tx, + restored_any: false, + }); + } + + unsafe { + SKPaymentQueue::defaultQueue().restoreCompletedTransactions(); + } + + let restored = match rx.await { + Ok(Ok(restored)) => restored, + Ok(Err(e)) => return Err(e), + Err(_) => return Err("Restore was cancelled".to_string()), + }; + + Ok(IapRestoreResult { restored }) +} + +/// Eagerly install the transaction observer (called from `lib.rs` at startup +/// so we don't miss transactions delivered while the app is launching). +/// The `MainThreadMarker` parameter is unused at runtime but documents the +/// expectation that the caller is on the AppKit main thread. +pub fn install_observer_on_startup(_mtm: MainThreadMarker) { + let _ = manager(); +} + +// --------------------------------------------------------------------------- +// Helpers. +// --------------------------------------------------------------------------- + +fn product_cached(mgr: &Manager, product_id: &str) -> bool { + mgr.delegate + .ivars() + .cached_products + .lock() + .unwrap() + .iter() + .any(|p| { + let id = unsafe { p.productIdentifier() }; + id.to_string() == product_id + }) +} + +fn lookup_cached(mgr: &Manager, product_id: &str) -> Option> { + mgr.delegate + .ivars() + .cached_products + .lock() + .unwrap() + .iter() + .find(|p| { + let id = unsafe { p.productIdentifier() }; + id.to_string() == product_id + }) + .cloned() +} + +fn format_ns_error(error: &NSError) -> String { + let desc = error.localizedDescription(); + desc.to_string() +} + +fn product_to_wire(product: &SKProduct) -> Option { + unsafe { + let id = product.productIdentifier().to_string(); + let title = product.localizedTitle().to_string(); + let description = product.localizedDescription().to_string(); + let price = format_price(&product.price(), &product.priceLocale())?; + Some(IapProduct { + id, + title, + description, + price, + }) + } +} + +fn format_price(amount: &NSDecimalNumber, locale: &NSLocale) -> Option { + let formatter = NSNumberFormatter::new(); + formatter.setNumberStyle(NSNumberFormatterStyle::CurrencyStyle); + formatter.setLocale(Some(locale)); + // `NSDecimalNumber` is an `NSNumber` subclass; pass through the AsRef impl. + let as_number: &objc2_foundation::NSNumber = amount; + formatter.stringFromNumber(as_number).map(|s| s.to_string()) +} + +fn compute_expires_at( + product_id: &str, + txn_date: Option<&NSDate>, + cached_products: &[Retained], +) -> Option { + let product = cached_products.iter().find(|p| { + let id = unsafe { p.productIdentifier() }; + id.to_string() == product_id + })?; + let period = unsafe { product.subscriptionPeriod() }?; + let txn_date = txn_date?; + let secs = txn_date.timeIntervalSince1970() as i64; + let start = DateTime::::from_timestamp(secs, 0)?; + let units = unsafe { period.numberOfUnits() } as u32; + let unit = unsafe { period.unit() }; + add_period(start, units, unit).map(|d| d.to_rfc3339()) +} + +fn add_period(start: DateTime, units: u32, unit: SKProductPeriodUnit) -> Option> { + match unit { + SKProductPeriodUnit::Day => { + start.checked_add_signed(chrono::Duration::days(units as i64)) + } + SKProductPeriodUnit::Week => { + start.checked_add_signed(chrono::Duration::weeks(units as i64)) + } + SKProductPeriodUnit::Month => start.checked_add_months(Months::new(units)), + SKProductPeriodUnit::Year => { + start.checked_add_months(Months::new(units.saturating_mul(12))) + } + _ => None, + } +} + +// --------------------------------------------------------------------------- +// Tests — limited to logic we can exercise without a live StoreKit session. +// --------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + use chrono::TimeZone; + + #[test] + fn add_period_year_adds_twelve_months() { + let start = Utc.with_ymd_and_hms(2026, 1, 1, 0, 0, 0).unwrap(); + let end = add_period(start, 1, SKProductPeriodUnit::Year).unwrap(); + assert_eq!(end, Utc.with_ymd_and_hms(2027, 1, 1, 0, 0, 0).unwrap()); + } + + #[test] + fn add_period_month_adds_calendar_month() { + let start = Utc.with_ymd_and_hms(2026, 5, 18, 12, 0, 0).unwrap(); + let end = add_period(start, 3, SKProductPeriodUnit::Month).unwrap(); + assert_eq!(end, Utc.with_ymd_and_hms(2026, 8, 18, 12, 0, 0).unwrap()); + } + + #[test] + fn add_period_week_adds_seven_days_per_unit() { + let start = Utc.with_ymd_and_hms(2026, 5, 18, 0, 0, 0).unwrap(); + let end = add_period(start, 2, SKProductPeriodUnit::Week).unwrap(); + assert_eq!(end, Utc.with_ymd_and_hms(2026, 6, 1, 0, 0, 0).unwrap()); + } + + #[test] + fn add_period_day_adds_n_days() { + let start = Utc.with_ymd_and_hms(2026, 5, 18, 0, 0, 0).unwrap(); + let end = add_period(start, 5, SKProductPeriodUnit::Day).unwrap(); + assert_eq!(end, Utc.with_ymd_and_hms(2026, 5, 23, 0, 0, 0).unwrap()); + } + + #[test] + fn add_period_unknown_unit_returns_none() { + let start = Utc.with_ymd_and_hms(2026, 5, 18, 0, 0, 0).unwrap(); + assert!(add_period(start, 1, SKProductPeriodUnit(999)).is_none()); + } +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index 9f5366a..053b926 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -2,6 +2,8 @@ pub mod connections; pub mod data; #[cfg(feature = "mas")] pub mod iap; +#[cfg(feature = "mas")] +pub mod iap_storekit; pub mod license; pub mod saved_queries; pub mod schema; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 68713c8..f76bf53 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -114,6 +114,17 @@ pub fn run() { } }); } + + // App Store rules require the SKPaymentQueue transaction observer + // to be installed at launch so we don't miss transactions + // delivered while the app is starting up (e.g. a renewal that + // fired between two launches). + #[cfg(feature = "mas")] + { + let mtm = objc2::MainThreadMarker::new() + .expect("Tauri setup runs on the main thread"); + commands::iap_storekit::install_observer_on_startup(mtm); + } Ok(()) }) .invoke_handler(tauri::generate_handler![ From 77140b62a53b4daff38efb90076d15b07ae2a0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Tue, 19 May 2026 07:58:16 +0200 Subject: [PATCH 6/8] feat(mas): add PurchaseSheet + build-flavour branching for licensing UI 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 --- progress.txt | 105 ++++++++++++ src-tauri/src/commands/license.rs | 28 ++++ src-tauri/src/lib.rs | 1 + src/features/license/LicenseBanner.tsx | 82 +++++++--- src/features/license/LicenseSettings.tsx | 166 ++++++++++++++++++- src/features/license/PurchaseSheet.tsx | 199 +++++++++++++++++++++++ src/features/license/api.ts | 36 +++- src/features/license/index.ts | 20 ++- src/features/license/types.ts | 31 ++++ 9 files changed, 639 insertions(+), 29 deletions(-) create mode 100644 src/features/license/PurchaseSheet.tsx diff --git a/progress.txt b/progress.txt index e4706eb..762ce9b 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,108 @@ +## MAS PRD P2 — Step 4: Frontend (Purchase Sheet, build-flavour branching) [DONE] +- Goal: ship the MAS-flavoured licensing UI (PurchaseSheet, Restore Purchases, + Manage Subscription) without forking the Vite bundle. Single index.html / + React tree picks the right UI at runtime by querying a new build-flavour + Tauri command. Direct build's UI is unchanged — every Direct branch in the + modified components matches the previous markup byte-for-byte. +- src-tauri/src/commands/license.rs: + - New always-on Tauri command get_build_flavor() -> &'static str. Returns + "mas" when cfg!(feature = "mas"), else "direct". cfg! is a compile-time + macro so each binary returns its own constant — no runtime feature + detection. Doc comment notes the frontend caches this with + staleTime: Infinity since the value is fixed for the binary's lifetime. + - Two new unit tests pin the cfg → string mapping per build: + build_flavor_reports_direct_when_mas_feature_off (#[cfg(not(feature = "mas"))]) + build_flavor_reports_mas_when_mas_feature_on (#[cfg(feature = "mas")]) + They live in the existing tests module so cargo test on Direct asserts + "direct" and cargo test --features mas asserts "mas". One of the two is + always cfg'd out for any given build — there's no runtime branch to test + that could lie about the wrong flavour. +- src-tauri/src/lib.rs: registered get_build_flavor in the always-on section + of invoke_handler! (alongside open_url and the prefs commands), so the + frontend's first call resolves regardless of feature flags. +- src/features/license/types.ts: added BuildFlavor = 'direct' | 'mas' plus + the wire shapes for IAP — IapProduct, IapPurchaseStatus, IapPurchaseResult, + IapRestoreResult, IapEntitlement (camelCase fields matching the Rust + serde rename_all = "camelCase"). productId / expiresAt typed as + string | null since the Rust side serialises Option as null. +- src/features/license/api.ts: cleaned up and extended. + - New query keys: BUILD_FLAVOR_KEY, IAP_PRODUCTS_KEY, IAP_ENTITLEMENT_KEY. + - licenseApi.getBuildFlavor() + - licenseApi.getProducts() / .purchase(productId) / .restore() / + .checkEntitlement() — wrappers for the four MAS-only commands. + - licenseApi.openManageSubscription() — invokes open_url with + macappstore://apps.apple.com/account/subscriptions, the canonical + deep link for managing a Mac App Store subscription. macappstore:// + opens the Mac App Store app directly; the https:// fallback would + detour through a browser → handoff and feels broken to users. + - The Direct-only methods (activate, deactivate, openCustomerPortal) + stayed in place; they're still callable but only reachable from the + Direct branch of the new components. +- src/features/license/index.ts: re-exports PurchaseSheet, all new query + keys, and the new types so callers can import everything from + '../features/license'. +- src/features/license/PurchaseSheet.tsx (NEW, ~210 lines): + - Right-side Radix Dialog (w-[360px], matches LicenseActivationSheet + so the two sheets feel like one component family). + - Fetches products via React Query keyed on IAP_PRODUCTS_KEY, enabled + only while the sheet is open, staleTime 5 min. Loading state shows + a centred spinner; failure state shows the error + a Try again + button that triggers refetch(). + - Renders one card per IapProduct with title, price (StoreKit-formatted + on the Rust side, so no Intl needed), description, and a Buy button. + busyProductId tracks which card is awaiting iap_purchase; while one is + in flight all other Buy buttons + the Restore link disable. + - Purchase outcomes: status="purchased" → refresh both LICENSE_STATUS_KEY + and IAP_ENTITLEMENT_KEY caches, toast success, close sheet. + status="cancelled" → silent (user hit Cancel themselves). + status="failed" → toast error. + - Restore link at the bottom of the sheet: calls iap_restore, refreshes + both caches, toasts success/info based on result.restored, closes if + something was restored. +- src/features/license/LicenseBanner.tsx: branches on buildFlavor. + - Reads buildFlavor via React Query (BUILD_FLAVOR_KEY, staleTime: Infinity). + - The revalidation-required banner is now Direct-only — it's gated behind + !isMas because revalidation_required is always false on MAS (StoreKit + is the source of truth, no offline-grace concept). + - The standard banner: Direct keeps the existing two-button layout + (Purchase license + I have a license key); MAS shows a single + Get a license button that opens PurchaseSheet. Dismiss [×] still + works in both flavours. + - Sheets are rendered conditionally: Direct mounts LicenseActivationSheet, + MAS mounts PurchaseSheet. Mounting both at once would either be a no-op + (only one ever opens) or a dead-call risk (the Direct sheet calls + activate_license, which doesn't exist on MAS). +- src/features/license/LicenseSettings.tsx: branches on buildFlavor with + three render paths. + - MAS commercial: pulls IapEntitlement via React Query, maps productId + through PRODUCT_LABELS to a friendly plan name (Personal — Lifetime, + Personal — Annual, Business — Annual) with a fallback to the raw ID. + Subscription rows show "Renews on " + Manage subscription + + Restore purchases. Lifetime row (expires_at == null) shows + "One-time purchase" and skips Manage subscription. + - MAS unlicensed: Personal (free) / No license header, Get a license + button (opens PurchaseSheet), Restore purchases button. + - Direct: existing layout untouched (Commercial / Personal / Unlicensed + branches all match the previous file). + - The IAP_ENTITLEMENT_KEY query is enabled only when isMas is true so + Direct doesn't try to invoke iap_check_entitlement (would 404 — the + command isn't registered there). + - Restore purchases is mounted in two places (PurchaseSheet + Settings) + per the PRD's mitigation for "first submission rejected for missing + Restore Purchases": both placements together cover the App Review + precedent that Restore must be discoverable without buying anything. +- Verification: + - Direct: cargo clippy --all-targets -- -D warnings clean, cargo test + 22 passed (was 21 — the new build_flavor_reports_direct test). + - MAS: cargo clippy --all-targets --features mas -- -D warnings clean, + cargo test --features mas 27 passed (was 26 — the new + build_flavor_reports_mas test). + - Frontend: npm run type-check clean, npm run lint clean. +- Live StoreKit testing of PurchaseSheet (sandbox accounts, three IAP + products appearing with correct prices, sandbox purchase end-to-end, + Restore Purchases) is a TestFlight-time validation per the PRD's + Submission Flow → TestFlight checklist; not part of this step. + ## MAS PRD P2 — Step 3: objc2-store-kit wiring [DONE] - Replaces the four iap_* command stubs from Step 1 with a real StoreKit 1 backend, wired through objc2-store-kit (pure-Rust bindings, no Swift diff --git a/src-tauri/src/commands/license.rs b/src-tauri/src/commands/license.rs index c78f7b8..3aa4145 100644 --- a/src-tauri/src/commands/license.rs +++ b/src-tauri/src/commands/license.rs @@ -803,6 +803,22 @@ pub fn open_url(url: String) -> Result<(), String> { .map_err(|e| e.to_string()) } +/// Build flavour identifier exposed to the frontend so a single bundled +/// `index.html` can render the right licensing UI for each binary. Returns: +/// - `"mas"` — Mac App Store build (StoreKit IAP, no Dodo, no updater) +/// - `"direct"` — GitHub Releases / Homebrew build (Dodo Payments, updater) +/// +/// The frontend caches this with `staleTime: Infinity` since the value is +/// fixed for the lifetime of the running binary. +#[tauri::command] +pub fn get_build_flavor() -> &'static str { + if cfg!(feature = "mas") { + "mas" + } else { + "direct" + } +} + #[tauri::command] pub async fn get_ui_preferences(app: AppHandle) -> Result { match read_prefs_json(&app) { @@ -922,6 +938,18 @@ mod tests { assert!(!status.revalidation_required); } + #[cfg(not(feature = "mas"))] + #[test] + fn build_flavor_reports_direct_when_mas_feature_off() { + assert_eq!(get_build_flavor(), "direct"); + } + + #[cfg(feature = "mas")] + #[test] + fn build_flavor_reports_mas_when_mas_feature_on() { + assert_eq!(get_build_flavor(), "mas"); + } + // -- Direct-only: Dodo cache mapping + error messages -- #[cfg(not(feature = "mas"))] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f76bf53..7bde509 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -151,6 +151,7 @@ pub fn run() { commands::license::dismiss_license_banner, commands::license::notify_connection_count, commands::license::open_url, + commands::license::get_build_flavor, commands::license::get_ui_preferences, commands::license::set_ui_preferences, // Dodo Payments + in-app updater: Direct build only. diff --git a/src/features/license/LicenseBanner.tsx b/src/features/license/LicenseBanner.tsx index 2745dde..4533a2d 100644 --- a/src/features/license/LicenseBanner.tsx +++ b/src/features/license/LicenseBanner.tsx @@ -1,8 +1,13 @@ import { useState } from 'react'; import { X } from 'lucide-react'; import { useQuery, useQueryClient } from '@tanstack/react-query'; -import { licenseApi, LICENSE_STATUS_KEY } from './api'; +import { + BUILD_FLAVOR_KEY, + LICENSE_STATUS_KEY, + licenseApi, +} from './api'; import { LicenseActivationSheet } from './LicenseActivationSheet'; +import { PurchaseSheet } from './PurchaseSheet'; export function LicenseBanner() { const queryClient = useQueryClient(); @@ -11,8 +16,20 @@ export function LicenseBanner() { queryFn: licenseApi.getStatus, staleTime: 60_000, }); + const { data: buildFlavor } = useQuery({ + queryKey: BUILD_FLAVOR_KEY, + queryFn: licenseApi.getBuildFlavor, + staleTime: Infinity, + }); const [activationOpen, setActivationOpen] = useState(false); + const [purchaseOpen, setPurchaseOpen] = useState(false); + // `revalidationRequired` is always false on MAS (StoreKit is the source of + // truth, no offline-grace concept), so the dedicated revalidation banner + // never appears there. Fall back gracefully if the build-flavour query + // hasn't resolved yet by treating the build as direct (matches behaviour + // before P2 Step 4). + const isMas = buildFlavor === 'mas'; const showBanner = status?.bannerVisible || status?.revalidationRequired; if (!showBanner) return null; @@ -21,7 +38,7 @@ export function LicenseBanner() { queryClient.invalidateQueries({ queryKey: LICENSE_STATUS_KEY }); } - if (status?.revalidationRequired) { + if (status?.revalidationRequired && !isMas) { return (
Esploro is free for personal use. Commercial use requires a license. - - + {isMas ? ( + + ) : ( + <> + + + + )} + )} + +
+ + + ); + } + + // ---- MAS — Personal / unlicensed user + if (isMas) { + return ( +
+

+ License +

+
+
+ + + {status?.tier === 'Personal' ? 'Personal (free)' : 'No license'} + +
+

+ Commercial use requires a license. +

+
+ + +
+
+ setPurchaseOpen(false)} + /> +
+ ); + } + + // ---- Direct build (existing UI) return (

diff --git a/src/features/license/PurchaseSheet.tsx b/src/features/license/PurchaseSheet.tsx new file mode 100644 index 0000000..7ee6f3e --- /dev/null +++ b/src/features/license/PurchaseSheet.tsx @@ -0,0 +1,199 @@ +import { useState } from 'react'; +import * as Dialog from '@radix-ui/react-dialog'; +import { Loader2, X } from 'lucide-react'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { + IAP_ENTITLEMENT_KEY, + IAP_PRODUCTS_KEY, + LICENSE_STATUS_KEY, + licenseApi, +} from './api'; +import { useToast } from '../../components/Toast'; + +interface Props { + open: boolean; + onClose: () => void; +} + +/// Right-side sheet that lists the three IAP products fetched live from +/// `iap_get_products` and routes per-card purchases through `iap_purchase`. +/// Only rendered in the MAS build (`buildFlavor === 'mas'`); the Direct build +/// uses `LicenseActivationSheet` instead. +/// +/// Restore Purchases is mounted both here (App Review precedent) and in +/// `LicenseSettings`, so a user who already paid on another machine can recover +/// their entitlement without ever opening this sheet. +export function PurchaseSheet({ open, onClose }: Props) { + const queryClient = useQueryClient(); + const { toast } = useToast(); + const [busyProductId, setBusyProductId] = useState(null); + const [restoring, setRestoring] = useState(false); + + const { + data: products, + isLoading, + error, + refetch, + } = useQuery({ + queryKey: IAP_PRODUCTS_KEY, + queryFn: licenseApi.getProducts, + enabled: open, + staleTime: 5 * 60_000, + }); + + async function refreshLicenseState() { + const [status, entitlement] = await Promise.all([ + licenseApi.getStatus(), + licenseApi.checkEntitlement(), + ]); + queryClient.setQueryData(LICENSE_STATUS_KEY, status); + queryClient.setQueryData(IAP_ENTITLEMENT_KEY, entitlement); + } + + async function handlePurchase(productId: string) { + setBusyProductId(productId); + try { + const result = await licenseApi.purchase(productId); + if (result.status === 'purchased') { + await refreshLicenseState(); + toast('License activated. Welcome aboard!', 'success'); + onClose(); + } else if (result.status === 'cancelled') { + // No toast — user dismissed the sheet themselves. + } else { + toast('Purchase failed. Please try again.', 'error'); + } + } catch (e) { + toast(`Purchase failed: ${String(e)}`, 'error'); + } finally { + setBusyProductId(null); + } + } + + async function handleRestore() { + setRestoring(true); + try { + const result = await licenseApi.restore(); + await refreshLicenseState(); + if (result.restored) { + toast('Purchases restored.', 'success'); + onClose(); + } else { + toast('No previous purchases found on this Apple ID.', 'info'); + } + } catch (e) { + toast(`Restore failed: ${String(e)}`, 'error'); + } finally { + setRestoring(false); + } + } + + return ( + !v && onClose()}> + + + e.preventDefault()} + > +
+ + Get a license + + + + +
+ +
+

+ Esploro is free for personal use. Choose a plan below for + commercial use. +

+ + {isLoading && ( +
+ + Loading plans… +
+ )} + + {error && ( +
+

+ Couldn't load plans from the App Store. +

+ +
+ )} + + {products?.map((product) => { + const busy = busyProductId === product.id; + const anyBusy = busyProductId !== null || restoring; + return ( +
+
+

+ {product.title} +

+ + {product.price} + +
+

+ {product.description} +

+ +
+ ); + })} +
+ +
+ +
+
+
+
+ ); +} diff --git a/src/features/license/api.ts b/src/features/license/api.ts index 1b1ef9c..9580f80 100644 --- a/src/features/license/api.ts +++ b/src/features/license/api.ts @@ -1,17 +1,47 @@ import { invoke } from '@tauri-apps/api/core'; -import type { LicenseStatus } from './types'; +import type { + BuildFlavor, + IapEntitlement, + IapProduct, + IapPurchaseResult, + IapRestoreResult, + LicenseStatus, +} from './types'; export const LICENSE_STATUS_KEY = ['license-status'] as const; +export const BUILD_FLAVOR_KEY = ['build-flavor'] as const; +export const IAP_PRODUCTS_KEY = ['iap-products'] as const; +export const IAP_ENTITLEMENT_KEY = ['iap-entitlement'] as const; + +/// Apple's deep link to the user's subscription management screen on macOS. +/// `macappstore://` opens the Mac App Store app directly; falling back to the +/// `https://` URL would route through a browser → App Store handoff. +const MANAGE_SUBSCRIPTIONS_URL = + 'macappstore://apps.apple.com/account/subscriptions'; export const licenseApi = { + // Both builds. getStatus: () => invoke('get_license_status'), - activate: (key: string) => invoke('activate_license', { key }), - deactivate: () => invoke('deactivate_license'), + getBuildFlavor: () => invoke('get_build_flavor'), answerUsageDialog: (answer: 'personal' | 'commercial') => invoke('answer_usage_dialog', { answer }), dismissBanner: () => invoke('dismiss_license_banner'), notifyConnectionCount: (count: number) => invoke('notify_connection_count', { count }), openPricingPage: () => invoke('open_url', { url: 'https://esploro.app/pricing' }), + + // Direct build only — calls fail at runtime on the MAS binary because the + // commands aren't registered there. + activate: (key: string) => invoke('activate_license', { key }), + deactivate: () => invoke('deactivate_license'), openCustomerPortal: () => invoke('open_customer_portal'), + + // MAS build only — same caveat in the opposite direction. + getProducts: () => invoke('iap_get_products'), + purchase: (productId: string) => + invoke('iap_purchase', { productId }), + restore: () => invoke('iap_restore'), + checkEntitlement: () => invoke('iap_check_entitlement'), + openManageSubscription: () => + invoke('open_url', { url: MANAGE_SUBSCRIPTIONS_URL }), }; diff --git a/src/features/license/index.ts b/src/features/license/index.ts index e6b7f88..ee4be99 100644 --- a/src/features/license/index.ts +++ b/src/features/license/index.ts @@ -1,6 +1,22 @@ export { LicenseBanner } from './LicenseBanner'; export { LicenseActivationSheet } from './LicenseActivationSheet'; +export { PurchaseSheet } from './PurchaseSheet'; export { UsageTypeDialog } from './UsageTypeDialog'; export { LicenseSettings } from './LicenseSettings'; -export { licenseApi, LICENSE_STATUS_KEY } from './api'; -export type { LicenseStatus, LicenseTier } from './types'; +export { + licenseApi, + LICENSE_STATUS_KEY, + BUILD_FLAVOR_KEY, + IAP_PRODUCTS_KEY, + IAP_ENTITLEMENT_KEY, +} from './api'; +export type { + LicenseStatus, + LicenseTier, + BuildFlavor, + IapProduct, + IapPurchaseResult, + IapPurchaseStatus, + IapRestoreResult, + IapEntitlement, +} from './types'; diff --git a/src/features/license/types.ts b/src/features/license/types.ts index 67bb5f7..b854b00 100644 --- a/src/features/license/types.ts +++ b/src/features/license/types.ts @@ -7,3 +7,34 @@ export interface LicenseStatus { showUsageDialog: boolean; revalidationRequired: boolean; } + +/// Identifies which binary flavour is running. The Direct build is shipped via +/// GitHub Releases / Homebrew with Dodo Payments; the MAS build is shipped via +/// the Mac App Store with StoreKit IAP. The frontend ships a single bundle and +/// picks the right UI by querying `get_build_flavor` once at startup. +export type BuildFlavor = 'direct' | 'mas'; + +export interface IapProduct { + id: string; + title: string; + description: string; + /** Already localised + currency-formatted by StoreKit (e.g. `"$129.00"`). */ + price: string; +} + +export type IapPurchaseStatus = 'purchased' | 'cancelled' | 'failed'; + +export interface IapPurchaseResult { + status: IapPurchaseStatus; +} + +export interface IapRestoreResult { + restored: boolean; +} + +export interface IapEntitlement { + entitled: boolean; + productId: string | null; + /** RFC 3339 timestamp; `null` for non-consumable lifetime products. */ + expiresAt: string | null; +} From f32f5013ab2edc23f25a3a8e34761c44bad19a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Tue, 19 May 2026 08:04:21 +0200 Subject: [PATCH 7/8] chore(mas): add scripts/build-mas.sh for repeatable MAS builds 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 --- package.json | 3 +- scripts/build-mas.sh | 115 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100755 scripts/build-mas.sh diff --git a/package.json b/package.json index b9168c1..ca3bb4e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "preview": "vite preview", "type-check": "tsc --noEmit", "lint": "eslint .", - "tauri": "tauri" + "tauri": "tauri", + "tauri:build:mas": "bash scripts/build-mas.sh" }, "dependencies": { "@codemirror/autocomplete": "6.20.1", diff --git a/scripts/build-mas.sh b/scripts/build-mas.sh new file mode 100755 index 0000000..2bbcbae --- /dev/null +++ b/scripts/build-mas.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# +# build-mas.sh — Build the Mac App Store target. +# +# Strips the literal "macos-private-api" feature from src-tauri/Cargo.toml's +# `tauri` dependency, runs `cargo tauri build` with the MAS overlay config and +# the `mas` Cargo feature, then unconditionally restores Cargo.toml on exit +# (success or failure, including Ctrl+C). The Direct (GitHub Releases / +# Homebrew) build remains the day-to-day default — `cargo tauri dev` keeps +# working unchanged. +# +# Why the patch is needed: `tauri-build` strictly compares the literal `tauri` +# features array in Cargo.toml against the merged config allowlist. Feature +# aliases (`mas = ["tauri/..."]`) are NOT resolved during that check (see +# tauri-apps/tauri#11142, #7940), so physically removing the feature from the +# array is the only way to produce a binary without `macos-private-api` +# linkage. App Store review rejects any binary that links private APIs. +# +# Usage: +# scripts/build-mas.sh # build aarch64-apple-darwin (default) +# TAURI_TARGET=x86_64-apple-darwin \ +# scripts/build-mas.sh # override target +# scripts/build-mas.sh --verbose # extra args forwarded to `tauri build` +# +# Environment: +# TAURI_TARGET Rust target triple. Default: aarch64-apple-darwin. +# PRD scope is ARM-only for the first MAS submission; the +# variable exists for future fat-binary work. +# +# Exit codes: +# 0 success +# 1 precondition failure (Cargo.toml missing, expected line absent, …) +# * propagated from `cargo tauri build` +# +# The patched Cargo.toml is always restored via `trap … EXIT` — including on +# SIGINT — so a Ctrl+C during the build does not leave the working tree in a +# half-patched state. See `restore` below. + +set -euo pipefail + +TARGET="${TAURI_TARGET:-aarch64-apple-darwin}" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$SCRIPT_DIR")" +CARGO_TOML="$ROOT_DIR/src-tauri/Cargo.toml" +MAS_CONFIG="$ROOT_DIR/src-tauri/tauri.mas.conf.json" + +# The exact line we expect to patch. Strict equality (anchored ^ … $) so this +# script fails loudly the moment the `tauri` dependency line changes shape — +# better to force a conscious script update than to silently produce a +# half-patched Cargo.toml that builds the wrong binary. +EXPECTED_LINE='tauri = { version = "2", features = ["macos-private-api"] }' +PATCHED_LINE='tauri = { version = "2", features = [] }' + +if [[ ! -f "$CARGO_TOML" ]]; then + echo "error: $CARGO_TOML not found" >&2 + exit 1 +fi + +if [[ ! -f "$MAS_CONFIG" ]]; then + echo "error: $MAS_CONFIG not found" >&2 + exit 1 +fi + +if ! grep -Fxq "$EXPECTED_LINE" "$CARGO_TOML"; then + echo "error: expected line not found in $CARGO_TOML" >&2 + echo " expected: $EXPECTED_LINE" >&2 + echo " The MAS build script needs to match this exact line so it can" >&2 + echo " strip 'macos-private-api' from the tauri features array." >&2 + echo " If the tauri dependency declaration has changed, update both" >&2 + echo " EXPECTED_LINE and PATCHED_LINE in this script accordingly." >&2 + exit 1 +fi + +BACKUP="$(mktemp -t esploro-cargo-toml.XXXXXX)" +cp "$CARGO_TOML" "$BACKUP" + +restore() { + if [[ -f "$BACKUP" ]]; then + cp "$BACKUP" "$CARGO_TOML" + rm -f "$BACKUP" + fi +} +trap restore EXIT + +# In-place patch via a temp file (portable across BSD/GNU sed without -i''). +# We pin the replacement to the full literal line — any drift in formatting +# (extra spaces, reordered features) would have already tripped the grep +# preflight check above. +awk -v expected="$EXPECTED_LINE" -v patched="$PATCHED_LINE" ' + $0 == expected { print patched; next } + { print } +' "$CARGO_TOML" > "$CARGO_TOML.new" +mv "$CARGO_TOML.new" "$CARGO_TOML" + +echo "==> Patched Cargo.toml (stripped 'macos-private-api' from tauri features)" +echo "==> Building MAS binary" +echo " target: $TARGET" +echo " config: $MAS_CONFIG" +echo " feature: mas" + +# We invoke `npm run tauri -- build` rather than `cargo tauri build` so this +# script uses the same Tauri CLI version pinned in package.json — matching the +# Direct build path and avoiding "which cargo-tauri is on PATH?" drift in CI. +( + cd "$ROOT_DIR" + npm run tauri -- build \ + --target "$TARGET" \ + --config "$MAS_CONFIG" \ + --features mas \ + "$@" +) + +echo "==> MAS build complete" +echo "==> Bundle: src-tauri/target/$TARGET/release/bundle/" From 6b92f96dca5d56c0b17e649ce53b708ee5962448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Munjakovi=C4=87?= Date: Tue, 19 May 2026 08:22:30 +0200 Subject: [PATCH 8/8] chore(mas): add P3 store listing assets (icon, metadata, screenshots scaffold) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- progress.txt | 148 ++++++++++++++++++ store-listing/README.md | 28 ++++ store-listing/app-icon-1024.png | Bin 0 -> 288417 bytes store-listing/metadata.md | 92 +++++++++++ store-listing/screenshots/README.md | 47 ++++++ .../scripts/build-app-store-icon.swift | 146 +++++++++++++++++ 6 files changed, 461 insertions(+) create mode 100644 store-listing/README.md create mode 100644 store-listing/app-icon-1024.png create mode 100644 store-listing/metadata.md create mode 100644 store-listing/screenshots/README.md create mode 100755 store-listing/scripts/build-app-store-icon.swift diff --git a/progress.txt b/progress.txt index 762ce9b..6ef0f8e 100644 --- a/progress.txt +++ b/progress.txt @@ -1,3 +1,151 @@ +## MAS PRD P3 — Store Listing Assets: app icon + metadata [PARTIAL: icon + text DONE, screenshots PENDING] +- Goal: produce the App Store Connect-ready assets and text content from + PRD §P3. The PRD said "no code changes" — implementation here is a new + store-listing/ directory plus a small Swift generator so the icon build + is reproducible (re-runnable if src-tauri/icons/icon.png ever changes). + Screenshots are intentionally not produced — they need a running app + with real DB content, which can't be reasonably scripted from a CLI. +- store-listing/app-icon-1024.png (NEW, 288417 bytes): 1024×1024 8-bit RGB + PNG, no alpha channel, no rounded corners. App Store Connect rejects + PNGs with alpha or with the source's own rounded mask (Apple applies + its own squircle mask). Verified with `file`: "PNG image data, 1024 x + 1024, 8-bit/color RGB, non-interlaced". +- store-listing/scripts/build-app-store-icon.swift (NEW, ~150 lines): the + generator. Loads src-tauri/icons/icon.png (rounded-corner gradient with + transparent corners), samples the source's own corner-most fully-opaque + pixel along each of the four diagonals (walks inward from each corner + until alpha == 255 — that hit is the gradient colour at the rounded-rect + apex), averages the four samples for the background fill, then composites + the source onto a 1024×1024 noneSkipLast (RGB-only, alpha-discarding) + CGContext. Final PNG carries no alpha channel because the underlying + bitmap doesn't have one — not "alpha set to 255" but the channel is + genuinely absent. Reproducible: `swift store-listing/scripts/build- + app-store-icon.swift src-tauri/icons/icon.png store-listing/app-icon- + 1024.png`. Sampled background for the current source: #203753. + - Why edge-extension by ray-cast to centre was tried and reverted: ray- + casting each transparent pixel toward the centre and copying the + nearest opaque pixel along that ray produced visible radial streaks + in the corners (the source's gradient varies tangentially around the + rounded rect, so neighbouring corner pixels picked colours from + different gradient positions). The "composite onto matched solid + fill" approach has one harmless artefact in trade — a faint outline + where the rounded mask used to be — but that area is fully outside + Apple's eventual icon mask, so it's invisible in the App Store. +- store-listing/metadata.md (NEW, ~120 lines): full App Store Connect + text-content block in one file so the submission form can be filled in + from this alone (no PRD context-switching). Mirrors PRD §P3 Text + Content + IAP Products + adds Version Release Notes, Age Rating, and + an App Review note explaining the network entitlement scope and how to + exercise the commercial-license code path during review. The PRD's + description block is copied byte-for-byte; the IAP product table + mirrors PRD §IAP Products. +- store-listing/screenshots/README.md (NEW): capture guidance + file-name + convention (01-connections.png … 05-settings.png so gallery order is + preserved during upload). Lists the five suggested shots from PRD §P3 + with concrete instructions (which table to load, which theme to use, + what state to put the UI in). Calls out that the Direct build and MAS + build look identical in App Review's eye except for the sidebar + vibrancy, so captures from the Direct build are valid for MAS + submission. +- store-listing/README.md (NEW): file-by-file index of the directory so a + future reviewer can see at a glance what's ready vs pending. +- PRD.md: P3 section reorganised. Sub-headers are now `#### App icon + [DONE]`, `#### Screenshots [PENDING — manual capture]`, `#### Text + content [DONE]`. Each sub-section references the corresponding file + under store-listing/. The icon sub-section embeds the regenerate + command so it's discoverable from the PRD alone. +- Verification: + - npm run type-check — clean (asset-only change, no TS impact). + - npm run lint — clean. + - cargo test (Direct) — 22 passed (unchanged). + - file store-listing/app-icon-1024.png — confirmed + "PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced", i.e. + correct dimensions and no alpha channel. +- Out of scope (intentionally): + - Screenshot capture. Requires a running app with realistic DB content, + correct window sizing, theme toggling, and at least 3 distinct UI + states. Doing it from a CLI agent without a graphical session would + produce sub-spec screenshots and waste re-capture effort later. + Documented as the next manual step in store-listing/screenshots/ + README.md so whoever submits the app can pick it up cleanly. + - App Store Connect configuration (create app record, register IAP + product IDs, set privacy/support URLs, enrol in Small Business + Program). Per PRD §Submission Flow Step 1 these depend on Apple + Developer account access that's outside the repo. + - TestFlight upload via Transporter. Needs the App-Specific Password + + Apple Distribution cert + provisioning profile not in this repo. + +## MAS PRD P4 — Build pipeline (scripts/build-mas.sh) [DONE] +- Goal: turn the Cargo.toml patch + cargo tauri build + restore sequence from + the PRD's P1 note into a single repeatable command. Previously the procedure + lived only in prose; running it by hand risked leaving Cargo.toml in a + half-patched state if anything went wrong mid-build. Now it's one npm + script. +- scripts/build-mas.sh (NEW, ~100 lines, +x): + - Computes ROOT_DIR from BASH_SOURCE so it works regardless of where it's + invoked from (CI, repo root, src-tauri/, …). + - Preflight: asserts src-tauri/Cargo.toml and src-tauri/tauri.mas.conf.json + exist and that the literal line + `tauri = { version = "2", features = ["macos-private-api"] }` + is present (anchored full-line equality via `grep -Fxq`). Any drift in + the dependency declaration fails fast with a remediation hint that names + the EXPECTED_LINE / PATCHED_LINE constants in the script to update. + Better to refuse to build than to silently produce the wrong binary. + - Backup: copies Cargo.toml to `$(mktemp -t esploro-cargo-toml.XXXXXX)` and + installs `trap restore EXIT`. The restore function copies the backup + back, then unlinks it. EXIT fires on success, normal failure, and SIGINT + so Ctrl+C mid-build still leaves the working tree pristine. + - Patch: awk full-line match against EXPECTED_LINE replaces with + PATCHED_LINE (= `tauri = { version = "2", features = [] }`), writes to a + sibling .new file, then `mv` for atomicity. Using awk rather than sed + sidesteps the GNU/BSD `sed -i` flag-arg portability foot-gun. + - Build: invokes `npm run tauri -- build --target $TARGET --config + src-tauri/tauri.mas.conf.json --features mas "$@"`. Going through npm + (rather than `cargo tauri build`) uses the Tauri CLI pinned in + package.json so the developer-local build matches whatever CI ends up + running. Extra "$@" args forward to `tauri build` for flags like + --verbose or --debug. + - Environment: TAURI_TARGET overrides the target triple. Defaults to + aarch64-apple-darwin per the PRD's "ARM only initially" scope. The var + exists for the eventual fat-binary follow-up. +- package.json: new "tauri:build:mas" script = "bash scripts/build-mas.sh". + `npm run tauri:build:mas` is now the one-liner entry point. No new + dependencies (awk, sed, mktemp all ship with macOS). +- PRD.md: + - P1 note's trailing paragraph now references P4: "The patch+build+restore + dance is automated as `scripts/build-mas.sh` (see P4)." + - New `### P4 — MAS build pipeline [DONE]` workstream captures the script + behaviour, the environment variables, and the verification matrix. + - Submission Flow → Step 2 (Build MAS binary) collapses the three-step + manual procedure to `npm run tauri:build:mas`. +- Verification: + - `bash -n scripts/build-mas.sh` clean (no shell syntax errors). + - Awk patch tested on a copy of Cargo.toml in /tmp: produces exactly the + expected single-line diff (line 39 `features = ["macos-private-api"]` → + `features = []`), no other changes. + - Direct build untouched: `npm run type-check` clean, `npm run lint` + clean, `cargo clippy --all-targets -- -D warnings` clean, `cargo test` + 22 passed (unchanged from previous step). + - MAS build untouched: `cargo clippy --all-targets --features mas -- + -D warnings` clean, `cargo test --features mas` 27 passed (unchanged + from previous step). Note: the Cursor terminal's sandboxed view of + ~/.cargo/registry/cache/ has no write permission (macOS TCC restriction + on this app, not a project issue), so MAS checks ran with + CARGO_HOME=/tmp/esploro-cargo-home. This is a local-environment quirk + only; CI on macos-latest writes to the default $HOME/.cargo and is + unaffected. +- Out of scope (intentionally): + - Wiring the script into .github/workflows/ci.yml. The current CI workflow + only exercises the Direct build (clippy + test + tauri build). Adding a + MAS job needs Apple Distribution cert + provisioning profile + + App-Specific Password for Transporter, all of which require repository + secrets that aren't configured yet. The script is the unit; CI is the + next deliverable once the App Store Connect side is set up (PRD + Submission Flow Step 1). + - Live TestFlight build with this script. That validates end-to-end IAP + flow (PurchaseSheet → SKPayment → Keychain entitlement) and is a Step 3 + Submission Flow concern, not a P4 deliverable. + ## MAS PRD P2 — Step 4: Frontend (Purchase Sheet, build-flavour branching) [DONE] - Goal: ship the MAS-flavoured licensing UI (PurchaseSheet, Restore Purchases, Manage Subscription) without forking the Vite bundle. Single index.html / diff --git a/store-listing/README.md b/store-listing/README.md new file mode 100644 index 0000000..0ce9b7b --- /dev/null +++ b/store-listing/README.md @@ -0,0 +1,28 @@ +# App Store Listing Assets + +Assets and metadata for the Mac App Store submission of Esploro. +Mirrors PRD §P3 — Store Listing Assets so the App Store Connect form can be +filled in straight from this directory without re-reading the PRD. + +## Contents + +| File | Status | Notes | +|---|---|---| +| `app-icon-1024.png` | Ready | 1024×1024 RGB PNG, no alpha, square fill — generated by `scripts/build-app-store-icon.swift` from `src-tauri/icons/icon.png`. | +| `metadata.md` | Ready | Text content (Name, Subtitle, Keywords, URLs, Description). | +| `screenshots/` | Pending | Manual capture against a running app — see `screenshots/README.md`. | +| `scripts/build-app-store-icon.swift` | Ready | Reproducible icon build. Run again whenever `src-tauri/icons/icon.png` changes. | + +## Regenerating the icon + +```bash +swift store-listing/scripts/build-app-store-icon.swift \ + src-tauri/icons/icon.png \ + store-listing/app-icon-1024.png +``` + +The script composites the rounded source icon onto a solid background sampled +from the source's own corner-most gradient pixel, then writes RGB-only PNG so +the output carries no alpha channel — both App Store requirements. Apple +applies its own rounded-rectangle mask in the App Store, so the slight square +fringe visible in the bare preview is clipped away in production. diff --git a/store-listing/app-icon-1024.png b/store-listing/app-icon-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..93e3986ec2dea3221433484d0c444f0b2b46f818 GIT binary patch literal 288417 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

*f(HBdc=7-J!KfX%?|EbzHAZQC6r@+; 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 LERCy-Kym*8HT#A< literal 0 HcmV?d00001 diff --git a/store-listing/metadata.md b/store-listing/metadata.md new file mode 100644 index 0000000..a0b74c5 --- /dev/null +++ b/store-listing/metadata.md @@ -0,0 +1,92 @@ +# App Store Connect Metadata + +Direct copy of the text content from PRD §P3 — Store Listing Assets so the +App Store Connect form can be filled in from this file alone. Update both +this file and the PRD if either drifts. + +## Identification + +| Field | Limit | Value | +|---|---|---| +| Name | 30 chars | `Esploro` | +| Subtitle | 30 chars | `Postgres & MySQL Client` | +| Bundle ID | — | `app.esploro` | +| Primary Category | — | Developer Tools | +| Pricing | — | Free download (in-app purchase for commercial use) | + +## Keywords + +100-character limit, comma-separated, no spaces (App Store counts spaces). + +``` +postgres,mysql,sql,database,query,client,developer,db,schema,postgresql +``` + +## URLs + +| Field | Value | +|---|---| +| Privacy policy | https://esploro.app/privacy | +| Terms of use | https://esploro.app/terms | +| Support URL | https://esploro.app | +| Support email | support@tandoku.hr | +| Marketing URL (optional) | https://esploro.app | + +## Description + +Use as-is. Paragraphs are separated by blank lines; bold markers in the App +Store are not rendered as markdown, so the `**` prefixes act as label cues +that read naturally even as plain text. + +``` +Esploro is a native Mac database client for PostgreSQL and MySQL. Built for developers who want to move fast without a cluttered UI. + +Browse and filter data — Open any table, sort by any column, and apply filters across multiple column types including UUIDs, timestamps, booleans, and more. Pagination keeps large tables fast. + +Write and run queries — A Monaco-powered SQL editor with syntax highlighting, keyboard-driven execution, and per-tab result sets. Export results as CSV. + +Explore your schema — Browse tables, views, columns, types, indexes, and foreign keys in the schema panel without writing a single query. + +Multiple connections — Manage all your databases from one window. Colour-coded connection tabs. + +Esploro is free for personal use. Commercial use requires a license — available as a one-time purchase or annual subscription. +``` + +## Version release notes (1.0) + +First Mac App Store release. Features parity with the existing GitHub +Releases / Homebrew build, with these MAS-specific differences: + +- Licensing via Mac App Store In-App Purchase (Personal Lifetime, Personal + Annual, Business Annual). The Direct build's license-key flow is not + used on MAS. +- Auto-updater disabled (App Store handles updates). +- Sandboxed; only outbound TCP entitlement (`com.apple.security.network.client`) + is requested — required to reach PostgreSQL / MySQL servers. +- Flat sidebar instead of the Direct build's frosted-glass vibrancy + (private API not allowed in App Store submissions). + +## In-App Purchase products + +Mirror of the table in PRD §IAP Products. All three resolve to +`LicenseTier::Commercial`; the app does not gate features between them. + +| Product ID | Type | Price | Intended for | +|---|---|---|---| +| `app.esploro.personal.lifetime` | Non-consumable | $129 | Individual commercial use, one-time | +| `app.esploro.personal.annual` | Auto-renewable subscription | $49/yr | Individual commercial use, subscription | +| `app.esploro.business.annual` | Auto-renewable subscription | $79/yr | Business / company | + +## Age rating + +4+ (no objectionable content; no user-generated content; no third-party ads). + +## App Review notes + +> Esploro connects to PostgreSQL and MySQL databases over outbound TCP only +> (`com.apple.security.network.client` entitlement). It does not host a +> server, does not collect telemetry, and does not require an account. To +> exercise the commercial-license code path during review, use one of the +> sandbox IAP products listed above. Personal use is free and does not +> require any purchase to test the core features (connection management, +> schema browsing, table viewer, SQL editor). diff --git a/store-listing/screenshots/README.md b/store-listing/screenshots/README.md new file mode 100644 index 0000000..d27b61c --- /dev/null +++ b/store-listing/screenshots/README.md @@ -0,0 +1,47 @@ +# Screenshots — Pending Manual Capture + +App Store Connect requires a minimum of three screenshots per size set, +maximum of ten. These cannot be reasonably scripted because they require +real database content, a configured connection, and a running app +window — capture them by hand against the Direct build (the visible UI is +identical to the MAS build except for the sidebar vibrancy, which is +irrelevant to App Review). + +## Required size sets + +| Display | Resolution | Required | +|---|---|---| +| MacBook Pro 14" / 16" | 2880×1800 or 1440×900 | Yes | +| MacBook Air / Pro 13" | 2560×1600 or 1280×800 | Recommended | + +## Suggested shots (in App Store gallery order) + +1. **Connection manager** — sidebar list with at least two saved connections, + one connection active (green dot), the connection form open with a + realistic-looking host/port/database/user filled in. +2. **Table browser** — a populated table loaded into the table viewer, + sorted by one column, with one column filter applied (e.g. `status = ...`). + Pick a table that includes a UUID column and a `created_at` timestamp so + the typed-cell rendering is visible. +3. **Query editor** — a non-trivial SQL query (a join with `ORDER BY` and + `LIMIT`) with the result panel showing rows below. Use the Tokyo Night + theme — it's the default for new installs. +4. **Schema browser** — a deeply expanded schema tree (database → schema → + tables → one expanded table showing column types). +5. **Settings / dark theme** — Appearance section visible, theme picker open, + demonstrating the available themes. + +## Capture tips + +- Resize the window to one of the required resolutions before capturing + (use `osascript` or Rectangle to set window size programmatically). +- Use macOS Screenshot (`⌘⇧4`, then space → click window) and crop tightly. +- Disable any system overlays (notifications, Stage Manager bezel) before + capturing. +- Save as PNG; App Store Connect accepts PNG and JPEG, PNG preserves text + edges better. +- File-name convention: `01-connections.png`, `02-table-browser.png`, + `03-query-editor.png`, `04-schema-browser.png`, `05-settings.png` — + numeric prefix preserves gallery order during upload. + +Place captured files directly in this directory. diff --git a/store-listing/scripts/build-app-store-icon.swift b/store-listing/scripts/build-app-store-icon.swift new file mode 100755 index 0000000..ad96595 --- /dev/null +++ b/store-listing/scripts/build-app-store-icon.swift @@ -0,0 +1,146 @@ +#!/usr/bin/env swift +// +// build-app-store-icon.swift +// +// Produces the App Store-compliant 1024x1024 icon from the existing +// rounded-corner source icon (src-tauri/icons/icon.png). +// +// App Store Connect requires: +// - exactly 1024x1024 px +// - PNG with no alpha channel +// - no rounded corners (Apple applies its own rounded-rectangle mask) +// +// Strategy: composite the source onto a solid square background coloured +// to match the source's own corner-most gradient pixel. We find the most- +// corner-ward fully-opaque pixel along each of the four corner diagonals +// (these sit exactly on the source's rounded-rect edge, where the gradient +// is darkest) and average them for the background fill. CGContext's alpha +// blending then handles the rounded-rect anti-aliased edge cleanly, and +// because the fill colour matches the gradient where the rounded rect +// meets the corner, Apple's icon mask cannot expose a visible fringe +// regardless of how its radius compares to the source's. +// +// Usage: +// swift build-app-store-icon.swift + +import AppKit +import CoreGraphics +import Foundation + +guard CommandLine.arguments.count == 3 else { + FileHandle.standardError.write(Data("usage: build-app-store-icon.swift \n".utf8)) + exit(2) +} + +let inPath = CommandLine.arguments[1] +let outPath = CommandLine.arguments[2] + +guard let inputData = try? Data(contentsOf: URL(fileURLWithPath: inPath)), + let inputImage = NSImage(data: inputData), + let inputCG = inputImage.cgImage(forProposedRect: nil, context: nil, hints: nil) +else { + FileHandle.standardError.write(Data("error: failed to load input image at \(inPath)\n".utf8)) + exit(1) +} + +let size = 1024 +guard inputCG.width == size, inputCG.height == size else { + FileHandle.standardError.write(Data("error: input image must be \(size)x\(size), got \(inputCG.width)x\(inputCG.height)\n".utf8)) + exit(1) +} + +let colorSpace = CGColorSpaceCreateDeviceRGB() +let bytesPerRow = size * 4 + +// Read the source into a pixel buffer once so we can sample arbitrary +// coordinates without going through CGContext.draw per sample (which is +// silently slow on this Apple Silicon machine). +var pixels = [UInt8](repeating: 0, count: size * bytesPerRow) +guard let readCtx = pixels.withUnsafeMutableBytes({ buf -> CGContext? in + CGContext( + data: buf.baseAddress, + width: size, + height: size, + bitsPerComponent: 8, + bytesPerRow: bytesPerRow, + space: colorSpace, + bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue + ) +}) else { + FileHandle.standardError.write(Data("error: failed to create read CGContext\n".utf8)) + exit(1) +} +readCtx.draw(inputCG, in: CGRect(x: 0, y: 0, width: size, height: size)) + +@inline(__always) func offset(_ x: Int, _ y: Int) -> Int { (y * size + x) * 4 } + +// Walk inward along the diagonal from a corner until we hit a fully-opaque +// pixel. That's the gradient colour right at the rounded-rect edge — +// exactly the colour the corner would have if the rect weren't rounded. +struct Sample { let r: Double; let g: Double; let b: Double } +func sampleCorner(cornerX: Int, cornerY: Int) -> Sample { + let stepX = cornerX == 0 ? 1 : -1 + let stepY = cornerY == 0 ? 1 : -1 + var x = cornerX + var y = cornerY + while x >= 0 && x < size && y >= 0 && y < size { + let idx = offset(x, y) + if pixels[idx + 3] == 255 { + return Sample( + r: Double(pixels[idx]) / 255.0, + g: Double(pixels[idx + 1]) / 255.0, + b: Double(pixels[idx + 2]) / 255.0 + ) + } + x += stepX + y += stepY + } + return Sample(r: 0, g: 0, b: 0) +} + +let cornerSamples = [ + sampleCorner(cornerX: 0, cornerY: 0), + sampleCorner(cornerX: size - 1, cornerY: 0), + sampleCorner(cornerX: 0, cornerY: size - 1), + sampleCorner(cornerX: size - 1, cornerY: size - 1), +] +let count = Double(cornerSamples.count) +let bgR = cornerSamples.map(\.r).reduce(0, +) / count +let bgG = cornerSamples.map(\.g).reduce(0, +) / count +let bgB = cornerSamples.map(\.b).reduce(0, +) / count +print(String(format: "sampled rounded-rect edge colour: r=%.3f g=%.3f b=%.3f (#%02x%02x%02x)", + bgR, bgG, bgB, + Int(bgR * 255), Int(bgG * 255), Int(bgB * 255))) + +// Render: solid background + source on top, into a no-alpha bitmap so the +// output PNG carries no alpha channel. +guard let outCtx = CGContext( + data: nil, + width: size, + height: size, + bitsPerComponent: 8, + bytesPerRow: 0, + space: colorSpace, + bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue +) else { + FileHandle.standardError.write(Data("error: failed to create output CGContext\n".utf8)) + exit(1) +} + +outCtx.setFillColor(red: bgR, green: bgG, blue: bgB, alpha: 1.0) +outCtx.fill(CGRect(x: 0, y: 0, width: size, height: size)) +outCtx.draw(inputCG, in: CGRect(x: 0, y: 0, width: size, height: size)) + +guard let outCG = outCtx.makeImage() else { + FileHandle.standardError.write(Data("error: failed to make output image\n".utf8)) + exit(1) +} + +let rep = NSBitmapImageRep(cgImage: outCG) +guard let pngData = rep.representation(using: .png, properties: [:]) else { + FileHandle.standardError.write(Data("error: failed to encode PNG\n".utf8)) + exit(1) +} + +try pngData.write(to: URL(fileURLWithPath: outPath)) +print("wrote \(outPath) (\(pngData.count) bytes, no alpha channel)")