@@ -364,13 +364,118 @@ impl QueryExecutor {
364364 }
365365 }
366366
367+ /// Validate a query against TypeLL's VQL-UT 10-level type checker.
368+ ///
369+ /// Calls the TypeLL server at localhost:7800 to verify that the query
370+ /// meets its declared safety level. Returns the verified level and any
371+ /// diagnostics. Falls back gracefully if TypeLL is unreachable.
372+ async fn validate_with_typell ( & self , query : & ProofQuery ) -> Result < TypeLevel > {
373+ let typell_url = std:: env:: var ( "TYPELL_URL" )
374+ . unwrap_or_else ( |_| "http://localhost:7800" . to_string ( ) ) ;
375+
376+ let check_body = serde_json:: json!( {
377+ "query" : serde_json:: to_string( query) . unwrap_or_default( ) ,
378+ "modalities" : [ "Semantic" , "Document" , "Graph" , "Provenance" , "Temporal" ] ,
379+ "result_fields" : query. theorem_name. as_deref( ) . map( |t| vec![ t] ) . unwrap_or_default( ) ,
380+ } ) ;
381+
382+ let client = reqwest:: Client :: builder ( )
383+ . timeout ( std:: time:: Duration :: from_secs ( 5 ) )
384+ . build ( )
385+ . context ( "Failed to create HTTP client for TypeLL" ) ?;
386+
387+ match client
388+ . post ( format ! ( "{}/api/v1/vql-ut/check" , typell_url) )
389+ . json ( & check_body)
390+ . send ( )
391+ . await
392+ {
393+ Ok ( resp) if resp. status ( ) . is_success ( ) => {
394+ if let Ok ( body) = resp. json :: < serde_json:: Value > ( ) . await {
395+ let max_level = body
396+ . get ( "safety_report" )
397+ . and_then ( |sr| sr. get ( "max_level" ) )
398+ . and_then ( |ml| ml. as_u64 ( ) )
399+ . unwrap_or ( 0 ) ;
400+
401+ let valid = body
402+ . get ( "valid" )
403+ . and_then ( |v| v. as_bool ( ) )
404+ . unwrap_or ( true ) ;
405+
406+ if !valid {
407+ let errors = body
408+ . get ( "rule_errors" )
409+ . and_then ( |e| e. as_array ( ) )
410+ . map ( |arr| {
411+ arr. iter ( )
412+ . filter_map ( |v| v. as_str ( ) )
413+ . collect :: < Vec < _ > > ( )
414+ . join ( "; " )
415+ } )
416+ . unwrap_or_default ( ) ;
417+ anyhow:: bail!( "TypeLL VQL-UT validation failed: {}" , errors) ;
418+ }
419+
420+ info ! (
421+ "TypeLL verified VQL-UT level {}/10 for {:?}" ,
422+ max_level, query. operation,
423+ ) ;
424+
425+ // Map TypeLL's 1-based SafetyLevel to our 0-10 TypeLevel
426+ Ok ( match max_level {
427+ 0 | 1 => TypeLevel :: Parse ,
428+ 2 => TypeLevel :: Schema ,
429+ 3 => TypeLevel :: TypeCompat ,
430+ 4 => TypeLevel :: NullSafe ,
431+ 5 => TypeLevel :: InjectionProof ,
432+ 6 => TypeLevel :: ResultType ,
433+ 7 => TypeLevel :: Cardinality ,
434+ 8 => TypeLevel :: Effect ,
435+ 9 => TypeLevel :: Temporal ,
436+ 10 => TypeLevel :: Linear ,
437+ _ => TypeLevel :: Linear ,
438+ } )
439+ } else {
440+ debug ! ( "TypeLL returned non-JSON response, falling back" ) ;
441+ Ok ( query. level )
442+ }
443+ }
444+ Ok ( resp) => {
445+ debug ! (
446+ "TypeLL returned status {}, falling back to local validation" ,
447+ resp. status( )
448+ ) ;
449+ Ok ( query. level )
450+ }
451+ Err ( e) => {
452+ debug ! ( "TypeLL unreachable ({}), falling back to local validation" , e) ;
453+ Ok ( query. level )
454+ }
455+ }
456+ }
457+
367458 /// Execute a typed query and return results.
459+ ///
460+ /// Validates the query against TypeLL's 10-level type checker before
461+ /// execution. Falls back to local validation if TypeLL is unreachable.
368462 pub async fn execute ( & self , query : & ProofQuery ) -> Result < QueryResult > {
369463 info ! (
370464 "Executing VQL-UT query: {:?} at level {:?}" ,
371465 query. operation, query. level,
372466 ) ;
373467
468+ // Pre-flight: validate with TypeLL if available
469+ let verified_level = self . validate_with_typell ( query) . await . unwrap_or ( query. level ) ;
470+
471+ if ( verified_level as u8 ) < ( query. level as u8 ) {
472+ anyhow:: bail!(
473+ "TypeLL verified level {:?} is below requested level {:?}" ,
474+ verified_level,
475+ query. level,
476+ ) ;
477+ }
478+
374479 match query. operation {
375480 QueryOp :: FindProof => self . execute_find_proof ( query) . await ,
376481 QueryOp :: FindSimilar => self . execute_find_similar ( query) . await ,
0 commit comments