The PhoenixKit core surface this package calls, in one list, checked against whichever core actually resolved.
mix.exs requires phoenix_kit ~> 2.0 — every core 2.x, and nothing else;
core 1.7 is excluded because 2.0.0 squashed the migration chain to a V135
floor this module is verified against (see core_pin_conformance_test.exs).
Admitting a minor is not the same as working on one: 2.1 may move or drop
anything. What this module buys is a legible failure — the surface is declared
here, so a core that moved something reports a named list at boot and in the
test suite, instead of raising UndefinedFunctionError at whichever call site
a user happens to reach first.
Four lists, because the failure modes differ:
runtime_calls/0— called unguarded. A gap here is a broken feature.optional_calls/0— already behindCode.ensure_loaded?/1orfunction_exported?/3at the call site, so a gap degrades quietly by design (activity logging, dashboard registry).compile_time_modules/0—used orimported. A gap here fails the build before any check in this module can run; they are listed so the inventory of what core owes this package is complete in one place.sibling_calls/0— aPhoenixKit.*namespace owned by another package rather than by core, checked only when that package is installed.
Not covered: behaviour semantics. A core that keeps Settings.get_setting/2
but changes what it returns passes every check here and still breaks billing.
Only the test suite against a real core can catch that.
Summary
Functions
:ok, or {:error, report} naming every gap against the resolved core.
Core modules billing uses or imports.
The resolved core version, or nil when :phoenix_kit is not loaded.
Logs check/0's report when the resolved core is missing something.
Core modules from compile_time_modules/0 that are not loadable.
Guarded core calls the resolved core does not export.
Unguarded core calls the resolved core does not export.
Sibling-package calls whose module is installed but no longer exports them.
Core functions billing calls behind an existence guard.
Core functions billing calls without a guard.
Calls into sibling phoenix_kit_* packages under a PhoenixKit.* namespace.
Types
Functions
@spec check() :: :ok | {:error, String.t()}
:ok, or {:error, report} naming every gap against the resolved core.
The report is a human-readable string meant for a log line or a test failure message — it names the core version so a bug report says which core it was.
@spec compile_time_modules() :: [module()]
Core modules billing uses or imports.
@spec core_version() :: String.t() | nil
The resolved core version, or nil when :phoenix_kit is not loaded.
Read from the application spec rather than a compile-time constant, so it reports the core actually running, not the one this package was built against.
@spec log_check() :: :ok
Logs check/0's report when the resolved core is missing something.
Called from the supervisor, so a host that upgraded core past what this
package understands is told once at boot, by name, instead of discovering it
one crash at a time. Missing unguarded calls log at :error, everything
else at :warning — the former is a broken feature, the latter is degradation
the call sites already handle.
@spec missing_compile_time_modules() :: [module()]
Core modules from compile_time_modules/0 that are not loadable.
@spec missing_optional_calls() :: [mfa_tuple()]
Guarded core calls the resolved core does not export.
@spec missing_runtime_calls() :: [mfa_tuple()]
Unguarded core calls the resolved core does not export.
@spec missing_sibling_calls() :: [mfa_tuple()]
Sibling-package calls whose module is installed but no longer exports them.
An uninstalled sibling returns nothing: not having phoenix_kit_emails is a supported configuration, not a compatibility break.
@spec optional_calls() :: [mfa_tuple()]
Core functions billing calls behind an existence guard.
@spec runtime_calls() :: [mfa_tuple()]
Core functions billing calls without a guard.
@spec sibling_calls() :: [mfa_tuple()]
Calls into sibling phoenix_kit_* packages under a PhoenixKit.* namespace.
Checked only when the module is loaded — see missing_sibling_calls/0.