Module-owned versioned migrations for phoenix_kit_billing — the
decentralized-migrations protocol that core's mix phoenix_kit.update
discovers via migration_module/0: current_version/0 +
migrated_version_runtime/1 + idempotent up/1 + version-aware
down/1. phoenix_kit_legal (over phoenix_kit_consent_logs) is the
closest sibling example of this exact situation — a core-created table
whose future shape a module chain adopts.
Ownership situation — read before touching
phoenix_kit_payment_provider_configs is one of core's V135 baseline
tables. Nothing in this package's lib/ reads or writes it today — it
is currently orphaned application-code-wise, though core still creates
it (and can still roll it back on its own baseline down). Payment
provider credentials this package actually reads and writes today live
in phoenix_kit_settings, via PhoenixKitBilling.Providers — this
version changes NONE of that.
V1 is purely an ADOPTION step:
- on existing installs the table is already there (core V135), the
CREATE TABLE IF NOT EXISTSfinds it, and the only new object is thepkb_schema:1marker — from then on this chain owns the table's future shape; - on a hypothetical future install whose core baseline no longer creates the table, the same statements create it — shape-identical to core's V135, with core's exact index and constraint names.
Because V1 changes no shape, core's ExpectedSchema manifest (which
still audits the V135 shape of this table) stays accurate and NO core
release is required for this version.
What down/1 is NOT
down/1 unstamps the version marker; it NEVER drops
phoenix_kit_payment_provider_configs. The table is core-created, and
rolling back this module's chain must not destroy it — only core's own
baseline rollback does that. The same invariant holds for V2 below —
down/1 never drops a core-created table, even one whose shape this
chain now owns.
The migrated version is tracked as a pkb_schema:<N> COMMENT on
phoenix_kit_payment_provider_configs (the marker convention from the
projects/legal chains, namespaced). A marker-less table reads as
version 0 — the core-baseline shape before this chain existed.
V2 — phoenix_kit_currencies gets a shape
phoenix_kit_currencies is likewise a core-created table (V31
baseline), and likewise untouched by V1 above (an unrelated table). V2
is this chain's first shape-CHANGING step, entirely on
phoenix_kit_currencies:
- a partial unique index
phoenix_kit_currencies_default_uidxon(is_default) WHERE is_default— today uniqueness of the default currency is held only by the transaction inset_default_currency/1, not by the database: twois_default = truerows raiseEcto.MultipleResultsErrorout ofget_default_currency/0(Ecto.Repo.one/2). This index is also a prerequisite for aLIMIT-lessWHERE is_defaultbackfill a future chain runs against this table, so it must exist before that backfill runs, not merely by the time it finishes. A host can already BE in the two-default state the index forbids, so V2 demotes every default but one (lowestsort_order, then oldest) immediately before creating the index — otherwiseCREATE UNIQUE INDEXaborts the whole chain on exactly those databases. ThatUPDATEis the one row-level write this chain makes to a core-created table, and it only repairs a state no reader can handle:get_default_currency/0raises on it today. rounding_rule character varying(16) NOT NULL DEFAULT 'exact'andrate_updated_at timestamp with time zone— both additions with no reader anywhere in this version; the default reproduces today's rounding behavior exactly, so nothing observable changes for any host that migrates to V2.
Both ride in the same chain version because this chain moves one
version per module per release, not one version per column. down/1
to below V2 drops the index and both columns — never the table.
Summary
Functions
Rolls back to target (:version in opts). Never drops the table — see the moduledoc.
The SQL down/1 executes, as data. Below V2 this also drops the
phoenix_kit_currencies index and columns V2 added — never the
phoenix_kit_payment_provider_configs table itself.
The chain version currently applied in the database, read OUTSIDE a
migration (the protocol shape core's update task calls — opts with
:prefix): the pkb_schema:<N> marker when present; a marker-less or
foreign-comment table reads as 0 (core-baseline shape — V1 is purely
adoptive, there is no pre-chain content to defend).
Applies every chain version up to target (:version in opts, default current_version/0); idempotent.
The SQL up/1 executes, as data — the testable single source. The
ownership test parses these statements to prove that the object names
are core's V135 names, that the CREATE TABLE stays shape-identical to
core's ExpectedSchema manifest, and that nothing here can drop the
table.
The table carrying the pkb_schema:<N> marker (auditor contract).
Functions
@spec current_version() :: pos_integer()
Rolls back to target (:version in opts). Never drops the table — see the moduledoc.
@spec down_statements(String.t(), non_neg_integer()) :: [String.t()]
The SQL down/1 executes, as data. Below V2 this also drops the
phoenix_kit_currencies index and columns V2 added — never the
phoenix_kit_payment_provider_configs table itself.
The chain version currently applied in the database, read OUTSIDE a
migration (the protocol shape core's update task calls — opts with
:prefix): the pkb_schema:<N> marker when present; a marker-less or
foreign-comment table reads as 0 (core-baseline shape — V1 is purely
adoptive, there is no pre-chain content to defend).
Applies every chain version up to target (:version in opts, default current_version/0); idempotent.
@spec up_statements(String.t(), pos_integer()) :: [String.t()]
The SQL up/1 executes, as data — the testable single source. The
ownership test parses these statements to prove that the object names
are core's V135 names, that the CREATE TABLE stays shape-identical to
core's ExpectedSchema manifest, and that nothing here can drop the
table.
target selects how much of the chain to emit (default
current_version/0): 1 is the pure V135-adoption step on
phoenix_kit_payment_provider_configs; 2 additionally shapes
phoenix_kit_currencies (partial unique default-currency index,
rounding_rule, rate_updated_at — see the moduledoc).
@spec version_table() :: String.t()
The table carrying the pkb_schema:<N> marker (auditor contract).