@@ -19,6 +19,7 @@ import {
1919import type { Config } from '../config/config.js' ;
2020import * as sdk from './sdk.js' ;
2121import { ClearcutLogger } from './clearcut-logger/clearcut-logger.js' ;
22+ import { EventMetadataKey } from './clearcut-logger/event-metadata-key.js' ;
2223
2324vi . mock ( '@opentelemetry/api-logs' ) ;
2425vi . mock ( './sdk.js' ) ;
@@ -144,4 +145,174 @@ describe('conseca-logger', () => {
144145
145146 expect ( mockLogger . emit ) . not . toHaveBeenCalled ( ) ;
146147 } ) ;
148+
149+ it ( 'should omit user_prompt/trusted_content/policy from OTEL when logPrompts is disabled' , ( ) => {
150+ const configNoPrompts = {
151+ getTelemetryEnabled : vi . fn ( ) . mockReturnValue ( true ) ,
152+ getSessionId : vi . fn ( ) . mockReturnValue ( 'test-session-id' ) ,
153+ getTelemetryLogPromptsEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
154+ getTelemetryTracesEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
155+ isInteractive : vi . fn ( ) . mockReturnValue ( true ) ,
156+ getExperiments : vi . fn ( ) . mockReturnValue ( { experimentIds : [ ] } ) ,
157+ getContentGeneratorConfig : vi . fn ( ) . mockReturnValue ( { authType : 'oauth' } ) ,
158+ } as unknown as Config ;
159+
160+ const event = new ConsecaPolicyGenerationEvent (
161+ 'sensitive prompt' ,
162+ 'sensitive content' ,
163+ 'sensitive policy' ,
164+ ) ;
165+
166+ logConsecaPolicyGeneration ( configNoPrompts , event ) ;
167+
168+ const attrs = mockLogger . emit . mock . calls [ 0 ] [ 0 ] . attributes as Record <
169+ string ,
170+ unknown
171+ > ;
172+ expect ( attrs [ 'user_prompt' ] ) . toBeUndefined ( ) ;
173+ expect ( attrs [ 'trusted_content' ] ) . toBeUndefined ( ) ;
174+ expect ( attrs [ 'policy' ] ) . toBeUndefined ( ) ;
175+ expect ( attrs [ 'event.name' ] ) . toBe ( EVENT_CONSECA_POLICY_GENERATION ) ;
176+ } ) ;
177+
178+ it ( 'should omit user_prompt/trusted_content/policy from Clearcut when logPrompts is disabled' , ( ) => {
179+ const configNoPrompts = {
180+ getTelemetryEnabled : vi . fn ( ) . mockReturnValue ( true ) ,
181+ getSessionId : vi . fn ( ) . mockReturnValue ( 'test-session-id' ) ,
182+ getTelemetryLogPromptsEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
183+ getTelemetryTracesEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
184+ isInteractive : vi . fn ( ) . mockReturnValue ( true ) ,
185+ getExperiments : vi . fn ( ) . mockReturnValue ( { experimentIds : [ ] } ) ,
186+ getContentGeneratorConfig : vi . fn ( ) . mockReturnValue ( { authType : 'oauth' } ) ,
187+ } as unknown as Config ;
188+
189+ const event = new ConsecaPolicyGenerationEvent (
190+ 'sensitive prompt' ,
191+ 'sensitive content' ,
192+ 'sensitive policy' ,
193+ 'some error' ,
194+ ) ;
195+
196+ logConsecaPolicyGeneration ( configNoPrompts , event ) ;
197+
198+ expect ( mockClearcutLogger . createLogEvent ) . toHaveBeenCalledWith (
199+ expect . anything ( ) ,
200+ [
201+ {
202+ gemini_cli_key : EventMetadataKey . CONSECA_ERROR ,
203+ value : 'some error' ,
204+ } ,
205+ ] ,
206+ ) ;
207+ } ) ;
208+
209+ it ( 'should include user_prompt/trusted_content/policy in OTEL when logPrompts is enabled' , ( ) => {
210+ const event = new ConsecaPolicyGenerationEvent (
211+ 'visible prompt' ,
212+ 'visible content' ,
213+ 'visible policy' ,
214+ ) ;
215+
216+ logConsecaPolicyGeneration ( mockConfig , event ) ;
217+
218+ const attrs = mockLogger . emit . mock . calls [ 0 ] [ 0 ] . attributes as Record <
219+ string ,
220+ unknown
221+ > ;
222+ expect ( attrs [ 'user_prompt' ] ) . toBe ( 'visible prompt' ) ;
223+ expect ( attrs [ 'trusted_content' ] ) . toBe ( 'visible content' ) ;
224+ expect ( attrs [ 'policy' ] ) . toBe ( 'visible policy' ) ;
225+ } ) ;
226+
227+ it ( 'should omit sensitive fields from verdict OTEL when logPrompts is disabled' , ( ) => {
228+ const configNoPrompts = {
229+ getTelemetryEnabled : vi . fn ( ) . mockReturnValue ( true ) ,
230+ getSessionId : vi . fn ( ) . mockReturnValue ( 'test-session-id' ) ,
231+ getTelemetryLogPromptsEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
232+ getTelemetryTracesEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
233+ isInteractive : vi . fn ( ) . mockReturnValue ( true ) ,
234+ getExperiments : vi . fn ( ) . mockReturnValue ( { experimentIds : [ ] } ) ,
235+ getContentGeneratorConfig : vi . fn ( ) . mockReturnValue ( { authType : 'oauth' } ) ,
236+ } as unknown as Config ;
237+
238+ const event = new ConsecaVerdictEvent (
239+ 'sensitive prompt' ,
240+ 'sensitive policy' ,
241+ 'sensitive tool call' ,
242+ 'allow' ,
243+ 'sensitive rationale' ,
244+ ) ;
245+
246+ logConsecaVerdict ( configNoPrompts , event ) ;
247+
248+ const attrs = mockLogger . emit . mock . calls [ 0 ] [ 0 ] . attributes as Record <
249+ string ,
250+ unknown
251+ > ;
252+ expect ( attrs [ 'user_prompt' ] ) . toBeUndefined ( ) ;
253+ expect ( attrs [ 'policy' ] ) . toBeUndefined ( ) ;
254+ expect ( attrs [ 'tool_call' ] ) . toBeUndefined ( ) ;
255+ expect ( attrs [ 'verdict_rationale' ] ) . toBeUndefined ( ) ;
256+ // verdict (the allow/deny result) is not sensitive and should be present
257+ expect ( attrs [ 'verdict' ] ) . toBe ( 'allow' ) ;
258+ } ) ;
259+
260+ it ( 'should omit sensitive fields from verdict Clearcut when logPrompts is disabled' , ( ) => {
261+ const configNoPrompts = {
262+ getTelemetryEnabled : vi . fn ( ) . mockReturnValue ( true ) ,
263+ getSessionId : vi . fn ( ) . mockReturnValue ( 'test-session-id' ) ,
264+ getTelemetryLogPromptsEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
265+ getTelemetryTracesEnabled : vi . fn ( ) . mockReturnValue ( false ) ,
266+ isInteractive : vi . fn ( ) . mockReturnValue ( true ) ,
267+ getExperiments : vi . fn ( ) . mockReturnValue ( { experimentIds : [ ] } ) ,
268+ getContentGeneratorConfig : vi . fn ( ) . mockReturnValue ( { authType : 'oauth' } ) ,
269+ } as unknown as Config ;
270+
271+ const event = new ConsecaVerdictEvent (
272+ 'sensitive prompt' ,
273+ 'sensitive policy' ,
274+ 'sensitive tool call' ,
275+ 'allow' ,
276+ 'sensitive rationale' ,
277+ 'some error' ,
278+ ) ;
279+
280+ logConsecaVerdict ( configNoPrompts , event ) ;
281+
282+ expect ( mockClearcutLogger . createLogEvent ) . toHaveBeenCalledWith (
283+ expect . anything ( ) ,
284+ [
285+ {
286+ gemini_cli_key : EventMetadataKey . CONSECA_VERDICT_RESULT ,
287+ value : '"allow"' ,
288+ } ,
289+ {
290+ gemini_cli_key : EventMetadataKey . CONSECA_ERROR ,
291+ value : 'some error' ,
292+ } ,
293+ ] ,
294+ ) ;
295+ } ) ;
296+
297+ it ( 'should include sensitive fields in verdict OTEL when logPrompts is enabled' , ( ) => {
298+ const event = new ConsecaVerdictEvent (
299+ 'visible prompt' ,
300+ 'visible policy' ,
301+ 'visible tool call' ,
302+ 'deny' ,
303+ 'visible rationale' ,
304+ ) ;
305+
306+ logConsecaVerdict ( mockConfig , event ) ;
307+
308+ const attrs = mockLogger . emit . mock . calls [ 0 ] [ 0 ] . attributes as Record <
309+ string ,
310+ unknown
311+ > ;
312+ expect ( attrs [ 'user_prompt' ] ) . toBe ( 'visible prompt' ) ;
313+ expect ( attrs [ 'policy' ] ) . toBe ( 'visible policy' ) ;
314+ expect ( attrs [ 'tool_call' ] ) . toBe ( 'visible tool call' ) ;
315+ expect ( attrs [ 'verdict_rationale' ] ) . toBe ( 'visible rationale' ) ;
316+ expect ( attrs [ 'verdict' ] ) . toBe ( 'deny' ) ;
317+ } ) ;
147318} ) ;
0 commit comments