Maximum on-disk size for supporter.json. The legitimate record is
well under 1 KiB; capping the read at 16 KiB defends against
pathological inputs (10 GiB JSON file with one nested object) without
constraining future record growth.
Tag-binding HMAC key for supporter.json. The threat model here is
โraise the bar above text-editor tamperingโ โ a determined user with
the binary can extract this constant, so this is not a security
boundary against a sophisticated adversary. It is, however, sufficient
to detect casual JSON edits (โflip is_supporter to trueโ) and prevents
replay of records between machines (each install pins the HMAC against
a per-record activated_at + instance_id).
HTTP-layer split for activate_remote: takes an explicit base URL so
tests can point it at mockito::Server without bringing up Lemon
Squeezy. The production caller hard-codes LS_API_BASE.
Pure activation helper: sniffs the keyโs source, runs the matching
verification path (offline Ed25519 for ENT1-โฆ, Lemon Squeezy API
for everything else), and persists the resulting record to disk.
Override manual_verifier to bypass the embedded production public
key (e.g. tests that mint a token with a freshly generated keypair).
Production always passes None.
Canonical byte encoding of the recordโs verifiable fields. Field
ordering and length-prefixing are fixed so the same record always
serialises identically โ JSONโs object-key order is not stable enough
for HMAC input.
Single-call answer to โis this install a supporter right now?โ.
Reads the on-disk record and applies the offline grace window so
callers donโt have to thread now/grace logic of their own.
Used by gated IPC paths (e.g. custom_css) to authorise per-call.
Read the supporter record from disk. Returns None if the file is
missing, malformed, larger than MAX_FILE_BYTES, or carries a
signature that doesnโt verify under the current HMAC key. Records
with an empty signature (written by app versions before HMAC
binding shipped) parse but record_is_active will require the next
online validation to re-sign before granting supporter status.
Whether the daily background loop should hit the storefront for this
record. Manual (community) licences carry their proof on the token
itself, so the network round-trip is skipped.
Reject records whose timestamps are impossible โ e.g. activated_at
later than last_validated_at, or either timestamp far enough into
the future to suggest the user wound their clock forward to extend
the offline grace window. NTP drift is accommodated by
FUTURE_CLOCK_SKEW_TOLERANCE.