@@ -492,3 +492,84 @@ describe('[#5462] the declared-status band is untouched', () => {
492492 expect ( r . body . field ) . toBe ( 'label' ) ;
493493 } ) ;
494494} ) ;
495+
496+ // ---------------------------------------------------------------------------
497+ // 5. [#8264] The Postgres limb is anchored on the quoted template — both
498+ // decision paths this one const feeds
499+ // ---------------------------------------------------------------------------
500+ //
501+ // `looksLikeMissingRelation` used to read `relation` and `does not exist`
502+ // anywhere in the message, not necessarily the same sentence, so ordinary
503+ // business prose using both words matched — `error-leak.test.ts` pins the
504+ // identical negative case (`'This relation does not exist in the diagram'`)
505+ // for the shared #8132 leak predicate this heuristic was never wired to.
506+ // This section pins the same anchor here, for BOTH of this file's readers of
507+ // the const: the 500 gate right where it is defined, and the
508+ // `looksLikeUnknownObject` 404 limb a few lines below it.
509+ //
510+ // ---------------------------------------------------------------------------
511+ // Reverse verification, direction predicted BEFORE running
512+ // ---------------------------------------------------------------------------
513+ // Restoring the old `(lower.includes('relation') && lower.includes('does not
514+ // exist'))` conjunction:
515+ //
516+ // §5a (decision 1, the 500 gate) RED — the business message reverts to
517+ // `DATABASE_ERROR`/500 instead of the
518+ // generic terminal `INTERNAL_ERROR`
519+ // §5b (decision 2, the 404 limb) RED — the crafted unattributed-but-
520+ // word-matching message reverts to a
521+ // SILENT 404 `OBJECT_NOT_FOUND`
522+ // §5c/§5d (real driver phrasings) GREEN — untouched; every case here is
523+ // already quoted, matching both the
524+ // old and the new predicate
525+ //
526+ // Both are the ordinary RED direction, not one of the inverted families.
527+ // Measured after predicting it; the run is quoted in the PR.
528+
529+ describe ( '[#8264] anchored on the driver quoted template, not a bare conjunction' , ( ) => {
530+ it ( '§5a decision 1 (the 500 gate): business prose using both words is no longer DATA_STORE_FAULT' , ( ) => {
531+ // The card's own counter-example. No `object`, so it could never be
532+ // attributed either way — the fixed predicate simply stops calling it
533+ // a missing-relation condition at all, and it falls through to the
534+ // generic terminal fault instead of the DATABASE-flavoured one.
535+ const r = mapDataError ( driverError ( 'This relation does not exist in the diagram' ) ) ;
536+ expect ( r . status ) . toBe ( 500 ) ;
537+ expect ( r . body . code ) . not . toBe ( 'DATABASE_ERROR' ) ;
538+ expect ( r . body . code ) . toBe ( 'INTERNAL_ERROR' ) ;
539+ } ) ;
540+
541+ it ( '§5a holds with an object present too, and does not spill into the 404 limb either' , ( ) => {
542+ const r = mapDataError ( driverError ( 'This relation does not exist in the diagram' ) , 'diagram' ) ;
543+ expect ( r . body . code ) . not . toBe ( 'DATABASE_ERROR' ) ;
544+ expect ( r . body . code ) . not . toBe ( 'OBJECT_NOT_FOUND' ) ;
545+ } ) ;
546+
547+ it ( '§5b decision 2 (the 404 limb): an unquoted "relation <name> does not exist" no longer silently 404s' , ( ) => {
548+ // Crafted to isolate decision 2, which the card's own example cannot
549+ // reach: `missingRelationIsObject`'s Postgres branch tolerates
550+ // UNQUOTED names (it answers a different, narrower question — which
551+ // relation, once one is already suspected), so it still extracts
552+ // `acct` and matches it to the object. Under the OLD predicate this
553+ // fell through to the `looksLikeMissingRelation` OR-limb of
554+ // `looksLikeUnknownObject` and silently answered 404 — the exact
555+ // second consequence the card's own text never measured.
556+ const r = mapDataError ( driverError ( 'Sorry, relation acct does not exist in our records' ) , 'acct' ) ;
557+ expect ( r . status ) . not . toBe ( 404 ) ;
558+ expect ( r . body . code ) . not . toBe ( 'OBJECT_NOT_FOUND' ) ;
559+ } ) ;
560+
561+ it ( '§5c quoted forms — every quote style Postgres could use — still trip the 500 gate' , ( ) => {
562+ for ( const quote of [ '"' , "'" , '`' ] ) {
563+ const msg = `relation ${ quote } sys_metadata${ quote } does not exist` ;
564+ const r = mapDataError ( driverError ( msg ) ) ;
565+ expect ( r . status , msg ) . toBe ( 500 ) ;
566+ expect ( r . body . code , msg ) . toBe ( 'DATABASE_ERROR' ) ;
567+ }
568+ } ) ;
569+
570+ it ( '§5d the quoted form still attributes to 404 when the relation IS the object — decision 2, real case, unchanged' , ( ) => {
571+ const r = mapDataError ( driverError ( 'relation "ghost" does not exist' ) , 'ghost' ) ;
572+ expect ( r . status ) . toBe ( 404 ) ;
573+ expect ( r . body . code ) . toBe ( 'OBJECT_NOT_FOUND' ) ;
574+ } ) ;
575+ } ) ;
0 commit comments