CluPilotCloud/app
nexxo 06c214e597 Make the money gate compare the whole recurrence
activePricesFor() reported interval alone, never interval_count or usage_type.
A Price we could not have created ourselves — billed every three months, or on
metered usage — could carry our own metadata (Stripe's dashboard "duplicate
price" copies it) and pass AdoptStripePrice's amount/currency/interval check on
'month' alone. Adopting it would move money onto a different recurrence, which
is exactly what nothing here may do.

Filtered at the boundary instead of in the predicate: HttpStripeClient now
skips anything besides Stripe's own defaults (interval_count 1, usage_type
licensed), so activePricesFor() can promise callers it returns only prices we
could have minted. FakeStripeClient needed no filter — it only ever holds
prices its own createPrice()/plantPrice() made, all standard — but says so, so
the omission doesn't read as forgotten.

Two more silent-failure paths, closed with the same three lines each:

- The metadata-differs check was a bare !==, which is key-order sensitive and
  blind to Stripe's own merge. A Price carrying an extra key of its own, or
  metadata handed back in a different order, could never compare equal and
  would be rewritten every sweep forever. Compared through
  array_intersect_key() plus ksort() on both sides instead, so only what WE
  would send is what gets compared.
- Metadata is normalised to strings once, up front, so an un-cast value from a
  caller can't make confirms() fail forever and silently turn adoption off for
  that Price.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 11:15:16 +02:00
..
Actions Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
Console Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
Exceptions Refuse a portal login for an address that already belongs to an operator 2026-07-28 14:42:16 +02:00
Http Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
Jobs Let the export have as many destinations as somebody wants 2026-07-29 02:43:15 +02:00
Listeners Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
Livewire Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
Mail Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
Models Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
Notifications Add the SSH identity to the vault, and give deployment config a console page 2026-07-29 00:52:44 +02:00
Observers Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
Policies Move the console's identity out of the customer table 2026-07-28 10:31:43 +02:00
Providers Ask the EU register whether a VAT number is real 2026-07-29 22:42:29 +02:00
Provisioning Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00
Services Make the money gate compare the whole recurrence 2026-07-30 11:15:16 +02:00
Support Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00