Contents

naviapps/license-kit-setapp

Use LicenseKit in Setapp-distributed

Requirements

  • iOS 15 or later, or macOS 14 or later
  • Swift 6.0 or later
  • LicenseKit 2.0.0 or later
  • A Setapp-integrated app that supplies whether Setapp currently allows access

Installation

Add the packages with Swift Package Manager:

.package(url: "https://github.com/naviapps/license-kit.git", from: "2.0.0"),
.package(url: "https://github.com/naviapps/license-kit-setapp.git", from: "2.0.0")

Then depend on the products:

.product(name: "LicenseKit", package: "license-kit"),
.product(name: "LicenseKitSetapp", package: "license-kit-setapp")

Documentation

How It Works

Setapp does not give users a license key. For Setapp builds, activate LicenseKit with .automatic and let SetappLicenseProvider map the app's current Setapp access into a LicenseKit activation.

SetappLicenseProvider creates activations with:

  • source: setapp
  • planIdentifier: setapp
  • licenseKey: nil
  • activationIdentifier: nil
  • expiresAt: nil

During validation, the provider reads the latest access state from your checkAccess closure. Return false when Setapp definitively denies access. Throw when the access check cannot complete so LicenseKit can apply its refresh failure and grace-period policy. Valid Setapp refreshes keep the activation's existing plan identifier.

Use .automatic to create or replace the stored LicenseKit activation for a Setapp build. Use manager.refresh() later when your app wants LicenseKit to re-check the latest Setapp access state for an existing activation.

Usage

First, keep Setapp integrated in your app. Then pass the current Setapp access decision into SetappLicenseProvider. The activationStorage value below is a LicenseActivationStorage implementation owned by your app.

import LicenseKit
import LicenseKitSetapp

let provider = SetappLicenseProvider(checkAccess: {
  true
})

let manager = LicenseManager(
  provider: provider,
  activationStorage: activationStorage
)

let state = try await manager.activate(.automatic)

The provider does not persist Setapp account data. Persist LicenseKit activation state through your LicenseActivationStorage, and wire LicenseKit's current license state into your UI.

Use manager.refresh() when your app wants LicenseKit to re-check the latest Setapp access state through the provider.

Typical Flow

  1. Initialize Setapp in your app.
  2. Read whether Setapp currently allows access.
  3. Pass that access state into SetappLicenseProvider.
  4. Activate LicenseKit with .automatic for the Setapp build.
  5. Refresh LicenseKit when the Setapp access state changes or needs re-checking.

For non-Setapp builds, use the provider package that matches that distribution channel and activate with the request shape it expects, such as a license-key request for a license-key provider. Setapp builds should use SetappLicenseProvider with .automatic.

Checking License State

Setapp account or access checks stay in your app. LicenseKitSetapp receives only the current access state and maps it into LicenseKit state.

Use LicenseKit's state to decide whether licensed functionality should be available:

let state = try await manager.activate(.automatic)

if state.isLicensed {
  // Enable licensed functionality.
}

When your app wants to re-check the current Setapp access state, refresh the manager and read the returned state:

let result = try await manager.refresh()

if result.state.isLicensed {
  // The latest Setapp access state is still usable.
}

Responsibility Boundary

LicenseKitSetapp owns the LicenseKit provider bridge for a host-supplied Setapp access decision. Your app remains responsible for:

  • Setapp Framework initialization
  • Setapp access monitoring
  • app lifecycle hooks
  • LicenseKit activation storage
  • UI state and messaging
  • Setapp review and distribution requirements

See Setapp's documentation for Setapp Framework initialization and subscription monitoring details:

Development

Run the package check with:

make check

GitHub Actions runs the same check on pull requests and pushes to main.

The manifest resolves LicenseKit from GitHub by default. Set LICENSE_KIT_PATH to test against a local LicenseKit checkout. GitHub Actions uses this override to validate coordinated changes against the current LicenseKit repository.

Contributing

See CONTRIBUTING.md. Release notes are in CHANGELOG.md.

Security

Report vulnerabilities privately. See SECURITY.md.

License

LicenseKitSetapp is released under the MIT License. See LICENSE.

Package Metadata

Repository: naviapps/license-kit-setapp

Default branch: main

README: README.md