signup: flag-gated paid account option with payment in the form #149

Öppen
öppnade 2026-08-02 10:27:20 +00:00 av supernaut · 1 kommentar
Ägare

Offer a paid account at sign-up, behind the payments flag, taking payment as
part of the form.

Epic: bitborg-docs#5
Sibling of #145, not a duplicate: that issue is the upgrade path for an account
that already exists; this is the choice made before the account exists.

Behaviour

The two options are mutually exclusive, driven by paymentsEnabled()
(src/lib/payments-access.ts, off by default):

PAYMENTS_ENABLED Sign-up offers
off trial account, participant account
on paid account, participant account — no trial

When the paid option is selected, payment is taken as part of sign-up rather
than deferred to a later upgrade.

Why trial disappears when payment arrives

The trial exists because there is nothing to buy yet (ADR 0036). Once there is,
offering both asks people to choose between paying and not paying for the same
capabilities. The existing TRIAL_OPEN switch stays the mechanism for retiring
the trial; this issue is about the two flags not contradicting each other — a
state where both a trial and a paid option render should not be reachable.

Decide explicitly what happens to accounts already on the trial when the flag
flips. They convert or downgrade per ADR 0036, and that is operational work, but
the sign-up form must not be the place it is discovered.

Prerequisites already in place

  • paymentsEnabled() — flag, off by default, inverted polarity so a missing or
    mistyped variable leaves payment surfaces dark.
  • signup.accountType.paid and .paid.description — copy exists in both
    languages, currently unused. The trial and paid descriptions are presently
    identical; the paid one should say what is actually different (that it does not
    expire).

The trap to avoid

requiresCountry() in src/lib/eligibility.ts decides which account types must
declare a country of residence, and PAYING_ACCOUNT_TYPES is deliberately
empty today because nothing on the form is a purchase.

Adding the paid radio without adding "paid" to that set means country is
silently never collected for the one type that needs it — for VAT and banking.

Nothing fails; it simply stops asking, and country_code/region stay NULL.

Worth a test binding the paid option to that set so the two cannot drift apart. A
comment did not prevent the gap being left in the first place.

Out of scope

Billing state, the provider integration and subscription lifecycle all belong to
the separate payment service. The portal's job is the choice, the hand-off, and
reading status for display — never computing entitlements from it. Tier changes
flow payment → Kanidm group → reconciler, never writing to the Git application
directly.

Sequencing

Deferred until after the sign-up form refactor (#146) lands, on its own branch.

Offer a paid account **at sign-up**, behind the payments flag, taking payment as part of the form. Epic: bitborg-docs#5 Sibling of #145, not a duplicate: that issue is the upgrade path for an account that already exists; this is the choice made before the account exists. ## Behaviour The two options are mutually exclusive, driven by `paymentsEnabled()` (`src/lib/payments-access.ts`, off by default): | `PAYMENTS_ENABLED` | Sign-up offers | | --- | --- | | off | trial account, participant account | | on | paid account, participant account — **no trial** | When the paid option is selected, payment is taken as part of sign-up rather than deferred to a later upgrade. ## Why trial disappears when payment arrives The trial exists because there is nothing to buy yet (ADR 0036). Once there is, offering both asks people to choose between paying and not paying for the same capabilities. The existing `TRIAL_OPEN` switch stays the mechanism for retiring the trial; this issue is about the two flags not contradicting each other — a state where both a trial and a paid option render should not be reachable. Decide explicitly what happens to accounts **already on the trial** when the flag flips. They convert or downgrade per ADR 0036, and that is operational work, but the sign-up form must not be the place it is discovered. ## Prerequisites already in place - `paymentsEnabled()` — flag, off by default, inverted polarity so a missing or mistyped variable leaves payment surfaces dark. - `signup.accountType.paid` and `.paid.description` — copy exists in both languages, currently unused. The trial and paid descriptions are presently identical; the paid one should say what is actually different (that it does not expire). ## The trap to avoid `requiresCountry()` in `src/lib/eligibility.ts` decides which account types must declare a country of residence, and `PAYING_ACCOUNT_TYPES` is deliberately **empty** today because nothing on the form is a purchase. **Adding the paid radio without adding `"paid"` to that set means country is silently never collected for the one type that needs it — for VAT and banking.** Nothing fails; it simply stops asking, and `country_code`/`region` stay NULL. Worth a test binding the paid option to that set so the two cannot drift apart. A comment did not prevent the gap being left in the first place. ## Out of scope Billing state, the provider integration and subscription lifecycle all belong to the separate payment service. The portal's job is the choice, the hand-off, and reading status for display — never computing entitlements from it. Tier changes flow payment → Kanidm group → reconciler, never writing to the Git application directly. ## Sequencing Deferred until after the sign-up form refactor (#146) lands, on its own branch.
supernaut lade till detta till projektet Bitborg Web 2026-08-02 10:27:29 +00:00
Upphovsperson
Ägare

Board grooming 2026-10-03: dropped blocked. The stated dependency, the sign-up form refactor (#146), merged on 2026-08-02. The option stays dark behind PAYMENTS_ENABLED, so it can be built now and turned on with checkout.

Board grooming 2026-10-03: dropped `blocked`. The stated dependency, the sign-up form refactor (#146), merged on 2026-08-02. The option stays dark behind `PAYMENTS_ENABLED`, so it can be built now and turned on with checkout.
supernaut refererade till detta ärende från en incheckning 2026-10-03 00:12:45 +00:00
Logga in för att delta i denna konversation.
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-web#149
Ingen beskrivning angiven.