SDK
Kotlin
Android and plain JVM. Headless today: you get the decision, you render it. One dependency, and it exists for a reason worth reading.
Install
dependencies {
implementation("dev.ripstop:ripstop:0.1.0")
}Quickstart
// Off the main thread: init performs the first check.
val ripstop = Ripstop.init(
apiKey = "rs_pub_your_key",
appVersion = BuildConfig.VERSION_NAME,
storage = SharedPrefsStorage(context),
)
when (val decision = ripstop.check()) {
is RsDecision.ForceUpdate -> showBlockingWall(decision)
is RsDecision.SoftUpdate -> showDismissibleSheet(decision)
is RsDecision.Maintenance -> showMaintenance(decision)
RsDecision.None -> Unit // carry on
}The when is exhaustive: if the protocol grows a decision, your app stops compiling instead of silently showing nobody anything.
Storage is yours to wire
The library does not depend on Android, which is why it cannot ship a SharedPreferences implementation, and why it stays usable from plain JVM code and from tests. Four lines:
class SharedPrefsStorage(context: Context) : RipstopStorage {
private val prefs = context.getSharedPreferences("ripstop", Context.MODE_PRIVATE)
override fun read(key: String) = prefs.getString(key, null)
override fun write(key: String, value: String) { prefs.edit().putString(key, value).apply() }
override fun remove(key: String) { prefs.edit().remove(key).apply() }
}Why not the standard library for Ed25519
The JVM has had Ed25519 in JCA since Java 15. Android does not expose it below API 33. An SDK built on JCA would therefore stop verifying signatures on most of the installed base while appearing to work. That is the worst kind of failure, because nothing reports it.
So this uses net.i2p.crypto:eddsa: ~100 KB, pure Java, works everywhere the library does. It is the only dependency.
HTTP is yours too
The default transport is HttpURLConnection, which is in Android and in the JDK. An SDK you add to protect a release should not pick your HTTP client for you. Pass a Transport to route through OkHttp, or through a stub in tests.
Options
| Option | Default | What it does |
|---|---|---|
apiKey | no default | Your app’s public SDK key. Safe to ship |
appVersion | no default | The running build; rules evaluate against it |
platform | android | Which platform’s rules to read |
locale | en | Which wall copy to resolve; falls back to en per key |
minFetchIntervalMillis | 6 hours | How long a payload is fresh enough to skip the network |
timeoutMillis | 5000 | Fetch budget. After that, cache |
storage | in-memory | Pass a SharedPreferences-backed one in production |
signingKeys | pinned | Override for self-hosted deployments and tests |
transport | HttpURLConnection | Inject OkHttp, or a stub |
Threading
init and check block, deliberately. The SDK does not choose a coroutine scope or a threading model for you, so wrap them in whatever your app already uses.
Source
- github.com/ripstop-dev/ripstop-kotlin (MIT).
- 13 tests: all 62 golden vectors plus the failure paths.