CluPilotCloud/app/Actions
nexxo 2277dfe4cb
tests / pest (push) Failing after 8m24s Details
tests / assets (push) Successful in 26s Details
tests / release (push) Has been skipped Details
Ask the EU register whether a VAT number is real
vat_id_verified_at was declared on the customer and read by TaxTreatment, and
set by no code anywhere. hasVerifiedVatId() therefore never returned true, so
reverse charge could not trigger for anybody - and every EU business customer was
invoiced Austrian VAT they cannot reclaim in their own country, which is not a
pass-through for them but a real cost until the invoice is corrected.

The check has THREE outcomes, and the third is why VatIdCheck exists. VIES is a
gateway onto twenty-seven national registers and any of them is regularly down.
Reading "I could not ask" as "not registered" would clear a verification that has
stood for months, move that customer onto the domestic rate, and change what
their next invoice says - because a register was asleep. Reading it as
"registered" would put reverse charge on an unchecked number, which is our
liability. So on UNAVAILABLE nothing at all is written.

Asked at the moment the number is entered, because that is when somebody is
looking at the field and can fix a typo. The save has already happened by then
and the check cannot undo it: a register that is down must not cost a customer
their address change.

Shape and membership are refused before a request is spent, and the fake refuses
on the same rule as the real verifier. A fake that answers where VIES would never
have been asked is not a simplification but a different product, and free text
normalises into a well-formed number more easily than it looks - "not a number"
becomes NOTANUMBER, which the shape rule alone reads as a Norwegian one.

clupilot:verify-vat-ids re-asks about the numbers reverse charge rests on, since
a registration can be withdrawn. Deliberately not scheduled: it queries a public
service with a concurrency limit on behalf of somebody else's tax position, and
the cadence is the owner's to set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 22:42:29 +02:00
..
Fortify Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
ApplyPlanChange.php Invoice every renewal, and tell Stripe when the package changes 2026-07-29 19:35:15 +02:00
ApplyStorageAllowance.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
ApplyStripeBillingEvent.php Bill a booked module every month, and put it on the invoice 2026-07-29 20:22:02 +02:00
BookAddon.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
EndInstanceService.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
GrantAddon.php Decide who may have their own domain, and decide it in one place 2026-07-29 15:59:04 +02:00
GrantSubscription.php Let a subscription or add-on be opened for free, with who and why on the row 2026-07-29 12:41:06 +02:00
IssueStripeInvoice.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
MoveStripeSubscriptionPrice.php Invoice every renewal, and tell Stripe when the package changes 2026-07-29 19:35:15 +02:00
OpenSubscription.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
ReapplyInstanceAddress.php Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
RecordCommercialEvent.php feat(billing): Stripe owns the billing cycle, we own capability 2026-07-26 13:36:28 +02:00
RestartInstance.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
StartCustomerProvisioning.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
StartHostOnboarding.php fix(engine): durable queueing for long provisioning steps 2026-07-25 10:36:49 +02:00
SyncStripeAddonItems.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
VerifyCustomerVatId.php Ask the EU register whether a VAT number is real 2026-07-29 22:42:29 +02:00
WithdrawContract.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00