@@ -553,16 +553,15 @@ model Foo {
553553` ,
554554 { plugins : [ new PolicyPlugin ( { fetchPolicyCodes : false } ) ] } ,
555555 ) ;
556- // create: error is still thrown but policyCodes is empty (y=0 triggers deny)
556+ // create: pre-create check still fires → REJECTED_BY_POLICY, but no codes (y=0 triggers deny)
557557 await expect ( db . foo . create ( { data : { x : 1 , y : 0 } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
558558 const row = await db . foo . create ( { data : { x : 1 , y : 1 } } ) ;
559559 // negRow: x=-1 (denied for update/delete), but y=1 so create succeeds
560560 const negRow = await db . foo . create ( { data : { x : - 1 , y : 1 } } ) ;
561- // update: error is still thrown but policyCodes is empty
562- await expect ( db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
563- // delete: error is still thrown but policyCodes is empty
564- await expect ( db . foo . delete ( { where : { id : negRow . id } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
565- // post-update: error is still thrown but policyCodes is empty
561+ // update/delete: diagnostic query skipped entirely — behaves as if no codes → NOT_FOUND
562+ await expect ( db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } } ) ) . toBeRejectedNotFound ( ) ;
563+ await expect ( db . foo . delete ( { where : { id : negRow . id } } ) ) . toBeRejectedNotFound ( ) ;
564+ // post-update: postUpdateCheck fires independently of fetchPolicyCodes → REJECTED_BY_POLICY, no codes
566565 await expect ( db . foo . update ( { where : { id : row . id } , data : { x : - 1 } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
567566 await expect ( db . foo . update ( { where : { id : row . id } , data : { x : 2 } } ) ) . resolves . toMatchObject ( { x : 2 } ) ;
568567 } ) ;
@@ -596,19 +595,16 @@ model Foo {
596595 await expect ( db . foo . create ( { data : { x : 1 , y : 0 } } ) ) . toBeRejectedByPolicy ( undefined , [ 'NEGATIVE_Y_CREATE' ] ) ;
597596 const row = await db . foo . create ( { data : { x : 1 , y : 1 } } ) ;
598597 const negRow = await db . foo . create ( { data : { x : - 1 , y : 1 } } ) ;
599- // update: flag suppresses codes
598+ // update: flag skips diagnostic query entirely → NOT_FOUND (same as no codes defined)
600599 await expect (
601600 db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } , fetchPolicyCodes : false } ) ,
602- ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
601+ ) . toBeRejectedNotFound ( ) ;
603602 // update: without flag, codes surface
604603 await expect ( db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } } ) ) . toBeRejectedByPolicy ( undefined , [
605604 'NEGATIVE_X_UPDATE' ,
606605 ] ) ;
607- // delete: flag suppresses codes
608- await expect ( db . foo . delete ( { where : { id : negRow . id } , fetchPolicyCodes : false } ) ) . toBeRejectedByPolicy (
609- undefined ,
610- [ ] ,
611- ) ;
606+ // delete: flag skips diagnostic query entirely → NOT_FOUND
607+ await expect ( db . foo . delete ( { where : { id : negRow . id } , fetchPolicyCodes : false } ) ) . toBeRejectedNotFound ( ) ;
612608 // delete: without flag, codes surface
613609 await expect ( db . foo . delete ( { where : { id : negRow . id } } ) ) . toBeRejectedByPolicy ( undefined , [
614610 'NEGATIVE_X_DELETE' ,
@@ -623,6 +619,46 @@ model Foo {
623619 ] ) ;
624620 } ) ;
625621
622+ it ( 'fetchPolicyCodes:false for update/delete behaves identically to a model without error codes' , async ( ) => {
623+ const schema = `
624+ model Foo {
625+ id Int @id @default(autoincrement())
626+ x Int
627+ @@deny('update', x <= 0, 'NEGATIVE_X_UPDATE')
628+ @@allow('update', x > 0)
629+ @@deny('delete', x <= 0, 'NEGATIVE_X_DELETE')
630+ @@allow('delete', x > 0)
631+ @@allow('create,read', true)
632+ }
633+ ` ;
634+ const dbWithCodes = await createPolicyTestClient ( schema ) ;
635+ const dbOptOut = await createPolicyTestClient ( schema ) ;
636+
637+ const [ rowWithCodes , rowOptOut ] = await Promise . all ( [
638+ dbWithCodes . foo . create ( { data : { x : - 1 } } ) ,
639+ dbOptOut . foo . create ( { data : { x : - 1 } } ) ,
640+ ] ) ;
641+
642+ // With codes: update throws REJECTED_BY_POLICY with the error code
643+ await expect ( dbWithCodes . foo . update ( { where : { id : rowWithCodes . id } , data : { x : 0 } } ) ) . toBeRejectedByPolicy (
644+ undefined ,
645+ [ 'NEGATIVE_X_UPDATE' ] ,
646+ ) ;
647+ // Opt-out: same update → NOT_FOUND, matching the no-codes baseline
648+ await expect (
649+ dbOptOut . foo . update ( { where : { id : rowOptOut . id } , data : { x : 0 } , fetchPolicyCodes : false } ) ,
650+ ) . toBeRejectedNotFound ( ) ;
651+
652+ // With codes: delete throws REJECTED_BY_POLICY with the error code
653+ await expect ( dbWithCodes . foo . delete ( { where : { id : rowWithCodes . id } } ) ) . toBeRejectedByPolicy ( undefined , [
654+ 'NEGATIVE_X_DELETE' ,
655+ ] ) ;
656+ // Opt-out: same delete → NOT_FOUND, matching the no-codes baseline
657+ await expect (
658+ dbOptOut . foo . delete ( { where : { id : rowOptOut . id } , fetchPolicyCodes : false } ) ,
659+ ) . toBeRejectedNotFound ( ) ;
660+ } ) ;
661+
626662 it ( 'query-level fetchPolicyCodes:true overrides plugin-level false' , async ( ) => {
627663 const db = await createTestClient (
628664 `
@@ -655,19 +691,19 @@ model Foo {
655691 db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } , fetchPolicyCodes : true } ) ,
656692 ) . toBeRejectedByPolicy ( undefined , [ 'NEGATIVE_X_UPDATE' ] ) ;
657693 // update: without override, codes are suppressed
658- await expect ( db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
694+ await expect ( db . foo . update ( { where : { id : negRow . id } , data : { x : 0 } } ) ) . toBeRejectedNotFound ( ) ;
659695 // delete: query-level true re-enables codes despite plugin false
660696 await expect ( db . foo . delete ( { where : { id : negRow . id } , fetchPolicyCodes : true } ) ) . toBeRejectedByPolicy (
661697 undefined ,
662698 [ 'NEGATIVE_X_DELETE' ] ,
663699 ) ;
664700 // delete: without override, codes are suppressed
665- await expect ( db . foo . delete ( { where : { id : negRow . id } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
701+ await expect ( db . foo . delete ( { where : { id : negRow . id } } ) ) . toBeRejectedNotFound ( ) ;
666702 // post-update: query-level true re-enables codes despite plugin false
667703 await expect (
668704 db . foo . update ( { where : { id : row . id } , data : { x : - 1 } , fetchPolicyCodes : true } ) ,
669705 ) . toBeRejectedByPolicy ( undefined , [ 'NEGATIVE_AFTER_UPDATE' ] ) ;
670- // post-update: without override, codes are suppressed
706+ // post-update: without override, codes are suppressed and we get a policy rejection without codes (not NotFound)
671707 await expect ( db . foo . update ( { where : { id : row . id } , data : { x : - 1 } } ) ) . toBeRejectedByPolicy ( undefined , [ ] ) ;
672708 } ) ;
673709} ) ;
0 commit comments