Repository navigation
v2.12.3
IBeam v2.12.3
Completes the provider-webhook fix from v2.12.2 for hosts that use licensed
service operations. One commit: b3e9b98 (PR #24).
Provider webhooks still failed under AddIBeamLicensedServiceOperations()
v2.12.2 (ee1e8f8) let a verified provider callback run without tenant
authorization. BillingWebhookProcessor opens an IServiceOperationSystemContext
scope after signature verification, and ServiceOperationExecutor skips the
tenant demand inside it.
That fix never reached hosts that call AddIBeamLicensedServiceOperations().
The call replaces the executor with LicensedServiceOperationExecutor, which
builds its own inner ServiceOperationExecutor and passed it no system
context. The scope was open, but the executor doing the authorization check
couldn't see it. So every webhook still returned 500 with
"tenantId is required for service operation authorization", the failure
v2.12.2 set out to remove. In Qurvia, 21 of 21 Stripe sandbox events failed on
v2.12.2.
What changed
LicensedServiceOperationExecutortakesIServiceOperationSystemContextas
an optional constructor parameter and passes it to its inner executor.- Its licence check is skipped only while the scope is active. A verified
webhook has no licence subject and no tenant, so demanding a licence fails
the same way. This matters because a host'sIBillingPaidPurchaseHandlers run
insideProcessAsyncand can call licensed operations. Outside the scope,
every caller is licence-checked exactly as before, including admin and
support tooling that calls the same operations. AddIBeamLicensedServiceOperations()now also registers the context
(scoped, viaTryAdd). The processor and the executor share one instance per
request, even in a host that never calledAddIBeamServicePolicies.
The design is unchanged from v2.12.2: a request-scoped exemption, not
Permission = false or a licence-free operation list. Annotating operations
would also exempt authenticated callers, and would need a new annotation every
time the webhook path grew.
Why it was not caught
The processor tests built their services by hand with the plain executor,
which does honour the scope. The composition production uses was never
exercised: same code, different container. Both halves of this fix are needed.
With only the context pass-through, the new tests still fail, this time on the
licence check.
Tests
- New
LicensedWebhookCompositionTests: builds the container the way a host
does (billing, licensing,AddIBeamLicensedServiceOperations()and a
denying authorizer) and runs a signed event end to end. All four cases fail
on v2.12.2 with the production exception, and pass on v2.12.3. - Executor unit tests: inside and outside a system scope, plus an
authenticated caller with no licence (still denied). - Full suite: 594 passed, 2 failed. The 2 failures are OAuth tests that
already failed before this change (587 passed, same 2 failed).
Upgrade notes
- Additive only. The new constructor parameter is optional and last, so
existing direct construction ofLicensedServiceOperationExecutorcompiles
and behaves as before. - Hosts on v2.12.2 that call
AddIBeamLicensedServiceOperations():
webhooks start succeeding with no code change beyond the package bump. - Remove any workaround that caught
AccessControlException/
UnauthorizedAccessExceptionaround webhook recording (Qurvia's QUR-0261
catch inPaymentWebhookService). With this release, IBeam records provider
events and runs its own paid-purchase handlers again. Verified against
Qurvia with its workaround removed: webhook tests 7/7, including a signed
commerce purchase reaching paid. - Hosts that don't use licensed service operations are unaffected.