@@ -19,7 +19,7 @@ const mocks = vi.hoisted(() => ({
1919 requireBillingAttribution : vi . fn ( ) ,
2020 validateHallucination : vi . fn ( ) ,
2121 validateJson : vi . fn ( ) ,
22- validatePII : vi . fn ( ) ,
22+ validatePIIViaHttp : vi . fn ( ) ,
2323 validateRegex : vi . fn ( ) ,
2424} ) )
2525
@@ -41,8 +41,10 @@ vi.mock('@/lib/guardrails/validate_hallucination', () => ({
4141 validateHallucination : mocks . validateHallucination ,
4242} ) )
4343vi . mock ( '@/lib/guardrails/validate_json' , ( ) => ( { validateJson : mocks . validateJson } ) )
44- vi . mock ( '@/lib/guardrails/validate_pii' , ( ) => ( { validatePII : mocks . validatePII } ) )
4544vi . mock ( '@/lib/guardrails/validate_regex' , ( ) => ( { validateRegex : mocks . validateRegex } ) )
45+ vi . mock ( '@/lib/guardrails/validation-client' , ( ) => ( {
46+ validatePIIViaHttp : mocks . validatePIIViaHttp ,
47+ } ) )
4648vi . mock ( '@/ee/access-control/utils/permission-check' , ( ) => ( {
4749 assertPermissionsAllowed : mocks . assertPermissionsAllowed ,
4850 ModelNotAllowedError : class ModelNotAllowedError extends Error { } ,
@@ -78,7 +80,7 @@ describe('executeGuardrailsValidation', () => {
7880 mocks . validateHallucination . mockResolvedValue ( { passed : true , score : 8 } )
7981 mocks . validateJson . mockReturnValue ( { passed : true } )
8082 mocks . validateRegex . mockReturnValue ( { passed : true } )
81- mocks . validatePII . mockResolvedValue ( { passed : true , detectedEntities : [ ] } )
83+ mocks . validatePIIViaHttp . mockResolvedValue ( { passed : true , detectedEntities : [ ] } )
8284 } )
8385
8486 it ( 'runs hallucination work once with authorized scope, billing, provenance, and signal' , async ( ) => {
@@ -146,6 +148,38 @@ describe('executeGuardrailsValidation', () => {
146148 expect ( mocks . requireBillingAttribution ) . not . toHaveBeenCalled ( )
147149 } )
148150
151+ it ( 'routes PII validation through the app-container capability boundary' , async ( ) => {
152+ const controller = new AbortController ( )
153+
154+ const result = await executeGuardrailsValidation (
155+ {
156+ validationType : 'pii' ,
157+ input : 'email a@b.com' ,
158+ piiEntityTypes : [ 'EMAIL_ADDRESS' ] ,
159+ piiMode : 'mask' ,
160+ piiLanguage : 'en' ,
161+ } ,
162+ {
163+ actorUserId : 'user-1' ,
164+ headers : new Headers ( ) ,
165+ requestId : 'request-1' ,
166+ signal : controller . signal ,
167+ }
168+ )
169+
170+ expect ( result . output . passed ) . toBe ( true )
171+ expect ( mocks . validatePIIViaHttp ) . toHaveBeenCalledWith (
172+ {
173+ text : 'email a@b.com' ,
174+ entityTypes : [ 'EMAIL_ADDRESS' ] ,
175+ mode : 'mask' ,
176+ language : 'en' ,
177+ customPatterns : undefined ,
178+ } ,
179+ controller . signal
180+ )
181+ } )
182+
149183 it ( 'conceals inaccessible workflow validation as a failed verdict without provider work' , async ( ) => {
150184 workflowAuthzMockFns . mockAuthorizeWorkflowByWorkspacePermission . mockResolvedValueOnce ( {
151185 allowed : false ,
0 commit comments