LemonCore. Env
(lemon_core v0.1.0)
View Source
Typed, declarative environment-variable registry for Lemon.
This module is the framework: typing, aliases, defaults, resolution and
redaction-safe reporting. The declarations themselves belong to whichever
app reads the variable — each app ships a LemonCore.Env.Registry module
and the runtime lists them under :env_registries (see registries/0).
all_declared/0 aggregates whatever is loaded, so a build with only some
of the umbrella's apps reports exactly the variables its code can read.
It does not yet replace the scattered System.get_env/1 call sites across
the umbrella -- callers migrate to LemonCore.Env.get/2 in a later phase.
Until then, this registry is the living documentation: see
docs/config-registry.md for the reference table.
Usage
# Look up a declared variable by name, applying its declared type,
# aliases, and default:
LemonCore.Env.get(:lemon_arena_poker_models)
#=> ["anthropic:claude-sonnet-4-20250514", "openai:gpt-5"]
LemonCore.Env.get(:lemon_web_port)
#=> 4080
# Raw (undeclared) typed reads, e.g. for one-off/local variables that
# don't warrant a registry entry:
LemonCore.Env.int("SOME_TIMEOUT_MS", 5_000)
LemonCore.Env.bool("SOME_FLAG", false)
LemonCore.Env.list("SOME_HOSTS")
# Every declared variable, for tooling (e.g. `mix lemon.doctor`) or
# generating docs:
LemonCore.Env.all_declared()Declaration shape
Each declared variable is a map with:
:name- atom key used withget/2, e.g.:lemon_web_port:env_var- the canonical environment variable name:aliases- legacy/fallback environment variable names checked (in order) if:env_varis unset. Existing grandfathered non-conforming names live here rather than as the primary:env_var-- see the naming convention section ofdocs/config-registry.md.:type- one of:string,:integer,:float,:boolean,:list,:bytes(parsed viaLemonCore.Config.Helpers.get_env_bytes/2):default- value used when nothing resolves from the environment:doc- one-line human-readable description:secret?- whether the value should be redacted in any reporting surface (seeLemonCore.Env.Resolved):required?- reserved for call-site opt-in;get/2also accepts a per-callrequired: trueoption independent of this flag:area- a coarse grouping used to organizedocs/config-registry.md:apps- umbrella app(s) that read this variable today
Type casting
Casting is delegated to LemonCore.Config.Helpers, the umbrella's
existing env-parsing toolkit, so behavior (bool truthy/falsy spellings,
duration/byte-size suffixes, list delimiters) stays consistent with
every other config reader in the codebase.
Summary
Functions
Returns every declared environment variable (name, env var, type, default, doc, secret?/required? flags, area, and owning apps).
Gets a raw (undeclared) boolean environment variable.
Returns the declarations for a single :area (e.g. :agent, :gateway,
:arena). See all_declared/0 for the full list of areas in use.
Returns the declaration for name, or nil if nothing is declared under
that name.
Resolves a declared environment variable by its registry name.
Gets a raw (undeclared) integer environment variable.
Gets a raw (undeclared) list environment variable, split on delimiter.
The registry modules consulted by all_declared/0, in order.
Returns a redaction-safe snapshot of every declared variable's current
resolved value, tagged with its resolution :source (:env, :alias,
or :default). Secret-flagged values are redacted whenever the snapshot
is inspected/logged (see LemonCore.Env.Resolved).
Gets an optional raw (undeclared) string environment variable.
Types
@type var_type() :: :string | :integer | :float | :boolean | :list | :bytes
Functions
@spec all_declared() :: [declaration()]
Returns every declared environment variable (name, env var, type, default, doc, secret?/required? flags, area, and owning apps).
This is the source of truth behind docs/config-registry.md and is
intended for tooling (e.g. a future mix lemon.doctor check) as well as
interactive exploration.
Gets a raw (undeclared) boolean environment variable.
@spec by_area(atom()) :: [declaration()]
Returns the declarations for a single :area (e.g. :agent, :gateway,
:arena). See all_declared/0 for the full list of areas in use.
@spec describe(atom()) :: declaration() | nil
Returns the declaration for name, or nil if nothing is declared under
that name.
Resolves a declared environment variable by its registry name.
Resolution order: env_var -> each of aliases (in declared order) ->
opts[:default] -> the declaration's own :default. The resolved value
is cast according to the declaration's :type.
Options
:default- override the declaration's default for this call:required- if true (or if the declaration hasrequired?: true), raisesArgumentErrorwhen the value resolves tonil/""/[]
Examples
iex> LemonCore.Env.get(:lemon_web_port)
4080
iex> System.put_env("LEMON_ARENA_POKER_MODELS", "anthropic:claude-sonnet-4-20250514")
iex> LemonCore.Env.get(:lemon_arena_poker_models)
["anthropic:claude-sonnet-4-20250514"]
Gets a raw (undeclared) integer environment variable.
Gets a raw (undeclared) list environment variable, split on delimiter.
@spec registries() :: [module()]
The registry modules consulted by all_declared/0, in order.
Defaults to lemon_core's own declarations so the library works unconfigured;
the reference runtime lists every app's registry in config/config.exs.
Modules that are not loaded are skipped rather than raising.
@spec snapshot() :: [LemonCore.Env.Resolved.t()]
Returns a redaction-safe snapshot of every declared variable's current
resolved value, tagged with its resolution :source (:env, :alias,
or :default). Secret-flagged values are redacted whenever the snapshot
is inspected/logged (see LemonCore.Env.Resolved).
Gets an optional raw (undeclared) string environment variable.