@@ -70,6 +70,74 @@ describe("renderPrComment", () => {
7070 expect ( out ) . toMatch ( / \| \/ a p i \/ v 1 \/ n e w \| n e w \| \d + \| / ) ;
7171 } ) ;
7272
73+ // Mirrors the guard report.test.ts has for the terminal renderer: audit-trail fails almost
74+ // every sensitive mutation today (no audit helper exists), so it is a headline figure, not a
75+ // per-route nag. A regression here previously let it leak into the "now failing" column.
76+ it ( "does not list audit-trail among a new sensitive entry's failing checks" , ( ) => {
77+ const sensitiveMutation = scanFile (
78+ "api.v1.envvars.ts" ,
79+ `import { prisma } from "~/db.server";
80+ export async function action() {
81+ try {
82+ return await prisma.envVar.update({ where: {}, data: {} });
83+ } catch (e) {
84+ return null;
85+ }
86+ }`
87+ ) ! ;
88+ const head = buildReport ( [ sensitiveMutation ] , [ ] ) ;
89+ const base = buildReport ( [ ] , [ ] ) ;
90+ const out = renderPrComment ( head , base ) ;
91+
92+ const row = out . split ( "\n" ) . find ( ( l ) => l . startsWith ( "| /api/v1/envvars |" ) ) ! ;
93+ expect ( row ) . toBeDefined ( ) ;
94+ expect ( row ) . toContain ( "new" ) ;
95+ expect ( row ) . not . toContain ( "audit-trail" ) ;
96+ expect ( row ) . toMatch ( / e r r o r - c l a s s i f i c a t i o n | a u t h - b o u n d a r y | r e q u e s t - c o n t e x t / ) ;
97+ } ) ;
98+
99+ it ( "sorts a sensitive entry with a small drop above a non-sensitive entry with a large drop" , ( ) => {
100+ const sensitiveSmallDropBase = scanFile ( "api.v1.auth.tokens.ts" , cleanSource ) ! ;
101+ const sensitiveSmallDropHead = scanFile (
102+ "api.v1.auth.tokens.ts" ,
103+ `import { requireUserId } from "~/services/session.server";
104+ import { logger } from "~/services/logger.server";
105+ import { prisma } from "~/db.server";
106+ export async function action({ request }) {
107+ const userId = await requireUserId(request);
108+ try { return await prisma.token.create({ data: { userId } }); }
109+ catch (error) { logger.error("token create failed", { error }); throw error; }
110+ }`
111+ ) ! ;
112+
113+ const notSensitiveLargeDropBase = scanFile (
114+ "resources.busy.ts" ,
115+ `import { logger } from "~/services/logger.server";
116+ import { prisma } from "~/db.server";
117+ export async function loader({ params }) {
118+ try { return await prisma.thing.findMany(); }
119+ catch (error) { logger.error("failed", { environmentId: params.envId, error }); throw error; }
120+ }`
121+ ) ! ;
122+ const notSensitiveLargeDropHead = scanFile (
123+ "resources.busy.ts" ,
124+ `import { prisma } from "~/db.server";
125+ export async function loader() {
126+ try { return await prisma.thing.findMany(); } catch (e) { return null; }
127+ }`
128+ ) ! ;
129+
130+ const head = buildReport ( [ sensitiveSmallDropHead , notSensitiveLargeDropHead ] , [ ] ) ;
131+ const base = buildReport ( [ sensitiveSmallDropBase , notSensitiveLargeDropBase ] , [ ] ) ;
132+ const out = renderPrComment ( head , base ) ;
133+
134+ const sensitiveIndex = out . indexOf ( "/api/v1/auth/tokens" ) ;
135+ const notSensitiveIndex = out . indexOf ( "/resources/busy" ) ;
136+ expect ( sensitiveIndex ) . toBeGreaterThan ( - 1 ) ;
137+ expect ( notSensitiveIndex ) . toBeGreaterThan ( - 1 ) ;
138+ expect ( sensitiveIndex ) . toBeLessThan ( notSensitiveIndex ) ;
139+ } ) ;
140+
73141 it ( "reports a removed entry as a count line, not a row" , ( ) => {
74142 const head = buildReport ( [ scanFile ( "api.v1.auth.tokens.ts" , cleanSource ) ! ] , [ ] ) ;
75143 const base = buildReport (
0 commit comments