Document P0 webhook fix + test seam; ship :54; track EVALUATION.md
This commit is contained in:
+18
-3
@@ -51,9 +51,24 @@ card+lightning+onchain), NOT stored per row.
|
||||
3. else earliest-`connected_at` (deterministic) + a warning.
|
||||
|
||||
`payment::build_provider(&row, ...)` constructs a **real** `BtcpayProvider` /
|
||||
`ZapriteProvider` from the DB row — there is **no mock seam** in this path, so
|
||||
integration tests can't drive it with `MockPaymentProvider` without one. The legacy
|
||||
`state.payment` arc is a compat shim and is NOT consulted by the new resolver.
|
||||
`ZapriteProvider` from the DB row. Tests swap in a mock via the always-compiled
|
||||
`AppState::provider_override` seam (`None` in production), honored by
|
||||
`AppState::provider_from_row` at every resolution site — see [testing](testing.md).
|
||||
The legacy `state.payment` arc is a compat shim and is NOT consulted by the new
|
||||
resolver.
|
||||
|
||||
## Webhook settle confirmation (anti-forgery)
|
||||
|
||||
Zaprite webhooks carry no signature, so the settle handler does **not** trust the
|
||||
webhook body's claim. `api/webhook.rs::handle_inner` re-fetches
|
||||
`provider.get_invoice_status` and requires `Settled` before persisting status or
|
||||
taking ANY settle-derived action (license issuance, tier-change, subscription
|
||||
renewal — the guard sits ahead of all of them). On a provider-API error it acks
|
||||
`200` without issuing — the reconcile loop re-confirms and issues on its next tick
|
||||
(fail-closed on issuance, and a 2xx avoids a provider retry-storm). **Not yet
|
||||
done**: a literal paid-amount/currency check (the trait exposes only a status
|
||||
enum); trusting the provider's own `Settled` determination is the current
|
||||
boundary — see the auditor's open P1.
|
||||
|
||||
## Provider connect
|
||||
|
||||
|
||||
Reference in New Issue
Block a user