
    jv              	       $   % S r SSKrSSKrSSKrSSKJrJrJr   SSKr	Sq\\   \S'   S\\   4S jrS\S\\\\4      4S jrS	\R"                  S
\\\4   S\\\\4      4S jrS	\R"                  S\S\\\\4      4S jrg! \
 a    Sr	 Nof = f)a  
Bridge auth Supabase <-> ERGON backend.

Responsabilidades:
- Validar JWTs emitidos por Supabase Auth usando SUPABASE_JWT_SECRET (HMAC SHA256)
- Sincronizar usuario en tabla local `usuarios` cuando se autentica via Supabase
  (crea fila si no existe, actualiza last_login_at si existe)
- Resolver session dict standard a partir de un JWT valido, compatible con
  el formato que ya consume _require_session() en servidor_local.py

Convivencia con auth legacy:
- Cookie ergon_session bcrypt sigue siendo valido (admin@demo.local, etc).
- _require_session() acepta AMBOS: cookie O Authorization: Bearer <jwt>.
- Un usuario tiene UNA fuente de verdad: o supabase_uid != NULL (auth via SB)
  o password_hash != NULL (auth legacy). Nunca los dos.
    N)OptionalDictAny_JWT_SECRET_CACHEreturnc                     [         b  [         $ [        R                  R                  SS5      R	                  5       n U (       d  g [
        R                  " U 5      q [         $ ! [         a    U R                  S5      q  [         $ f = f)zj
Lee SUPABASE_JWT_SECRET del environment, decodifica base64 si aplica.
Retorna bytes para PyJWT.decode().
NSUPABASE_JWT_SECRET zutf-8)	r   osenvirongetstripbase64	b64decode	Exceptionencode)raws    /app/db/supabase_auth.pyget_jwt_secretr   !   sx     $  
**...
3
9
9
;C0",,S1   0JJw/0s   A! !BBtokenc           	          [         c  g[        5       nUc  g [         R                  " U US/SSSS.S9nU$ ! [         R                   a     g[         a     gf = f)a  
Valida un JWT emitido por Supabase Auth. Retorna el payload si es valido,
o None si invalido/expirado/secret faltante.

Payload tipico de Supabase:
    {
        "sub": "uuid-del-usuario",
        "email": "...",
        "role": "authenticated",
        "aud": "authenticated",
        "iss": "https://[ref].supabase.co/auth/v1",
        "iat": int, "exp": int,
        "app_metadata": {"provider": "google|facebook|email"},
        "user_metadata": {"full_name": "...", ...}
    }
NHS256authenticatedT)
verify_aud
verify_exp)
algorithmsaudienceoptions)pyjwtr   decodeInvalidTokenErrorr   )r   secretpayloads      r   validate_supabase_jwtr$   8   so    " }F~,,y$#'t<
 ""  s   6 A	AAconnr#   c                    UR                  S5      nUR                  S5      =(       d    SR                  5       R                  5       nU(       a  U(       d  gUR                  S5      =(       d    0 nUR                  S5      =(       d,    UR                  S5      =(       d    UR                  S5      S	   R                  5       nU R	                  5       nUR                  S
U45      R                  5       nU(       a;  UR                  SUS	   45        U R                  5         US	   US   US   US   USS.$ UR                  SU45      R                  5       nU(       a7  UR                  SX'S	   45        U R                  5         US	   X7S   US   USS.$ UR                  SX5U45        UR                  nU R                  5         XSUUSS.$ )aG  
Sincroniza el usuario en la tabla local `usuarios` a partir de un JWT payload
validado. Crea fila si no existe (rol cliente por default), actualiza
last_login_at siempre.

Retorna dict con shape compatible con session dict:
    {"id": int, "email": str, "rol": str, "nombre": str,
     "supabase_uid": str, "via": "supabase"}
subemailr
   Nuser_metadata	full_namename@r   zBSELECT id, email, rol, nombre FROM usuarios WHERE supabase_uid = ?z@UPDATE usuarios SET last_login_at = datetime('now') WHERE id = ?         supabase)idr(   rolnombresupabase_uidviazMSELECT id, rol, nombre FROM usuarios WHERE email = ? AND supabase_uid IS NULLzRUPDATE usuarios SET supabase_uid = ?, last_login_at = datetime('now') WHERE id = ?z
        INSERT INTO usuarios (email, password_hash, nombre, rol, activo, supabase_uid, last_login_at)
        VALUES (?, NULL, ?, 'cliente', 1, ?, datetime('now'))
        cliente)	r   lowerr   splitcursorexecutefetchonecommit	lastrowid)	r%   r#   r4   r(   r)   r3   currownew_ids	            r   sync_user_from_supabaserA   ^   s    ;;u%L[[!'R..0668EuKK06BM,`0A0A&0I`U[[Y\M]^_M`ggiF
++-C
++L	 hj 
 NVI	
 	a&3q6#a&CF(
 	
 ++W	 hj 
 `q6"	
 	a&5Q3q6(
 	
 KK	 
% ]]FKKM Y&$Z     auth_headerc                     U(       d  gUR                  SS5      n[        U5      S:w  d  US   R                  5       S:w  a  gUS   R                  5       n[	        U5      nUc  g[        X5      $ )z
Punto de entrada single-call para el middleware del servidor.
Recibe el valor crudo del header 'Authorization', valida el Bearer JWT,
sincroniza el usuario y devuelve el session dict.
Nr-   r.   r   bearer)r8   lenr7   r   r$   rA   )r%   rC   partsr   r#   s        r   !session_from_authorization_headerrH      si     dA&E
5zQ%(..*h6!HNNE#E*G"411rB   )__doc__r   r   sqlite3typingr   r   r   jwtr   ImportErrorr   bytes__annotations__r   strr$   
ConnectionrA   rH    rB   r   <module>rS      s   "  	  & & &* 8E? ) .# #$sCx.)A #LF'"4"4 FtCH~ FRZ[_`ceh`h[iRj FR2G,>,> 2S 2U]^bcfhkck^lUm 2]  Es   B BB