Skip to content

Releases: muhiro12/MHPlatform

1.20.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:48

Changes

  • Restore retained update evidence automatically before the first operation
    check, including App Intents and other headless entry points (#17).
  • Add read-only decision evaluations with policy/publication freshness,
    evaluation reasons, and restoration/refresh diagnostics (#18).
  • Coordinate evidence reads and revision-checked writes across controllers and
    processes. Older responses and failed delayed publication saves cannot roll
    back newer accepted policy. Empty publication results retain their ordering.
  • Share overlapping refresh requests while preserving independent caller
    cancellation. Cancelling the last waiter invalidates late responses.
  • Unify public schedule JSON encoding and decoding, separate private cache
    representation, and validate update feature format versions independently.
  • Add a publisher-only configuration validator that uses the runtime decoder
    and immutable-revision rules, without adding app products or dependencies.

Compatibility

Standard controller construction and operation checks keep their existing API.
Existing shared configuration documents and retained snapshots remain readable;
restoration never renews their observation timestamps.

Direct MHRemoteUpdateSchedule Codable now uses the documented shared Config
envelope and ISO 8601 dates, matching encoded() and decode(_:), rather than
the previous flat cache shape. Use MHRemoteUpdateSnapshot for retained evidence.

features.remoteUpdate.schemaVersion describes the update feature format;
the current value is 1, and omission still means 1. It is independent of the
shared envelope version and the policy revision. Unsupported feature formats
fail only that selected section. Previously distributed readers cannot learn
this check retroactively; incompatible future formats need a reader migration
and a separate endpoint while older readers remain supported.

Validation

  • 485 package tests / 600 executions passed, with no failures or skipped tests.
  • Five consumer fixtures passed 25 tests; publisher tool passed 7 behavior tests.
  • Example iOS app build passed; native build diagnostics reported no warnings
    or errors for the package and example app.
  • Three trials of 32 independent concurrent processes retained the highest
    policy revision in every trial.

Full changelog: 1.19.0...1.20.0

1.19.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 12:03

Remote update plans without weakening active requirements

  • Keep the current requirement while announcing additional timed scheduledRequirements. The strictest active minimum applies, including when plans overlap; ending or removing a plan leaves the active baseline in force.
  • Retain and reevaluate plans across restarts with the existing immutable revisions and bounded policy/publication evidence. A future unpublished version does not invalidate sufficient publication evidence for the current minimum.
  • Add MHRemoteConfigSection<Value> so missing or invalid feature payloads remain observable without discarding valid siblings from one shared response. Broken JSON, envelope/identity failures, and cancellation still reject the shared request. Failed update sections cannot renew retained update evidence.

Compatibility and adoption

  • Standard endpoint/Store-ID initialization, lifecycle preparation, and operation checks are unchanged. Existing schedule/feature initializers, 1.18.0 documents, and retained snapshots remain supported.
  • Deploy this reader before relying on scheduledRequirements: older readers ignore the new field and enforce only the baseline. Keep that baseline when announcing plans. Clear both the baseline and all plans, with a higher revision, for full cancellation.
  • No announcement feature or additional app-side plan-selection/recovery machinery is introduced.

See the remote update adoption guide for the wire format, failure boundaries, and rollout order.

Full changelog

1.18.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 10:58

Changes

  • Add the standalone, Foundation-only MHRemoteConfig product for shared HTTPS fetching, app identity validation, and typed configuration decoding. It is also available through MHPlatformCore and MHPlatform.
  • Support static update policies without periodic publisher renewal. A validated network fetch renews bounded retained evidence; disk reads, failures, and reused responses do not.
  • Keep planned activation, immutable revisions, postponement, explicit cancellation, and App Store publication evidence separate. Unknown evidence remains distinguishable from a confirmed lack of an update requirement.
  • Omit the storefront country by default, with an optional explicit storefront override for publication lookup.

Migration from 1.17.0

This release deliberately replaces the scheduled-update contract before operational adoption. It is an explicit minor-release exception to normal source and wire compatibility.

  • Rename the standard initializer's policyURL: argument to configurationURL:.
  • Use the common configuration envelope with features.remoteUpdate. Remove publisher-authored issuedAt and validUntil; each feature owns its policy and revisions.
  • Advanced providers now return MHRemoteConfigResponse<MHRemoteUpdateSchedule> with the original network observation. Use policyLifetime: in place of maximumValidity:.
  • Existing 1.17.0 snapshots are not migrated or reinterpreted. prepare() attempts a fresh fetch after an incompatible cache; without valid evidence, protected operations remain unavailable.
  • Set storefront: "jp" explicitly to retain 1.17.0's reference store. Omission uses Apple's service default, which is not a global catalog.

See the migration and adoption guide. Existing legacy comparison and evaluator primitives remain available. This package release does not migrate consuming apps or deploy their configuration.

Full Changelog: 1.17.0...1.18.0

1.17.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 13:46

What's New

  • Adds MHRemoteUpdate, a Foundation-only module available through
    MHPlatformCore, MHPlatform, or its standalone product.
  • Provides version comparison, identity-validated App Store lookup, and explicit
    notRequired, updateRequired, and unavailable decisions.
  • Retains scheduled update requirements across launches and re-evaluates
    activation, expiry, installed version, and publication evidence when checking
    an operation.
  • Adds standard App Store integration with a policy URL and Store ID,
    package-managed persistence, preparation, and operation checks.

Adoption

import MHPlatformCore

let updates = try MHRemoteUpdateController(
    appStoreID: appStoreID,
    policyURL: policyURL
)
let preparation = try await updates.prepare()

Call prepare() at startup and foreground entry points. Place
checkOperationAllowed() before protected operations; it requires confirmed
permission and refreshes once when evidence is unavailable. App-designated
low-impact operations can explicitly use .allowWhenUnavailable. A confirmed
update requirement blocks both rules.

Standard integration uses the jp storefront, a maximum policy-document
lifetime of 30 days, and publication evidence valid for 24 hours. Apps supply
release policy, classify operations, and connect lifecycle hooks, UI, and
logging. Adoption requires app changes; existing binaries do not acquire
enforcement automatically.

Publish operational policy independently of app source releases. See the
remote update adoption guide
for the JSON contract, deployment approach, legacy migration, and advanced
overrides.

Reliability

  • Preserves immutable policy identity through JSON round trips by normalizing
    dates to whole seconds and rejecting collapsed intervals.
  • Retries failed initial cache reads on a later preparation call until evidence
    initializes.
  • Bypasses local HTTP cache when observing App Store publication, preventing
    stale metadata from renewing publication evidence.

Compatibility and Verification

This is an additive minor release from 1.16.0; existing public APIs remain
available. Verification includes 114 relevant iPhone Simulator tests, five
consumer fixtures, SwiftLint, the Example app build, and eight version-selection
tests. App-specific adoption and live Store or policy deployment remain separate
verification steps.

Full Changelog: 1.16.0...1.17.0

1.16.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 07:08

Full Changelog: 1.15.0...1.16.0

1.15.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 07:43

Full Changelog: 1.14.0...1.15.0

1.14.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 03:57

Native ads: migration required

MHPlatform 1.14.0 adopts GoogleMobileAdsWrapper 2.0.0 and replaces the old native-ad size API with layout choices. This is an explicitly documented breaking transition within a minor release. There are no compatibility aliases.

Previous API Replacement
MHNativeAdSize.small MHNativeAdLayout.compact
MHNativeAdSize.medium MHNativeAdLayout.media
runtime.nativeAdView(size:) runtime.nativeAdView(layout:)
MHRuntimeNativeAdViewFactory.makeView(size:) MHRuntimeNativeAdViewFactory.makeView(layout:)
// Before
runtime.nativeAdView(size: .small)
runtime.nativeAdView(size: .medium)

// After
runtime.nativeAdView(layout: .compact)
runtime.nativeAdView(layout: .media)

Custom native-ad factory closures now receive MHNativeAdLayout and are @MainActor. Call makeView(layout:) on the main actor as well, matching SwiftUI view creation. Update stored selection properties, picker tags, and switches accordingly. Consumers do not need to import Google SDK types.

If an app persists the old enum raw values, migrate "small" to "compact" and "medium" to "media" before decoding MHNativeAdLayout. MHPlatform does not automatically rewrite app-owned preferences.

The adapter waits for shared SDK initialization before requesting ads. The code-built views use the available width and natural height, with compact text and media-forward layouts. Apps retain ownership of backgrounds, padding, placement, and optional frame constraints. Recheck any fixed heights chosen for the previous Small or Medium layouts.

Consent orchestration and Privacy Options integration are not enabled automatically by this update. Complete applicable consent and audience configuration before starting the runtime or displaying ads. Shared orchestration remains tracked in #14; per-app integration remains separate work.

Preferences and startup

This release also includes the preference improvements accumulated since 1.13:

  • Add MHPreferenceRegistry and synchronous startup migration, with async-only step rejection before migration or cleanup begins.
  • Add explicit defaults-selection initializers for preference and deep-link stores.
  • Include domain cleanup allowlists in diagnostics.
  • Document descriptor-first migration, external raw-key preservation, startup ordering, and enum-backed AppStorage shorthand.

Read the preference migration guide before enabling migration or whole-domain cleanup. Existing destination values remain protected; callers own the complete storage allowlist and serialization of migration runs.

Dependencies

Dependency Resolved version
GoogleMobileAdsWrapper 2.0.0 (updated)
Google Mobile Ads SDK 13.10.0 (updated)
SwiftLintPlugins 0.65.1 (updated)
StoreKitWrapper 1.4.0 (already current)
LicenseList 2.5.0 (minimum raised to refresh older consumer resolutions)
Google User Messaging Platform 3.1.0 (already current)

Versioning

Releases now use MAJOR.MINOR.PATCH. Automatic releases increment the minor number and reset patch to zero; the next automatic release after this one is 1.15.0. Manual workflow dispatch supports explicit major or patch releases. Legacy two-component tags are normalized for version selection, and rerunning an already tagged commit does not publish a second release.

Following the 1.14.0 transition exception above, incompatible public API changes require a major release.

Verification

  • iOS package tests: 342 passed, zero failures; one non-iOS-only test is not applicable to the iOS run.
  • Package build including test targets, macOS umbrella build, and watchOS Simulator umbrella build passed.
  • SwiftLint, model-directory rules, and all five consumer fixture checks passed.
  • Eight isolated Git-based release-version tests passed.
  • Example Simulator smoke: actual Google test ad displayed through Compact → Media → Compact with natural List sizing; final Example build passed with current dependencies and no actor-isolation warning.

The final iOS package test used official xcodebuild after the Xcode integration timed out and disconnected. Real-device, purchase/restore, production consent, and full ad-policy validation are outside this release's targeted verification. An adjacent unavailable-subscription row appeared blank in the Example Simulator; this was recorded separately from the successful ad layout check.

1.13

Choose a tag to compare

@github-actions github-actions released this 13 Sep 06:24

Changes

  • Adopt StoreKitWrapper 1.4 and derive premium status from verified purchased product identifiers independently of product metadata. A failed catalog request no longer makes a verified subscription appear inactive.
  • Adopt GoogleMobileAdsWrapper 1.4 and Google Mobile Ads SDK 13.9.0, including native ad layout and loading lifecycle fixes.
  • Use the wrapper's typed ad-size API inside MHAppRuntimeAds while preserving the public MHNativeAdSize cases.
  • Add a local StoreKit subscription catalog and complete the official test-ad configuration in the example app. Remove empty ad spacing when ads are disabled.
  • Expand regression coverage for purchase updates, premium ad suppression, and native ad adapter configuration.

Integration notes

  • MHAppRuntime.StartStore and its purchased-product-identifier callback are MainActor-isolated. Custom startup bridges must preserve this isolation. Invoke a stored bridge from the main actor or await it from another actor.
  • The minimum deployment targets remain iOS 18, macOS 15, and watchOS 11. The package requires a Swift 6.2-capable toolchain.

Full Changelog: 1.12...1.13

1.12

Choose a tag to compare

@github-actions github-actions released this 23 Jun 03:26

Full Changelog: 1.11...1.12

1.11

Choose a tag to compare

@github-actions github-actions released this 13 Jun 07:01

Full Changelog: 1.10...1.11