
    f[j                       U d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlmZmZmZ ddlmZmZ ddlmZmZ ddlm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#m$Z$m%Z%m&Z& ddl'm(Z(m)Z) ddl*m+Z+ ddl,m-Z.  ej^                         dz  dz  dz  Z0ejb                  je                  d      r# eejb                  d         jg                         ndZ4e0dz  Z5e0dz  Z6 eejb                  d         jg                         Z7ejb                  je                  d      r# eejb                  d         jg                         ndZ8 eejb                  je                  d e9e0dz  dz  dz                    jg                         Z:ejb                  je                  dd      Z; e<ejb                  je                  dd            Z=ejb                  je                  dd      j}                  d       D  ch c]?  } | j                         r-| j                         j                         j                  d!      A c} ZBd"ZCd#ZDd$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3ZEd4ZFd5ZGd6ZHd7ZId8ZJd9ZKd:ZL eejb                  je                  d; e9e0d<z  d=z                    jg                         ZMejb                  je                  d>d?      j                         ZNejb                  je                  d@      r# eejb                  d@         j                         ndZPejb                  je                  dA      r# eejb                  dA         j                         ndZQ eRdB eS e<ejb                  je                  dCdD            dE            ZTejb                  je                  dF      dGk(  ZUeNrH ej                  dHeN      s eWdI      eMj                   edJ      jg                               s eWdK      dLZYh dMZZh dNZ[h dOZ\h dPZ]h dQZ^ eRdB eS e<ejb                  je                  dRdD            dE            Z_dSZ`dTZa e!dU      Zb eRdV eS e<ejb                  je                  dWdX            dY            ZcdZZdd[Ze e(       Zfi Zgd\ehd]<    ej                         Zji Zkd\ehd^<    ej                         Zli Zmd\ehd_<    ej                         Zn ej                         Zo G d` daep      ZqddbZrddcZsdddZt	 d	 	 	 	 	 	 	 ddeZuddfZvddgZwddhZxddiZyddjZz	 	 	 	 	 	 ddkZ{ddlZ|ddmZ}ddnZ~ddoZdddpZdddqZdddrZdddsZdtdu	 	 	 	 	 ddvZddwZ	 	 	 	 ddxZ	 	 	 	 ddyZdtdzdd{Zdd|Zdd}Zdd~ZddZddZddZddZddZ G d de      Zedk(  rPe7j'                         s ed      e:dz  j'                         s ed       ee;e=fe      j+                          yyc c} w )zHServe the local Health Dashboard with strict routes and privacy headers.    )annotationsN)datedatetime	timedelta)CookieErrorSimpleCookie)BaseHTTPRequestHandlerThreadingHTTPServer)Path)Any)parse_qsquoteunquoteurlparse)ZoneInfo)APIErrorconnect_read_onlydispatch_api_resolve_record_document)configured_original_rootsprobe_original)validate_supplement_payload)validate_actionz.hermesassets
GesundheitHEALTH_DASHBOARD_DBzhealth_data.dbreportsHEALTH_DASHBOARD_FILEHEALTH_DASHBOARD_V5_FILEHEALTH_DASHBOARD_ASSET_DIRscriptszhealth-assetsHEALTH_DASHBOARD_HOSTz	127.0.0.1HEALTH_DASHBOARD_PORT8014HEALTH_DASHBOARD_ALLOWED_HOSTSz127.0.0.1,localhost,.z/health-dashboardz/health-dashboard-v5)chart.umd.min.jstext/javascript; charset=utf-8)zdashboard-v5.jsr)   )zdashboard-v5-nutrition.jsr)   )zdashboard-v5-range.jsr)   )zdashboard-v5-global-search.jsr)   )zdashboard-v5-api-explorer.jsr)   )zdashboard-v5-associations.jsr)   )zdashboard-v5-observations.jsr)   )zdashboard-v5-echarts.jsr)   )zdashboard-v5-day-controller.jsr)   )zdashboard-v5-record.jsr)   )zdashboard-v5.cssztext/css; charset=utf-8)zecharts-6.1.0.min.jsr)   )zfullcalendar-6.1.21.min.jsr)   )z!dashboard-v5-echarts-prototype.jsr)   )z/health-assets/chart.umd.min.jsz/health-assets/dashboard-v5.jsz(/health-assets/dashboard-v5-nutrition.jsz$/health-assets/dashboard-v5-range.jsz,/health-assets/dashboard-v5-global-search.jsz+/health-assets/dashboard-v5-api-explorer.jsz+/health-assets/dashboard-v5-associations.jsz+/health-assets/dashboard-v5-observations.jsz&/health-assets/dashboard-v5-echarts.jsz-/health-assets/dashboard-v5-day-controller.jsz%/health-assets/dashboard-v5-record.jsz/health-assets/dashboard-v5.cssz#/health-assets/echarts-6.1.0.min.jsz)/health-assets/fullcalendar-6.1.21.min.jsz0/health-assets/dashboard-v5-echarts-prototype.jsz/health-actions/symptom-checkinz!/health-actions/nutrition-mappingz/health-actions/symptom-eventz /health-actions/medication-eventz/health-actions/general-eventz /health-actions/supplement-eventz/health-actions/observationHEALTH_DASHBOARD_ACTION_INBOXruntimezdashboard-actions!HEALTH_DASHBOARD_TEST_INSTANCE_ID HEALTH_DASHBOARD_API_TOKEN_FILE$HEALTH_DASHBOARD_BASIC_PASSWORD_FILE<   $HEALTH_DASHBOARD_BROWSER_SESSION_TTL900i  .HEALTH_DASHBOARD_BROWSER_SESSION_COOKIE_SECURE1z[A-Za-z0-9_-]{8,64}z)invalid HEALTH_DASHBOARD_TEST_INSTANCE_IDz/tmpz;synthetic test instance requires an action inbox below /tmp)aphthengifatigueskineyesjointsvascular>   assignignore	composite>   0r4   23unknown>   lowhighmedium>   local_aliasmanual_reviewsighi_referenceingredient_label>   unclearrB   documented_tolerateddocumented_not_toleratedHEALTH_DASHBOARD_CSRF_TTLx   i  zEurope/Zurich   $HEALTH_DASHBOARD_MAX_PENDING_ACTIONS64   i  @))s   %PDF-zapplication/pdfz.pdf)s   PNG

z	image/pngz.png)s   z
image/jpegz.jpgzdict[str, float]_csrf_tokens_queue_receipts_browser_sessionsc                      e Zd ZdZy)QueueFullErrorzERaised when the bounded private action queue cannot accept more work.N)__name__
__module____qualname____doc__     H/home/agent/.hermes/assets/Gesundheit/scripts/health_dashboard_server.pyrW   rW      s    Or]   rW   c                    t         t        d      t        j                  t         t        j                  t        j
                  z  t        j                  z        } 	 t        j                  |       }t        j                  |j                        rR|j                  t        j                         k7  s1t        j                  |j                        dk7  s|j                  dkD  rt        d      t        j                  | d      }t        j                   |        |j#                  d      j%                         }t'        j(                  d|      st        d      |S # t        j                   |        w xY w)	Nz.read-only API authentication is not configured  rR   z'read-only API token file is not privatei  ascii[A-Za-z0-9_-]{32,128}zread-only API token is invalid)API_TOKEN_FILEOSErrorosopenO_RDONLY
O_NOFOLLOW
O_NONBLOCKfstatstatS_ISREGst_modest_uidgetuidS_IMODEst_sizereadclosedecodestripre	fullmatch)
descriptormetadatarawtokens       r^   load_api_tokenr|      s	   FGG
bmm#bmm3J88J'X--."))+-||H,,-6#%CDDggj#&
JJw%%'E<<0%8677L	 	s   B'E E2c                    t         
t               S t        j                  t         t        j                  t        j
                  z  t        j                  z        } 	 t        j                  |       }t        j                  |j                        rR|j                  t        j                         k7  s1t        j                  |j                        dk7  s|j                  dkD  rt        d      t        j                   | d      }t        j"                  |        |j%                  d      j'                         }t)        j*                  d|      st        d      |S # t        j"                  |        w xY w)Nr`      z&dashboard password file is not private   ra   z[A-Za-z0-9_-]{5,128}zdashboard password is invalid)BASIC_PASSWORD_FILEr|   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rq   rd   rr   rs   rt   ru   rv   rw   )rx   ry   rz   passwords       r^   load_dashboard_basic_passwordr      s   "
bmm#bmm3J88J'X--."))+-||H,,-6#%BCCggj#&
zz'"((*H<</:566O	 	s   B'E E1c                    | j                  d      r| j                  d      dk7  ry| j                  d      }t        |      t        |      k(  xr t	        j
                  ||      S )NzBearer  rO   F)
startswithcountremoveprefixlensecretscompare_digest)headerr{   supplieds      r^   api_request_is_authenticatedr      sX    Y'6<<+<+A""9-Hx=CJ&R7+A+A(E+RRr]   c                   t        | |      ry| j                  d      r| j                  d      dk7  ry	 t        j                  | j                  d      d      j                  d      }|j                  d      \  }}}||n|}|dk(  xr6 |d	k(  xr/ t        |      t        |      k(  xr t        j                  ||      S # t        j                  t        f$ r Y yw xY w)
NTzBasic r   rO   F)validateutf-8:health)r   r   r   base64	b64decoder   rt   binasciiErrorUnicodeError	partitionr   r   r   )r   r{   basic_passworddecodedusername	separatorr   expecteds           r^   $dashboard_principal_is_authenticatedr     s     $FE2X&&,,s*;q*@"")D

&/ 	
 %,$5$5c$:!Hi&.uNHS 	7 	7MS]*	7 ""8X6		 NNL) s   5C CCc                 0   t        j                         } t        5  t        j	                         D cg c]  \  }}|| k  s| }}}|D ]	  }t        |=  t        j                  d      }| t        z   t        |<   d d d        |S c c}}w # 1 sw Y   S xY w)N    )time	monotonic_browser_session_lockrU   itemsr   token_urlsafeBROWSER_SESSION_TTL_SECONDS)nowkeyexpiryexpired
session_ids        r^   issue_browser_sessionr     s    
..
C	 J*;*A*A*CU;3vQT}3UU 	'C!#&	'**2.
(+.I(I*%J  VJ s"   BBB6BBBc                   	 t        |       }|j                  d      }|y|j                  }t        j                  d|      syt        j                         }t        5  t        j                  |      }|||k  r t        j                  |d        	 d d d        y	 d d d        y# t        t        f$ r Y yw xY w# 1 sw Y   y xY w)NFhealth_api_sessionrb   T)r   r   
ValueErrorgetvaluerv   rw   r   r   r   rU   pop)cookie_headercookiemorselr   r   r   s         r^    browser_session_is_authenticatedr   %  s    m, ZZ,-F~J<<0*=
..
C	 "&&z2>Vs]!!*d3	 
   $  s#   B% 4B:B:%B76B7:Cc                 P   | D ]  }|st        |      }t        t        j                  j	                  |            t
        |z  t        j                         |z  t        |j                  t        t        j                         dz        t        t
                          g}|D ]o  }	 |j                         }|j                         rL|j                  t
        j                               s#|j                  t        j                               r|c c S q  y # t        $ r Y w xY w)Nr   )strr   re   path
expanduserBASEhomereplaceresolveis_fileis_relative_toREPORTSrd   )valuesr   rz   
candidates	candidateresolveds         r^   resolve_doc_pathr   9  s     %j##C()3JIIK#S|!;<c$iHI	

 $ 		I$,,.##%++DLLN;..w/@A#O		(   s   'A'D	D%$D%c                    t        j                  t        j                         j	                          dd      }|j                  d       t         j                  |_        	 |j                  d| f      j                         }|s	 |j                          y t        |d   |d         }|s	 |j                          y |t        |d   xs |j                        f|j                          S # |j                          w xY w)	Nz?mode=roT)urizPRAGMA query_only=ONzISELECT datei_name,dateipfad,local_original_path FROM dokumente WHERE id=?local_original_path	dateipfad
datei_name)sqlite3connectDBr   as_uriexecuteRowrow_factoryfetchoners   r   r   name)doc_id
connectionrowr   s       r^   document_pathr   Q  s    BJJL$7$7$9#:(!CNJ-.$[[J  WI
 (* 	  	  $9 :C<LM 	 S\*7dii88
s   "#C+ C+ =C+ +C=c           	        | j                         } |j                         }	 |j                  |       }|j                  rt        d |j                  D              rt        d      t        j                  | t        j                  t        j                  z  t        j                  z        }	 |j                  dd D ]a  }t        j                  |t        j                  t        j                  z  t        j                  z  |      }t        j                  |       |}c t        j                  |j                  d   t        j                  t        j                  z  t        t        dd      z  |      t        j                  |       S # t        $ r}t        d      |d}~ww xY w# t        j                  |       w xY w)	z4Open each path component without following symlinks.outside_rootNc              3  $   K   | ]  }|d v  
 yw)>   ..r-   r'   Nr\   ).0parts     r^   	<genexpr>z(_open_regular_beneath.<locals>.<genexpr>l  s      TT!8 Ts   invalid_path)dir_fdri   r   )absoluterelative_tor   rd   partsanyre   rf   rg   O_DIRECTORYrh   rs   getattr)rootr   relativeerror	directoryr   childs          r^   _open_regular_beneathr   d  sQ   ==?D""$I1((. >>S TX^^ TTn%%bkkBNN:R]]JKINN3B' 	DGGbnn,r}}< E
 HHYI	 wwNN2KK"--''"lA*FF
 	)  1n%501( 	s$   F -CF( 	F%F  F%(F?c                P   t        |       }	 t        ||d      }	 |j                          t        j
                  j                  d      rt        n't        j                         t        j                         f}t        |d   xs |d   |t        t              }|j                  dk7  s|j                  |j                          y|j                  |j                   |j"                  |j$                  fS # t        $ r Y |j                          yw xY w# |j                          w xY w)	zMResolve any known document and pin the safely opened descriptor for HEAD/GET.F)reviewedNHEALTH_DASHBOARD_ORIGINAL_ROOTSr   r   )roots	max_bytesopener	available)r   r   r   rs   re   environr   ORIGINAL_ROOTSr   r   r   r   MAX_ORIGINAL_BYTESr   statusrx   sizemimedownload_name)databaseopaquer   r   r   probes         r^   open_safe_originalr     s    #8,J&z6EJ 	 ::>>;< 	mmow//12 

 !"6c+&6$$	E ||{"e&6&6&>UZZU5H5HHH%   	s#   C4 4	D=D DD D%c                    t        t        |             j                  }t        |z  j	                         }	 |j                         r%|j                  t        j	                               r|S y # t        $ r Y y w xY wN)r   r   r   r   r   r   r   rd   )r   cleanr   s      r^   safe_report_pathr    sh    $$EeO$$&D<<>d11'//2CDK   s   4A- -	A98A9c                      rt         fddD              ry 	 t        d z         }|j                  }|j                  }|r|j                         j                  d      S d S # t        $ r Y y w xY w)Nc              3  &   K   | ]  }|v  
 y wr  r\   )r   charraw_hosts     r^   r   z)canonical_request_host.<locals>.<genexpr>  s     I48+Is   )/@\//r'   )r   r   hostnameportr   lowerrstrip)r  parsedhost_s   `   r^   canonical_request_hostr    sp    sI8HII$/*KK (,4::<s#55  s   &A# #	A/.A/c                4    t        |       }|d uxr |t        v S r  )r  ALLOWED_HOSTS)r  r  s     r^   host_is_allowedr    s!    !(+Dt5 55r]   c                   	 t        d|z         }t        |       }|j                  }|j                  }|j                  dk7  sT|j                  rH|j
                  <|j                  0|j                  s$|j                  s|j                  s|j                  ry|j                  }|d uxrP |j                  j                         j                  d      |j                         j                  d      k(  xr ||k(  S # t        $ r Y yw xY w)Nr  Fhttpr'   )r   r  r   schemer  r   r   r   paramsqueryfragmentr  r  )originr  request_authorityr   request_portsupplied_portrequest_hosts          r^   origin_matches_requestr#    s    $TH_5F#(--  	6!  ((==??>>$--LD  	*##%,,S1\5G5G5I5P5PQT5UU	*\)  s   1C9 9	DDc                   | t        j                         n| }t        j                  d      }t        5  t
        j                         D cg c]  \  }}||z
  t        kD  r| }}}|D ]  }t
        j                  |d         |t
        |<   t        t
              dkD  rHt        t
        t
        j                        }t
        j                  |d        t        t
              dkD  rHd d d        |S c c}}w # 1 sw Y   |S xY w)N   rR   r   )r   r   r   r   
_csrf_lockrS   r   CSRF_TTL_SECONDSr   r   minr   )r   	issued_atr{   existing	timestampr   oldests          r^   issue_csrf_tokenr.    s    $'K SI!!"%E	 + (4'9'9';
#)9$'77 
 

   	-HXt,	-'U,#%<+;+;<FVT* ,#%+ L
+ Ls   C7C1$BC71C77Dc                    |t        j                         n|}t        5  t        j	                  | d       }d d d        d uxr d||z
  cxk  xr	 t
        k  S c S # 1 sw Y   &xY wNr   )r   r   r'  rS   r   r(  r{   r   
checked_atr*  s       r^   consume_csrf_tokenr3    sd    %([!cJ	 2 $$UD1	2D TQ*y*@%TDT%TT%TT2 2   AA$c                   | t        j                         n| }t        j                  d      }t        5  |t
        |<   t
        j                         D cg c]  \  }}||z
  t        kD  r| }}}|D ]  }t
        j                  |d         t        t
              dkD  rHt        t
        t
        j                        }t
        j                  |d        t        t
              dkD  rHd d d        |S c c}}w # 1 sw Y   |S xY w)N   rR   r&  )r   r   r   r   _queue_receipt_lockrT   r   QUEUE_RECEIPT_TTL_SECONDSr   r   r)  r   )r   r*  r{   r   r,  r   r-  s          r^   issue_queue_receiptr9    s    $'K SI!!"%E	 .!* #2"7"7"9
Y9$'@@ 
 

  	+CT*	+/"S(o.A.ABF- /"S(. L
. Ls   !C7C1-A9C71C77Dc                    |t        j                         n|}t        5  t        j	                  | d       }d d d        d uxr d||z
  cxk  xr	 t
        k  S c S # 1 sw Y   &xY wr0  )r   r   r7  rT   r   r8  r1  s       r^   consume_queue_receiptr;    sn    %([!cJ	 5#''t4	5 	 	Ei'D+DDD5 5r4  Fcapture_queuedc               t   t        j                  d      }t               }t               }| j                  d      }t	               }|j                  d|      }|j                  d|      }|j                  d|rdnd      }|j                  d	|j                               }|j                  d
|j                  d            }|j                  dt        j                  t              j                  d            }|j                  dd| d      }|j                  dd| d      }|j                  d      |||fS )Nr6  r   )encoding__CSRF_TOKEN____BROWSER_SESSION_CSRF____CAPTURE_QUEUED__truefalse__CAPTURE_DATE____CAPTURE_DATE_LABEL__z%d.%m.%Y__CAPTURE_DATETIME__z%Y-%m-%dT%H:%Mz<scriptz<script nonce=''z<stylez<style nonce=')r   r   r.  	read_textlocal_todayr   	isoformatstrftimer   r   CAPTURE_TIMEZONEencode)r   r=  nonce
csrf_tokenbrowser_session_csrf_tokentextcapture_days          r^   dashboard_html_with_noncerT  	  s   
 !!"%E!#J!1!3>>7>+D-K<<(*5D<<24NOD<<,fGTD<<*K,A,A,CDD<<0+2F2Fz2RSD<<.=M0N0W0WXh0ijD<<	_UG1#=>D<<N5'";<D;;w
4NNNr]   c                 P    t        j                  t              j                         S r  )r   r   rM  r   r\   r]   r^   rJ  rJ    s    <<()..00r]   c                   | j                  d      xs dgd   }	 t        j                  |      }|j                  dk  s|t               kD  rt        d      i }t        D ];  }| j                  |      xs dgd   }|dvrt        d|       t        |      ||<   = | j                  d	      xs dgd   j                         }t        |      d
kD  rt        d      |j                         ||fS # t        $ r}t        d      |d }~ww xY w)Nr   r-   r   zinvalid date  zdate outside allowed range   r?   r4   r@   rA   zinvalid or missing score: notes,  znotes too long)r   r   fromisoformatr   yearrJ  SYMPTOM_FIELDSintru   r   rK  )formday
parsed_dayexcscoresfieldrz   rY  s           r^   validate_symptom_formre  "  s    88F#tQ
'C2'',
 km!;566F !xx&2$***9%ABBCu	!
 XXg&2$*002E
5zC)**!6500  2(c12s   C0 0	D
9DD
c                J   dddht         }|dhz  }t        |       }|t        |      t        |      hvrt        d      t        d | j	                         D              rt        d      | j                  ddg      d	   }|d
vrt        d      t        |       \  }}}||||fS )NrP  r   rY  	return_tozinvalid submission shapec              3  8   K   | ]  }t        |      d k7    ywrO   Nr   r   r   s     r^   r   z.validate_symptom_submission.<locals>.<genexpr>@       
83v;!
8   z$every field must have a single valuev4r   >   rn  v5invalid return target)r]  	frozensetr   r   r   r   re  )r_  requiredallowedkeysrg  r`  rc  rY  s           r^   validate_symptom_submissionru  8  s     fg??H+&GT?DIh'7);<<344

8$++-
88?@@tf-a0I$011.t4Cy((r]   rr  c                   dj                  | j                               }|r|r3t        |      |kD  s%t        j                  d|t        j
                        rt        d      |S )Nr   )[\x00-\x1f\x7f]|https?://|/|\\\\|\.hermeszinvalid action text)joinsplitr   rv   searchIr   )r   maximumrr  cleaneds       r^   _safe_action_textr  I  s_    hhu{{}%GS\G%;ryyIuw~  AC  AE  AE  @F.//Nr]   c                l   	 t        j                  |       }|j                  |j                  dk  rt        d      |j                  t              }|t        j                  t              t        d      z   kD  rt        d      |j                  d      S # t        $ r}t        d      |d }~ww xY w)	Nzinvalid action datetimerW  )tzinfo   )minuteszfuture action datetimer  )timespec)
r   r[  r   r  r\  r   rM  r   r   rK  )r   r  rb  awares       r^   _local_action_datetimer  P  s    =''. }} FKK$$6233NN"2N3Ex||,-	!0DDD122Y//  =23<=s   B 	B3"B..B3c                    | sg S | j                  d      }t        |      dkD  st        d |D              rt        d      |S )Nr&      c              3  L   K   | ]  }| xs |j                         |k7    y wr  )ru   )r   items     r^   r   z#_csv_identifiers.<locals>.<genexpr>a  s%     R4$h>$**,$*>>Rs   "$zinvalid identifier list)rz  r   r   r   )r   r   s     r^   _csv_identifiersr  ]  sA    	[[F
6{Q#R6RR233Mr]   c                \   t        d | j                         D              s| j                  ddg      d   dk7  rt        d      | j                  ddg      d   }h d}|d	k(  r|h d
z  }t	        |       |k7  rt        d      dd| d   d   | d   d   | d	   d   t        | d   d         t        | d   d         t        | d   d         t        | d   d         | d   d   | d   d   | d   d   | d   d   | d   d   dk(  dd}n|dk(  r|h dz  }t	        |       |k7  rt        d      dd| d   d   | d    d   | d!   d   | d"   d   | d   d   | d   d   | d#   d   t        | d$   d         t        | d%   d         t        | d   d         t        | d   d         | d&   d   | d'   d   d(}n|d)k(  rz|h d*z  }t	        |       |k7  rt        d+      dd,| d   d   | d    d   | d-   d   | d&   d   | d.   d   | d/   d   | d0   d   | d1   d   | d2   d   | d3   d   | d4   d   | d   d   d5}nq|dk(  r2t	        |       |ddhz  k7  rt        d6      dd7| d   d   | d   d   d8}n:|d9k(  r*t	        |       |dhz  k7  rt        d:      dd;| d   d   d<}nt        d=      t        |      dfS )>Nc              3  8   K   | ]  }t        |      d k7    ywri  rj  rk  s     r^   r   z2validate_observation_submission.<locals>.<genexpr>g  rl  rm  rg  r-   r   ro  zinvalid observation submissionmode>   r  rg  rP  question>   notetitler   lag_maxlag_minend_dateoutcomesr  
influences
start_dateinclude_doctorobservation_idzinvalid observation shaperO   observation_upsertr  r  r  r  r  r  r  r  r   r  r  r4   zpersonal-observation-phases-v1)versionactionr  r  r  r  r  r  r  r  r  r   r  r  method_versionphase>   r   rY  eventsr  r  metricsr  phase_id	adherence
phase_typer  behavior_goalr  zinvalid phase shapeobservation_phase_upsertr  r  r   r  r  r  r  rY  )r  r  r  r  r  r   r  r  r  r  r  r  r  r  rY  checkin>   r`  r  stresstravelr  r  	infectionr  sleep_disruptionunusual_activitymedication_change_factsupplement_change_factzinvalid checkin shapeobservation_checkinr`  r  r  r  r  r  r  r  )r  r  r  r  r`  r  r  r  r  r  r  r  r  r  zinvalid status shapeobservation_status)r  r  r  r   snapshotzinvalid snapshot shapeobservation_result_snapshot)r  r  r  zinvalid observation mode)r   r   r   r   setr  r^  validate_observation_action)r_  r  commonrr  payloads        r^   validate_observation_submissionr  f  s   

8$++-
88DHH[SURV<WXY<Z^b<b9::88FRD!!$D0Fz  g  gt9 899(<dScNdefNgptu|p}~  qA  MQ  R\  M]  ^_  M`  n~  C  DP  Q  RS  T  nU  aq  rv  wA  rB  CD  rE  aF  QT  UY  Zc  Ud  ef  Ug  Qh  sv  w{  |E  wF  GH  wI  sJ  X\  ]i  Xj  kl  Xm  y}  ~H  yI  JK  yL  VZ  [c  Vd  ef  Vg  os  tz  o{  |}  o~  PT  Ue  Pf  gh  Pi  kn  Pn  @`  a	  q  qt9 233&@RVWgRhijRkw{  }G  xH  IJ  xK  Y]  ^j  Yk  lm  Yn  vz  {A  vB  CD  vE  SW  Xd  Se  fg  Sh  tx  yC  tD  EF  tG  X\  ]l  Xm  no  Xp  {K  LP  QZ  L[  \]  L^  {_  iy  z~  G  zH  IJ  zK  iL  WZ  [_  `i  [j  kl  [m  Wn  y|  }A  BK  }L  MN  }O  yP  ]a  bm  ]n  op  ]q  z~  F  zG  HI  zJ  K		  I  It9 455&;TRbMcdeMfrv  xB  sC  DE  sF  MQ  RW  MX  YZ  M[  hl  mx  hy  z{  h|  FJ  KS  FT  UV  FW  ko  pB  kC  DE  kF  SW  Xc  Sd  ef  Sg  {  @R  {S  TU  {V  `d  em  `n  op  `q  KO  Ph  Ki  jk  Kl  FJ  Kc  Fd  ef  Fg  os  tz  o{  |}  o~  		t9"28!<<<344&:DQaLbcdLeost|o}~  pA  B		t9"2!333566&CUYZjUklmUno344&w/55r]   c           
        |t         k(  rh d}t        |       |k7  s t        d | j                         D              rt	        d      | d   d   dk7  rt	        d      | d   d   }d	| d
   d   | d   d   | d   d   | d   d   | d   d   | d   d   | d   d   | d   d   d	}|dk(  rI| d   d   }i |d| d   d   | d   d   |j                         rt        |      nd | d   d   | d   d   d}n(|dk(  ri |d| d   d   | d   d   d d}nt	        d       t        |      dfS h d!}|t        k(  r|h d"z  }n-|t        k(  r|h d#z  }n|t        k(  r|h d$z  }nt	        d%      t        |       |k7  s t        d& | j                         D              rt	        d'      | d   d   dk7  rt	        d      t        | d   d         }t        | d   d   d(      }	|t        k(  r| d)   d   }
|
d*vs
| d+   d   d,vrt	        d-      | d.   d   }|rt        |      nd/}| d0   d   }|r)|j                         rt        |      d1kD  rt	        d2      t        | d3   d   d4|
d5k(  6      }d	d7||
t        | d+   d         ||rt        |      nd ||	d8	dfS |t        k(  r| d9   d   }|d:vrt	        d;      t        | d<   d   d=d>6      }t        t	        d?      t        t              }	 |j                  d@|f      j!                         }|j#                          |t	        dA      t        | dB   d   dC      }t        | d   d   dD      }t        | dE   d   dF      }d	dG|||||||	dH	dfS | dI   d   }|dJvrt	        dK      | dL   d   }|r|d,vrt	        dM      t        | d3   d   dNd>6      }d	dO||||rt        |      nd |	dPdfS # |j#                          w xY w)QN>   r  unitrY  amountr   productr  weekdaysrg  rP  r  occurred_atnutrient_keybrand_variantinterval_daysschedule_typecomposition_sourceassignment_reliabilityc              3  8   K   | ]  }t        |      d k7    ywri  rj  rk  s     r^   r   z*validate_patient_action.<locals>.<genexpr>  s     'UVFq(8'Urm  z#invalid supplement submission shaperg  r   ro  rp  r  rO   r  r  r  r  r  r  r  rY  )	r  r  r  r  r  r  r  r  rY  plannedr  supplement_planr  r  r  r  )r  r  r  r  r  r  actualsupplement_intaker   r  )r  r   r  plan_idzinvalid supplement mode>   rY  rg  rP  r  >   labelonset_atseveritysymptom_typeduration_minutes>   doser  route
event_typemedication_name>   r  category	intensityzunsupported patient actionc              3  8   K   | ]  }t        |      d k7    ywri  rj  rk  s     r^   r   z*validate_patient_action.<locals>.<genexpr>       #QCK1$4#Qrm  zinvalid patient action shaperZ  r  >   r6   r9   r8   otherr:   aphthaer7   headacher  rX  zinvalid symptom eventr  r-   r  i`'  zinvalid symptom durationr  P   r  rv  symptom_event)	r  r  r  r  r  r  r  r  rY  r  >   missed	correctedadministeredzinvalid medication eventr  rN   Tzmedication catalog unavailablezHSELECT 1 FROM medication_administrations WHERE medication_name=? LIMIT 1z"medication is not in exact catalogr  (      r  r0   medication_event)	r  r  r  r  r  r  r  r  rY  r  >   heatr  r  r  r  appointmentphysical_loadr  zinvalid event categoryr  zinvalid event intensityd   general_event)r  r  r  r  r  r  rY  )SUPPLEMENT_EVENT_ROUTEr  r   r   r   isdigitr^  r   SYMPTOM_EVENT_ROUTEMEDICATION_EVENT_ROUTEGENERAL_EVENT_ROUTEr  r  API_DBr   r   r   rs   )r_  action_pathrr  r  common_payloadintervalr  r  r  rY  r  onsetr  durationr  r  
medicationr   knownr  r  r  r  r  s                           r^   validate_patient_actionr    s   ,,
 t9 C'Ut{{}'U$UBCCQ4'455F|AIq)!/215 038nQ'LO"&';"<Q"?&*+C&DQ&G']1%
-
 9O,Q/H +!%o!6q!9 ,Q/2:2B2B2DX$"<03 ,Q/G X -x.+#M215G 677*73T99@F))aa	.	.VV	+	+>>566
4yH#Q4;;=#Q Q788Kt#011(m)<Q)?@Kd7mA.4E))N+A.jjnrs}n~  @A  oB  J^  o^455Z #49)%0r*+A.X--/3x=53H788!$w-"2BQXAXYeq  @C  DH  IS  DT  UV  DW  @X  fn  U]  DG  HP  DQ  cg  rw  BG  H  JN  N  	N,,,'*
DD788&t,='>q'A3QUV
>=>>&v.
	&&Z hj 
 =ABB fa"5 fa"5!$w-"2B7(:;fp  FP  Z^  hl  w|  GL  M  OS  S  	SJ"H}}122[!!$IY&::233d7mA.dCEOK]epu  W`  EH  IR  ES  fj  uz  {  }A  A  A s   #!O Oc                ^   h d}t        |       |k7  s t        d | j                         D              rt        d      | d   d   }|dk7  rt        d      | d   d   }| d	   d   j	                         }d
j                  | d   d   j                               }d
j                  | d   d   j                               }| d   d   }| d   d   }| d   d   }	d
j                  | d   d   j                               }
d
j                  | d   d   j                               }d
j                  | d   d   j                               }| d   d   }| d   d   }d
j                  | d   d   j                               }t        j                  d|      st        d      |df|df|
df|df|df|dffD ]C  \  }}t        |      |kD  s&t        j                  d|t        j                        s:t        d       |r|
r|st        d      |t        vs$|t        vs|t        vs|	t        vs|d vs|t         vrt        d!      |d"k(  }|d#k(  r|d$k(  s|r|rt        d%      |d&k(  r|d$k7  s|st        d'      |d(k(  r|d$k7  s|s|rt        d)      d*d+|||||d$k(  rd$n
t#        |      ||	|
|||||d,|fS )-N>   r  aliasdecision	queue_keyrg  
confidencerP  sighi_scoresource_labelcanonical_foodmapping_methodsource_versionpersonal_tolerance_notepersonal_tolerance_statusingredient_review_requiredc              3  8   K   | ]  }t        |      d k7    ywri  rj  rk  s     r^   r   z.validate_mapping_submission.<locals>.<genexpr>   r  rm  zinvalid mapping shaperg  r   ro  rp  r  r  r   r  r  r  r  r  r  r  r  r   r  r  z[0-9a-f]{32}zinvalid queue key   rN   r  r  rZ  rx  zinvalid mapping textzmapping documentation required>   rC  rD  zinvalid mapping valuerC  r<   rB   zassign requires canonical scorer>   zcomposite remains unclassifiedr=   zignore must not classifyrO   nutrition_mapping)r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  )r  r   r   r   ru   ry  rz  rv   rw   r   r{  r|  MAPPING_DECISIONSMAPPING_SCORESMAPPING_CONFIDENCEMAPPING_METHODSPERSONAL_TOLERANCE_STATUSESr^  )r_  rr  rg  r  r  r  r  scorer  methodr  r  r  reviewtolerance_statustolerance_noter   r}  r   s                      r^   validate_mapping_submissionr    s0   H" 4yH#Q4;;=#Q Q011[!!$ID011J"H[!!$**,IHHT']1%++-.EXXd#34Q7==?@N"El#A&J"#A&F88D0399;<LXXd#34Q7==?@N88DLO))+,D./2F78;XXd#<=a@FFHIN<<3,--			r		s	 	5w u:299-Y[`bdbfbf#g344	5 N9::))&//(**#>>011!'6!18)!3>Mg:;;;EY$6>X9::8)!3~Ic344%($)Y$6yCJ  $(&@%5#1  ! r]   c                 &   t         j                  ddd       t         j                         } t        j                  | j
                        r!| j                  t        j                         k7  rt        d      t        j                  t         d       y )Ni  T)r  parentsexist_okz-action inbox is not a private owned directory)ACTION_INBOXmkdirlstatrk   S_ISDIRrm   rn   re   ro   rd   chmod)ry   s    r^   ensure_private_inboxr  C  sb    E4$?!!#H<<(()X__		-KEFFHH\5!r]   c                V   t         5  t                t        d t        j	                  d      D              t
        k\  rt        d      t        j                  d      }t        d| dz  }t        | dz  }t        j                  | dd	
      j                  d      }t        j                  |t        j                  t        j                  z  t        j                   z  t        j"                  z  d      }	 t        j$                  |d      5 }|j'                  |       |j)                          t        j*                  |j-                                ddd       |j/                  |       t        j                  t        t        j0                  t        j2                  z        }	 t        j*                  |       t        j4                  |       	 ddd       y# 1 sw Y   xY w# t        j4                  |       w xY w# t6        $ r |j9                  d        w xY w# 1 sw Y   yxY w)zNAtomically enqueue a validated action; the network server never writes the DB.c              3      K   | ]  }d   ywri  r\   )r   r  s     r^   r   z'write_action_payload.<locals>.<genexpr>O  s     6Qq6s   z*.jsonzprivate action queue is full   r'   z.tmpz.jsonFr&   r   )ensure_ascii
separatorsr   r`   wbNT)
missing_ok)_action_lockr  sumr  globMAX_PENDING_ACTIONSrW   r   	token_hexjsondumpsrN  re   rf   O_WRONLYO_CREATO_EXCLrh   fdopenwriteflushfsyncfilenor   rg   r   rs   	Exceptionunlink)r  r{   	temporarydestinationpackedrx   handler   s           r^   write_action_payloadr5  K  s   	 6,++H566:MM !?@@!!"% QugT?2	"we_4!
 &/	 	
 WWKK"**$ryy02==@


	:t, *V$)* k*bkkBNN.JKI$##7 $* * # 	-	9 sP   C/H7G?AGAG?%G%:G?G"	G?%G<<G??HHH(c                &    t        dd| ||d       y )NrO   symptom_checkin)r  r  r   rc  rY  )r5  )r`  rc  rY  s      r^   write_symptom_checkinr8  n  s    '	
r]   c                      e Zd Z	 	 d	 	 	 	 	 	 	 d fdZddZeZeZeZeZeZ	e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ddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZ xZS )HandlerNc                h   t        t        | dd            j                  }|j                  d      rot        | dd      dk7  }t	        | j
                  j                  dd            s| j                  dd|       y |d	k(  rd
n|}|d	k(  rdnd}| j                  |||       y t        | %  |||       y )Nr   r-   /api/v1/commandHEADHost  invalid_hosti    read_only_endpointrequest_rejected)
r   r   r   r   r  headersr   _send_api_errorsuper
send_error)	selfcodemessageexplainrequest_path	send_bodyr   
error_code	__class__s	           r^   rH  zHandler.send_error{  s      fb 9:??"":.i4>I"4<<#3#3FB#?@$$S.)D CKSTF15-BTJ  Y?4'2r]   c                   t        | j                  j                  dd            sat        | j                        j                  j                  d      r!| j                  dd| j                  dk7         y | j                  d       y t        | j                        j                  j                  d      r!| j                  dd| j                  dk7         y | j                  d       y )	Nr?  r-   r<  r@  host_not_allowedr>  rB  rC  )	r  rE  r   r   r   r   rF  r=  rH  rI  s    r^   _reject_unsupportedzHandler._reject_unsupported  s    t||//;<		"''22:>$$S*<dllf>TU  $DII##..z:  &:DLLF<RSr]   c                   t        | j                  j                  dd            sTt        | j                        j                  j                  d      r| j                  ddd       y | j                  d       y | j                  d       y )Nr?  r-   r<  r@  rR  FrN  	r  rE  r   r   r   r   rF  rH  _handlerS  s    r^   do_HEADzHandler.do_HEAD  so    t||//;<		"''22:>$$S*<eD  $u%r]   c                   t        | j                  j                  dd            sTt        | j                        j                  j                  d      r| j                  ddd       y | j                  d       y | j                  d       y )Nr?  r-   r<  r@  rR  TrV  rW  rS  s    r^   do_GETzHandler.do_GET  so    t||//;<		"''22:>$$S*<dC  $t$r]   c                r	   t        | j                  j                  dd            sTt        | j                        j                  j                  d      r| j                  ddd       y | j                  d       y t        | j                        j                  }|j                  d      r+|dk(  r| j                  d       y | j                  dd	d       y t        | j                        j                  }|t        t        t        t        t        t        t        hvr| j                  d
       y | j                  j                  dd      }| j                  j                  dd      }t!        ||      s| j                  d       y | j                  j#                         dk7  r| j                  d       y 	 t%        | j                  j                  dd            }|dk  s|dkD  r| j                  d       y 	 t)        | j*                  j-                  |      j/                  d      ddd      }|j                  d      xs dgd   }t3        | j                  j                  dd            }|j                  d      }	|r"|	r t5        j6                  ||	j8                        s| j                  d       y t;        |      s| j                  d       y d}
	 |t        k(  rt=        |      \  }}}}t?        |||       nn|t        k(  r(tA        |      \  }}tC        |d         }
tE        |       n=|t        k(  rtG        |      \  }}tE        |       ntI        ||      \  }}tE        |       |dk(  rctO        tQ               d       }|t        k(  r tO        |
d       }tR        d!z   d"| d#| z   }n.|t        k(  rtR        d$| d%z   }ntR        d&| d'z   }n	tT        d(z   }| jW                  d)       | jY                  d*|       | jY                  d+d,       | j[                          y # t&        $ r | j                  d       Y y w xY w# t0        t&        f$ r | j                  d       Y y w xY w# t&        $ r | j                  d       Y y tJ        $ r | j                  d       Y y tL        $ r | j                  d       Y y w xY w)-Nr?  r-   r<  r@  rR  Tz/api/v1/browser-sessionrB  rC    Origin  z!application/x-www-form-urlencodedi  Content-Lengthr?     rO   i   i  r      )keep_blank_valuesstrict_parsingmax_num_fieldsrP  r   Cookiehealth_csrfr      ro  )safez1?view=nutrition&workspace=mapping&map_status=openz&map_sort=frequency&mapping=z&queued=z.?view=explorer&explorer_area=questions&queued=z#observation-statusz?queued=z#capture-statusz?queued=1#symptomei/  LocationCache-Controlno-store).r  rE  r   r   r   r   rF  rH  _handle_browser_sessionCHECKIN_ROUTENUTRITION_MAPPING_ROUTEr  r  r  r  OBSERVATION_ROUTEr#  get_content_typer^  r   r   rfilerr   rt   r   r   r   r   r   r3  ru  r8  r  r   r5  r  r  rW   rd   r   r9  V5_ROUTEROUTEsend_responsesend_headerend_headers)rI  api_pathr  r  r  lengthr_  r{   r   cookie_tokenmapping_queue_key_valuer`  rc  rY  rg  r  receiptr  targets                      r^   do_POSTzHandler.do_POST  sj   t||//;<		"''22:>$$S*<dC  $DII&++z*44,,T2  $$S*>Etyy)..}.EGZ\r  uH  J`  bs  t  tOOC !!(B/||+%fd3OOC <<((*.QQOOC 	))*:C@AF A:$OOC 		

'..w7"&#!	D ,'/B43dll..x<=zz-0))%1C1CDOOC !%(OOC "$	m+0KD0Q-VUI%c659 77%@%F"*-gk.B*C'$W- 11%DT%J"$W-%<T;%O"$W- /1;G55!"9C	IJ4YKxyQR 
  11!&TU\T]]p$qq!hwi$GG11F3V,*5O  	OOC 	 j) 	OOC 	>  	OOC  	OOC  	OOC 	sC   3%P 57P= BQ# P:9P:= Q Q #R6?R6R65R6c                    t         y	 t               }t               }t        | j                  j                  dd      ||      S # t        t        f$ r Y yw xY w)NTFAuthorizationr-   )r  r|   r   rd   r   r   rE  r   )rI  r{   r   s      r^   _v5_principal_authenticatedz#Handler._v5_principal_authenticated  s_    >	"$E:<N 4LL_b15.
 	
 & 		s   A AAc                    | j                  d       | j                  dd       | j                  dd       | j                  dd       | j                  dd	       | j                  d
d       | j                          y )N  WWW-Authenticatez!Basic realm="Health Dashboard V5"rl  rm  Pragmano-cacheX-Content-Type-Optionsnosniffr`  r?   )rv  rw  rx  rS  s    r^   _send_dashboard_auth_requiredz%Handler._send_dashboard_auth_required#  sp    3+-PQ*5:.19=)3/r]   c                   t        | j                        }|j                  }|j                  d      r| j                  ||j                  |       y |dk(  r8| j                  d       | j                  dt               | j                          y |t        t        hv r|t        k(  r!| j                         s| j                          y |t        k(  rt        nt        }|| j                  d       y 	 t        |j                  d      j!                  dg       }|xr) |t        k(  xr t#        |      d	k(  xr t%        |d
         }t'        ||      \  }}}	}
| j-                  ||j.                  d|||	|
|t        k(         y |t0        v r(t0        |   \  }}| j3                  t4        |z  |||       y |j                  d      rY	 t7        |j9                  dd	      d         }t=        |      }|s| j                  d       y | j3                  |d
   |d	   d |       y |j                  d      rQt?        |j9                  dd	      d         }|s| j                  d       y | j3                  ||j.                  d |       y | j                  d       y # t(        t*        f$ r | j                  d       Y y w xY w# t:        $ r | j                  d       Y y w xY w)Nr<  r	  i.  rk  r]  T)rc  queuedrO   r   r<  ztext/html; charset=utf-8rO  rP  rQ  connect_selfz/health-doc/r   z/health-report/) r   r   r   _handle_apir  rv  rw  ru  rx  rt  r  r  DASHBOARD_FILEDASHBOARD_V5_FILErH  r   r   r   r;  rT  rd   r   _send_bytesr   ASSET_ROUTES_serve_file	ASSET_DIRr^  rsplitr   r   r  )rI  rN  requestr   selectedqueued_valuesr=  datarO  rP  rQ  filenamecontent_typer   foundreports                   r^   rX  zHandler._handle,  s   499%||??:&T7==)<3;s#Z/E8$$x(H(H(J224)-~<MH$ ($ O S Sb!  @(@M*a/@ .mA.>?	  . '5 DeZ)C *%+E!X-  	 <%1$%7"HlH$	 ??>*T[[a045 "&)E$U1XuQxyA??,-%dkk#q&9"&=>F$VV[[$	BU \* $4  $s%   0A&J J5  J21J25KKc                   t        | j                        }|j                  st        *| j	                  t        dndt        d|       y d|       y | j                         s| j	                  dd|       y | j                  j                  dd      }| j                  j                  d	d      }|r&t        || j                  j                  d
d            r|r|dvr| j	                  dd|       y | j                  j                  dd      dvr| j	                  dd|       y 	 t        | j                  j                  dd            }| j                  j                  dd      }|j                  d      }|rN|Lt        |      t        |j                        k7  s+t        j                  ||j                        rt!        |      s| j	                  dd|       y t#               }d| dt$         }t&        r|dz  }| j)                  d       | j+                  d|       | j+                  dd       | j+                  dd       | j+                  dd        | j+                  d!d"       | j+                  d#d$       | j+                  d%d&       | j+                  dd       | j-                          y # t        t        f$ r | j	                  dd|       Y y w xY w)'Nrh  ra  api_unavailableunknown_parameterr  authentication_requiredr^  r-   Sec-Fetch-Siter?     same-originnoner_  origin_not_allowedr`  r?   >   r-   r?   rD  rf  csrf_rejectedzX-Health-Browser-CSRFhealth_browser_csrfzhealth_api_session=z3; Path=/api/v1; HttpOnly; SameSite=Strict; Max-Age=z; Secure   
Set-Cookierl  rm  r  r  r  r  X-Frame-OptionsDENYReferrer-Policyno-referrerContent-Security-Policy*default-src 'none'; frame-ancestors 'none')r   r   r  r  rF  r  rE  r   r#  r   r   r   r   r   r   r   r3  r   r   BROWSER_SESSION_COOKIE_SECURErv  rw  rx  )	rI  rN  r  r  
fetch_siter   csrf_headercsrf_cookier   s	            r^   rn  zHandler._handle_browser_session{  s   499%==FN  ~3%+^!
  :M
 //1  &?K!!(B/\\%%&6;
1&$,,:J:J6SU:VWZ/FF  &:IF<<,c2)C  &8)D	!$,,"2"28R"@AF ll&&'>Cjj!67";3{'8'8#99))+{7H7HI%k2  oyA*,
!* .235 	 )j F3v.*5:.19=*F3*M:%'S	
 	)3/A Z( 	  oyA	s   #%J, ,"KKc                   t         | j                  dd|       y 	 t               }|d uxr& t        | j                  j                  dd      |      }t        | j                  j                  dd            }|| j                  dd|       y |s|s| j                  dd|       y | j                  j                  dd      }| j                  j                  d	d      }|r&t        || j                  j                  d
d            r|r|dvr| j                  dd|       y t        j                  d|      }	|	r|r| j                  dd|       y t        t         |	j                  d            }
|
s| j                  dd|       y |
\  }}}}	 | j                  d       | j                  d|       | j                  dt!        |             | j                  dd|        | j                  dd       | j                  dd       | j                  dd       | j                  dd        | j                  d!d"       | j                  d#d$       | j#                          |rct%        j&                  |d%d&'      5 }|j)                  d(      x}r/| j*                  j-                  |       |j)                  d(      x}r/d d d        t%        j.                  |       y 	 t1        t         ||      }| j;                  d||       y # t        t        f$ r d }Y w xY w# 1 sw Y   ]xY w# t        $ r Y t%        j.                  |       y w xY w# t%        j.                  |       w xY w# t2        $ r1}| j                  |j4                  |j6                  |       Y d }~y d }~wt        t        f$ r | j                  dd|       Y y t8        $ r | j                  d)d*|       Y y w xY w)+Nrh  r  r  r-   rf  r  r  r^  r  r?  r  r_  r  z6/api/v1/documents/(api-document-[a-f0-9]{24})/originalra  r  rO   r]  original_not_available   Content-Typer`  Content-Dispositionzinline; filename=rl  rm  r  r  r  r  r  r  r  r  r  r  rbF)closefdi   ri  internal_error)r  rF  r|   rd   r   r   rE  r   r   r#  rv   rw   r   grouprv  rw  r   rx  re   r*  rr   wfiler+  rs   r   r   r   rJ  r/  _send_api_json)rI  r   r  rN  r{   bearer_authenticatedsession_authenticatedr  r  originalopenedrx   r   r   r  r4  r  r  r   s                      r^   r  zHandler._handle_api  s   >  &7C	"$E  %D0  
5QLL_b156
 !ALLXr*!
 =  &7C#,A  &?K!!(B/\\%%&6;
1&$,,:J:J6SU:VWZ/FF  &:IF<<Et
 $$S*=yI'q0ABF$$S*BIN/5,JdH%""3'  6  !13t9=  !6:KH:8VW  *=  :6  !99E  !2F;  !2MB  -@   ":tUC 3v&,kk)&<<d< JJ,,T2 '-kk)&<<d<3 $
	"647G 	C)4I & 	E	b3 3  $ $  	  uzz9E& 	  &7C 	  &6	B	ss   
K; C)L 4AL7L M ;LLLL 	M (M ?M  M M	O&'N%O9OOc                2    | j                  |dd|ii|       y )Nr   rJ  )r  )rI  r   rJ  rN  s       r^   rF  zHandler._send_api_error  s    FWvtn$=yIr]   c                   	 t        j                  |dddd      j                  d      }t        |      t        kD  rd}d	}| j                  |       | j                  d
d       | j                  dt        t        |                   | j                  dd       | j                  dd       | j                  dd       | j                  dd       | j                  dd       | j                  dd       | j                  dd       |dk(  r| j                  dd       t        r| j                  dt               | j                          |r| j                  j                  |       y y # t        t        t
        f$ r d}d}Y Xw xY w)NFTr  )r  	allow_nan	sort_keysr  r   ri  s#   {"error":{"code":"internal_error"}}i  s'   {"error":{"code":"response_too_large"}}r  zapplication/json; charset=utf-8r`  rl  rm  r  r  r  r  r  r  r  r  Permissions-Policy(camera=(), microphone=(), geolocation=()r  r  r  r  z#Bearer realm="health-dashboard-api"X-Health-Synthetic-Instance)r%  r&  rN  	TypeErrorr   OverflowErrorr   MAX_API_RESPONSE_BYTESrv  rw  r   TEST_INSTANCE_IDrx  r  r+  )rI  r   r  rN  r  s        r^   r  zHandler._send_api_json  sx   
	:::"% fWo  t9--F=D6")JK)3s4y>:*5:.19=*F3*M: "L	
 	%'S	
 S=/1VW:<LMJJT" 3 :}5 	:F9D	:s   )E( (FFc                    	 |j                         }|xs% t        j                  t        |            d   xs d}| j                  ||||       y # t        $ r | j                  d       Y y w xY w)Nr]  r   zapplication/octet-stream)
read_bytesrd   rH  	mimetypes
guess_typer   r  )rI  r   r  r  rN  r  r   s          r^   r  zHandler._serve_file+  sw    	??$D
  *##CI.q1*) 	
 	xy9  	OOC 	s   A A-,A-Fr  c                  | j                  d       | j                  d|       | j                  dt        t        |                   | j                  dd       | j                  dd       | j                  dd	       | j                  d
d       | j                  dd       t        r| j                  dt               |r$|rdnd}	d| d| d|	 d}
| j                  d|
       |r| j                  dd| d       |r| j                  dd| d       | j                  ddt        |              | j                          |r| j                  j                  |       y y )Nr  r  r`  rl  rm  r  r  r  r  r  zstrict-originr  r  r  z'self'z'none'z-default-src 'none'; script-src 'self' 'nonce-z'; style-src 'self' 'nonce-z6'; img-src 'self' data:; font-src 'self'; connect-src zP; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'r  r  zhealth_csrf=z#; Path=/; HttpOnly; SameSite=Strictzhealth_browser_csrf=z); Path=/api/v1; HttpOnly; SameSite=Strictr  zinline; filename*=UTF-8'')	rv  rw  r   r   r  r   rx  r  r+  )rI  r  r  r  rN  rO  rP  rQ  r  connect_sourcepolicys              r^   r  zHandler._send_bytes>  s    	36)3s4y>:*519=*F3*O< "L	
 :<LM)5X8N,,17 3++0' 2-. /a	a  6?zl*MN &&'A&BBkl 	!%>uX>O#P	
 	JJT" r]   c                     y r  r\   )rI  formatargss      r^   log_messagezHandler.log_messager  s    r]   )NN)rJ  r^  rK  
str | NonerL  r  returnNoner  r  )r  bool)rN  r  r  r  )r   r   r  r   rN  r  r  r  )r   r^  rJ  r   rN  r  r  r  )r   r^  r  dict[str, object]rN  r  r  r  )
r   r   r  r   r  r  rN  r  r  r  )r  bytesr  r   r  r   rN  r  rO  r  rP  r  rQ  r  r  r  r  r  )r  r   r  objectr  r  )rX   rY   rZ   rH  rT  
do_OPTIONSdo_PUT	do_DELETEdo_PATCHdo_TRACE
do_CONNECTrY  r[  r  r  r  rX  rn  r  rF  r  r  r  r  __classcell__)rP  s   @r^   r:  r:  z  s\    #"	33 3 	3
 
3$
 %J F#I"H"H$J&%cJ

M^8tJ5XJ%#%#$5%#BF%#	%#N:: : !	:
 : 
:4 !!%15"2#2# 2# 	2#
 2# 2# 2# %/2# 2# 
2#hr]   r:  __main__zhealth dashboard file missingr(   zlocal Chart.js asset missing)r  r   )r   r   r{   r   r  r  r  )r   r   r{   r   r   r  r  r  )r   r   r  r  )r   r  r  Path | None)r   r^  r  ztuple[Path, str] | None)r   r   r   r   r  r^  )r   r   r   r   r  z tuple[int, int, str, str] | None)r   r   r  r  )r  r   r  r  )r  r   r  r  )r  r   r  r   r  r  )r   float | Noner  r   )r{   r   r   r  r  r  )r   r   r=  r  r  ztuple[bytes, str, str, str])r  r   )r_  dict[str, list[str]]r  ztuple[str, dict[str, int], str])r_  r  r  z$tuple[str, dict[str, int], str, str])r   r   r}  r^  rr  r  r  r   )r   r   r  r   )r   r   r  z	list[str])r_  r  r  ztuple[dict[str, Any], str])r_  r  r  r   r  tuple[dict[str, object], str])r_  r  r  r  r  )r  r  r  r  )r`  r   rc  zdict[str, int]rY  r   r  r  )r[   
__future__r   r   r   r%  r  re   rv   r   r   rk   	threadingr   r   r   r   http.cookiesr   r   http.serverr	   r
   pathlibr   typingr   urllib.parser   r   r   r   zoneinfor   dashboard_v5.read_apir   r   r   r   dashboard_v5.document_originalsr   r    dashboard_v5.supplement_contractr   !dashboard_v5.observation_contractr   r  r   r   r   r   r   r  r   r   r  r  r   r  	BIND_HOSTr^  	BIND_PORTrz  ru   r  r  r  ru  rt  r  ro  rp  r  r  r  r  rq  r  r  r   rc   r   maxr)  r   r  rw   RuntimeErrorr   r]  r  r  r  r  r  r(  r8  r  rM  r#  r   ORIGINAL_MIME_MAGICr   rS   __annotations__Lockr'  rT   r7  rU   r   r   rd   rW   r|   r   r   r   r   r   r   r   r   r   r  r  r  r#  r.  r3  r9  r;  rT  rJ  re  ru  r  r  r  r  r  r  r  r5  r8  r:  rX   r   
SystemExitserve_forever)r   s   0r^   <module>r     s   N "     	 	      . . 2 C   ; ;   V H \tyy{Y)L8 
zz~~+, 	)	*+335	 
 


bjj!89:BBD 
zz~~01 	.	/088:	 
 JJNN$D9x'/9:
 
') 
 JJNN2K@	

6?@	 (*?eCj	 {{}	 
KKM  % 	!('1-5444/6. (W,29m:v 2= 5 ; 5 ; 1 JJNN'D9223
 
')  ::>>"ErJPPR  
zz~~78 	5	67BBD	  
zz~~<= 	:	;<GGI	 
 "C

EuMNPTU  JJNNCDK  2<<.0@AFGG&&tF|';';'=>I
 	
 T5 0. Y  C

:EBCTJ      O, s3rzz~~DdKLcR  &  
 +,!# #Y^^
$&! &$inn& &( # (&	( y~~PW P22S ;?-7	.(0&:III%I8	66
6$U$ !O
O O !	O*11
1$1,)
)))" EJ 
06BdANRj" F	y$ yx z!!#899**335788I.8FFH {)s   ?AW