Remote config, update walls and maintenance mode for iOS. Decided at the edge, verified on device, zero dependencies.
Not tagged yet, so add the package by URL and track main:
// Package.swift
.package(url: "https://github.com/ripstop-dev/ripstop-swift", branch: "main")Or in Xcode: File → Add Package Dependencies…, paste the URL, choose the main branch.
import Ripstop
let ripstop = await Ripstop.initialize(apiKey: "rs_pub_your_key")
// SwiftUI
RipstopShell(gate: ripstop, onOpenURL: { UIApplication.shared.open($0) }) {
ContentView()
}CFBundleShortVersionString is read from the bundle, so there is no literal to
forget to bump. Pass appVersion: when you need to override it (a staged
rollout pretending to be an older build, or a test) and yours wins. If the
bundle will not say what it is running, the SDK has no opinion and your app
runs. CFBundleVersion is deliberately not folded in: the protocol orders
semantic versions, and a build number is not part of one.
switch await ripstop.check() {
case .forceUpdate(let title, let body, let storeUrl): break // blocked
case .softUpdate(_, _, _, let canSnooze): break // a nudge
case .maintenance(_, let message, let endsAt, _, _, _): break // down on purpose
case .none: break // carry on
}The switch is exhaustive: if the protocol grows a decision, your app stops compiling instead of silently showing nobody anything.
let enabled = await ripstop.values["checkout_enabled"]?.boolValue ?? true| Situation | What happens |
|---|---|
| No network | The last signed payload drives the decision |
| No network, no cache | .none, so your app runs unrestricted |
| Server returns 500, or times out | Cache, then .none |
| Signature doesn't verify | Treated as a failure. A forged payload can never wall your app |
| Cache edited on device | Re-verified on read, so it grants nothing |
| Wall up, then network lost | The wall stays, until a fresh signed payload clears it |
Turning on aeroplane mode is not a way out of an update wall, and a compromised CDN cannot show your users anything, because it does not hold the signing key.
Every Ripstop SDK runs the same vectors.json: version ordering, evaluation
order, snooze accounting, the fail-open state machine. swift test runs it
here, alongside tests that sign with a real CryptoKit key pair.
Full docs: ripstop.dev/docs/swift
MIT
