Lucerna. Gates
(Lucerna v0.0.1-alpha.0)
Server-side gates reads. The hot path has no process: an ETS lookup, a pure evaluation, done. No call funnels through a mailbox.
Guarantees (mirroring the Ruby/Node server clients):
- Reads never raise. Before the first snapshot (or against a bad
identity, or a malformed rule) they answer safe fallbacks: flag
false, experimentnil, switchtrue, evaluate empty. Stale beats default, default beats crash. - Fail-safe, then fail-stale. No snapshot yet → fallbacks with
reason
:uninitialized. Once a snapshot exists, sync failures serve the stale table — a crashed poller never degrades reads to "off".
Every point read emits [:lucerna, :gates, :evaluation] telemetry
with %{name, type, key, reason} metadata.
All functions take name: MyLucerna in opts for non-default
instances; the default instance name is Lucerna.
Summary
Functions
One identity's decisions over the entire runtime — for SSR or bootstrapping a client. Never records exposures. No runtime yet: empty maps.
The assigned variant name, or nil (not assigned / unknown key / no
runtime yet).
The flag's decision for this identity: true / false. Unknown key
or no runtime yet: false.
Debug projection of one key across all three gate kinds, with the rule-by-rule trail. Never records exposures.
The last-known compiled runtime document (wire shape), or nil.
Kill switch state — false means the guarded path IS killed. Unknown
key or no runtime yet: true (not killed).
Blocks until the first runtime load succeeds (true), the timeout
elapses (false), or the first settle was a 401/403 (raises
Lucerna.AuthError — a bad key should be discoverable). Optional to
call: reads are safe before ready. Network errors and 5xx keep
waiting — polling retries them.
Functions
One identity's decisions over the entire runtime — for SSR or bootstrapping a client. Never records exposures. No runtime yet: empty maps.
The assigned variant name, or nil (not assigned / unknown key / no
runtime yet).
This is the only read that records an exposure — and only when a
variant was assigned to a known user (an async cast to
Lucerna.Reporting; a dead Reporting process never breaks a read).
The flag's decision for this identity: true / false. Unknown key
or no runtime yet: false.
identity is nil (anonymous), a Lucerna.Identity, or a loose
map/keyword with user_id / email / traits — lenient by design,
reads never raise.
Debug projection of one key across all three gate kinds, with the rule-by-rule trail. Never records exposures.
The last-known compiled runtime document (wire shape), or nil.
Kill switch state — false means the guarded path IS killed. Unknown
key or no runtime yet: true (not killed).
Blocks until the first runtime load succeeds (true), the timeout
elapses (false), or the first settle was a 401/403 (raises
Lucerna.AuthError — a bad key should be discoverable). Optional to
call: reads are safe before ready. Network errors and 5xx keep
waiting — polling retries them.
Options: :timeout (ms, default :infinity), :name.