Runbook — wa_hold_settlement enablement toggle (BIF-8740)
As-built (2026-07-22). Deduction V2 hold/settlement is gated by
Services::Billing::FeatureFlag, a company-scoped billing feature flag. This supersedes the two-tier design the RFC's Decision 6 described (a globalServices::Preferenceflag ∨ a per-orgorganization_packages.extras['wa_hold_settlement']jsonb boolean) — that design was never shipped.extras['wa_hold_settlement']is not read by any code; setting it does nothing. Enable orgs only via the mechanism below.
An org is on the hold/settlement path when the flag is enabled for its company:
# Repositories::Billings::Helpers#wa_hold_settlement_enabled? (hub_core, added in T1)
def wa_hold_settlement_enabled?(organization_package)
Services::Billing::FeatureFlag.new.enabled?(
:wa_hold_settlement,
unique_id: organization_package&.company_id
)
end
Services::Billing::FeatureFlag (hub_core/app/core/domains/services/billing/feature_flag.rb) is
read-only in hub_core. It resolves the flag from the billing DB + a Redis cache
(REDIS_BILLING_R, keys preference:wa_hold_settlement:{state,global,<company_id>:unique}), mirroring
qontak-preferences. Its logic (#enabled?(feature, unique_id:)):
state == false(or the preference row is absent) → false (fail-safe, default OFF).is_global == true→ true for every company (fleet-wide GA / short-circuits the per-company check).- otherwise → true iff a
preference_unique_idsrow exists for(preference, unique_id = company_id)(per-company pilot opt-in).
So there are two enablement levers, both on the billing preferences / preference_unique_ids
tables for the wa_hold_settlement feature — not Services::Preference and not extras:
- Global (GA / kill switch):
preferences.state = true, is_global = true→ all companies on. - Per-company (pilot opt-in):
preferences.state = true, is_global = false+ onepreference_unique_idsrow per pilotcompany_id→ only those companies on.
Who writes the flag
hub_core only reads it. Seeding the wa_hold_settlement preference row and managing its
per-company preference_unique_ids allow-list live in the billing-preferences managing service
(qontak-preferences / the billing preferences admin surface), not in this repo and not in
hub_core's Services::Preference (a different, non-billing flag system). Use that service's admin
tooling to:
- Register the
wa_hold_settlementbilling preference once per environment,state = false,is_global = false(default OFF). - Pilot — add each pilot
company_idto thewa_hold_settlementunique-id allow-list (leaveis_global = false). Roll back a single org by removing itscompany_idfrom the allow-list. - GA — set
is_global = true(every company on at once). Kill switch — setstate = false(instant fleet-wide revert regardless of the allow-list).
The exact admin command belongs to the billing-preferences service and is out of scope for this repo; confirm it there. Whatever the surface, the effect must be one of the three table states above — the Redis cache is populated from the DB on read (cold-miss), so after an admin change the next
enabled?call reflects it.
Consumer check (T2–T6, M1)
All gated branches call the single shared predicate — never the flag directly.
Repositories::Billings::Helpers is a module (mixin); include it (interactors/repos on the
deduction path already do):
include Repositories::Billings::Helpers
wa_hold_settlement_enabled?(organization_package) # company-scoped Services::Billing::FeatureFlag read
moderator-be replicates the same reader (M1b, BIF-8958) as Core::Services::Billing::FeatureFlag
against the same billing tables + Redis, and hub_core exposes the boolean on billing_info as
is_wa_hold_settlement_enabled (M1a, BIF-8883) for the client FE.
Sources (grounded against hub_core)
- Reader:
hub_core/app/core/domains/services/billing/feature_flag.rb(#enabled?(feature, unique_id:),REDIS_BILLING_Rcache; comment: "hub-core only reads flags; seeding and unique-id management live in the managing repo"). - Backing models:
Models::Billing::Preference(tablepreferences) +Models::Billing::PreferenceUniqueId(tablepreference_unique_ids). - Predicate:
Repositories::Billings::Helpers#wa_hold_settlement_enabled?(hub_core/app/core/domains/repositories/billings/helpers.rb:61-63) → delegates toServices::Billing::FeatureFlagwithunique_id: organization_package&.company_id; truth-table spec infeature_flag_spec.rb.