@@ -993,35 +993,41 @@ export async function handleInvoicePaymentFailed(event: Stripe.Event) {
993993 resolutionSource,
994994 } )
995995
996- const failureOrgScoped = await isSubscriptionOrgScoped ( sub )
997- const failureEntityType = failureOrgScoped ? 'organization' : 'user'
998- const failureActorId = await resolveBillingActorId ( failureOrgScoped , sub . referenceId )
999-
1000- recordAudit ( {
1001- actorId : failureActorId ,
1002- action : AuditAction . INVOICE_PAYMENT_FAILED ,
1003- resourceType : AuditResourceType . BILLING ,
1004- resourceId : invoice . id ,
1005- description : `Invoice payment of $${ failedAmount . toFixed ( 2 ) } failed for ${ failureEntityType } ${ sub . referenceId } (attempt ${ attemptCount } )` ,
1006- metadata : {
1007- entityType : failureEntityType ,
1008- referenceId : sub . referenceId ,
1009- plan : sub . plan ,
996+ // Best-effort instrumentation; its DB reads must never abort the
997+ // user-blocking that follows, so the whole block is guarded.
998+ try {
999+ const failureOrgScoped = await isSubscriptionOrgScoped ( sub )
1000+ const failureEntityType = failureOrgScoped ? 'organization' : 'user'
1001+ const failureActorId = await resolveBillingActorId ( failureOrgScoped , sub . referenceId )
1002+
1003+ recordAudit ( {
1004+ actorId : failureActorId ,
1005+ action : AuditAction . INVOICE_PAYMENT_FAILED ,
1006+ resourceType : AuditResourceType . BILLING ,
1007+ resourceId : invoice . id ,
1008+ description : `Invoice payment of $${ failedAmount . toFixed ( 2 ) } failed for ${ failureEntityType } ${ sub . referenceId } (attempt ${ attemptCount } )` ,
1009+ metadata : {
1010+ entityType : failureEntityType ,
1011+ referenceId : sub . referenceId ,
1012+ plan : sub . plan ,
1013+ amount : failedAmount ,
1014+ currency : invoice . currency ?? 'usd' ,
1015+ attemptCount,
1016+ invoiceType : invoiceType ?? 'subscription' ,
1017+ invoiceId : invoice . id ,
1018+ } ,
1019+ } )
1020+ captureServerEvent ( failureActorId , 'payment_failed' , {
1021+ plan : sub . plan ?? 'unknown' ,
10101022 amount : failedAmount ,
10111023 currency : invoice . currency ?? 'usd' ,
1012- attemptCount,
1013- invoiceType : invoiceType ?? 'subscription' ,
1014- invoiceId : invoice . id ,
1015- } ,
1016- } )
1017- captureServerEvent ( failureActorId , 'payment_failed' , {
1018- plan : sub . plan ?? 'unknown' ,
1019- amount : failedAmount ,
1020- currency : invoice . currency ?? 'usd' ,
1021- entity_type : failureEntityType ,
1022- reference_id : sub . referenceId ,
1023- attempt_count : attemptCount ,
1024- } )
1024+ entity_type : failureEntityType ,
1025+ reference_id : sub . referenceId ,
1026+ attempt_count : attemptCount ,
1027+ } )
1028+ } catch ( auditError ) {
1029+ logger . warn ( 'Failed to record payment_failed instrumentation' , { auditError } )
1030+ }
10251031
10261032 if ( attemptCount >= 1 ) {
10271033 logger . error ( 'Payment failure - blocking users' , {
@@ -1033,7 +1039,7 @@ export async function handleInvoicePaymentFailed(event: Stripe.Event) {
10331039 stripeSubscriptionId,
10341040 } )
10351041
1036- if ( failureOrgScoped ) {
1042+ if ( await isSubscriptionOrgScoped ( sub ) ) {
10371043 const memberCount = await blockOrgMembers ( sub . referenceId , 'payment_failed' )
10381044 logger . info ( 'Blocked org members due to payment failure' , {
10391045 invoiceType : invoiceType ?? 'subscription' ,
0 commit comments