Ë
    uPêjA  ã                   ó    — d Z ddlZddlmZmZmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZmZmZmZ erdd	lmZ dd
lmZ  G d„ d«      Zy)aY  
Policy Validator - Validates policy configurations.

Validates:
- Guardrail names exist in the guardrail registry
- Non-wildcard team aliases exist in the database
- Non-wildcard key aliases exist in the database
- Non-wildcard model names exist in the router or match a wildcard route
- Inheritance chains are valid (no cycles, parents exist)
é    N)ÚTYPE_CHECKINGÚAnyÚFinalÚOptional)Úverbose_proxy_logger)ÚRouteChecks)ÚTeamRepository)ÚVerificationTokenRepository)ÚPolicyÚPolicyValidationErrorÚPolicyValidationErrorTypeÚPolicyValidationResponse)ÚPrismaClient)ÚRouterc                   ó¶  — e Zd ZdZ	 	 d'ded   ded   fd„Zeded	efd
„«       Z	d	e
e   fd„Zded	efd„Zded	efd„Zded	efd„Zedededededed	efd„«       Z	 	 	 d(dedee   dz  dee   dz  dee   dz  d	ee   f
d„Z	 	 d)dedeeef   de
e   dz  ded	ee   f
d„Z	 d*deeef   d ed	efd!„Zeded"ed#e
e   d	ee   fd$„«       Z	 d*d%eeef   d ed	efd&„Zy)+ÚPolicyValidatorz>
    Validates policy configurations against actual data.
    NÚprisma_clientr   Ú
llm_routerr   c                 ó    — || _         || _        y)zÅ
        Initialize the validator.

        Args:
            prisma_client: Optional Prisma client for database validation
            llm_router: Optional LLM router for model validation
        N)r   r   )Úselfr   r   s      úq/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/policy_engine/policy_validator.pyÚ__init__zPolicyValidator.__init__&   s   € ð +ˆÔØ$ˆ�ó    ÚpatternÚreturnc                 ó   — d| v xs d| v S )zÀ
        Check if a pattern contains wildcards.

        Args:
            pattern: The pattern to check

        Returns:
            True if the pattern contains wildcard characters
        Ú*ú?© ©r   s    r   Úis_wildcard_patternz#PolicyValidator.is_wildcard_pattern5   s   € ð �gˆ~Ò/ ¨ Ð/r   c                 ó
  — 	 ddl m} |j                  «       }|D �ch c]&  }|j                  d«      sŒ|j                  dd«      ’Œ( c}S c c}w # t        $ r*}t        j                  d|«       t        «       cY d}~S d}~ww xY w)zˆ
        Get set of available guardrail names from the guardrail registry.

        Returns:
            Set of guardrail names
        r   )ÚIN_MEMORY_GUARDRAIL_HANDLERÚguardrail_nameÚ z*Could not get guardrails from registry: %sN)Ú+litellm.proxy.guardrails.guardrail_registryr#   Úlist_in_memory_guardrailsÚgetÚ	Exceptionr   ÚwarningÚset)r   r#   Ú
guardrailsÚgÚes        r   Úget_available_guardrailsz(PolicyValidator.get_available_guardrailsB   sq   € ð		õð !<× UÑ UÓ WˆJØ9CÖ_°AÀqÇuÁuÐM]ÕG^�A—E‘EÐ*¨BÕ/Ò_Ð_ùÒ_øÜò 	Ü ×(Ñ(Ð)UÐWXÔYÜ“5�Lûð	ús3   ‚A œA
³A
ÁA Á
A Á	BÁA=Á7BÁ=BÚ
team_aliasc              ƒ   óþ   K  — | j                   €y	 t        | j                   «      j                  j                  d|i¬«      ƒ d{  –—† }|duS 7 Œ# t        $ r!}t        j                  d||«       Y d}~yd}~ww xY w­w)zÃ
        Check if a specific team alias exists in the database.

        Args:
            team_alias: The team alias to check

        Returns:
            True if the team alias exists
        NTr0   ©Úwherez#Could not check team alias '%s': %s)r   r	   ÚtableÚ
find_firstr)   r   r*   )r   r0   Úteamr.   s       r   Úcheck_team_alias_existsz'PolicyValidator.check_team_alias_existsT   s‹   è ø€ ð ×ÑÐ%Øð	Ü .¨t×/AÑ/AÓ B× HÑ H× SÑ SØ# ZÐ0ð !Tó !÷ ˆDð ˜tÐ#Ð#ðùô ò 	Ü ×(Ñ(Ð)NÐPZÐ\]Ô^Üûð	üó@   ‚A=‘4A ÁAÁA ÁA=ÁA Á	A:ÁA5Á0A=Á5A:Á:A=Ú	key_aliasc              ƒ   óþ   K  — | j                   €y	 t        | j                   «      j                  j                  d|i¬«      ƒ d{  –—† }|duS 7 Œ# t        $ r!}t        j                  d||«       Y d}~yd}~ww xY w­w)z¿
        Check if a specific key alias exists in the database.

        Args:
            key_alias: The key alias to check

        Returns:
            True if the key alias exists
        NTr9   r2   z"Could not check key alias '%s': %s)r   r
   r4   r5   r)   r   r*   )r   r9   Úkeyr.   s       r   Úcheck_key_alias_existsz&PolicyValidator.check_key_alias_existsj   s‰   è ø€ ð ×ÑÐ%Øð	Ü:¸4×;MÑ;MÓN×TÑT×_Ñ_Ø" IÐ.ð  `ó  ÷ ˆCð ˜d�?Ð"ðùô ò 	Ü ×(Ñ(Ð)MÈyÐZ[Ô\Üûð	ür8   Úmodelc                 ó*  — | j                   €y	 || j                   j                  v ryt        | j                   d«      r)| j                   j                  j	                  |¬«      }|ryy# t
        $ r!}t        j                  d||«       Y d}~yd}~ww xY w)zê
        Check if a model exists in the router or matches a wildcard pattern.

        Args:
            model: The model name to check

        Returns:
            True if the model exists or matches a pattern in the router
        NTÚpattern_router)r=   FzCould not check model '%s': %s)r   Úmodel_namesÚhasattrr?   Úget_deployments_by_patternr)   r   r*   )r   r=   Úpattern_deploymentsr.   s       r   Úcheck_model_existsz"PolicyValidator.check_model_exists€   s‹   € ð �?‰?Ð"Øð	à˜Ÿ™×3Ñ3Ñ3Øô �t—‘Ð(8Ô9Ø-1¯_©_×-KÑ-K×-fÑ-fÐmrÐ-fÓ-sÐ#Ù&ØàøÜò 	Ü ×(Ñ(Ð)IÈ5ÐRSÔTÜûð	ús   �A( ¨>A( Á(	BÁ1BÂBÚpolicy_nameÚ
error_typeÚfieldÚvalueÚlabelc                 óV   — t        | ||j                  «       › d|› d|› d|› d�||¬«      S )Nz 'z(' does not exist. Reference an existing z" or use a wildcard pattern (e.g. 'z*') to match by prefix.©rE   rF   ÚmessagerG   rH   )r   Ú
capitalize)rE   rF   rG   rH   rI   s        r   Ú_scope_errorzPolicyValidator._scope_error�   sL   € ô %Ø#Ø!à×#Ñ#Ó%Ð& b¨¨Ð/WØ�'Ð;¸E¸7ÐBYð[ð Øô	
ð 		
r   ÚteamsÚkeysÚmodelsc              ƒ   ó  ‡ ‡K  — t         j                  }|xs g D �cg c]  } ||¬«      rŒ|‘Œ }}|xs g D �cg c]  } ||¬«      rŒ|‘Œ }	}|xs g D �
cg c]  }
 ||
¬«      rŒ|
‘Œ }}
t        j                  ˆ fd„|D «       Ž ƒ d{  –—† }t        j                  ˆ fd„|	D «       Ž ƒ d{  –—† }g ˆˆ fd„t	        ||«      D «       ¢ˆˆ fd„t	        |	|«      D «       ¢ˆˆ fd„|D «       ¢S c c}w c c}w c c}
w 7 Œp7 ŒO­w)a   
        Validate the concrete scope entries of a policy attachment.

        Returns an error for every non-wildcard entry that does not resolve to an
        existing team alias, key alias, or model. Wildcard patterns are always
        accepted: a pattern like "healthcare-*" may match zero entities today and
        match ones created later, so it cannot be validated by existence. Tags are
        intentionally not checked - they are free-form labels with no registry to
        validate against.
        r    c              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­w©N)r7   )Ú.0Útr   s     €r   ú	<genexpr>z=PolicyValidator.find_invalid_scope_entries.<locals>.<genexpr>É   s   øè ø€ Ò3lÐXY°D×4PÑ4PÐQR×4SÑ3lùó   ƒNc              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wrT   )r<   )rU   Úkr   s     €r   rW   z=PolicyValidator.find_invalid_scope_entries.<locals>.<genexpr>Ê   s   øè ø€ Ò2iÐVW°4×3NÑ3NÈq×3QÑ2iùrX   c              3   ón   •K  — | ],  \  }}|s%‰j                  ‰t        j                  d |d«      –— Œ. y­w)rO   r6   N)rN   r   ÚINVALID_TEAM)rU   r6   ÚexistsrE   r   s      €€r   rW   z=PolicyValidator.find_invalid_scope_entries.<locals>.<genexpr>Í   s=   øè ø€ ò á �D˜&Ùð ×!Ñ! +Ô/H×/UÑ/UÐW^Ð`dÐfl×mñùó   ƒ25c              3   ón   •K  — | ],  \  }}|s%‰j                  ‰t        j                  d |d«      –— Œ. y­w)rP   r;   N)rN   r   ÚINVALID_KEY)rU   r;   r]   rE   r   s      €€r   rW   z=PolicyValidator.find_invalid_scope_entries.<locals>.<genexpr>Ò   s=   øè ø€ ò á�C˜Ùð ×!Ñ! +Ô/H×/TÑ/TÐV\Ð^aÐch×iñùr^   c              3   ó†   •K  — | ]8  }‰j                  |«      s%‰j                  ‰t        j                  d |d«      –— Œ: y­w)rQ   r=   N)rD   rN   r   ÚINVALID_MODEL)rU   r=   rE   r   s     €€r   rW   z=PolicyValidator.find_invalid_scope_entries.<locals>.<genexpr>×   sD   øè ø€ ò àØ×.Ñ.¨uÔ5ð ×!Ñ! +Ô/H×/VÑ/VÐX`ÐbgÐip×qñùs   ƒ>A)r   Ú_is_wildcard_patternÚasyncioÚgatherÚzip)r   rE   rO   rP   rQ   Ú
is_patternrV   Úconcrete_teamsrZ   Úconcrete_keysÚmÚconcrete_modelsÚteam_existsÚ
key_existss   ``            r   Úfind_invalid_scope_entriesz*PolicyValidator.find_invalid_scope_entries°   s  ùè ø€ ô( (×<Ñ<ˆ
Ø-2ª[°bÖ W qÁÐTUÖAV¢Ð WˆÐ WØ,0ªJ°BÖU a¹zÐRSÖ?T¢ÐUˆÐUØ.4ªl¸Ö!Y¨Á:ÐVWÖCX¢!Ð!YˆÐ!Yä#*§>¡>Ó3lÐ]kÔ3lÐ#m×mˆÜ")§.¡.Ó2iÐ[hÔ2iÐ"j×jˆ
ð
ôä$'¨¸Ó$Dôð
ôä#& }°jÓ#Aôð
ôà,ôð
ð 	
ùò !XùÚUùÚ!YàmøØjúsV   „C?�C,¬C,°
C?ºC1Á	C1Á
C?ÁC6Á&C6Á* C?Â
C;Â"C?Â-C=Â.AC?Ã=C?ÚpoliciesÚvisitedÚ	max_depthc           
      ó„  — g }|dk  r.|j                  t        |t        j                  dd¬«      «       |S |€
t	        «       }||v rC|j                  t        |t        j                  ddj                  |«      › d|› �d¬«      «       |S |j                  |«      }|€|S |j                  r–|j                  |vrG|j                  t        |t        j                  d|j                  › d�d|j                  ¬	«      «       |S |j                  |«       |j                  | j                  |j                  |||d
z
  «      «       |S )aï  
        Validate the inheritance chain for a policy.

        Checks for:
        - Parent policy exists
        - No circular inheritance
        - Max depth not exceeded

        Args:
            policy_name: Name of the policy to validate
            policies: All policies
            visited: Set of already visited policy names (for cycle detection)
            max_depth: Maximum recursion depth to prevent infinite loops

        Returns:
            List of validation errors
        r   z6Inheritance chain too deep (exceeded max depth of 100)Úinherit)rE   rF   rL   rG   zCircular inheritance detected: z -> zParent policy 'z' not foundrK   é   )Úappendr   r   ÚCIRCULAR_INHERITANCEr+   Újoinr(   rs   ÚINVALID_INHERITANCEÚaddÚextendÚ_validate_inheritance_chain)r   rE   ro   rp   rq   ÚerrorsÚpolicys          r   r{   z+PolicyValidator._validate_inheritance_chainÞ   sC  € ð0 68ˆð ˜Š>Ø�M‰MÜ%Ø +Ü8×MÑMØTØ#ô	ôð ˆMàˆ?Ü“eˆGà˜'Ñ!Ø�M‰MÜ%Ø +Ü8×MÑMØ=¸f¿k¹kÈ'Ó>RÐ=SÐSWÐXcÐWdÐeØ#ô	ôð ˆMà Ÿ™ [Ó1ˆØˆ>ØˆMà�>Š>Ø�~‰~ XÑ-Ø—‘Ü)Ø$/Ü#<×#PÑ#PØ"1°&·.±.Ð1AÀÐ MØ'Ø$Ÿn™nôôð ˆð —‘˜KÔ(Ø—‘˜d×>Ñ>¸v¿~¹~ÈxÐY`ÐbkÐnoÑboÓpÔqàˆr   Úvalidate_dbc              ƒ   ó¬  K  — g }g }| j                  «       }|j                  «       D �]  \  }}|j                  j                  «       D ];  }|sŒ||vsŒ|j	                  t        |t        j                  d|› d�d|¬«      «       Œ= |j                  j                  «       D ];  }|sŒ||vsŒ|j	                  t        |t        j                  d|› d�d|¬«      «       Œ= |j                  �)t        j                  |||¬«      }	|j                  |	«       | j                  ||¬«      }
|j                  |
«       �Œ t        t        |«      d	k(  ||¬
«      S ­w)a   
        Validate a set of policies.

        Args:
            policies: Dictionary mapping policy names to Policy objects
            validate_db: Whether to validate against database (teams, keys)

        Returns:
            PolicyValidationResponse with errors and warnings
        zGuardrail 'ú!' not found in guardrail registryzguardrails.addrK   z0' in remove list not found in guardrail registryzguardrails.remove)rE   r}   Úavailable_guardrails)rE   ro   r   ©Úvalidr|   Úwarnings)r/   Úitemsr,   Úget_addru   r   r   ÚINVALID_GUARDRAILÚ
get_removeÚpipeliner   Ú_validate_pipelinerz   r{   r   Úlen)r   ro   r~   r|   r„   r�   rE   r}   Ú	guardrailÚpipeline_errorsÚinheritance_errorss              r   Úvalidate_policiesz!PolicyValidator.validate_policies(  sz  è ø€ ð 68ˆØ79ˆð '+×&CÑ&CÓ&EÐà#+§>¡>Ó#3ó %	.ÑˆK˜à#×.Ñ.×6Ñ6Ó8ò 
�	Ú'¨IÐ=QÒ,QØ—M‘MÜ-Ø(3Ü'@×'RÑ'RØ&1°)°Ð<]Ð$^Ø"2Ø"+ôõð
ð $×.Ñ.×9Ñ9Ó;ò 
�	Ú'¨IÐ=QÒ,QØ—O‘OÜ-Ø(3Ü'@×'RÑ'RØ&1°)°Ð<lÐ$mØ"5Ø"+ôõð
ð �‰Ð*Ü"1×"DÑ"DØ +Ø!Ø)=ð #Eó #�ð
 —‘˜oÔ.ð "&×!AÑ!AÈkÐdlÐ!AÓ!mÐØ�M‰MÐ,Ö-ðK%	.ôN (Ü�f“+ Ñ"ØØô
ð 	
ùs    ‚AEÁEÁAEÂ&EÂ+B)Er}   r�   c                 ó
  — g }|j                   }|€|S t        |j                  j                  «       «      }t	        |j
                  «      D ]µ  \  }}|j                  |vrH|j                  t        | t        j                  d|› d|j                  › d�d|j                  ¬«      «       |sŒ_|j                  |vsŒn|j                  t        | t        j                  d|› d|j                  › d�d|j                  ¬«      «       Œ· |S )z+Validate a policy's pipeline configuration.zPipeline step z guardrail 'z,' is not in the policy's guardrails.add listzpipeline.stepsrK   r€   )r‰   r+   r,   r†   Ú	enumerateÚstepsrŒ   ru   r   r   r‡   )rE   r}   r�   r|   r‰   Úguardrails_addÚiÚsteps           r   rŠ   z"PolicyValidator._validate_pipelinej  sú   € ð 68ˆØ Ÿ/™/ˆØÐØˆMä # F×$5Ñ$5×$=Ñ$=Ó$?Ó @ˆä  §¡Ó0ò 	‰GˆAˆtà�~‰~ ^Ñ3Ø—‘Ü)Ø$/Ü#<×#NÑ#Nà,¨Q¨C¨|¸D¿N¹NÐ;KÐKwÐxà.Ø"Ÿn™nôô
ò $¨¯©Ð>RÒ(RØ—‘Ü)Ø$/Ü#<×#NÑ#NØ#1°!°°LÀÇÁÐ@PÐPqÐ!rØ.Ø"Ÿn™nôõð#	ð6 ˆr   Úpolicy_configc           
   ƒ   ón  K  — ddl m} g }i } |«       }|j                  «       D ]  \  }}	 |j                  ||«      }	|	||<   Œ |rt        d|g ¬«      S | j                  ||¬«      ƒ d{  –—† S # t        $ r8}
|j                  t        |t        j                  d|
› �¬«      «       Y d}
~
Œ‡d}
~
ww xY w7 ŒH­w)	aS  
        Validate a raw policy configuration dictionary.

        This parses the config and then validates it.

        Args:
            policy_config: Raw policy configuration from YAML
            validate_db: Whether to validate against database

        Returns:
            PolicyValidationResponse with errors and warnings
        r   )ÚPolicyRegistryzFailed to parse policy: )rE   rF   rL   NFr‚   )r~   )Ú+litellm.proxy.policy_engine.policy_registryr˜   r…   Ú_parse_policyr)   ru   r   r   ÚINVALID_SYNTAXr   r�   )r   r–   r~   r˜   r|   ro   Útemp_registryrE   Úpolicy_datar}   r.   s              r   Úvalidate_policy_configz&PolicyValidator.validate_policy_config•  sÛ   è ø€ õ" 	Oð 68ˆØ-/ˆá-Ó/ˆà(5×(;Ñ(;Ó(=ò 	Ñ$ˆK˜ð
Ø&×4Ñ4°[À+ÓN�Ø(.�˜Ò%ð	ñ Ü+ØØØôð ð ×+Ñ+¨HÀ+Ð+ÓN×NÐNøô% ò Ø—‘Ü)Ø$/Ü#<×#KÑ#KØ":¸1¸#Ð >ô÷ñ ûðúð$ Oús:   ‚(B5«A/Á(B5Á*B3Á+B5Á/	B0Á8.B+Â&B5Â+B0Â0B5)NN)NNN)Néd   )T)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   ÚstaticmethodÚstrÚboolr!   r+   r/   r7   r<   rD   r   r   rN   Úlistrn   Údictr   Úintr{   r   r�   rŠ   r   rž   r   r   r   r   r   !   sM  „ ñð 37Ø)-ñ%à Ñ/ð%ð ˜XÑ&ó%ð ð
0 Sð 
0¨Tò 
0ó ð
0ð¨#¨c©(ó ð$¸ð Àó ð,°cð ¸dó ð,¨ð °ó ð: ð
Øð
à-ð
ð ð
ð ð	
ð
 ð
ð 
ò
ó ð
ð* #'Ø!%Ø#'ñ,
àð,
ð �C‰y˜4Ñð,
ð �3‰i˜$Ñð	,
ð
 �S‘	˜DÑ ð,
ð 
Ð#Ñ	$ó,
ðd $(ØñHàðHð �s˜F�{Ñ#ðHð �S‘˜D‘ð	Hð
 ðHð 
Ð#Ñ	$óHðZ !ñ@
à�s˜F�{Ñ#ð@
ð ð@
ð 
"ó	@
ðD ð(Øð(àð(ð " #™hð(ð 
Ð#Ñ	$ò	(ó ð(ðZ !ñ/Oà˜C ˜H‘~ð/Oð ð/Oð 
"ô	/Or   r   )r£   rd   Útypingr   r   r   r   Úlitellm._loggingr   Úlitellm.proxy.auth.route_checksr   Ú$litellm.repositories.team_repositoryr	   Ú2litellm.repositories.verification_token_repositoryr
   Ú!litellm.types.proxy.policy_enginer   r   r   r   Úlitellm.proxy.utilsr   Úlitellm.routerr   r   r   r   r   ú<module>r²      sF   ðñ	ó ß 6Ó 6å 1Ý 7Ý ?õ÷ó ñ Ý0Ý%÷cOò cOr   