Rule DSL Reference
This page documents the core rule-building DSL available in konditional-core.
Rule basics
object AppFeatures : Namespace("app") {
val darkMode by boolean<Context>(default = false) {
rule(true) { platforms(Platform.IOS) }
rule(true) { locales(AppLocale.UNITED_STATES) }
}
}
Boolean sugar
val darkMode by boolean<Context>(default = false) {
enable { ios() }
disable { android() }
}
Targeting primitives
Inside a rule block (RuleScope):
locales(...)targets locale idsplatforms(...)targets platform idsversions { min(...); max(...) }targets version rangesaxis(...)targets custom axesextension { ... }custom predicaterampUp { ... }percentage rolloutallowlist(...)stable IDs that bypass ramp-upnote("...")attaches a human-readable notealways()/matchAll()mark a catch-all rule explicitly
Example
val checkout by string<Context>(default = "v1") {
rule("v2") {
platforms(Platform.IOS)
versions { min(3, 0, 0) }
rampUp { 25.0 }
note("iOS v2 rollout")
}
}
Custom predicates
extension { ... } receives the Context type for the feature.
data class EnterpriseContext(
override val locale: AppLocale,
override val platform: Platform,
override val appVersion: Version,
override val stableId: StableId,
val subscriptionTier: Tier,
) : Context
val enterpriseOnly by boolean<EnterpriseContext>(default = false) {
rule(true) { extension { subscriptionTier == Tier.ENTERPRISE } }
}
-
Guarantee: Custom predicates participate in specificity ordering.
-
Mechanism: Predicate implementations report their own
specificity()which is added to the rule total. -
Boundary: Konditional does not validate predicate correctness or determinism.
Ramp-up allowlists
allowlist(...) bypasses the ramp-up check after the rule matches by criteria.
- Boundary: It does not override rule criteria,
isActive, or the namespace kill-switch.