Let an operator disable purchases live from the admin — a whole rail/channel or
one account — and show the user a localized reason on their next attempt, so a
provider outage or a misconfig is explained instead of a silent dead button.
- rail kill switch (payments.rail_status, per rail direct:web / direct:android /
vk / telegram): enabled + a per-language message, edited on the catalog page.
Fail-open — a rail with no row stays enabled, so payments are never accidentally
killed. The intake gate (CanPurchase in handleWalletOrder, before the order)
returns payment_unavailable + the localized message, orthogonal to the security
gates.
- per-account override (payments.account_payment_override, a row only for
non-default): allow / deny / default, edited on the user card. "allow" bypasses
ONLY the ops rail switch, never the security gates (trusted platform, the email
anchor, the VK-iOS freeze, the min client version).
- wire: an additive ExecuteResponse.message envelope field (frozen-contract-safe);
the gateway forwards a backend domain-error message; the client shows it on a
payment_unavailable buy attempt.
- admin: rail toggles on the catalog page, the override control on the user card.
- tests: the pure gate (unit, TDD), the store + gate + override end-to-end
(integration, migration 00016), the client (svelte-check / vitest).
- docs: PAYMENTS (+ru), the decisions log (D45/D46). Fiscalization stays
cabinet-side (owner decision) — no itemized-receipt code.
Contour-safe: additive migration (two new tables, no wipe), the wire add is
additive, and fail-open so nothing is disabled until an operator acts.