feat(lite): runtime kill-switch + staged-rollout gate (M5b)
Adds a fail-open, local-only gate that decides whether the lite wallet may run,
so a post-release issue can disable it and rollout can be staged — without any
phone-home (privacy posture: no runtime network fetch; the per-install rollout
bucket is a hashed, never-transmitted local id).
- wallet/lite_rollout_policy.{h,cpp}: a pure decision core. Order — emergency env
kill-switch (absolute) -> local override -> manifest gates (global enable /
version floor-ceiling / blocklist / staged-rollout permille) -> fail-open allow.
Plus a JSON manifest loader (missing/invalid -> fail-open) and FNV-1a bucketing.
- Threads the decision through LiteWalletController -> LiteWalletLifecycleService:
new availability() reason RolloutDisabled blocks create/open/restore and surfaces
the gate's user-facing message via the lifecycle status.
- App::rebuildLiteWallet() resolves it from: DRAGONX_LITE_KILL_SWITCH (env), the
lite_rollout setting (auto/force_on/force_off), and a locally-cached manifest at
<config-dir>/lite_rollout.json. install id generated once via libsodium.
- Settings: persist lite_rollout override + the install id.
A signed remote fetcher can populate the manifest cache later without touching the
policy. Unit-tested (version compare, bucketing, override/env precedence, manifest
gates, staged rollout, loader fail-open, controller integration) and runtime-verified
on Linux (env kill-switch, manifest disable, control sync). Both variants build;
full suite passes; hygiene clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -196,7 +196,8 @@ LiteWalletController::LiteWalletController(WalletCapabilities capabilities,
|
||||
: bridge_(std::make_shared<LiteClientBridge>(std::move(bridge))),
|
||||
chainName_(connectionSettings.chainName),
|
||||
lifecycle_(capabilities, connectionSettings, bridge_.get(),
|
||||
LiteWalletLifecycleOptions{options.allowBridgeCalls}),
|
||||
LiteWalletLifecycleOptions{options.allowBridgeCalls,
|
||||
options.rolloutBlocked, options.rolloutMessage}),
|
||||
gateway_(capabilities, connectionSettings, bridge_.get(),
|
||||
LiteWalletGatewayOptions{options.allowBridgeCalls}),
|
||||
sync_(capabilities, connectionSettings, bridge_.get(),
|
||||
@@ -226,13 +227,14 @@ LiteWalletController::~LiteWalletController()
|
||||
|
||||
std::unique_ptr<LiteWalletController> LiteWalletController::createLinked(
|
||||
WalletCapabilities capabilities,
|
||||
LiteConnectionSettings connectionSettings)
|
||||
LiteConnectionSettings connectionSettings,
|
||||
LiteRolloutDecision rollout)
|
||||
{
|
||||
return std::make_unique<LiteWalletController>(
|
||||
capabilities,
|
||||
std::move(connectionSettings),
|
||||
LiteClientBridge::linkedSdxl(),
|
||||
LiteWalletControllerOptions{true});
|
||||
LiteWalletControllerOptions{true, !rollout.allowed, rollout.message});
|
||||
}
|
||||
|
||||
void LiteWalletController::onLifecycleResult(const LiteWalletLifecycleResult& result)
|
||||
|
||||
Reference in New Issue
Block a user