Ë
    tPêj1  ã                   ó  — U d Z ddlm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 dd	lmZmZ dd
lmZmZmZ erddlmZ ddlmZ dZeed<    eddh«      Z eed<   de!dz  de"fd„Z# G d„ de«      Z$y)zÇ
Security hook to prevent user B from seeing response from user A.

This hook uses the DBSpendUpdateWriter to batch-write response IDs to the database
instead of writing immediately on each request.
é    )ÚAsyncGenerator)ÚTYPE_CHECKINGÚAnyÚFinalÚcast)ÚHTTPException)Úverbose_proxy_logger)ÚCustomLogger)ÚLitellmUserRoles)Údecrypt_value_helperÚencrypt_value_helper)ÚBaseLiteLLMOpenAIResponseObjectÚResponsesAPIResponse)ÚCallTypesLiteralÚLLMResponseTypesÚSpecialEnums)Ú	DualCache)ÚUserAPIKeyAuthz/openaiÚ_RESPONSES_API_PROVIDER_PREFIXz/v1/responsesz
/responsesÚ_RESPONSES_API_CREATE_ROUTESÚrequest_routeNÚreturnc                 óp   — | €y| j                  t        dz   «      r| t        t        «      d  n| }|t        v S )NFú/)Ú
startswithr   Úlenr   )r   Ú	canonicals     ún/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/hooks/responses_id_security.pyÚ_is_responses_api_create_router   #   sJ   € ØÐØð ×#Ñ#Ô$BÀSÑ$HÔIð 	”cÔ8Ó9Ð;Ñ<àð ð
 Ô4Ð4Ð4ó    c                   ó  — e Zd Zd„ Zdddddededeez  ez  d	z  f
d
„Zded	z  ded	z  ddde	fd„Z
dede	fd„Zdedeeed	z  ed	z  f   fd„Zded	z  fd„Z	 ddedddeeef   d	z  defd„Zdedddedefd„Zdddededeed	f   fd„Zy	)ÚResponsesIDSecurityc                  ó   — y ©N© )Úselfs    r   Ú__init__zResponsesIDSecurity.__init__/   s   € Ør    Úuser_api_key_dictr   Úcacher   ÚdataÚ	call_typer   Nc              ƒ   óz  K  — h d£}||vry |dk(  rS|j                  d«      }|r>| j                  |«      r-| j                  |«      \  }}}	| j                  ||	|«       ||d<   |S |dv rQ|j                  d«      }
|
r>| j                  |
«      r-| j                  |
«      \  }}}	| j                  ||	|«       ||d<   |S ­w)N>   Ú
aresponsesÚaget_responsesÚacancel_responsesÚadelete_responsesÚalist_input_itemsr-   Úprevious_response_id>   r.   r/   r0   r1   Úresponse_id)ÚgetÚ_is_encrypted_response_idÚ_decrypt_response_idÚ check_user_access_to_response_id)r&   r(   r)   r*   r+   Úresponses_api_call_typesr2   Úoriginal_response_idÚuser_idÚteam_idr3   s              r   Úasync_pre_call_hookz'ResponsesIDSecurity.async_pre_call_hook2   sç   è ø€ ò+
Ð ð Ð4Ñ4ØØ˜Ò$à*.¯(©(Ð3IÓ*JÐ Ù#¨×(FÑ(FÐG[Ô(\Ø9=×9RÑ9RÐSgÓ9hÑ6Ð$ g¨wØ×5Ñ5°g¸wÐHYÔZØ/C�Ð+Ñ,ð ˆð ÐkÑkØ!%§¡¨-Ó!8ˆKá˜t×=Ñ=¸kÔJØ9=×9RÑ9RÐS^Ó9_Ñ6Ð$ g¨wà×5Ñ5°g¸wÐHYÔZØ&:��]Ñ#Øˆùs   ‚B9B;Úresponse_id_user_idÚresponse_id_team_idc                 óø  — ddl m} |j                  t        j                  j
                  k(  s|j                  t        j                  k(  ry|rP||j                  k7  rA|j                  dd«      r"t        j                  d|j                  |«       yt        dd¬	«      ‚|r[||j                  k7  rL|j                  dd«      r-t        j                  d
||j                  |j                  «       yt        dd¬	«      ‚y)Nr   ©Úgeneral_settingsTÚdisable_responses_id_securityFziResponses ID Security is disabled. User %s is accessing response id %s which is not associated with them.i“  zËForbidden. The response id is not associated with the user, who this key belongs to. To disable this security feature, set general_settings::disable_responses_id_security to True in the config.yaml file.)Ústatus_codeÚdetailzkResponses ID Security is disabled. Response belongs to team %s but user %s is accessing it with team id %s.zËForbidden. The response id is not associated with the team, who this key belongs to. To disable this security feature, set general_settings::disable_responses_id_security to True in the config.yaml file.)Úlitellm.proxy.proxy_serverrA   Ú	user_roler   ÚPROXY_ADMINÚvaluer:   r4   r	   Údebugr   r;   )r&   r=   r>   r(   rA   s        r   r7   z4ResponsesIDSecurity.check_user_access_to_response_idT   s  € õ 	@ð ×'Ñ'Ô+;×+GÑ+G×+MÑ+MÒMØ ×*Ñ*Ô.>×.JÑ.JÒJàáÐ#6Ð:K×:SÑ:SÒ#SØ×#Ñ#Ð$CÀUÔKÜ$×*Ñ*ØØ%×-Ñ-Ø'ôð
 ÜØð eôð ñ
 Ð#6Ð:K×:SÑ:SÒ#SØ×#Ñ#Ð$CÀUÔKÜ$×*Ñ*ð BØ'Ø%×-Ñ-Ø%×-Ñ-ô	ð ÜØð eôð ð
 r    r3   c                 óÄ   — |j                  d«      }t        |«      dk  ry|d   }t        |dd¬«      }|€y|j                  t        j
                  j                  «      ryy)NÚresp_é   Fé   r3   T©rH   ÚkeyÚreturn_original_value©Úsplitr   r   r   r   ÚLITELM_MANAGED_FILE_ID_PREFIXrH   )r&   r3   Úsplit_resultÚremaining_stringÚdecrypted_values        r   r5   z-ResponsesIDSecurity._is_encrypted_response_id   se   € Ø)×/Ñ/°Ó8ˆÜˆ|Ó˜qÒ Øà".¨q¡/ÐÜ.Ð5EÈ=ÐptÔuˆàÐ"Øà×%Ñ%¤l×&PÑ&P×&VÑ&VÔWØØr    c                 óÂ  — |j                  d«      }t        |«      dk  r|ddfS |d   }t        |dd¬«      }|€|ddfS |j                  t        j
                  j                  «      rt|j                  d«      }t        |«      dk\  rP|d	   }|j                  d
«      d   }|d   }|j                  d«      d   }	|d   }
|
j                  d«      d   }||	|fS |ddfS |ddfS )z”
        Returns:
         - original_response_id: the original response id
         - user_id: the user id
         - team_id: the team id
        rK   rL   NrM   r3   TrN   ú;r   zresponse_id:éÿÿÿÿzuser_id:zteam_id:rQ   )r&   r3   rT   rU   rV   ÚpartsÚresponse_id_partr9   Úuser_id_partr:   Úteam_id_partr;   s               r   r6   z(ResponsesIDSecurity._decrypt_response_idŽ   s  € ð *×/Ñ/°Ó8ˆÜˆ|Ó˜qÒ Ø  dÐ*Ð*à".¨q¡/ÐÜ.Ð5EÈ=ÐptÔuˆàÐ"Ø  dÐ*Ð*à×%Ñ%¤l×&PÑ&P×&VÑ&VÔWà*×0Ñ0°Ó5ˆEä�5‹z˜QŠà*/°©(Ð Ø.>×.DÑ.DÀ^Ó.TÐUWÑ.XÐ$ð ',¨A¡h�Ø!-×!3Ñ!3°JÓ!?ÀÑ!C�ð ',¨A¡h�Ø!-×!3Ñ!3°JÓ!?ÀÑ!C�à+¨W°gÐ=Ð=ð # D¨$Ð.Ð.Ø˜D $Ð&Ð&r    c                 óF   — ddl }ddlm} |j                  dd«      }|€|}|S )z.Get the signing key for encryption/decryption.r   N)Ú
master_keyÚLITELLM_SALT_KEY)ÚosrE   r_   Úgetenv)r&   ra   r_   Úsalt_keys       r   Ú_get_signing_keyz$ResponsesIDSecurity._get_signing_key¶   s)   € ãå9à—9‘9Ð/°Ó6ˆØÐØ!ˆHØˆr    ÚresponseÚrequest_cachec                 ór  — | j                  «       }|€t        j                  d«       |S t        |dd «      }t        |dd «      }|r§t	        |t
        «      r—|j                  d«      r†|�||v rt        |d||   «       |S t        j                  j                  j                  ||j                  xs d|j                  xs d«      }t        |¬«      }d|› �}	|�|	||<   t        |d|	«       |S |rÈt	        |t        «      r¸|�)|j                   |v rt        |d||j                      «       n€t        j                  j                  j                  |j                   |j                  xs d|j                  xs d«      }t        |¬«      }d|› �}	|�|	||j                   <   t        |d|	«       t        |d|«       |S )NzôResponse ID encryption is enabled but no signing key is configured. Please set LITELLM_SALT_KEY environment variable or configure a master_key. Skipping response ID encryption. See: https://docs.litellm.ai/docs/proxy/prod#5-set-litellm-salt-keyÚidre   rK   Ú )rH   )rd   r	   rI   ÚgetattrÚ
isinstanceÚstrr   Úsetattrr   Ú5LITELLM_MANAGED_RESPONSE_API_RESPONSE_ID_COMPLETE_STRrH   Úformatr:   r;   r   r   rh   )
r&   re   r(   rf   Úsigning_keyr3   Úresponse_objÚencrypted_response_idÚencoded_user_id_and_response_idÚencrypted_ids
             r   Ú_encrypt_response_idz(ResponsesIDSecurity._encrypt_response_idÁ   sÏ  € ð "×2Ñ2Ó4ˆØÐÜ ×&Ñ&ðVôð ˆOä$ X¨t°TÓ:ˆÜ% h°
¸DÓAˆáœ: k´3Ô7¸K×<RÑ<RÐSZÔ<[àÐ(¨[¸MÑ-IÜ˜ $¨°kÑ(BÔCð< ˆô9 )5×(jÑ(j×(pÑ(p×(wÑ(wØØ%×-Ñ-Ò3°Ø%×-Ñ-Ò3°ó)Ð%ô 3GÐMbÔ2cÐ/Ø!&Ð'FÐ&GÐH�Ø Ð,Ø1=�M +Ñ.Ü˜ $¨Ô5ð$ ˆñ! œj¨Ô7KÔLàÐ(¨\¯_©_ÀÑ-MÜ˜ d¨M¸,¿/¹/Ñ,JÕKä(4×(jÑ(j×(pÑ(p×(wÑ(wØ —O‘OØ%×-Ñ-Ò3°Ø%×-Ñ-Ò3°ó)Ð%ô
 3GÐMbÔ2cÐ/Ø!&Ð'FÐ&GÐH�Ø Ð,Ø5A�M ,§/¡/Ñ2Ü˜ d¨LÔ9Ü�H˜j¨,Ô7Øˆr    c              ƒ   ó¦   K  — ddl m} |j                  dd«      r|S t        |t        «      r"t        t        | j                  ||d¬«      «      }|S ­w)a  
        Queue response IDs for batch processing instead of writing directly to DB.

        This method adds response IDs to an in-memory queue, which are then
        batch-processed by the DBSpendUpdateWriter during regular database update cycles.
        r   r@   rB   FN)rf   )rE   rA   r4   rk   r   r   ru   )r&   r*   r(   re   rA   s        r   Úasync_post_call_success_hookz0ResponsesIDSecurity.async_post_call_success_hookû   sX   è ø€ õ 	@à×ÑÐ ?ÀÔGØˆOÜ�hÔ 4Ô5ÜÜ$Ø×)Ñ)¨(Ð4EÐUYÐ)ÓZóˆHð ˆùs   ‚AAÚrequest_datac                óØ   K  — ddl m} i }|2 3 d {  –—† }t        |t        «      r:t	        |j
                  «      r%|j                  dd«      s| j                  |||«      }|­–— ŒY7 ŒT6 y ­w)Nr   r@   rB   F)rE   rA   rk   r   r   r   r4   ru   )r&   r(   re   rx   rA   Úrequest_encryption_cacheÚchunks          r   Ú'async_post_call_streaming_iterator_hookz;ResponsesIDSecurity.async_post_call_streaming_iterator_hook  sq   è ø€ õ 	@ð ;=Ð à#÷ 	ð 	�%ä˜5Ô"AÔBÜ2Ð3D×3RÑ3RÔSØ(×,Ñ,Ð-LÈeÔTà×1Ñ1°%Ð9JÐLdÓe�ØŒKð	ø™8ùs&   ‚A*�A(‘A&’A(•AA*Á&A(Á(A*r$   )Ú__name__Ú
__module__Ú__qualname__r'   Údictr   Ú	Exceptionrl   r<   Úboolr7   r5   Útupler6   rd   r   ru   r   r   rw   r   r|   r%   r    r   r"   r"   .   sd  „ òð à+ð ð ð ð ð	 ð
 $ð ð 
�S‰˜4Ñ	 $Ñ	&ó ðD)à  4™Zð)ð ! 4™Zð)ð ,ð	)ð
 
ó)ðV°Sð ¸Tó ð&'°ð &'¸¸cÀ3ÈÁ:ÈsÐUYÉzÐ>YÑ8Zó &'ðP	 #¨¡*ó 	ð 04ñ	8à1ð8ð ,ð8ð ˜C ˜H‘~¨Ñ,ð	8ð
 
)ó8ðtàðð ,ðð #ð	ð
 
óð.Ø!1ðØ=@ðØPTðà	Ð7¸Ð=Ñ	>ôr    r"   )%Ú__doc__Úcollections.abcr   Útypingr   r   r   r   Úfastapir   Úlitellm._loggingr	   Ú"litellm.integrations.custom_loggerr
   Úlitellm.proxy._typesr   Ú0litellm.proxy.common_utils.encrypt_decrypt_utilsr   r   Úlitellm.types.llms.openair   r   Úlitellm.types.utilsr   r   r   Úlitellm.caching.cachingr   r   r   Ú__annotations__Ú	frozensetr   rl   r‚   r   r"   r%   r    r   ú<module>r‘      s„   ðòõ +ß 2Ó 2å !å 1Ý ;Ý 1÷÷÷ QÑ PáÝ1Ý3ð )2Ð  Ó 1Ù&/°À,Ð0OÓ&PÐ ˜eÓ Pð5°#¸±*ð 5Àó 5ôs˜,õ sr    