From 56c9d96f3d210f4b2ed91a53fa0296111d7d48b6 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 3 Feb 2026 13:39:37 +0100 Subject: [PATCH] Update Module Interaction Diagram (#6019) Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com> --- docs/docs/92-development/05-architecture.md | 12 +- .../woodpecker-architecture.dot | 157 ++++++++ .../woodpecker-architecture.png | Bin 62587 -> 0 bytes .../woodpecker-architecture.svg | 352 ++++++++++++++++++ flake.nix | 3 + 5 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 docs/docs/92-development/woodpecker-architecture.dot delete mode 100644 docs/docs/92-development/woodpecker-architecture.png create mode 100644 docs/docs/92-development/woodpecker-architecture.svg diff --git a/docs/docs/92-development/05-architecture.md b/docs/docs/92-development/05-architecture.md index b5ac422e6..556c595c9 100644 --- a/docs/docs/92-development/05-architecture.md +++ b/docs/docs/92-development/05-architecture.md @@ -1,8 +1,16 @@ # Architecture -## Package architecture +## Module Interactions -![Woodpecker architecture](./woodpecker-architecture.png) +![Woodpecker architecture](./woodpecker-architecture.svg) + + ## System architecture diff --git a/docs/docs/92-development/woodpecker-architecture.dot b/docs/docs/92-development/woodpecker-architecture.dot new file mode 100644 index 000000000..e72bede01 --- /dev/null +++ b/docs/docs/92-development/woodpecker-architecture.dot @@ -0,0 +1,157 @@ +digraph WoodpeckerArchitecture { + graph [ + rankdir=TB, + splines=ortho, + nodesep=0.5, + ranksep=0.8, + fontname="Helvetica" + ] + + node [ + shape=box, + style="rounded,filled", + fillcolor="#2b2b2b", + fontcolor="white", + fontname="Helvetica" + ] + + edge [ + color="#bdbdbd", + arrowsize=0.7 + ] + + /* ===================== UI ===================== */ + subgraph cluster_ui { + label="UI" + fillcolor="#c7efe9" + fontcolor="black" + style="rounded,filled" + + ui_web [label="web/"] + } + + /* ===================== SDK ===================== */ + subgraph cluster_sdk { + label="SDK (woodpecker-go)" + fillcolor="#e8f5e9" + fontcolor="black" + style="rounded,filled" + + sdk [label="woodpecker-go"] + } + + /* ===================== CLI ===================== */ + subgraph cluster_cli { + label="woodpecker-cli" + fillcolor="#bfe9e0" + fontcolor="black" + style="rounded,filled" + + cli_cmd [label="cmd/cli/"] + cli_core [label="cli/"] + } + + /* ===================== Agent ===================== */ + subgraph cluster_agent { + label="woodpecker-agent" + fillcolor="#ffe0c7" + fontcolor="black" + style="rounded,filled" + + agent_cmd [label="cmd/agent/"] + agent_core [label="agent/"] + } + + /* ===================== Pipelines ===================== */ + subgraph cluster_pipelines { + label="Pipelines" + fillcolor="#ffe8d6" + fontcolor="black" + style="rounded,filled" + + pipe_core [label="pipeline/"] + pipe_frontend [label="pipeline/frontend/\n(yaml)"] + pipe_backend [label="pipeline/backend/\n(exec engines)"] + } + + /* ===================== Server ===================== */ + subgraph cluster_server { + label="woodpecker-server" + fillcolor="#dbe9ff" + fontcolor="black" + style="rounded,filled" + + srv_cmd [label="cmd/server/"] + srv_router [label="server/router/"] + srv_api [label="server/api/"] + srv_grpc [label="server/rpc/"] + srv_queue [label="server/queue/"] + srv_pubsub [label="server/pubsub/"] + srv_store [label="server/store/"] + srv_model [label="server/model/"] + srv_forge [label="server/forge/"] + } + + /* ===================== Shared Libs ===================== */ + subgraph cluster_shared { + label="Shared Libs" + fillcolor="#eeeeee" + fontcolor="black" + style="rounded,filled" + + shared_util [label="shared/util/"] + shared_token [label="shared/token/"] + shared_http [label="shared/httputil/"] + shared_log [label="shared/logger/"] + } + + /* ===================== External ===================== */ + subgraph cluster_external { + label="External Systems" + style="rounded,dashed" + fontcolor="white" + + ext_scm [label="SCM Providers", shape=cloud] + ext_db [label="Database", shape=cylinder] + } + + /* ===================== Runtime Interactions ===================== */ + + /* UI */ + ui_web -> srv_router [xlabel="HTTP"] + ui_web -> srv_api [xlabel="REST API"] + + /* CLI */ + cli_cmd -> cli_core + cli_core -> sdk + sdk -> srv_api [xlabel="REST API"] + + /* Agent */ + agent_cmd -> agent_core + agent_core -> srv_grpc [xlabel="gRPC connect"] + agent_core -> srv_queue [xlabel="poll work"] + agent_core -> pipe_backend [xlabel="execute steps"] + + /* Pipelines */ + pipe_frontend -> pipe_core + pipe_core -> pipe_backend + + /* Server internal flow */ + srv_cmd -> srv_router + srv_router -> srv_api + srv_api -> srv_store + srv_api -> srv_pubsub + srv_api -> srv_queue + srv_grpc -> srv_queue + srv_store -> srv_model + + /* External integrations */ + srv_forge -> ext_scm [xlabel="SCM API"] + srv_store -> ext_db [xlabel="SQL"] + + /* Shared libs usage (consumer -> library) */ + srv_router -> shared_token + srv_api -> shared_http + srv_grpc -> shared_log + pipe_core -> shared_util +} diff --git a/docs/docs/92-development/woodpecker-architecture.png b/docs/docs/92-development/woodpecker-architecture.png deleted file mode 100644 index 22f6a054aeaa1914f3206932b88fd07ab8d69458..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62587 zcma&NXIN8F(=JRAQIIAAA|)UoARQ@E1Ja9tbP)(0L;)$%NkF>vE*~)~ z(2>vrNltv8_x-*<=f~OCzLLFX)|z$CJ+oH!we}=jOGAl-=ot|X4i1Tmvb;794gnGe z=brupe5^zlaXy5DgLj~%uB(8(y?2iQ`{@~${3E5-Gc@^AWP115!vCI&-DB8up+jf_ z+W>p^U{&Lb|KD}9;28G$e;fags#9pPdwhY()6SK&n<=;MzkOXuySD?Su)^ISF?gT^ zJWzaU=St1^6KolU+@3vNUB%iNJ3hdgno{_1HhqD?V6dpT!xmN+Zx5H3%PlPz=dShw z#V^(-$JYN2@9$b0UOcPJ=6tPywGUrhJefS-otryb85@S3z-I>rcejof{!CAtu8xh4 z4IgeyO~FRGPL_tD%L@aG`@2)USR_4jyF&vz{XOgZBgaSMr#&06?Lqij-_~?r-@>0i z3(%FWiS_o8<>u*$>6!C)7GID^}E)QIG4@6b5+!06i6 zuH3RZN8hl%;fb{Titd3?QF$$(nn7t@YiL4dWn-s;wpmPie#+0%PhP~oZs-l;`6+vM{VzHR$2R> z*-c$zyU5@S4FikuwyARHNMTFgjHcB_a6)eN@1y#T@wxSnjy}rojAmB1&1_stzOHS} z%-sD&Z111^h$)(w-FNr&p`xMPPW)M4&~?`HXFtF6W@nF`i&rBdYWBTDe@9nvP}EdX zNlW{jw@2hm`R{_%x{IlKJ4d%KPJzWEQ$BTdm9;}7^~ZBLO(H?Q1qCHR8M)IDSvEg& zrh-y;t4CAYpgk5#aY|E_Ue0Mw8!O}cKf1?*`A3>7FIwYLY;7lZ>yO_CR98=)xsY|U znr3HUQ;O3~TSEuu0jd8}NfV&42ODAmQk}M&*g4ZEf1VLG@@uQ7?9ZRV>>_GodM|t^4-}%=tD?#Hi%Q-@S7va2F&@XWwJ6jNS zI*&vO7klvYvK!9rHHcYM1;?if7fd{lg1SWFFdIkd?dL#{oa*6|H z8BU(~Woakg{ik1rr!7cm*D=VSKQNl^LsK&J{mz84gi5j?|KfXtV=d&@QO?AU3^9**-_oSe1rdrblLT;+JfZg`P#`4y zxEgel^C7vN$W`UTK8sz$%akn)?H@Upu`i;&A1dd<4y69(s^neGM=)e_S~(NBKH2al zvxe?MnooK~U+N5OJlWysxnR6@zO*_#_Nu883Fg)?kA7o3<~MZET@|HxTzQ*yHR_ar zP(ub^vzs;^hb{HBjQ&qQ<#-`n)AI8twXcK4hy>zU-}=)W++EcgCQyKF6e5PoQ}G|( zOq?UQT!`0LTDn6bomt^Da$5@VFS;VWqJ7>kqhF$Wd*L8K!fB>SP*wpXnneZr^f}*u ztkyx{q1rY1ph-TkMWjj^4&Us;CgK)4#|Nj$+xV}EPNoRg+WXYUY}PossRHi_m`E!c z%^&5|+te_#l-nH`+x{Uqi)j3G6^a~Rtw19BaiQ{BpUMJba9k=yXGOk@D)NTb{j;~Z z{y+9uBRF;B(>N_gcwW9O!V?td)T*QTX~rI-HCf|2%#&HDhDm!NYq2*iqu7MrJ> z-H+McpTI(E)F5v=@ZUV63Z53=zSuPhT>Y5;&s*LN9c1>X{4U&cGCTIIa`zastIYZR zX68H(UUz}_-=@qLcS4^V)P!GbvUt;+$kjo1=ip7`)27xwKcAlk-gi# zs+hWkIRm~ICo^*kb!YhiTql=VV*>8mSxdD(=J4ap9H{Okyh-NGEQt>%USU6?$qnz` zp3y9)0F{uu|K*;7M7&ytvX>3;!%B{xE5cVFBp0;V=Eg7oe9@$mB;tqE z997z1VVZ=#NC6mZeZcy7s)A%gHEmVSv(e%e&wm8F|7Mpkxee;c$UF@vnc7szl59;v zPYtByKYN2DdnKSc$)_kY$p?p8s}Ua>V?OBFxFI)N(A^<16&0h8akB9oXh?7xgmxTU zJwr6#iYOD6;a|mw5z}WzMFO9e;$|EW?ufRGM%;_Fy$)OdHzP2*vJqti2@-55*nCOg zGk^1^I2OyHzWA}KKBl^KK{szvQu{zHC^B3dikt!Df=Q=gt{+h`NZ`IL+eI0KWo=R=vf9=Un4efW@mUuKom+paF54UDn(cA&zs zK0uzni&VTyHyBny#!yeRCMu-93$vQ6@~#c~DL0sd&)oqn@<1_=sgo*ba&3i7=XXcu z1CboOg>`;oxx*at&){VA(Qtrn!N)TV{bJ>>S?Cdaxz5c%_m0MTEvu9ylMq@J$l6j} zYS}M1#J>E3?35r|Lh8dwEc$1F3li%7NUHgEZ4;GTS@gkU5$5LR)|6;1 zhAO(gUAC%YI_KWd4qJTj<)ubAnF7=~hUrVM4=a+BQusBh_x_jt7?PD=HxMOFS`@xq z0beL=ErDFZxAO1RP4h_naNQnxCb)kc?h&Q|4cseIpV2}<_OF|-IJ@Beeki$KKh#lk z6(oXh%gs>=-fVez&>woM3>oUO?W_Xu`J5(!E(`0no5~9@&mq~G^Dm?J*pZxnihu6$ zmF>0qr{-V;vEs$@LCJ{Hc|_Sv4u~opoU~Uotbm9}d5F}+f~X(K#e(=u`P%mDp2xQ? zv2gGoD|x7AY7X=!5r<1!9{Pm>mALRM72WoC5@dYVVpqnWo4r@Wk*8P)njRj9ERVKX zlyUz@#F7hYA0BsVbHtq7N`!;gpCdWzC{P>L-_bj+?xuAW@msl&K(_B=gLkWjja`6x zgGk=+LXitpo@=X{hHh$)+hyP z{-ICJ6uTz9Q*Ek>3^IYBLU=ISur`+WGdmG{!x+pmluf)axdlF{y|>gA6ExWzgdht! z`!xi}MLF($i1O_7%kbfmUN|wq{VX8=36&T`fzqFd5zcNTo+P|5L$JRWNu6w3a^Y@^ zQ{Fufk9w1)c|3Ka&Rek?If&{U5)=n=SVcM0LU*E+aD3B_?;G%wR>pd`KNlq9@0Zl6 zsb<8%F|bP8D`FjXWJmJk0zS1m(&Up7<^iK3&kJtL8%K)HxdZ;3li@{a9=mccgk<9l z`lS>YoiW))4k<&_34c7Z`BZ&;)*TdT37A_Uw|s>Y^E4MYp(f$WL0h*J4j$U;j|NFw z)BFsa$Tkbl2Ekk~AJjm{jkySw#(>a@TRyJSp~m;MuX(q3MpK4&iJ}oPZ|sPe?!L#U zzXGaX;LG?&;WQ(a!oaG1hwizsH^`bDt`xqk%4vu!wXX|&l32>JE1K)3ATPs4{rC!0 zXdQV0rca4SOJ915-0QBf9wBthG-vd`VZ(W9?TSO(U0;w( zm&~F*TsP!m7AD)JBX(VaVZ1|oz0N8awG`VP3H(iBwLlzcYT{F09F!#v`JC|@880O& zG4Z_&L;@{fAGcp~O~#JAO8E`I z$Y=$W1sVn);k-&equqzWnvGWYmkYjpu!;-1wb@02h%qoc-* zs4*&V3wNMpFn9D2QjT=o!!QWzDyvJj|f*Lo*&515eiqWSep>1V>T|%~5S9d?z>s#;h z|Kzd%#a0PMFrz}q*ggsu0@fkxgdfkLGI!x%SK;xorj|RzxkKXgOfuR%5s-gOFyT}i zlA8@~Nr-Pxn~b^iP?g;6ziU2}L!^iOTM4{MIZ@36Fp~JW6%|DK_y3A6zG>RhD4Wt~ z+=ineN(d~Gk~8kJAU?!YIZR$2IH5VHQ(=o*X_EQt_!TSC{jVs>7L|D+17V+Vdhu_v zZ-rxxDMalR6?cT8Aqt3e+jlFUDI4E5h$G5)$wg9B5jrmtBGJ4z@RL#yl40L5z51v$ z+J5{*%R^?~UH9KotLBOH@!n5GXI)(=KwS;Sy)ZkKbw&sYk9(O{ZSEQJKx>h8xIyAo zLoP)65ybAD2WI;T_36D*WsHwP2^}(OhP>!JD^@JCnOb}F`3j3dxEl0tg(5=9c8!eW z5`FaK(w(YQ2_srCx~D|rb#?DHqGX%W!Yb}KF85v`D14>y%P-q&p1Y1+qa1q#ESmGH zBCvJ9wNzt5n}llUeZEgVM;vx^zL`Ae)ls78>-#t?!-Rgw-&RnMV8BI%qU5GDPLoIt zW?Ja-h)8 zts-+gXlK-cV_1#!<}^1QF8GOm|D8~zV8&%kjBL_g3>V?aBt<&8Gxd;3yR*)+`d*Z01h0R9#r4EutS%fJZm0UvzX>aM~uOS>^AQaYVx>NGU>Bad41CWqc< z{M2bb0j;DjJQtyOLp?+}(|dBbGNPd)`?T*Yt&yAgR}YCq%9w?5Mu9-(1CbZA)vqRI zIK>EzjO;9RhzbBgxNkUlr~{b7nb*G~NZsI4o`rgv&)E=`-r{mu+0QILJYK#_ZOlp&rPj}8=Px^`a^bk(@8mrn;MQn}1Pw#p5)+s~D+N-m!HcW`S}i@%iF zlv(LS(+R};-?yUn@%cH!H>L#_eKw`(arz3Sle<|XQ9(*_EpkF=?Q{+{IqK;QW4R&| zQLQ}@kT7?sYI!Up5_7CmBI&P>Ysg!n(xoAp_Yze}Cf6}SM?|(cT+lnC#NmZ#Y@XAsV@Hdv%fl%0vsCrw_K=bW`+H^n3xGA z{$lqcPAzY63_I^t@8ASW6=d&38Ixs!Ifb~4bppZ@-nXyFN!hNCnSPnkL;xU@0BY?o zVI!GdNdWlw{?a+UGSaO&nO@bT{W2~prjB=xjoP$VamKmlx)b8KpAX0fdPzxLYec@E zMgB&p-7rt`jSN&sC%|^k{}wRIodSP=pT~gUWKz_Xr}<JeP zJois{Bk2dmoj>5}9n~56fv>w21iTSWuQHtn?APgq{LU53ZUc}L6ZRQ=QOBi`B3MFo)&Y>*&%SUVXvt=m9yHtD4$hX z%S`;JRB$e7_9P(j_Qp#sr4}*dq4A=#cXw9!MQag;YD#nKj0NSgN@;~mDgdE5GOtyn z)uHGg;MPD*cy`h`qv=rPq0uF$*r5Uc**jmJwpBQ!|37|UEX8unu$_Q+@_|y)O;Z@^ zXFfw%&7BIATQ3Z5kO1c7Fn$$-7ifk|#gYzy(^Pha!BdW6c<1@kI>?i@0X(S5@-HI< z-T3N$Kfs0Adt}{{K!8~AgvNGTJ4+Rk?PrpvIyCtQcz>iA0Zf5|UJHA!IAwd&`6{YH zg;?BvBR+-0i&i65A-3~?_l8E^mc<1H!OHbjdQh(;gKRX{C&Jf_pPMrfv{Pe zH&i6Pj1kZso4|D$z$2e@4<~$x*w7OFH9so9MxYAWb`+z?qWE30tM-Q-8`tC9D>DNXTn7F1<%+>S{pHmOZC@lmf>Q10R%938h>n^S z2;)mc{_(ilmkt&?YWX%%IemDLO}P<}wVYZV9WeYXmUj?xh=21HoR$J-ABpk-VSK08 zgrQr-H$qjh_g7{<$|K`OlRZRv19X3W%l-Pzs(s)e<1J@^Eu3xzy^M9rS+hxCB_jLD z23(4eqxY{}AN>}w{Cwn3bT*R^pSvN9+R=%P!))sM)U6g*?%OwqnSF1S%qV&c|uemTA>x0>d=SS9LJwJ ziNH!{sk`%mtp9Ql&Yl@5fucB{Ix(60%F@FRCnLfNu`%INhrr<37-npDPknx@#VJki z2{zO%51o{;BR+ctk$2e%-i(~*;oU>zZb!Q(7=i?WBBIlmz$l_s>&tL*Y!57ZHf}1I zuOq)4Qs-$;TWUhG9uGOpSMYegTp&X3bS!_|I(dt^FS*ZFUAMK=}529eaEAr+I? zR!))cP>5?{(C)BmuG8w!5^N4|u`RYp-fCv3+w+x8zI z7<&U;U89FLe>aD!dLewFIvks;2q<+oa%8omO~j=KmtK^$MI`pQwQ|CaT32skU%p_Y zin(jaqmREG=S@_~Jf5>IcoSQhAJ8(Zy~bOQg>uZjm_Y$1?07_~&f&)!mL90vWlJ8L zkhc8;^L8V@_SS4*4jd@%qhi(}DS_Q(sG%r9H0jn&eO(;a(koBY;fQt{<2rLM0sy+X zN%c!fS=u}&24QPtvPB=eiXZ9db+&OOJu20JJFaWe77+EKtz6-+yG(|2eyXlmaAq}U zlkUQMM1VVfWp!v%+u>7oaQ%834-SEe9PCSZMm4^7uSq-Va z&9s{O$R`dS=91B0Dlseajs8IS$r3yb631z#T~Z6zNZ+~YJ5G(pxV@HiHOReb`ev;_ z1&iVrt8V;)fk%$VcNZfkrxV}Oz$ZPs2t=EVxYW$96n0zWSm7lqH4b;~PeDRMaq&yT zn`cq;_qdB9%$v+|shexW*Ph%l?=_O><9m#c?6_elSuJR;b(RfD=8Xs3{aq-RKk7Pf_hYDt`nJ8NEkQ1p72GXWunpN1n|*8nOy;> z39^ki6tWwg-Tr5qq5$C|#+cLvf5S{7G%ePENNQYro*ZcXu+oB;d%6dZJ1b&H<{8n# zBReE=T4Y>8U)`dsyNL#<)A%Q+o)@}Oj5(x(QH_=6Zj(?)%%AtC^dDRAu#`x?Q-$b} zn8)p}^;PC%H00Rq{tyc>XMIdWF@=S7D_T%pTltC&J9TBydWPoMOsL5wx|OuMblU*CSv_-z*)r^y;p zye@>}B*SO(^X2%TeiBFnW8g?{M^sb9wopd@eUvt2&3h{9nnCk5s;y1d0khv0pAUKf zN}Pm&M$3}2aL*s=&NRPE9mS2OI*E|C{x0GCGydK)5(tMu4UW_r&+HW9E_}Oc))F18 zP*7{9{_}XNG)a-vsa0=K>I_kJM7W=#G|ATklIKJ%h<9>Lt@#-y-?Xu3qQ8E^pF^W& zAjIrHO)7QN9O<# zFrRb;1U&17EIp8LE#yjgfYah;$B$t)6gnB`BI+T1`*JJm=)oE2c_R8t z*carL!8!!~SowIU$x|)m^6X;-jhC15`6yynWYQMg`HsdQLlvc9+ zrGa^WI*IAE&GxHdk-wHYu7vn)oOj1CUmoqZv$wXP>vZrAh5X@|!*nOFjC?3` zCTc7j0?;1I_VKt-a>u?RfXKnh4ss<;VvJ@> zCijZ8hv+lPhH6draa-QcI=-0ax4-#ZBZgOY{Nv2EzDA5NFZPeSM5C#9T#XazEX|cl zQ`ls!)=JzUoeDdr8OduAfIIbKlyCJ_{_3QjUTRxf#Y;nhHi`C;sFBHPYu=y5iczYa zj}#YM9IbCZ*N==wQ6Bu}p6%G{r^Y$L8yA)6Zcd$0Q!{Az2{aXH+vL&KTTm(P=a#gb`S!Cl zuc-28QHYG(SVbvaaWP)K-s97L9cL!Lh@_YP<}@AuLHxK90mvYCVSfh>8G}xq?8nv( zcNe7Lg^1yZdnu3kzo!>$+Iu(mqg==?HDuH`Dc2#OMgvn!?50D_dU4=ui_( zU3ET4lz!;=&8zMm;Tv8lJ%U5=hhO82RlZaS;oEzCvG3wf4g?b(gUAxqH1%*Gcj7j( za(bLr@o7H|g0^@}{$7hvQ2gaIsXB-H>JAZ_t6;Q**NjYLTh|I8rI=Ee5*L1h-7=s@ z*S9D)x<^Ha3JM84lqCj9;r5 zPQtXdBPuJNJ*{ExT8;#H48M4C-X+h*oLNDpR6>7+EK#*6A<~MN38AgSO?|#NK>tW> zXAjJIz3GsX5KKJN`En=1TfvZVi%DKy83_QQki|f5cu~>_Z$#lQL%oU7&BCdgoRzsi z5q{n!_(DchX@#zYJIS%2Q%aGRN{iijtx2mo)kz9+bL*hX?%p&*n{R_DGn{6_JRUvw zzyb+;poxSTTf}FSa?(wJebdP)&gS7jQV22zCWZp|JzGay`M+U&i=D29_gGPoS`QH} zdpYx`riN`9Z-`gi=C<1gxNEshNT1le`tZ{v@qs|N^Ykn7$CR6VcKr5<{2>Hy&p$JL|=ryr1fF6>T1v4JQiC&-;yx(XFnZrpisD&K9Y7($N>?=dKAqQ@r2j( z-IidwM=16o{U(*jx26ZdzGPfKkhGDu-B1Ilt)H|Z>RW9OrS9U=^X~=ZpYza6c%yhS zIYQM8MsH|o0z0NLy&I$km`}&wW@3KE>sXw>x_I?;ECf=8o*@K~=|lCpvct$OcqkNj zyyjKw@MIq1s<+`azER`I6`{O(hY`(|Fhs#UmKDkXbZGpGx{=IC;&s;jT?A^{N$+TI z^1hj-|2GNI4qjZDVe2vKJd-VF)@BljSSmhwsni&aOezN}X?e-ol{c<`r;^D@ssC1a z?XsB)G!Px*Jokz~=Ck4IBuyUQfj7GK-X0D9;ZL+uGLEO)i{rHWl$8eHq zS~zdV-M)YVci$Q(SzTu9;WQDfT$bCze?gADoa2QIb)9?fgT0imLfzqNI0BDqKA=Ql zEpjuMjcuRkzn2Tcrz($Cbb)kRUCrc|+L#E$(6r9o-OV+-agbNt2b8=>d7nIEpC1kT zQpx>5Lfj!2E`By1`}zKNDP;X#JZj{L3~l0C)fOL%g~sjpAN*D8B&z2+unqp)Nj8zx zZ(sjFCeBEo%0_6R419?-4o$poJww- zo*!lm>YkJwrz>{%t?o+nHF7?6dDExHPRX0)GwpN|=(6IKt1*oV9qM9i6C{$SU!`G5 z|Ce4o8Kx*W*Ri2{DKv#m7v(K^{LTeO9JiTi%y^C`DVNK6T4dvaf+bb3E~@gU1;e8g z0;V8|YU?kV8sP#Fm0Kl>B^{P00E!a5DZ4VtbDAYkPvVuqrz1ZO#koJSxAtYSYTzD0 zCtJ=~(}SK`(xAW9PND^zihb=`JhcAldbmAoZ>APpW98aQO@=v5ocni=k3T(cY0E<~ z{!5?kmTADsITYgDvoq>+dw4)ooA>T@@w~q_zWAh_z$<#({Ex%+JLLSXub98Lx_~VmrLBllRk-5^(#&c_}DV7BrDj;-v1RcK_vn_7G_(3aU+fX4%P(iZp?r~m%iLF>XNT#KPpIX4EtjS=pK zTv-{}TM8x~Te~^GoZWAaldg}^n@f&9DFxttG?hncTYg;l@YsJ6tO%(S3Y-+a0oTDE zWmlG4$khZ=#_ggYA}!}TZ60F#G0V{B36j$9if>Y}nJ>Jni#gEIIG!GwXR`8nO`+F$ z$`>jEibYldwQtxHW2W!0&h&-Um0%o@iTl}l)#js1uPID5%=RIwSeNGj2}2jcI>5l1 zb>Dr>OgB@g#IKMyQET$o;y;ktxWZL@N6u7shS+ zf=@*+KsET!Fmx9X^+~Q@*wo<-f|dY#qpf42t)Wa8ww2iewAg5F((gkCr!f&75{(W| z@8faoKOd(rU9iHTE`9JV>VX}B?D)Njr;d~TGVa=+svc8R#y{877+67x2F&}?KZvVO zLW4b*K{Ktu5Hy~QB#I9bj}|U&e5MK!<(Msu|!tE!U^D(;hHIJ^1KoukW=S%)EE1ui=2wOx(1AVh!Trq17b?xEuGvjrVq zVZn<)788C&A=Fq6bW4&m$+g4*8j1*vpf~&OiL_L0psy9**3$W&56B11h803T9%<^8 zAh>~WTR;Y)oBFH-^9; zl4$Ex_hQKj8jn;#<%7TNi78{hw1Kh+`VoE1NoExqrh67%^SfoS*L{aHBOvC^p6fABvNt9D3 z=V#IOAiv`p?}mfBbGd4}-lhyPUx*AQwY}5cv$-yWz9eV3R{}-NfQ;lBl4+hWG3aZh z3>)J*hmwK1K)(&n0REK3glXky+#1noh?s!00H+&|C}pH`z#fw_szL`dloC|}1j#Vy zKgU5x?&oqRKe4j4o>s~l`MnW=3iv|%Rv!Y1Db7Cm&KKmk?efi;hddKI-q(Ga-aMsZ zpy_D)`=~!%=K3KSJn~a5kDdnq-KXQjxq4xE&U-2j;47lkr%}qD3c!ctW<=wU|J|N3 z{^_px66c!U*={>gcx#mvUVJql6q72gp@R3K&I3{l*X6{)UF^NCahH%aBf$OW# zfx#oaM=ejZvL>nz4Bty?%?UBJ*3~{ldkL4RwWEXjVGWeADnrk8mi$xv?`Via(H6(EbhM~lE%LUP@f~J9cpY6C8Lmrm z4#5WJ+cZr3BBBO(SPJ@@auMW1XXt|et{*H}x31DfCmnV`S1H%S&?fVpbMYX2FCdY{ z{wwZ7kNe{`)4DHq2Jw(|exgU?>v~P+-s1Oymj9Nf=^uv}CU8jDt3ssea&VMy82Ad&r#gO1R&c z*0m10A0I%ja3U;VxnteeA;0vvc< zWrb!RP*CubUZpZ9=#b&!-1GHr?xIPFbPA;vdNgPn1Dpnq0|oEye9q#6K9^u(CFmt6 zIEb0om_E--1jKVaA#xDk;5bVb2FAL7%>K$O?eSo(fgQ)pomN${gMRVKj-!O=(X#zK zCE-6O6K&g@4irRk7xXb@a~pXxz*BWAUl`ZEXjA{}EX=;RK|g)gK5$5LCZeqD(=W5X z-WyQghK9ugnpZ1iB~bGVvS?pEksc+9{g}UB+73;FQk({6{BW#eXi6ao-KN}lKP*EP zsJiGhyY}NfM7j*q2-ht0bhy;g(@W{J)c7BGQtRJbw=vJMru%A5yt4^y;W#YCbZ1=~ zVh!Ihx!m_wMA>L%xPJXKaw}9e6LRfT0sbhJ-CHwZbhP;4=?ZBHRQ7`GQAAXHT^_o; zo3KZUlckt%EV(PP^5qvk`?MWm8P{!`C?(swPdFkw&U3+c8Dx*3bTW(Ea?SO0NgXz zpWTU8-xb}V`%v+wVd%M`6n+U*;DQXzB=RS&!e4W+?p>JTv_Hl4mDsc$vqbv+#u+K8 zR<|%YC4ITRIRDz}M`pH5`|&KyIOW|*d^st5ft-!g8{V*@Q zQ}JA!WjcKWU7p`zi{auumT|@5bx9zMMUrsWd@?l{YNu{!x7$B! zgv%SX&{@3A-I}T*o_G@bva1jo(-Yz;f-nJ;K&^F0o{r!<+S5ETF}D83bOB64zD3e0 zA3s{~%P-pt>$ZT!gv3rrmK$OKxhluFa3IE4KXjeKy`iU*O&fC1Ec6I7jxta@4e5dT z#3JeRFlIW$Vp|LfhSygUAwTwQ?~JH>mDoMvkss8)=9<#}R9RBF*^NhNTt6#{7h)r4 zz{VY$e?mWy>F-;!b-q_EZUGIor({R>uK!USU@F_nuN0ZPUmwsd zIJs`^G4BL(ImaiwQP}vgFZw{^;mI(~Fe=Tf^C$T7wsZFPT!Om8kHL9yIwqC2J4&&G z&4!!Hc`MuBLLc-Q5f6e0N}$pex)4Zq@8-dcFY84D68ezltLrV-@TjFMxOniYIam3Y z^K8&LWhD&nQ&mnO+9EjfEZJ$Izu#JA=aawb0++_$&bk~o?gu9=n6Ya(tw^g2GCOvn z#C3m~Gm?;PLM&4#h1hA^P2JFz__x6A@R-jYa~%01!a%PJ83>ulZ-m0Z|0)=6Biin|N*iD1oYn@|^JL{Ec0y9;yFQ zOL)u8h+Sc|@Lmd?pUt9i`IE8-rY%UNta`Ti*Bo<{TFLfFWp<`he2J`8b$4)ReYmYHqXzz8a^wAbq@GDM-OwEo9ah_jwHYzkh zZH(Fw24$3pT_%!HK?5Qu?3?4dcddJO`Z*sGI}LlzeUbfY>@UMrjrn@F)t3W#{<@Qd&?y^JpyN3*hN4Fd zK&kwqAz`T9HV_Sq9q}9y&+$+iO1Zgw6DQ8EzZ$kkX|nX3PiE z)vKerZT4WvNMQR`e2T^6G0Yb4^#&kiMk8Z6uMX@MKWjj@& z^*p30Oz+*js<~b!B~N=>V9eVEeYCJ1U1U?+^~arAobJ;l1AMbMj#WAfJy58 zq6fYyr+hvhj~C^i-2ZYno?k)iNM+FOc}@@#>rW$F7#31$NG@8+@#Fgk;hKuq_729c z?3W!VsHi9kCQB9GMt&0#3EkNku^`|0_AQ4=d%6xLI{13leRA5$&2;BBu%OOLTk`HN z@~6;T~+OZ$H+1_RyxBTJfr17l|Lqurfs2Dgb4UkSHT+Zk{q_HhUEg z#{brv3Bu%O*V@QKq!F9Gn&Gs2PLeeg7OjYr)uGY0rcKWK<1t6PPf^#2-7?sTb>B{jND%nQA@Ol8>;aPV`yQV@k}!e~=^VUk z_^;k?It-i{hGyP~KtG!08F<^#U;S|JP*)BCZ50 z4}`yi9k5k}2pxNQsHx;c75CYD*I?)6B;n>R+h}uyW+)0SY zd<%olYLhys`x8|wtSk~JKhTc0*cHhhq{;!^#bb(`Oo?$lk%pDmtBdkMS&$>Dke#U2 z0yWXk^VLCZYoVsCLOf8}Jg`H!raSU>N4xvs9_FV*N9c%?YfA|q*$o%ZtVAxX95MDw z)VoYFs~}_NOjnOl(+vj@O<8)%9vjv3CLJuW1 zLEE^eu9lLr!@+fv*^HM4dU{^XkHBB7$FUSF?t0Zt0X>c_2!-3P^I^EqHIx)el#7QI zI1lnl*c0VJxhBHV`};3>0|CZfF>^m!z(*p|RC1FiIpwlY766iq%Ott9HvV5rJ7{RP z7r22WORO&n+0f<@&4z3U17pJhcnU%IR65`NVE)y2hNAn4EV0+aE#Y3UF&b9Tb2%a$iH$$M`U1~|BUqd(@WJOmf-0QeZy z3z%>+LjFQqG=Hp{$OC7bG+FWRFz_)1pGdEEhwkyA!@yIMz#_vvQMc)s1zRHOitUna zSuCE}Ts|VzhD*}<=&nR(1AO))T4Rl1r z#p-?PQA}zUEskT;*a{y^e_qUDfY?P5LWMyXQ2B$~)jlX(_GV70aW^-+UanB%wi$RL z#iI6hv%w!0o;YaOPV4>{Z7Pui)1S_@5^f#1i?b)Aoa5rIIe2m*VZ$mw-u2WR*Uyny zp7*i8oA(ZRumPgMM>YN()X7vmIyy2jF&TAx^#rBV6$V%Xl=nIA7XJn9$NUfwN3{xg z?^}6ViRS`+cJcx2=lwPx=07$aN6}{y&AWsynw(|fFTHs4m(w>?zg-4F6NCK}Y}ww?#Re$k+YH=G8Si;3r-vS==X zVjLtp1BfYa#2rdbE;oN2Ugq7R-=aL`W}O`RoAAQWhpF*s0pz*V)S2F|eMo7+c9S`V z;Vi&YGY`_}_7a2yI@dRz1IEdEw=?$0Nav}@DqUp1#I28K4@6!?q@rD(Rs=411z&p1 zk$LAA5!3iTMlA@kpbGG;=772uUy&z7<7%OkeM)uP_oL9kxv}ghr)DI>TJ|`Abp6Q? z3+I#6P|LptXJ*%4Z&i~Mg!jB(a`Z0AfZsjwF{!jO{*8ja$>eRA8H{Bu((jgjebU19 z{Fhtog9H^pV@h7ecyZ7#$6}b%!}I60Px@9U;9jqP7*VOO7vw+qT$F7TU7`R zMLNK#Bm+fcX%QbX(F=Ifaj7TpFZX(aX_2;7#gs786!eALE%q;GxU*?N^AU{wlqv$> zV9JB?%8A|Ki9hh%0V*o79u=P)xaaSK3Y5Z?`43gu`;F}v*6dLlyIU6dumj-mefY9ihn!&w}fvO6lc;w~z97!MUQKsr7AT@7y{ z)(U=$LBUd!i$L$!7vfV--s7I%Ud4jnm2?YmBWu2%0C`^^35!6Sk5)sv&t)t=T6?QA zQd#GSakrSAQ+-w)95#kj)jxA^bmb(l^n7`b-IDWt=BdgQ>>-%2+jE73{x0}x@dxYo z$9LjdEEm5&#;nyVBhBcfKiEEPdZlSXiTX;-hv-flsc3NA{Pfvlw3><;#XeRS;7|^$ zaDA}kj(lW!E3)!{f2Gku?3bHFeTuo#n8R=!n(X%}oNt2KX}|o0Rt*88%0c*&MPCGx z>=R}CaM2U}TRn-Iek*++!~fZ>W-M$**Y6&`+lTjfY=t_F_WU>US;P&|S>6 zd(V`NL&cxHCAgi6p_CAy+*wcKE&zUGdE3tVt( z>=EAhEMr(fZLW(07C)gkYb86gI;SHgHhueP`*?3hmb4CuEB>sCUkO}{7Ys9>{F*H! zHVqNJp)*`_^PBQ=Fa7G{df?tj5lyhh>NKU-EW;pqn19r$9g*sQbhpu;2>VdcGq1EWus#CYcqL_=H=*7L)^(q@;%okALiGjc6R}*s3y|9x8;$AMkvaIAH(%{E=1J(@4P&MU_l3t>6yTvP=l`MU ztK*vdzJLj76r>elBGTQ>KtQ^r5kX055Rl&J4(Voemmn!PX^<2)0f`X`GLR5P47R=d z{@(ZfJpVnn&N=sr7GnP67{QJLuL2pBWd{%5D5;^NpiZK&o}VutkZ5U36XZ$ja;bQv-Qy$3L+Qr2CtHRt#C4z$)S5I3_p~_t2o_V0?HC$C$GZ^w z)5|4Gskjik6d}jeh=XXv`NKe0J|Q8?vJEsa@XGJ}zx#ZY;8m46D1Wf;!M&j;jRdkC z^YiE^NkF3dGyVuVvVo~A!u5@$q*uN#zy|Lha0<5bKmJDNRWpAjb(i4Z+xMRp2wzh# zJ#vcF_!IlA``%vAOJu7b*>+8%*e{@r#Y;R|K=>sskn;Fb9eDNySn~kQ^ZdLIL^*EQ z*?_1!7{3ZtIw5}F>d=hQoPh@^BP@sadOH&*?H*Dq@%b#i0=>J47dxB`3C+Sqp_ulm!BdaxfIEby5=jcvOy_QoD8C5^ zYBPMSrc4!XRc|rBU9Nb+EWgocMmQ<23cT}`duChuPgmq&Z6t#ZnOT`!u^45SAW?)K z^uFNrYFO1lYWPbWy0PWUiK3tQ(tqfHU9M2+K;TChxQ-fvzR>8a{Uq*VcxK->J{Xb` zzbC>3OKS*AA1!wzxnzR5NlusyDznp?1mV9+T8 z5H06b_9C7xKMJ1rQ+gv!x*At${La6TH<=}7^OXGa2NrsRhB>5xc7DZr=+CZU6(QXG)ndAkYHzi&EOlk0eACH z#@0Ym;cjrh4d2h#rfCEfdp>_?zkd07rT2|FPCS`tIsEN~Vo}F~Vb2FnNi%6PLLWt! z7fvsj-vxcza7EcU)kBAoIMgIJV&Hr-cR=|%cWlrI*PY!|t7jk(U5Ry&u^XhfYul(i zk-3DTJ?-ly?Tn0J;{39I1cl)EV0b^5=cFA!k)E7e*K-RS!ak{>)12b8T8uDngS3iG z_Hg+fnhdiADIxdhHc1`VD$#qJ2D2>x!J-P^_BDGLo!_z6f=+zx0tZvL)I(n)c{Xl> z4mMhO(2;mBFm}zGM5>&tFUd48<3}D%O-*6@4)GC1&h{3~s>f!8LkD(ivM-OPezl3jxeP{u318B|yz$GM zt8mg(AjnjfME;fa#FnD_jV1CpXlQS)<^VUQpb90yL|0(fSr|}u?`yGA$?;Yu`C>1UK0LA-)X|7rmipBG?@h(YlI@RUBu$8Q zJ5WxP1LtxVGH@U-gbH*hyd3z!i~F3qo@a1QmW$SJ!R~zW8s6Hj5%E;qKpPX+}&LXrONIgD>xtB6vn9 z5A_j!aR04%E-H$`HS{jzq7ys`uM6A0z{}J?OU(1kJzt080c^qc-*U8!r+WiX-q{>i za@$^1K(Ie0!HaXiG-5$zy>W))y=Wp`%zE7cuCn?A&imkH-!$9d@yI76a8^ViU;Cu& zHvJ{?n0-bnOnzoP&*pVKlnTjniTjE6IZniuGa~`qrDA-;G1_pvJc=*f^L{m&1s#0> zUV7WIwP@Ay>=e&*W>5`7SZgwPr0UNCiJ!Qwr(kO<^NUV^MW2BseFxPbTPT; z&=%0}EvH@Y*X*7z4_$i@Dai3{_Qk4D|1d>xJ)Su8Q+P-!upAxVHBdztbm!&h@3*h5 z=P}%7IHCS&J<>j0el=)hbgaDNQ_GgaLlo-|v2{R+Z5?<*a!IAu4u%lLC1^W4tgR zM0M+Bx4s{!20Je{Kz9DUgy9bTUfY+3{%AtVtP6^4ZMDihL6U(9J?yCy`YON=ERwR1 zh1nTVmDh3-(MNb1Oy0icpU3Rtvzx4Cz|cDIvOf~&Wq?u;-SJb00dj0i*dsnhMT_x7 z6n^E7`&+(gYy{@qR&w3QhscJ%po#ok0otL<=iTM8LAywQM9Up<>SChv4r+hjh$!I) zHgx2>_klX~XQSo|Og?mP`tGcVzZu4#;;ZAPi}Yu7Z%j27Hz=0XV7KM1z>iGNTQer$ zqM=nR#Pc4Dix<1X$}7|&7eQ7zco#5(xmkXhi>8_N+%4X9^1}Y8tia0cb`WR7PTO3H z(0`lW5)2rYU<2Q>c{V zjHtv<{oaa1QU%nQ(3^Gvo???KD?mPIUy~o|a%zkH8alWGWPB3~q2oLpCyNK?_zN09 zmUS9rSBJ|2qE(Q(%r6tv{tuRXa1h^P?i`S?R|<(P8r1 zvPOvY5Gus!#qu!5er3*o_p%<80o|>uL+qvvl~T8%S%Z(p^;)sx=Ocm4_(>%?s|Nr( z_UVF5ras8~}*$+mAPrBCY zpw)zP!=b&08{_XYmtmh6cqK-5TzR1eLRmsc%^%9gacCt?ZY1P#a&R+YqSLs<s@#3DFRPMs&FLyl zMoX6kw{9Bx_9sBPV}Om|pSV|)-qff|_l5J6Tut^^tA(1Lc{-tO#78zIeadA zRMLk%6PrK+^6PMst=GiuiY!R*p=7+`kB&Yp46|nj&QB$J6L@1ho%T3lm12UIig==v z?Qh(`qDK=-@NQtqJ&~_;?0NouK0CxLE@D47ABcsJ@IAON!W#^m)4%~!99!VpGMeNS zdl&0Bdlg!u`}Jm+!}Wj~@)aSZcN=%bmIaEx^zlO=t@E}z^=D$`SD41eCk{@gxJ;wr zkHi6{(9Jg!+mZ@o3uL=tg_ns~3mm;OJ|1ce4J~yiGuugMu>8GU@!c|Mhue1hJy-R> zkZ-X0ubvP6zCl}$kpOfAP!!;AiZOM3XJAv!a+n0hf*Wyc_ktTN(*3!<3_#gXBC%5{ zoeSBu#@m}t8jr&$$aRwye%=igAbG2lEL_i%R#ZqTosl+EhW48#p*<(qy#I!vNTeTt zqPM#=!q6z4&*unLWG^4d>eQQYbn0V#Rg?9S5_2gb>WN~KVH(~(63=DGnM!C^kkpHC z5%rH!0(HxFFU$h^QpTIaEBL3ma>G936`9oUhst;f#DPq2yR&rfi=-w4IY z{oCJf{lqfYbfitCPc==ek%Tbty8@u-REhqTQO2ZP;>QQesT#hA;Ch7CW!TRfjiUHt z1m_Y&128E}-cHJw;1!0Qr<>4i8(44aex*bB={%Rv<`-CA;5px8EqB?ztT_9-V}wb| zpDc!4g1d3I>8W7c!P=D3L$j_e+^#R6Lgg9;M;+wCFO@TL5X;)}=#j*dZAItEyYpK>MA%ocT!e z=dr&@{H&<0AmRJ`j~;KGb#nL$#sYu2+7{L*$^=i|`)piBXb|2*c zd{YOZRSSw=iA;wM#n{2$iPR(Rg{PLlz^$$@s0+-_RK2@!czG=^Kptk%#>J`dNW7~! z_qIVzZf2laZcQ6`a`VXg1D?=<6fz6_$csC2Y0qR(l3t?yfpH7$nwe?yJ|<^xs2qaQ z=nb{@_jao$uyF8;xz%FDx3P1HehttHdBuHkN)LA2R^?T|` zrR@G_)54krzcJIKwX_)7d5S(LuRXWD=L8JLv0!*^mlaTmK!nVm1(3^Q%#vi6Rr`U+ zPn$^6fcQhQbb$$s0PiH^(_6&KuYan^oQBh&_<{^NAFY>#<%>F)zVx(&&k78HH;L8 zT5ZNYXXJj}_tV~t1Mg{)wy2(ZEN$wiu5a&8V)>xeRKr*v_Tand!X@_LZB_buaBCe< zBsR)QF1jK2lU}CKo2>Ti33*fT&N(3D*Sm^hZQZjVzt`nW+&aG?-IE(~yQOnMBNjat zlt*i>!n1VCyxOsPkxtT?3Wagw?bXGlbV)nC3D!SxlE=g$Kf9<#OZ;AVx|yd&==<)P zloC}#l4L-l)7e+bf14s%>L*{OICk$F|GLU?OblsxcAfB)#@g$zwv(cxbE(s zp>-FMIcwCY7nsX|U}e-E7x?K`wkI#rU-%CdlB$B8(Wz42@Vn zWg?$Qtqo=tSbXa90_dj|S`QEi8wzMRDPMS8?&!}Di-M)tZqX;yIL9=VgT_aGnTqnO zzc+!(L5rAm!))2(m7VcQ86cg7zDz=Au^WtQi-d8c&GR_!y!BD{t7vm72-OfQ13h&a z-uQ*0{_Wk~)WBMLrke^gEWF3RWtclQyz@`6GlPy_YBv03@y~8_Jl5g(5cIIVf?y-& z9|zs7Wyj|hG+B_COh+g^-OkQfzD7mjWFM;$;Ez_V#O9}J>l?yP4EFV-&-k8Yl*Kq+ zmJ5#cjOqKUJ(E_Y3twnjk&zmEEBO#ZrRd`I(e!idJ%)ayn(MiZ(h^C1w4fE7uACSIY#}=s(mM#P<$cSD}e(A$HwHhzY z(RvBof*5$+wa2vNVCiAY zCQ>L)AS`InnRCzYI-(A@l%$TK(NfUU>Z&%s51$jbu?s@M_uMiq?7|~0P)pBY&@GDx zy05LBB@S@f&@@KkP)3EU>96Ur@)3p4Lk%C?8$V@ay9A z?jPYEzZ5q5(axJrOHTnA^60m0M|XSS!cdiSvxVDdKh1HyLZzpZ7T`Iu;9hLxct_~j zJB)d9q*NYUq)#UAfVm%kg+P@wAsm-||H3Y4w}9C#+oiOZKozP*0U_oOdrt3>Jtj(% zULInTHZ3^wy1KUgS!CTqJ0j_zzA={kUl$jfJ-R!K-77?M1niPjwFL{V(wj>*E5q9! znFwhebDZ$($@>Ch;0a2A%0e9q2N(x=r&_;w|a z>DMsK!ipwYUqxmG6a;EO0@de^!4)9ofP|mvvPNfRZmsqnDGPUZE61E4xiAkRWocix zRY#s(+J^@|b-(I4wTUoM{d~Yz_|@YBvE4Zzh-L2Xpl78cD)6ifk&Vs(B-MdgvXp$` zUDH2;d%w}{USu#r6$hYwBl|P@CeDc8{KmOfkFr#JZ!II+bA6qDB_K7a_rVkEc2VfS z)}g=?oEbFZbkg)=3!*R-tTUf7*Y&{|*Z^3^-JUVK(Or!W-sb3CNt);wX7eEf`P{!J zWNuD|%ab%*w4Waqw!A)M-rX^I)1+ z9U2pYi{z7LdCR6L2bW2DSNKUt(myr4!xqG;6|{{L3iQ3!vVx^Ag=T?Y#+&2rVukYe zrXCtz73W1DfiuaUwsnMvGVl8pGEdVW!F})HILSI_rZJeR`g~Aa1H-Bvf2dX4ma5jp zB*FM$JtO8h&UKN%>F;a~1NBpe%R&IDq+)jZ8DCUS^vpuG-K+A-={<{2w6T@tC!B72 zID^TDbEpv|H#c+b0u!89A`-XbX1f+*fl3dOT6xfQUmRdmyzlgE*HHmr^>vJ}7fDxq zK@yZf0q%yd;^Blvn3rKl|+A6Tkt|j5{0<7 z_*NlYD1H3On}$SLu^4@PasYMc8rrM;;&&GXU~lAtyyxS5-38VRQPIO&_!jP0!L~QZ zoFwir10$WHk;Aq999I$;WUvsM2?KK?Zo3aE?SLfj^l$7GQ_yx>6e5eGB@l?hk`c~W zR%pBZ@B@`aNL+5S03+l31zLbzUChfD96mo1Z8z$5wvd;3&Nbtdd~5563Z_^rylkyY>X?um(xj>|&K5aM=r_ zh-*#@#5gGM^{|%J`O*~sD~5??cn(s|5;GPvp1Y#i2fA|dPHwc@#0hxXVD@56pw%eb z?`y4&RpuOU?{jZXDFYJ7u4lPQhsJarwL@u)DWR40$L@?)>~eVf1PT=Y074AMNz9%o+e)J@!5nYbyl*P( zY*54EsS91RF@t>TtHK}9d;{%s7}R_#*bWAcU1+a|77+0?!0mJoWqnAwJh!x>PJy|0F)r-av3+IE1s%U`s*7}1r`=TV>L(x%gx zonH2J&patc^I>YRFx*{|Z)G5NKix$N%Cc)+3t)nGnT&=8H(cSXkR=~#$KtVNOUTvH z((ThcaLozo-`{AM_tP)ajbNybh#e^^`X&-oev26Iy@P}n^MF6XXgUUHw(NEo-ly;y zXd~Ztnp$GaDT}MPwx_y0TEbB-d%@wK))W^!#Okr7MW&8k7pArtrKJQTo1G;a5AAR3 zoOOU?w0FKa&;rYz_d%IZ>>0=imKa;xd8T2 z-o@Z=kwWyxA1*~~ROnf0tk6F(@@s(xkUNjm)Y^AAkg1({S%EGjm4=bKUn@!MzH}`% zz}nnkgNy@eg{r&~whc4Z6Sh^S%C*Bh0h4I777XWAOEzOWB38`$fYW`1p?%2aYzMShX>5%_2yf{5IbL#B1EcBJi)?2MEPMeL z-qkouq|g#&CCIb*4~^g@8^Pa;;nc`IE+wf4XPkVtC!ED-LxAR(=H!W&XO1~g2F!EI zi;revhUj|sNSQG>Tz{Zf59n<(sHa7eokm`hhNwFdJSArmgrZ5Xlu57ruxLDP)mUZgj`PHN zthx5THn*J^FHbWgVC|&3FOT_UK0YXLbXVh%FRe5y=lgCZN)kyM1(CM)UBgu$rGdi_ znnif?-h#qP@A*RHh{Zn`jby$M;04XdwE(j4?(EKHtZp8ODfD+FG9Hukw9`x+h1c?A}awqOl}P&Ah@28J_6hjxo z8cLXB4#qP3Qo+Df*psB&MI~|uh3z&i6;5O;C#oAL=;UuM;4R#hrG3a&qEMyZ70g91wLEfNqEucAnn@kFI3L0?O*F9mNu zRbn|)3i|>36Et6)`hh~)AVJN_&L*&FMf(MnutDe^g|DFytJ-@ujZ!T-@x~EmX8T24 zof6#y@Ozbfw``wyOd#p~kgNRQs>ZTwl7e4rhJm?p=vZSg9=E5pPqj@f8RyFaqpRJJ z-r|V4J#wY6+exjb1>|(%l)c4o;6-}eH5-v9>%WtlM!v37jAx2TIy#=S89y`6!v4|; z$+#oc^4>)d&ou0bBhNh|t$guAdH#wZZ@?&GWMCpmXjWsehMbW0gW75SlrLQCq3P8j zNN+L3+;|ub;Ipz!m$JN9{K`+c;?WZFS^eniL{E?Ka6-SU9lzwU`3dSTMMV*LiB~p0 z?Dy``MWYh?>9?*zd=i#-+@jxy#~;-cN^{0tlN|k|K5Fek0}1572s1tq>!aJ|_i%4+q@nEo zn}m-HB)KpyYw8&i5o6ihou%4^5cBIJUL}GpIL$vW%dgg6+`7ee-<_Tn4qtCM)DyNs zj$f@c=w|#R7r%9L?J{qVpCfw7Emv{Ro=MU8zTU-&+(or@`^?mx)a#798xu{1$m46z zlgpMQ--9`zH@pQsqmG#+SE9a8qd`Pr%@9svTk|NJ-Z?8fZkdb%-*92vPw`r8a#@;D3zNeVL6B$tML(haZ4@Fk9Hm3BrGe%Qj46>K_BOWdEql-+wDs1+X zRjSo%%!gfIINH|c%6Rp=*_iR#!>+fWD|U8wym*z(KFOsf0wjS2V}a}CR<&2m_*9$`ph<29>uUe zue9;0rN!uL&Im(>JR_>{G#uiid6EK3IT^0ZM!G#kjz<7iPM-47zMGdf1}=c+3gQ*y zkDwMvSwCcH*Tq2X7x8af)9Gwm2HK=c-Cg1ZDKY-VZXJidDM)YO`V6%Jp?S-T=l5n9 zWZ!t!LCZm66uqP{vq*VEWGXdQs-iI)d2W|gTv+~II(oc1d8%W z_YXhIJgvm$I>`j>7q!j*mJ4WrY#R;pw;k$=11h*-Es zqEa}WRQ5L0pC1bFcMtuH0`@5>qq;5cnFDJ};WXL$m@s7j$_P=al6@nzHcGdXA>PA3 zG5L=%Fg1i_(dFxIOVh52yH}3bgP8$s!c>m7=8#iz>OGfVcORXw4uWJaDJsz}q?lu^ zvR%d_aH&P#^T=#=ET9fxahlVWbO)>OKoUyPP=htlRl_)$0i*l|E^}B=c+D46gn0kI zaXu90sKVH%w?0ei(6ifxQB+=hD6EK3Xpfn9-BpWKIB`m%F;aZXd6~#p@(y>ls{X9< zIg-pLIF~o`{Q@o)E!0eV<&Dt5mI~$5N*lM^>7%-{8$fs9c+({HE*z&G3rl~4n}n_? zK$y9PMAN7k8A&izc6)Wpfx(F}B;8Xs_F_*}EtBucS2fFfU2_g=C;sd-^YfrD0$CnC zoA-r9$14R;$qTXV$**(%0saYg9&<{La&kOmyTm+|-<@s>xVkFY3lDoQV~FYB9Dasu zWu^0Wm_f7$pHoPggi5Gpc-&vT5<^7Ketyz_BH8dzLjN&H>y(D+RFh*I=A* zDcZ9U*l(2k72iBu9i98pHQ&%u5n@#eA^o@zx^h;YrvlM%P{8Lak+AVrw>*? z@zD5N4i|ua1BV z)8V&p|DD48lYuX>nn(NeI+xRW!@Bz^Q`;Yt!x#M9n$P;kYfrkEn3=b{e`@zRz-ZQi zwW+hX^E?lJWa^m7iilmx58SY(N7Jt~bIj+%I-Gddm7-;U?@@Y_vgpIG;upa8LG0W0 zh%U5?LLrmYoGP02lX8(`3u2$^5 zHIe2)TuW6JV**yij;MP44-?A0jYFV~Uh({d46XIsH{vvk2C_Cu9eVi}7<_xal^jn~ zDhK)p1HB9epCb_tniz8zFt7jKtQ7ORJp*3H0F**C=zT=i zW&*%1WmgaIE(0_h%Se=aKtRrq%6)5PHydI_DTUL94QHun0V3^>rmexi{2hyY%iUKA zZz25u+NSz*(NbHfH9C=e*VQdk>4}D4Y6V{8PgACM=IEn##E;b>{;_Fa+6|n!%no$J zbK!F)K$l<0ZZ~CNmv@J6n%$dc zn0c_=sm>U!vZG(^^N25kqbfUS%)4u@k>DARqnIQ^E3rZaihq=a3f@_K)hR%q2IdTY z{>7<&MU-Fh3mnSP@kg@VoWIvXv0gHx3ncNOval*Ix~qW&61pU`|V$!(cJuR z1X{Iv+~Fs1ro=u(dCCCUt&}i|JZZH@wnib$yi*(OHwwop8g@^6h$40@SWKV-SFK2k zI$dKul-)McMH|Ch1C8SjR4i{@WX{*d3{%^?2ER=I!}*8$6_W%^QB^FmUF65l`mTW6 zclX9y+r%dZ&2BYOc97LFVJC+pc?;lBHhNCqk9ziF7CN3~)xRD=gm7*B#)p&`DkL`BTVNZ0{R)V)UI}j@Nqh_koJ0qDiW;*&GnwS)CMZL%t6jX zv(Q$r&yipt5Qs~a9i6+rhP0Ri&BJ!RHr{c`?6qwS!;eqfszGTa3iS}e=dIYeGVC1Q z7fsmR2v`R%23*8brkyJ=eyxX`A5`0|cn9b%v_8QYkoX{ZF!T$@ zkFcoDEG+lJvFZPs6=0{lgyajgaJp59`iQOb8`URwZ3_#&Rb@cVFROqgw0f#IVMQUf z<4mkc4=1Jy@gu_cT$3cFIYA5e7%f3?%7A~Ogly?AvjlF&?RSPQRkPn;MBgT^DOMF7StrQ-0n(062M{+Zmb`5 zPE%(0t1ej^xPP2xS8 z45SJ{0W6nfk726l_{HNqqu!XE`;w-9=P+%nw8l@yCV;Q@7YQ~L^v0w z3J1g&KfKAeaN2g*=qlJpxV>5kSo28xxz8*v7Da1h?y!9Wg-UCnXUf1I?e&wd^ZcDIA*qMT3Ok1Azh!`BMDT?=z7Q9J z+FQ+|K>#mig}BrBslU=x%)2qzR|+M1bH@$G3F#6YLF>51w7vDV4jg1=VDHP#xvi@ws0`vNhWh z>457C&y?L;Ej|x~b9RZs)}XJg%#YRnxiIu-C~_8Y?DB`C1tbjv@1`UY7t8tmDw3v; z6PvG@aj3fmo1)U$D$r8aYu7N%V`mOK$3J&k@cfr6`wnF%_?X(Es?u7z3S)fupbh~{=eoFr6^V_OhLCTXl0X35|mBy$KH_afADTvLCfKg;Dc5@ z2f!4T!9e-g=?}sGFBwAuvUJ6pI!e%Ddsr?L2^8n?e)ab7|1d$%q8sD3{|aXu#xjXX zXWvCJ-%_}X6u2m$py?=fPk4IAocja$h(<^wgv-AKWk)|X;Th*PVapOY7S~=5Qu*vK zjqO0Us@?Q=A#vG_I53$7bQT8Qw8EW?O%K#W9+K?!$Y*Cn89v!_VP65nVj2Nde+}Il zu`V4E)NKEknum@Ui?z(!&UD(Bm9LuW^SIVGKQ76Tl?9todnYNp=oBOA9m zd}RGBt_nH$(3|h0TvghMk46!*mvm6m%N<(J<|y6PfxVoxh@5kZjZ)Rmj$Bm@4Fl^G zmG*27#0Mmoj?qtH_k(!_ywBXiKr60{Em(yuqzhvg9H>+8G=8s9(s6;^xgC3tIm4Ci zCxvBSsSQ&c`Mj{{2RgBSsWhcgIxTdpwTA;#`#wd{BSNOUYE~vt z(w~SbFuv1Ge5Wm-2MACuuchD2ukLYqmnhIm?~DZJyqwSgmmL0a)c;6q}_4?a1| ztlwy#6|U>RR=#hwXDIBfd#Vpw^V}W8xDj0vjUXvuuLL@}>)CdQe7Dna#>iu6oS%>7@m&yTPZMDGG39vBsQH$iQ`!dro;x$j&IUNFbPGRe7LFDXem zl@nfaGu=|r2XiOHM}5C<1Vo1W4?<1vh}o(C&FyCTr-^1ny>#9$9yR^+@ZX&NU^7Xd zJRPN3p(#Hn2ly?D?$eK`!9R3&%m3_U&ofld$B?0U=Ub^z$JwYn`;WDYZ@4bryv>e0 zcx9&U-1FRn=T}l1di1msE6xA109eMFpt^suJ2AV&`YxXNXt;Az?4QiFcMM*O6H5ov&z2{21<&6GvI+!}wj|t>ZMpVf{g^0j(KsT+HI^`fIJ1JauASSWi9K7=!s| z)Al@CBUcJJM~u1=2w$vW(a3Q*8$^xL(x7XMFxMdYH++-}6s9;WEcvZBX+6rqR8GU9 zl5qj&+uGf08ysq}OWEJ4dz7%0lSfxI@Of>ON}eWJn&^GJInDXO{bslEE0u-q(-ezj z^GDy{bA@QcM7Z)Et`b`e^+UY2!f21D^YGMGJyLit{`VvO{(h}NNeF?KzWx9Xdo$zQ zqe9Q=!>NQBad72HXVcZzHc$pB@|~WgRDg_bthw$kWVq_g72f*a`KvEfY3VmN99C+t zC3JQ5yS@To@Av)BqcDL$;*(NH%eP6qCQIGCrLD+VUBL=w$DuVvL4!mzBX7y~Qne%> zR_WG(0LsBSn#etcz@sMYvx@t%KO2EEGJCixZ1I{+7Yq{9lBW;mXFU7@J~C9|nj;aV zAK@Vyt^=perp|-<+DL1<$_~Eo1($()_G;aOKYq{%7U*Vy(TI^yy*Gi=T$OtOb?<9n z8d+fwnc5MN;+#fR1nys}U8Nw)n| z+(N8%+P}boQH(4QoAhxJ@&twUbxJ@=JyoQ+OzX+yu-uMK!V@YcQ(Uf{urpr+IO20-?&fhA@INXP|dejqvOqb}~gdF7I1T2@J538wIics+t zizkfW-#sx%nbbJywid|!9<+o6?kcAdm=+0xgo(eJJZFBzu02mMxno@{#>tb$bzp*F zm1`IJ>Epy(f%v-`^aFf_6v_IgW#6y#GL#Ej51pIcMW#D2pm^AHEt*9r3!j8A;%Wi9 z+ek!?Uq_{eiD_`91U4?tUk*#3}5|j@cVv12d-aE zYV<48PLz!xH_-|=?XFY(>#w38#@^D@Tv}+;piU(*Y{a3pY8Z z*rZ{B%`YE*5rj?EE-h<~e$aFiP8@a6obPF%un}#gk)&U+<@~Ae+p~$xy=sH9;zFkh zYuE7~&<=M{wFNWmk*YS%XO+**fH${fC?Iv~-+{nZY}7%FRSWZ>KE|*m?DjO}`s-B? zR|a~A?1OgXptL3p2mG17i<;#|ah>|%6Z5=*#?eK#+?b;iZ7o2%c3n8F$z_b zA${(LG1Q+En;+4IHJa)ttUJZF>Hf_z!a!XBybv5Hx)DNxs_iH^<@*2d5b zx`)oa`p;y=-uh9$!zvbnEl?0F3#(>12t^>?$nv~gVeoqWj_cpJDlnb8vLHaus$tAw z&)}kGBEpgl;3XHY$5Txf|T4)22@cm`jS)^2_>^# zjXyTWP$pE3WE|b= z@6t7z7Gc!+S!_v}=^D8`7h!!nZkq_FIgqC*Job89hh+v5e!=cPzsLHv7UWE&Tv5;n zZf&c=R%y0vcetR&7eU#;=!h$L6_^ZVXS#UKnEw=eu-gAwDAbJRabtju0I|-bQ@O#b zCO`cqt}6Aq(IAR3nPS`MmlnxRRsAiG(5Agpv;q`Vj5@!`LOnmX?2meE5^U_g>OI}L zL>|*Z-DSFlS>9Z zV`PcnvvR1hQ-A%-A2v}oA2aaYasfR=Mpg#O0U)NIgJ4D&NI&X_A> zf(Wb%Ea{JY`+lqKF{+oB5C|JO^mO+>VQNjTKBIg1#e!U|!~E^vri*7S$4rF>Jk`#< zOI=7!kiugW=ZT<-8VYx3X%Bi1?cumm*vrvZo%n@!b~_pJyP_X$llkiK8ezb7`?rc13Jx_}r!q;M3%$ zN7h680U@ntd9AN+e#U0?fH8*!jj~PP+p(PRJ@4X?N*nI>@Po}BkO=`Q3t486U{y^j zMe(MCFIuYbmn>e00JtSf#3Y|(nnkzo#89)!SDH2s6h959G6Pn@5zHgj6XhrD233uq zxrA!$gaKnhkU5Z!`O&C822)b9AoaI+p|i&3TsHpNoh;8=0G}`r$6EQ8@oe;Iz4Hsk zA8+XjS;PkndRFt^;T8!>bBf{>bZ#4Q0HN6xOq8fHpru0zM#DXi%I3{O!F< zjp&k**pME2jd%8~TlfT$OGO4XjH6_Mq%WBtCe4|9&fhct#0Dx=@O0!+6$|Rj#+VLc zD7(-IkdwLhu#}?0bc#A`Jw*Yb^BP67Svh7~U;3B+QWf(DW;k z&JbfqYylkpQ~Dq$NlL31&8jb7BxEHy2#3tj6aBUC>9I-}IHVNOp8gmx2dxk|&(RQSKZB!8tb!qF@X zleA#p3ICkdYf)tKw!;*=h!J|7xm{PNruL!PX6{tR<+MmQBHq>^%2aZEo>hTn>wUFG z`zJMC<~l)6Y;(gaG_2k~Ci?~zwGI3tiQL--WMtw+I6Pflx{**6g{<3_FfLouMu`-^ zKjHL2b(hxI9NAT)p$Vcr^yfgG%r5le@W^-AW^PMCLj*cmaVr`+22UTqf5T#M1w+VN zdP9EX(Ja)1UvK_S&i~XOBuCKHiAP6B0Y(s1eML2Q=`V`3bIZr=`EMfUG+vt6mY|p3 z=`fqH+3?IPoAgM*lb)p*5UKTmQ^t#LN4u`rp3%>1DkdI5PLU{Dx(--Ct7HEjl~_TbH`(5r-*yR-*ycYBLOOB<5j!WB1p|Ata*6=!+Pa2^;1UW z_KvJx?C4^^1}Wq~q?O_5w|O;4g7i)mR!wYfActVUDthW_kHejFW0lEvgn+;V4b3N_<-y2f`JajrP*xB^aa+CYsy#$ z=4(dqM&RC37A!Q%9R?f2NmrvrUti4uq>HX6U4X|^?S37@8tW)h2s_rJfNhaYq%BdUo+RcvO{q`*c^H>{eTd`s@OVv#=&Gy4xr zIogu2-*IC`=jip7*V+SWXHV{yAvChX3aJLu0p2Juv>CX@V+2VbPCGjp-!mhy+x>OB z7kFw4@Q;|2UcCQ=Dk9HO#jvcdV@Z7#-@nyLOP8Vz4$-Woi0m*g=|VB`y-@M-$9ZRx z04#1}X5JjmqKKY;JO-?&>iM%=VelDa{o_ZHa?vO>LQ%yNzyGJ@-N*MV;7tWo4KI(5 zN{Amme9+&phipF&+mFG|(-D%MTSJ<5CMy1=q@9_C|1p5E7Vzxod+@guuyNK+8ypt* zqcfu#B%AX0;=q=TwY7gKdzo9AuR{zhzj(;(dK43JQoXpzO1x* zf%DXewD@#PQXP_>oOaflEh9>uwq4YL7>vtt*GVPBSPYJ(nDanBjFa;uSzp-?6=4bM zstPXcJRnpN?LD`=bs_q{mZTrP6%L_G(q)r!gu#Xa;=)E|(}ckC%Ew5){sSu^g08wK z!I1U#ZiHdQd>gZDi}K+Fcg{pT_~uYBh+Y*!RMs0Yr&p!q1#nCK!jkptmmK7>p2}p zB*}w;g?e|PvkQz%`ZOAn&vvJWmrnCP**oYOK1HVwI9a)SW+X=lPFMnV6o2~|Y#SVCf}d7jco0^rLlFN!JQ&Bl1*g6YNI5Kw`rSu&ls zg~BgBrAygzIAN?f3^ag(ru+$yd<%&Cu3&@%YH*k1q&stM+8C8Lew*{}_T!)qnl2L& zI4~Ahte7_90bcmvhy zVR$1sJ!+r~$ZG5qZl@vF+wfibzBQwwt>u25nzR~=r%_+fg0hZ~i8|2NMOcHXQ%A(J z#){~8>i2D?%wEaHlpT{T;-l(cbz;Q7&VIHoB3s}}aL{L)=`Tfd0t9a{|80wiyr0^IsJatRKo#L2>JTeh2DrD&P;w0(GKs>hOAlnvjj1j|N8 zCwb7?XfCI&E-Px_-cC@o_W~oe%le_=m4L@!j3X{%k|5U zeXxx)>%@aGR35JcYoHF)cdE1>+~|zx3I;4I0J>ytj5y6~CJ&`5X9c{x|2+$PefEv0 zu#SkSUwZZ(Q6Ef4l1$BLMlN*tZ^+RnaEQ=|?q}830H>A~vEZ=;-WoAtpF|F6%6>N{q>eXD@UwH=9x*EmdBLSseZ6W4x% zU$)RKGM{@-E0Koxu&%4HCidkFCBD3q7JJC3;=?Yw=C3Z(;qd8it2_JzLqIY^fHGP* zQCIjX~8?U>}D{tdizO^-5V>YAb0ij-m@>7 zV}^0F)3d$m2+CSm(XO1@OYERz-*_SBMVZ{lX>UUXZ6vw;**-(rKP}AVu6QIA5i-ny z9goW|yj{(8z&p3-|FT}x*`gFP`WE{lmYs0`?7c`IS1tbRC@>17uTEoM+{q{Y{S`Hi zN|}aaXLO!pOA3Kool*s4gxP2iHxy-+`>3ACo0~FE{W@KiyI7#;HEhhHjsmye0GdML z1!iWWrSu;oY#Yj9$mon5Q_^3nxW?HGuooSjhWd<5G6HaAXt=X~Q^$2vfXzS~DU~Hj zyj`zwvdPmqqArn{lkTq$Ee>&05KZmXOHn!FhNz1UETTtenTr%lh+{)TQH&~o6SSN< z(SHU7Z3s#BNq&8V;dvwYIOsFU|GW%-W_TYLX>#&HIOJYI4X>_>4>=uFQA{B&YaP@2FRoB+nP*g^gX>Nt<2I-`eJR`m>mtQFUc#1;5 z9X6~Fm3i>lhM!a)5Fd#5m?uj&`gMQp=!M1Qj1aPZ3NneF^h znHDwOcL|Y6E_P&b4(s#Qg#{$URlxI0#sW3*5&|nTGpmqid6S zt}(tkDIBhrMVN)NSM-!cE?Bz98G2RUtjoBF^||3JN8BBhJT?UkU7$*2(r++K z8)Ci_F1_C|^3if2TSD7O?MVGuo3&WKY@U>bRevUj46%(^A5Tv)SB2QE+dQoR9F9y$ zq<(PpP-XMBs9{)_`s&Sb7=HhpH6Tf@b-_D^mWB$6{FZ@E6C{z;`3k%C_L4v?SCuOt z!5Da_E&BI{MA16hcZ`Gxk4s;7`|=*e zq}tE?}L_mAN=%4{~2<9eDtH}{p$g8ZAgZjca6ZLQ|m}E8F6?Zgst#LamLmVg$u}4rQb&Z|d9Aw8aJs z0nsafp!=~F=gjX#I!`#vZY(M6{g-?qCRyo1CgnVD=tv@~mWc?Ji{u(JMH)6GE!}7K`PRb+6!(%J_dg)bTaZd?f32yrc0p^B3skTI z4Tx@>C;;I~iEl6VN?6ZZKqisQl(K@Vvl6O_IrRLzl+KMNrto=TN~Z~f;U^rC4RjQz z?hluL%3?|WMoffJgvzrrz)iazW@Oz^DVy-8__<(*E#vu!!}ZVX z_sLx|&iakW-P*fXMT?1xbs^;CX*HaunShcwMU(xD$OL+R*Ndt)Zrk+pFuMD*x(e3> z^Fod7XZg7~70VD`kx44#L-r3$%MgRneZ4G{9CpUm1~W8Se^Y8VV|3W^J>SR@sLe#E z>}v;izOm-SC-bUmRCfCtKYx>hHA&CBqXAa5l=NRz3A2OxpqkbLZ^ON559WQiYiTL! z5#pxUI*|;5QtSE1?cGi`lYef|Wf~>TKSPfgct7UKc-GuLynF48R=vbh`gK{mKj$0y z?=^DCN(2fm27rB*=+o$Ps6?#b#CREeJr7xM?G}=aLO_AbQ5MFl{Ut)^+ATu+>x#m@ z;$PPdRDWHf!09YoPq6mrk4bzQboeB+TMQmHf||zA3eic^cB#JL{$iFR!s$kMT0StF zFGXSrs>}krtdH8FgP*iCnr1P)T38Tx|C0LqZOZ3;u|Nn_C(|2vlke@#u zHzVdZ3btaY>PVi$!m@j`cSR-$Cn8en*QgH(U0}T1RAeI3KqR)>NF+w zn6w0mo0Xz}P@iE^yDUPhR?4tY;P-Zi!%Jpp7WtAPGM^NC-tvXJ0bLe9DQ?T@^eXJ(M&cQ{iC_{+cv(+2A6^n;sWc zuXzQi29WNZxxk13K0f?w?4JFtS0>>OQT}&z>FyY?t<$n<`F3Y9=0k^XpDa_f&|d-3 z6xNToB+g&+u!}4vmZGOZBowa>gw9G|Xw0R4GBFhXBWG<&|Bu9ga4lA}V#8zY z>(cMH9y3yfI|b$L^Zx4R?BikFQ=z?iW9gHy zp00gxALXV%(bXOcHIDXG9+ieT@U1Z@E6?G)fu4Pc^?5n?2TMX;$$atEgw*rhdkp?% zYzn11LifUgWW#5R`nqvZMT9e$vF*wDkJ0!7><&X(JAJePjoWtc@6GZ8n-1^hKI)x6 zADK1{EPb=&|IpVG?|E%a~ne|VPP%OU(&%rmd*Rn@AS_G<#4uJU%`vj+t2*g zCMWyeE9ny|Oi6alWk6b)gJjmRW|$GwdVx?!qmc@B1(zTkTVsHz)9BrCRNF=n#5pf5 z=OsH{V*;^aixJYF2eOO-cAE-P!-vOWzYUef|2Q-^Kl4uoCoM9oKUJWZ&vJh->+Px4 zxY+AzX>tFHDQVgphH2g@XmTJ|3mV4)R+0pneN-i1!M(UK(z?ua1*stEnFJQ4_~i|_ z`!g{YrFeh@Ne`yKNY9ZcC+>WVX((B&!|iPZR1BJrQey!y?5#sTaY>s3o2|6}u~^veXG^*v}_t?vM)j@1k;W4or_JQ5!x5tusXYW}^=KK+$; zH9F0>Yg118thQnhF$RCNilm&&4z1zC0$4NGF#vnWQh|CLR4(CJB(hl7{02nvm~^Fk z*p>o8-`TKT&kc3Ol05Q>LDZI*=?yHd&Z;u^+GlIA2(m<$jNM^PGCo*e%=Qk zq37B2qFxoG(^pXyfm=ZYoYKS3Aqvz>U#)o1CD~xSnmQ-JG=mhePKEQRM(7-nzfOM9 zmv>m|HhO-L&U22o@VlHO&@b7n74lgsB&f6e!nwnq~CX^$J zneW7=Z$vUk$Y0Hgm0vS32-BdL-%1*MMqL>h4>le(%#|S_ey7*dD{Ukn7eBh@pIl${ zHFPVjUOpX1&3^^s?~e_}JX++&0`qQIbTIA*BH?d}-=*jlD9*F(%RSD{nC!wh)S$wcx9wElki)DT{&_@<8_5j>Ij@X)a=U4X`Rng zm?u|&J10H{7~CZQOfUZ07L)_%HYJ>b-o9++?7YMpRE0Rap~KJ9M!)8C+mbXF^XqCc zI9@>#CZovkNC+!cPVS6frG{Bj{Dje0+KkMyc8DD#6Ba7&BxdfZY6XQ`uQ=}*?iGffamln_PkRF&5b0`s~Ae`EVbd z*a{UJk0))yUmmy;aXP0y`zeHYO_ptRoLePg>4Vx5gDLbv`)GmDu)c{{nXt^yMg25- z{QY(Hppno3Qto({2$u-*EKS(?Gon`o9#raIi1yNZ{5g8hCymTXY?FEHN+sR0Wi*5|DogTFMg1$yzH)NF!*<7UG#%6(< zhel&b=hOr_gLy1l8|#WgTFzdSWTsNdZ#HF2kQJsF8iUm@DttXnLpLxbFQz@s)}`uO zOo-W2R}mC__%R2Z{AvuBj^5Ke+31mvN76##GTv+ipGMMF>Wh^v=6&u55M%H*YVAAU zA=>rYpG&^lKaIcRYNuxET6>e)G9`pNU1x(yeDvFoK9f(`8djVr^<$7j?Nej8Y>JQH|As3Jym@gbH*Mi_ zZJX1D;=w{HUc%^+Xg!wX7&o%=8#C%~s_ZLz*^tI(cyPt=^#;EGk^tS)_FBKOq;1V( z?i9K1)7Fnf68W%q|J}%+dwUu#{JsvwpD8|Hv#1#NZU{KT^GPitBwi1gs%j)IN!LLF ze-Gz;+gPxI+m|#9k^zhz6kB;c@$4d#1u5$gk zx_sXl-h^C1{m9umC4Ur#q_X@<__cqhjF>}Db(sO&HtvjWk7K>67ziIhqXBe;yu<=i zo(ZeHe7KbqbSGj3yy{$&3C1h&aBuSB+$xA6ek?D2Z~RlCUOy*Jsf?IHk-Vt$DN2+< z-z{UO>4#i{{Y+AqZ4bc4HBVO%0^^c;O`Zla3fX`^aZeM0>sv(F=Ih;4dn45Flrf}O zxiM)3wOP%TU8%FScBw{njiI|CFk<2q|GbLjtV^~l`#b%89@5{6H;apXUr&y263|q| z#HazFzWWn7%zKlGYnf6t(8tHgNBRVxAM>W9QX4{VYA6bRt|QgDo4Z1AmExl?O5T_@ ztDpYWd^nAcaAJTf1+OV<3>Tq6?^4N`5oJ%dzfZ23!KF_BV$_x@-d6;A4f0A4QC}io z(%_sSs+-%gU3hxpaMl#Etvwv8QN$vvbRvRKwQs^MuzgmD&c>);FNWKjdfb6nCLp^;6FSIW~PS@SPvE&O;* zo=*i4SaXX%q0N9Wtf2iR92JN2S_|1e&b-^>R)p~{HBR13f%7=1HwS(t{D5j~v%hHx03qX}q#RDX?^hx>~~TD!%Ny3uKz z5anlfwNLd^KlAw4~cwD|QH7C^~GdMtO3+^~)b&$0b(9YkG^!n#0 z3Zq4OV|x%t+P=4$s+5!O@awfmoPtF)9>6d{XF)X-nFiOq0fbHxnQ-m4Cdf(j8R+_B zv!?#f{vS#Hoa?Ag0cJAUOETHF4diTV#Qv~H)8K|rG=f2<{K~3T)3DD56~ygH4dpxB zTf`)J=~(jNGPrSJ9z%kPngBX&`-@zjp z6f#=VTM$mD9a&Z2hueWiJ`5ixsSM>@!}zRKJIE4O8>k`C5zkTbb9(agKLpDUfVrzi z#NQ}lwDiEg$4VTckeopn?tV@%;%udJz{nSzEIW!y;(DpYBj4l0TwHY;^G>Z$?3jw}X1+ZHS__^HG*PghsvJ~=2K zB|qeY?dwFc524euG=@-jF0*tkU-fy@)xPM){ZDevx=pA0Xg-QhDy{@Q?X!EB9gFT^ z1$C()g24W+myU;hS`^Wn|2gprF#20}Mt~ai7KYEH1rrith~Hv~m+`^Z&*5!PtB5=^ zU*7+yM%@~6cyJHT?q|;kwj{HG%*3|3O{YnR%j=R7BA~EK4i$7&>kO2GIChw2`PY6z zLIOhP4;`pPCVta?Fk^dQPj(aoo|BUcO8YEK3+)QNK%k?DPojuRjs-|E<+6`Bn8bSD z^}732uq$R+e-wDcm!b;z?JwXxWN+ld!HJKgv4yoGy(?8}r1iB0=Q=#jyMK+_j|OCF zxrv@;)`NfUC%o2rn|VRTH6N}F3DOP!D*gckf3ybIY{@@eYHZswTfMtyL_GbxZuQ?C zMK+DpWGh^gywO*w284iNf(AUWU&EL2Fu2Q#Pa1-J_DJLWx}Qefyp)1+rDig1qN8D9Dix0n1otf5rrKeLcirr|B31F<>zkM{ci(faT~v;vu{ zL{2)q=DobgdzIAd^iWkH@=px(%8Lecx^Ad?eS#7nLwq`dtdyFZ+v3QFi~Nrn@CC<< zDv+q~qtP%8$MXj8BG1t`i%7SxMKs_BmRAOcxi*BmaU+R{hcee#+YI1$T4Zvdb<$kY zR2>GAWQa9XgwlNNGX!2eF}UI08OjhvoL21Y3ky4g4->wqj%o&v=T>&{Gob|$p>;kr z^KS#@J|fLJXkL?nUY)DxG96%Ah%Q`MgdvE@8qcDh5rsikT$wpC&Jbc zddOtks|84{0BswH8ud8t*17eX&wPE~P;siHSJQ^1bmGW#5x~7J_%{+IbNWgZsM>N} zy?ciSZ2d*KUJ?dPKLc~iC)B`-D+~Nzgci%iSrSx%)~oU_*QL#!IA>VO^D-a0@JM*Nc9Gk`6XiTS`W{jJo~wP@CuXas!A zWpvnnk{aUa`IAPMk5oC>@U+nv8zSYjDp?tGzg(8ji%HH}`NR}$u|tWt)Bh+@A!Lu| zPuK}n7}}IGqgMBkaI8uA8S7@V%v$vy9R-58h%Ch^b@%LUD((6#;TZuQQM=(9qLGV?XhZbLVsYh|z;n$xo<Vl-0g!ie{UuR(BFG0CmgA$4BHEDNF4 z(DpMLGnxITVfhgV#hVVZbSK!OxN%6Lkp6kKL@^_GaInz!P^b%^V@Z5`(+P~gzP=a6 z5BZ|-Na+&^mr_~CN~d8$sDu3fNkEnqgouS?gS;=yjKaQRm=)Ttlqy1v>E2aFFEDa7 zM|uy*CUCHVtzX2Olo-4)urvOyRAanQV~TgbaWqD5F!)~+-K_?ff=rFqGfDuVyrOos zOIf?pxIFAz!~>m@POjHk#P&QSro<`!nRgPM^d^l<7O}VpW{MdLz9a?d!N>bm zg+41lCFdDAqH7d5dP=QLY>-^+MaAzZO^&3XAlZKqYY(zOX zAyBKNMb*MMioCtjmWM%yhBve&dp}T1Aaj=`ULQZS$|P!CJxh(=#0-vYab5Oz__nfK z4183W{E@$Q@W{LoX#V5vTqYd&pN7Kb8^_J~5^O&Ek&7YlqVmJ$F7os)=x{ZQI5@Jt z3dPmIdA`l-)X5D!`lmrbwaxBu5q$UNq`MZX>NJ&3WXWgu?am*s!T~a&^^S9d&dZ3oExA_1QYI z-Ek8~y&@g}Luh|>(#H?o&5XhmK`0fHt>iz1Jnzl)&777QxA(wsw@-=BUefGK>^nJ`uG4_VIN zHSZ%D=LJG{_YM^|{W1qItVg*+Bm!`_siAN4l3C+_ayXzUjgYS$-`SuoM{WruEgz|cG@_4+CLU$pTQgu}w|@6O5jD$|{F3*d4T0mlvNEVB#LBlI)QIa>Tb ziC-{2$Hn@9;P=fD*rwsu;l7=|4Umw1?w?BsUJ_4ChA;3}nMqaeeQ>USM+5^gHNi31 z6L5S@x*>acKwxh5{{L?PP6_^^kR9>duj46y#W=q1;LCbVgW{aMs{bSkTD}9>9=zt5 zv3zlGQ2ZxMd3sV{4y*c)lba8$QrQsJvRT%>WSWB0v8Y(jJl)zlYmdPyPJe)%$`CD+ zna77Z1Nj8v|Aob6Ukj*B8)v6K_i%q_uE+k@g>T96c@{^CktVXz(k#ZucRpRI$*^?P zr{Iyk)@$`6GK12yh=8Bp8yZuTTq%gBqpR>58jL1zjRH=~s)=St2xEU6t*4SS z|1xjelLte(P*J`0xBci!zg+N=`NQSn-ZI&&<~fGR+t0szCgl7V&d;HR@H}D9`;njQV|W!Q3t35d-PR+L zd5KP@4pc_3D76?S8t`X)`IA}qsVUYNcr&Z21f$}FS9&N8LPu=8a)?M2Fqla6I;rtE zX7>7-xyU+wH1J#IpC2ZbM_8XH z3_D#|auqf{f6@L*?xeyfQ;1?4kKGF)TdGe5ac`Aqecw?$d7$^apn^?9r0Eh*v5GBy z_+F?-y*|hae9OK8(bC7=d=q~den9*bELo#Z<44g&%Cr8H@BICWztyXi>pUFK%w+Qy zn2=g_9^vNt7tl2}9rPBZoTHs-DFWy9gm^adI8xQG37*?s>IS}N>zma2%}l-5^DRD( z5WhX=oSCPRZSXjF*PI<+ z3i-|d@XxTYbWFg(NZpB_^oIaN#MWL*`{WmDR|7j_C>IhFihX=)B@nRr+pjtJ76@$5 zR$eOG-x=*XL`|r$#vuej?1|r%A;+N-`X6L0$9z~y#g-=OX+q^RaF1qEx{Jjy4?Yyo z9XpzOxePeLR9yC2T`1~KO$Cb!vdWoM;ozNC5%;DPTS zJZ}i*2Z1f;Q8a-xxyQB+eD`xrmtKDQ;6|U2Ee#lj&?^3V4a%KUE~5R?kxV?gme<=5 z;XH)HL6(bn$wz>IV`eAijp6&ES?MyYcxov59wjtaeP@K`S0SuQYW?ug%lZ~1aghFZ zDt;9lz`MxN{v%Q*6B$TNxV`!a6OTK}I^5U;ZPsuxxM+;47#Y{RjO{efk14LynF>;c z^XsYta{jfPd}{cDK_0AU+ax;dpoXakbtyE0RlM$R$+vY%mQ-8Xf4ZhbBJTghlt9iS z=!mQOLeM_tsO)CSl(=MX=()I_Zi;{6G*#hByZ8d!;<{${rD|8f3GsNlzfToY_O}~80UMhe^ zT+jxJ3?K1-6iLjGp(cmG=-2&BVxin}s-^!dz-vekh2v}D3rQ@?(ftoD`i@zo{Ody+ zPXaNTX^4Q?+L0a?>t%r=cz1ilkZE%s^P+!GMhu^;Srj=LUyYm@MSlinO{#alo`#1@ zCKRH+H+l*h4&F4({Fkh+hF*>$r5T7lF7E=1kpVx~Dzw0WKbEu%zdIhJi{-=CxfzMJ8vDI%bO!VlcNZe^bhmIh6R<(H?O>0=2bGbbh30Yp(}?lDrinOdViJ zO%Az`bAdkmhr=+N`uQOrM~B3$zjsbudjBaO`{WD8@F`@8WqP}kkLqjmcEwAFFnzs$jsY*~(BnSZ8Oy^)8oh`!!m@Y@uSg%-G>R${)J z+3whr{?Ap@&2Nj5Y~|Za2ER&w=aWmxDBWG}{-$eXHsEr59VzoTsK(t%9p~}W4Szb; zM+GJK32Oqx#^Q%v`<|zwXF-Jn7x9gnk7~_bd$WGpiR}IhHFQvu)cdD78YEHjsGyj> zUc!e6lAO+U9EQUwpyOn`(>cNYT3p9=MsfAwm6>w;@CUV5JGnb<+*p@Gd?C?;*Xm8< z5%<Zdh&z zOcGfmjBK5$C857oA)w{2x$Maw5&gV*J(*hoJ<(*erU6?OJzoqAx%cNRK=A%|#Va zAN#3_`K3IlrEY2!Up`C&UOT1&x#ElAFm`>CI%8}R`bV4CFBr!Yc$G4$iu^`^(Ui?&`rrN+>y;65292b-{VtO!xexNCfisBQtvx7CK`u z_{jvG^F>C{_@|bJN-eB(xZT3=FX`SAext!SqQPmpWhPwDQj|WT(XB(rsBUR@cCIft zYi;(|JMOAOfxN8T-Q)450RL3^zB9mJZdgi|%qK3!??FAY^p-iS%?5zE7g!PZ$7d45 z`E--cAl5Ek_|wz2oqa#mQA6CUHc?UtVs4qC2zb;u5q_?k>5)2HIk@lk6yfT%Ou=~FG=%GMDZE*l>C=~U+LaH}Wx`b+Z>#dt z`#*@9+G=c4roG86BB|*pANli&>UU(9vG8A30m>>`zS!C+=`7}c>gT~0(eWR*5NBxC zl%{7fRR_XQ=%aw2-V2k>ZUN7}H%s}#dgn79|8+dH`6UGXx}k$A_=d_7E}8h?SnSbZ z#KqffT9J^$CQ9+Og`&;PR~&|>_`Mg>_U#gd)ghd+lzfxz4d;`D@QV*qIaeFh7c)UoDdmK#_yMFZo`^h#)YadMct#++)MsL719%IL+3F| zzY$LR@D(P&^3wk%{Gc_XhwO(<9@vZ*wD zf<033+nE35y+`ZvkOL92i~z?`AA65EyMuJKri+2~={?qo!xB8Z4ymb2cmS%%^6TZG zQ4dY#IMNfqU-0qorgUJ1;G53{K8xCytV? z@J+ zX3>jl^O)-vEt_`qmxlvXI{Y~&N}^VH$4{Z!N8v*uc>n3<3^q4~_qu9v81zwCqa^0= zjMCG)CscO(BN7p#@U*9mG!-ksy02w}Q&^0^_sYAAkL2j~PlZ(<(&hhh{c+y#q>Av) zRlf72IE0}v@Law^EK-JgZy~0MhGO$M6({w^@URBOAC~qG4CZ$M%P1iG8hlH1ik$() znU-oJ4q`enxZ^e=eCNFM)`sBwe7w?5M*+D|P0f$j@Oo>Ou6Gr;M(7-9F1%TjZMa^S z{P&{jRA(U&Kd7%3FA1Mn^q_EQlWplN5T`zNb8ur{A(ApiyDtT15P=s!r)vMALroq) z+Ot;!ufj_;FcPpp#UBHhT;hj=y$T-^TM;radIaZO#&*l}#uewEk3}%lLY}I3hjXdS zv~z~H1S!Z17x`8!{0?Giw7+Sg#mf|ZbPB9-nYMI$!x!5qC>|4+@PW=B>hJ*UsR1zR zfKEy)CdGh3$LNk54pRzMqcu!A@DF&=zr7O2ef}HY2N2T{phJ@({29^u5ol<(x%FlL zb-XT%HG2_BS_jU>mPV{Fr<(Afu%WY@M~8w_oQD`q09K|;Dobg7|CGMuSK2xCr=h)(r(Qd#e@#^g!Z9VBE3%gN`yq%ChYZYF1rD-VtAe+U_V|a1xNiSRtw6)A4)ZdWq?=OQRCdG7?N9 z{wH{4yBOJx4-;secc@<`7(8Dtwhd>zbk?**9gA=v&m{$KkTVuYyk@m zFeTRTCfi%Or1elzJ?L0Eh>>J!p)Q^;`y@)1dAkk~Fw@93bzAJm^&;fiEBzx$_k&K< z{fE$aV2fY^?_q3Ve?L;=JmIjcupD>Z@bZXG?qkS#XFU_q4@#2Gey;@j7QK|rcgAKc z!*A)JQmlcL$=5Lde(v~x@_6P(eCofDbmg~EI}fjh#mx_Pss} zDFK{L9J84|zwkd{=?J~jwj8Ca?ZW$WE_*8h4$VO8_}vNa8nPjH?SFb*AME~yTNr%B z$;@|NW+z#8Z|{D#57&!$z#M9Man3<@=t1(+qhz&0JMger?e1vUz%D%Fcw0JjuPJV` zL;%a;vrzC`_mSm@Amr@|+4?D0?r^^N+!Ju=e59>|u5)6$P? zC5{- z$$dUrzFg^*O1RIae{b&FwLSXgt3?rzGcP%~FEEq-1Cshmt?4l(ug-3;> zR0OMAFQ!U~)um0dMR#5|eEY*m_YwDmXxz{0LVeI~0Ccd*A+XaH_;CgI`ux5-{<3hV zgwya+=Y4e*tj2!BPwzDQeqFjzU~^92R|p!t#E)tReer{eo{;&-m&=Ch<`IPF_A7=NCj6R`N0*vjW)vbR zN_47xbuSbwehVox3k919D`j|}FePY){V&N+{F6j>xRTC%oBT3j5Ef6cv3iw?ynLVs zuFZl0f&Ddqx{lsOgu*{e;chwORezb;9NZhmpu&v;KNs!Gg*V>*TZPB9J$IEtWz6Yx zp)3Q%T4PfhL~SI3*Bm;~XDUWht>o;r;XqUBj2Mp&DdTVyb^G&@OqkNum+xa!g858F zIgZ6f)$M=R%`=IJrt-`|~elwF_kw?!L6}gthv{Ye6m92H- zDfM>$32!#7d4fD@w#k80V{(M#zp&Gz?{nw}U)u^Jzi-=`*V~$L8O0<9L%1BXA?ZQ% zXEz1Y-<0}}&WyLF%f1`erF$it=4+`enQ7mKyN#bHylG>}*RlD_em>uUot{OTgZR=$ zAu-}z*1`j+obG#Uk#LK^cL=Obpg5!vPw-o9J^iux_0wy)^UHm@7_^keVYZSoH0!Ah z1!$*I8~OjCIDN(N+}w&q>++E8_qW^hCS}8?ZA*wE4Y{zZM{LwX{AyQ3ukqG&FLz%P zrm{|<^{s681Ix(Z@+5o5pjZrl@2CBjta7M*0}vCRggKZ;%3?yvTkLX7hNN5!DOZJd zC*up{J^z=fBBl3u+^f9)w$gnc(%e6JCHI>v(uzs`_<0La)0W~DzkFWS1nigg(y^8Eu@x~*fKTd0o;IrW;N;-IzRBHZ&{dLLDS!5?GPExo%P<^sGk)um zPq(H~+29a-)Q90~>OT`gX(KEDQr6S7kZSJ>xhSi>`oj|SFXTegOIn zR{y#bA_PrLqn7u#n!49!K4&2E5Z(fL#Ly1WLI%FeA5Tl&5JpYTHcXUURr+f`;zH-E z8$VFX^SRS#GpklUr%qw8X6a-vZDOOPX@3)BNE*Tv5z)O4eOy|v?R*MJ-dlj5?lSJ< zRgX24ElBS0Wg+0&2p!vX=G>V$8Ncr@zaMA}GgEMl(5(!)5sh~DKb^hsTUbJiOUMSW zOO`wU>Zub;>bg z%AlnFI{8OiHrPG!d5o^f%Mc%5jU5C3D{5*lAGqJp5`isT7Ij$Y?DzM3)$#uQcs6Mp zS0MD#^El}J+%YZ+56hk1Nl)1zZ*7=~R^53xDV7suH2apk68c1!784hdOpHlwq4>&} zOyvIX4l92C&YFMl+DikFeF^qr{DE)Y1w@Z=H%JdGyMq zjle3lRTOiBS8{e^bj=9`mRj(_NIYzM!A|m736iM$0gEwkEM418sN>Bd+HpR3V)puu zudtblI(Y3)AySA5gJc-bD)M)c_ky#%QrN=F$qyDm*OCI05x!I-$ow-HB$GyFk&JAs zjA^M`2`Nu=Tl7W9Sq!}(FU0UF8S$aH=aXPXPCLg^Ko5pBRP2@nK>m}H{3l};Q8UA2 z(0A3}PN?|#D0-0;^tu;z7yLn~1w=0up$10Yy_DPkynFivGH{fXhjYs!2EUBeg8$JJ zf;@AG2MoqrUSM|r|5x32M>W-a?NX#Sr3i|21*AwXiV%92E(ihvk={W%Bp}jz?@dCN zCLmISpduXtNGEg%MNmQuB)P%&z2EP^KYM1MnK?6akY^uj zXNTikk1@r07>e#vo4_yZr=iI3kY?B+Ngv(&$T0Vd58y$AmpK_7JoNCLa@>;Wti*7n zQXA}0gC1o;L5YQCx6FemTG={~euga4U!iFH3(bIym{Wwpf z`|;9M;1;0R0q(@qEmS;ZUht_AkUsjZYssBOEU6Pt1y0eanj zZNN*npDj-x7hq2829iO%3aHXwGOLGvnT0$>zLVe)qLRQ9gku(RjF+j%o;=98t@k$ioxnQxHxMRZnJf5P(-6H_ z`z@5%6J)n5Sa78t3|>0Ob8qT4r>PiwQ^JNOr$95d;MUL1zxG4|T5}Fa&W?utYc?DI zxs`>SO6vMlwYCFw7Yk}z>%{y*4(cIGfz~D1)aA=YpFF;B%qv_{MQmy<$}dV%pX?7z z5rB%o5G|Y*$<1GACTHD7O$Z@{X3DWnGo!|DJDbOoKqcTd-!2;PrPjZ9$9`c&-+^$j zJ4vMIzQO%a5CbLpf)atA7T7u&XNr9G{`R$>xqXr!Z zYq8K|y~F69{<8e$%1+*QbP~*WW1&VmBQPw8rc#fq!&A(n=UXL{o=w;nm3eWlxOo1D zJCa_qDFXfXIl#WO_2JzWx8wv~c1zk5=OK8?i?*V0(_CT@U|x zOV*A*Ifk6{eue9}VTo{m=_ax4)+J4>M{SLLN^#QZFXaaarmMxjkl8!g7`xMijx`@B z6kSi>k>x4JRs=3pt&?foLYeXN>i5*;!`KG91y5*8#dq>IqW4QET6$UT*3=T}nI20j z-XF~^|A_bVLFz}|dykYT7mv)IdVGBHJevYHNa(7a7y%ev3ydq*u0^KJp+V6O4 z3g0m?EisJ!>j7=m^TW{goq3lybr(M)OM1?w^#;eFN%Kg&C!QAUtePektixLyIse!g z@BiRc(3I#rI1R%P+G9OVEz~%s{}ONWZmS{eD-(VHZ|Jv_DW(@u%gS2%p+mw{B(_hs z;Oiqt+DMn%+S-6gU2SZsz#-5!#WCd6RO{zjp;&4Zh6Cqql;No{A`Y}5)eB}0v zXtnO5WdS?ftIBI;qt0j-3MW1r65a&dGcISNMCE|*IVb!f_=Puv4(7&ZIpe~OGj#1Hp`j)o$x+ff%uBVa;=gB zO%FYx(v;1z_@oJQ=gz1MBwlLEqrnYP@n1DV1$Tt}Ks0{~3HW3T1~je>+TT(cAQ1Z} zKeXE^yyns5X|&pJM|cJPR^(q|ikkd^*})(<_t(EdCijJLg+~NkzrWt$ceVKecs)Za zP)8dZvJCC)?5Fwdx+Qi!398~N5&({r>+B516G0cv*4W&8XU!Y^c3VRYHHFMieM=tG zwDI)CduncRjO9q&29iG@9#n!2J{E2Mbo+0py4bQMMPJt?AScowCt5MI6XdT(ASjjKc-(NRa%($Qk?pE2#GR zy^zO`-gY`s&09O0tcHOiA~4wbqOp+20&hFLsODGa>v}1!V{&ep0up{Lv)=TsGPcwr zf*Hkd8wGaG+t7BSM9*kBD?xh|u_lKLXO1}=F3?%Em62tZ4#``Qp7+Msr;JHR6j-hZ z3+4MRQ%@qb=V(Op-jXOfbbNkIcMn!Fu2QnH5*Y6Kz?FEiW7*&Evy3#ax@6Q!(dzN? zbg_sa$4JXz5Jt`_t$3r6go=?#@TlhJWF(1pJE)em{ zt!Z_D!wrNQ>KVraSQ3&DhGoRHEoN9?G`#w{nDU|Z*F2ZX?p3WO0+Y(LFLD^Y zT4i~13Xvo+!^mlCx1~*<&JW#vhCJw|y$cy)nC=EAS{<;chGOfa$HtVw4j(tZ4p?Zz zT3Vh3Po*hOz9T7^eV#OD3d&_!wF}#hV$ZQKd5@PTV_J<#8L(1hM;B9Z+6KoTT;1*T4!E-z^+b@;kikE^?aJ66&}c!R$PBnVv{o$Ki!C}OR@=u z#I>b{@Pu=qi&Io4p^wrlaIJ`BjJaG9BFM?Ol%VhgJPcMmffQnNK4(?i$ShA&I<#*B zSq>@>^DX?8Xb|==WB?6}=835=+F8-G{)z$tO|7Pq8|7uY+PFNIB9uVVT>T)cAWQ0< zrRkM-JtDj6@tiJJvs(+~oZCl9e^0pgf^Y7fb|f-f^|luFJKYyaK5uq3^g=_L)pM^8 zu>xPsvb@RdDPG9ENFiBpf3)zO^~P3~pQ#)}u0>I|&DG&0N@xUtbDjcETp6~^$~hw- z8AMf!`2fFb_9m%YYn=z@7YExCWIfqwrzj(=zGS)ry5um4MrdvF(I@q=Ta_jBRn~v5onkCisXzFD;R|zwu z=XSA)Z0YdNh2_z0-QdN%M{KQ5aBep~??*Y**WjrbpOzx17Zna80JWLAsKwd7Q|Mlh zpVDO_Bm2wE^LJ~s+`SD%y##d>$&%#5`kHOE1lNzJfP$HGY0jB6m2-vfN+<=cI0$y` z+2xZI5S3sN2H~*j?Cww%C5!oJI7A{hi9CKkEi*u(u$_-}eX=JRQ!QbcqH<)Ja*+%g z|G|j>2Tpd9AZEq|Cl6`$y(=bG$VNSt9_MRdsXe!oqNy$(u((bBmb=BW|A$fcc8^%F zH_o5!ruWf8Zu4_7Nar12#33*hcK6rm&g-P~93-@x16^m{V&HP9fKtHCV*y%hhUm2s z`+4~fDipf=CFpbqUdyBJ}3m!;-~7n{-eA;p}udIEh|7*NBV4f)zde}&+ojkLxree zG1cWaPB51`)(7D}j|-wPOPxNb1-8@ndfnq^c}~rSd!YM)GYf!GV!4a0(SugpVaZjl zu3FOX_I<%`+-wjw@wdn^TU)xKn3QewGGwQtb=r4Fs3Xd#L92?XdjzLp0y}z!=JLR} zqsunmx5L&OWxoJ4Lea=kC$%#gH6MNsVaCNS@I?86drQJ`T-W9HGiK6tX-i$#c}n4v zq$$QDVI#kesJzaXgNtT^;}3RIBWewZ#a;~3LeyE>1M%K!Gf|R?h;eZ=+Ex1Bkqr-D zn~G7?&ks5}oUHWG&3PL9xL{;yqWuaPpIgx^GDV?ig1q8%nUBAYz>E9$(TO$dV~Km* z{OHS17Jx)21zfxpdROoj?%C#<-$emG-*qiF)3mZUVwQ0&{D(t(q49nxeB zBX^6BeF7?|=-WSmn_|6?Bk?ob8^T8U7MUfcbk7sItqx$ife^BflwJdkrGSJA_e}P)xV0v1|5WYqB%9_PT6*5}yL%mp$Z(Bi@Gum_RuAUp`$rz17H#hY5{06Z9t z?k7^)SB=%(+V2G5$2g}YgZyJ1JG0eV4MVCX6zi0aRfci9?Jy&v3QUJF>}cZb;Vf(M z)Tbk_%qohyRbfv{dCf<8kd<;U8kvtwinw9@&J8oPvUJ%3a#B3q?yjIspfUw6^Va2b ztW~8!h;5@5SgMl5mD7nBhm`-kIYM@ka-*qhDp)r=WK*0~cA^b?kNwA&MP zWupKnlIf!_WGO#{5Dk5XN_k~t+N8SCvtU^HX$^?6PC$2@$Q-vrQwyH6kzb|e5O-XHD6O|BOwybZ+sPGGe{j|D+>y5u^^B|=5+u8%HE3zb#BC1=R3`|8!#H| z$XX%DvI)dlF*7A`){)*Y9V)IHfO$~??_d#^MT>0LD|l*R4@}0o4H9qT7;W&cfWOKF zWf>2l0t&qU`DG3@=nhN|Yk`$}(UKT##oD>LPbMJkGrq_I!_4x3VG`NgH^D;YY?gN;=YyJ26XVvnYcz-sh zA3|t~hno(H&c4tG27)ed;?07SLr+w}P$c+ILSc{ZsYrQqlUEL3YeaAzYl^lJ51_6&8==?9Zy~@4ngzs%sCY z-emg%S{K{5*)Nz-O%VV~X6+4M+^3&p(OnaQ-b=N%An`UwrEMmA@X9p))-bi47YGKN z-^+Z#apz-KXDdcx#FM}4DU|bGphY4kwzD314nB$r3_cLIBYEtMuBV}?e`$od<7PV( z1t*OHf!Z5K2LBieuDxUnUgMDYVY&w<@2jvfv=wdAykPgZkIp>%)=_m2H1g6DGt&iu z9}m{QAsaITmy+Mx<8FS{T_tu?DMY6f<2 z%~Cw}TG4a3kjm&N$da9JQ-;p2*J4NUq_*C+Cq~BPgu=GF<{fCWbfQ|Aqs7g4RSu1l zI1HkAX3ArItWh6?&T0Y8pENo8Z!w!;o^85plR&nYdRPT+I`&7UG**#Z1^}1RPXy}Lg>_g4{GE}ETT-z zRHcU6W&D|O7ijV7f#IV!6raVCr@{hLGcanB9JSb{3rkVS=BvEwY?-Vb#vm8;&a!%u z;&a<}<;dY4-VAMd3C9|`;!i(Vt@H`q=p^sgf-jK5H0Bh7*mAG7W3L9{7|?3Vk~=y% zpXL=iYkpa={@PNAAr+$9InwDyw!$f1I}zQawHOQq$UWq-Q5u3)#kP6JfEves0xWmr zZq9^?vA1#fWP*&My6<)^g+^8v$R2%Q<=|`Na74?|kGtq#%lWoOAE3Um;$Dqa-*B!T z)2(PHtd5yBngsFdJc_1#x(5lUV17;WX6g=I$cP=}1Z;$F7Zy~q2{-z-c zF__L@=I?<&{`-mgUe*p!<2|7MnsKlHe)7!~O^XK4HQF!}TjPeSJk9us8*eNfBr}Lg z4&F8rNTy&&V4$T~4Y~qCrhf8+3eIDZHEuen->o}v6deNl?^*puJ4a<=4H(ygZGVhV zdvd@-u zPgqt1O&=5N>t`{AB{VSbyGhs~H%y3M#TCqPbvX&0-OE`JX}=2pvPl$ORz1Z2pNa7M_=$KLKn3#bQ1yRM3X9>AMxNeL4D&5qe;ea{PZBJnr=u?T`#? zoapY{{zE*Vv`DMm!LQ`&uCVe&>WwE!T3LGJ_=9v`>42dflE-r`LTzFQiMH?;YiAEx z_~tnuBIERxb1-Sy7`?N61kWp!?kkkil6QGgGy;IwMT|kpJt7r3i{pYuk#r(xpcfjs z2YKbuAbM`zW{(@9;Vg$9-a!eV^G3(F?#QlO7K)*j(U ztbc-#ZMRHF%ugg zb);=u8<28_NJ?ZqunY=5AJ5s&8bdv^y|F*#^6>{=#}63e@YFp0lX_Uau^rd#hL1we zEb$`nCd_J6BXSAaK8)ym>PfKd|1B5y`5NdDLDEgboP?J1lN&yM%PeQp;{%_D${syT zXXbmL!l&^ZO(6WMgU<)GO-pFlLf|Eff9gfZ|KOSy^84s>kq@#+v|xYV(=iP!L2a9Q zyd-)KW|r3;W@Nw)a}&rIPH*By$8_TT@IK4IkG74CF}q*3dCi9c1nc@DXfG&oKEN`t zZ(DWf+yv!amBWWVc+u(0rICR-bpwBLg8>KW)x{osOt{un9}m%gIUcZ!Rq3-U%qj<$ zO&zaRffMFEQDF|b1CZk>cscwIqv-ZEJO_j=>6hzMwqMyZ$DQJ6lPnHuf9yQ+C7KSCt% zKMf8G8^-l+I0dRhnc?3eMrEXe=aI~FcblfxYYr}0>b{Jm;Rq2!+oOEJXH;E=BfCiK zkw!X^T_DNqNPic|0=TC8jbQfk?<`J}xTViQ^-v8ky}g;cU|nzRuWpkdkPOq}`*0kD zG+G(_3KjE63rtTbuK1Gc9`NTD);tIFXEqDQCUJ9E?M&!N^aIxVnzQ<%GjChefKA0D ze3GOA%ReP?dWQcbzfBaq(FCmkRL8&9_js=v>g@7!^V{C`?`w>CUEiUVNNc9ZuuFeR zC1_9S>l;Z~UGtg)t<=f7i7U_K6;~9rPPUnXXdaJ>4Eb~h-ugu{>U6>^$$v6)cYAqb z*51{$c6~a|1K?&{1Mg`o!LT-Ih_1KVb|p^7c>-X?@x| zxc7g(`l}M`{NCm9zoP7LqQ)=kF;i>)C-;gP5)RXeWD2`(o+;V2pr}}DfDK#*6_5|c z&@ac(G{8o{g>-drVSX! zX*j+wsI#WtvC(Tno+l|Porm;G&FsiUGS6QwA+^qimEJpeYrZnGIKT(CJ)Hkw;Ru6k znEkrOKJ=Re)7+<7XU3MbA3gAK25)X`h3iT=w*3WXgJ9c_3Xr7fHVYPnhG(plaS4L> zE$=Qm0OkXB%kK&m4RN7zhh=bHJK=^!BY^MC+36jJTIzbvdl1oC=Z}T+20zqEo{#fB z@uDZ;{l-kfBMS{&u%mXN7p7BaOf;8{Cc95QJ5M{55ZlXm2gbjvW*pVR^ktxC&?1{q zfX?dBt?9XwEHzsUI#^VDRps4T6&Lr5u#SiC{j#GgXLTOD(8n?GAE{%?Nx4Y6hWuOS zkK}b<7xTT~rGPc(ND3B9PEArh_66Y6RPXoK@yT;7<8}u zL%+riM_Doz?Nv&vEe*-FVPJ$P`20=Azx->U+~@GKqxo-Y$9&72_fXxkXxwK>uEeqT zVkxv^=XjT3l#~jsNirr(Y=z_Q#Fi|?;+HQ+1)!_1X&>j%E9=8yugS>w!ktCf6M<6aoixE! zd>fZ!fdwluQ-ZU~}cP%Vuu#yAIk&N3@Q zJ?Qm*-dpkAkgw3tnm(S2NSoh*iJ{nWKVUJC)tyA1JIGjkS8lvmwxNQUe*Se_-_lJc z=FVg-k?f^R-=5|qE=`E5E>96e#_?bssjtEOUi;ay5wQzfylp)>ZUblcfhmUP7>T>j z@lJqCeO*(0(?YijTWi2Yfx!{A6vf7boqPtY5|f1EuWPdSo?>7<{JZ$hyDT#|B)`h& z5!v1)4Ei%!#pTcKpGQAsznKg z^NjsLHJ}OAA35W)SN@j!0T=Waq0ZZM2~To528rx3?Wlg>UH|g-CSQxzagO@< z?9KsmLwtuXuN`4{u_9yChz|LgQxd@-3Te5*9j3|two*Y|p0m9<35%%SEj=5o$?5zzYetIg#vx zHy=8p$cv>_Zy@&q0c3c?(L4NViVsJrO$9=8?W?Chz5Vg2hqBx^WFo-x&+9?E@$)Y} zG~LyBLwYrCem&-bt7L$$U=t`JY#<`$DIL?es1)@Z(}&(>jZVb!Eg7{*#}t_lPW%_v zC-iJ2jneo`|MFP&A0FE-7Fr*(jy5GZiFLf2Ir`-ezy0}mR#8s-Yim;u(0kofltEDT z<-VT74dgj+GWK+*iu|S_rIBpUdV!?T5T}u;_%7cGV;c#FGj7{K(y@_g_cIUbi0xk^ zHy9trqh|0^o(x9CysGx7laNY82#0Lg-+Gql2~qNudfDDk@W?PL{&)RA9qOUtw~5NV zDc}a{yARK+ft*iUjRCr!3vDV})JodF+Qz;I6^oN0#jH7o(ae#_Kn7^d3v zmm=)Wm2V&#uO_66{it+%^?!o|)(*;7nrruES{GH($LipFc>J;E{9Mwm1bVt(AqyjD zK)PjG!DxDPWbvkN=pls@_-&(h`V8Lx#w`cO`j2Y&HvFxaq7MBeM0`z*jx$$=EHvp~U*< z;FO@7AC0R(F-Phr@Vb5w!}h~^K4&wE-TOS9A#`PBu9EZ@4)o zKf#_)eYJpHA(cQzLjcZeFE0|+8(_Cdh~U3B>$0Po8N!t~| z`?ms^RAKS`2EvW7mt6l=-3-*>QEpKqejKtVr&_J12Y9XQT^_QT z@k z&b*eP$}_6D5%#&9<3fL`ZtZ~E?(k5%c{OG*Dqx>&q5Pa(H%@W;yt-Md?8Q*Ar6eWD zW4pxo2%k~g;C&aF>~y?fT@4ipt2x74&wta*)K_L(U{S2)2#KWlWL4y7_Q>{=PdXl? zD< z@Nclz$owt}&U=y|Ac3m3(0DL2dW$X>+THay zNqJ2Qq~j0P5o0w!uBe*EU}6F@noG+YyzM@7=dX387ze{xF1pBE!_-G5#mGa6sC0VF zhB{2|<7YGbi=wy!nq|Jv;6JDpV|_VA^!}D`X2sG|^J3c%y0kz(k@DQ1cs+`8PZ`m6 z{W&Mx8V8z%CobEw2_mt*GpNuh4V-7>qzKS{qtX!i=!f6miWaM6{bAWo;1cE`qnIb` zQ5OqKA<^Erz2c|$2#`!De_ZlHj=c)s>JHvMmy9Q6_7oun&y@FsyQ36g9g}X-6mjQ6 zt8?B`>N+iJ9(lJMmz9k+i;1$^m!<8geQR>fj`3f}XLfB|Nc+?_!jGkqQYVRY-vGzT zxxdf$t&|4OeT>_^e5|>Lm<_)J(acB^7Q9D3DX_4{r$n9j?I^M%S9aUZclWpP%2}-r z@%O3HhZd%Y#s|hL3^jDJeDRuZWT%j2w@)(jyhW;fie zMze0unExRlHfuY1gDmP`E^bc^s}A;~H2z#oGq6XFj0^T)jlz^KPjH>_6sn8yw2e?p zLgIn_Qhbc6c|V`sQDMb0Bh`#vNB0m8juh@tu2c5h!4G?W3KtcQ)I&1J2;&1s&)s2^ z_zZW#p)%*>Kg9879hH}p>2}+84ky>_lrdxQEIM>~9VS40>XNZfl6GUhMW}r~iDGLv@0sLbX6f z2;w>MY)tV}8)}*^YVnvJPmhcZH57lI`mAXv0b!E(# znHXz{&GYE$n?8;)soWWo@OUrCKG4Lh3whKT{MgC<ASupYm!~74g1Lk|i z8)vXagMg!U-B&~!z%cMa;{!>+LdR;-8awlG)zfyj<7N&-mg13eK-S*G>)Q=`8`?e4 zXQ_QclqZ|Eo0ZI}l@+D%oJC4f33C@p%{W4Xe%8apX2Q&6?KLe^M_KE%nqN&5fEo0% zyclFxlRMDMQ@jjkN^q@vbqFq=CXLGOY@4Zwl|rlz8T){P@r*i6EIF-(>JK_!OZrFd zm#nSihgc;EJ}1d&|B{g~81c|M{=A#q&pJ4SFkdG4?8csLEsSfzy-?Pjo-ogg-+q{U z=MLV7*AW2nH&mv1d{_2kHW`9&g5+LardIu`vR1k+rx8HMXXA@B&TKfGvy8ao%-hM!fEq( zE%2K>QL!!W1@KJSsW(n0wMuWL_2UpA(H-Q!$XRut$(K@sk=rs*IsF)%+9ACASz1iW zR(pP$j|>UFg}A}{{RTh_=yv^dxq(tqW{v%;Gcr-9w?|MbTbZ(p|5VTSy68|0S&xxI z^S#O{#9ucg;>t~$)qT7Sil&q_*B~umC?notgrgzbW(fCPPnqWG`{Q6WQ6J&B4Jyz* z?`bm2QfDq)rQ%Fd0+&6X>N}y1`59W3pqaHPFUDRrSIc8SCS*s^qn$N)Ni6e&>W;&m zEKxqP@5FlE)?O5wVi2>buK7R<5UxUfP_O3e8W?KrVnUUL^vAxsx-TmckW!aGij0eX zN{!AiUR7Ix)&=$_e|YV-qtp`{nLOn&JM9qkxA6ZUhkczV)af}$-Af#ee|f)^R(mAk zj^Q%RQwpY3IDwxv@zrqI!|?n+eJ!c-Sc)yd4ss;e=8)3(F7bO_6krLrz~HsiFkANX zj|~~)(G*`&tr!%{eaqP0t}-u#WJcm_q;d=tvo8Z_=-c_u{$%&1%NY=iJ>I2pW;o&Q zeBHHP>cTeD@e}*m47EABiSp^FPCQfY?Hxk*xthAinRe8@?$~JHSogsQXx&lM62|&j z$JXa6W%pabQ zJfaV2V|I0K|M*}82#W$wzi;4z=%jqaGKW7^EB18bgI9!Eo`jZ8_^3?CFi67e&VHB@G z#imuDw>su%%uD~YKNkDi)!)HjIGe34OI$Z&&z04+$_3G=O-+|SS7vtt+%{nKH8!|~ zc2^$%xsx!EVI7~L1+7agF+m;ojo>tU6FDtp(l~7DoNiq^M4csV%YqHWAEuGUk};)YfZzW?BTP2?qVZX+fZ)jrL+?%z1KqNyB)i@i0Odu!2+hi=8~Wcd<$D z$6{$iDe`SLn}>0A5iU}Jtm~L+S%BhB;bGdzjYRGx zniOAEa_P0L{KOBN@xUc&cAhA@kRNeBwI?38@eh3(Zq)?D;MQcf_PZ|kA4syoT(rP7 z$g~&fn2Apeq+RpLAXqF6uz)cS>-p6B5Dj4{gG#MbJi7h^MtF;}3)=x9Ma{T(%D9>G z0U7{xz^3~D>!EX@%I0pUH4~myS1i{d-a9}UC_s%f_sKV6>l3j=lma@w6r=}OuVkAV zlinry@0VWxBy4_oa!i=gj~*}A`Tlm{;D*@&(ab`Me4a1>@BjP@-XvPZHi)}=Fvwmf O)=<$=u2Zyn`#%7$GeGPB diff --git a/docs/docs/92-development/woodpecker-architecture.svg b/docs/docs/92-development/woodpecker-architecture.svg new file mode 100644 index 000000000..5bb308a59 --- /dev/null +++ b/docs/docs/92-development/woodpecker-architecture.svg @@ -0,0 +1,352 @@ + + + + + + +WoodpeckerArchitecture + + +cluster_ui + +UI + + +cluster_sdk + +SDK (woodpecker-go) + + +cluster_cli + +woodpecker-cli + + +cluster_agent + +woodpecker-agent + + +cluster_pipelines + +Pipelines + + +cluster_server + +woodpecker-server + + +cluster_shared + +Shared Libs + + +cluster_external + +External Systems + + + +ui_web + +web/ + + + +srv_router + +server/router/ + + + +ui_web->srv_router + + +HTTP + + + +srv_api + +server/api/ + + + +ui_web->srv_api + + +REST API + + + +sdk + +woodpecker-go + + + +sdk->srv_api + + +REST API + + + +cli_cmd + +cmd/cli/ + + + +cli_core + +cli/ + + + +cli_cmd->cli_core + + + + + +cli_core->sdk + + + + + +agent_cmd + +cmd/agent/ + + + +agent_core + +agent/ + + + +agent_cmd->agent_core + + + + + +pipe_backend + +pipeline/backend/ +(exec engines) + + + +agent_core->pipe_backend + + +execute steps + + + +srv_grpc + +server/rpc/ + + + +agent_core->srv_grpc + + +gRPC connect + + + +srv_queue + +server/queue/ + + + +agent_core->srv_queue + + +poll work + + + +pipe_core + +pipeline/ + + + +pipe_core->pipe_backend + + + + + +shared_util + +shared/util/ + + + +pipe_core->shared_util + + + + + +pipe_frontend + +pipeline/frontend/ +(yaml) + + + +pipe_frontend->pipe_core + + + + + +srv_cmd + +cmd/server/ + + + +srv_cmd->srv_router + + + + + +srv_router->srv_api + + + + + +shared_token + +shared/token/ + + + +srv_router->shared_token + + + + + +srv_api->srv_queue + + + + + +srv_pubsub + +server/pubsub/ + + + +srv_api->srv_pubsub + + + + + +srv_store + +server/store/ + + + +srv_api->srv_store + + + + + +shared_http + +shared/httputil/ + + + +srv_api->shared_http + + + + + +srv_grpc->srv_queue + + + + + +shared_log + +shared/logger/ + + + +srv_grpc->shared_log + + + + + +srv_model + +server/model/ + + + +srv_store->srv_model + + + + + +ext_db + + +Database + + + +srv_store->ext_db + + +SQL + + + +srv_forge + +server/forge/ + + + +ext_scm + +SCM Providers + + + +srv_forge->ext_scm + + +SCM API + + + diff --git a/flake.nix b/flake.nix index 1e7df0045..543d8e534 100644 --- a/flake.nix +++ b/flake.nix @@ -45,6 +45,9 @@ protoc-gen-go protoc-gen-go-grpc gcc + + # docs + graphviz ]; CFLAGS = "-I${pkgs.glibc.dev}/include"; LDFLAGS = "-L${pkgs.glibc}/lib";