@@ -561,6 +561,56 @@ describe('WebhookSystem persistence', () => {
561561 }
562562 } ) ;
563563
564+ it ( 'persists webhook auto-disable state after repeated failures' , async ( ) => {
565+ process . env . NODE_ENV = 'production' ;
566+ process . env . WEBHOOK_SECRET_ENCRYPTION_KEY = Buffer . alloc ( 32 , 9 ) . toString ( 'base64' ) ;
567+ mockWebhookFindMany . mockResolvedValue ( [
568+ {
569+ id : 'wh-auto-disable' ,
570+ organizationId : 'org-1' ,
571+ url : 'https://hooks.zeroid.example/private' ,
572+ secret : encryptWebhookSecretForTest ( 's' . repeat ( 64 ) ) ,
573+ events : [ 'credential.issued' ] ,
574+ status : 'ACTIVE' ,
575+ failureCount : 9 ,
576+ lastDeliveredAt : null ,
577+ lastStatusCode : 500 ,
578+ createdAt : new Date ( '2026-04-21T00:00:00.000Z' ) ,
579+ updatedAt : new Date ( '2026-04-21T00:00:00.000Z' ) ,
580+ } ,
581+ ] ) ;
582+ mockWebhookDeliveryUpsert . mockResolvedValue ( { } ) ;
583+ const dnsSpy = jest . spyOn ( dns , 'lookup' ) . mockResolvedValue ( [
584+ { address : '127.0.0.1' , family : 4 } ,
585+ ] ) ;
586+
587+ try {
588+ const deliveryIds = await webhookSystem . emit ( 'credential.issued' , {
589+ credentialId : 'cred-1' ,
590+ } , 'org-1' ) ;
591+
592+ expect ( deliveryIds ) . toHaveLength ( 1 ) ;
593+ expect ( mockWebhookUpdate ) . toHaveBeenCalledWith ( expect . objectContaining ( {
594+ where : { id : 'wh-auto-disable' } ,
595+ data : expect . objectContaining ( {
596+ failureCount : 10 ,
597+ lastStatusCode : 0 ,
598+ status : 'DISABLED' ,
599+ } ) ,
600+ } ) ) ;
601+ expect ( JSON . parse ( redisStore [ 'enterprise:webhook-config:wh-auto-disable' ] as string ) ) . toMatchObject ( {
602+ health : expect . objectContaining ( {
603+ consecutiveFailures : 10 ,
604+ disabled : true ,
605+ } ) ,
606+ } ) ;
607+ } finally {
608+ dnsSpy . mockRestore ( ) ;
609+ process . env . NODE_ENV = 'test' ;
610+ delete process . env . WEBHOOK_SECRET_ENCRYPTION_KEY ;
611+ }
612+ } ) ;
613+
564614 it ( 'pins vetted DNS address during production webhook delivery' , async ( ) => {
565615 process . env . NODE_ENV = 'production' ;
566616 process . env . WEBHOOK_SECRET_ENCRYPTION_KEY = Buffer . alloc ( 32 , 9 ) . toString ( 'base64' ) ;
@@ -700,6 +750,14 @@ describe('WebhookSystem persistence', () => {
700750 success : true ,
701751 } ) ,
702752 } ) ) ;
753+ expect ( mockWebhookUpdate ) . toHaveBeenCalledWith ( expect . objectContaining ( {
754+ where : { id : 'wh-deliver' } ,
755+ data : expect . objectContaining ( {
756+ failureCount : 0 ,
757+ lastDeliveredAt : expect . any ( Date ) ,
758+ lastStatusCode : 200 ,
759+ } ) ,
760+ } ) ) ;
703761 fetchSpy . mockRestore ( ) ;
704762 } ) ;
705763
0 commit comments