- Shipped
- September 7, 2026 at 12:17 AM UTC
- Author
- Kamo
- Commit
- 1e0fd15
Answering "is changing the default still there on Payment Info" — it was, and reading it turned up a defect worth more than the answer: nothing stopped an EXPIRED card being made the account default. Nothing warned when the current default lapsed either. Both failures are silent by construction: the account looks correctly configured, and the first sign is a renewal that fails for a reason no screen has ever mentioned. So "Set default" is disabled on an expired card, with a tooltip saying why rather than leaving a dead button to be guessed at; a default that has expired wears a red "Default — expired" badge instead of the ordinary blue one; and the list is headed by a warning when that is the state, because it is the only thing on that page that costs money if it is ignored. The two surfaces that render saved cards had also drifted into two presentations of one thing. Payment Info printed cardBrand.toUpperCase(), so Mastercard read as "MASTERCARD"; it had no brand tile; its expiry line was built with String(cardExpMonth) and printed the word "null" when Stripe had not told us; and it had no notion of expiry at all. paymentMethodDisplay now owns a card's identity — mark, name, whether it still works — so the rule cannot be true on the plans console and absent one tab away, and a third surface gets it for free. Also: the default row is ringed so it can be found without reading, "Set default" is busy-tracked (it is a round trip plus a full reload, and without it an impatient second click fired a second request), and Add card matches the casing of every other control on the screen. The expiry boundary is tested rather than asserted — a card is good through the last day of the month printed on it, and being a month out either refuses one somebody is still using or offers one that will be decoderd. An absent expiry reads as working, not lapsed: that means Stripe did not tell us, and refusing on a null would lock somebody out of their own card. 163 files / 2413 tests green, 11 new. Typecheck clean; eslint errors unchanged from HEAD at two, both pre-existing. Copy in kamo-translation-dictionary c2f6fcf3, pushed first.