Skip to content

feat(mobile): v1.18.0 "Dormant" - monetization scaffold#107

Merged
doublegate merged 3 commits into
mainfrom
feat/v1.18.0-dormant
Jul 14, 2026
Merged

feat(mobile): v1.18.0 "Dormant" - monetization scaffold#107
doublegate merged 3 commits into
mainfrom
feat/v1.18.0-dormant

Conversation

@doublegate

Copy link
Copy Markdown
Owner

Summary

  • New standalone rustysnes-monetization UniFFI crate (Mobile Phase 5): a dormant
    entitlement/ad-pacing policy scaffold (check_entitlement, default_ad_pacing_policy,
    should_show_ad). Never a dependency of the deterministic core — no rustysnes-core/
    -cpu/-ppu/-apu/-cart dependency in either direction. Every concrete pricing/pacing
    number is an explicit placeholder default, not a committed figure (unlike RustyNES's own
    already-shipped module) — the real store-launch decision stays with
    docs/mobile-readiness.md's standing "Mobile Phase 6" gate.
  • Wired into both mobile shells as an inert dependency: compiled in, called once at startup,
    logged only, no real store SDK calls, no paywall/UI shown.
  • Android: build.gradle.kts builds the new crate's native .so alongside the existing two
    and generates its own separate UniFFI Kotlin bindings. Verified for real: rebuilt via a real
    Gradle build, installed on the real AVD, launched, and confirmed via logcat:
    monetization scaffold (dormant): unlocked=true minIntervalSecs=300 sessionsBeforeFirstAd=3,
    app stayed alive afterward.
  • iOS: scripts/build-ios-xcframework.sh gained a third crate to build/package
    (RustysnesMonetizationFFI.xcframework) and ios/project.yml gained it as a target
    dependency. The Rust staticlib/rlib outputs cross-compile for real in this dev environment;
    the cdylib output the bindgen/xcframework step needs only links with a real Apple toolchain
    (confirmed pre-existing, not introduced by this PR — rustysnes-mobile's own cdylib fails
    identically in isolation), so the full pipeline is compile-verified via ios.yml's real macOS
    CI only, matching the platform's standing scaffolded-only disposition since v1.16.0.

Test plan

  • cargo test --workspace --exclude rustysnes-android — all green
  • cargo clippy --workspace --exclude rustysnes-android --all-targets -- -D warnings — clean
  • cargo fmt --check — clean
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --exclude rustysnes-android --no-deps — clean
  • cargo build -p rustysnes-core --target thumbv7em-none-eabihf --no-default-features — no_std gate green
  • cargo deny check — advisories/bans/licenses/sources all ok
  • cargo audit — 0 vulnerabilities
  • Real Android Gradle build + AVD install/launch + logcat verification of the dormant scaffold log line, app remained stable (no crash)
  • Real aarch64-apple-ios staticlib/rlib cross-compile for rustysnes-monetization
  • Full iOS xcframework + xcodebuild pipeline — pending ios.yml's macOS CI run on this PR

🤖 Generated with Claude Code

…th shells

New standalone rustysnes-monetization UniFFI crate (dormant entitlement/
ad-pacing policy scaffold, never a dependency of the deterministic core,
placeholder-only figures). Wired into Android (real Gradle build, AVD
install, logcat-verified) and iOS (staticlib/rlib cross-compiles for real
here; the cdylib/xcframework pipeline needs the real macOS ios.yml CI
runner, matching this platform's standing scaffolded-only disposition).
Copilot AI review requested due to automatic review settings July 12, 2026 22:34

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the rustysnes-monetization crate (Mobile Phase 5), a standalone UniFFI library providing a dormant entitlement and ad-pacing policy scaffold. It is integrated as an inert dependency into both the Android and iOS mobile shells, where it is invoked once at startup for logging purposes only. Feedback on the changes identifies a potential runtime crash in the Swift implementation when casting a negative Double to UInt64 if the system clock is set before 1970, and suggests safeguarding the conversion using max(0.0, ...).

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread ios/RustySNES/Sources/RustySNESApp.swift Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new mobile-only UniFFI crate (rustysnes-monetization) that provides a dormant entitlement + ad-pacing policy API, and wires it into both Android and iOS shells as an inert startup-time log (no gating/UI/SDK integration). It keeps the determinism boundary intact by not depending on any rustysnes-* core chip/core crates and by keeping the monetization APIs pure and host-time-injected.

Changes:

  • Add new standalone crates/rustysnes-monetization UniFFI crate with placeholder policy APIs (check_entitlement, default_ad_pacing_policy, should_show_ad) plus unit tests.
  • Integrate the new crate into Android (Gradle cargo ndk build + separate UniFFI bindgen output) and iOS (xcframework packaging + Swift bindgen generation) as a one-time startup log.
  • Update iOS/Android app versions and document the Mobile Phase 5 verification status in docs/mobile-readiness.md and CHANGELOG.md.

Reviewed changes

Copilot reviewed 11 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/build-ios-xcframework.sh Builds/packaging updated to include the new monetization crate and generate Swift bindings + xcframework.
ios/RustySNES/Sources/RustySNESApp.swift Adds an iOS startup hook to log the dormant monetization scaffold state.
ios/project.yml Bumps iOS marketing version and adds the monetization xcframework dependency.
docs/mobile-readiness.md Documents Mobile Phase 5 verification for the new monetization scaffold and inert shell wiring.
crates/rustysnes-monetization/src/lib.rs New UniFFI-exported pure policy API + tests for entitlement and ad pacing.
crates/rustysnes-monetization/src/bin/uniffi-bindgen.rs New bindgen helper binary (feature-gated) for UniFFI Swift/Kotlin generation.
crates/rustysnes-monetization/Cargo.toml New crate manifest defining crate-types and UniFFI dependency/feature gating.
CHANGELOG.md Adds Unreleased notes describing the new crate and inert Android/iOS wiring.
Cargo.toml Adds rustysnes-monetization to the workspace members list.
Cargo.lock Records the new rustysnes-monetization package entry.
android/app/src/main/kotlin/com/doublegate/rustysnes/MainActivity.kt Logs dormant monetization scaffold once at Android startup via generated UniFFI bindings.
android/app/build.gradle.kts Builds/copies the new .so and adds a dedicated UniFFI bindgen task + source dir.
.gitignore Ignores generated Swift bindings for the monetization UniFFI surface.

Comment thread ios/RustySNES/Sources/RustySNESApp.swift
Comment thread crates/rustysnes-monetization/src/lib.rs Outdated
Comment thread crates/rustysnes-monetization/Cargo.toml
…ollision

Real macOS CI failure: xcodebuild copies every "library"+-headers
xcframework's headers into one directory shared across the whole
target, so two separate per-crate xcframeworks each contributing a
same-named module.modulemap produced "Multiple commands produce"
build failure. Merge rustysnes-mobile and rustysnes-monetization into
one combined RustysnesFFI.xcframework via libtool -static + a combined
umbrella modulemap instead.
Gemini/Copilot review: UInt64(Date().timeIntervalSince1970) traps if
the device clock is set before 1970 - clamp with max(0.0, ...).
Copilot review: Entitlement's doc comment claimed an "and why" the
struct doesn't have a field for - trimmed to match the actual API.
@doublegate
doublegate merged commit ec54ab7 into main Jul 14, 2026
13 checks passed
@doublegate
doublegate deleted the feat/v1.18.0-dormant branch July 14, 2026 23:08
@doublegate doublegate mentioned this pull request Jul 14, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants