Ë
   Ð0ŠX±‡†ã                  ó   — d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlmZmZmZmZmZ dddœZdZd(d	„Zd
ej(                  fddddœ	 	 	 	 	 	 	 	 	 	 	 d)d„Ze
j,                  d(d„«       Ze
j,                  d*d„«       Zd+d„Zd,d„Zd,d„Zd,d„Zd-d„Zd-d„Zd,d„Zd,d„Z e
jB                  jE                  dg d¢«      	 	 	 	 	 	 d.d„«       Z#d-d„Z$d,d„Z%d,d„Z&d-d„Z'd,d„Z(d-d „Z)d-d!„Z*d,d"„Z+d,d#„Z,d,d$„Z-	 	 d,d%„Z.d-d&„Z/d,d'„Z0y)/aº  Tests for the HTTP API gateway (cyberbrain26.control_plane.api).

These tests lock down the security-critical behaviour of ``APIGateway`` and the
bundled ``SimpleAPIKeyAuth``:

* D1 - fail-closed authentication (no bypass when no provider is configured)
* D2 - raw bearer tokens never reach handler claims or any response body
* D4 - handler exception text is never echoed to the client
* D3 - rate limiting is keyed on the authenticated principal, not a per-request UUID
* D6 - rate limiting is never silently skipped when no principal and no
      ``client_addr`` are available (regression: fail-open throttling hole)
* D5 - route matching has no prefix-collision foot-gun; OpenAPI leaks nothing
é    )ÚannotationsN)ÚUNIDENTIFIED_RATE_LIMIT_KEYÚ
APIGatewayÚ
APIRequestÚ
HTTPMethodÚSimpleAPIKeyAuthúprincipal-1zprincipal-2)úsecret-token-1zsecret-token-2zSUPER_SECRET_DB_PASSWORD=p@sc                 ó    — t        t        «      S ©N)r   Ú
VALID_KEYS© ó    ú8/home/oem/CyberBrain26-unified/tests/test_api_gateway.pyÚ_authr       s   € ÜœJÓ'Ð'r   ú/úreq-1)ÚauthorizationÚclient_addrÚ
request_idr   c          
     ó8   — |�d|ini }t        || |i d i ||¬«      S )Nr   )ÚmethodÚpathÚheadersÚquery_paramsÚbodyÚpath_paramsr   r   )r   )r   r   r   r   r   r   s         r   Ú_reqr   $   s=   € ð CPÐB[˜°Ñ>Ðac€GÜØØØØØØØØô	ð 	r   c                 ó   — t        «       S r   )r   r   r   r   Úauthr    9   s	   € ä‹7€Nr   c                ó   — t        | ¬«      S )N)Úauth_provider)r   )r    s    r   Úgatewayr#   >   s   € ä DÔ)Ð)r   c              ƒ  ó   K  — ddiS ­w©NÚokTr   ©ÚrequestÚuser_idÚclaimsr   s       r   Ú_okr+   C   s   è ø€ Ø�$ˆ<Ðùó   ‚c               ƒ  óF  K  — t        «       } | j                  dt        j                  t        d¬«       | j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      d	œz  }d
d|iz  }t        t        j                  |«      «      ‚dx}x}}y7 ŒÍ­w)zŒRegression test for D1: a requires_auth route with NO auth provider must
    be denied rather than silently allowing unauthenticated access.ú/secureT©Úrequires_authNé‘  ©ú==©z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sÚresp©Úpy0Úpy2Úpy5úassert %(py7)sÚpy7©r   Ú	add_router   ÚGETr+   Úhandler   Ústatus_codeÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanation©Úgwr5   Ú@py_assert1Ú@py_assert4Ú@py_assert3Ú@py_format6Ú@py_format8s          r   Ú-test_requires_auth_with_no_provider_is_deniedrP   L   s³   è ø€ ô 
‹€BØ‡L�L�œJŸN™N¬C¸t€LÔDØ—‘œ4 	›?Ó+×+€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ô"ð ,úó   ‚AD!ÁDÁCD!c               ƒ  óF  K  — t        «       } | j                  dt        j                  t        d¬«       | j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      d	œz  }d
d|iz  }t        t        j                  |«      «      ‚dx}x}}y7 ŒÍ­w)zBAnonymous routes require an explicit allow_unauthenticated opt-in.ú/publicFr/   Nr1   r2   r4   r5   r6   r:   r;   r<   rI   s          r   Ú*test_anonymous_route_denied_without_opt_inrT   U   s±   è ø€ ä	‹€BØ‡L�L�œJŸN™N¬C¸u€LÔEØ—‘œ4 	›?Ó+×+€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ô"ð ,úrQ   c               ƒ  óà  K  — t        d¬«      } | j                  dt        j                  t        d¬«       | j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd	||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}}|j                   }ddi}||k(  }|s­t        j                  d|fd||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}}y7 �Œ˜­w)z9A route explicitly opted into anonymous access is served.T©Úallow_unauthenticatedrS   Fr/   NéÈ   r2   r4   r5   r6   r:   r;   r&   ©z,%(py2)s
{%(py2)s = %(py0)s.body
} == %(py5)s)r   r=   r   r>   r+   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   rI   s          r   Ú(test_anonymous_route_works_when_opted_inrZ   ]   s%  è ø€ ä	¨$Ô	/€BØ‡L�L�œJŸN™N¬C¸u€LÔEØ—‘œ4 	›?Ó+×+€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�9‰9Ð$˜˜t˜Ð$ˆ9˜Ñ$×$×$Õ$ˆ9˜×$×$×$×$×$Ñ$ˆ4×$×$Ó$ˆ4×$×$Ô$ˆ9×$×$Ò$˜×$×$×$×$×$×$Ô$ð ,ûs   ‚AG.ÁG+ÁFG.c              ƒ  óÊ  K  — d„ }| j                  dt        j                  |d¬«       | j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s­t        j                  d|fd	||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}|j                  }ddi}||k(  }|s­t        j                  d|fd||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}y 7 �Œ˜­w)Nc              “  ó   K  — d|iS ­w)Nr)   r   r'   s       r   ÚhandlerzDtest_authenticated_route_with_provider_runs_handler.<locals>.handlerg   s   è ø€ Ø˜7Ð#Ð#ùr,   r.   Tr/   úBearer secret-token-1©r   rX   r2   r4   r5   r6   r:   r;   r)   r	   rY   )r=   r   r>   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   )r#   r]   r5   rK   rL   rM   rN   rO   s           r   Ú3test_authenticated_route_with_provider_runs_handlerr`   f   s.  è ø€ ò$ð ×Ñ�i¤§¡°ÈÐÔMØ—‘¤ YÐ>UÔ VÓW×W€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�9‰9Ð2˜ MÐ2Ð2ˆ9Ð2Ñ2×2×2Õ2ˆ9Ð2×2×2×2×2×2Ñ2ˆ4×2×2Ó2ˆ4×2×2Ô2ˆ9×2×2Ò2Ð2×2×2×2×2×2×2Ô2ð Xûs   ‚AG#ÁG Á	FG#c              ƒ  óN  ‡K  — i Šˆfd„}| j                  dt        j                  |d¬«       d}| j                  t	        dd|› �¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s­t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}‰d   }	d}|	|k(  }
|
slt        j                  d	|
fd|	|f«      t        j                  |	«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}
}‰d   }
||
v}|s™t        j                  d|fd||
f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |
«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}}
d}	‰d   }|	|v}
|
slt        j                  d|
fd|	|f«      t        j                  |	«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}
}|j                  }t        |«      }||v}|�s7t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      d œz  }d!d"|iz  }t        t        j                  |«      «      ‚d x}x}}y 7 �ŒÐ­w)#Nc              “  óN   •K  — |‰d<   t        |«      ‰d<   |t        |«      dœS ­w)Nr)   r*   )r)   r*   )Údict)r(   r)   r*   r   Úcaptureds       €r   r]   z7test_valid_bearer_runs_handler_no_leak.<locals>.handlerx   s.   øè ø€ Ø%ˆ�ÑÜ! &›\ˆ�ÑØ"¬d°6«lÑ;Ð;ùs   ƒ"%r.   Tr/   r
   úBearer r_   rX   r2   r4   r5   r6   r:   r;   r)   r	   ©z%(py1)s == %(py4)s©Úpy1Úpy4úassert %(py6)sÚpy6r*   ©únot in)z%(py0)s not in %(py3)sÚtoken©r7   Úpy3úassert %(py5)sr9   Úapi_key)z%(py1)s not in %(py4)s©zN%(py0)s not in %(py7)s
{%(py7)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.body
})
}Ústr©r7   r8   rp   r9   r;   úassert %(py9)sÚpy9)r=   r   r>   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   rt   )r#   r]   rn   r5   rK   rL   rM   rN   rO   Ú@py_assert0Ú@py_assert2Ú@py_format5Ú@py_format7Ú@py_format4Ú@py_assert6Ú@py_format10rd   s                   @r   Ú&test_valid_bearer_runs_handler_no_leakr   u   s~  øè ø€ Ø€Hô<ð
 ×Ñ�i¤§¡°ÈÐÔMØ€EØ—‘¤ YÀÈÀwÐ>OÔ PÓQ×Q€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�IÑÐ/ -Ð/Ð -Ñ/×/×/Õ/Ð -×/×/Ó/Ð×/×/Ò/ -×/×/×/×/×/×/Ó/à  Ñ*Ð*ˆ5Ð*Ð*×*×*Õ*ˆ5Ð*×*×*×*×*×*Ñ*ˆ5×*×*Ó*ˆ5×*×*Ô*Ð*×*×*×*×*×*×*Ñ*ØÐ.˜H XÑ.Ð.ˆ9Ð.Ð.×.×.Õ.ˆ9Ð.×.×.Ó.ˆ9×.×.Ò.Ð.×.×.×.×.×.×.Ó.à ŸI™IÐ&œ˜I›Ð&ˆ5˜Ð&×&×&Ö&ˆ5˜×&×&×&×&×&Ñ&ˆ5×&×&Ó&ˆ5×&×&×&×&×&Ò&œ×&×&Ó&œ×&×&×&×&×&Ò&˜D×&×&Ó&˜D×&×&Ô&˜I×&×&Ò&˜×&×&×&×&×&×&Ô&ð Rûs   ƒAP%ÁP"ÁOP%c            
     ó*  — t        «       } | j                  D �]#  }t        |t        «      }|�sddt	        j
                  «       v st        j                  t        «      rt        j                  t        «      nddt	        j
                  «       v st        j                  |«      rt        j                  |«      nddt	        j
                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      dœz  }t        t        j                  |«      «      ‚d}�Œ& t        D �]L  }|j                  }d} ||«      }| j                  }||v}|�st        j                  d|fd	||f«      d
t	        j
                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      t        j                  |«      dt	        j
                  «       v st        j                  | «      rt        j                  | «      ndt        j                  |«      dœz  }	dd|	iz  }
t        t        j                  |
«      «      ‚dx}x}x}x}}�ŒO y)z,No plaintext key survives construction (D2).z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}Ú
isinstanceÚdigestÚbytes)r7   rh   r8   ri   Nzutf-8rl   )zm%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.encode
}(%(py4)s)
} not in %(py10)s
{%(py10)s = %(py8)s._keys
}Ú	plaintextÚprovider©r7   r8   ri   rk   Úpy8Úpy10úassert %(py12)sÚpy12)r   Ú_keysr�   rƒ   rC   rD   rA   rE   rF   rG   rH   r   ÚencoderB   )r…   r‚   rM   rz   r„   rK   Ú@py_assert5Ú@py_assert9Ú@py_assert7Ú@py_format11Ú@py_format13s              r   Ú,test_simple_api_key_auth_hashes_keys_at_restr’   ‰   sr  € ä‹w€HØ—.‘.ó )ˆÜ˜&¤%Ó(Ð(Ò(×(×(×(×(Õ(Œz×(×(Ó(Œz×(×(×(×(×(Ò(˜&×(×(Ó(˜&×(×(×(×(×(Ò(¤%×(×(Ó(¤%×(×(Ô(Ð(×(×(×(×(×(Ò(ð)äó ?ˆ	Ø×ÑÐ> Ð>Ñ Ó(Ð>°·±Ð>Ð(°Ð>×>×>Ö>Ð(°×>×>×>×>×>Ñ>ˆy×>×>Ó>ˆy×>×>Ô>Ð×>×>Ò> ×>×>Ò>Ð(×>×>×>×>×>Ð>°×>×>Ó>°×>×>Ô>°×>×>×>×>×>×>×>Ñ>ñ?r   c               ƒ  ór  K  — t        «       } | j                  t        dd¬«      «      ƒ d {  –—† \  }}d}||k(  }|s™t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }d	d
|iz  }t        t        j                  |«      «      ‚d x}}d}||v}|s™t        j                  d|fd||f«      t        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      nddœz  }d	d
|iz  }t        t        j                  |«      «      ‚d x}}d}||v}|s™t        j                  d|fd||f«      t        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      nddœz  }d	d
|iz  }t        t        j                  |«      «      ‚d x}}d}t        |«      }||v}|söt        j                  d|fd||f«      t        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }	dd|	iz  }
t        t        j                  |
«      «      ‚d x}x}}y 7 �Œ­w)Nz/xr^   r_   r	   r2   )z%(py0)s == %(py3)sr)   ro   rq   r9   rr   rl   )z%(py1)s not in %(py3)sr*   )rh   rp   r
   )z4%(py1)s not in %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}rt   )rh   rp   ri   rk   úassert %(py8)sr‡   )r   Úauthenticater   rA   rB   rC   rD   rE   rF   rG   rH   rt   )r…   r)   r*   ry   rK   r|   rN   rx   r�   r{   Ú@py_format9s              r   Ú*test_simple_api_key_claims_exclude_raw_keyr—   ’   sÕ  è ø€ Ü‹w€HØ$×1Ñ1ÜˆTÐ!8Ô9ó÷ �O€GˆVð $Ð#ˆ7�mÑ#×#×#Õ#ˆ7�m×#×#×#×#×#Ñ#ˆ7×#×#Ó#ˆ7×#×#Ô#�m×#×#×#×#×#×#Ñ#ØÐ"ˆ9˜FÐ"×"×"Õ"ˆ9˜F×"×"Ó"ˆ9×"×"×"×"×"Ð"˜F×"×"Ó"˜F×"×"×"×"×"×"Ó"ØÐ)Ð 6Ð)×)×)Õ)Ð 6×)×)Ó)Ð×)×)×)×)×)Ð) 6×)×)Ó) 6×)×)×)×)×)×)Ó)ØÐ.¤3 v£;Ð.Ð ;Ð.×.×.Õ.Ð ;×.×.Ó.Ð×.×.×.×.×.Ð.¤3×.×.Ó.¤3×.×.×.×.×.Ò. v×.×.Ó. v×.×.Ô. ;×.×.×.×.×.×.Ô.ðûs   ‚*L7¬L4­LL7)Nre   zBearer nopezBasic secret-token-1zBearer 	secret-token-1zBearer  secret-token-1c              ƒ  ó6  K  — | j                  dt        j                  t        d¬«       | j	                  t        d|¬«      «      ƒ d {  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      d	œz  }d
d|iz  }t        t        j                  |«      «      ‚d x}x}}y 7 ŒÍ­w)Nr.   Tr/   r_   r1   r2   r4   r5   r6   r:   r;   ©r=   r   r>   r+   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   )r#   r   r5   rK   rL   rM   rN   rO   s           r   Ú(test_invalid_or_missing_auth_returns_401rš   �   s³   è ø€ ð ×Ñ�i¤§¡´ÀDÐÔIØ—‘¤ Y¸mÔ LÓM×M€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ô"ð Núó   ‚ADÁ	DÁ
CDc              ƒ  ó6  K  — | j                  dt        j                  t        d¬«       | j	                  t        dd¬«      «      ƒ d {  –—† }|j                  }d}||k(  }|s­t        j                  d|fd	||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}y 7 ŒÍ­w)Nz/knownTr/   z/unknownr^   r_   é”  r2   r4   r5   r6   r:   r;   r™   )r#   r5   rK   rL   rM   rN   rO   s          r   Útest_unknown_route_returns_404rž   µ   s²   è ø€ Ø×Ñ�h¤
§¡´À4ÐÔHØ—‘¤ ZÐ?VÔ WÓX×X€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ô"ð Yúr›   c               ƒ  óx  K  — t        d¬«      } | j                  dt        j                  t        d¬«       | j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}| j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}y7 �Œb7 Œ¥­w)zBD5: /admin must NOT match /administrator (segment equality guard).TrV   z/adminFr/   z/administratorNr�   r2   ©z3%(py3)s
{%(py3)s = %(py1)s.status_code
} == %(py6)s©rh   rp   rk   r”   r‡   rX   )r   r=   r   r>   r+   r?   r   r@   rA   rB   rF   rG   rH   )rJ   rx   ry   r�   rL   r{   r–   s          r   Ú*test_no_prefix_collision_in_route_matchingr¢   »   s  è ø€ ä	¨$Ô	/€BØ‡L�L�œ:Ÿ>™>¬3¸e€LÔDØ—)‘)œDÐ!1Ó2Ó3×3ÐGÐ3×@Ñ@ÐGÀCÐGÐ@ÀCÑG×G×GÕGÐ@ÀC×G×GÓGÐ3×G×GÒGÐ@×G×GÒGÀC×G×G×G×G×G×GÕGØ—)‘)œD ›NÓ+×+Ð?Ð+×8Ñ8Ð?¸CÐ?Ð8¸CÑ?×?×?Õ?Ð8¸C×?×?Ó?Ð+×?×?Ò?Ð8×?×?Ò?¸C×?×?×?×?×?×?Ö?ð 4ùØ+ús&   ‚AF:ÁF5ÁB>F:ÄF8ÄB#F:Æ8F:c               ƒ  óÞ  K  — d„ } t        d¬«      }|j                  dt        j                  | d¬«       |j	                  t        d«      «      ƒ d {  –—† }|j                  }d}||k(  }|s­t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}|j                  }ddi}||k(  }|s­t        j                  d	|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}y 7 �Œ˜­w)Nc              “  ó   K  — d|d   iS ­w)NÚidr   r'   s       r   r]   z+test_path_params_extracted.<locals>.handlerÄ   s   è ø€ Ø�k $Ñ'Ð(Ð(ùs   ‚
TrV   z/items/{id}Fr/   z	/items/42rX   r2   r4   r5   r6   r:   r;   r¥   Ú42rY   )r   r=   r   r>   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   )r]   rJ   r5   rK   rL   rM   rN   rO   s           r   Útest_path_params_extractedr§   Ã   s-  è ø€ ò)ô 
¨$Ô	/€BØ‡L�L�¤
§¡°Àu€LÔMØ—‘œ4 Ó,Ó-×-€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�9‰9Ð$˜˜t˜Ð$ˆ9˜Ñ$×$×$Õ$ˆ9˜×$×$×$×$×$Ñ$ˆ4×$×$Ó$ˆ4×$×$Ô$ˆ9×$×$Ò$˜×$×$×$×$×$×$Ô$ð .ûs   ‚AG-ÁG*ÁFG-c                óN  — d„ }| j                  dt        j                  |d¬«       | j                  «       }|d   }d}||k(  }|slt	        j
                  d|fd||f«      t	        j                  |«      t	        j                  |«      d	œz  }d
d|iz  }t        t	        j                  |«      «      ‚d x}x}}d}|d   }||v }|slt	        j
                  d|fd||f«      t	        j                  |«      t	        j                  |«      d	œz  }d
d|iz  }t        t	        j                  |«      «      ‚d x}x}}t        |«      }t        D ]Ð  }	|	|v}
|
sÆt	        j
                  d|
fd|	|f«      dt        j                  «       v st	        j                  |	«      rt	        j                  |	«      nddt        j                  «       v st	        j                  |«      rt	        j                  |«      nddœz  }dd|iz  }t        t	        j                  |«      «      ‚d }
ŒÒ |d   d   d   d   }dg ig}||k(  }|slt	        j
                  d|fd||f«      t	        j                  |«      t	        j                  |«      d	œz  }d
d|iz  }t        t	        j                  |«      «      ‚d x}x}}y )Nc              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   z;test_openapi_generation_exposes_no_secrets.<locals>.handlerÏ   ó   è ø€ Ø�dˆ|Ðùr,   r.   Tr/   Úopenapiz3.0.0r2   rf   rg   rj   rk   Úpaths©Úin)z%(py1)s in %(py4)srl   )z%(py0)s not in %(py2)srn   Ú
serialized©r7   r8   úassert %(py4)sri   ÚgetÚsecurityÚ
bearerAuth)r=   r   r>   Úgenerate_openapirA   rB   rF   rG   rH   rt   r   rC   rD   rE   )r#   r]   Úschemarx   rM   ry   rz   r{   r¯   rn   rK   Ú@py_format3s               r   Ú*test_openapi_generation_exposes_no_secretsr¸   Î   s½  € òð ×Ñ�i¤§¡°ÈÐÔMØ×%Ñ%Ó'€FØ�)ÑÐ' Ð'Ð Ñ'×'×'Õ'Ð ×'×'Ó'Ð×'×'Ò' ×'×'×'×'×'×'Ó'ØÐ'˜˜w™Ð'ˆ9˜Ð'×'×'Õ'ˆ9˜×'×'Ó'ˆ9×'×'Ò'˜×'×'×'×'×'×'Ó'Ü�V“€JÜò 'ˆØ˜JÐ&×&×&Õ&ˆu˜J×&×&×&×&×&Ñ&ˆu×&×&Ó&ˆu×&×&×&×&×&Ò&˜J×&×&Ó&˜J×&×&×&×&×&×&Ò&ð'à�'‰?˜9Ñ% eÑ,¨ZÑ8ÐP¸lÈBÐ=OÐ<PÐPÐ8Ð<PÑP×P×PÕPÐ8Ð<P×P×PÓPÐ8×P×PÒPÐ<P×P×P×P×P×P×PÔPr   c                 óœ  — t        d¬«      } | j                  dt        j                  t        d¬«       | j                  «       }|d   d   d   d   }g }||k(  }|slt        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}y )NTrV   rS   Fr/   r¬   r²   r³   r2   rf   rg   rj   rk   )r   r=   r   r>   r+   rµ   rA   rB   rF   rG   rH   )rJ   r¶   rx   rM   ry   rz   r{   s          r   Ú,test_openapi_anonymous_route_has_no_securityrº   Ü   s’   € Ü	¨$Ô	/€BØ‡L�L�œJŸN™N¬C¸u€LÔEØ× Ñ Ó"€FØ�'‰?˜9Ñ% eÑ,¨ZÑ8Ð>¸BÐ>Ð8¸BÑ>×>×>Õ>Ð8¸B×>×>Ó>Ð8×>×>Ò>¸B×>×>×>×>×>×>Ô>r   c           	   ƒ  óˆ  K  — d„ }| j                  dt        j                  |dd¬«       | j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }	d}|	|k(  }
|
s­t        j                  d	|
fd|	|f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |	«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}
}|j                  }	|	j                  }
d} |
|«      }d}||k(  }|sét        j                  d	|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |	«      t        j                  |
«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}
x}x}x}}y 7 �Œp7 �Œ²7 �Œô­w)Nc              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   z=test_rate_limit_same_principal_within_window.<locals>.handleré   rª   r,   ú/limitedTé   ©r0   Ú
rate_limitr^   r_   rX   r2   r    r¡   r”   r‡   é­  r4   r5   r6   r:   r;   úRetry-AfterÚ60©zg%(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.headers
}.get
}(%(py6)s)
} == %(py11)s©r7   r8   ri   rk   r‡   Úpy11úassert %(py13)sÚpy13)r=   r   r>   r?   r   r@   rA   rB   rF   rG   rH   rC   rD   rE   r   r²   )r#   r]   rx   ry   r�   rL   r{   r–   r5   rK   rM   rN   rO   r�   Ú@py_assert10rŽ   Ú@py_format12Ú@py_format14s                     r   Ú,test_rate_limit_same_principal_within_windowrÌ   è   sí  è ø€ òð ×Ñ�j¤*§.¡.°'ÈÐZ[ÐÔ\à�n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð —‘¤ ZÐ?VÔ WÓX×X€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�<‰<Ð2ˆ<×ÑÐ2˜MÐ2Ñ˜MÓ*Ð2¨dÐ2Ð*¨dÑ2×2×2Õ2Ð*¨d×2×2×2×2×2Ñ2ˆ4×2×2Ó2ˆ4×2×2Ô2ˆ<×2×2Ò2Ð×2×2Ò2˜M×2×2Ò2Ð*×2×2Ò2¨d×2×2×2×2×2×2×2Ò2ð 	Vùð 	VùàXûs9   ‚AOÁ	N9Á
C OÄ
N<ÄC OÇN?ÇG.OÎ<OÎ?Oc              ƒ  ó   K  — d„ }| j                  dt        j                  |dd¬«       | j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}| j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s€t        j                  d	|fd
||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}y 7 �Œ§7 �Œé7 �Œ+7 �Œm7 Œ®­w)Nc              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   zEtest_rate_limit_different_principals_are_independent.<locals>.handlerù   rª   r,   r½   Tr¾   r¿   r^   r_   rX   r2   r    r¡   r”   r‡   rÁ   zBearer secret-token-2)r=   r   r>   r?   r   r@   rA   rB   rF   rG   rH   )r#   r]   rx   ry   r�   rL   r{   r–   s           r   Ú4test_rate_limit_different_principals_are_independentrÏ   ø   sô  è ø€ òð ×Ñ�j¤*§.¡.°'ÈÐZ[ÐÔ\ð �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð
 �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ð �n‰nœT *Ð<SÔTÓU×UðØUß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	V÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ò ð 	Vùð 	Vùð 	Vùð 	Vùð 	Vús_   ‚AO>Á	O0Á
C O>Ä
O3ÄC O>ÇO6ÇC O>ÊO9ÊC O>ÍO<ÍB#O>Ï3O>Ï6O>Ï9O>Ï<O>c              ƒ  ó¼  ‡K  — dgŠ| j                  t        dˆfd„«       t        dd¬«      }d„ }|j                  dt        j
                  |d	d¬
«       t        d«      D ]î  }|j                  t        dd¬«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t!        t        j"                  |	«      «      ‚dx}x}}Œð |j                  t        dd¬«      «      ƒ d{  –—† }
|
j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |
«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚dx}
x}x}}|j                  t        dd¬«      «      ƒ d{  –—† }
|
j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |
«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚dx}
x}x}}y7 �ŒR7 �Œg7 Œ¨­w)zEAnonymous requests are keyed on the explicit client_addr, not a UUID.ç     @�@Útimec                 ó   •— ‰ d   S ©Nr   r   ©Úfake_nows   €r   ú<lambda>z6test_rate_limit_keyed_on_client_addr.<locals>.<lambda>  ó   ø€ ¨h°q©k€ r   Tr¾   )rW   Údefault_rate_limitc              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   z5test_rate_limit_keyed_on_client_addr.<locals>.handler  rª   r,   r½   Fr¿   ú1.1.1.1)r   NrX   r2   r4   r5   r6   r:   r;   rÁ   r    r¡   r”   r‡   z2.2.2.2)ÚsetattrrÒ   r   r=   r   r>   Úranger?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   )ÚmonkeypatchrJ   r]   Ú_r5   rK   rL   rM   rN   rO   rx   ry   r�   r{   r–   rÖ   s                  @r   Ú$test_rate_limit_keyed_on_client_addrrà     sô  øè ø€ àˆx€HØ×Ñœ˜fÓ&9Ô:Ü	¨$À1Ô	E€Bòð ‡L�L�œZŸ^™^¨WÀEÐVW€LÔXÜ�1‹Xò 'ˆØ—Y‘Yœt J¸IÔFÓG×GˆØ×ÑÐ& 3Ð&Ð 3Ñ&×&×&Õ&Ð 3×&×&×&×&×&Ñ&ˆt×&×&Ó&ˆt×&×&Ô&Ð×&×&Ò& 3×&×&×&×&×&×&Ô&ð'ð —)‘)œD ¸ÔCÓD×DÐXÐD×QÑQÐXÐUXÐXÐQÐUXÑX×X×XÕXÐQÐUX×X×XÓXÐD×X×XÒXÐQ×X×XÒXÐUX×X×X×X×X×X×XÕXà—)‘)œD ¸ÔCÓD×DÐXÐD×QÑQÐXÐUXÐXÐQÐUXÑX×X×XÕXÐQÐUX×X×XÓXÐD×X×XÒXÐQ×X×XÒXÐUX×X×X×X×X×X×XÖXð	 HùàDùàDús9   ƒA?KÂKÂC-KÅ0KÅ1C KÈ1KÈ2B#KËKËKc           	   ƒ  ó(	  ‡K  — dgŠ| j                  t        dˆfd„«       t        d¬«      }d„ }|j                  dt        j
                  |dd	¬
«       t        d	«      D ]ì  }|j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t!        t        j"                  |	«      «      ‚dx}x}}Œî |j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t!        t        j"                  |	«      «      ‚dx}x}}|j$                  }|j&                  }d}
 ||
«      }d}||k(  }|sét        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |
«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚dx}x}x}
x}x}}|j(                  }t+        |«      }d}||k(  }|�s
t        j                  d|fd||f«      dt        j                  «       v st        j                  t*        «      rt        j                  t*        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd |iz  }t!        t        j"                  |«      «      ‚dx}x}x}}y7 �Œ7 �Œ$­w)!a–  D6: no principal AND no ``client_addr`` must still be throttled.

    Regression test for the fail-open hole: the key derivation used to be
    ``user_id or request.client_addr`` guarded by ``and rate_key``, so an
    unauthenticated request with ``client_addr=None`` skipped the limiter
    entirely - five requests, five 200s, zero buckets created. Throttling must
    fire instead of being skipped.
    rÑ   rÒ   c                 ó   •— ‰ d   S rÔ   r   rÕ   s   €r   r×   zFtest_rate_limit_fires_without_client_addr_or_user_id.<locals>.<lambda>1  rØ   r   TrV   c              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   zEtest_rate_limit_fires_without_client_addr_or_user_id.<locals>.handler4  rª   r,   r½   Fr¾   r¿   NrX   r2   r4   r5   r6   r:   r;   rÁ   rÂ   rÃ   rÄ   rÅ   rÇ   rÈ   é   )zY%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s._rate_limit_buckets
})
} == %(py8)sÚlenrJ   )r7   rh   rp   r9   r‡   zassert %(py10)srˆ   )rÜ   rÒ   r   r=   r   r>   rÝ   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   r²   Ú_rate_limit_bucketsrå   )rÞ   rJ   r]   rß   r5   rK   rL   rM   rN   rO   r�   r�   rÉ   rŽ   rÊ   rË   ry   r}   r–   r�   rÖ   s                       @r   Ú4test_rate_limit_fires_without_client_addr_or_user_idrç   '  s×  øè ø€ ð ˆx€HØ×Ñœ˜fÓ&9Ô:Ü	¨$Ô	/€Bòð ‡L�L�œZŸ^™^¨WÀEÐVW€LÔXÜ�1‹Xò 'ˆð —Y‘Yœt JÓ/Ó0×0ˆØ×ÑÐ& 3Ð&Ð 3Ñ&×&×&Õ&Ð 3×&×&×&×&×&Ñ&ˆt×&×&Ó&ˆt×&×&Ô&Ð×&×&Ò& 3×&×&×&×&×&×&Ô&ð	'ð
 —‘œ4 
Ó+Ó,×,€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�<‰<Ð2ˆ<×ÑÐ2˜MÐ2Ñ˜MÓ*Ð2¨dÐ2Ð*¨dÑ2×2×2Õ2Ð*¨d×2×2×2×2×2Ñ2ˆ4×2×2Ó2ˆ4×2×2Ô2ˆ<×2×2Ò2Ð×2×2Ò2˜M×2×2Ò2Ð*×2×2Ò2¨d×2×2×2×2×2×2×2Ñ2à×%Ñ%Ð+Œ3Ð%Ó&Ð+¨!Ð+Ð&¨!Ñ+×+×+Ö+Ð&¨!×+×+×+×+×+Ñ+Œ3×+×+Ó+Œ3×+×+×+×+×+Ò+ˆr×+×+Ó+ˆr×+×+Ô+Ð%×+×+Ò+Ð&×+×+Ò+¨!×+×+×+×+×+×+Ö+ð 1ùà,ûs&   ƒA<RÁ?RÂ C+RÅ+RÅ,L!RÒRc               ƒ  óÔ  K  — t        d¬«      } | j                  dd«      }|t        k(  }|sÒt        j                  d|fd|t        f«      dt        j                  «       v st        j                  |«      rt        j                  |«      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      nddœz  }d	d
|iz  }t        t        j                  |«      «      ‚d}|sedddt        j                  «       v st        j                  |«      rt        j                  |«      ndiz  }t        t        j                  |«      «      ‚y­w)z7The key derivation is total: it never reports "no key".TrV   Nr2   )z%(py0)s == %(py2)sÚkeyr   r°   r±   ri   zassert %(py0)sr7   )r   Ú_derive_rate_limit_keyr   rA   rB   rC   rD   rE   rF   rG   rH   )rJ   ré   rK   r·   rz   Ú@py_format1s         r   Ú'test_rate_limit_key_is_always_derivablerì   D  s±   è ø€ ä	¨$Ô	/€BØ
×
#Ñ
# D¨$Ó
/€CØÔ-Ñ-×-×-Õ-ˆ3Ô-×-×-×-×-×-Ñ-ˆ3×-×-Ó-ˆ3×-×-×-×-×-Ò-Ô-×-×-Ó-Ô-×-×-×-×-×-×-Ñ-Ù‡J‡J‡J‡J†Jˆ3‡J‡JƒJˆ3‡J‡J‡J‡J‡Jˆ3ùs   ‚E&E(c              ƒ  ó(  ‡K  — dgŠ| j                  t        dˆfd„«       t        t        «       d¬«      }d„ }|j	                  dt
        j                  |dd	¬
«       |j	                  dt
        j                  |dd	¬
«       |j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}|j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}|j                  t        d«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}t        d	«      D ]î  }	|j                  t        dd¬«      «      ƒ d{  –—† }
|
j                  }d}||k(  }|s­t        j                  d|fd||f«      dt!        j"                  «       v st        j$                  |
«      rt        j                  |
«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}}Œð |j                  t        dd¬«      «      ƒ d{  –—† }|j                  }d}||k(  }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}x}}t'        |j(                  «      }|j*                  }d}d} |||«      }||v }|�st        j                  d|fd||f«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      nddœz  }d d!|iz  }t        t        j                  |«      «      ‚dx}x}x}x}}|j*                  }d"}d#} |||«      }||v }|�st        j                  d|fd||f«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      nddœz  }d d!|iz  }t        t        j                  |«      «      ‚dx}x}x}x}}|j*                  }d}d$} |||«      }||v}|�st        j                  d%|fd&||f«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      nddœz  }d d!|iz  }t        t        j                  |«      «      ‚dx}x}x}x}}|j*                  }d"}d} |||«      }|j*                  }d}d"} |||«      }||k7  }|�sft        j                  d'|fd(||f«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dt!        j"                  «       v st        j$                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      d)œ
z  }d*d+|iz  }t        t        j                  |«      «      ‚dx}x}x}x}x}x}x}x}}y7 �	Œe7 �Œ©7 �Œí7 �Œ!7 �Œ6­w),zThe fallback bucket is shared among unidentified callers, and principal
    buckets stay independent of it (and of each other).rÑ   rÒ   c                 ó   •— ‰ d   S rÔ   r   rÕ   s   €r   r×   zQtest_unidentified_bucket_is_shared_and_separate_from_principals.<locals>.<lambda>R  rØ   r   T)r"   rW   c              “  ó   K  — ddiS ­wr%   r   r'   s       r   r]   zPtest_unidentified_bucket_is_shared_and_separate_from_principals.<locals>.handlerU  rª   r,   z/anonFr¾   r¿   z/authNrX   r2   r    r¡   r”   r‡   rÁ   r^   r_   r4   r5   r6   r:   r;   r­   )zf%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s._derive_rate_limit_key
}(%(py4)s, %(py6)s)
} in %(py10)srJ   Úkeysr†   r‰   rŠ   r	   rÛ   z9.9.9.9rl   )zj%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s._derive_rate_limit_key
}(%(py4)s, %(py6)s)
} not in %(py10)s)ú!=)z¿%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s._derive_rate_limit_key
}(%(py4)s, %(py6)s)
} != %(py18)s
{%(py18)s = %(py12)s
{%(py12)s = %(py10)s._derive_rate_limit_key
}(%(py14)s, %(py16)s)
})
r7   r8   ri   rk   r‡   rˆ   rŠ   Úpy14Úpy16Úpy18zassert %(py20)sÚpy20)rÜ   rÒ   r   r   r=   r   r>   r?   r   r@   rA   rB   rF   rG   rH   rÝ   rC   rD   rE   Úsetræ   rê   )rÞ   rJ   r]   rx   ry   r�   rL   r{   r–   rß   r5   rK   rM   rN   rO   rð   r�   rŽ   r�   r‘   Ú@py_assert11Ú@py_assert13Ú@py_assert15Ú@py_assert17Ú@py_format19Ú@py_format21rÖ   s                             @r   Ú?test_unidentified_bucket_is_shared_and_separate_from_principalsrý   L  sA  øè ø€ ð
 ˆx€HØ×Ñœ˜fÓ&9Ô:Ü	¤%£'ÀÔ	F€Bòð ‡L�L�œ*Ÿ.™.¨'ÀÐST€LÔUØ‡L�L�œ*Ÿ.™.¨'ÀÐRS€LÔTð —)‘)œD ›MÓ*×*Ð>Ð*×7Ñ7Ð>¸3Ð>Ð7¸3Ñ>×>×>Õ>Ð7¸3×>×>Ó>Ð*×>×>Ò>Ð7×>×>Ò>¸3×>×>×>×>×>×>Õ>Ø—)‘)œD ›MÓ*×*Ð>Ð*×7Ñ7Ð>¸3Ð>Ð7¸3Ñ>×>×>Õ>Ð7¸3×>×>Ó>Ð*×>×>Ò>Ð7×>×>Ò>¸3×>×>×>×>×>×>Õ>Ø—)‘)œD ›MÓ*×*Ð>Ð*×7Ñ7Ð>¸3Ð>Ð7¸3Ñ>×>×>Õ>Ð7¸3×>×>Ó>Ð*×>×>Ò>Ð7×>×>Ò>¸3×>×>×>×>×>×>Õ>ô �1‹Xò 'ˆØ—Y‘Yœt GÐ;RÔSÓT×TˆØ×ÑÐ& 3Ð&Ð 3Ñ&×&×&Õ&Ð 3×&×&×&×&×&Ñ&ˆt×&×&Ó&ˆt×&×&Ô&Ð×&×&Ò& 3×&×&×&×&×&×&Ô&ð'ð �i‰iœ˜WÐ4KÔLÓM×MðØMß�kðàðð àñ÷ çÑóð à÷ñ ç‰yð 	N÷ð ç‰yð÷ ð ç‰y�S÷÷ ÷ ñ çÑ÷÷ ñ ô ˆr×%Ñ%Ó&€DØ×$Ñ$Ð8 TÐ8¨4Ð8Ñ$ T¨4Ó0Ð8Ð0°DÐ8×8×8Ö8Ð0°D×8×8×8×8×8Ñ8ˆ2×8×8Ó8ˆ2×8×8Ô8Ð$×8×8Ò8 T×8×8Ò8¨4×8×8Ò8Ð0×8×8×8×8×8Ð8°D×8×8Ó8°D×8×8×8×8×8×8×8Ñ8Ø×$Ñ$ÐF ]ÐF°IÐFÑ$ ]°IÓ>ÐFÐ>À$ÐF×F×FÖFÐ>À$×F×F×F×F×FÑFˆ2×F×FÓFˆ2×F×FÔFÐ$×F×FÒF ]×F×FÒF°I×F×FÒFÐ>×F×F×F×F×FÐFÀ$×F×FÓFÀ$×F×F×F×F×F×F×FÑFð ×$Ñ$ÐA TÐA¨9ÐAÑ$ T¨9Ó5ÐAÐ5¸TÐA×A×AÖAÐ5¸T×A×A×A×A×AÑAˆ2×A×AÓAˆ2×A×AÔAÐ$×A×AÒA T×A×AÒA¨9×A×AÒAÐ5×A×A×A×A×AÐA¸T×A×AÓA¸T×A×A×A×A×A×A×AÑAà×$Ñ$ð  ]ð °Dð Ñ$ ]°DÓ9ð ¸R×=VÑ=Vð ØðØðÑ=VØˆmó>ð Ð9ð >ñ ÷ ð ïé óÐ9ð >÷ ò ïé ÷ò ïé ð ÷ ñ ïé ð ÷ ò ïé ð %÷ ð ïé ð &3÷ ð ïé ð 59÷ ð ïé ð :÷ ñ ïé ÷ò ïé ð >@÷ ñ ïé ð >@÷ ò ïé ð >W÷ ð ïé ð 	÷ð ïé ð ÷ð ïé ð>÷ ÷ ÷ ñ ïé ÷÷ ÷ ô ð' +ùØ*ùØ*ùð Uùð 	Nûs_   ƒBhÂhÂB>hÅhÅB>hÈh	ÈChË+hË,C-hÏhÏX*hèhè	hèhèhc              ƒ  óÂ  K  — d„ }| j                  dt        j                  |d¬«       | j                  t	        dd¬«      «      ƒ d {  –—† }|j
                  }d}||k(  }|s­t        j                  d|fd	||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}|j                  }t        |«      }t         |v}|�sCt        j                  d|fdt         |f«      dt        j                  «       v st        j                  t         «      rt        j                  t         «      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      ndd
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }	t        t        j                  |	«      «      ‚d x}x}}d}
|j                  }|
|v}|s­t        j                  d|fd|
|f«      t        j                  |
«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}
x}}|j                  d   }
d}|
|k(  }|slt        j                  d|fd|
|f«      t        j                  |
«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}
x}}|j                  d   }
d}|
|k(  }|slt        j                  d|fd|
|f«      t        j                  |
«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}
x}}y 7 �Œ­w) Nc              “  ó(   K  — t        t        «      ‚­wr   )ÚRuntimeErrorÚ
BAD_SECRETr'   s       r   r]   z2test_handler_exception_not_leaked.<locals>.handlerz  s   è ø€ Üœ:Ó&Ð&ùs   ‚ú/boomTr/   r^   r_   éô  r2   r4   r5   r6   r:   r;   rl   rs   r  rt   ru   rv   rw   Údetail)z0%(py1)s not in %(py5)s
{%(py5)s = %(py3)s.body
})rh   rp   r9   ÚerrorzInternal server errorrf   rg   rj   rk   Úcorrelation_idr   )r=   r   r>   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   rt   r  )r#   r]   r5   rK   rL   rM   rN   rO   r}   r~   rx   ry   rz   r{   s                 r   Ú!test_handler_exception_not_leakedr  y  s†  è ø€ ò'ð ×Ñ�gœzŸ~™~¨wÀdÐÔKØ—‘¤ WÐ<SÔ TÓU×U€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø!%§¡Ð+œS ›^Ð+Œ:˜^Ð+×+×+Ö+Œ:˜^×+×+×+×+×+Ñ+Œ:×+×+Ó+Œ:×+×+×+×+×+Ò+œS×+×+Ó+œS×+×+×+×+×+Ò+ ×+×+Ó+ ×+×+Ô+ ×+×+Ò+˜^×+×+×+×+×+×+Ó+ØÐ$˜4Ÿ9™9Ð$ˆ8˜9Ð$×$×$Õ$ˆ8˜9×$×$Ó$ˆ8×$×$×$×$×$Ð$˜4×$×$Ó$˜4×$×$Ô$˜9×$×$×$×$×$×$Ó$Ø�9‰9�WÑÐ8Ð!8Ð8ÐÐ!8Ñ8×8×8Õ8ÐÐ!8×8×8Ó8Ð×8×8Ò8Ð!8×8×8×8×8×8×8Ó8Ø�9‰9Ð%Ñ&Ð1¨'Ð1Ð&¨'Ñ1×1×1Õ1Ð&¨'×1×1Ó1Ð&×1×1Ò1¨'×1×1×1×1×1×1Ô1ð Vûs   ‚AQÁQÁ	PQc               ƒ  ót  K  — t        t        «       d¬«      } d„ }| j                  dt        j                  |d¬«       | j                  t        dd¬«      «      ƒ d {  –—† }|j                  }d}||k(  }|s­t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}|j                   d   }d}||k(  }	|	slt        j                  d	|	fd||f«      t        j                  |«      t        j                  |«      dœz  }
dd|
iz  }t        t        j                  |«      «      ‚d x}x}	}y 7 �ŒX­w)NT)r"   Údebugc              “  ó    K  — t        d«      ‚­w)Núboom-detail)Ú
ValueErrorr'   s       r   r]   zDtest_debug_mode_discloses_detail_only_when_opted_in.<locals>.handler‰  s   è ø€ Ü˜Ó'Ð'ùs   ‚r  r/   r^   r_   r  r2   r4   r5   r6   r:   r;   r  r  rf   rg   rj   rk   )r   r   r=   r   r>   r?   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   r   )rJ   r]   r5   rK   rL   rM   rN   rO   rx   ry   rz   r{   s               r   Ú3test_debug_mode_discloses_detail_only_when_opted_inr  †  s  è ø€ Ü	¤%£'°Ô	6€Bò(ð ‡L�L�œ*Ÿ.™.¨'À€LÔFØ—‘œ4 Ð7NÔOÓP×P€DØ×ÑÐ"˜sÐ"Ð˜sÑ"×"×"Õ"Ð˜s×"×"×"×"×"Ñ"ˆ4×"×"Ó"ˆ4×"×"Ô"Ð×"×"Ò"˜s×"×"×"×"×"×"Ó"Ø�9‰9�XÑÐ/ -Ð/Ð -Ñ/×/×/Õ/Ð -×/×/Ó/Ð×/×/Ò/ -×/×/×/×/×/×/Ô/ð Qûs   ‚AF8ÁF5ÁEF8)Úreturnr   )r   rt   r   r   r   ú
str | Noner   r  r   rt   r  r   )r    r   r  r   )
r(   r   r)   r  r*   rc   r   rc   r  rc   )r  ÚNone)r#   r   r  r  )r#   r   r   r  r  r  )1Ú__doc__Ú
__future__r   ÚbuiltinsrC   Ú_pytest.assertion.rewriteÚ	assertionÚrewriterA   rÒ   ÚpytestÚcyberbrain26.control_plane.apir   r   r   r   r   r   r  r   r>   r   Úfixturer    r#   r+   rP   rT   rZ   r`   r   r’   r—   ÚmarkÚparametrizerš   rž   r¢   r§   r¸   rº   rÌ   rÏ   rà   rç   rì   rý   r  r  r   r   r   ú<module>r     sz  ðñõ #ç  „ ƒã ÷õ ð !.ÀÑO€
Ø+€
ó(ð
 Ø#Ÿ™ðð !%Ø"ØñØ
ðàðð ð	ð
 ðð ðð óð* ‡�òó ðð ‡�ò*ó ð*óó#ó#ó%ó3ó'ó(?ó/ð ‡�×ÑØòó
ð#Øð#Ø(2ð#à	ò#ó
ð#ó#ó@ó%óQó?ó3ó ó0Yó.,ó:ð%à	ó%óZ
2ô	0r   