Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 14:33
· 1 commit to main since this release

[0.6.0] - 2026-09-06

Added

  • require_signed_config — Ed25519 verification of server-owned product
    settings.
    The Keylight worker has signed the trial length and free-tier flag
    on every route that delivers them since 2026-09-06; nothing in this SDK
    checked those signatures. verify_config now does, over the payload format
    shared byte-for-byte with the Swift, C#, C++ and JS SDKs.

    Off by default, and it should stay off unless you know your product is
    signed.
    The worker signs a product's settings only once that product has a
    trial length configured in the dashboard; every other product is served
    unsigned, and enabling this against one of those would reject legitimate
    responses and pin the install to the seed you compiled in.

    When enabled, settings that do not verify are never cached — the SDK keeps
    your seed rather than trusting what the server claimed. The check lives at the
    single point where settings are merged, so no route can write settings around
    it: /config, validate and the keyless beacon all pass through it. In
    particular validate now carries the signature fields it previously dropped.

    Trust is rooted in the trusted_keys you compile in. The SDK does not fetch a
    keyset at runtime, on purpose: keys fetched over the same connection that
    serves the settings would let anyone able to forge one forge the other. The
    trade-off is that rotating to a new key id leaves builds already in the wild
    on their last known settings until they update — they freeze, they do not
    break.

    Verification is pinned by a golden vector captured from the live worker, the
    same one the other SDKs pin.

  • refresh_after_upgrade(timeout, poll_interval) — brief poll-revalidation
    after an upgrade.
    Call it when the customer returns from completing an
    upgrade so new entitlements unlock in the running app within seconds,
    instead of waiting for the normal refresh cadence. It re-validates against
    the server every poll_interval (clamped to a 100ms floor) until either
    the license's entitlement set or its resolved state changes, or timeout
    elapses — covering the gap between checkout completing and the payment
    provider's webhook actually reaching Keylight. Returns false on timeout
    or when no license is stored (the latter makes no network call). Parity
    with Swift's LicenseManager.refreshAfterUpgrade(timeout:pollInterval:).

    This call blocks for up to timeout — run it on a background thread
    (std::thread::spawn), not on a UI/main thread. A seat-only upgrade whose
    entitlement set and state end up unchanged (e.g. a device-cap bump with no
    feature/tier change) is invisible to it and will run to timeout; the
    normal refresh cadence still picks that up on its own schedule.

  • Tauri plugin: active_revalidate and refresh_after_upgrade commands,
    exposing both to the JS side of a Tauri app.