From ee235653ee6cef20afe512b4c71bb9b5bfa6054a Mon Sep 17 00:00:00 2001
From: BaranekD <0Baranek.dominik0@gmail.com>
Date: Wed, 13 Jul 2022 11:07:28 +0200
Subject: [PATCH] Initial commit

---
 .github/workflows/main.yml                    |   41 +
 .gitignore                                    |    6 +-
 .mvn/wrapper/maven-wrapper.jar                |  Bin 0 -> 59925 bytes
 .mvn/wrapper/maven-wrapper.properties         |   18 +
 .releaserc                                    |   20 +
 README.md                                     |    0
 mvnw                                          |  287 ++
 mvnw.cmd                                      |  187 +
 package-lock.json                             | 4423 +++++++++++++++++
 package.json                                  |   10 +
 pom.xml                                       |   73 +-
 renovate.json                                 |   17 +
 .../java/cz/muni/ics/ga4gh/Application.java   |    3 +-
 .../cz/muni/ics/ga4gh/ApplicationContext.java |   44 +
 .../muni/ics/ga4gh/adapters/PerunAdapter.java |   39 +
 .../ga4gh/adapters/PerunAdapterMethods.java   |   23 +
 .../adapters/PerunAdapterMethodsLdap.java     |    4 +
 .../adapters/PerunAdapterMethodsRpc.java      |   12 +
 .../ga4gh/adapters/impl/PerunAdapterImpl.java |   72 +
 .../ga4gh/adapters/impl/PerunAdapterLdap.java |  199 +
 .../ga4gh/adapters/impl/PerunAdapterRpc.java  |  283 ++
 .../java/cz/muni/ics/ga4gh/aop/LogTimes.java  |   11 +
 .../muni/ics/ga4gh/config/AdapterConfig.java  |   19 +
 .../ics/ga4gh/config/AttributesConfig.java    |   20 +
 .../ics/ga4gh/config/BasicAuthConfig.java     |   19 +
 .../muni/ics/ga4gh/config/BrokerConfig.java   |   37 +
 .../cz/muni/ics/ga4gh/config/Ga4ghConfig.java |   20 +
 .../cz/muni/ics/ga4gh/config/LdapConfig.java  |   33 +
 .../cz/muni/ics/ga4gh/config/RpcConfig.java   |   25 +
 .../ga4gh/connectors/PerunConnectorLdap.java  |  154 +
 .../ga4gh/connectors/PerunConnectorRpc.java   |  188 +
 .../controllers/Ga4ghBrokerController.java    |   35 +
 .../controllers/JwkSetPublishingEndpoint.java |   40 +
 .../cz/muni/ics/ga4gh/enums/MemberStatus.java |   31 +
 .../InconvertibleValueException.java          |   24 +
 .../exceptions/MissingFieldException.java     |   24 +
 .../exceptions/UserNotUniqueException.java    |   24 +
 .../ics/ga4gh/facade/Ga4ghBrokerFacade.java   |    8 +
 .../facade/impl/Ga4GhBrokerFacadeImpl.java    |   23 +
 .../ga4gh/jose/keystore/JWKSetKeyStore.java   |   79 +
 .../cz/muni/ics/ga4gh/mappers/RpcMapper.java  |  277 ++
 .../cz/muni/ics/ga4gh/model/Affiliation.java  |   19 +
 .../ics/ga4gh/model/AttributeMapping.java     |   23 +
 .../cz/muni/ics/ga4gh/model/ExtSource.java    |   40 +
 .../ics/ga4gh/model/Ga4ghClaimRepository.java |   20 +
 .../ics/ga4gh/model/Ga4ghPassportVisa.java    |   59 +
 .../java/cz/muni/ics/ga4gh/model/Group.java   |   45 +
 .../java/cz/muni/ics/ga4gh/model/Member.java  |   26 +
 .../ics/ga4gh/model/PerunAttributeValue.java  |  173 +
 .../java/cz/muni/ics/ga4gh/model/Repo.java    |   27 +
 .../cz/muni/ics/ga4gh/model/RepoHeader.java   |   30 +
 .../muni/ics/ga4gh/model/UserExtSource.java   |   56 +
 .../ga4gh/security/WebSecurityConfigurer.java |   50 +
 .../ics/ga4gh/service/Ga4ghBrokerService.java |    8 +
 .../JWTSigningAndValidationService.java       |   37 +
 .../impl/Ga4GhBrokerBrokerServiceImpl.java    |   61 +
 .../JWTSigningAndValidationServiceImpl.java   |  227 +
 .../impl/brokers/BbmriGa4ghBroker.java        |  204 +
 .../impl/brokers/ElixirGa4ghBroker.java       |  201 +
 .../service/impl/brokers/Ga4ghBroker.java     |  223 +
 .../java/cz/muni/ics/ga4gh/utils/Utils.java   |  218 +
 src/main/resources/application-bbmri.yml      |   77 +
 src/main/resources/application-elixir.yml     |   92 +
 src/main/resources/application.yml            |   13 +
 update-versions.sh                            |    2 +
 65 files changed, 8766 insertions(+), 17 deletions(-)
 create mode 100644 .github/workflows/main.yml
 create mode 100644 .mvn/wrapper/maven-wrapper.jar
 create mode 100644 .mvn/wrapper/maven-wrapper.properties
 create mode 100644 .releaserc
 create mode 100644 README.md
 create mode 100755 mvnw
 create mode 100644 mvnw.cmd
 create mode 100644 package-lock.json
 create mode 100644 package.json
 create mode 100644 renovate.json
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/ApplicationContext.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapter.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethods.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsLdap.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsRpc.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterImpl.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterLdap.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterRpc.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/aop/LogTimes.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/AdapterConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/AttributesConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/BasicAuthConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/BrokerConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/Ga4ghConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/LdapConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/config/RpcConfig.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorLdap.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorRpc.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/controllers/Ga4ghBrokerController.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/controllers/JwkSetPublishingEndpoint.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/enums/MemberStatus.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/exceptions/InconvertibleValueException.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/exceptions/MissingFieldException.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/exceptions/UserNotUniqueException.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/facade/Ga4ghBrokerFacade.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/facade/impl/Ga4GhBrokerFacadeImpl.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/jose/keystore/JWKSetKeyStore.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/mappers/RpcMapper.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Affiliation.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/AttributeMapping.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/ExtSource.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Ga4ghClaimRepository.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Ga4ghPassportVisa.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Group.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Member.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/PerunAttributeValue.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/Repo.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/RepoHeader.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/model/UserExtSource.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/security/WebSecurityConfigurer.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/Ga4ghBrokerService.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/JWTSigningAndValidationService.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/impl/Ga4GhBrokerBrokerServiceImpl.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/impl/JWTSigningAndValidationServiceImpl.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/BbmriGa4ghBroker.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/ElixirGa4ghBroker.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/Ga4ghBroker.java
 create mode 100644 src/main/java/cz/muni/ics/ga4gh/utils/Utils.java
 create mode 100644 src/main/resources/application-bbmri.yml
 create mode 100644 src/main/resources/application-elixir.yml
 create mode 100644 src/main/resources/application.yml
 create mode 100755 update-versions.sh

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..79bc9f5
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,41 @@
+name: Maven build with tests
+on: [ push, pull_request ]
+jobs:
+  build:
+    name: JDK ${{ matrix.java }}
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        java: [ '11', '17' ]
+    steps:
+      - uses: actions/checkout@v3
+      - name: Set up JDK ${{ matrix.java }}
+        uses: actions/setup-java@v3
+        with:
+          distribution: 'zulu'
+          java-version: ${{ matrix.java }}
+      - uses: actions/cache@v3
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-maven-jdk${{ matrix.java }}-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-maven-jdk${{ matrix.java }}-
+      - name: Build with Maven
+        run: mvn -B clean install -Djava.version=${{matrix.java}}
+  release:
+    name: Release
+    needs: [build]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - name: Setup Node.js
+        uses: actions/setup-node@v3
+        with:
+          node-version: 16
+      - name: Release
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: npm install && npx semantic-release
diff --git a/.gitignore b/.gitignore
index 5ff6309..946c634 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,11 +3,15 @@ target/
 !**/src/main/**/target/
 !**/src/test/**/target/
 
+# semantic
+node_modules
+
 ### IntelliJ IDEA ###
 .idea/modules.xml
 .idea/jarRepositories.xml
 .idea/compiler.xml
 .idea/libraries/
+.idea
 *.iws
 *.iml
 *.ipr
@@ -35,4 +39,4 @@ build/
 .vscode/
 
 ### Mac OS ###
-.DS_Store
\ No newline at end of file
+.DS_Store
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..bf82ff01c6cdae4a1bb754a6e062954d77ac5c11
GIT binary patch
literal 59925
zcmb5U1CS=sk~ZA7ZQHhc+Mc%Ywrx+_*0gQgw(Xv_ZBOg(y}RG;-uU;sUu;#Jh>EHw
zGfrmZsXF;&D$0O@!2kh40RbILm8t;!w*&h7T24$wm|jX=oKf)`hV~7E`UmXw?e4Pt
z`>_l#5YYGC|ANU0%S(xiDXTEZiATrw!Spl1g<J=Bi|XeNO+{WbLk9%<x8@z!nrdDA
znRkh>yQYxsqjrZO`%3Yq?k$Dr=tVr?HIeHlsmnE9=ZU6I2QoCjlLn85rrn7M!RO}+
z%|6^Q>sv`K3j6Ux>a<oZy1b+;ewnh8hg1fCQIy&S)pjS|#@g<H^-1bOAp22TCVK*w
zFkI=E*w`OZuq3_?1=;MYHTh>s6NoB}L8q#ghm_b)r{V+Pf3xj>b^+M8ZFY`k|FHgl
zM!^0D!qDCjU~cj+fXM$0v@vuwvHcft?EeYw=4fbdZ{qkb#PI)>7{J=%Ux*@pi~i^9
z{(nu6>i-Y^_7lUudx7B}(hUFa*>e0ZwEROS{eRc_U*VV`F$C=Jtqb-$9MS)~&L3im
zV)8%4<VB^#l&fNdVL+JS#Gd)Z7;?KpcjQxDGC$|w*q|-2XBXD7Z@~V#j=d2Jn(=(d
zj;Go7{VAM)ps_dipAHajR`iu7Mbu_~Cg#nL$e%?~3mx>)^9W3c4IT<q-5S`|-}diF
z&3@h>94|h<wSsY#m<=Yy_XhgsCDYir7h?16V?8<`Af*33M_DORF?nUNO)YJw^<i|M
z=bBZ=Vr2`6;w&}`+~e@NgODmwiyv*a6p5kawL~otwWAC~5g(8IDP8`B#%_Pr<cis)
zF4h{3@3O8lhhT5pdc+tfvQVyF%6Llj`0ft`lU)8d@14J%i@eLZ7BoWMKAx{^^R=0C
z!hK|@*F3#_=*)9C0a|Ksw#K_W{b8?bu6?v3ht8xsyEJv_uTwZHn%v!-C<Q8OU>)3k
zdAT_~?$Z0{&MK=<JbrB6g(AMdL%&!uRI60+^7}d3e)e0j-czPSw<OAuYLW9Y_ew#U
zXj2-ihtE5s*Pt}j89A3DsXZ>M0K)Y#_0R;gEjTs0uy4JHvr6q{RKur)D^<rtx<Ou-
zqt>%t<Wq43%-yGx02S@K8jJu1G+H^|TF(yLpf$H~7)5A|vt6PCu8XLpui}r+Oeflq
zEIcsl_9hezS8dPHbz)^98xzuMsfTbBKqw^H<?lFhDQGP}>>W+U;a*TZ;VL{kcnJJT
z3mD=m7($$%?Y#>-Edcet`uWDH(@wIl+|_f#5l8odHg_|+)4AAYP9)~B^10nU306iE
zaS4Y#5&gTL4eHH6&zd(VG<m$AZp09z($MlF$DL@O;dBOKw7hMqCwv<#(TCHtYGEJp
zbGLnOjWuLzZ6;4R1<-{$=CeT?`>yR0Qccx;>0R~Y5#29OkJpSAyr4&h1CYY|I}o)z
ze}OiPf5V~(ABejc1pN%8rJQHwPn_`O*q7Dm)p}3K(mm1({hFmfY{yYbM)&Y`2R=h?
zTtYwx?$W-*1LqsUrUY&~BwJjr)rO{qI$a`=(6Uplsti7Su#&_03es*Yp0{U{(nQCr
z?5M{cLyHT_XALxWu5fU>DPVo99l3FAB<3mtIS<_+71o0jR1A8rd30@j;B75Z!uH;<
z{shmnFK@p<c*k!ASW^jFT4}x1ZHyr_B0z&E&2fAG4Drji!}+Si_*v^Asl&{lo8sUs
zE197O5W)UAP3Qz04`k+7LkT%O2P^-#_vBI$;n=o<hJMKY<R0M5_Ot*^b+IcmpK1?9
zN?+u6)z54MQhWMdr=<xT$0xZtDu;R}I8X#KhXz`kB#>l080=?j0O8KnkE;zsuxzZx
z4X2?!Dk7}SxCereOJK4-FkOq3i{GD#xtAE(tzLUiN~R2WN*RMuA3uYv-3vr9N8;p-
z0ovH_gnvKnB5M{_^d`mUsVPvYv`38c2_qP$*@)N(ZmZosbxiRG=Cbm`0ZOx23Zzgs
zLJPF;&V~ZV;Nb8ELEf73;P5ciI7|wZBtDl}on%WwtCh8Lf$Yfq`;Hb1D!-KYz&Kd<
z+WE+o-gPb6S%ah2^mF80rK=H*+8mQdyrR+)Ar5krl4S!TAAG+sv8o+Teg)`9b22%4
zI7vnPTq&h=o=Z|$;>tEj(i@KN^8N@nk}}6SBhD<PPHB-6A{xgn^pO2wnq-{uDn}!X
zkFWGAiA)5r(su8%oSzM+Ef6oCJJ^=+oLG9IrvSP+Y5y&%7ILTT;nkXDJSzGRlRpIe
zzY2O&*;Dr{?(R&M^d|SxO!Y8U-k>IGCE4TrmVvM^PlBVZsbZcmR$P7v3{Pw88(<uW
ztB)y~m-H1G6Tfxrt^Gu+qumDml;Hs;IfKCD6rvW^QmZFHcZB3DT|PuYV0Tl|5RopA
z|AclGR1+|zjkh`!XJo-j`yp&<(}-)o;pnV#Xfcv}Gruqz8{}TbRyJY~bgC)J*RP~g
zGcgy1kkIn`2~{LV?t)5@;qalE^deO82VuP7j5tZak~R2KGRe%+>jhhI?28MZ>uB%H
z&+HAqu-MDFVk5|LYqUXBMR74n1nJ|qLNe#G7UaE>J{uX(rz6McAWj)Ui2R!4y&B01
z`}LOF7k|z0$I+psk+U^Z3YiAH-{>k*@z|0?L4MPNdtsPB+(F791LsRX$<VuyvnwiI
z(K-dJn=*HufvEc<DZQQ-7`T*9aZ~p0n%dwwY)BoD$|P|)Do)#9yCHe&0qAi6{^48b
zd2+7n5%@}QT9MqR=pdokZNF(9OZ;E^;bL1YhirmI%<+eb_%lgP{TQyZgshO8(qNlk
zpw~LREK7)~2D6TE{v`eZF}V3MbN8C8*TA}vhP<!2VTa(srLi0?(R_#zewIK!ufD)a
zQTVIO$dG(WPnB^76q#^xy#g>D<K1?(n{4=8S(Q<%hpM!=Wqn)k)~;N&B+z43xDE}0
z7cTNza%-B}LOHW@RQQ(q*)Nz^D1QtVsP&P7KmFo=s3}auU<QFYgq~N>m(Gycm1k}n
z#a2T#*)k-v{}p@^L5PC^@bH+-YO4v`l7Gq)9pgSns??ISG!M6>7&GySTZkVhykqk*
zijh9sE`ky?DQPo+7}Vu@?}15_zTovL$r%h~*)=6*vTz?G#h|~>p(ukh%MKOCV^Jxa
zi~lMP5+^-OW%Te@b#UoL6T1%9h-W}*hUtdu!>odxuT`kTg6U3+<o&G>a@6QTiwM0I
zqXcEI2x-gOS74?=&<18fYRv&Ms)R>e;Qz&0N20K9%CM_Iq#3V8%pwU>rAGbaXoGVS
z-r5a$;fZ>75!`u@7=vV?y@<KA?*qC~z8eOm#r+t)N&K0Gr}Fa`*A-cJ2@B5ChOyV(
z4uz7%MM16aabC<2Qoxh28y4jTf4j9;P%G9v6{_|#J+^3F=IOLabAu`<nFg}E({jJE
z8xRgYA;UVCZ7N89FPzL$-OZdX5uF;0hjM&8G|U`vQHCIHEYb9d6I|I#N-A!FS)A~=
zY6uj)3N{}_dLrvILYe)ol)TL2qWKbefZ9Wk-TUlP!_w5p-Q^=(!nFgD7vRq;f1IP)
z+ripz;odY^?mD_xT2yo`1!#dJ^v6`{lSR!25-O?8ds8F6Qe>7J;S;E#lvQ?Ar>%ao
zOX)rc794W?X64tUEk>y|m_aCxU#N>o!Xw7##(7dIZDuYn0+9DoafcrK_(IUSl$m`A
zZF1;0D&2KMWxq{!JlB#Yo*~RCRR~RBkfBb1)-;J`)fjK%LQgUfj-6(iNb3|)(r4fB
z-3-I@OH8NV<qrI{Pq_{P2}sy$Miq<CUN%Sud1OuR>#Rr1`+c=9-0s3A3&EDUg1gC3
zVVb)^B@WE;ePBj#Rg2m!twC+Fe#io0Tzv)b#xh64;e}usgfxu(SfDvcONCs$<@#J@
zQrOhaWLG+)32UCO&4%us+o5#=hq*l-RUMAc6kp~sY%|01#<|RDV=-c0(~U2iF;^~Z
zEGyIG<C}{(SZGU?CPQqQF7}Y}Ph2mTLXWA$H5>a;#2iBbNLww#a{)mO^_H26>4DzS
zW3Ln9#3bY?&5y|}CNM1c33!u1X@E`O+UCM*7`0CQ9bK1=r%PTO%S(Xhn0jV&cY5!;
zknWK#W@!pMK$6<7w)+&nQZwlnxpxV_loGvL47cDabBUjf{BtT=5h1f2O&`n<$C%+3
zm$_pHm|BCm`G@w&Db)?4fM_YHa%}k|QMMl^&R}^}qj!z-hSy7npCB+A1jrr|1}lLs
zw#c+UwVNwxP{=c;rL2BGdx*7zEe1Bcd{@%1-n8y7D4tiWqfpUVh-lHmLXM^KZShOH
z*xFp)8|Y+bM`|>mg}p~MOHeh4Ev0_oE?T1n|HMCuuhyf*JDmFP(@8+hi#f-8(!7>g
zH}lOHg#Nw(x(LkB`Q;g)oVAM{fXLqlew~t2GU);6V}=6Hx<4O5T!!-c93s;NqxUDm
zofsXe!Q%wAD~BBUQ3dIiCtR4WMh-t>ISH?ZMus*wja+&<^&&Gm-nBlDvNS4vFnsl^
ztNpIbyMcWMPfKMe=YnWeIVj|?e>nZbwm$=sV@Qj@A@PE#Gnjlk{CGPDsqFS_)9LEa
zuKx7=Sa>|^MiSKB?)pG()OoM<?&<tW6FJ$u^Kt1qT7ksS8@}8_z<b*L*puJzY3=CJ
z)OTt+T<?dl!w~u+;8=1#7vf~yK$jl?=QESDW1n~8v4@`vj#YdoADlWW;<Ir^;6f(g
z>}_%lx|mMlX&!?+`^^4bT=yz=ZoxWH_ngA*jX*IZcHOjb62dT(qTvBPn`2AFuL0q`
zG+T@693;<++Z2>R2bD`qi0y2-Zf>Ao)K0f&<Hn4AI6O9Ew*L_j4l@0K+eIuQF>d2P
zfP78gpA6dVzjNaH?(M_mDL)R0U=lEaBZvDI4%DXB?8uw7yMJ~gE#%4F`v`Nr+^}vY
zNk!D`{o4;L#H`(&_&69MXgCe`BzoU+!tF?72v9Ywy}vJ>QpqhIh5d@V>0xHtnyvuH
zkllrfsI^;%I{@6lUi{~rA_w0mAm940-d++CcVAe<%1_RMLrby@&kK~cJQDXKIiybT
z-kqt-K3rNz|3HT@un%{nW0OI{_DTXa-Gt@ONBB`7yPzA#K+GBJn@t@$=}KtxV871R
zdlK|BI%<KdxORnw$Cvt>we#j)k%=s3KJX%`<AeGv)9T)JOEGs4MG2hoY8CIW?2%l8
z4+J!~^2?j01U4i<1BbAiAxCtM2(q0=aBbjZN{!YIUn*mF&pfa&An>+e4L~_qWz2@P
z#)_IbEn(N_Ea!@g!rjt?kw;wph2ziGM|CPAOSzd(_Cp~tpAPO_7R!r5msJ4J@6?@W
zb7r0)y);{W17k3}ls4DaNKdRpv@#b#oh4zlV3U@E2TCET9y3LQs1&)-c6+olCeAYp
zOdn^BGxjbJIUL0yuFK_Dqpq%@KGOvu(ZgtKw;O*bxSb1Yp#>D?c~ir9P;<3wS2!-P
zMc%jlfyqGiZiTjBA(FcUQ9mq#D-cvB9?$ctRZ;8+0s}_I8~6!fM~(jD=psem4Ee>J
zWw&CJ7z{P9{Q7Ubye9)gwd`}~OSe#Rf$+;U1GvliVlhuHCK9yJZ2>_y@94OzD`#Ze
z9)jO->@7)Bx~CeDJqQK|0%Pfmg&-w7mHdq3hENhQ;IKK;+>|iFp;c?M^kE!kGY&!y
zk0I0Fk*!r6F59pwb<6v2ioT*86d(Tee%E1tmlfVjA#rHqA%a~cH`ct#9wX$-o9erW
zXJEEOOJ&dezJO$TrCEB2LVOPr4a1H9%k<&lGZo1LDHNDa_xlUqto!CGM^Y}cxJn@x
ziOYwn=mHBj_FAw|vMAK^Oqb(dg4Q?7Umqwc#pL?^vpIVNpINMEiP4Ml+xGo3f$#n$
zSTA3aJ)pM~4OPF>OOXOH&EW^(@T%5hknDw^bLpH%?4DjNr1s9Q9(3+8zy87a{1<&7
zQ@0A|_nnege~*7+LF5%wzLWD`lXWotLU4Y&{0i|(kn5hdwj^9o@)((-j86#T<b@W9
z+j_`4S)Ygdp}18#H-?4dA?hq#k==B$W6aKP0}Rf@202&?(gT!k9-icY&e5MF9?2lH
zC42?xgC_QqCaKAztkZ%x9*0s%qzMCGn6?QW1nbSqe`ZtIjQ|}sKs)gN%p+*X7H^Y6
z0s&nk00FUnPx#;HssA9K{++b>KNN|Got?9j^EYE8XJ}!o>}=@hY~siOur_pZ`mJW+
zg}Q?7Q_~bhh6s%uqEU!cv`B=jEp1K|eld>}I`pHtYzif`aZCe88}u$J6??5!TjY7Z
zi_PXV!PdeegMrv48ein(j_-BWXDa73W&U|uQY2%u#HZ5hI@4>q?YPsd?K$Vm;~XD|
za8S@laz_>}&|R%BD&V-i4%Q6dPCyvF3vd@kU>rvB!x*5ubENu_D>JSGcAwBe1xXs>
z#6>7f9RU7nBW^%VMe9x%V$+)28`I~HD=gM$1Sivq)mNV>xD~CileqbUCO{vWg4Rh#
zor2~~5hCEN)_0u$!q<(|hY5H=>Bbu%&{4ZV_rD1<#JLjo7b^d16tZ8WIRSY-f>X{Z
zrJFo^lCo+3A<buY*fei3#c|;F8_PK|gfwnU^T}JB*6KAsTXPn}g|)%h>agC{EW4g=
z#o?8?8vCfRVy)U15jF^~4Gl{&Ybt92qe)hZ^_X>`+9vgWKwyZiaxznCo|TfVh3jIi
zc<r9gMg|huztruD*~;Ja(RrQ-=~g4gilb{xySPH%Swbd#|A4M4H!-y|;?(wNQKi~&
zLftNvKx(Hu<enep8Q|!v;})qVY~TeNST*zep)=$5d9<wxd-Tu|ellCFi4+vF=x6}*
z-gAweZb9irHN<q936{Ic2*rBc$&_dbxz0t12@80t>Ef?H`U;iFaJh=3Gy2JXApN`o
zE=O1Gg$YQt6|76IiMNF?q#SA1bPB@dw#H+-V@9gL>;1mg+Cb#k1ey8`dvR+(4ebj=
zUV1Z)tKRo}<wDK+$w==~fhD3fWQd2{>YEh@TN=$v(;aR{{n8vk`w|nNuHuckt$h27
z8*aBefUxw1*r#xB#9eg<Ia!ovMuf%^ol=+K6qEa~=#G4X0X@^X45!<fK8D68Ajebl
zhwOrwX<bCl?lFyz{|egs&!HN7IRmEx1k;;Lq323NQ;a7MeHx$W?OIu58WshudZ{71
zTOOAUa)s$^(i<3`lD+2_P;j#@gC~yt8F_o3`3XUAUzJ;k>cpXEi_*UAJYXXk!L7j@
zEHre9TeA?cA^qC?JqR^Tr%MObx)3(nztwV-k<CqH`xSfi8)&P$HcH|UF8z+N8t4s*
zHBjJo6|KQ;VB!*0(q(aM^qiVTzuG+K>CeU-pv~$-T<>1;$_fqD%D@B13@6nJvk$Tb
z%oMcxY|wp&wv8pf7?>V>*_$XB&mflZG#J;cO4(H9<<L!rDR5PSb<UG)n1aeahvnHh
zHZm&#0>>)V(X0~FRrD50GSAr_n^}6UI=}MTD3{q9rAHBj;!)G9GGx;~wMc8S8e@_!
z_A@g2tE?_kGw#r}Y07^+v*DjB7v08O#kihqtSjT<VbVM3+HC$Rd+I2d5+-ntwZcz#
zsr)&#WRhKPRkD0uQhj)C!QSq}%HDboI$2&sNNF9}cEAA3x7Ak~Jym(GW}T(RP`_EU
z{9L(YjNS4__0brzuEECd!Ol7FvAShsB-oHa>)2uwHG1UbSIKEAO<7Nt3T;R`YCSSj
z!e)qa4Y~g>{F>ed`oWGW>((#s<m@uWrltM4nDkH1=1WXteiJQ5jiOR+R9VC8DKXxF
z;^(<c0hedd*Mvi)emSi?CSB?jYzGO-=B~0MnA>$zQGbsS&sg}^pBd?yeAN05Roe8>
zT5^XsnI??pY-edI9fQNz3&cr}&YORzr4;sw1u{|Ne1V}nxSb|%Xa_Xy5#TrcTBpS@
z368Ly!a8oDB$mv21-kqD9t&0#7+@mt50oW4*qGcwbx}EyQ=zv+>?xQUL*ja2`WGq`
z)sWi!%{f{lG)P(lu6{68R~smEp!Jy9!#~65DQ1AHIc%r7doy*L!1L>x7gLJdR;hH_
zP$2dAdV+VY*^|&oN=|}3-FdyGooDOM-vAGCT@@JyuF4C(otz>?^9!lR%m-tde}ePe
z)Jp)zydtP%C02mCPddGz5R9NYvrS6)Bv$~r@W&cP5lLp7-4NrEQDN3%6AmXH@Tdfj
zZ+k^}6%>L=d8BK-pxg<cM-c6;y=-m0fM(b12l{KfZ_~Ky44ntwW>vV`ix>w6F;U0C
zlZ#lnOYYDhj4r)_+s){%-OP5Z{)Xy~)T{p`w1d-Z`uhiyaHX5R=prRWzg^tr8b$NI
z3YKgTUvnV)o{xug^1=F=B;=5i^p6ZQ3ES<#>@?2!i0763S{RDit@XiOrjHyVHS*O`
z`z@(K2K8gwhd0$u@upveU3<SEyIL<vU5VP293PR^vId<wnSZ5H#V8&}X5MEqI$gsY
zw_wX*_eg}_+wT2Jiig_;?mii|&#WWqeoXB?7E6%B{>ryuDP~by=Xy(MYd_#3r)*XC
z^9+R*>njXE-TIP1lci2Q!U>qTn(dh*x7Zxv8r{aX7H$;tD?d1a-PrZ_=K*c8e050Z
zQPw-n`us<k<i9ouLYsAM)F41W#NYKGmVfon{b6Ei=wj{s!_Ljt+Ro6}#F32oKYqE&
zx(cYmX#Ap9Ep#$vszUD|MMf<|uzR>6g%-5T&A%0G0Pakpyp2}L*esj#H#HB!%;_(n
z?@GhGHsn-TmjhdE&(mGUnQ3irA0sJtKpZ!N{aFsHtyTb#dkl=dR<nHpjD5*<cRzAm
zCBDYEx*e9m{^o6|8s^HRBwLU7FwQ^yyayv9p8Qj>F+oo-dwy<#wYi=wik;LC6p#Fm
zMTEA@?rBOmn>eCuHR%C{<p(lKrvz899}(A(Nm9R60wLL}f1x5KDv`$Zc`y{szWTZG
z1oST<OD>!jx>b|+<6B-)Z%(=lG{@y_@8s2x4Hym6ckPdCB$7NZFp_|El()ANXTORs
zO@b$@1`3tXjEm>;bX)%xTUC>T)r6eTFtq<FZ?(?<OGM?Q&tuPYN@Uo6^hF$HSg%vD
zxZPci;YQo$IM+`KS#jfY=;pX&`Eh95*PkBf!pBjI`|zhghY<f+c8J@x2)q6(c7SPJ
z@vhg-rRn7!E<Or7$~cF7r~Xh?fhUivkh#DN^)A(rTA8N>*Rp*_?%C+fEzT##kVNH`
zV}-lw6&hY;cyl5#RR-w!&K4e)Nf4noLFyjiAbKvP7Y!=2lRiRjc$&d?P~!<L9`Pf+
z!Wf_eYE3HUYN{A)l?w4UTbR`6Pa3|Fjj}OMaSzE~3YSAxBkIUW%0UI@&rdiGf2cJ~
zvWlSdMjUsuS+1bi9q}Gd1Wt?SJq%mrBI2UH%Y}W)f8Ok6DE{oF{|>zM@4!?3-vyqs
zhm*63jiRI7cfruv!o=zO%H2cQ#o64%*4YAJ=xp~No53pO?eEA$`fR4x=^|*#{u3bx
z1YB3OT97ZU3=ol)l`K!lB?~Dj(p_i0)NN=fdgz(QBu>8xV*FGZUb7m4NEbrA+BJ1O
z%CPI+T>JPq9zpg~<>QR+je>?{g)rSuWpyCDcc2@rE8T>oNWPi<fu;%S0UC=%q2HEW
zp~w28q0J^lW32`{qyl{f^_r(jmss#-lS1qwLjQ2ehC#QB01QyR3juep-6a&hT>P*u
zLZc3LaQVE<Q%=lxsMdBz9@w<&A(EWI2L-m&S@TkVb;D7^5wx)9)$i1v&=TIOiJ9Y3
zQnvh2z4G88H#&6xDg(FRlE)F=bw2S&ar%)zB-pz8F8JDE1a%x6o(5aPl*)8uPL=MI
zHS(f{32nFnz|`^{QyIZoEin3kEh{|H#1u?6aKSx~od93-C%9Q4Io3Z8f<T+9H?QtP
z;l0AdPre$9O3OV!b@QOi-we)<(S@wB0(G+lWnw=QU6kg)!m;M+VV#BSq4sUc3r=Qj
z9O;MDN=1sJnJ65iI1r;oIuAZ6@;D=Bt4?A<VweU;i?ZoxlzE-<@-vz5tu7#jpdS1~
z40)~v=z+@OFs=yLh{V@#l+%$!a?Y0pj$jw(!Cn-|dV>sC6emsi7DCL0;U0BP!Sw<O
z^{LPXkK_|y9l^kdKTqbT`cCTK&-}Z6;y<!E$wJDh1hd^_xY*`K1?)v{e*P4fo5NYP
z7q($Np}592cPOK~JhB@w4ll6(9Gw$SIv#m&KtNaD#cHPiRdoKxM^O{n9d`)*b0oRR
z%EJNgupUJ+X}!h45A4EzHAV_VAmETIRmhOk&YJvAx>AkXuetI25TYuCwD8~Z|M@2_
z0FaB<B_bnp{nmXQxP{5~VWyTqt{s9j(!p!D#eV&9JvDi3_W68*3N(#`k8=f+3-6Y)
zkFr5Zc#Uv#OYrJm6Y~sy<Krzf00~MpvI}%I^ovJ;Ed2TWr8Wc-BsDnJ{KXtd;>G|x
zW)FZvkPsN^5(Q}whYFk-E8)zC(+hZMRe5VA6GZM!beBdDBqq#Rye$I~h@Kf8ae!Ay
z*>8BsT)dYB${E3A<HPN>^j5m_ks3*1_a^uA+^E{Gxcgw2`f7jw8=^DG391okclzQA
zwB6_C;;k_7OnwT<<5RjXf#XxTO9}jrCP+Ina|?UA%gFvNJy7HFE<R$%{w_aq4SF(2
zSU4>x9r{(c&yDZ9e2a<iyL8Km@5?wMc%y*-m2mg9d_xHTg|30Img87eM=wue!EHM!
zeQUM-`P9g3xn@ge*$yqyyK23jynxNAOifG9G$Bi|@5qo`>ovtJL$um8u>s&1k@G6#
z-s55RDvTcFYZji6x+UMyCu{&*d4N<{6;H^PEF!?X@SqMfGFR}LYImL1;U}{iT!qnA
zgqLCyvSp>>nS}|sv56Dnwxdo<Hl(o?6sX;&wvE(hJo7k@I;L}K@J=~zY{soxji4UY
z9?q^P7eITNS(9CAD6iCXGE~LKWTH4som>&HrZG1WQL_EkC!D6j)JW4Tv1yyqe&aM-
zHXlKm;srQVctoDYl&e}E-P8h#PCQNW{Dg*Te>(zP#h*8faKJ!x-}2Rd)+>ssE`OS?
zH{q>EEfl3rrD`3e_VOu!qFXm7TC9*Ni&^{$S76?jtB;*1+&lyEq_j{|Nhg&s;W6R9
zB#r9L#a7UU(Vnq#7asUx%ZyVz{CiVL5!CBl-7p|Kl&=g>)8<oLm>e?z&u?Q^r>L@P
zcB6n=#5Wz+@-j`qSB=wD1p_n<<!Z4TwPnXG0NM(mk8BJHasZc63tA1F5<UYzCpGn^
zaCw4*XIlW6!N%@nmz4q~6V7|gW9*Evv?<MW`|W(<J&=kb^a>(NhAp8wa!IxDP?M&_
zKNcJonwpOS>a3-OBC9jGV@*WND}F8~E_QS7+H3ZK6w&kq>B}kc123ypkAfx`&en&T
z+?U=!q?N5DDkt(2$KU;t^dR}IVC|M)pn@S)m{saxD4V?TZZWh@hK|C|n(P&eXLAq1
zZ#v0gPhHJYiyjEkJT~&%u@zLE`Lm!p!&-VAfk?eF{HN%PeV5S87-u3n<EG-NKh;9e
zHd6ZRnwlqsSBq{N`~1@O`qqL;n4`rUsjWrqkLJfmI|D&4Y=TBfP+&D{!vce^jm?tW
z;&2#ItUa{kQev7RI@dB0wFMJBw?f?t&5$mBUX~xfQ|T2c29k`zaY@2>;g}^R(OZqI
zA|#<QT)9k3DycGz-0LL=Y)LY0qzuJLDicr$Vv6{tj4fd7!nG^)sDDQ|VDC2mY_%{j
zkSUZxy@zAgr(>#x9SAAKAb!FSr9+E^(}_HX+lb+XLQiWF2UmH*7tM?y7R{u<P=FOP
zBWV-FjUW$!iYyAzph#|z!!`>3(Vr<5h8V>Y-c`SgYgD9RvV*ZP{xBLuk-5sAcGP5G
zDdk)Ua8PaYS-R*C(V(}4>%>{X%~yk{l3&El7iOz}m0Y8MAl_Qc`-2(z2T3kJ4L1Ek
zW&^0C5lA$XL5oFZ0#iRevGn2ZyiotWRIag?#IT-E<oqCxXeP1wGo5H9`Z=6KGgpZp
zBduVG<TeVF%vpEwFTiavKC@S=Mc`@r)o0;QaaSli5r0}%A;`*oO`vvKLk_;{Pfg$S
zCT7#a(@wrfvvB`YbE)9x;SDA5m|D!8{!21Enc&MHT=}BJF)&>$gv92YXfp3P1BJxO
zShcix4$;b#UM2o=3x#3;cA8Q#>eO8bAQ6o|-tw;9#7`gGIFVll^%!T5&!M|F|99EZ
z?=t(Tag~g}`Wep_VX!|sgf_=8n|trl((YTM-kWDQ1U@<yM;E5LwY(dqOgnE%;}k9@
zCe}Lhy;O+fRGf@^p)X`3$xyT`^@c5M#3Fe>WIg!~YjGqsZN<Z&N7q4NUy=|6zu63a
zkSWFyU~--krqX)3yN$z^C*;C+4Q1tvq~<QK;+PFJFYFdUY_tWX^^5ll4&KL1PTp~}
z*5#1Y0kk?$sfG_q6Pu9YEsj9qQ@NnsIHqT9^^z$r`l*UEpWgUt#x!Q{&G2|+Xpn8a
zg}M@|QQm`;HfZp{@{M+<;~DAx!Re8Meri5&vpJ%LZ3Q<E<7_Yu@|B-JJK&n=3kZF?
z{RTIqc8D3%HwQ7ogl`?q&Mj`Px@#_{N29$*ThV-0E<H)9ZgKMSY0>Orayhav_lrw<
zgSle+;b;p^Ff)tDt~?&TweI#6(}<3?Uw1@|4MvG2w}sQgX*N;Q=eD+(bJ%jKJ9L2o
z3%MlC9=i-DKzXOun`;&7ZI$Iw?Y|j!RhIn*O`mRl2_vUnE*Rf6$?{IC&#;ZS4_)ww
zZ${m6i^cVHNiw5#0MSjEF!NaQfSr&DbTX&tHM{Ke)6Pt9^4_Jf%G&51@IH0aA7QRc
zPHND$ytZTZ7-07AEv8Rn%5+<=Bx1tW<V>JSG_?CqXuJ99Zwp=hP2?0a{F)A8HLWkv
z)nWbhcgRVdtQ4DpZiw6*)QeCWDXGN6@7m@}SN?Ai*4{l!jL`wrp_lL`bJF6HVAOnj
zNa*f<X;jZAB)4k7r8h%R&J6p_E?hYm>Tj+{niV5~<z2_=Ab$2%kQ$)H6gJxLq0>*O
zN5NwHHcEed1knV2GNSZ~H6A+13`U_yY?Dlr@mtyq*Eutin@fL<nXfGhU->qITcw+{
zgfCsGo5WmpCuv^;uTtgub$oSUezlUgy1KkqBTfdC=XJ}^QYY+iHNnhYEU)j7Oq^M^
zVSeY5OiE#eElD6|4Haq&dOHw4)&QX<E*5YFc4PxPT|+n$;GjYnKmaFaV5s|RfSE3x
ztp^JyC$QAO5zbOqa=*g7KAS?jwRH@uW^BkEp6){Bs;Uo4{50BmCKLt0j7r<H3M{$#
z`%#6jk50}0h^ULZsl@@Wr0MV3nP@jaW73b#f*$rYU{`UCD>=k_Ut{?Uvr21pd&diJ
zB2+roNX!_7mJ$9n7GNdG8v{=K#ifQnT&%`l82sR{h&TKf?oxK%8RlG}Ia$WP=oQ3C
z8x#$S3Rrhe<WNB%j3wm5=)s6xy(`=5X{+P(T2E)>yw7recyTpSGf`^->QMX@9dPE#
z?9u`K#Vk!hl`$zv<^Wl(#=J4ewGvm4>kxbr*k(>JDRyr_k#52zWRbB<V~_esjy-4T
z>BxSsQfy=+DkvQ40v`jh_1C>g+G@4HuqNae&XeekQeAwk+&jN88l<W5RNb5WY_l&<
z4vjiv#Y$YDdI#JN;w&!o)}QvjfYM7FZ>@etjc2U0(3m{pQ8vycb^=k>?R~DSv8<p?
z?+6f!5F<p8)sbMmfg7C)5!GYrDezJb%v`O`gudLw$^><0tRfmLp27RlxR~V8j?ClC
z)_B-Ne*s0#m}G~_QwykU<`~vMvpTlr7=W&w=#4eEKq!$muL_QJblmEh6<Vep?ucjj
zm?AdidWiIS?B0e$rbNu6!tOgMnoUYResDf<4%PV9nHOA^XdgVvm9E0PRF+MB4mwI+
zL(T3wtQ2JVOJ{fkC+m8P0kSRmJi-p%Mo6?fEV3tV(N*r^dfS5=6J;n?ryGlXXz3xt
zhM$+p3xiosr8uocP0<lWa~$r=VL>*MUg!$z4fC{DBd*3h=N|lf1X7dTfqL1v6~_al
z%J+WD;fSJ>TKV*mid$G+8eIjdfK%pu!#kkan;Qi>LK<0bn$?ecFn-b|@+^+OT=0nl
zZzN%OUn9w14s`D45>E^)F8?Z?;l!%DF^oL|Yt!@m^V@3twFD@^D5$*5^c%)sM*sbi
zk(RQq-d<^O7T8RfFwEK9_us2+S$&W1-Z3OR+XF6$eJl7IgHM~N8<S>sHzWeuzxpB%
zE9h3~^*;?_y)7i>a4#z6(ZQ%RaIo)|BtphTOyY@sM+vd#MYN11?ZV(xUvXb&MFg6g
z=p`JrH(5;XsW4xVbiJ?|`nutpC1h*K1p~zS%9GcwUz0UWv0GXKX{69Mbhpcsxie0^
zGqg<E+tGEr7w5%hM<MEAj(6pKUdtTtomfVtsfptX39tM8{v=8heZ`>qzpqFAefIt5
zbjNv;*RSO}%{l!Z)c-Qw`A_=i-}4-?=swGSMI^E7)y37u+#O1^yiI2ehK4F|VMVkK
z!hIFgJ+Ixg^6jI3#G8UbMwE1a!y~wFx@T(|6G*f($Q=e5na9eDt?f6v;SI;w0g-j%
z!J#+aN|M&6l+$5a()!Cs22!+qIEIPkl)zxaaqx#rxQ_>N-kau^^0U$_bj`Aj28>km
zI4^hUZb4$c;z)GTY)9y!5eJ{HNqSO{kJDcTYt-+y5;5RiVE<zYg(d4ZgpVzeW5j>9
z-rfg@X78JdxPkxzqWM?WOW8U(8(Lfc7xz`AqOH6jg!Y-7TpXRJ!mtM~T)9C^L}gSL
z;YSLGDG_JZayritQkYm6_9cy96BXEf5-2!+OGf|OA7sdZg?o)Z<$B#|?fq|82c!WU
zA|T92NDMBJCWHwuFa{aCfTqmu)kwClHDDbMnUQhx07}$x&ef5J(Vmp?fxerb?&J3W
zEcoupee$`(0-Aipdr2XA7n`Vp9X;@`bGTh>URo?1%p&sSNNw!h%G)TZ^kT8~og*H%
z!X8H2flq&|Mvn=U>8LSX_1WeQi24JnteP@|j;(g*B2HR-L-*$Ubi+J1heSK4&4lJ|
zV!1rQLp=f2`FKko6Wb9aaD_i=<=1h?02JU2)?Ey_SS%6EQ>I20QL=(nW-P4=5mvTJ
z&kgssLD)l`rHDCI`%vQMOV-yUxHQyhojHdYC*$H1=nrJKqFo93>xvB=M`$}Roksx#
zRgV+d8#sk=v+tN#P-n?dx%RC(iv;9-YS-7PrZu#xJ5%k4i*8joRv1J`M_tOQR`{eV
zE~<8%VC63sx|_U&{Bpy&<DOu$QP*lC-#xsn41k7rV=faO;)ch$qL#Es?Jo>?!<ly%
zBK1m=5{1=bZ`{Yxoz$Yp$=go~!b-1j4#_)rcBj!*OYKK(_&jJ)#h3lc5B2=D=G}<M
zrWKC@BKj6?V-z-BNmnz)D40`_ByT~@bE<$*Ku91%_WpOiJX;SQK6iPRCYr|+sL6K+
zRO5?sv8zZIA4f`j6w*BwYz&s1F;jvSsnVNG9I?sYS^%R&H>~^Ce+CNv^T)?diyKrA
zu^d&el}PFVW<rN^c}-9)rh!{>KFz9wkriy~eruRakPmmS0ZsKRiEMGj!_V`HL0FT$
zQU#r2x}sc&kxyY}K}1C{S`{Vdq_TYD4*4zgkU_ShWmQwGl2*ks*=_2Y*s%9QE)5EL
zjq8+CA~jxHywIXd=tyIho1XBio%O)2-sMmqnmR&ZQWWD*!GB&UKv6%Ta=zRBv&eyf
z{;f~`|5~B_&z17;pNS$3XoIA~G@mWw1YgrTRH95$f&qLKq5wY@A`UX)0I9GbBoHcu
zF+!}=i8N>_J}axHrl<NPnB@wB#t1bu5faM_VjG(l+jW=A_Vw>mb)A1>vwib%T;N(z
z!qkz-mizPTt^2F1``LZ#Is;SC`!6@p@t72+xBF5s!+V#&XJ54bJ|~2p(;ngG3+4NA
zG?$Orjti%b`%<{?^7HlMZ3wR29z7?;KBDbAvK`kgqx4(N-xp5MuWJ1**FC|9j~trE
zo`+jX&aFP*4hP;(>mA>X7yZujK`$QP9w?a`f9cQJaAA2cdE{Tm@v?W3gT&w=XzhbY
zCDpADyRHQ?5fOuf*DrAnVn6BjADR2&!sV&wX1+TC*Qk}9xt8KA7}6LBN-_;c;r`H=
zwL1uGsU0;W?OEez?W5HYvu>6SR+O8l#ZM+X@T3>y9G^L76W?!YFcytB^-`NyTDB=;
zw421!sr`Wwopu>VDWNN>IN&RxE08d0JJZigpK%)p|Ep&aHWO`AFP)}VkqQg1S#TY>
z(W)bm7duX(Nvry|l%sGs+Eudz3=_A0i@M47VtBp1RTz_zxlmqgi53tT!_i)(bad*R
zt<1n~oT!|>QLmYf?YL$n8QEJ2A6liMI!hR<?ciV1ZmMhIw0V@Z)FhX|xm0blrPEPo
zXa+budJGtI@%niCK;IQA%qK-^q`~<J=dZx3dXiM<!n$pNJz5qs>Y#mB@?9sWAUW8!
z3#M&1`ZQmRP*o`jtHjbA78}!&iq6v&rlp|5&!}O}NT>|10NoWbiq5@7lhquTSHBCO
z2a!-M+(e10feoq(nVw~!ZC;y+4M=F0%n)oHB7{BRYdVp<fSv_74KFL=#!$ZZ6>eTN
zryeS3Ecv^OC_2HcYbRWnOSY2McCa2PfRXH~!iu|fA^#y<&eJkS1^d|DM3)QKAnMe1
zp%9s~@jq$zOV8LQ$SoOZGMPYE@s<@m$#S(N##mh{yFb!URLo?VmR4c2D<_vio;v$u
zEJivu^J$RML#dZFhO#!?D8s-JTIP{sV5EqzlSRH3SEW;p+f8?qW%}bdYNyDgxQcQg
z)s4r6KHcPGxO_<pp*<o#D{ceRBM|+YAp0z93!g=mqa5foY^;!gUB!|6C<b%WxsLr4
zH7KJ-4m%g8c9ptnGRh&^ywI3_#X(zcIs(7eM*~YyRiJw>ErHr?P}mfM;FZE)8_I3?
zDjMJvQui}|DLHJ=GXcz4%f~W;nZtC{WKitP66ONo4K<7TO!t?TYs_icsROOjf=!bP
z#iDYw8Xa2L$P!_IMS+YdG$s?Gh(pybF}++ekEr=v(g97IC8z28gdGEK?6QPNA@g_H
znGEeNG!5O#5gfi{IY+V>Q!Z=}bTeH|H2IGYcgh~<ZL&~moA|(;3?|bDEa@$T?`TXk
zdLtT!kt@h>!jjG`b~g<YdQxorOx@EJT+o8y^dEDsKWU?2Exj<5M*I&p%hjc20q9Bv
z`iqz}jTBO*R31Wa{f%@X>Go!$<2(Kis_p5;(P-s_l8JWL!*jOOFW7(UIXj)5^C~7r
z>g7M$hT|sIVBpur@M~;gi~j(BNMp8UkYv?y&{`-sK=@)-@S(2kqob<t<DjnW@u+1|
ztB2{=8psNjt!TnPo__%6$7=Qz<(V88rw>O@Wt_pSnMh|eW*8azy%8exS@DAQxn9~G
zE=4(L_gg-jHh5Ltd<xN_Ak0l{eNfBZrq2_1$gPnAi$0~-D+Ck=1-WAplfbtuCY9<~
zNXuf8u;K={X%at42UA0zvY7}%$e#B55pTAi6DU_FRHQ++l?@KJ*a6s}dsb2%t8^&2
zcn`&{My%cjGB$zCuO1znsB;!2LN|n1=Y?wEioK<m(CA|R0-%)z=sDBxu-nGsGO(du
zFQ7onN#?Q}fpb_7F<v{VTgEYEU-Na$_K^9c-PsOh?o5mdsrBdNHYxN?-f%Th0;HC-
zv@ONGa0WUlx+4LTiKg_mr9J>XPgG=|7Xcq4E&x?X2G2ma(6{%4i1k?yUE4(M*Qk6_
z1vv$_*9q$Ow(QAvO;Y5T^gBQ8XX5ULw$iW6S>Q`+1H*Qj+COZ<4PxD-Fwh71j0cBx
zz1pnDR}STs5k`ekB^)M`Iu39H@BwM@^8_X7VVp@epjNMqRjF($LBH!#dnEe)By}7T
z7<ExUvk*DvY}k!+-b$yha(LWlYZS^TuO&eq2&2we*kE;l?7|Shvf<m2jSjZA10o-C
zh!NB7YVlYOweKz)Gj;qhl2pZb0xz4**3iuD+G*VjL~Z)kk;7lHrtdMla08PCZJF`(
z_zTKldD8m$w}e7lDCbWv?;3VmU*+dl1$3;(NwpZn$-22@bvO={s?G)+L#boO_TOiJ
z585erlPcUyKF>*XbIUY>#irgB@|lb)RRvHN^cPT%6slXqX1FW;4YMtNurd;?3g>rm
zCSyAc0+aO+x0NojMi`4bp59%=g=zuk4R4o~h<Sbs1RmBIdeO*zF0VFQ>TUxxaj-YA
z@UtFr6OY{A=_+?qZnrqBO4<lgx+G$a?yZ0w5+6aP_cErQ^r;4D5?%`Tfq!i$W*f|n
z@GRG>9}q~-hZ!+0QZzD)8F6c7AMQ8Edl-y|d#R;NOh4ukOeId((#ChBKo`M=<kU87
zZlEe?9MF;x;*QVWGQBa>8Z@5!BZsX7<wHNcinxSlyJBQv*p=6uZZaZEg?c!imP$`!
zvm&{~Z+5Vc#|X6scG--Zmp}eU39D6)xe?hc--uB!d4q1z-o)h{j#HIc4R^bWD7nb`
zsm0r_ZluPCvN3Z%P+6B1j~*`6>A3n)%+;0Dy*bI-#fNe6_VV1{v%_*=I&54mqAWAg
z3XmVyRkbAG&>7rIx23lx*caz7vL$Tha&FcrqTEUNZXhFsibRbc*L@H$q*&{Bx?^60
zRY;2!ODe~pKwKFrQ{(`51;0#9$tKAkXx7c-OI>j-bmJb*`eqq_;q-_i>B=}Mn^h`z
za=K-$4B2-GE(<ub7){>-X{u|gHZ+)8*(@CW35iUra3LHje(qEJao_&fXoo%kNF}#{
zYeCndcH;)cUYsmcLrAwQySyF2t+dUrBDL;uWF|wuX8S|lr+Kg8>%G?Kuzxf;L!g<n
z2tfcQ;uFzP=zMS-4_*7={8N^Zd9n(*Hok5S8Bxb%Z3SshR%-POXAUAc=ZwcY0@g!`
zC|k1-#MkSM$xjA%N`=lGR(y{QfLE5zQ=o()q~p7unk|>ZoxAqhd;`!i$5wZfphJ-c
zd|uR@Q=cF4N1HXz1y}KjQJ8{7#aqNM_|j!oz6@&wEfq)8)wG4ngiGocMk=1Ft54#R
zLyJe(u>P{fm>k_wUn20W9BZ#%fN9ZePCU*5DGK$uQ{GP3{oE1Qd^}1uSrdHw<-AM%
znk>YZOU^R94BahzlbdB994?8{%lZ*NSZ4J+IKP3;K9;B))u#S>TRHMqa<Uv+%agK*
zG@_9~S$UcESJn?TPB(0sL2VG2c?NiYLDNK8*{{j8HajSeEHz)O{Z?)Y0cDHnwlWgl
zY3?2zxL5M$5hMxRU0HjF)6#801_E2GIhx<W>-y}{@z#V5wvOmV6zw~pafq=5ncOsU
z`b-zkO|3C@lwd3SiQZeinzVP4uu+V>2-LKKA)WQXBXPb#G9E8UQ%5@sBgZtYwKzkq
zNI6FloMR!lx7fV|WjJ*b<y5iz8TPE(Dv4iwOECqbuZLasiz#SNedZd@D7YAp{T@iF
zlslIE2yRkJjIs=AU05rjd%;~;+mX-$p`pGq6i@kun2FvosHq$6CtSrzvX?__v4OFk
z(pleqJSApg!fQ$gPR=1Uv&yTH*aCoveIg14YOb(b0@5$d%(c)41Oqj#!!?zXpyP)?
zw?4f|*|TZ=U6pR@<SvV3O=Hc}ya%i@m)N=3wdSw{?lJxcfGvSHLu>`&y_UK9mPl*`
z;XO8P%7{H*<oxnGWnFF=q6xhP{~>K=GrNF#+K3At?5`_oXT|Vz!Rh_05t2S&yd`A2
zjcyVJB|#czi?o<&biP<}0alxnpPLzJ9d#_R9(c$2IPXg7=4mL{7WoN>JTCCZ%zV{)
zm691r%m<UGTs@CcI*RoP9k)$KUOF3-<@*}^iboE|&-?v+>?d5yR3l=Qxn7|f0?e7@
zk^9ia@dNTbyi6%GO;kec5sHCjtyr*i1QSY;G}gTsivUQRTG(i)y`O_~K{I*S+x=>M
z;}<><>$k8!-=R}>b#)kmSE&~qf+xi@lJazu^F@~pV>MQ3ISq0)qH;F^;_yT@vc-Pr
z390Cb$Zq{edB^7W@Mz_+gQ$>@*@>hJIjn4*`B@N%Lt_t1J1wT!aN`jpEBE5;Z|_X|
zT^67k%@CVrtYeC}n;uLV%ZSClL-hu4Q5t8ke5a8BZ`=p#4yh?Xa^Q~OrJm_6aD?yj
z!Od*^0L5!;q95XIh28eUbyJRpma5tq`0ds9GcX^qcBuCk#1-M-PcC@xg<jAxaAZ(K
z9Cs+Lw_mae&$G9{rVh3{yU)MxW;<@WLMI~37V>aV`dTbrNS$rEmz&;`STTF>1pK8<
z7ykUcQ^6tZ?Yk3DVGo<BD<xc-Tmn%LrcpmWr}|w%H%}%p1&r~#q?YjfZr0KK#w340
zEq0%*I5F#ZNpw{R8bLvr(Gt;6&eNeSf?Nm<?gh?qa(Xv)&naQR!l^YOk^o?^i|TyE
zq2td{JO@`S>vmRU?@pWL#e2L7cLSeBrZc$+IyWiBmoex!W#F#PlFAMT00niUZfkGz
z0o{&eGEc{wC^aE3-eC$<2|Ini!y;&5zPE>9MO-I7kOD#cLp<3a%Juu2?88km=iL=?
zg)Nm=ku7YEsu57C#BvklPYQ>o_{4C>a9C*0Px#k2ZkQ)j3FI#lIW3mT#f*2!gL4$_
zZDI76!tIw5o=j7Opkr~D0loH62&g?CHDg;Lp^HZ;W7)N+=s>^NuhmsYC?}lxS;sOE
z69`R?BLA*%2m_L7BSZ^X5BKaWF-Y?b-HqGLcTd9NU7vY8k|j{O`cOrwxB2WW@tmhU
zt`FA4?YCJwFISu42CLh~%e8Qg093rgqDa!ASGd!qoQ1e+yhXD=@Q7u0*^ddk+;D{)
zKG0?!-U>8p8=*&(bw!x;E{EjWUUQyY3zVB2V}@t$lg*Bn3FId6V_Ez&aJ%8kzKZg$
zVwL+>zsp<S!J3=qtJdFY3l2w_(iG~PKDlH}9ZXY(Ub4F;@>;_`X|m4RRvc|Wtejy*
z?bG~}+B%y$b6zBRba$P?mX#UbwE{i{@jbuL@tZ6Rn;SCu#2M*$dpQIn$Hqv`MgjBn
zURSnq5+1ReLXsI#*A8G1&h5`YFo^I17Y<LTYJDV#PsEG;0S7I$GvwB!46%vlMZdzV
zA6w<~*Y*X*Vy5L$`GX#<ZEY3ebvrARttJ|G<7>=&&1eQDtwY8HI3#DdGWslPJSP1`
z1D()O()qzD6U~BYRUPw6gfc4Wx!am$yM#i~5MCmF8=7(q7;n3?L@7uuvn$;8B8wk8
z3>T-EJ5X9Z3@yH;L=9QF<J;MPlIShBahYVw?ra1in#iAZg`LxyM5`EeO~%7yl~@|W
zDuKRWvmTNE{LFm)kV#UShv^jA(y#05ioo)j8toZQT(%3>tWmzdE_;Kw^v+te+u`pF
zN4&*o>iRKeC&l_{U^a`eymoog3(GY&2h;5vMyRyld37+7bW+&7tvIfrL9TpA@{Z<P
z#LlQa&pk3XbCJ0)C*x{@U61TLrQ}mQoWSBEkF5o`Hn<~7iINRp`|>dy!05UMhSKsK
zV1FiJ5SlAhkpcl_H0wRzql?0Qp5wz72o2cMC@utM(|&o0Z<PEPLq8j(m;_d){7lZ1
zF_OaWlle+Y8g%~*Z#haKbN@W`hIv!1T!mINCoGsLnABfWym7N;@I;yctV@5kWyyDe
zR)2y1Gs!c^*V`fgO^1?ycV>O_JpXr+N7l~F?Ef_02md^m|Ly|(EN;<FF6ssODI7dr
zRW)AjZU+DZ4JpJNNaqlVN?SJ6w06t51i4l6hO^8c{6W|o%93q^8KJS4!|lXy|LfS>
z%;)3t6SWt{5hgzszZWS1v^AU?`~Rctor7%qx@EySW!tuG+qP}nwr$(CZQHi1PTA*F
z*Vo_ezW4q*-hHnl_8%)^$Bx*s=9+Vi%$1qr5fK%c+Hm4kiE$B;k<pgoct_P9YzomC
zw4%GWMU`<CW1Urq+H52BHJcz?G7W=}E(b2qfZcAR(0#rf@)f3Tm7?$@2eU4%!|L4^
zKHA+&HHsj^O<U<qMt2LzGYAh-i_g)ci9(y_cY3LPld|PT7wnKQW#1fJhwfQx1y-)r
zhUw}V44Y=D+=E=A!T6o~jZpxboJ3r^71MZ!CXcxeLpD$wDJwM}&w7dWOM-H=zOo4R
z5aMlRd)R04-UhX8^6m_6Gb*@Av6y=0ZB!<ifyf9DxAOgXUF>gV)wam25w$Y7#k5$>
zyB^6k3i~L_6~PX554`c3Lxx;&_sT;I^U92G@fS6#(Xv!B%;H3+{e)1R6lyU)8AK1_
z<b9Yx>?@>F5H=sXG=ep;kDRZO_ofS}`Jus*Qp3`_V4v~&b-RQ=t8AN5H5{@!_Il~0
zZd!-aH=h)(7CJ&tL%%{P{6d_g=5tsj%S3Z!QxjrLdjoKmNP-zSjdJ!?qL(UMq38ps
zjKSz5gzwhDFA;5md5yYb>QN)U_@8Xpjl4yw5065)+#MSGp;yQ*{%mt>12;$~<lHVd
zN)WcYirx|8&u_*vzY{vQsf1A13nP`x4p{!Gj=nN$nssATE}$So=MMM)DL9H{?MW!R
z=w2AeegEeJc{Zg*|0Bj?!vX-H`=1_2nSUjZsQo)h<X_g1f0K_j>R{eVV>o|juO{Z^
z^o^m@DOBrE2mm1nLgBfA(Wi=X9R%(1UYZcZJ!3;*bR^smI~6lyn`O4<Q(G_aC8)C6
zAuc30oqzXiIse`<ed>BOwo-STsQcyodVA~leg9`{=l(qDl@DCM>s+w`%S_q*PIjYP
ziuHHuj0VVW1%+TH*lx9#-$^q&l)G_o<!|`B#1^v^cZay|E_IQgcLpGM3h-|Fk|9V-
zkh4=IpDN1wq9cgj$^$@@lqKz-clm)(l&VM3fnmzkDM?lL4DZhl8{UGjd=>jju-w{#
zVs{oOc>_fcS51xY+19tN`;V~R0wVyu<YRh@cP1!$18OSXFnVhDFy2ZdZFe>xdkS|t
zC}~Gtu-<wjaCbr-XJR9748Di`awuQYv3|4^xJvg>UyA{H5~6*ocUWM)RfQ076mL1r
zFVWV%zx!_*zk`5&d<JA+8Y6mlY9M|}3$cAvZ(%^+$<u#N`uj-Ki$CM8@#si#<;dL?
zAw4Du_TdHf71Yc=<<;EG(%QP(R<?-tpKzAQoaOl8Vmv$x4gAcl)A%i#Fd~JY<(u{3
zhM@yaXm)*Ke0p~aUPgWG#^m+l+Pu#B&AQa|D|&d2*?5Zn`X5{@7Ku&hyMP{4j}H{E
z{>Fbdq4nbWxIwAu=`+$V-`m<*-Z*mE2X|>OCAJVV;wlq0E$hVe@&x7V(!xg1*;%`}
zxxBu5;jmZEH*e!Rj=Mz|udBR8BR6LiGoLWb<1=<14it;Fuk$6=7YCR&;F+%r`{S6M
zP92W>ECy`pZR$Q<6n8Zw1|uh*M=zK=QP0b38_aX#$gB^y>EahIiUzy^MP1ct%UhZX
z>FFLVJ=H`FRSq!<_DtWyjLZ6t^Nf|?<69Aj$U0*lrAJG0{t;t8Y^SKLacoR%3EXw+
zDi5T^PkjmJp7@B|$lkEwHHaQ7BGc$})@qNRqk4JH!(bgPM!{Mb&K<yV<jHRMWIVoy
z#u^lpT9VaBm{6$Q#Vgx7GGuBV=mm4Rl&zI_;J=qdQMCaL`aB=*Z23ry<fzS<o&7tJ
zGx2dXgoDlOHa_zC?MFb(j9Ll?s~b$yb*40(w;?oo@-Z%6N--T-X+1$qG?wE-;&n?S
zk)DEzpu!Q3^Gnok8M0Ue0+Q(R;>z|UGk?Qsk<?2zwD2RMgFHT^kgO68uk1$kaQu+$
zK?B8fq-5;P5b8y_Cpn^n9u^CM2^E(Wlc<>ODW5-NCJ3`Fbks<}%TsOB+e{Hn1i7BP
z(XsKkfl`r0N)u1VqaPYGlDxR3>%y{&vYaQCnX8AAv8h8>a^4<#jAhtfa;T<VWT@C$
zcAr@%#X?7E8V^0eKy|@fBz@}eT(aKTqEMVX(|*61Fp{Mp5>doFlN=?Ac{@Cdxj{YI
z!kxobbr?~GU8JKwH2Ywa(#i=Rzof$nu?4-zlN#QJflTO^QkyarxNI<~MY1}jy~Jz`
zBRwV&0+G01D9biQ4PR*1NiSqTXZB~NdI6yVEU|AiWJYA>k9G=*`R^VFjr{jhqZ$&G
za0#huq)Mhb&8oR!jrv%;xRe@b&PWBXh7ATurhUY7<a&NYjA0Tf>yobngzP;($8b5g
z9U{5JMt%fMp(N6ZVGsYa2p(#ry;Y&;GG(DG((_<Zcui)zvbEB%tBf`&Et+}@|0YDW
zbf}&iHS#l9Oozxt8O~FSwBu<ZX>GrS%r&waWuX94*RX8>&x|Lzv8WCaXaWo(<C;Bx
zobc#{`&v1MD@n8KJ-K5{V|rJphcoU1QK;3_>3FK=U@G#S$8kCX_R6q|VO;WbeXk~x
zmq?NS+S2WfO|{j{dKy5``SRA!r+%)`DCW{s?8uZJW{-4%x}KJzAtiyY6b#)!fe0kA
z)=W5C>X6ZLRFH_-$)Z(B8Hr}FD#FLGum2gRluDsrJHf$do$r!ORQqrI6~=-H0vPiG
zC2V88MIp?Xhc&UnIS(c)naRXTu-r!%x0J;3uWjp5K%!b_v$;;T0*{_2txs!*+BgP}
z%eY2;N7AFz(g@fFy&(hWk`R9#fRZ&X598A7xjHyoDJ4!3CK{Grr4>0<Pu-bQJPm1~
z3ZL+{{?5v5u!pZf>bTBw3ps{tN7KqVY^)~B5<X_j#!R!Mg*@9{m0oqN(P;C_h1SAK
z&NY_ma8_1OK<0YNBSvBmHJ$62XvXwfpp3E}pW>St2NQS9wH_Lc=s8$1H5J?52_$nh
z+rnm{F~bV<RKn)ryqnXMtd;GHb^w{yrpZLgy27Hr3|FIVKEH|@_s~hg94A@HJ_W~w
zn!A>IsiCZ^Gy&eV*X9JTJZB^`|6F$9|Fq@ekZKP~h_BWGsow^hUpo~MCTrdk^1B;=
zNXiYAZnUPm>}{vX*&Yb&{0FNvW!V)h-<{na1yT-|kAkG7xU7QA-NAc|e4Nf2`OWnV
zxbr6@^w<Z7vr$p6)@)lM5X7EeVt}e48rj5_sbN(%z$<ZxoTI`~7JR5|)2b2RMLgGW
zxlhK6@t>O^6xW+Xdu=Z{sdK+Qw3Dii+X&Y(VdCv>CFEIOt?MCM?9@CDUKm7+N>%!q
z$WI;(L@2YJ&Qfwr7k@<77r}%_q3O8c#><<+(JFdeT2?e+nsP4h+`n(HuX8^8qLN88
zv^9`|ICnNwS^PYDf7ebCGG~QNosD6-%$5;6<Yd`;#g3;T%=7$CQOe<RIqmU=G$xQC
z%xa)bppnQGB=eZ+D<@Ly#Yht0z!$Dg?<F{e!@@BwCnA-r%F)1XrvL7cRA9%ZH=&?P
zf!kYuV_ymZA$_l(NpQSSP!isXo)7M?rS5X<n_b%Rf4<Xa0{~M!<irN7`;m1U(2aF(
z-gP0)$!7dMRhPqfb@V1S;hw%1pIqN}XExy;y<bRfz@zMYZ#2f*j}Gh6*E`P*Y#$?p
zXryT*twJ!Y+5o0!nC(Sp!<VMCMfG47I?&d~^ytmBIBsjAI8PTf5E_7v1TD*F$8kVb
zL#>Yx$`PGlZVnxs6ntftJW^L?iy3KIBDW&1q;{OspV)`a4w`+K45XmW5g6HLPL(lu
zM^>HAPux}=ZJ?|;f=zDh!2|)WLyu7pHcc)9vAr(R_-sI`3GRfExjVpYMgql~xox)Q
z)W3=WFT93oM<sfrh5>dC)bluYO{cphI8Hjl&)W$TKN(PAk2r&mB9-)@%@xbewYx!c
z{}phewJ939{qT;q&KR_!>>XnVYPC^kRaX%+G_v;*kg4g0jdi&G2G5$4#bk+*0mK8`
zie_>y1oDA_0hGE(n`I(s0k(P&;*KDaX278vofbbNMZ-&1MCm<E#?3vdvlx&C!E^6y
z%Nr;4Kp#UhoTqf#96{V^MH39GF#SCI4zIvIEsuHlWngU>PD*6d6oN$VjMzpTd@C8e
zg81s83_+Y#T;duYQ%tXE$RWVk=@P5Z1VY<1C?mU)7?G9IHYx#rHCx1Mhb!a<IW)-;
z%8)HdAH7t_{i0h&7F*+>jXBoJ-rANULXqSAu0Mn9s%@_;uy-AOG|5#jDZ3j5dR7|<
zR_{f>x5E@uRa$=rDD-yel$t(bf5=#v9ZWObAu%fou?4Kk<Xwr*>V-kv<f}csM|CF|
zJBi_3H&``c!GbiK>jmRiGX7iDe(Q)_^=>m}`2$#Xi#5CpJTi#5EF1T1mmPB}c<v9l
zq}e?4xpl7KR0xJUhRx@uN%&2j3vPH(OVO-{J*Ewi3k=9@SVQTlfwKLA8|rN6VCLi?
zJLjxm0#gde*`}3G3mRr5<3)0&BuPl^xnS1t=*Gz6eKl0G7u?d|l(14pCQ!s*_!VrE
z9tcP7{`mwW`c^w*LfHD0o)~Q)CD>@A6ou~a`>sHSeM4gF(ksh|DObX#Ao1r$Jp3I3
z-#zhd+d&)DO54E0K@@kKgxRB5%x&3BZ$OrawIi6~b_kN~$5G(kH6b5BD&%g70UWu6
z-ub`EccvhA2YleM%U@;V)N{Ixrkd0bjN}m<e=~F%BMAETB$;lrqdEY}O!BRrUFC|(
zVtOfEUu28sK049<m?<32`T+nfwTp%}#e^lj_<N!$7^NUijytn9N7aX3!;ui3I3z2a
z9R7ja6%E?URos1~?oZ>=kn%!g%wE&P@WcBs>5NJ~t}y$Ar7F1n_=iC*<|&`C=qG#+
z0|)?s_kRK(@&?Z40!~gQHirKa2ua%+8CVNj{J7LD3|*Wp?EV9b<S6b)VhN!0G<8j|
zUTh9O*R^V*2pcMPqV0yK1_}oYnuCz!yCoS*lUlnDU6bm*blNEm;JY6HJrzXmNefoE
z&`H|$_Hq2+WYgEPx=%0wuXS?5uoOV-?p1@85iK+;Xj?JTixO-`YSs_$=^*jZffQ&F
z`^lx<1893{6rsOG(Z(MU1*#K)rZcWt(6T(Y;Gv2_qK8xF^N5$(ZGxF^G3_%$q-u(<
zO$A9W#)I^Bv#}N}i8Tt8N8tmX*dl@}Lb=3&_+T;WE<n7;H@V=T-qeNrn)e6t<V~O9
z@<55oTXV(ds=jK)ezDUaX;fVscJjo`Jqr=buu*3B;w>Z1_j%PH`5U;9>aTZzwPD=a
zXur{4zSk&)HrOFOmSK8ZKMHdg*HQk|a($OZ(0puje1K8EZNjPavWjhh64i-B(p7Zf
z2g`IQ_W)I`lGa!LCabrDUSVPmGZbVX*#xhnAH|koEn~hs`=w;zVM^IEU${9oXf4C9
zk#|zrR`2_TI+u08MszOoi%H;viD}|x@Ax-{F_aW3ZIQHw-pT;hgNi%we<wp6P$AY~
ze{^A|KlqdS|9JWT4LoyHE!2?AkbOggrO`p-!wbk;%yk3-i&s@?%0*Zq1o;OQo0DY|
ze~Bh$urmo<_iA;m)w(u#{gIrrh*(~F@%onh7L=3w&BYW7F9`P{wENsU_qlzx`zrhQ
z>uhcB7xt*kubK4fep+r)eaJIl%p9|sqv{M(E4lgwXe=HL2nYvO$$HX>QpPxqUn}WG
zs*l{rztHOO@k5#cP%_alezmlZW9HCcT_;auQpbtV(Kh6e(9wF`C;OM(L&uqUaFglN
zk@mRfKGV716J9j|zU-6W(m9pmEF&sbiZMv*M3~8lC~<@%sH8mKCL5zS4h--)TNbi$
zGT~m~<Xqt4Ugku^#E2G_alC=jiAO22lT<hzpy#Naak4ABSXCNGR&o%OG%|)=CM+BT
z?A|tfRa7=NlUE&uR=-+VFqStdD2qVNQBrVl6J|UHA92){M|va%QO$D?4D8g9OthQI
zE1a0K;-oz@P~;|JK%Djm7gJf^Qg_aHgrtLkviQ(an-mXsW4G4A=q;8=i>}sa$tL(&
zG_GBAe(+OZUY}-iY-rcb4f^fNZt_IXS52F^MC6>C?-IuOU<D2U%OD#%fbX50V0SxA
z#1|nVZDkSLd#P7gVRDpiG3DCKPh;dLF=CSfVF7us<)%T?=B+6GNo0^CQe4Bm=|TFn
z0UZ}7dW)@-r*jMaOJ1>ttpxwVQBy0~D@|I1g*pQ^8D9@mu?5(kge3_GjbOm2G+7-z
zkx`X#L5jF0+(b=RSgOE*XGFk$mF562Yft^UFH0micC5KNH~tfuDq*ce5Q~fKPyieC
z9su^<T|}5m7lk2^7Xbk}{9L##e9c~DnB0(1cT5G>F5Df-F2X&FrZ1?<8uQ5h`uh~m
z=&m+g_sL;h^%^JcRk%COiklbyo`Co8z9C%hj$&e+^pKMm>7Jt({+@)$DJbC`QjMHZ
zi%3X-hLW4Gca)8|Pf3A1t4Ud8Gcj`ZNDE=lz<+3#C9z0jMR_q934+6jFXzJ$uCq~+
za-#O3p1hSU;tiKizC8=Mh@y(Ne3L{f0B?<h54#Vaj9g9g_az0qaDE57O&i)uDlHYw
zB_Ih>%ewopC*<FLQjXKDcFE0)#)1;mi$wj4KsC&$6OI(%tX!ssUqU1XtW_mjY_&=m
zt_b*Hv50eLU#WV@>gCiXqueXVpGg9HaGK>hK#}F8++%^d7M6b=5@V(e#PAgrUnD<Z
zGZ9!Q=wRj;s}PgH`v%8HVZbKv!jnS{M`lxFP>^4)b1JPZ-PGNWqckW?kadj9w8b7f
zp6l)!4JIwHtcBOekEW-B`yJ(E6n$+g06FFIjgZzz&+`UpKdgY-=lxNe1BI|=Cg;T;
z?FYQs{*)^&tV>xbx0m~jf7l5>`+q#>!*0u^UJNZmE(3w>j|yNHB$#6zkjE;_0pL0S
ze2gb<KtkiAe}I@+k*^3tfg?(SqX@?lyxUlTMZ}=fh!*1Dz@F+k2bTGAqH6|FfxXJt
zlY~8(*Rv!CmF>)=zGHVUt5ge;3k7XmZcc5;mh=#z-ZobkM!xX0De$bw@9s|&m~zN9
z!K5tX5=4qA2sK|$bdVMz5etUdXN!`}2PL8R7qLr)<a8|9Ax(EN$heY)`+|&)H>Si}
z!IONdCg$e~UlJ3u{n50K+;kj7SP&tC(^xDUbl{fdvL#ilA93{7Vm|&0)1p+nx=!<!
z8a22i)%L7m9r#kgjn(JEWEO*7$Jkg+h=-oV_|jv4%O%SrWaw$r7t+~+#l3pL1VZq5
zy3oTe^S3GKsl+M%6e0s;3-94ZJ>XmT2qv6B?FjPHZV*SamC-ro9lXMAb<nm^4uzi2
zh~Z44PXIc>WtsPx?Xq1Kcc_^$@r-YuI4|#Q?})HOyhMfBUVTIsc4Su?*<H!~NMj7^
zL!PUBO<c}&<;aTo*sE>`>kGqVs(0tbI_r0@mbv4tR&NZCQd@%?W!R_Br)qtk^~)!$
zd{bZ$2k_tV&)c$dz%vTer6*=naysJcAnpE2vboBzhwzL3ZZg^xE_1)_2eUw2B&FcL
zW(!+zg@=0oy{=sCi##j;)Rn!Ty7I5A;QytP@}FjBaRXc9p9bUK6(&VZ!%ayA`L8Y0
zHgiu1Y%~0(WC8`wP<c8syrdNsj-XN$2(sOhkmJ@9>F)OYDg?-xhpK#kN37I*3t$V>
zeFT`E`_n>;_dQuVYN1PBmZ_}9TfEcl#^=`Ab<?Zc3&;EOUY;*#J;>h1!Ek&ykSp^2
zUtg|J2l-(Fu4-@Z^f<izAg~+uz%b!)S8;TN12hK8zzu~^0<72v-u^6nJ7lg@!|1G-
zH2mNQ#B%UQQbIwhQBYwid7vCR*?IKX4TcDcUFofRaNLv4G08i6+_nP<Sa#Y&2?RL^
z^-HW553r9OvF<J~FfPy!V0O>ZW1~i@QYwP9Q9$d-lN6U6i%K#778wN;pE7`?CIfN*
z4j%4F^H^LF6Q70%gi@GEB7#Kar{F)1=Hjc!yt?q2&-sWb^&Mo@Ali<?FJKu~g1n>3
zYsI8ugwjs$rA3@sca{d2=a5mZ6PM=U7R~l1{udpZzpk<&^i)W$IV*$FUzyJ>#@G4l
zunDZP3O}4<CXfIt5hWSVRf!mQ2uQ>G8=e2)DEXo;q|ooRSY*pQ@?dPnSA%LBmzMuh
zj6iCX{hWsksbMQPykb&WEA^2^)4$ly11z>xG12rAj}?8Ft!(tswaOoNlpt=|kqrTJ
z&?vxxBG>4bNn(%_w*|gVh^|*LD_=TzvKLX^EG3#)_JHhIOGSwPo4|0o#`B(-!+g_f
zebxHKe=60kQz4i3=g8Q=o!~GyJjpp(m|JFSl$~J?ocx92m&&RUW=F?w)i?X8sjbbg
z0+7xvpM&&Mvk2s6TEQh%-l$+wW+-wwx(yPsAW>CS<4@5r)9$_e^l&p0?yxh8t`Ni|
zvkg20%R$9KD0hWHDff&(!UL3EXA@7RAORZg2_v!tmF`q!lSi%o$>srm>6H|S)B^2X
ztV|vT66Q&WzEYv3LCrtL@fFVn_1u!3AIwvi9c5g^-LY)$kEOwFcdT%;T!@=Lh3b{K
zJ5DKC5TfipAQ;Xelrj5>A<F_0bDsQwIxIVBe^iW+H}wvp?GrgK;!S%HEj{6mWLEqQ
zQV)tesx;BLePv^F9sdB!n@a!an}(NJg|;FhLqk^4X1q+tw0S9o6oN&%tD<t!Q(a0>
z=_T7N`9+b0vmdY_zM3SwtpmRY?wNX&N^VG?5}z__+A;qz)l|ZX+QaujvNXdiXZ(V?
z{OmPo1P@Yd;$G3ic^NHAm|1j%cIXFahDM~236V%gF?}nu9!H?ApHB?XA?IZs*m$xN
z6e^ufgCQ0+_=81#=-f_IGbvy4Xizg)_Q^<)baO)G5(D<h2Rb&#$y|)0NL?^hjpA>O
zgxn}JpKET9(UqM<ZEpa!8s8T3kX!M-*hg3RrmCPh*;RMHdnUbRzn2d#89|sIpfmJM
zZs^dvn{+TbvJNi;@S!(1*+zoC^Ad*{4#OcWi1xn#Vsv}RDmlRaIfw{%5VaM|0;I#N
zE^SLn(zR6v@rWs)L-J9AC~FN7rM(2Xq=`Wz(9Vw|Y*w^l3AU1e@$A6>upTD8jB3cp
z4G`IGH%ByG7iZ-QD?Esze`e049rA`qU8-l!$qPyeHl#z_q%CNdv(L)XI;?Ng4p}qk
zjkLr}p4PA1I;7{Kc1WJp_Y!Q55JqK#sB5nY)=dehb&d)~g=roafxSw>Sbm)`xVXcf
zG#`10jAW<8I#Nd!Q<)M`*0YE;dZ$(eKex&V5$dNnGAi-clRskp_SX#aKy?8;Y^RA;
z@xEcdlr!iVGK@89*}AMBb@<d!X5*;F?il5tHLQUEGd=CI<CHt-M8drWt~;t(@0-Uf
zo~I{&%1se>T}NL#V3*a00ErFr0GKMbDa2<jN+ec6KIVjU0t#tI(VDPC(y$@Px-o8n
zA+yMFa^}%4r8>oQ-DkTV{N0Y_X9!nY1oWN1B)$PK)1Hfas5LPvtlH8ZL@g6sQ;=~>
z=vTK;Y5TAt=ya36;hG?pES_n__RRVv!qlpCcy$N%vN$cm%p@=41Lzl*;2C>KsLXaT
zT7L{$DZI@k7u*!SE|y2=Df|?99>gyrLB^u<lqJS7tSt;_l3AuAO~FzxChT_ugB*4D
z7v{Ii;w@YFq}zoQgGY;i5~2A>r<D3PktH2^vs{x0PzE$+=&M2{0GEW-Io%Mf)%`!5
zL0m#=rUyUJcMalylgaiUuib>~Y)vi9TpSJl6Z57d+o)lQAdh`R5kMGB7)eE`*Q;2G
z<Ehp}Y6`OvCyR?4;@Ws4fUSp))Mq8_^bgD(Lp_f-jG_Gj@FkCPb7c#lPD1lZ$mnpp
z?Rm`l&Y9`^{__ah&-8^X0Js-=r-N<@tYIw{FXW5Mv<`6ulIJEw9(>QEcRN!Q?$b+o
zUoag8iRTMmKuJ)5s&zS~S*B1~zU7tUT|q&h!EInBeZf#vwR|05>zpU0zRe0VWg5C;
z+*3eGa6)oAS)<rceY&lj@jSZ`vO@oHeTN32s3o}Uax(2yWY$O&$+1XN=}F)0vXuW5
zMJ3dfBHF@FHd6Q7ETiOI8^sh)s{N$oqVz%Xw*};@qT{(*&+pT_6fDf`Wtg4aMEWdU
zveEul58=;-LR<5agNp#x@}{8N(cd<>jk-xN&bD5&{yx=Oh{=T<=akX4F4Yue*V0VM
zkH4;7TLKmx%@)s6c5z_Q&5qaRX;$2vIP-ud)H84PAd0uJX*ee_AkeYKVtI6CW@W(9
z<?233jxCY|BA$$)`Djk4PA*-olx-WoDWs6SxqO&Zl{amM7t@#5So|E=zGO9#XQsr;
zy}g#t!(Ddl-L?UDW6hSQ5BBA^7Ch9_L}a`s<&y4kZ>8KHRBux28|zpfOJu7mRVm*s
z%?_&|3rLG%MZsk-XuimeAl!(zkxHX`$uQhJ=7%b<zf>ztEXtmw!ImA{G>b$_T&F%g
zFsQ^s?i59_UX8n_!c>ZltM6ABcMHOtRyrRBB3#Yo+AYyiYjPIXgd#0RF$%&xX*?+-
zsPtBuy)cP<j(M@vH`kGSu|8OFrF(1xzCWL`t7y+2xGam*e;-4(c(%mbEJK|rmKCnL
zIpqCaM|>jVkYkf31o50Tp3zUe-dekc|5FYz`%%l5L^><o$-yLXI$f39bGpt@DL@xI
z3TCVmuUF_n^vG5$?fAk1SjXTNp-+l|Su>Pje2fT{!AGEHxWG_Yi|{!_@x>cc6%5SD
z$ZvA==C5j@X;L3MCV!XA?SG9M0(T#83W28(9aS(t{d&siNAR`PZa(ke>q+Bbo82ut
zvU5xmnR~F1ffCpw7|Fg1Gx@$)QGYDzf$|nfH3sKP3=Huhz#4)dH-ay~7cR-ML4hxY
zJC3AyNh<#3hBqDyFFY{D#*eE*cnh{slzoT{|2On)ATR!sO#t-^ABA9?$(s~V<1UDq
zyo>|Hc*Nrxk#`IYFkXaDTnoHWAP3E#`a^&-`SJ1RcPRHkeTbBZ&q3G_0==kIKNsi8
zPK+SND@w;5@(Jm9!|;LDkth-G0@RZYW&YJ3k={qg)_?xtrkih<Qf&V@EqZ>&RnY!V
zo$Y^|7$WW_MlSzvW>1PbggdqghA-L1jCJc$kjxUI<c*+I*9Ni97NB6%JXJ{mbHqk*
ze5z(ymIb48Q`7A%D@<5hp*udMAPTTRHJD`-^Myf$nSwI1-N;XNiWc70=Zy5rB=BSs
z*`waxtMBXU_r%dR*9*D7%3EBdTG(ACMmtEI%6%t2U^@#mNS)e!DE)3YTSa>fuHEPj
zLAS_=)=>DNjluF!EIspf<>8IN^gzw?ak~<)+k{ykeXo%GE=68f$Z;<GF3C|(qf_4W
zF3#W|Mqd2Jy`sYb`rRm?#>ZaxUAiN%<HrGb+{AmKhxhu(xL|vEWOibHxUdF5JQRO1
zV^?+4BT7<1cET|+lSf#TG2wzE!>zGF_5d-JZ0I9JZ*6=&gi*5l3i_WA7VrU|K{v|a
zF=S?&Yw?$7*XrNDug-5bH}<wVn#$U`%6i)D_yvj|J$>qO#ji37gcoNsG74BAO>OHL
zJ+$W5wVs^^<n3ia`afJIUKoSlw>UjrNk2QiwyJ(aXP&FiHZNvXoDgPCs;lE0r3q^E
zb1QZFSr@``4tbojlnOSCOUjP5QW*?2!?w1>p3YwB&Mp*GO<UNC@#oEsLJ&MvWuY;{
z;k|3)#G+1~spt__+YUiO8sitO7AE7H^;?q)r_Z93yXL2FEsjQztD|4QEPO<spS(mW
z_`m@`Sk(fS++9o4=sF<@I-<35dnByFoHfb0yOn3s8eUn4aB^TEW=dpm^<|U4n37s^
zH=9J}JiT4gGBB2UwFR>3M*qgz>{jv<I2mc^Hvg8w(3m6p<+X0CerRS(d!;yHrjaP^
zG0K$1)aW_8Zho3!(*+5*mB)lK9l_$IiRoI{*Cr&G)&|*uoRXp9G1!@}7O8on;vKts
z2JJI1(DLDA@lZ_TQ(s1%Bxo86VS7#_a&#UWE8VK!wH54>{ak$b7(E?tkY*+R+^&>>
z2dO%o%W=L!QGyw(WuAnw#oO{!I(8KwC|wq_y)<9lMxDiZwL#OlUU_DnD8&!tX&a7f
zewQGgB8{dwkjR8EC%AP&bY^iirN#jA47*}#6?~g6@a?%^7(){yv(mgF=P`2yXr$Ab
zuYEY=Rw^DeYTFZ^Ywa=6!`PU?q?O*FI=gFl`bbPev2k8T+=C;_X>sLJQt7BpOATpg
zrpfyxa?;Uc`KUT2B@@q5dI0rCDDr{Q8d~En$h%e_rtAvjTEMd-OH%Qc7)o~}(R!O`
z(i0MG6N^6LsC174qc^gK-0ayYDy1n5!q9mg_|<rxKVmZ4STxG3y6BiH57Fe6#>@<(
zH^wGhrdBV;Qzf}LA3=l3S|l{2(ylqgc3&K7pj~tzGSA`-wO86b&<LqpcLoEqH=u-R
z+dqTZOC?A}UQA*6hTB_r0OnpPsKeGy>05pv_SO)Zw_hfmjx}wah`^|Qo(J(X2h!rc
zPxx05-j4zshL<KqcUvE2F(|gI*hECkCp)uA6uXQT&F+unP(1p(Rl*yVz<15GFW6~{
z>Mr@l7%0`IwPtjmgCwA{Sxj^m0H$vopZOcn-(l18gE{v?!K>bbY!=G2sL;OsI!wlS
zl`om0y?Z#6@8vtXFRh`e5wNSy>T)H41%)Nt*jt9t?c#B>nB<NvX3!$j(Y3{iCxc$$
zQe90*)MTu5?5XvSUPe9Ex2NZaom)mt7PI4;C*4(Z>knI{Kbhq*5+Q8Lxe_H!J*!N?
zH;Gr-bx%ExZEmt^9#)xcGN#!|?Xz6|l^~v7U7wM4&5cAIxbMj53pOBXW2LxqE#=+s
zUC(EG;8)Odp&Rd)Qg_wrCnDExg_o7dmilm!?}lv0f5NK>w#Db7WRQa5Z94pw011GV
zyHnjESKowJ&H%GT#al{iWgq|S`7S<DIAvwHz(Af&q1{G6?dP;dy)Esjj#xSYFC&po
z+>)<lPkX(EPtH$|9{MiU)F8{X<2BQq>99~4MXM?gl`=`rD9WWj$*)*NbWq$x&Jdq^
z(Q<+*Sx9NqE8$^Fqc(bfoIHwRM8##C@jW61>q;vG-*gk8G>_$;P+4b&%lQGl^XQpt
z@48~+y!wp4mqN@Q?HOZ!Yr_;kT-E1R!Dz4OldNG)t;&2^&}q?~dMa&r60E7E)}#><
zrV*SWbim~#un~*J_!+nsWF_-x*9gTk>Hl>g2f7!ZQCMExX9omA0+-Fd%?Ek`^u5Av
zTse2a$3`W_+4p=xIbdWKo>d*OlH=zIocE<>kNpS;Lx`OQ&-Q1P$CASxn1-0<yb!NO
zR=En#96@LYWGde=^eiBDOfi${6RM&<?SGA;(n8qyb&DM(r_UO22LDz)6h5p4S46Pu
zi0-7NU4r>~RGYd=l#b>XT!xg+7u%F$Q7jSakj)eTa>Ty2qji4Eb4HFzvHy#qP|SXp
zeb#Lbt?Nt*I~QuZr{s3Gk%GGcNPV5<BEJ199@Rm73s_SYw~$22p6yno=`50#`K~L&
zRVR7_`b?WMKY~_WFph2M5=x>a16K0EjBCtb^pLdk4E5uLHP+1tY@v3<XFarN{i2<b
z_8SU+vIX59+b7y=>z5hntx9$Vv0Tj2xkovNOuQz_TE%+7VTio)we=x|p6Zw6woNPx
zcG_Z2O%BbGxfe9ld2ol=fLGR4aFV*%y*3D#mSjOJI|7z5B4+&ACSoxT&RK_fuBkxk
z1Z{D-MxPSpq+f$DN!oyle^-|TkMi;fqFJ1UGd5NFA{AM^B_NurnPV??jj4yDq`QF!
zXQ%rlV=SedtGKM5GccN+LZ_zY*nRh^QhVnOGA2jgF~DjqY%>eUXu}5pt)p9N9V|0Q
zXC@$-8kj_9y)dSR&f2Q-S$t*V60-4m5IfeHAp)(*?%V*RU3YRI+fVm;XbrN;Znfre
zHV>~Kt<08qOPU*d|3s=CmW8uaSX^bMnclwZa0*-JYD_xdlH-9QSVqCTFRD6%n}VS4
zy>uY+r9H8?BwSa;PMf%#`x7lDq2Ra&?)MJ=q&X-Vdw3kLg=AF;<RGPiFQ|);tUm7f
z1rf(b{<SjQmc{@UHBBcvI~Bs51E2g8k5i&Iir*rhoa<K}e%zYHh4I*BkNUzDj@GF?
zG8s;<XDucP407#)jX6O6lE5b2GIqYnzwm2@`>bh`Ngu`{SU0AP{2FA1bXzI)&Qc+N
zQe2V^EkBDVUja~}gLyF(bfSN%OWm}<eG0hNysEb1vtkXX`9{Ds9%!VK%t=AGh)mFw
z?w~ppo9Rw*)>6u4HUH3r`v7TIiEzS4!DYc1O$+O(bDf_b(zmfoP2*iYBPA-5lKMee
z{!TLNugW*re`hye;8u`de<Z}pKePAv{-+-BUvt|84F8qoZR9LuXJhk2Zc1C&n*5+h
z*Pm?1|A*$xQL#}%R6zEvrKYn@HZ4x>34Z~ks!!LT7(P~?WfwY)j%M<?YP4;KrJimy
z{~O^O<uj0xc>(rRlsVfY75wv`_j8-f<~Zh@@_No5u3lgB08$gw3J7t6YYm|-P>#mI
z?Ihgih8w9<&jhN0?+L@xpaZf^v}|(+(B!Te$gx^{k_-y<H%?ufG#PUU=~T!WRmw5C
z8^>^@xZ8pvz4Teo8$&XcRy}gCz)E#b#7b-MxVm-OaCXYoKRhcAIJfQDELSMoUPZ2A
zGJT9WYcGs3O6S~oE52|3o?hBGjTo}Z^#p~Y8HA5Pg?)uzq1dK9(?}wqZwRa130=%H
zYf~z=E0yYqfTG0fyWBEMhY>h2^w4T@H3nLOIgGoExay2GP9=7H+(sF!>QtGs1-g&W
z_gbac+_K^zlCn7G0blgrvHCKoOxX2B-RbMlZrJ;wg{CYdkQ}uH=vCz{^XL9b<ITT_
zWa8SdkpnaiO^sjVkzKQXbf2<q-)23>5<UcK_~StLu2kE;`pvtChxq~joMYqCw(1P+
zw1n7%*kz8n2*?smU&~Z1#?@?4ZAcSM?P#z)s*UbI9Q>MT@I1LRLBCN2G_*J_s4ZGh
zWx7MbR#kfA8X5^2SsOa1ssX$FKr+_smpY<zk;e9G=+v(^HKEMJ?$`puk}w&4=biE#
zc*!p~j~WM9({6r=Q-ic{6Jwpt(K|h#1wW`My_n^iWS_Kje3ug~BHqLqv$R6CnTz0x
zi0cu^2ybrRtByoVzWLY?>Mtr_8IC^|BTXp$X~a|@aOR`r7XM(DK=Ni-`62A>;$AvH
z9_f{d2&YC<vP+zI$h8kQz8y3iNka!~15RV1><VfNY9LLptQTumJa+f3Wmu5pj?vTK
zz19_0N4nkaVJ-6`ACjv0nAVW>RYk$@WOzak*c~OoAFfe6f@DJQ(UOb0(1s-V6+8}t
zM%Y6TDbM(n0`0~e(Z=fVgs<RBw^a^BM4C~g+bqU6w=Mi<NXtL67k;!(LjymOd;}N(
z0Ez$8J@ua<ssHQU)uXDRge3<5S5&iMu@SUb9p3tI{howh6n1o!RUZtf^(34q;m5!n
zp0+}WTC8K@Hj==_N2KCAXZ1iBR-E|Y^j8iyadM@JlV1#@pqNla=J(UnllLDPxw)^0
zH8?(?pJa97?0z1ESCS{f*(@-`T~Wb7>Qi^OTtAv{cQHYLACfn!I5^C`4kt?8a_m$6
zbcTozSL$v*0uQgb2#l)xk-#q3kt{M?g;oWD0s&KKtKIf|mIl<W*e^jKol&XyM*2LI
zHEpiea#hHLMJQ8#P&s9~(D0&LPZ4sq)0SzPSegn)$uY9CcBFAK)pWR(h9qsNIz4m2
zD5<K|h@!GdKcm>uc_x>!Nn=F(UZhmoC@MLVWfWf8%A{!LJ-a9ibm(5(&roPX(GX)q
zd@M1x1j~Z)riLkJ6<cJ^oFcRr)Tq_+f+X(O3iIld^KKzPt*|caAAos~kwyp-vI?3r
zUnXtdOY2OlRDEW?HgupF8@A?~b_1@+0>l^njEwFgGs7mySZY8C9vkvltS$4KH+P<d
z=S;0*5#^|?!FqdeK3nw)AoVdz{1u_6Q)x*I)UxEwWmmKmY2B=i35`sfuI6COn^tw=
z8Q$a;Pi|<%+C(?*2CI8#HL@4m+U#vLE#u$niwes!nFk*T4Wee5^3&JlnhcN#7NKU}
zi5sK`&6$8JW4697LP|J_bgkhZ`DvlCHK&r|MS~2xis9Vi6c(p6DqU5NH@Mcd(l8Es
zjIxDs1y!qc(QNjrqa4{N4YWo8o#8MTS>xmEb7GD8$Z)quJ$36>!5YC6H4?tWLx3jX
zL_~2klDHUK>j@1}T+ZgC#@^9#==euU-lRuP-UC^5Cc+L8jCGOV7-{#UL(6{hSs1p>
z-8|04uLdI$1?;B<uyE{|&5Q5VrtB$?L-fwgl~QQR#|}QQPk225Y(4hxFNtd?UDyCB
zc?aT9QLgcEl~C544}8E%ZiyJU*giX)bSW!hni*nf*gH43IRe(9m9*`_wvU2~3N;3I
zS1H+7wVCp>BEEg_BTk#KN4<f#3tgl3T!ps9%{lKZq4q`dM_-InNjuNtJ`z@qw;<Qt
zd|bzILs4T`ysm=@qMirPJx8+s-+=nvgbJUS&xXVmqWx@l*w<Vicl*dKHnoj#bwO)z
zYXD^qpzy%Dt=b;7#B)v(tZ4QP$IN1@x`}9@K70dB*Er<;S=y-L;1ht}O$&gVrbWvr
zP<M1Ub(n$tHzJ-9qUJZg58V5N>^e`X!u!4==E(^<WE#+m)&XcNiQdl!iP#O_V!)|+
zLLaT9l?6Zw?^3*B+E}unD*~D^pYJJ!=0qKg<M(Luy8hi^M$k@aFY^O;ET-p0Ne3X@
zY$3V?%PRbLnRM4)q58?41w7q{Ba3Y85<GV6YW?@R1lLHpsPMEffByI+7a?gom*FdN
z2`cCjaTh&J_XS8u>tnRt1KV|!i-9k}i*QR9@it-?e5<6jq(E{}G5amY*n+H0gn_Y9
z-8;^pTZ~?CK_9>Yi%5S(q=#!=vps#u3bpC*N25|FGH$TQ9Pd_4r2%$YW!S{i=_C!G
zD_fX}hHLaDE%xg_fp|i?KbzndD++)5bCZZKr8}JL`2AxVDM>tTh|-T>%j~EB_}}&(
z|K(H^a5QtVF|l<PaW^ut|4;ThCt*$&kO6+Q>}x|sSOHm@dqAK_|9T*4ARfIiVq!E1
z{?^1IHFL*xX$M4a3Mm5YU!EpeD1oBkARcKhJu}}&7N2i-A0U4zc4~oNFEZ@*1*d{J
z{!TQ-;$6U&WxGgOjF^lV^S+fK(41yMfFZe<PJk$K;(y~sh-$&CkqZ@{ljjBrmIjZd
z8scSz1@n(6aO6>${01$COSKm>OdY0Ko`nRwC?nIcv5sS48^fobUN+7gD3h<@?TK=U
zsq2}1JqYJDkDjs^)6H3!Y^(ni&NTu{w6vfAOZuc(<n2Km^}eSyKmm~pAz&l9f@}Zz
zi~)}A-R3rBL_yHg5kz`;6EZ#VPxnCAneI$Kvv<?H;fP1`>I-NvUIA5QH9(Sk7D2hx
zN<HMqXiYFs=aO3GnH@j6ZQVR`8vhfFW3&_z!h&i-mEIMcp#<VuGs3f_^XDH5s}*7d
z7V)3;>iT)h!1lkZYyV}v{?Q|*B<@K93LuZprFU9<U-R_@=q?i@CQ}Kj3*aMHyYtnS
z*%-UIVu)RBbe{k6EH}qC&~Pktu`@mO&fatTvC#VXc?0r8$>Oj(?x*`7jTy!&B9yOv
zBC(n=8x!WoL6TsFoU<~Hlq~@JoFJC(_I;+4<3?2gkpWZU!T~EWMF7v*q|26`QcQ^K
zyY7tY=WEzh-Beb&#7}LTZdzTqsr?>f%%?W^OSKq2qcG1lkqAukEF_zkk$u>XCWe4?
z#Ea%vy>ICg-GEoSljel7W)-xQqU;Q+>#pyscZDYnsvo{+1MT9<8T4`~uVdxf?M~|B
zy<gzUHMQ?Kg<sgM?u=l5nnPqmEdOaEzE4VbstVc!9wOPKL&~2I5LKs4T>net59NiL
z!rIjSxz;b%7{vy1l_G16WSgRE^<<rzYk`^Vv=kq9`m=+7khx)fU4O+u004gd$P}3W
ze=LsNf89Z<T24qN=)SEIO%{zj@KWSp1>nid77&vHB`Hc!j_1F`ZD`0gi18)_8?o51
zU@6a|ci)iO?`1pg1#z@MGaRt#+VAApkLK*L@84Osn8n1p&wayu_RhR=UwwK_{XRd-
z@_u3Wn-N%#fS{lWoezfKS`U=q7T4pO{SIjeFQMNZYxLGubs&kZYA-$P^!^hNiAC_F
z(&Wq`HKids+xS2b*p4AAYkL|*f4oYA(x!rpT&_C7K;2ZG?{}K&D<-FkT@)`3VJ0Xb
zH#wfssnie>s1svHRy7r9dzwfw#yY({tYB*1nNx)vazVXK$6z6(v#cyYmxjT(-pz)Q
zmT^!`Ze~41QiQ(<S%<G&Tg;@|P@bhBYAiB=ilH+~chNclFN$tjns}P4O`e7VObWAP
zA4|E8TqVSP1+FEBHavV@2>6|xf}+@C5ZNKgKywZ9F6&s&=xLzP2GjAv3Y0oF|N9sQ
z)#f|e<SfxsV(wU^v3w7~^r5yUO>$7y6jIc&Qc}%ut}8+Yq?|zk-iAB&`7zddtXt^a
zODQ(DgQqHOTe)pS1jRV(Z4SSYxFFm9bj`YffOXR_nrFrf=Pmfr^F8?NXDAH)RY_IJ
zia@*!T}8>IHGTVN@d71~NRP5^{UuSEQBA;iP@E>vHBrii=Mt#3LM<}6v(uCW8I>pj
z)iuPfGO41XkYTVm86?P+ZI7a!bu#F#q8E#ld66=_3qe5(7rwYzkyP1Cj<^O27m+O1
zqSOMa#3!)|Oi}&%<#TTC!j#90$`EUJWnuAw(DgEXbdGZ}D3-~lWKfV3CT06jARCpc
zgW3?!cG<SeGDeZ~IM4bF)JB0YrmI0)Xxv>xC<4bPFx>G2K|pQw6%H=mDNJ9f0i7Z9
zM9Op2T#uZC_CRl%l}%9a`x8xq0TEG6nyJmw%8@N+>W!<FgG?n>pE-tgq@Th2AO(m(
z5h}V(JEs-EqPp`)cKevppHePn%`Qoa-TTm}v83nfYu{=X)eka!5~;S>wiZ9KJjMq6
z>Fgx8lpK|M8rEmK1%a_jTLUsb<JJc>8vpPoSY+$7N+_;3vCrkzy8E~s*E6qfhheM@
zrP!Wm9FgoRV70zMFupOPdouaMx%rka;9iusBffkukbq&Oa!Av$T*C5wgjUDJqJ6aB
z(?h;NzQ4!^wA4Jl_hYZYcSg~3H}db;N0wk864a3n*J6lB-nb)I+5y2n+93^b!`=_}
zy?b!&O*YX7-^{Ztu`4-1**M4EM4h_wU2-D?C}Aqy5ML7Yl@D#`Ppq--or&5LPqq_}
zTx|N&G<n<H$BpHOZeC_;0;KJ15pHkE_+cGHMuGR@;UnR7N8@!6cl7{Fs||s;se&ao
z^v$m5V-XI8G@}f?N}9t@tWg|0qS1omNxBaVqEkW3?uH;eG-r8ci_uUBHK8k>1%{D-
z63FD%(!Xv4BFxT<ls?SH&G$K)gR#{b3?ht<ISeCIx*t#kBLWUoplL}6u}-)!kR8Yp
z%F((m5JEGJ!nWg8tW%YJXjh27ngMAW+0)D`L7?x4Y{2+7MC~({>lU%s)bFl{J%a)l
zqbCh9*g7WHB#?5O@r&ddY*myj&i_IQQSRbI!%jx#TIh8Iq)wt}a5M>>xO${;MLFTF
zQ_O(@DdX&)d|+07Gko>hSrJy<P_MN(^$T&Ix3*UOZV%?x3(9`M|0FRM{wxJL?BN{#
zD>|%;=1|&mC?0hPHtn%4a35agZa4ED#_egj-4`fBqo0R#9mQ#BIn&i-6N6{L`Zvuc
zhVM*t=AS0*G3(^>#-9WE*H7jAAN6DZVp#r5)s#1Ibo$Ty%9LoC$U%Pi5WROaGDy=C
zPt+z^E_YxBba`ZMfei{n!7?uADyKFLcYluL^~1#!m1QqvZ}0E6J}Q3>QHVrfykO_w
zv$|82jDqR3+Dr8`t0^fspZL6W?}Nb;i<U=%CQ~ulv9;pyh^Dh?ky@)_3NU)Zm3nhF
zRJs;Q6=*AKYzALOHE$sY@Wk+qVLBMCC7ZaG3uJ<SbD2MZ3xdv^j|hE#5=ma^!#SeU
zL_=};S-bz?3^t~38Pfad8_J>n4>0ln_bv#S{!mP!7LHENN-l=~@%6ujbu+43{~BuZ
zw^SLl6$KJ<_cuxbNb7Q!O0hDnWC6M4;8A_GNy9bkmdF>;M}Dt+#2h+{u6VQ^>0eSK
z?k25<;(Ths!zu0AKiM3QGv1%~7fk+3?IroYB0MoYk(mh#@FSK8vIjI`ov_bH&I$oz
zrLZYtsUQX0EBOWR#C}5l3RW{%Bo}~%2(30eRFFehtEwIkdu=PDTFFsev{oQPGaF9N
zLO7CGq<ys4Np@rtZcT=mvvomhcIqDTPIL+~AZwJzh=u5lX3n8w66ss%`D(V>Mw|o4
zXEdacLL>~Z9Q8;+O$?#CmfUc5aG9?YnHuPISSR3nZ8JM_D8dyb$SQv2-HWX?N}@nm
z^pSjPE?!b&xN4pT6Iqj~IYUn!w~x*r*YJ!DJC8qDd%4PPqge{1d$<fXz%b=imO8)9
zR8As^C=*?GQ#+)%aQaQ9l)+Oi&Zbyk{U(zWB9-H9@hU1j$1T_z0D^{V>*@GPtr)Wz
z>kkUX_B@U^7XN4)%$HV&YAuDsY&6oUGVU~47&0HNr6)8$M29v4AHrT6Y7amNwe@2$
zMSs9J#(B)Opvkmq-rs#zH^A-}z<5I6p~|}zU3FOP#3gE}fPLjmm(O>k5}KVb$R=n4
zvES$OqRV_LtbbnFs2e-~T>F$+Tee&KFz1vD>C`sQ)TI=mBR(H3_R%|oh4VtiF3Lw_
z7tdE0!H=H2f)&ytAwMlWbDnuG(ULf9m*DTI1h-oaT(SX8kWAje29U8iM_5m`S?wCh
z|2)fTcQ|>_y8p(TEt&BeR`_UPS^SO_Aw+z!Pzmz)2I2q4*o0Z?4L!A|{tFwR-u=j9
zsk_AMkBW&!9LF;X`vOexf?OkPMS?qF1or}T8%dvO4jne0W%dkm317^C;}z8p2F%50
zC<dS>&$arDGBdTW<Z!q=vhKA^M<bMx=r{!~Gr|>teETu7-Ej;`Eo6}jy1~TUaAs~m
zhhS2-ZEu)clw!Zg9(sfvs-2Us;-4ssADLua7E|t`zlU(bj*`I2HTml-oa)BD4e;6x
z#Il6qrF;-Y&tW8D@woFayo)8iO4hl9<<`}vd|k|mufrz)`$@MDyYyXLUZ9H^p@Jxe
zn3mtSIH_Iw3x1|2Uhj^WaR8u^ISw=>@4vIf@UM=kjX!9O{)a6V`2W#l{>NGNfA8Xd
zH=IuY-n}iVHvby@<NKoNd7^2qAmA+~5>n;Z4Nh6Epb#M;g4i74tF_sb-Rd>-;(kwu
z!RK#BjQOW9?`I~}#+8PwCNmj9+V$-8Ece{>&Gqh|xAzMwe+X%;d4~ahM4=pFn5%J&
z@T0^41a(ePmuQCKNZXc45sKg7Sq99%CmTnsy4$U_RC+C;tYjWEXHr!g4%MNwS8o=t
zU5BBC4m*jkf0GUk%P;RA01A1p(jYj9Vw|c~O0{}Vr%@Vn#JfdxEAB5Uc<M)cP08jE
z_<VMlO^LD0IfN+UfgAip6xOZTDB6AT#L0vDN;=X<i=voReXS(+oI6~wL__xoy`y=j
zXra(ft`?HvDCA=Jj=~=`Rx8?Q7@s?efD4YX3&{!D)-M){q0qDm*bbqz6r+;1DA~%(
zOrkv2zUgRP#(AS|s$iz@Ojj8N4#aL_DNu}k*)Fb%t?>Ks;NtiXs5`3}FZBK{*S)g3
z$55~%jX_?tZ2!@XL*pbtJ0W!BhNlhcAlYmd__dLYu$LT3VyZdB7?{G*%+mk){+zJ4
zs;d!SlV0vINdFQ8yIDmbS|~){ZQ+Xl-0nVjY{WBZH5Ok(qD#50@k&H<HyPPI38m8a
z=f#%z_`f)N2QJaNEm`p7$&<Ei+tx|jwr$(CZQHhO+qSLF>aWJ=SGQjG>sw?0g%xYX
zo)I%5ZHB10EwcdH<m^vOVR!@E9Alb1@w%VU5jSp=XjzaIdOKYH2$VyOB<ckfy}`M8
z3qiQQ4-J`$&@|oyaE?491r60xQD`DAMu<KJzqy`?0o#TC!@i2oZ47=0R_b&J&t&Q~
zoIIM7#l^3WJwRwijdY*XUoxV@qH`kLzVZMMnK?%Mxkudix>ot<W`Umkah@=RW{k0s
zz;;SVUhF;X;@n|8x<^et%+3Zc><PMgq47Ov-;HFal)#@6Q?Iedrau<tC(+{C;Et#n
z55}r5K#7b3*S`P;@edR_d-xIB{}m8W4>a@yKcn98pHZ*azYhpLLnCWD!~gxero1VS
zp@{gsIoVg3UI+zeB3s%p_gfSf;DeNK@ONMnGm*)fS&4SKAx4v=6GM980?4Bv)-VW8
z#%=F+UKG0m8qZe7ZTAh#?Cr)Tq8}KQ_&S>Q)0X>H>+#1=Ija73_V>pJg^y?j*~!oY
z-dh3EgHGCh#cwnQaC#T22>X=76ohcssCz$4SzkX0OcV~A(0xas<XFX-Pzp?O@H~|x
z7yo_9ASdU^3aBDfIn{MCqQ<hKYP8WXr{S77j3}i_bSXKS^ikJ#x!H=v3RAT4G<k*$
z#>~l-q|+(dlYU+po{VjMHA~h+?A9sV>Gg8pemGtgwQ5AD<1!^m1fsM?$4U=Pdx_dA
z1Vdd^{^<<cd8Y`$`O?<cM?Fnqf49*(NaL=GMKj=9Dqu#PnnIO3QI&07&jR@$o99VG
zWk)%iRn=Kq)1Yl)?s)cln&~{zsCoaY`WhCM>QaRq{WW`$q8N+3kYCzjK`3k>V=-aI
z24N<C&(q6j=GVY>j-l1^-9@jCMfs_jjagNd?f30jHf$A9_`|w#Lm3Kw0)GM{<}zxR
z>)9>F0>Hl3fVi{#9s@Nu0wh9jAuXw^`{pc}oS@tT^KC?^x}q(lC%Kz#g8xDh&VExs
zNwY#n<nQ6IFbtPqUCI^7QWunKIt|c}y)?)5I+hCLRy&JoDkKscIou`GqNj4JC9+Co
z$Z^e<a*Rh6PFZDIndtdh`dg?MGCEp^GG@jh*j3SNjoYN$c1%GecBMeC->tAS8{_V%
z>+5d(Cat43U!n=EJ35}M^%!aT7r^byL#@M=>I%4i#Ns}GAERjzpA-XOl0L$U&V?$O
zU5Et*b(n1e(Qj=l+Kt#miKG*{HUE^I6ZIRiZkqVvq{2)w$2r|dfN{q6-d5PiP=H>y
z<zK76UXvv+4IMevq=$Z>Ffj3n#fJ%9Wti#CMh3gPv`;=Zu!_H}OdwcEN1rtFVw`_}
z_Z7iZ!2v$7Z1VH$Qo_SQ#Tns=<Z1ius;X%gIEDx@A%DZkQD&_OoN%a#yF_&b4`RQA
zT3+Y}tdh87nRGS?f1Hr4-WV+eh78@{ODz|E{p?fBnpp5s4<J||Sc=#F?6(TL?~&Mm
zb?57=UB!R*v`BM5Q01x1fZM7C=?_$It@9b<xv6{s34`a(es~Hn&pxgr=K<O3HAs8)
zyiRaUlL9=mvi5!^<ah;nJ+VpE(ZuLz<4<<=(Z8?xf5*XCV08K7K_XbtVdSO;&?>?5
z`x!jNy9?0?NhcN<mprh{{cyzFE6|b9ct?Bt0gCw%uJ2l`??#B;3w~+a3FB3z39vC)
zX}aO@ERewqq>i)A88qo3M6Dd#sE$?1>im5Hw1V3NN-b%$fzwz<JOM#=TrFt`SnGVq
z-q@2VhLLgjt>Rli)mN1NdKEb(pdIM^yv_VSLm-8J|0?3wwKx390yng>H+3*|GL-*W
zhqW^PVcIsjKMvvlr>9Td{6EOHk^L&Om4yV2S>uv;W9x#II$Ugm-=BcL6@dv|(oORY
zX7m_FEQ`+Ch_@gwICp#EKsW=&-ti&EPRU}DiodxpG8l}z?0>$@*Qfn^lwUA4vHp>T
zn8Xuty_)qK^|cm#L>NdIiWn4-tCFP#ErT)SiO;BWj^5g|5=@2g>;78mCz@MVas?|7
zTw9y_YH6PE62ZarIw}?Se;E~U6>#}oDb;e5%H*HjJ*!+#%z=w@6J{Q%VSe+1aY$-A
zYiu2F<=VJ^sE|Gv9({JrR4pe`8$PwHv2b13V1af%!1$s2UkY;k<aIA_?hS8T+AZ4Z
z8(1>RS;<6g!xUC8O*#<x%<n^`*=u8C($bENHuGI|x(vOC{xM$3YK{&-SrQ^R42pb*
zgc09|?$ToL9&~FQs-g3u?l%y3LWBVkN}1$wWCt}|{wzE?DnV6OAYZ-%SwoO6M02+a
zuv#Q!8`<^qS8Rb^+M!4EqB+z-XJ8h&zx;LwnX(z&r<=%N!RcRX5u=wNc{X3Rc1WlW
zJPp!)%4j#TS~?(0({<#epPMXF7H2xaD%M34G(Db~A{rktBG1<GBpl|;TB-n3tG12x
zAOY3^7p$8I$s{!AD;`BIry%(m?Roq)(lz;bh{-GcS%t%`U>Q-fj;-J7t=$q<q_8!T
zTXd;U2~P=Yk;oF{Vr}s&S1{(jI^n=na^d?}hW`?FNWxFAR_MmB=i3IW>+gn)jXnj(
z1wxL)j~-PE{e9s9bfni~T8*~RgP&P!!_c?gcR8}vTUg>9en5>d&RK=wqPzDm#gp4$
zj01f?E#o{t{#5aQ|3r&h{ZwH5!#4lnpFjQM4u=2m&Px?_6-;NO@5vh4aaz$4;+Vfo
zXzFr0t(35F%ut&_KV4xqqT+;eWs@}=fuc#Njz-9FE@W#<@0CnSrHbWCOXB6BNkoY5
zx5$>A@1ET6XYn+j+&CX^rN<K!)XkBTe$ibY#~;?m8Q-s&>sROBZnuWN+;2(HE>lR0
zdt+vO8Q`bJK=B4C;yF_|RX7V=U2w9SiCA@8{v$N4F98y0ULq4>-vfwx=hNc^ke)jP
z=JtUX3@51;5GL@pCPIo6e?R{P_1Z&Yh~!3;`{l=LI!TdT+GBjnhRsd0E4$?t(cF!z
z4~#<OAuGfsr^`9DO>=v5NNe=^9uQHzBg*}*h}OJs4&Oz+O9l{@=ma&6>15fDnS3Lu
zhNjlUH_tu4aG8~G#M(x%^W-&-9c^k#MVC8F+(@<=A-S%`Ub$W?Fc$Kt5+9$Idch*`
z8DPZGrrDga&I@4J#R*`!JUMdw*O>xdJluM;2O(QyC<rxyz3S);zDuyf<1xsU_pfqo
zwVG2p4pU(vy+!8O7sFZt@_367`I0p&^<^Rq#(vR}kp;YbvswFib}^$pC$b9Z)Wrr^
zf2ldekWd%5NAox>6bm(|7=LXtOMpeK2{Oc%&@VGgIM}n=xPTsHZu*o|%=ydsHI*<W
z{7)r5@ko=V-g_Oo0Z`BqZY#C<qUu|4Z#K0G_CPc^tvW-e_5D=QO$VS16P0t=NDTYQ
znxtcF)p3m;V)hhPj+{dOWNRY<rgf}^>DGc2AD4b$rWMYr_F+cj(?lYu$Y(d0;`Gym
zsVB<E-yw05Yk*#)BXIBG4{<%sgq&2n>+o4{0WaVAxWNLo&g-2maMO*qGgJH^Fz&7=
z2fEolQG2QIcl}C3QYX&n7uJjBQw?>=<ShuoNSM4d^3&ieO$lu6mg*eSr}52Q`8%*}
zNaTynq%BAwh#Nuv;B7X+e$IZ_Hal)i6Kp2etpV6C+gm#AM1t>S+N}$3TvDBB4GzLg
zRLYKx^=)OTX4DgErJ$67t1~NTT)b{xDBJpm-PJp6oYIFy>k5yf4es3Dl0RBGlcl=6
zkeqZGj7n2lOVEiD7>~>izlNL*I0?~Dk3B&I=?k3@VF&JxNNflsY7~FfIS1h??ud;d
z(DEysJz}!|k{hFP%wR_V1vv6eo}VD6bZprUiHm6Oc!Z({ZoD1T7?|r-)XyP$bG-Kk
zs+K#Tcp+0iFn)Ojr~N=xynz_nO>QaMQGRLk!77)=oI))vu#!h&Wy>uG*Xlp#{1EDy
z%3$r6jdxpHLNJIgSmO)!3NMHED&BdX_<))Ch(?8<dFLrb_zhi2K~bqw+t{<#3q{BQ
z&|Jxb0d}GxZB~rmlmPOkvALuX?qf#53<0*HY@rK!hlfOiK0X3N!c=Am0<LiJ{-#Xw
z(=-DlX04cOHa#KV#&#v;QukKkRds=8swz&byg3z`+qR~r0frwg=XoVnSaIqRS~Mk0
zpP?lsBY1N^NvP9iGG28Vz7#AOm?Ux%CBMA2DkOM*<#-l*-46cuX*;rZ$h7pGq{1$!
zOXk<L9!5~}$zatYoGi6{1VjalFBklWN+=^^)n}_*`g4#5wbl`mE&-0+A_es^Uo5H!
zLR$YMK`3MA^i$AKW7e1sQM@>pE>b8Lyn%w;OM+3lR+y?QTQooRsb|E)Y+ibYPpR&p
z6s+)b!X(VTwzS7+!HF5!N~m_e9HxfjR~m1(1NVhmD`i`y54ph*<FwoXbNUEle`;;c
z+3Y%%{S3I-ABBc|z`tnt8^7U@cBx0+<p>TuOHuB+7D#w|bn^rs6qM}j4>u88m-909
z8Qn378h$ehryt=81-d2(punML3ZG(*<xSeh<Wbp!3Y+uUlSVJilzFV~uL$o`iwGp~
zA%n@*LN?|FZ0e!957;q=(qH8<WRe<wu|@&(<f~ZE=BwPpN9%3!V-Kz+$2s|<f;)JG
z72Le`njj-d?*s{w=Eq9rCfB$&5Wf8`*riyZj~-J_t6NE1kE+-tZmTc_SQp5^7h0!*
z8-~9|YP0~bg&?%0Fzv=-3118eXF5SJ??h2}pS!0)9RS;qY}@2_0NuON6oA<`$hkCC
zLpW&<J_xKYNfU$;*ZSM&qiUfx5GBieKP66)xH1t0tEdpp!iRLu*&8-Z3hNQ=tR!O^
zi@y0+4aD<RhBf9%13R5w3nhOXH4sqfH%r`?=Pq6y)%qt?(<S9ua_JdHT~Q9+xT_aX
zW7h)4+o!oT!e7*mO#-Rltf^ETW$1*>KwecJa-AGkfNPyvMS%^{9mNgCm4!IL&HC@J
z^l77MMF&_St=`G-5)v585Jn?7Ln~EA!8Fe_82Ch>P0PpQ+VT)sB9MB@HR@Z3(I;CA
zJo(00bBCDqE0P=Q-p@S%iEzyp(jhvEEnkvBeitFmh~)w7kJK)2IQLuSThcG;t;19m
zA}y3r+ik(BUg}RFoeS0@+Aw!O=T#}{7vd=KmTSobahGQvS@-iPF`2(zEWZ|rcL;+h
z*A_P95X#6hgKb=iO8R&>Lx(@?U7Hnbcz{}VWQ+Y_<#T}WigYMJ>43m!22#ZMp5gld
zvjS`{o;AuM{G5Q_d%Q8HaIyEgX^dy2Nw)g^$op4#@1uRb@iKc^`0oDIN}!Mz`O)-4
zeusYO!vEkuT+-Cu{)g`VLl%DQ1^)|Es7&0Jo|i!!?smr5TtY%458>ez*n}wn6hK@k
z`Jf#NB}A3*Xpcyjt>2`!1o+JMh!McM?KR%_f7^?f=04Td<!q+1@6jSJ5Ox3QPWPIc
zZp!}lcmdVHoM)FCITy)~AucUh(8WU2kT)j~qmM_G)QjM)$H+1qCmcd+%YM7Vch=aY
zblpIJ93mhKWRTylqR<EeF<dWA>*%F0@2j|n!kd%~W<l?xqhK1(s6BV2Rvu461TZ}L
zWtZl$)l_h}X_zvOg`KQzBr>s5j%c1tuc1<14SI~GT{=5<Tc^3(Xn3U}27`jIl_psF
zz*(!Y9Jlz(b-OeOZCW_8lqz^`V(Il9i8pN@$o+sp*=v-gMRmW<jM^0%D}Ab4C&a$E
zERU;ZbjEa?E2NP*gn1_aM1Cj<qG`i1W0e6V{E|NO%%Qryf=XTD=zx5YC|O%-kG=m0
zPC`tfuY^avR+-2V!w@wbT4yHt!m$|th>FRz6U0JD0S?LmuiOd&*a4Hl2GA3j*mk~0
zHG{zh;!{+DZUTEyhhE~-I~nx~s|gCSu*A?HC1m3($CYe+6H9wDyGls11or9(nytJ|
zd*-n%2D@K`5fS*rJ)?+*sq?mMo6t0*6fGywY7RRNIp4Ub#|f4Kahsq^&@5tt_sEw0
z6$tBs!r=*u#H5mic33oSM;v_oggvkemK}+&k<S(*ltnU2=v`-9omDM9f0uFU1v9Nb
z=04>^{?7?z2fqgf*5IzCiS_fY*Gr3UPfh4gBdXY(XjrTV_9xzp6snGzFWJz6*U5Ae
z>b#^$8`}Oa>Yx%)Z5Ua^{d@1j`9<3&2(qX3VKiS|pK-r78?u0jI73d-73h_vE*<Vh
zgB7(JyzU#Zwg?I@A?43_wlOqR0lzePzgU^?19-QbuMr{*Tu&K*y3+3d`fF$ntl--D
zgO2SVbo>v9^nb#_S=Y|+zY*z1#s8FFs5YJ2SHfgyTzIL#sp<+tP{L67dQd6i78rY*
zPo1dBFRd8bfj;rLUm!egc@bm@LV0>{3_0s5RelFi_9kbtHD7z!KV_t9cYA;Qp^bbc
zltWd_-A&ujR6b=W(!+E`0+JwY$>sB{$|=DQjq@`FVnLG&nzyoVm#wvk&sDJ%kUz$<
zsz`N9uTKBzKyxY92j4VNeFI0ST2*<$kTnW%H&05Zz(!w3IP3>S<M@dncFyiag}}f}
zI&q1_YuaHvi7_ozxoSEua+x}(nuAop^lvuPP?3X9pmU`Sx~PvbW_$VoM&Z3G8|JDr
zkG5P#grK@=BYx!qclF!oZBa;+NbjypCj_%z57srQxC^Vc?;N}=(s~RqWEtP5LCw=(
zB>MCedaI4<yjbD*Rm!!X4DAOo?oD&*wT4=qeHW$8)!n#IHjfn4YA|YM^b8;&297>A
zV!|4#j{auL*KY|)(UQMQZG@D-G_i}_&nIGbPs1fosoM8gw&|v0gvu#GWiJny6dkAA
z-tutWs3nWft)s%3<fN0r^=2)56QfIfVRBgXp)0C#C3P<ml+I)Zyk$b!b^E9KR%!V|
z_<ac)aBDb1Ees>*w5>H2Uz2q{mj;TB{`%`((Z0bgJ@|&bigU0=wieD!l+jHeA2opi
z+<@NBOcX&dBF*y`WU)wDjBvt|L{|-1lJPd|sI&$C8(Rp_U|c3sZXHuWY9QX6;iwQ@
zLl)3S<^&wxggq*BjIn5v)~&}bg&vOc?VbThy}Qj`JF9KRFi;(X#(;=Vy)XB6dBV3J
zDevR#SQo(;_9_)=xm+BwUe=4x19DusZ;98PG=+T`ysxWBjg|D)oYj_G%rpHZl7LV)
zX$v2<vgaIIMlO>yquc{&c9dXA4Uk6IXmP8L=$*(MyP&AihZ^D6zu3_R{e=R?eo&(G
zgA&1i|9A5rl>F<&q)_1>d>FMGiksGIAa&&UH3jzB36t8@&K8KuOPGl~Sdzxq8MLok
zG>?S8p?u(Vy!;k|@2}?>b17=?6)Ue>Yv6hw&-f2<^6QYo2k0O#M4vuP>vh?m3~FAs
zWF|jlFeAtn3PM((0JAqP$ndl)Z#OhZ5y~7=^E}9~1p_iy!7Z70a`oMBSE#o}pjLJh
zVTz*5IIgH$C%LtC9E*RfOV079G@4(p_z1lzvA&$?%4XRKRqv;AP-^Pnu?;u+((h8i
zL2LgIFjx6Cw&tN3x_U7nKUtE$c!a$9$#6D#qZGn;&uoa&U&%^Lp(&%yiJeB8xx|}Y
z`tgF8XP6d)@q^wa%SeIAAnL0Rk7uuKv@%S~4y(V+fD5CQP@ZZivy)%ess1v}K?`t@
zQuF)fi}JY6u72#6vftxICFm+nwzg$GCg1zMT?(U0_l)Pc5!=B4LxEJS4ns<{gO;!<
zXgw`8Hc(F_hbG98bMbG9=a+QL9r8@r^6nI{s-;H15v2MGagO#T9zUH9Ae$D7YdLjA
z+b+6rUT1u5x61&npD`pu?-5155E}FMJ^B~@Z|iSJ|IA;1n~6ymKz||ax)GgDo`@H!
z=P1HkG53^qW<c^+cBT?Po)f{$PU^3SA+fJ=@Uy2|4SyxJpKD(@NwP~%+h$;!x~ZM6
zD&>lx#xF?6NhQERNoVoC3Pkt;yj{nM9isXV40D1&?jp+)C!d0N7Z~W~jmsB<X7YPZ
zPQiXfR6&>wN~D`fatRBJZO#*%k>!yjFS^0uKVbnUJd2Ryq$#3wPIxJfZVqJ{k&L&9
zXGCBQb4AEn#6de{voh66ZgSnUtK&f&3VPU`{pLb@%fxrO3nm!q)B}6PdXBGvSNwRb
znYu@N!ldSa(*GSjg59@Y<PBd+EV)lS8_ZbGN{`4S#_0(UH)lZ0Zx?WaFZ8d3D}R?F
zyZ*<~fcGPQ2>nmN^50&QLU~Q;g};bg&FW1uN-D6+(tiSj13|*jaU7szS?JO%d<?)~
zIwq4u(dMMmPbu%3J?L+HadxzCc~Gw%Sn&R6lVA3?+Phz|U8bH^^YD26b_tw>g{la;
zsYTbJ>S51)l`=Ja293O0qU*grE{>~Vl~KEju8(CD)=RK6c8wXv=Ry{0eQY>gXHbMs
zf(9?Q^CXoZo16h3k5<!eNGi$>t4ol0WgU@(59J#$rXL#!T$oiR2;)m5l~P=ou9rBG
zKW3L*?Z8_lpgc$u*MB}N{M3p2H4S>dtnu8Y?ig969?)uZXiMBkgy{rwyvHX{IwQ*1
zAaq*bEdCiNur{67aksM~O|G6rDQ9Zva~!a|*~U!cX7%1NuGu&KR{sIq?_r_$D%$FK
zxv_K6f~%Io%g_V7`)TPMKhqWVq~k!XKec!HEiArL`92$v=|=Fy{>{a`u^4b%_X}@F
zaX=)3VSRhobHA_OLU51xa|m;}5)1(E>KAu5Af;kUL_1Q|j#ePnvNgw%f9VT`kTto~
zH}bUvD8g--TZr)D%6`~)z-4bH@U}GFb+C$o1;du}!_&pT=wTNZRcmcOcPPeBVAB6U
zApYkL{b%<4&!DbQ;Zh1g7M80S$3itpF5HI{9ABip!2*Jmd?dIe6pq(l?`GSuoh<y)
zs=hskJ4|{<TjUSCq{lCuG1g}*-keWe{`jfPR1SNiqlv4puls!zA2Q0ue1tYJJq<y4
zHr*qH6dB!|oSYIqUa1gKydwA%<l1M%2~w9H*h8&Uyw1A*=N8#rsZ|vi&ULbB`i9oV
z9w#ihBa30^BeWs<NZZJ)3t)bWRVr0TO^PP{$}6R2%4@3aGL^hI^Sd$NXA9ls%vzoG
zC$t78RoVc&`@nsbExW+?F2Uw#WsPc!8+4Xts{FBM%HfxTTeZnM$a+1D@gI#kGmi8n
z&Asa|GD9%mHqMa3#q7Ni{JU<fT;b7-c-`V+>d_}1NBcI-LaLWPNMI*u862C=;tK_$
z(n&p`Ly#LKfE1kWXOo8=oF9Zma{O61Y#!*hdweURwIrF`@}}l=L)N;UYbO*a0={5B
zQUPPZEY(0o5Osk`nMW4tB5m+6q$f&l_QhIa+@Wd8uwM`_ByCMc5C*DD%?Pb~C@-qq
zcUh(7rHYZwlq0;NNurHgAibV_8IBFj&GvdPGrx4aFyXuJ79qf40_xr5Z*&bu?vUHi
zrL{iT&VA80Zh;VY{H%tC6_8BZ({o_1Zv)FXq{4b}9w7xB9s!AIEI+J~1?*I0z!gqC
z3xG=tIMJp6tvi@N)02M3zh-%m@oA)pc$rU1H2dNhDf8U~Nl`etmlVKWe5;&7d?}X)
z#txXgpFv;o;ZgP|?+G}GT#aCqPZCeLfh~{RR&(0C1`nBj>JD@+Yd*Zipb_W7Gf&dR
z5V2ZWykWs2WOT2WZg=R5kzfX%oX!y=y@3yCsa3&v#Q~(KRS0=IQG@~}1gL_Hi9MPT
zOb$ZvS{D{a8pi$b?0yjmst@Cz0w#;kwov4k0bZp8{{js0aEg`EA7HHgs5Ad#3jY5h
z$|y+wcqmZ4jM^{z+5*F5kf?I-8xU8MX!ONG3S{RC{6wKbw}R+RQPww&oWsAMXvhap
zt+d>3e}@taRsYzaJdD+4Db3PcR$O_GT)VSUS82Aly#Lhr7-D^<Eai?1^2_x{KqJ-L
zwdU$dS;aFl888~4;Zr18zLrDg8koiNPI9dK>DHL6>UFAa!(Z`tDH2S}%#z)&5j#_v
zI%kw=H*yBO2=zB(wjZ=7X^wI{0z0=}w?GQ@HU*|v+fE|{v@1JogpFc!`~<ONUW2cD
zoZSiWw-~h=r6Q^xKQ&Q)`m|@+kVsFb>(7k&3Q|dsgmZW#r!!e8PcYLjUy34;4uRDf
z9#U%h>|eU(4V1H2NwYq^1oLj0j2<77JiF#IyodH-sB`399Jg_m`T>J$i9NBqF_T2|
zyC&(TTyrJmb{i;KT(J-dQ+S^>oT@Y3lhjgdc2vlbcOEcq*0q?A*6wQ_9vQ>{0LuDb
zZRZ6M1wCSOOxa5#T1c;C9jdqIy%R@%1LB=aqoVR=;61$~LOOqq4|2q|NfP$om`cza
zxN$MGnK9`qf0*4Mo_0+=CIO(it+Jy|&3OL}#D@u}0H~9Qi!g9G0v+R!Lxh||kCi%P
z(<{KR{57SQLKrXL<i|rG;H5+584~06OVSg9se%2yys?7#DJQz*9h9PSpiAKyR!JQv
zhg(k=v=|J_R5ngV#wEf_LPksHuWM+)9k~1$cifn{K_ZKa476Vm^12`gl;|ZV^&iQq
zU3^n;re+^mjl2vni9LE#a?_lX5ZiRmz}~fTZ1sHGA@=<ZLXQvw2jWk#HA>Im6Z6l&
zc$4<Plm-%ZQL9)5_JF#1u*hbB;m=@OAZ1gY0CNB@_+>!0Kzl;r(d}r&AQ6n@8x<VM
zcs}&}ZGiv!Qwj&qSO@om2>KsH{QdVC#Q%mnNLtVTh4tKLwY8B;`=gfQktp{QX3*lp
z`j<RF!8ZVrDe*U#&EGY`@&Uz;DCVCKnt?zF5zLn#L&ZQvW>Ui_(Lx+oeZBQoN2=!c
z*Zn<;PjN}Bi2kG?u(|4nb8Qp|G&Vaa0zF69U4C+aLaW{18t48hLP};2qUR{TriE((
z_nufef{Tz|-<dAeXn&`LXW@X2t{H+-_1F;B6z}qcg?2zXbkVI1(}1?)(A<-ULX;5w
z(hg}g$Y445OyBFvAYNRB<ppt-C6bY|06yHV2BK<*1xz8Y5>WBOp<Gtvt-mE%%V7=G
zZjWOid`mc)f93d|BaX;0b@3DsETG8)^!Bn(^LX+{BI@p$SrkK&4*42U$`DT9>)YCQ
zAo-a9Tr1n4nZc&V?(4X#(kb*jw}?4Yd6IXU`Uo~-tv&3WlZt7X=AE&j>pXna8_WF7
zu%l%hY6M+wzY%r-KGIF<JxMv>b{7R<qH4IVL8m}Pqmp+1;OhZ@$(!BZu9knu8|z?$
zB%xt|Cc7Ng5;dJp;?#82>h~U65B(_(#e9GL)8hnJqlywnCmU+XCwELaE~6}7dR^0<
zmG6o(Pe~FJK>Sp-LmmQ_Y{Ny|<%<-BV3k!?K4k7SP4Ui}8v#G&m)pT5<uSE{-prJ^
zkuej`y%;})wGlb5r2oOCVbt!2cx|E6>%^uHxV*AOf5Z3mFX_<awiCMtKgZ4Z$GRr@
z?;kfsEA#&kIdSkmOsKN3UsFx%NteG1{|;i1=QWAzww7rKfZg)(#rz=(>%v@<RJELD
zUZ=V_`@ZGHPaXjA_Td?0HEt(E3M<mt8=uHvW7yV^ZszgwdWY8e9nCZlvp5s9%N!>}
zNJoU0h@y`^L<cvhfcT8I5H`$35f%)2t9YeE=`2Z(`apz7>0CQPfmGf{+kDXi6rb#B
zHBK+?u?~L}H9l@Q&SWpRuHhg?M142jRAWZ!52aHNiFbvJ8aIyf!pst`fjGf5-6-f=
zwb!bz9W=``d@FkoH4BPMZw#@XZv2wK9l1@uAviWs!4QCw$(cAyCaF|bC^_yq$P%7Z
zu{nCX$L?(D3Z0;9JzjM5)QOA}SWlpp#I+9B9jRNo7%=6RC*+7oc@0!e*%D|r3Xd&G
zl(~xANHEg(s8pe8%^PLPo!Pq5z$A<bqH0N>2(dTpf|bb^>)2{CN|a^v@|NwKqqt4y
zZJw|xD>_7omTcgs+u=xRHk>B!XurguZl!#dFd1?Y8D;e#LZ6?H0EVS0ayB!QtN-g$
zcH%6hKcDnOkn3A`eE6n7uz(m=Q__Lq7zgQdsbNhgsPy3#m~(CooW9}S<Lk8Q_|8$Q
zVy?A$mEw)!rqsbEzU!CeLn0_1nXr_c9JTMXDNKlP&Ik~|V1az7l<r<9Fo&NWBo?lL
z0Sqj25KPY1Y@i?FETRJZ_Fu&<K6&Pu(hmOUJM83>sS<!380BBuaR8|_qcLGLqXv8h
zonhv@CzQ6Pg#kRv`vL_*yWCY;?NByoRrx$OjDXUMtO5t)V8?v^^=i&tyqTqJ(g?~^
zcGRy^rD?pK_(;tkVJRMe0VX(CM_|G9v)dY@XYld{7W4%q^GJ~fkgD+t1)vg%=OTN5
znftSgd<ssWjzQ!2US^J%4L)aAtS;1t?MlrYqh0}fM(t*88<Q2r;%NjP5zGe7NO|}$
z+Vaiy-&OY!Qp+bb6RGf3O%h@UH2w>p8C3pFuJO|^k466PtsDJwZU4jVD^=Zf6c$sz
zJx3=tMkj&d{`&C7jN}vI;f;uc?!x`X7yFG4w_m<Rm`qEX8p?oxz2s~fZf)-AJ3XgY
zrbs~!Mz?rnRe9Ow)DENGe$`~<+`PHT?Nr{_h#&o#X>Ux-5YG#Gg~Rqd!M6RXb^Pvi
z%t2y}>Hezt%l@$N_n%u|v#*jgp3)<JKyT_EVOER2@My^>OuAYCVJJ)n-Lh+21Y{5(
z{EQ?{{yV5!#4u$K;;=zlSwb&<aEXL4RnkB`q%lym(lps1#MBnquunNXJ--NMgNRUu
z!UY=r#cSI#v})4d#BGLt+EX$F2#O4%kr}7SqYH9lA9hK2@)8QWC2^cTjq=21HVZWK
zuZhzoMnP(_RcYXZIdZp|rD^2+Ws;O}szD2=^y>nd8J2pr6J!ak^wTk~#7Pug_Ji~W
zzIeweDy5|82Dy0Q5*14Ejdd$Dj$?r03lnnPl=5km%95RA6a~DGO6YZEuqdOgUaFQO
zu4U~)q1@XvD5O}+Z-ug-R`dp$p%jSwk9xHvD07!%0Tc#7cqp%hs;f4&p-QVcZpkl(
z`ElaX+Gb+m8b%|Bzs)6CF9b07oG6b5{^&0|4*JL1*mI&oIx`Bew_lWCMGHW+^3k^T
zMzNXq(UD+64Ee8TSm5)<wzGR~Ci>lC^r`p9Ug|pAbz()b%^tO2IYYLF!PBtzZWsd%
zvISKmColu+(}g)1pXXz_g*7c$hjGX{Ga7|Zq2>!uK?&*K9$hJ&Et&?ekLm>0lfgUI
z4MCYovgLTSV>!|vG=YIL0FMldJtyfX3?Oyt8JihgBD<$+&SSv@nW0}+4f^>V=?Jex
zISZFs+aFnEzB3pEbC_uWhcEv`H8VLSZ#J!#o;EbI?WSGIwwI5GE;R)DF@be11NTRj
zkL(pD$XEpP#a>4CVoAC8AxU(M|H*%J8Pc*TD%d;?W4CO2VlbT3e26X=rIpJMW)||t
zBtD;=S4a_foJ;IY*+jQH0n*l_#f+dqI!IR5z`tP>Si>@8Uo<<rvT)2pq2LQs!!WJq
zPhOeLdCNq77+?V@9lDTjTG#|ElyDUr5AYLnlYPqRSuaciRZ7(6Ug$^4rc@C(mqw8G
z3bgd+DHVb)`fa}$#Y}=0Qo!EK8EFRfD7TayWh0IezoOb3ru$~O788LlosD2+j7%r7
zMEjRuG)0Lcsh<%H95VUDqAHS*akLpJn67ogK*Gr|-ENL*+OVT^m9VbUs-?&nor{?P
z-PwtVfPPu(P((7(j9{d~l0sgYW^q_89WUL*$n>S{B0)7%2v-7I!k$kBpHTmCx3?f$
z-V45|wQlS}4y_x{$ax0I*8%XXm3rf9hzemc%s^*5MWkUflo)UxE7I_{PCY`gk8D7?
zq}n;5q%8X6nvMkAp|ztEy>0Vq?p3_-m<;NH90_JLIdb`iwJGs})O^2~OaVug9$s;(
z1TZ#2rV}R?B2&11e18F2sxI5*ZBPkV_iN@8bnk)$Oa^XTk>TskAA@lF)Y$Wlk=8bD
z^~8Br&7<s(i7~u%qF_8M$~?$b3lW)R5p|Ul*zaZmKY{4BJH{@kSeX&id3<{SCuoVg
zJ49L86lj%mwdR;mKNc=DaZCFqNGtmZ(M8&>r7Oww1+Qove3QT|**)gcG2hqNcwNmx
zdKav4mfpGzC$czs#!CmON)5DFpNkY<t_i#L%E{2dqRDJ7b=qc+7FyX}JACWm3tnyr
zr0loddo($0A~b3_NC*U;sU@>2Zp|nDF;s7?)6KX+izo--brmr3100TkLCV3NKFgNP
zzRDHL-TM{8UGWvFl$e9gDvqs1tm7e8r(%k}m`Y@=_?SSB!g#1F`AJPqV30|!=_t#h
z(Fz>96BCh@xDW?bmtWDKMo`x_sQAIHQw8-0=%M6^dS$u~RhUPwsr4pG9c@snMx#!v
zz4g;^nRb;#+41L~7pu1BqmOog{Kai+aTtfhd#kjHA~ZLN2kB_bi;KzHjR#|?NgMbq
zDtE4{hNCD4;Yl8%E#gLcPNNlK;#P_4h`pCd8+gw2kPiuIy;x?#P+wJDc1lF@JeRB@
z$Q|W*vmy&|?Fno9LHPW%3srylO;$JUqKUMV+^Jr}>;^sS*5lp}0mQKrIH+7jfcj1_
zg+s$)`O(~+Z5M1?oCRX%$?t%xb;lIl73z~;%t!lwX8%D0z6e`q4aN9(@%@&dO|W@V
z;++@g`9#rU`e;?9(L$G*XN(8Bx}*DJ_pXYD$X;RIbq8Rr%D=?B$lobn(>RSrmZ>`M
z-l<&a!zIsh8VZC13ys|@+*k?NH}m`AtVbM^IEkd?ryM$Cw+$2q#>N(Yi)YDlurNR8
z>WtKfeX;c>G{i;QZ0iQAs5v{=VT)>lsdThblcv*gG3QgFQq=PcL_cL3UQ$N(Nxf4R
z4mK|YaaoT7B+@rRIk94fCa+#z8pbv>GA{?k6IfD9Qd$Y`8?O7`P8u?l8Bd@O1+~5F
zk3b}KkS^EVpdSt0anCSL5RrJwt8hsKk+@l)dZiqBrNB~tHz-%_@?V2tbD~Rua0hn;
zWoW$_b;r;ONq=)Qf5hY79~#b<R!zl*6ZwneUYoF=4IQ+>-t;BQ{x$wsnqi}_51Z!v
z?L4$6bsRH{)NG@|>9RUTPPU;ONhxDMcV4ew6>^FOq?dPAiRxB-ce;+K97R*jDvO87
z%8ORzfSUXc=Fjj9(@u|Z<>=g^{8`_qMa2JjSc)TIdA9;7Ovs|WIF^2?5?@bHmEE9n
z?$-A<oN^bY@f@Bf<!)T=mKZV=Poih)8kP1*|2StS*^Cut2uJuF@n=d@<MsOx-Jc0W
zd0=6)xSc6UB!BLXiR~JfK%uBGwV5s0HTx*;4$NAf03mPD>4c@Mu-|KO#O;O7Z`a9q
zxJ`0HDXm>7us3bPC>`CLNegu8cx_I)SX5V?5VP5TcLnIIvESG{2TtKQ!ND(1UekCl
zc7Z~|Rf=E8iPbjA*?%a-$`REL@!^e6s)e9S6@+6`78Q&|uy3@IdM-hfL5b}12!>@7
zfi4+{dXzwG`c-9RA($`Q=dT2GyitLcY8XS@vZwkO3Ci+XqErPHx&*hRQ>k!PAe-D(
zKu_wUU(Mob>8;nnjzNB<#*tzzfAQ<1dwkKY{0Grhe`2(zv-PHPL9cVv!zUY<M{zfk
z<V0eQf9%dC;#riXRF;-1HKIbMo(_=~8#0vm@<hlun9qi>JW6qGB=2E|tUuu!j*P^h
z6A5wz`(>$mvRL93>J%R=#xIxH;;J2358v*)8^Nzz=BoGRGwaZ{3P8dA#muN~;kYDc
z>n7*>Wq6krKp{owp7p!m9-g#sJ3KjP8~sZMC@ntYOMBxNs?=;(gUT<86<6XlZGIJq
zmjh$mh%uR~bHRQ7BgV^SsjI<oAb9>B;v!HL`s&hF=eEGq3m?O6obVrt*UTHzU@Z4X
z-?+ybh4+k#yoVF~sH@?!)5R-q4Q|Rswd5kT<URZ={jZ%D6y-Qa+kh^AUc*ekI35h~
zR$YK)7U+HUlE#u_wxi*BafF_ACH8-bsgsu%!04wNJ?UePb4d5hN8kE!-4&ey{qgn%
zYuq~XX+|-=h&2Y>iVN*bX#f!fWUUvZ%G_8Wh_-8~Krz1T{UZn5L6|icUfS5@Q;jk&
zVuJ-%WbUU5U_BeB<zeJIT}VkZ2q|d(C*qg4Yt@qZc&iB$isFf&v8h@#3$IucKsAjZ
z%PWw=l^|KEahw|sIEc((WZ4&Va!kom@dWhC8y!XT6neSKD?EIolM6*}`_fE;kl)?W
z8Nfo!>_uF?JDo7x^y#3+W2V|U%!@mnHH_HruYy(upytxuSII3PphBQALx?9`yvjWq
z!{rDyhWNr%9n&I}DeE;wT&`j5^IrP1xa2A;y)KY>>7rzO`p2Zq`2~9mCr27&C9Y}$
zfx-Fm65aMd-EO3PxIP63dL05*oaG(80iFDGhV@zm4jY1XbsMVt3-+Lk$CYS|8+hS&
z8-%Yo2Jc~sPn4sx_K6vo)bL^3@`#>GdT8enLM_X2n`ng{EjEy6QHHDJ@!K4W-u}5j
z;R82L;^tjjS9s~0wa*aDf%rR1PNM34(^t5x<n5iG^b`L(fVV?^$Pv1ZxMbl=MQl!g
zJ+q_!e3yvJ&y<Ma+duB_sV-&{IYvnw;+h)l{&Ph;<trfadMZKHwt@hSW{dS+V^ks!
z<TrpGnGV2?Hp_3OtM3P0(cR~VhMc2W%7#kx2&?X(ToYZlcj_L1(sa_rV>CC6U85Qv
z#9;JkXR1$G`yyCjQMyIG)@UwUJ-!4f);oc9t_(w1yln2mwLz7>DA6+c{VHy#uD;PW
zN?W=wE0W_bC`8(N-?(lFJxtjI;7k!>)4VR^AiV>FUDtB2%X2l;BD&j^t*Qr5y0^;)
zw?b0Lo~#FTBRnG3aNY;OfGPz$bxA(;DSs7~`8HJMf(s=V$pp@Z>o_eid+dOnJS&Ua
za40~9C)`k?Zi>!KS<OlwTP>8xnaf9n^g-+oHVESv4eYS(du>_~|A515P|J4yDM=;2
zM0UyQN$}xOR(jHhN`2J1+j$tsogdDId=a1G34kCCB(G4k&=$@;>O>I|B>>^{_48Sc
zF7goM;qdlV<~?UOte=}I&Ji_tE;=J>U=Zsh&qu-Rdjs0a+UHRgr^ak6plCe6KMeF@
zJU>)>K~p3`ao6e%LWVNsOi6dIjRmGE6I-(<lO!XOXh_gFLO-0uwZ0`}ZG(v3mR$@V
zhbizmP|Fy7qAHq<hU<}*@olC9;W-?AhUPuUh9hRQ7@l^)?Hqsj0Fr-B&UlrM`e5-2
z)ZTY~fr75*3fc}2eFnw67Ki)7y}uDwjp7jn<W7M0AY8w#-H6=3<AQtjJs3@os|LKL
z&f0;|A@b}?C>kifp$A3{Sw{=m9-@#~)7C{Vyvh&i?kDsRp06ZX^m-c+W=jeJ^p~r`
z&+tq(N2?f3FuG>)h|bl(t=@I?$kxS)Nd|=ilsIL(qm|b|;aqq@BJM+w07*Q$e{p1b
zO-~@UruWqZ<2gtf-?x_M^b)WpXI+Vm9hQZ_$sO<6#&`h%{5IL4!UqK9F4uw1q`lGK
z{0=2%_apif(a-9CV}ppm<kAu2ogsB+L<JO;C(?34TZGjM3dODQ{-ishJfl}Oyey!3
z2hh#!HI37Q1er>K!6k0&h0_%`)R_3$Lf)y<^B~YGbDr6N0;I?p&eL8ihQ+5`uJtvS
zwQtSfb<yi@k^~ImzjcccCmDeVF-Q-tC>OCxj}B3QIBrNu;DxC)>e6{U)~!hCzoqNp
zny3{~n|&&G;_;E;K01d<folC-cBwK|vYrXullHa!qKJ(HGcAjV@#4((o1ep1>ODI8
zgce24dlcM~M_<H0b;0&Jf#hk*qQcG5^y{~Dsqq{)qjI9#(Sn=f=8oh7lrKO-Q$hog
z-1NE!=%uHPN+hYvYC^{KNY?h@ZtwTSFLX5pu$AD+NJaFylpD!K(SQ;ufB@m~2L&SA
zLru?t<6>7Q@}Ut2iC8q15dzD=iGf1Qb}_RWK_mU<iCte#6c{>~xGb!Gi?!<LrcKmb
zdw#_RclpC3Eu(63mS&x%sa(#>VX_-6|Lq=cFf7%4eVe=NU9K=Wtel9tQbDhyk7@)G
zaj0%HnuKM}X@kYq@wq8P8UR1P)|Y09o!s#I`tXB|@NbghgAV!lkM0-Gs6jjMIJD5~
zLTaM>2S^zW_=`bgY{)EZmpg5NLtngzEc@%fOLn^h?{04}l=FyNQF^+-l}ln;N$hmK
zs2B#P%)WyHu$muQ{niPwIQuM9iJKo*_bCE-xZ`Z`Ay@{x264);+4~-3-OIP`T-_`#
zcPeW@wg{)zN6*M}nuJ;(iPbyb|6*;C%?G9x{IRt_{!DECkKr)?_lU;ef7!wRXIhh~
z{OXLMjPxZGE}TT-R6%H#QB;~Xm}EFe9!XYu$?iDUVr#}hM9pkPMw>)@R}d$J6`8?0
zlQf6iR@+cvy2>IC8e=EIH=_Fr1?>&keJd>^B{lK96=5)r-aH_DJkfsL)$Vn@#gXs5
z^)|2l3$yQ#bdR)*R1ofOEmCKVLP9=hd%Cg0imbqfWFZuEnWf4A+bwIgp6Fm8DZ5NW
z9#*z_|FNv%tp!F_|2^DKvo?fmnI~PCrHkyKxU54iYVWw-r`#WH<Z}wXJ;mHtH4H6b
zMT>1%;I6#AaySpFu+JAajI9B6z9S6suF{--a*iU!GEB`hCyV+7663v!t`g(2DAf^(
zvqL<f%6X%%0uIG>8QNtR_6sWrH?nM7C`d^aC+_^@#|yt$va@g@GW)5eal`&80|=ud
zy3H!oR{ftWnPfWzqfu6(PngIVY4=rTa-mUM)x;s0BB)^ecXT%Ht3tf}4*m0dr!KVu
zHuSYNA<MoBQ1SQWT4vfsdW$3pV}V|*QKsMfQM%{%K>8)lLcAv_i3|cY6Gmlf87vpW
zgQ<Qi0f~zc3~iQSox>K60L2h^GY9g%N=dM-xTG!K_Ac~x<MlSzAnG^sP;3xJhx|<G
z9`f>yX35Q)Ff>57LNZBXOgcjz2f@}X4z`BsMOa+#jN$U=Mv3JwNnzIQSVcM;*Z3^E
zA{w3pwPu#}T&w5q>C*~S!>Ck;QfkE4_@~-}UTIWF({*R?NVbKF#Tt%?4oqa2m1%()
zy5ShK6#7M)xe0fFu-=Hz<<Bz6Fj>HZzOA9QOVm*w#3~(}3Db$((Bg$sXXoT3D=1ov
zkfK!s{bCbgA!eie60>QMBl$du2R;Ll3Orz#P0szlxIga=FiAe;RxOO3j-ZZT+Q5*?
z6Q|eE7B>era5Jggs7a`%P6Eqn0q!c6Z}Qx?#9q-qP&^E*n=zQ71Rd7O)>QQ;5D{><
z2$yN_=V^VeVH*_*rA`uoo|=OY-_oF8)MjR)Bm6AOLGqg_X~2FldHi{{#Wi`MrnVzD
zalyDY`H#%&obRVPCEA+Q3Z{==JPNl2U5QKkReQteUVho+E$bNh{-J=04tckZ#4b={
z#YfY19!wIu2|?Mr#~!MdwAhG$=D?u3d+3Y#ql3UC%v@ma(Y->Q6+guK5nSZ@t8GPl
zx0v*OK4X_58bPD7r_r&0b8Ke7bAga^g~lBc+6|!@rJbWB4|#ay?>4(A_g~*E1n;i@
zK}pYZg<nj$QzDwLO;MsH8?IF~9>7p5CMF#s2%bg+NMygbkP)>)A8rmWDUoh6^L%h%
zUUA?NX=0>Bf2xpSkG+4hsathn7-sQHVo1_lFx>~p=JvevkF4kt|1(jzakgQep^wom
zfv;MAa8fkl6)X+?yXVr&KOyuO2y@d*%*(WiWs2?0ULdr`zIB!l;Q2<Lc`Et>S1<20
z7k5(g7f7pd_44zx-869ZHB4^e`7ds<H?O~FIY5aS$8yU#1y;DU&QQG+ps|qg7OlS%
z4FU|#kp$kW@+Er>-q;y|P;N;>sldO2o=P!Jawe8~XL`#|I-*kidTo?f;>AJ5z^yPW
zL_Yy?tCFf_94%n<oLmpJ$0@qKqu~N>=(yi!hm6D8JwG0Jd^AsX>tTdbR>88;CQdLJ
z+Iljw44H!snRV~hZ+`*L@|C{R2I#7>_C4}O(DEM*Z}R&T2-zmMU=mc?I<mpUvrD=0
z@KFSim*`0h5|CH!BDX0<l(UX*de3}n;~(q2k~*@|z7WQ-N^bY5;WrU{7!Mr#kr|a~
z^<&N3<M9dsy$b)NZa4~7UDDU}uZ)g3+jD6|lkN&)z!FS!l6Cy(F)yvY)O?-h^o)C2
z!#W~9WWLz22_OzHRn2gc!&e<)oAswFns%q))vG|lNy=ZbU140w%eg##-v+|4hJQry
z6N#CFX@x9s@T5pyFos3Hh*Q0xJ_(=p=)?kupqUD!_xIsXK?|kz({6=JKUukZJCtWp
z<QTBuIAA*hQ^HgORkj8A21&M$zgbbP*uZVk-EE@d5q8#6&)UP<je(W|2;h1O*}G)P
zX!#e63=3?PbFsBa%JpN85Iw-9T}iw9nFbn@hptrR&)UrjyDZ5E;kVu4c4rC?6TLxb
z7JI|TAC6V)*!paP3LAR%m<rGT$Zrk$1n}FQc0S^|-I{t7<zfOI*JI<N`?2K0M{JfG
z7T-rylfnd}taQ!golpRG()8eR5YKxLPhqU^pm4y(4X%)gU8A>sr*%;l2Z6E@GdQXQ
zE6yFGUdVB+48dw<tl1V{RQNzr{XQgiTS4X=r8h+Bju=1y4G+_%dPJ_CRTAgCNOiWS
zf8q4+NS^QC+BE9}wLb&XdFpgre!~}kEM!_PTkKy9dCz&!-K#LJJ<vSQ0!}CrSS&c~
z5t|$AeXM*1UshgCs}|)UTjtxG#%8lY6b+?A$azo#lZn|VF0AbP*JnAGTHo{NN0Ze3
zk-*viPnzU^dzSw(Oa15LEWiF^lS0&-Uw@$gi$<;WmlUNI(NG~L4A(Cts31%f3V0j(
zQj~)=)6}Sl)B}8)xa-9yR4hio^C>^#eF9P@tRto9xXw7caarv>W81sy`xkBCuxLSS
zJYB2+XzL$#8wSySDztc86VU-1jzEqUjNycoV#A3LHku%J`m6DjMA&sBA%70|xj?F>
z$%deE3^iWo4K}dQJT1D^^_tdz*`(?FuPq%TL5j8}E2Sgk6A=q77Ds1ZK30w{YP>p&
z#8Vq#UY6HzA<Ovn>Xjm1xJI4Cl-el^%?p2>fy%Q1LhYK1u%WXGg+sMSOM7{D<9fHu
zb+yr%#^ebn7uVIY#S~TK9&<<KW(jiaY8z+Gk=U6`EFNhYKJ{6{!scmJu96g1ZeGL1
zeS%5kh)f7AT+YF<L!$P%65IL2nRu>jqK}aJc*IBTk3GesKj0%hEbwuH<+{l)@|rc5
z-GAQ-{>shxYk_GNTO?bgUxJQ-v*(hd_CtaB7b_}5`75XJCbf7RdWO2IB<%VdjUhYJ
z7abavE%-q)IMZ(_rXmIk8F0$b2D^fJ^0L!SFQ5mNFGF1!vnRa4I-tx|iXn0K<@piu
zn!I_Zc>>#8+J`5P%s$me=Di=Bw0FgqGs=|<>MNzw1bHV!z{tO=ts#3LXvR1i7b-bB
z(+XTuNJdAmk#H8ahCAUo5Qv$Z{fbN`t@EL+^l`ZQC3gjy8wnWDjeoZ~-X)RmQva6+
zAGHTbjm(R?DsQ^~dbshIIZMyjaTi`&a1+4*v%>4I+w4}F5KMetKAu0j2ezypAqt?~
zIT!PzHOjTgtiStX=)^XLORSQ-T8qwJbKZV^5`a2_Gx?9e%J=f;XO4t{e|#d~(b1GJ
z^$Gx@Zl~deLFp61-Us0Gwc!6HhMq<4J6Dn~itURCUOqntcF|)BJI97<8wc2{_enZy
zpQYA?u{$78y*U+Vo3?EV&0iyA3X^e@^)cYW-}n9(1BqMq&0Wxs1(oS1R!Zdmh#os@
zGedoc|34|qg>mCjeSZ;yrfpDU|J?f7%CZ25%mj+lgz{;?5%t#KjMYM#a!k_dxKL=O
zw%h=CknWQy=-0?1w6l62Uw>z^%}<=K-$VSu?AJn;lNsw#0&Zfci4WRjOh7A;3M6@8
z^LHs+(~mJ31E3#i4h&vKXpTNhdd9K~voy6W9!>;Z%1xc&r!$%{6E{rXI9`I4OqQNy
zxJG*RRQSJ2I}>;)w>OSYhR9M~LZos{lo*6aQd!12G`6~;m}DQuPLfa|WlLRKT+1|B
zveXroREliLTFIIgd*oJ1uD}18D_+jkpnH6Ltk3UzmiN5pJ?FgVd8qGL{!Dwzg4I<C
z=h@+;{o-ARU~`&iv1nYn-r6;!zgcRWe6f`BWTT7%4c{u=;Nt}^pJ{u`;i@}Ru}x+>
zc39+X9C0Lx{^I$>^PQTBw{Rf3>3_1Om{>t(y9z0b^~)7bDnHXYu{`Eble#U_&d!&&
zqO0muWxsKCv7awPsWYwfe3b6hW)i9BW@9*n&ud8*nVdYs9=}KKc5lSZ*Y`aF(3%ap
zE0P%VUey^Lu(i4%-Ej2%ie^l4si4mG?ef)m+S?0RB6Dg+JSu{nl}^7YYktIO@2mXg
zk6v{~eslFzn0gh)_}|ncga~)ueQfGhocpp+;sA$J2xw~&(AF9YwKW`wbJkP_az%<X
zb+*4y2=DoGceYtj4&8F@68?2HFZD1d`*?~#b!<T+o|&C|MU0DgxBn`u%PN-aa;2r<
zK+?xr(AqL_5w(S0s2xG=3~!UECDi4n{G=Y@=2adHw`ICzjwuVa+m5a{y3;p=v5M#8
zi1i=`p{+3>>tbe^WB+J|Mg2}58P`%3hV|#z$|=ikYS{X?2i_aoWV<?9$}uLc*ltUG
z5trGD3&iHGB#jB8yISx#mvHJ1VS)?cF}2T8knhWiCVt(4D82MPgU)To4Wv5tpMR5d
z;1#x#Sh-?Qc<@Ytg-e-AM8uh}81er5V=>Rqrw4GpRmSYS!x-AdZqF1d<lLZ|QOm6q
z67g*8l!QjQ`RClv%lX4o3h#8twkUm}a`lH_w_9yHIbPpXEty@v;j{t4R3evQJkr=4
z!_OyJuViedFJ@?!>N@&?yW(6tB{}(slgRUw^dojogkv5-xylMbrrR#(P?LBG6U_1d
zQ-8r#_esbnGGsqz-4h|7i~gBpB{xT3sAEf?O&#b5@0H&NPIZ((W9#CKl(AZR>XME`
zPb()$5P(&J=uEV<wUYSf7ZP5sL}zC!*Qq~ar+;!LJ4$#vl5QU8B)7_~_IqLOA~RaY
z5OtBVo^UjiwNO{eD?_PNuV{BegNZdJieIZtE@)y{(cl8+WoE0=HOcJ}o$V*S7~(%!
zo4)-JqU|PnI6@-u<1fjYN2_q7KJNE#jhKgZlqT^`ydCer?jzXZOEje%PP<fcej`g9
zuzs}WVc0dbDt41Vn>S-MZpoOfkqk;1$&rj&6sb^2G1b7ka?Ij}Axx}kXn%#&Ka~=(
zBEvbvGPh3#IS#_E#a-6As2n2Z8TwkqN*zO|#2W&)1eLqCc(ck-Ndj;4+eDMHIV!@E
z2`}z$+Q+u8<ZtSg6o;&*zm^q78>`;uvWxbY`D(P8UE-9Rw>pa4WEPe**>A*Ffc}-k
zi2sj41}83Yj_aGWadB=UoS))DMxUQ;iFq7o#;<PCErhz=|InYW7X7VIj(V5%QH?d1
zl!i>?R<_pkho;(Z-2L8j8P^u^D%f+dPG;UpB}sTa&=$IoCtP3saye<Yqmo%v<rj5*
zC!A+@UqMy7{VuC?D_n}_vWpmzyY=2HqsLe}!h52}_<WPZ{Sw+GUw!;K<h1J$KBq^j
z=#<x=edCo!q!SwYmOpNk>==&j8<*KzwMwDHF+<!-sKRkb>b<+pKzqR{Y_P<(F0mwn
zrcl;zL6KVauEe4gHDhPT>Z@l>wLeSVa>1q*r+G8fesLU+(e^7VMd_Za%hk|*$~GF3
zn(%p#^~OgrCASlWg73E2-_vMibv(SI?cLZI?rTqZtAZ%clOC0It!$JlW0yQ1n#S!g
z*z@YiP5%vnB#(n^Cz#oLcZFs+q^eM3<qruI6>S-;B$08#&rD;RZ<<^bHMtZmD^iqw
zuBB65e^pB8LmvG%aninJoT`EGDyKd=Wa&3AYvQlr4>f1xEy1lR(5T+zoBBF2uU+0g
zDv*2a$^5ln%`9J`F_)uF_lEA&znh=2`?0e2I!uhX68b>eF0xOMaUf^1X~ue9s<bR2
zp*h0;5GNjeUEUMCFJ@mZ8-9r;HBYBBEAEo!#1_u*JC${Z^Rt)|Z}?_2$}?~8waHW#
zpcY4ejVUQR_v%K>F|S;^NedDo+GnDO%C+Gy1zg=|O+5EmS8KfwBxOGp^YhWZl9LB+
zoWXCn6}9=cT<oyn3BJEw>l!D|ka`B=OG1C=u5GOp{kS!4e_KL!?fWQ3@Ge#H@5XwH
z8|@}}^H&;Lh*`Eq-rHN*GBln$7*!&cCq~X4tGQ10-EhUmc2~V$442}#p4}EhN{}hO
zt)h1`@j%<93zx6DSiUeHVsA)enh?3KU(twm7ct2hzoFi8Fhz4PBbR4oFYZ&Q$;dT>
z!C3D0%&p~^eRAO~HLXDdSN+63B{Q}9X>L4NT6^*ZUtz>@ANBO)j_s3mRYP4t;v;y1
z1J$k76io@2(v=)lQ}ui_yf*ydMmBj?=0@)9wY8RMTQft)j}b1B_xu07p-@NTt1O1-
zrP&glb2U2-`-Q`(;a+<SN1MQx{pq#+86UX2D`Y)Qa~0EWdY;r%ym1N@ArfL2Rwmt<
zcv<l3&Rw{PtN@>19I#@FcwNEcG3AfmuF+c=pxVoPID8#uB=m8}g~n(O(fV>{k-yrT
z%?ghWQ)IKh$vXwJZ@YAD40G=ap`+1KK4p)Br_1Woavo@T^m<>PC&B#hU!|J&ey|k_
z4nD3pDDgS3(P11-Y$uQNhZVz5N6F>F!h6BZllEk!_MdK|&aPx|cXhY3a?=stT8Y=e
zON`*J*XWAt)HGrxwZ*q+Vqa@ZR!L$}q20V!284MwiP%v31Gsxj)?B>8!)?>u^OApn
zub<C#8CaBD#;^v>ibAoVP(51dG%rOn3B)1%o>rsY(~gcHxBV%zHNcGJAG5LXzusqp
zf6xIB1mL$bi4w3Gd_OZ<=ql@JspAZdBy`p3fx$rYJ<-5uph=7HP0s?jFr8%~{M}+|
zNTO>9R$pfs>diHr8r<k{`KGN=w49!p&wP6DqbIX|j!Zs18JbI4dQz+ANDTw2nc82t
zI9uiz3xIhrWc<T{o?ez{E_SC9t&)x`LG_;;&pbX%F_4QcL8EM$3lL@lg#`YHW)dZU
z=67Hw=V~|tPEQS|r>ccBgeCIxUk5pYDmyHW0xgInO29$zSUV$u*HXpl8RB4To$Jl)
z{=g^)d?NLZLQw)fbI!8X+h+vqVdLNM)J_c802p356&!dPP6<fmq7%|yg-mv*g?w_>
zCE7UwrwB-(Cm67|{rYWDP!Y8AfYQ_I;43A7XB{1Ynw2%tgXFFTJT;NX#G{D6V^}|d
zVDJD7^jm?x;T-)4a6Qv{?DzgRb=^((gMaJ8lLIg#^ggES;cg28O4wN<uFl{LRF9e+
zOJPT$hCnZrnv(&n;8HR$wO#|OyFXF%F9fQ6;8S#tx&W4*`b@peFYD|Fyx4$R8v@7i
zz>B&wi4wpM0>1vR)_@;4cOr@O<JLf(H(>b#+|3e&Q7EJv(^^|?+hTO*&u!_h2Ss`y
zx5A)}f$&VC1c<8AQN@#OY^LLn!S!0&Q*9~*T1_5YgpxCYw2a=t(UH`pO*9TnO)F@Z
z{`~n3`;;u525tv@p!e>cBQ9@1N1Q-(w^ep?vvNE_t6@CZl1Ngs1HH`dhzAnP1TKgR
z&x+=ipcT78VZ`UK<iIfc!<L-Gn!gkSuW+A@fO02LMsA+8DhfYHM;Y!%njjz?D9`*1
zI5zoo0Vn}-L^_P`EdVC%aHMj$df-sT2*B2AVZhwL#;`UVA`j6fk?CkJE?^!EgJXvw
zum`S-ge_)`3&z5sco1x_*8<pCt1CYU%mc&VI5G$<_SoWK&{7Tzf#abdknP7851GBj
z4ijL<{s`fz|KbT#2O>6Yo4@10Zu1dFQ^1lLKX#%I7Y+9FjbP)?{2X?wBENh6hH<bL
zWdxTMvSb_`pUN;7cA1KB<-(TCU6cb=I0vwcOC$#@kxR}2J%^Vt7<QP2fMsHr45s5g
z3+BSEh!C!R!jidD7nSn7j)`C}?A-+cdnNrO820r7BVivI2$GWWlgO#N#Vq$^FcWsb
zfG~^Fev&!c9RrMmkF_JXChC8}EmXJg>0t!iov~!_g0%`C9z|%z*OpA9f0PuiVfdgO
zf~Mpy6+QnL1HT-G5DZEdApC1jdVT`D&y5iJDway1HzLD3f(U2xlZ7~o-yeiq2;Q4Q
zs9aAMpu!K)v!10Ec)Wr4NDwHhZq{nR)NJ^N3n_D#JihOkz~zHi5)l;c*?&PH>xu*&
VCNKd3JGtOvEm(5t0lFyE{{i--k}m)N

literal 0
HcmV?d00001

diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..996a98a
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
diff --git a/.releaserc b/.releaserc
new file mode 100644
index 0000000..a05f894
--- /dev/null
+++ b/.releaserc
@@ -0,0 +1,20 @@
+{
+  "branches": ["master"],
+  "plugins": [
+    "@semantic-release/commit-analyzer",
+    "@semantic-release/release-notes-generator",
+    ["@semantic-release/exec", {
+      "prepareCmd": "./update-versions.sh ${nextRelease.version} && ./mvnw clean package"
+    }],
+    "@semantic-release/changelog",
+    ["@semantic-release/git", {
+      "assets": ["CHANGELOG.md", "pom.xml"],
+      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
+    }],
+    ["@semantic-release/github", {
+      "assets": [
+        {"path": "target/perun-ga4gh-broker.war"}
+      ]
+    }]
+  ]
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000..b7f0646
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,287 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.1.1
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`\\unset -f command; \\command -v java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir"; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname $0)")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $wrapperUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        QUIET="--quiet"
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+          QUIET=""
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath"
+        fi
+        [ $? -eq 0 ] || rm -f "$wrapperJarPath"
+    elif command -v curl > /dev/null; then
+        QUIET="--silent"
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+          QUIET=""
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L
+        fi
+        [ $? -eq 0 ] || rm -f "$wrapperJarPath"
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=`cygpath --path --windows "$javaSource"`
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..cba1f04
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,187 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.1.1
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %WRAPPER_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..dc43bd3
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,4423 @@
+{
+  "name": "perun-ga4gh-broker",
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.18.6",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+      "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.18.6"
+      }
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.18.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+      "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+      "dev": true
+    },
+    "@babel/highlight": {
+      "version": "7.18.6",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+      "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.18.6",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      }
+    },
+    "@colors/colors": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+      "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      }
+    },
+    "@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true
+    },
+    "@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      }
+    },
+    "@octokit/auth-token": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.0.tgz",
+      "integrity": "sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ==",
+      "dev": true,
+      "requires": {
+        "@octokit/types": "^6.0.3"
+      }
+    },
+    "@octokit/core": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.0.4.tgz",
+      "integrity": "sha512-sUpR/hc4Gc7K34o60bWC7WUH6Q7T6ftZ2dUmepSyJr9PRF76/qqkWjE2SOEzCqLA5W83SaISymwKtxks+96hPQ==",
+      "dev": true,
+      "requires": {
+        "@octokit/auth-token": "^3.0.0",
+        "@octokit/graphql": "^5.0.0",
+        "@octokit/request": "^6.0.0",
+        "@octokit/request-error": "^3.0.0",
+        "@octokit/types": "^6.0.3",
+        "before-after-hook": "^2.2.0",
+        "universal-user-agent": "^6.0.0"
+      }
+    },
+    "@octokit/endpoint": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.0.tgz",
+      "integrity": "sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ==",
+      "dev": true,
+      "requires": {
+        "@octokit/types": "^6.0.3",
+        "is-plain-object": "^5.0.0",
+        "universal-user-agent": "^6.0.0"
+      }
+    },
+    "@octokit/graphql": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.0.tgz",
+      "integrity": "sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ==",
+      "dev": true,
+      "requires": {
+        "@octokit/request": "^6.0.0",
+        "@octokit/types": "^6.0.3",
+        "universal-user-agent": "^6.0.0"
+      }
+    },
+    "@octokit/openapi-types": {
+      "version": "12.10.1",
+      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.1.tgz",
+      "integrity": "sha512-P+SukKanjFY0ZhsK6wSVnQmxTP2eVPPE8OPSNuxaMYtgVzwJZgfGdwlYjf4RlRU4vLEw4ts2fsE2icG4nZ5ddQ==",
+      "dev": true
+    },
+    "@octokit/plugin-paginate-rest": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-3.0.0.tgz",
+      "integrity": "sha512-fvw0Q5IXnn60D32sKeLIxgXCEZ7BTSAjJd8cFAE6QU5qUp0xo7LjFUjjX1J5D7HgN355CN4EXE4+Q1/96JaNUA==",
+      "dev": true,
+      "requires": {
+        "@octokit/types": "^6.39.0"
+      }
+    },
+    "@octokit/plugin-request-log": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
+      "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
+      "dev": true
+    },
+    "@octokit/plugin-rest-endpoint-methods": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.1.2.tgz",
+      "integrity": "sha512-sAfSKtLHNq0UQ2iFuI41I6m5SK6bnKFRJ5kUjDRVbmQXiRVi4aQiIcgG4cM7bt+bhSiWL4HwnTxDkWFlKeKClA==",
+      "dev": true,
+      "requires": {
+        "@octokit/types": "^6.40.0",
+        "deprecation": "^2.3.1"
+      }
+    },
+    "@octokit/request": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.0.tgz",
+      "integrity": "sha512-7IAmHnaezZrgUqtRShMlByJK33MT9ZDnMRgZjnRrRV9a/jzzFwKGz0vxhFU6i7VMLraYcQ1qmcAOin37Kryq+Q==",
+      "dev": true,
+      "requires": {
+        "@octokit/endpoint": "^7.0.0",
+        "@octokit/request-error": "^3.0.0",
+        "@octokit/types": "^6.16.1",
+        "is-plain-object": "^5.0.0",
+        "node-fetch": "^2.6.7",
+        "universal-user-agent": "^6.0.0"
+      }
+    },
+    "@octokit/request-error": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.0.tgz",
+      "integrity": "sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w==",
+      "dev": true,
+      "requires": {
+        "@octokit/types": "^6.0.3",
+        "deprecation": "^2.0.0",
+        "once": "^1.4.0"
+      }
+    },
+    "@octokit/rest": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.3.tgz",
+      "integrity": "sha512-5arkTsnnRT7/sbI4fqgSJ35KiFaN7zQm0uQiQtivNQLI8RQx8EHwJCajcTUwmaCMNDg7tdCvqAnc7uvHHPxrtQ==",
+      "dev": true,
+      "requires": {
+        "@octokit/core": "^4.0.0",
+        "@octokit/plugin-paginate-rest": "^3.0.0",
+        "@octokit/plugin-request-log": "^1.0.4",
+        "@octokit/plugin-rest-endpoint-methods": "^6.0.0"
+      }
+    },
+    "@octokit/types": {
+      "version": "6.40.0",
+      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.40.0.tgz",
+      "integrity": "sha512-MFZOU5r8SwgJWDMhrLUSvyJPtVsqA6VnbVI3TNbsmw+Jnvrktzvq2fYES/6RiJA/5Ykdwq4mJmtlYUfW7CGjmw==",
+      "dev": true,
+      "requires": {
+        "@octokit/openapi-types": "^12.10.0"
+      }
+    },
+    "@semantic-release/changelog": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.1.tgz",
+      "integrity": "sha512-FT+tAGdWHr0RCM3EpWegWnvXJ05LQtBkQUaQRIExONoXjVjLuOILNm4DEKNaV+GAQyJjbLRVs57ti//GypH6PA==",
+      "dev": true,
+      "requires": {
+        "@semantic-release/error": "^3.0.0",
+        "aggregate-error": "^3.0.0",
+        "fs-extra": "^9.0.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "@semantic-release/commit-analyzer": {
+      "version": "9.0.2",
+      "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-9.0.2.tgz",
+      "integrity": "sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==",
+      "dev": true,
+      "requires": {
+        "conventional-changelog-angular": "^5.0.0",
+        "conventional-commits-filter": "^2.0.0",
+        "conventional-commits-parser": "^3.2.3",
+        "debug": "^4.0.0",
+        "import-from": "^4.0.0",
+        "lodash": "^4.17.4",
+        "micromatch": "^4.0.2"
+      }
+    },
+    "@semantic-release/error": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz",
+      "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==",
+      "dev": true
+    },
+    "@semantic-release/exec": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/@semantic-release/exec/-/exec-6.0.3.tgz",
+      "integrity": "sha512-bxAq8vLOw76aV89vxxICecEa8jfaWwYITw6X74zzlO0mc/Bgieqx9kBRz9z96pHectiTAtsCwsQcUyLYWnp3VQ==",
+      "dev": true,
+      "requires": {
+        "@semantic-release/error": "^3.0.0",
+        "aggregate-error": "^3.0.0",
+        "debug": "^4.0.0",
+        "execa": "^5.0.0",
+        "lodash": "^4.17.4",
+        "parse-json": "^5.0.0"
+      }
+    },
+    "@semantic-release/git": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz",
+      "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==",
+      "dev": true,
+      "requires": {
+        "@semantic-release/error": "^3.0.0",
+        "aggregate-error": "^3.0.0",
+        "debug": "^4.0.0",
+        "dir-glob": "^3.0.0",
+        "execa": "^5.0.0",
+        "lodash": "^4.17.4",
+        "micromatch": "^4.0.0",
+        "p-reduce": "^2.0.0"
+      }
+    },
+    "@semantic-release/github": {
+      "version": "8.0.5",
+      "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-8.0.5.tgz",
+      "integrity": "sha512-9pGxRM3gv1hgoZ/muyd4pWnykdIUVfCiev6MXE9lOyGQof4FQy95GFE26nDcifs9ZG7bBzV8ue87bo/y1zVf0g==",
+      "dev": true,
+      "requires": {
+        "@octokit/rest": "^19.0.0",
+        "@semantic-release/error": "^2.2.0",
+        "aggregate-error": "^3.0.0",
+        "bottleneck": "^2.18.1",
+        "debug": "^4.0.0",
+        "dir-glob": "^3.0.0",
+        "fs-extra": "^10.0.0",
+        "globby": "^11.0.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.0",
+        "issue-parser": "^6.0.0",
+        "lodash": "^4.17.4",
+        "mime": "^3.0.0",
+        "p-filter": "^2.0.0",
+        "p-retry": "^4.0.0",
+        "url-join": "^4.0.0"
+      },
+      "dependencies": {
+        "@semantic-release/error": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-2.2.0.tgz",
+          "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==",
+          "dev": true
+        },
+        "fs-extra": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+          "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^2.0.0"
+          }
+        }
+      }
+    },
+    "@semantic-release/npm": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.1.tgz",
+      "integrity": "sha512-I5nVZklxBzfMFwemhRNbSrkiN/dsH3c7K9+KSk6jUnq0rdLFUuJt7EBsysq4Ir3moajQgFkfEryEHPqiKJj20g==",
+      "dev": true,
+      "requires": {
+        "@semantic-release/error": "^3.0.0",
+        "aggregate-error": "^3.0.0",
+        "execa": "^5.0.0",
+        "fs-extra": "^10.0.0",
+        "lodash": "^4.17.15",
+        "nerf-dart": "^1.0.0",
+        "normalize-url": "^6.0.0",
+        "npm": "^8.3.0",
+        "rc": "^1.2.8",
+        "read-pkg": "^5.0.0",
+        "registry-auth-token": "^4.0.0",
+        "semver": "^7.1.2",
+        "tempy": "^1.0.0"
+      },
+      "dependencies": {
+        "fs-extra": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+          "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^2.0.0"
+          }
+        }
+      }
+    },
+    "@semantic-release/release-notes-generator": {
+      "version": "10.0.3",
+      "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz",
+      "integrity": "sha512-k4x4VhIKneOWoBGHkx0qZogNjCldLPRiAjnIpMnlUh6PtaWXp/T+C9U7/TaNDDtgDa5HMbHl4WlREdxHio6/3w==",
+      "dev": true,
+      "requires": {
+        "conventional-changelog-angular": "^5.0.0",
+        "conventional-changelog-writer": "^5.0.0",
+        "conventional-commits-filter": "^2.0.0",
+        "conventional-commits-parser": "^3.2.3",
+        "debug": "^4.0.0",
+        "get-stream": "^6.0.0",
+        "import-from": "^4.0.0",
+        "into-stream": "^6.0.0",
+        "lodash": "^4.17.4",
+        "read-pkg-up": "^7.0.0"
+      }
+    },
+    "@tootallnate/once": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+      "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+      "dev": true
+    },
+    "@types/minimist": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
+      "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
+      "dev": true
+    },
+    "@types/normalize-package-data": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
+      "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
+      "dev": true
+    },
+    "@types/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+      "dev": true
+    },
+    "@types/retry": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+      "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+      "dev": true
+    },
+    "JSONStream": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+      "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+      "dev": true,
+      "requires": {
+        "jsonparse": "^1.2.0",
+        "through": ">=2.2.7 <3"
+      }
+    },
+    "agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "dev": true,
+      "requires": {
+        "debug": "4"
+      }
+    },
+    "aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "dev": true,
+      "requires": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      }
+    },
+    "ansi-escapes": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz",
+      "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^1.0.2"
+      },
+      "dependencies": {
+        "type-fest": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
+          "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+          "dev": true
+        }
+      }
+    },
+    "ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "ansicolors": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+      "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
+      "dev": true
+    },
+    "argv-formatter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz",
+      "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==",
+      "dev": true
+    },
+    "array-ify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
+      "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
+      "dev": true
+    },
+    "array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+      "dev": true
+    },
+    "at-least-node": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+      "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "before-after-hook": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
+      "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==",
+      "dev": true
+    },
+    "bottleneck": {
+      "version": "2.19.5",
+      "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
+      "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true
+    },
+    "camelcase-keys": {
+      "version": "6.2.2",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+      "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+      "dev": true,
+      "requires": {
+        "camelcase": "^5.3.1",
+        "map-obj": "^4.0.0",
+        "quick-lru": "^4.0.1"
+      }
+    },
+    "cardinal": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
+      "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==",
+      "dev": true,
+      "requires": {
+        "ansicolors": "~0.3.2",
+        "redeyed": "~2.1.0"
+      }
+    },
+    "chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "dev": true
+    },
+    "cli-table3": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+      "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
+      "dev": true,
+      "requires": {
+        "@colors/colors": "1.5.0",
+        "string-width": "^4.2.0"
+      }
+    },
+    "cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dev": true,
+      "requires": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "compare-func": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
+      "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
+      "dev": true,
+      "requires": {
+        "array-ify": "^1.0.0",
+        "dot-prop": "^5.1.0"
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true
+    },
+    "conventional-changelog-angular": {
+      "version": "5.0.13",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz",
+      "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==",
+      "dev": true,
+      "requires": {
+        "compare-func": "^2.0.0",
+        "q": "^1.5.1"
+      }
+    },
+    "conventional-changelog-writer": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz",
+      "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==",
+      "dev": true,
+      "requires": {
+        "conventional-commits-filter": "^2.0.7",
+        "dateformat": "^3.0.0",
+        "handlebars": "^4.7.7",
+        "json-stringify-safe": "^5.0.1",
+        "lodash": "^4.17.15",
+        "meow": "^8.0.0",
+        "semver": "^6.0.0",
+        "split": "^1.0.0",
+        "through2": "^4.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "conventional-commits-filter": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz",
+      "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==",
+      "dev": true,
+      "requires": {
+        "lodash.ismatch": "^4.4.0",
+        "modify-values": "^1.0.0"
+      }
+    },
+    "conventional-commits-parser": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz",
+      "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==",
+      "dev": true,
+      "requires": {
+        "JSONStream": "^1.0.4",
+        "is-text-path": "^1.0.1",
+        "lodash": "^4.17.15",
+        "meow": "^8.0.0",
+        "split2": "^3.0.0",
+        "through2": "^4.0.0"
+      }
+    },
+    "core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+      "dev": true
+    },
+    "cosmiconfig": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
+      "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
+      "dev": true,
+      "requires": {
+        "@types/parse-json": "^4.0.0",
+        "import-fresh": "^3.2.1",
+        "parse-json": "^5.0.0",
+        "path-type": "^4.0.0",
+        "yaml": "^1.10.0"
+      }
+    },
+    "cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      }
+    },
+    "crypto-random-string": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+      "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+      "dev": true
+    },
+    "dateformat": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+      "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
+      "dev": true
+    },
+    "debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "requires": {
+        "ms": "2.1.2"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "dev": true
+    },
+    "decamelize-keys": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+      "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==",
+      "dev": true,
+      "requires": {
+        "decamelize": "^1.1.0",
+        "map-obj": "^1.0.0"
+      },
+      "dependencies": {
+        "map-obj": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+          "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+          "dev": true
+        }
+      }
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
+    "del": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
+      "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==",
+      "dev": true,
+      "requires": {
+        "globby": "^11.0.1",
+        "graceful-fs": "^4.2.4",
+        "is-glob": "^4.0.1",
+        "is-path-cwd": "^2.2.0",
+        "is-path-inside": "^3.0.2",
+        "p-map": "^4.0.0",
+        "rimraf": "^3.0.2",
+        "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "p-map": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+          "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+          "dev": true,
+          "requires": {
+            "aggregate-error": "^3.0.0"
+          }
+        }
+      }
+    },
+    "deprecation": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+      "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
+      "dev": true
+    },
+    "dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "requires": {
+        "path-type": "^4.0.0"
+      }
+    },
+    "dot-prop": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+      "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+      "dev": true,
+      "requires": {
+        "is-obj": "^2.0.0"
+      }
+    },
+    "duplexer2": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+      "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^2.0.2"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
+    "env-ci": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz",
+      "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==",
+      "dev": true,
+      "requires": {
+        "execa": "^5.0.0",
+        "fromentries": "^1.3.2",
+        "java-properties": "^1.0.0"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
+    "execa": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+      "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^6.0.0",
+        "human-signals": "^2.1.0",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.1",
+        "onetime": "^5.1.2",
+        "signal-exit": "^3.0.3",
+        "strip-final-newline": "^2.0.0"
+      }
+    },
+    "fast-glob": {
+      "version": "3.2.11",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+      "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.4"
+      }
+    },
+    "fastq": {
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+      "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+      "dev": true,
+      "requires": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "figures": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
+    "find-versions": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz",
+      "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==",
+      "dev": true,
+      "requires": {
+        "semver-regex": "^3.1.2"
+      }
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "fromentries": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+      "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+      "dev": true
+    },
+    "fs-extra": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+      "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+      "dev": true,
+      "requires": {
+        "at-least-node": "^1.0.0",
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "dev": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true
+    },
+    "get-stream": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+      "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+      "dev": true
+    },
+    "git-log-parser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz",
+      "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==",
+      "dev": true,
+      "requires": {
+        "argv-formatter": "~1.0.0",
+        "spawn-error-forwarder": "~1.0.0",
+        "split2": "~1.0.0",
+        "stream-combiner2": "~1.1.1",
+        "through2": "~2.0.0",
+        "traverse": "~0.6.6"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        },
+        "split2": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz",
+          "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==",
+          "dev": true,
+          "requires": {
+            "through2": "~2.0.0"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        },
+        "through2": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+          "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+          "dev": true,
+          "requires": {
+            "readable-stream": "~2.3.6",
+            "xtend": "~4.0.1"
+          }
+        }
+      }
+    },
+    "glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "requires": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.10",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+      "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+      "dev": true
+    },
+    "handlebars": {
+      "version": "4.7.7",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+      "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.5",
+        "neo-async": "^2.6.0",
+        "source-map": "^0.6.1",
+        "uglify-js": "^3.1.4",
+        "wordwrap": "^1.0.0"
+      }
+    },
+    "hard-rejection": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+      "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+      "dev": true
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true
+    },
+    "hook-std": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz",
+      "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==",
+      "dev": true
+    },
+    "hosted-git-info": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+      "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+      "dev": true,
+      "requires": {
+        "lru-cache": "^6.0.0"
+      }
+    },
+    "http-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+      "dev": true,
+      "requires": {
+        "@tootallnate/once": "2",
+        "agent-base": "6",
+        "debug": "4"
+      }
+    },
+    "https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "dev": true,
+      "requires": {
+        "agent-base": "6",
+        "debug": "4"
+      }
+    },
+    "human-signals": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+      "dev": true
+    },
+    "ignore": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+      "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "dependencies": {
+        "resolve-from": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+          "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+          "dev": true
+        }
+      }
+    },
+    "import-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz",
+      "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==",
+      "dev": true
+    },
+    "indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+      "dev": true
+    },
+    "into-stream": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz",
+      "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==",
+      "dev": true,
+      "requires": {
+        "from2": "^2.3.0",
+        "p-is-promise": "^3.0.0"
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "dev": true
+    },
+    "is-core-module": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+      "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
+    },
+    "is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true
+    },
+    "is-obj": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+      "dev": true
+    },
+    "is-path-cwd": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
+      "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
+      "dev": true
+    },
+    "is-path-inside": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+      "dev": true
+    },
+    "is-plain-obj": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+      "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+      "dev": true
+    },
+    "is-plain-object": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+      "dev": true
+    },
+    "is-text-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz",
+      "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==",
+      "dev": true,
+      "requires": {
+        "text-extensions": "^1.0.0"
+      }
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "dev": true
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "issue-parser": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz",
+      "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==",
+      "dev": true,
+      "requires": {
+        "lodash.capitalize": "^4.2.1",
+        "lodash.escaperegexp": "^4.1.2",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.isstring": "^4.0.1",
+        "lodash.uniqby": "^4.7.0"
+      }
+    },
+    "java-properties": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz",
+      "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==",
+      "dev": true
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+      "dev": true
+    },
+    "jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.6",
+        "universalify": "^2.0.0"
+      }
+    },
+    "jsonparse": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+      "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+      "dev": true
+    },
+    "kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true
+    },
+    "lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+      "dev": true
+    },
+    "load-json-file": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
+      },
+      "dependencies": {
+        "parse-json": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+          "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1"
+          }
+        }
+      }
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "dev": true
+    },
+    "lodash.capitalize": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz",
+      "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==",
+      "dev": true
+    },
+    "lodash.escaperegexp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
+      "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
+      "dev": true
+    },
+    "lodash.ismatch": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
+      "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==",
+      "dev": true
+    },
+    "lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+      "dev": true
+    },
+    "lodash.isstring": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+      "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+      "dev": true
+    },
+    "lodash.uniqby": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz",
+      "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==",
+      "dev": true
+    },
+    "lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "requires": {
+        "yallist": "^4.0.0"
+      }
+    },
+    "map-obj": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+      "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+      "dev": true
+    },
+    "marked": {
+      "version": "4.0.18",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz",
+      "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==",
+      "dev": true
+    },
+    "marked-terminal": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.1.1.tgz",
+      "integrity": "sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^5.0.0",
+        "cardinal": "^2.1.1",
+        "chalk": "^5.0.0",
+        "cli-table3": "^0.6.1",
+        "node-emoji": "^1.11.0",
+        "supports-hyperlinks": "^2.2.0"
+      },
+      "dependencies": {
+        "chalk": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz",
+          "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==",
+          "dev": true
+        }
+      }
+    },
+    "meow": {
+      "version": "8.1.2",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
+      "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
+      "dev": true,
+      "requires": {
+        "@types/minimist": "^1.2.0",
+        "camelcase-keys": "^6.2.2",
+        "decamelize-keys": "^1.1.0",
+        "hard-rejection": "^2.1.0",
+        "minimist-options": "4.1.0",
+        "normalize-package-data": "^3.0.0",
+        "read-pkg-up": "^7.0.1",
+        "redent": "^3.0.0",
+        "trim-newlines": "^3.0.0",
+        "type-fest": "^0.18.0",
+        "yargs-parser": "^20.2.3"
+      }
+    },
+    "merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
+    "merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true
+    },
+    "micromatch": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "dev": true,
+      "requires": {
+        "braces": "^3.0.2",
+        "picomatch": "^2.3.1"
+      }
+    },
+    "mime": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+      "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+      "dev": true
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
+    "min-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+      "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+      "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+      "dev": true
+    },
+    "minimist-options": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+      "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+      "dev": true,
+      "requires": {
+        "arrify": "^1.0.1",
+        "is-plain-obj": "^1.1.0",
+        "kind-of": "^6.0.3"
+      }
+    },
+    "modify-values": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
+      "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==",
+      "dev": true
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "nerf-dart": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz",
+      "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==",
+      "dev": true
+    },
+    "node-emoji": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
+      "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.21"
+      }
+    },
+    "node-fetch": {
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+      "dev": true,
+      "requires": {
+        "whatwg-url": "^5.0.0"
+      }
+    },
+    "normalize-package-data": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+      "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^4.0.1",
+        "is-core-module": "^2.5.0",
+        "semver": "^7.3.4",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "normalize-url": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
+      "dev": true
+    },
+    "npm": {
+      "version": "8.15.0",
+      "resolved": "https://registry.npmjs.org/npm/-/npm-8.15.0.tgz",
+      "integrity": "sha512-sFXrMiO07eDWUb/e5ni2yNvtz2hePKqSyukUxYcQv0QHjyXCe+zKP7af/bISjcvsgRBWGyivk5V3KCZ0vg8J3Q==",
+      "dev": true,
+      "requires": {
+        "@isaacs/string-locale-compare": "^1.1.0",
+        "@npmcli/arborist": "^5.0.4",
+        "@npmcli/ci-detect": "^2.0.0",
+        "@npmcli/config": "^4.2.0",
+        "@npmcli/fs": "^2.1.0",
+        "@npmcli/map-workspaces": "^2.0.3",
+        "@npmcli/package-json": "^2.0.0",
+        "@npmcli/run-script": "^4.1.7",
+        "abbrev": "~1.1.1",
+        "archy": "~1.0.0",
+        "cacache": "^16.1.1",
+        "chalk": "^4.1.2",
+        "chownr": "^2.0.0",
+        "cli-columns": "^4.0.0",
+        "cli-table3": "^0.6.2",
+        "columnify": "^1.6.0",
+        "fastest-levenshtein": "^1.0.12",
+        "glob": "^8.0.1",
+        "graceful-fs": "^4.2.10",
+        "hosted-git-info": "^5.0.0",
+        "ini": "^3.0.0",
+        "init-package-json": "^3.0.2",
+        "is-cidr": "^4.0.2",
+        "json-parse-even-better-errors": "^2.3.1",
+        "libnpmaccess": "^6.0.2",
+        "libnpmdiff": "^4.0.2",
+        "libnpmexec": "^4.0.2",
+        "libnpmfund": "^3.0.1",
+        "libnpmhook": "^8.0.2",
+        "libnpmorg": "^4.0.2",
+        "libnpmpack": "^4.0.2",
+        "libnpmpublish": "^6.0.2",
+        "libnpmsearch": "^5.0.2",
+        "libnpmteam": "^4.0.2",
+        "libnpmversion": "^3.0.1",
+        "make-fetch-happen": "^10.2.0",
+        "minipass": "^3.1.6",
+        "minipass-pipeline": "^1.2.4",
+        "mkdirp": "^1.0.4",
+        "mkdirp-infer-owner": "^2.0.0",
+        "ms": "^2.1.2",
+        "node-gyp": "^9.0.0",
+        "nopt": "^5.0.0",
+        "npm-audit-report": "^3.0.0",
+        "npm-install-checks": "^5.0.0",
+        "npm-package-arg": "^9.1.0",
+        "npm-pick-manifest": "^7.0.1",
+        "npm-profile": "^6.2.0",
+        "npm-registry-fetch": "^13.3.0",
+        "npm-user-validate": "^1.0.1",
+        "npmlog": "^6.0.2",
+        "opener": "^1.5.2",
+        "p-map": "^4.0.0",
+        "pacote": "^13.6.1",
+        "parse-conflict-json": "^2.0.2",
+        "proc-log": "^2.0.1",
+        "qrcode-terminal": "^0.12.0",
+        "read": "~1.0.7",
+        "read-package-json": "^5.0.1",
+        "read-package-json-fast": "^2.0.3",
+        "readdir-scoped-modules": "^1.1.0",
+        "rimraf": "^3.0.2",
+        "semver": "^7.3.7",
+        "ssri": "^9.0.1",
+        "tar": "^6.1.11",
+        "text-table": "~0.2.0",
+        "tiny-relative-date": "^1.3.0",
+        "treeverse": "^2.0.0",
+        "validate-npm-package-name": "^4.0.0",
+        "which": "^2.0.2",
+        "write-file-atomic": "^4.0.1"
+      },
+      "dependencies": {
+        "@colors/colors": {
+          "version": "1.5.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "@gar/promisify": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true
+        },
+        "@isaacs/string-locale-compare": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "@npmcli/arborist": {
+          "version": "5.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@isaacs/string-locale-compare": "^1.1.0",
+            "@npmcli/installed-package-contents": "^1.0.7",
+            "@npmcli/map-workspaces": "^2.0.3",
+            "@npmcli/metavuln-calculator": "^3.0.1",
+            "@npmcli/move-file": "^2.0.0",
+            "@npmcli/name-from-folder": "^1.0.1",
+            "@npmcli/node-gyp": "^2.0.0",
+            "@npmcli/package-json": "^2.0.0",
+            "@npmcli/run-script": "^4.1.3",
+            "bin-links": "^3.0.0",
+            "cacache": "^16.0.6",
+            "common-ancestor-path": "^1.0.1",
+            "json-parse-even-better-errors": "^2.3.1",
+            "json-stringify-nice": "^1.1.4",
+            "mkdirp": "^1.0.4",
+            "mkdirp-infer-owner": "^2.0.0",
+            "nopt": "^5.0.0",
+            "npm-install-checks": "^5.0.0",
+            "npm-package-arg": "^9.0.0",
+            "npm-pick-manifest": "^7.0.0",
+            "npm-registry-fetch": "^13.0.0",
+            "npmlog": "^6.0.2",
+            "pacote": "^13.6.1",
+            "parse-conflict-json": "^2.0.1",
+            "proc-log": "^2.0.0",
+            "promise-all-reject-late": "^1.0.0",
+            "promise-call-limit": "^1.0.1",
+            "read-package-json-fast": "^2.0.2",
+            "readdir-scoped-modules": "^1.1.0",
+            "rimraf": "^3.0.2",
+            "semver": "^7.3.7",
+            "ssri": "^9.0.0",
+            "treeverse": "^2.0.0",
+            "walk-up-path": "^1.0.0"
+          }
+        },
+        "@npmcli/ci-detect": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "@npmcli/config": {
+          "version": "4.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/map-workspaces": "^2.0.2",
+            "ini": "^3.0.0",
+            "mkdirp-infer-owner": "^2.0.0",
+            "nopt": "^5.0.0",
+            "proc-log": "^2.0.0",
+            "read-package-json-fast": "^2.0.3",
+            "semver": "^7.3.5",
+            "walk-up-path": "^1.0.0"
+          }
+        },
+        "@npmcli/disparity-colors": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.3.0"
+          }
+        },
+        "@npmcli/fs": {
+          "version": "2.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@gar/promisify": "^1.1.3",
+            "semver": "^7.3.5"
+          }
+        },
+        "@npmcli/git": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/promise-spawn": "^3.0.0",
+            "lru-cache": "^7.4.4",
+            "mkdirp": "^1.0.4",
+            "npm-pick-manifest": "^7.0.0",
+            "proc-log": "^2.0.0",
+            "promise-inflight": "^1.0.1",
+            "promise-retry": "^2.0.1",
+            "semver": "^7.3.5",
+            "which": "^2.0.2"
+          }
+        },
+        "@npmcli/installed-package-contents": {
+          "version": "1.0.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-bundled": "^1.1.1",
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "@npmcli/map-workspaces": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/name-from-folder": "^1.0.1",
+            "glob": "^8.0.1",
+            "minimatch": "^5.0.1",
+            "read-package-json-fast": "^2.0.3"
+          }
+        },
+        "@npmcli/metavuln-calculator": {
+          "version": "3.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "cacache": "^16.0.0",
+            "json-parse-even-better-errors": "^2.3.1",
+            "pacote": "^13.0.3",
+            "semver": "^7.3.5"
+          }
+        },
+        "@npmcli/move-file": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mkdirp": "^1.0.4",
+            "rimraf": "^3.0.2"
+          }
+        },
+        "@npmcli/name-from-folder": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "@npmcli/node-gyp": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "@npmcli/package-json": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "json-parse-even-better-errors": "^2.3.1"
+          }
+        },
+        "@npmcli/promise-spawn": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "infer-owner": "^1.0.4"
+          }
+        },
+        "@npmcli/run-script": {
+          "version": "4.1.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/node-gyp": "^2.0.0",
+            "@npmcli/promise-spawn": "^3.0.0",
+            "node-gyp": "^9.0.0",
+            "read-package-json-fast": "^2.0.3",
+            "which": "^2.0.2"
+          }
+        },
+        "@tootallnate/once": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "abbrev": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "agent-base": {
+          "version": "6.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "debug": "4"
+          }
+        },
+        "agentkeepalive": {
+          "version": "4.2.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "debug": "^4.1.0",
+            "depd": "^1.1.2",
+            "humanize-ms": "^1.2.1"
+          }
+        },
+        "aggregate-error": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "clean-stack": "^2.0.0",
+            "indent-string": "^4.0.0"
+          }
+        },
+        "ansi-regex": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "4.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "aproba": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "archy": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "are-we-there-yet": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^3.6.0"
+          }
+        },
+        "asap": {
+          "version": "2.0.6",
+          "bundled": true,
+          "dev": true
+        },
+        "balanced-match": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "bin-links": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "cmd-shim": "^5.0.0",
+            "mkdirp-infer-owner": "^2.0.0",
+            "npm-normalize-package-bin": "^1.0.0",
+            "read-cmd-shim": "^3.0.0",
+            "rimraf": "^3.0.0",
+            "write-file-atomic": "^4.0.0"
+          }
+        },
+        "binary-extensions": {
+          "version": "2.2.0",
+          "bundled": true,
+          "dev": true
+        },
+        "brace-expansion": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0"
+          }
+        },
+        "builtins": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "semver": "^7.0.0"
+          }
+        },
+        "cacache": {
+          "version": "16.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/fs": "^2.1.0",
+            "@npmcli/move-file": "^2.0.0",
+            "chownr": "^2.0.0",
+            "fs-minipass": "^2.1.0",
+            "glob": "^8.0.1",
+            "infer-owner": "^1.0.4",
+            "lru-cache": "^7.7.1",
+            "minipass": "^3.1.6",
+            "minipass-collect": "^1.0.2",
+            "minipass-flush": "^1.0.5",
+            "minipass-pipeline": "^1.2.4",
+            "mkdirp": "^1.0.4",
+            "p-map": "^4.0.0",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^3.0.2",
+            "ssri": "^9.0.0",
+            "tar": "^6.1.11",
+            "unique-filename": "^1.1.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "chownr": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "cidr-regex": {
+          "version": "3.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ip-regex": "^4.1.0"
+          }
+        },
+        "clean-stack": {
+          "version": "2.2.0",
+          "bundled": true,
+          "dev": true
+        },
+        "cli-columns": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "string-width": "^4.2.3",
+            "strip-ansi": "^6.0.1"
+          }
+        },
+        "cli-table3": {
+          "version": "0.6.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@colors/colors": "1.5.0",
+            "string-width": "^4.2.0"
+          }
+        },
+        "clone": {
+          "version": "1.0.4",
+          "bundled": true,
+          "dev": true
+        },
+        "cmd-shim": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mkdirp-infer-owner": "^2.0.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "bundled": true,
+          "dev": true
+        },
+        "color-support": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true
+        },
+        "columnify": {
+          "version": "1.6.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "strip-ansi": "^6.0.1",
+            "wcwidth": "^1.0.0"
+          }
+        },
+        "common-ancestor-path": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "debug": {
+          "version": "4.3.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.1.2",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "debuglog": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "defaults": {
+          "version": "1.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "clone": "^1.0.2"
+          }
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "depd": {
+          "version": "1.1.2",
+          "bundled": true,
+          "dev": true
+        },
+        "dezalgo": {
+          "version": "1.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "asap": "^2.0.0",
+            "wrappy": "1"
+          }
+        },
+        "diff": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "encoding": {
+          "version": "0.1.13",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "iconv-lite": "^0.6.2"
+          }
+        },
+        "env-paths": {
+          "version": "2.2.1",
+          "bundled": true,
+          "dev": true
+        },
+        "err-code": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "fastest-levenshtein": {
+          "version": "1.0.12",
+          "bundled": true,
+          "dev": true
+        },
+        "fs-minipass": {
+          "version": "2.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "function-bind": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "gauge": {
+          "version": "4.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aproba": "^1.0.3 || ^2.0.0",
+            "color-support": "^1.1.3",
+            "console-control-strings": "^1.1.0",
+            "has-unicode": "^2.0.1",
+            "signal-exit": "^3.0.7",
+            "string-width": "^4.2.3",
+            "strip-ansi": "^6.0.1",
+            "wide-align": "^1.1.5"
+          }
+        },
+        "glob": {
+          "version": "8.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^5.0.1",
+            "once": "^1.3.0"
+          }
+        },
+        "graceful-fs": {
+          "version": "4.2.10",
+          "bundled": true,
+          "dev": true
+        },
+        "has": {
+          "version": "1.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "function-bind": "^1.1.1"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "hosted-git-info": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "lru-cache": "^7.5.1"
+          }
+        },
+        "http-cache-semantics": {
+          "version": "4.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "http-proxy-agent": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@tootallnate/once": "2",
+            "agent-base": "6",
+            "debug": "4"
+          }
+        },
+        "https-proxy-agent": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "agent-base": "6",
+            "debug": "4"
+          }
+        },
+        "humanize-ms": {
+          "version": "1.2.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ms": "^2.0.0"
+          }
+        },
+        "iconv-lite": {
+          "version": "0.6.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3.0.0"
+          }
+        },
+        "ignore-walk": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minimatch": "^5.0.1"
+          }
+        },
+        "imurmurhash": {
+          "version": "0.1.4",
+          "bundled": true,
+          "dev": true
+        },
+        "indent-string": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "infer-owner": {
+          "version": "1.0.4",
+          "bundled": true,
+          "dev": true
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.4",
+          "bundled": true,
+          "dev": true
+        },
+        "ini": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "init-package-json": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-package-arg": "^9.0.1",
+            "promzard": "^0.3.0",
+            "read": "^1.0.7",
+            "read-package-json": "^5.0.0",
+            "semver": "^7.3.5",
+            "validate-npm-package-license": "^3.0.4",
+            "validate-npm-package-name": "^4.0.0"
+          }
+        },
+        "ip": {
+          "version": "1.1.8",
+          "bundled": true,
+          "dev": true
+        },
+        "ip-regex": {
+          "version": "4.3.0",
+          "bundled": true,
+          "dev": true
+        },
+        "is-cidr": {
+          "version": "4.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "cidr-regex": "^3.1.1"
+          }
+        },
+        "is-core-module": {
+          "version": "2.9.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "has": "^1.0.3"
+          }
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "is-lambda": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "isexe": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "json-parse-even-better-errors": {
+          "version": "2.3.1",
+          "bundled": true,
+          "dev": true
+        },
+        "json-stringify-nice": {
+          "version": "1.1.4",
+          "bundled": true,
+          "dev": true
+        },
+        "jsonparse": {
+          "version": "1.3.1",
+          "bundled": true,
+          "dev": true
+        },
+        "just-diff": {
+          "version": "5.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "just-diff-apply": {
+          "version": "5.3.1",
+          "bundled": true,
+          "dev": true
+        },
+        "libnpmaccess": {
+          "version": "6.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aproba": "^2.0.0",
+            "minipass": "^3.1.1",
+            "npm-package-arg": "^9.0.1",
+            "npm-registry-fetch": "^13.0.0"
+          }
+        },
+        "libnpmdiff": {
+          "version": "4.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/disparity-colors": "^2.0.0",
+            "@npmcli/installed-package-contents": "^1.0.7",
+            "binary-extensions": "^2.2.0",
+            "diff": "^5.0.0",
+            "minimatch": "^5.0.1",
+            "npm-package-arg": "^9.0.1",
+            "pacote": "^13.6.1",
+            "tar": "^6.1.0"
+          }
+        },
+        "libnpmexec": {
+          "version": "4.0.8",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/arborist": "^5.0.0",
+            "@npmcli/ci-detect": "^2.0.0",
+            "@npmcli/run-script": "^4.1.3",
+            "chalk": "^4.1.0",
+            "mkdirp-infer-owner": "^2.0.0",
+            "npm-package-arg": "^9.0.1",
+            "npmlog": "^6.0.2",
+            "pacote": "^13.6.1",
+            "proc-log": "^2.0.0",
+            "read": "^1.0.7",
+            "read-package-json-fast": "^2.0.2",
+            "walk-up-path": "^1.0.0"
+          }
+        },
+        "libnpmfund": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/arborist": "^5.0.0"
+          }
+        },
+        "libnpmhook": {
+          "version": "8.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aproba": "^2.0.0",
+            "npm-registry-fetch": "^13.0.0"
+          }
+        },
+        "libnpmorg": {
+          "version": "4.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aproba": "^2.0.0",
+            "npm-registry-fetch": "^13.0.0"
+          }
+        },
+        "libnpmpack": {
+          "version": "4.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/run-script": "^4.1.3",
+            "npm-package-arg": "^9.0.1",
+            "pacote": "^13.6.1"
+          }
+        },
+        "libnpmpublish": {
+          "version": "6.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "normalize-package-data": "^4.0.0",
+            "npm-package-arg": "^9.0.1",
+            "npm-registry-fetch": "^13.0.0",
+            "semver": "^7.3.7",
+            "ssri": "^9.0.0"
+          }
+        },
+        "libnpmsearch": {
+          "version": "5.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-registry-fetch": "^13.0.0"
+          }
+        },
+        "libnpmteam": {
+          "version": "4.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aproba": "^2.0.0",
+            "npm-registry-fetch": "^13.0.0"
+          }
+        },
+        "libnpmversion": {
+          "version": "3.0.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/git": "^3.0.0",
+            "@npmcli/run-script": "^4.1.3",
+            "json-parse-even-better-errors": "^2.3.1",
+            "proc-log": "^2.0.0",
+            "semver": "^7.3.7"
+          }
+        },
+        "lru-cache": {
+          "version": "7.12.0",
+          "bundled": true,
+          "dev": true
+        },
+        "make-fetch-happen": {
+          "version": "10.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "agentkeepalive": "^4.2.1",
+            "cacache": "^16.1.0",
+            "http-cache-semantics": "^4.1.0",
+            "http-proxy-agent": "^5.0.0",
+            "https-proxy-agent": "^5.0.0",
+            "is-lambda": "^1.0.1",
+            "lru-cache": "^7.7.1",
+            "minipass": "^3.1.6",
+            "minipass-collect": "^1.0.2",
+            "minipass-fetch": "^2.0.3",
+            "minipass-flush": "^1.0.5",
+            "minipass-pipeline": "^1.2.4",
+            "negotiator": "^0.6.3",
+            "promise-retry": "^2.0.1",
+            "socks-proxy-agent": "^7.0.0",
+            "ssri": "^9.0.0"
+          }
+        },
+        "minimatch": {
+          "version": "5.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^2.0.1"
+          }
+        },
+        "minipass": {
+          "version": "3.3.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        },
+        "minipass-collect": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          }
+        },
+        "minipass-fetch": {
+          "version": "2.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "encoding": "^0.1.13",
+            "minipass": "^3.1.6",
+            "minipass-sized": "^1.0.3",
+            "minizlib": "^2.1.2"
+          }
+        },
+        "minipass-flush": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          }
+        },
+        "minipass-json-stream": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "jsonparse": "^1.3.1",
+            "minipass": "^3.0.0"
+          }
+        },
+        "minipass-pipeline": {
+          "version": "1.2.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          }
+        },
+        "minipass-sized": {
+          "version": "1.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          }
+        },
+        "minizlib": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0",
+            "yallist": "^4.0.0"
+          }
+        },
+        "mkdirp": {
+          "version": "1.0.4",
+          "bundled": true,
+          "dev": true
+        },
+        "mkdirp-infer-owner": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "chownr": "^2.0.0",
+            "infer-owner": "^1.0.4",
+            "mkdirp": "^1.0.3"
+          }
+        },
+        "ms": {
+          "version": "2.1.3",
+          "bundled": true,
+          "dev": true
+        },
+        "mute-stream": {
+          "version": "0.0.8",
+          "bundled": true,
+          "dev": true
+        },
+        "negotiator": {
+          "version": "0.6.3",
+          "bundled": true,
+          "dev": true
+        },
+        "node-gyp": {
+          "version": "9.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "env-paths": "^2.2.0",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.2.6",
+            "make-fetch-happen": "^10.0.3",
+            "nopt": "^5.0.0",
+            "npmlog": "^6.0.0",
+            "rimraf": "^3.0.2",
+            "semver": "^7.3.5",
+            "tar": "^6.1.2",
+            "which": "^2.0.2"
+          },
+          "dependencies": {
+            "brace-expansion": {
+              "version": "1.1.11",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "glob": {
+              "version": "7.2.3",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.1.1",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "nopt": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "abbrev": "1"
+          }
+        },
+        "normalize-package-data": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hosted-git-info": "^5.0.0",
+            "is-core-module": "^2.8.1",
+            "semver": "^7.3.5",
+            "validate-npm-package-license": "^3.0.4"
+          }
+        },
+        "npm-audit-report": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "chalk": "^4.0.0"
+          }
+        },
+        "npm-bundled": {
+          "version": "1.1.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "npm-install-checks": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "semver": "^7.1.1"
+          }
+        },
+        "npm-normalize-package-bin": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "npm-package-arg": {
+          "version": "9.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "hosted-git-info": "^5.0.0",
+            "proc-log": "^2.0.1",
+            "semver": "^7.3.5",
+            "validate-npm-package-name": "^4.0.0"
+          }
+        },
+        "npm-packlist": {
+          "version": "5.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "glob": "^8.0.1",
+            "ignore-walk": "^5.0.1",
+            "npm-bundled": "^1.1.2",
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "npm-pick-manifest": {
+          "version": "7.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-install-checks": "^5.0.0",
+            "npm-normalize-package-bin": "^1.0.1",
+            "npm-package-arg": "^9.0.0",
+            "semver": "^7.3.5"
+          }
+        },
+        "npm-profile": {
+          "version": "6.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "npm-registry-fetch": "^13.0.1",
+            "proc-log": "^2.0.0"
+          }
+        },
+        "npm-registry-fetch": {
+          "version": "13.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "make-fetch-happen": "^10.0.6",
+            "minipass": "^3.1.6",
+            "minipass-fetch": "^2.0.3",
+            "minipass-json-stream": "^1.0.1",
+            "minizlib": "^2.1.2",
+            "npm-package-arg": "^9.0.1",
+            "proc-log": "^2.0.0"
+          }
+        },
+        "npm-user-validate": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "npmlog": {
+          "version": "6.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "are-we-there-yet": "^3.0.0",
+            "console-control-strings": "^1.1.0",
+            "gauge": "^4.0.3",
+            "set-blocking": "^2.0.0"
+          }
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "opener": {
+          "version": "1.5.2",
+          "bundled": true,
+          "dev": true
+        },
+        "p-map": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "aggregate-error": "^3.0.0"
+          }
+        },
+        "pacote": {
+          "version": "13.6.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@npmcli/git": "^3.0.0",
+            "@npmcli/installed-package-contents": "^1.0.7",
+            "@npmcli/promise-spawn": "^3.0.0",
+            "@npmcli/run-script": "^4.1.0",
+            "cacache": "^16.0.0",
+            "chownr": "^2.0.0",
+            "fs-minipass": "^2.1.0",
+            "infer-owner": "^1.0.4",
+            "minipass": "^3.1.6",
+            "mkdirp": "^1.0.4",
+            "npm-package-arg": "^9.0.0",
+            "npm-packlist": "^5.1.0",
+            "npm-pick-manifest": "^7.0.0",
+            "npm-registry-fetch": "^13.0.1",
+            "proc-log": "^2.0.0",
+            "promise-retry": "^2.0.1",
+            "read-package-json": "^5.0.0",
+            "read-package-json-fast": "^2.0.3",
+            "rimraf": "^3.0.2",
+            "ssri": "^9.0.0",
+            "tar": "^6.1.11"
+          }
+        },
+        "parse-conflict-json": {
+          "version": "2.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "json-parse-even-better-errors": "^2.3.1",
+            "just-diff": "^5.0.1",
+            "just-diff-apply": "^5.2.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "proc-log": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "promise-all-reject-late": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "promise-call-limit": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "promise-inflight": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "promise-retry": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "err-code": "^2.0.2",
+            "retry": "^0.12.0"
+          }
+        },
+        "promzard": {
+          "version": "0.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "read": "1"
+          }
+        },
+        "qrcode-terminal": {
+          "version": "0.12.0",
+          "bundled": true,
+          "dev": true
+        },
+        "read": {
+          "version": "1.0.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mute-stream": "~0.0.4"
+          }
+        },
+        "read-cmd-shim": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "read-package-json": {
+          "version": "5.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "glob": "^8.0.1",
+            "json-parse-even-better-errors": "^2.3.1",
+            "normalize-package-data": "^4.0.0",
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "read-package-json-fast": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "json-parse-even-better-errors": "^2.3.0",
+            "npm-normalize-package-bin": "^1.0.1"
+          }
+        },
+        "readable-stream": {
+          "version": "3.6.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        },
+        "readdir-scoped-modules": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "debuglog": "^1.0.1",
+            "dezalgo": "^1.0.0",
+            "graceful-fs": "^4.1.2",
+            "once": "^1.3.0"
+          }
+        },
+        "retry": {
+          "version": "0.12.0",
+          "bundled": true,
+          "dev": true
+        },
+        "rimraf": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          },
+          "dependencies": {
+            "brace-expansion": {
+              "version": "1.1.11",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+              }
+            },
+            "glob": {
+              "version": "7.2.3",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.1.1",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+              }
+            },
+            "minimatch": {
+              "version": "3.1.2",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "brace-expansion": "^1.1.7"
+              }
+            }
+          }
+        },
+        "safe-buffer": {
+          "version": "5.2.1",
+          "bundled": true,
+          "dev": true
+        },
+        "safer-buffer": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "semver": {
+          "version": "7.3.7",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "lru-cache": "^6.0.0"
+          },
+          "dependencies": {
+            "lru-cache": {
+              "version": "6.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            }
+          }
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "signal-exit": {
+          "version": "3.0.7",
+          "bundled": true,
+          "dev": true
+        },
+        "smart-buffer": {
+          "version": "4.2.0",
+          "bundled": true,
+          "dev": true
+        },
+        "socks": {
+          "version": "2.6.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ip": "^1.1.5",
+            "smart-buffer": "^4.2.0"
+          }
+        },
+        "socks-proxy-agent": {
+          "version": "7.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "agent-base": "^6.0.2",
+            "debug": "^4.3.3",
+            "socks": "^2.6.2"
+          }
+        },
+        "spdx-correct": {
+          "version": "3.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "spdx-expression-parse": "^3.0.0",
+            "spdx-license-ids": "^3.0.0"
+          }
+        },
+        "spdx-exceptions": {
+          "version": "2.3.0",
+          "bundled": true,
+          "dev": true
+        },
+        "spdx-expression-parse": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "spdx-exceptions": "^2.1.0",
+            "spdx-license-ids": "^3.0.0"
+          }
+        },
+        "spdx-license-ids": {
+          "version": "3.0.11",
+          "bundled": true,
+          "dev": true
+        },
+        "ssri": {
+          "version": "9.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minipass": "^3.1.1"
+          }
+        },
+        "string-width": {
+          "version": "4.2.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.3.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.2.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.1"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "tar": {
+          "version": "6.1.11",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "chownr": "^2.0.0",
+            "fs-minipass": "^2.0.0",
+            "minipass": "^3.0.0",
+            "minizlib": "^2.1.1",
+            "mkdirp": "^1.0.3",
+            "yallist": "^4.0.0"
+          }
+        },
+        "text-table": {
+          "version": "0.2.0",
+          "bundled": true,
+          "dev": true
+        },
+        "tiny-relative-date": {
+          "version": "1.3.0",
+          "bundled": true,
+          "dev": true
+        },
+        "treeverse": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "unique-filename": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "unique-slug": "^2.0.0"
+          }
+        },
+        "unique-slug": {
+          "version": "2.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "imurmurhash": "^0.1.4"
+          }
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "validate-npm-package-license": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "spdx-correct": "^3.0.0",
+            "spdx-expression-parse": "^3.0.0"
+          }
+        },
+        "validate-npm-package-name": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "builtins": "^5.0.0"
+          }
+        },
+        "walk-up-path": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "wcwidth": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "defaults": "^1.0.3"
+          }
+        },
+        "which": {
+          "version": "2.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        },
+        "wide-align": {
+          "version": "1.1.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "string-width": "^1.0.2 || 2 || 3 || 4"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "write-file-atomic": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "imurmurhash": "^0.1.4",
+            "signal-exit": "^3.0.7"
+          }
+        },
+        "yallist": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        }
+      }
+    },
+    "npm-run-path": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.0.0"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "p-each-series": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
+      "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
+      "dev": true
+    },
+    "p-filter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz",
+      "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==",
+      "dev": true,
+      "requires": {
+        "p-map": "^2.0.0"
+      }
+    },
+    "p-is-promise": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz",
+      "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==",
+      "dev": true
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-map": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+      "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+      "dev": true
+    },
+    "p-reduce": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz",
+      "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==",
+      "dev": true
+    },
+    "p-retry": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+      "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+      "dev": true,
+      "requires": {
+        "@types/retry": "0.12.0",
+        "retry": "^0.13.1"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse-json": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
+      }
+    },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "dev": true
+    },
+    "path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true
+    },
+    "picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true
+    },
+    "pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+      "dev": true
+    },
+    "pkg-conf": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
+      "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==",
+      "dev": true,
+      "requires": {
+        "find-up": "^2.0.0",
+        "load-json-file": "^4.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+          "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^2.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+          "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^2.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+          "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+          "dev": true,
+          "requires": {
+            "p-try": "^1.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+          "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^1.1.0"
+          }
+        },
+        "p-try": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+          "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+          "dev": true
+        },
+        "path-exists": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+          "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+          "dev": true
+        }
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "q": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+      "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+      "dev": true
+    },
+    "queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true
+    },
+    "quick-lru": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+      "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+      "dev": true
+    },
+    "rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      }
+    },
+    "read-pkg": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+      "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+      "dev": true,
+      "requires": {
+        "@types/normalize-package-data": "^2.4.0",
+        "normalize-package-data": "^2.5.0",
+        "parse-json": "^5.0.0",
+        "type-fest": "^0.6.0"
+      },
+      "dependencies": {
+        "hosted-git-info": {
+          "version": "2.8.9",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+          "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+          "dev": true
+        },
+        "normalize-package-data": {
+          "version": "2.5.0",
+          "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+          "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+          "dev": true,
+          "requires": {
+            "hosted-git-info": "^2.1.4",
+            "resolve": "^1.10.0",
+            "semver": "2 || 3 || 4 || 5",
+            "validate-npm-package-license": "^3.0.1"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
+        "type-fest": {
+          "version": "0.6.0",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+          "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+          "dev": true
+        }
+      }
+    },
+    "read-pkg-up": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+      "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+      "dev": true,
+      "requires": {
+        "find-up": "^4.1.0",
+        "read-pkg": "^5.2.0",
+        "type-fest": "^0.8.1"
+      },
+      "dependencies": {
+        "type-fest": {
+          "version": "0.8.1",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+          "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+          "dev": true
+        }
+      }
+    },
+    "readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
+    "redent": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+      "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+      "dev": true,
+      "requires": {
+        "indent-string": "^4.0.0",
+        "strip-indent": "^3.0.0"
+      }
+    },
+    "redeyed": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
+      "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==",
+      "dev": true,
+      "requires": {
+        "esprima": "~4.0.0"
+      }
+    },
+    "registry-auth-token": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz",
+      "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==",
+      "dev": true,
+      "requires": {
+        "rc": "1.2.8"
+      }
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "dev": true
+    },
+    "resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "dev": true,
+      "requires": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true
+    },
+    "retry": {
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+      "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+      "dev": true
+    },
+    "reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true
+    },
+    "rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "requires": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true
+    },
+    "semantic-release": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.3.tgz",
+      "integrity": "sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==",
+      "dev": true,
+      "requires": {
+        "@semantic-release/commit-analyzer": "^9.0.2",
+        "@semantic-release/error": "^3.0.0",
+        "@semantic-release/github": "^8.0.0",
+        "@semantic-release/npm": "^9.0.0",
+        "@semantic-release/release-notes-generator": "^10.0.0",
+        "aggregate-error": "^3.0.0",
+        "cosmiconfig": "^7.0.0",
+        "debug": "^4.0.0",
+        "env-ci": "^5.0.0",
+        "execa": "^5.0.0",
+        "figures": "^3.0.0",
+        "find-versions": "^4.0.0",
+        "get-stream": "^6.0.0",
+        "git-log-parser": "^1.2.0",
+        "hook-std": "^2.0.0",
+        "hosted-git-info": "^4.0.0",
+        "lodash": "^4.17.21",
+        "marked": "^4.0.10",
+        "marked-terminal": "^5.0.0",
+        "micromatch": "^4.0.2",
+        "p-each-series": "^2.1.0",
+        "p-reduce": "^2.0.0",
+        "read-pkg-up": "^7.0.0",
+        "resolve-from": "^5.0.0",
+        "semver": "^7.3.2",
+        "semver-diff": "^3.1.1",
+        "signale": "^1.2.1",
+        "yargs": "^16.2.0"
+      }
+    },
+    "semver": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+      "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+      "dev": true,
+      "requires": {
+        "lru-cache": "^6.0.0"
+      }
+    },
+    "semver-diff": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+      "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+      "dev": true,
+      "requires": {
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "semver-regex": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz",
+      "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==",
+      "dev": true
+    },
+    "shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^3.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "dev": true
+    },
+    "signale": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz",
+      "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.2",
+        "figures": "^2.0.0",
+        "pkg-conf": "^2.1.0"
+      },
+      "dependencies": {
+        "figures": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+          "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        }
+      }
+    },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true
+    },
+    "spawn-error-forwarder": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz",
+      "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==",
+      "dev": true
+    },
+    "spdx-correct": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+      "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.11",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+      "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
+      "dev": true
+    },
+    "split": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
+      "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+      "dev": true,
+      "requires": {
+        "through": "2"
+      }
+    },
+    "split2": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
+      "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^3.0.0"
+      }
+    },
+    "stream-combiner2": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+      "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==",
+      "dev": true,
+      "requires": {
+        "duplexer2": "~0.1.0",
+        "readable-stream": "^2.0.2"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dev": true,
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      }
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^5.0.1"
+      }
+    },
+    "strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true
+    },
+    "strip-final-newline": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+      "dev": true
+    },
+    "strip-indent": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+      "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+      "dev": true,
+      "requires": {
+        "min-indent": "^1.0.0"
+      }
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+      "dev": true
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "supports-hyperlinks": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
+      "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^4.0.0",
+        "supports-color": "^7.0.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true
+    },
+    "temp-dir": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
+      "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
+      "dev": true
+    },
+    "tempy": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz",
+      "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==",
+      "dev": true,
+      "requires": {
+        "del": "^6.0.0",
+        "is-stream": "^2.0.0",
+        "temp-dir": "^2.0.0",
+        "type-fest": "^0.16.0",
+        "unique-string": "^2.0.0"
+      },
+      "dependencies": {
+        "type-fest": {
+          "version": "0.16.0",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
+          "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
+          "dev": true
+        }
+      }
+    },
+    "text-extensions": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
+      "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==",
+      "dev": true
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+      "dev": true
+    },
+    "through2": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+      "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "3"
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "dev": true
+    },
+    "traverse": {
+      "version": "0.6.6",
+      "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
+      "integrity": "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==",
+      "dev": true
+    },
+    "trim-newlines": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+      "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+      "dev": true
+    },
+    "type-fest": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
+      "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "3.16.3",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.3.tgz",
+      "integrity": "sha512-uVbFqx9vvLhQg0iBaau9Z75AxWJ8tqM9AV890dIZCLApF4rTcyHwmAvLeEdYRs+BzYWu8Iw81F79ah0EfTXbaw==",
+      "dev": true,
+      "optional": true
+    },
+    "unique-string": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+      "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+      "dev": true,
+      "requires": {
+        "crypto-random-string": "^2.0.0"
+      }
+    },
+    "universal-user-agent": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
+      "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==",
+      "dev": true
+    },
+    "universalify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+      "dev": true
+    },
+    "url-join": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+      "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+      "dev": true
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "dev": true
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "dev": true
+    },
+    "whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "dev": true,
+      "requires": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+      "dev": true
+    },
+    "wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        }
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "dev": true
+    },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "dev": true
+    },
+    "y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true
+    },
+    "yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "yaml": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+      "dev": true
+    },
+    "yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dev": true,
+      "requires": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      }
+    },
+    "yargs-parser": {
+      "version": "20.2.9",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+      "dev": true
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..37434d5
--- /dev/null
+++ b/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "perun-ga4gh-broker",
+  "private": true,
+  "devDependencies": {
+    "@semantic-release/changelog": "6.0.1",
+    "@semantic-release/git": "10.0.1",
+    "@semantic-release/exec": "6.0.3",
+    "semantic-release": "19.0.3"
+  }
+}
diff --git a/pom.xml b/pom.xml
index afebcd7..4544eee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,24 +4,32 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-    <groupId>org.example</groupId>
-    <artifactId>Perun-GA4GH</artifactId>
-    <version>1.0-SNAPSHOT</version>
-
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.4.0</version>
+        <version>2.7.2</version>
         <relativePath />
     </parent>
 
+    <groupId>cz.muni.ics</groupId>
+    <artifactId>Perun-GA4GH</artifactId>
+    <version>1.0.0</version>
+
+    <name>perun-ga4gh-broker</name>
+    <description>GA4GH broker</description>
+    <packaging>war</packaging>
+
     <properties>
-        <java.version>16</java.version>
-        <maven.compiler.source>16</maven.compiler.source>
-        <maven.compiler.target>16</maven.compiler.target>
+        <java.version>11</java.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
 
         <version.springfox>3.0.0</version.springfox>
         <version.swagger>3.0.0</version.swagger>
+        <version.apache-directory-api>2.1.0</version.apache-directory-api>
+        <version.nimbus-jose-jwt>9.23</version.nimbus-jose-jwt>
+        <version.guava>31.1-jre</version.guava>
+        <version.bouncy-castle>1.70</version.bouncy-castle>
     </properties>
 
     <dependencies>
@@ -30,17 +38,22 @@
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-oauth2-client</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
@@ -59,9 +72,39 @@
             <artifactId>springfox-swagger-ui</artifactId>
             <version>${version.swagger}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-all</artifactId>
+            <version>${version.apache-directory-api}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <version>${version.bouncy-castle}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>${version.bouncy-castle}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${version.guava}</version>
+        </dependency>
     </dependencies>
 
     <build>
+        <finalName>perun-ga4gh-broker</finalName>
         <plugins>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
@@ -78,4 +121,4 @@
         </plugins>
     </build>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..820b73b
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,17 @@
+{
+  "extends": [
+    "config:base",
+    ":automergeBranch",
+    ":automergeLinters",
+    ":automergeTesters",
+    ":enableVulnerabilityAlertsWithLabel(security)",
+    ":maintainLockFilesWeekly",
+    ":pinOnlyDevDependencies",
+    ":prNotPending",
+    ":rebaseStalePrs",
+    ":semanticCommits",
+    "npm:unpublishSafe"
+  ],
+  "stabilityDays": 3,
+  "transitiveRemediation": true
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/Application.java b/src/main/java/cz/muni/ics/ga4gh/Application.java
index 8627f5e..efc5f3c 100644
--- a/src/main/java/cz/muni/ics/ga4gh/Application.java
+++ b/src/main/java/cz/muni/ics/ga4gh/Application.java
@@ -2,9 +2,10 @@ package cz.muni.ics.ga4gh;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 
 @SpringBootApplication
-public class Application {
+public class Application extends SpringBootServletInitializer {
 
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
diff --git a/src/main/java/cz/muni/ics/ga4gh/ApplicationContext.java b/src/main/java/cz/muni/ics/ga4gh/ApplicationContext.java
new file mode 100644
index 0000000..13e6043
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/ApplicationContext.java
@@ -0,0 +1,44 @@
+package cz.muni.ics.ga4gh;
+
+import cz.muni.ics.ga4gh.config.BrokerConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.FileUrlResource;
+import org.springframework.core.io.Resource;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+import java.net.MalformedURLException;
+
+@Configuration
+public class ApplicationContext {
+
+    private final String pathToJwkFile;
+
+    public ApplicationContext(BrokerConfig config) {
+        this.pathToJwkFile = config.getPathToJwkFile();
+    }
+
+    @Bean
+    public Docket api() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .select()
+                .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public Resource jwks() throws MalformedURLException {
+        return new FileUrlResource(pathToJwkFile);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapter.java b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapter.java
new file mode 100644
index 0000000..7358f9a
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapter.java
@@ -0,0 +1,39 @@
+package cz.muni.ics.ga4gh.adapters;
+
+import cz.muni.ics.ga4gh.adapters.impl.PerunAdapterLdap;
+import cz.muni.ics.ga4gh.adapters.impl.PerunAdapterRpc;
+import cz.muni.ics.ga4gh.config.AdapterConfig;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Objects;
+
+@Getter
+@Setter
+public abstract class PerunAdapter implements PerunAdapterMethods {
+
+    private final String RPC = "rpc";
+
+    private PerunAdapterMethods adapterPrimary;
+    private PerunAdapterMethods adapterFallback;
+
+    private PerunAdapterMethodsRpc adapterRpc;
+    private PerunAdapterMethodsLdap adapterLdap;
+
+    private boolean callFallback;
+
+    public PerunAdapter(AdapterConfig config, PerunAdapterRpc adapterRpc, PerunAdapterLdap adapterLdap) {
+        if (config.getAdapterPrimary() != null && config.getAdapterPrimary().equalsIgnoreCase(RPC)) {
+            this.adapterPrimary = adapterRpc;
+            this.adapterFallback = adapterLdap;
+        } else {
+            this.adapterPrimary = adapterLdap;
+            this.adapterFallback = adapterRpc;
+        }
+
+        this.adapterRpc = adapterRpc;
+        this.adapterLdap = adapterLdap;
+
+        this.callFallback = Objects.requireNonNullElse(config.getCallFallback(), false);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethods.java b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethods.java
new file mode 100644
index 0000000..85485da
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethods.java
@@ -0,0 +1,23 @@
+package cz.muni.ics.ga4gh.adapters;
+
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+
+import java.util.List;
+import java.util.Set;
+
+public interface PerunAdapterMethods {
+
+    /**
+     * Fetch user based on his principal (extLogin and extSource) from Perun
+     *
+     * @return PerunUser with id of found user
+     */
+    Long getPreauthenticatedUserId(String extLogin, String extSourceName);
+
+    boolean isUserInGroup(Long userId, Long groupId);
+
+    List<Affiliation> getGroupAffiliations(Long userId, String groupAffiliationsAttr);
+
+    Set<Long> getUserIdsByAttributeValue(AttributeMapping attrName, String attrValue);
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsLdap.java b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsLdap.java
new file mode 100644
index 0000000..70c67cd
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsLdap.java
@@ -0,0 +1,4 @@
+package cz.muni.ics.ga4gh.adapters;
+
+public interface PerunAdapterMethodsLdap {
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsRpc.java b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsRpc.java
new file mode 100644
index 0000000..f2c4d5e
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/PerunAdapterMethodsRpc.java
@@ -0,0 +1,12 @@
+package cz.muni.ics.ga4gh.adapters;
+
+import cz.muni.ics.ga4gh.model.Affiliation;
+
+import java.util.List;
+
+public interface PerunAdapterMethodsRpc {
+
+    String getUserAttributeCreatedAt(Long userId, String attrName);
+
+    List<Affiliation> getUserExtSourcesAffiliations(Long userId, String affiliationsAttr, String orgUrlAttr);
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterImpl.java b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterImpl.java
new file mode 100644
index 0000000..fd5553b
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterImpl.java
@@ -0,0 +1,72 @@
+package cz.muni.ics.ga4gh.adapters.impl;
+
+import cz.muni.ics.ga4gh.adapters.PerunAdapter;
+import cz.muni.ics.ga4gh.config.AdapterConfig;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+@Component
+public class PerunAdapterImpl extends PerunAdapter {
+
+    @Autowired
+    public PerunAdapterImpl(AdapterConfig config, PerunAdapterRpc adapterRpc, PerunAdapterLdap adapterLdap) {
+        super(config, adapterRpc, adapterLdap);
+    }
+
+    @Override
+    public Long getPreauthenticatedUserId(String extLogin, String extSourceName) {
+        try {
+            return this.getAdapterPrimary().getPreauthenticatedUserId(extLogin, extSourceName);
+        } catch (UnsupportedOperationException e) {
+            if (this.isCallFallback()) {
+                return this.getAdapterFallback().getPreauthenticatedUserId(extLogin, extSourceName);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    public boolean isUserInGroup(Long userId, Long groupId) {
+        try {
+            return this.getAdapterPrimary().isUserInGroup(userId, groupId);
+        } catch (UnsupportedOperationException e) {
+            if (this.isCallFallback()) {
+                return this.getAdapterFallback().isUserInGroup(userId, groupId);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    public List<Affiliation> getGroupAffiliations(Long userId, String groupAffiliationsAttr) {
+        try {
+            return this.getAdapterPrimary().getGroupAffiliations(userId, groupAffiliationsAttr);
+        } catch (UnsupportedOperationException e) {
+            if (this.isCallFallback()) {
+                return this.getAdapterFallback().getGroupAffiliations(userId, groupAffiliationsAttr);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    public Set<Long> getUserIdsByAttributeValue(AttributeMapping attrName, String attrValue) {
+        try {
+            return this.getAdapterPrimary().getUserIdsByAttributeValue(attrName, attrValue);
+        } catch (UnsupportedOperationException e) {
+            if (this.isCallFallback()) {
+                return this.getAdapterFallback().getUserIdsByAttributeValue(attrName, attrValue);
+            } else {
+                throw e;
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterLdap.java b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterLdap.java
new file mode 100644
index 0000000..2c68d7e
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterLdap.java
@@ -0,0 +1,199 @@
+package cz.muni.ics.ga4gh.adapters.impl;
+
+import cz.muni.ics.ga4gh.adapters.PerunAdapterMethods;
+import cz.muni.ics.ga4gh.adapters.PerunAdapterMethodsLdap;
+import cz.muni.ics.ga4gh.config.AttributesConfig;
+import cz.muni.ics.ga4gh.connectors.PerunConnectorLdap;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.EntryMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.and;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.equal;
+import static org.apache.directory.ldap.client.api.search.FilterBuilder.or;
+
+@Component
+public class PerunAdapterLdap implements PerunAdapterMethods, PerunAdapterMethodsLdap {
+
+    public static final String OBJECT_CLASS = "objectClass";
+    public static final String OU_PEOPLE = "ou=People";
+
+    public static final String PERUN_USER_ID = "perunUserId";
+    public static final String MEMBER_OF = "memberOf";
+
+    public static final String PERUN_GROUP = "perunGroup";
+    public static final String PERUN_USER = "perunUser";
+    public static final String PERUN_GROUP_ID = "perunGroupId";
+    public static final String UNIQUE_MEMBER = "uniqueMember";
+
+    public static final String PERUN_VO_ID = "perunVoId";
+    public static final String EDU_PERSON_PRINCIPAL_NAMES = "eduPersonPrincipalNames";
+
+    private final PerunConnectorLdap connectorLdap;
+    private final Map<String, AttributeMapping> attributeMappings;
+
+    @Autowired
+    PerunAdapterLdap(PerunConnectorLdap connectorLdap, AttributesConfig attributesConfig) {
+        this.connectorLdap = connectorLdap;
+        this.attributeMappings = attributesConfig.getAttributeMappings();
+    }
+
+    @Override
+    public Long getPreauthenticatedUserId(String extLogin, String extSourceName) {
+        FilterBuilder filter = and(
+                equal(OBJECT_CLASS, PERUN_USER), equal(EDU_PERSON_PRINCIPAL_NAMES, extLogin)
+        );
+
+        return getPerunUserId(filter);
+    }
+
+    @Override
+    public boolean isUserInGroup(Long userId, Long groupId) {
+        String uniqueMemberValue = PERUN_USER_ID + '=' + userId + ',' + OU_PEOPLE + ',' + connectorLdap.getBaseDN();
+
+        FilterBuilder filter = and(
+                equal(OBJECT_CLASS, PERUN_GROUP),
+                equal(PERUN_GROUP_ID, String.valueOf(groupId)),
+                equal(UNIQUE_MEMBER, uniqueMemberValue)
+        );
+
+        EntryMapper<Long> mapper = e -> Long.parseLong(e.get(PERUN_GROUP_ID).getString());
+        String[] attributes = new String[] { PERUN_GROUP_ID };
+        List<Long> ids = connectorLdap.search(null, filter, SearchScope.SUBTREE, attributes, mapper);
+
+        return ids.stream().filter(groupId::equals).count() == 1L;
+    }
+
+    @Override
+    public List<Affiliation> getGroupAffiliations(Long userId, String groupAffiliationsAttr) {
+        Set<Long> userGroupIds = getGroupIdsWhereUserIsMember(userId, null);
+        if (userGroupIds.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        FilterBuilder[] groupIdFilters = new FilterBuilder[userGroupIds.size()];
+        int i = 0;
+
+        for (Long id: userGroupIds) {
+            groupIdFilters[i++] = equal(PERUN_GROUP_ID, String.valueOf(id));
+        }
+
+        AttributeMapping affiliationsMapping = attributeMappings.get(groupAffiliationsAttr);
+        FilterBuilder filterBuilder = and(equal(OBJECT_CLASS, PERUN_GROUP), or(groupIdFilters));
+        String[] attributes = new String[] { affiliationsMapping.getLdapName() };
+
+        EntryMapper<Set<Affiliation>> mapper = e -> {
+            Set<Affiliation> affiliations = new HashSet<>();
+            if (!checkHasAttributes(e, attributes)) {
+                return affiliations;
+            }
+
+            Attribute a = e.get(affiliationsMapping.getLdapName());
+            long linuxTime = System.currentTimeMillis() / 1000L;
+            a.iterator().forEachRemaining(v -> affiliations.add(new Affiliation(null, v.getString(), linuxTime)));
+
+            return affiliations;
+        };
+
+        List<Set<Affiliation>> affiliationSets = connectorLdap.search(null, filterBuilder, SearchScope.SUBTREE, attributes, mapper);
+
+        return affiliationSets.stream().flatMap(Set::stream).distinct().collect(Collectors.toList());
+    }
+
+    @Override
+    public Set<Long> getUserIdsByAttributeValue(AttributeMapping attrName, String attrValue) {
+        if (!StringUtils.hasText(attrName.getLdapName())) {
+            return new HashSet<>();
+        }
+
+        FilterBuilder filter = and(
+                equal(OBJECT_CLASS, PERUN_USER),
+                equal(attrName.getLdapName(), attrValue)
+        );
+
+        SearchScope scope = SearchScope.ONELEVEL;
+        String[] attributes = new String[]{PERUN_USER_ID};
+        EntryMapper<Long> mapper = e -> Long.parseLong(e.get(PERUN_USER_ID).getString());
+
+        List<Long> result = connectorLdap.search(OU_PEOPLE, filter, scope, attributes, mapper);
+
+        return Set.copyOf(result);
+    }
+
+    private Set<Long> getGroupIdsWhereUserIsMember(Long userId, Long voId) {
+        String dnPrefix = getDnPrefixForUserId(userId);
+        String[] attributes = new String[] { MEMBER_OF };
+
+        EntryMapper<Set<Long>> mapper = e -> {
+            Set<Long> ids = new HashSet<>();
+            if (checkHasAttributes(e, attributes)) {
+                Attribute a = e.get(MEMBER_OF);
+                a.iterator().forEachRemaining(id -> {
+                    String fullVal = id.getString();
+                    String[] parts = fullVal.split(",", 3);
+
+                    String groupId = parts[0];
+                    groupId = groupId.replace(PERUN_GROUP_ID + '=', "");
+
+                    String voIdStr = parts[1];
+                    voIdStr = voIdStr.replace(PERUN_VO_ID + '=', "");
+
+                    if (voId == null || voId.equals(Long.parseLong(voIdStr))) {
+                        ids.add(Long.parseLong(groupId));
+                    }
+                });
+            }
+
+            return ids;
+        };
+
+        Set<Long> res = connectorLdap.lookup(dnPrefix, attributes, mapper);
+        if (res == null) {
+            res = new HashSet<>();
+        }
+
+        return res;
+    }
+
+    private String getDnPrefixForUserId(Long userId) {
+        return PERUN_USER_ID + '=' + userId + ',' + OU_PEOPLE;
+    }
+
+    private boolean checkHasAttributes(Entry e, String[] attributes) {
+        if (e == null) {
+            return false;
+        } else if (attributes == null) {
+            return true;
+        }
+
+        for (String attr: attributes) {
+            if (e.get(attr) == null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private Long getPerunUserId(FilterBuilder filter) {
+        SearchScope scope = SearchScope.ONELEVEL;
+        String[] attributes = new String[]{PERUN_USER_ID};
+        EntryMapper<Long> mapper = e -> Long.parseLong(e.get(PERUN_USER_ID).getString());
+
+        return connectorLdap.searchFirst(OU_PEOPLE, filter, scope, attributes, mapper);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterRpc.java b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterRpc.java
new file mode 100644
index 0000000..7747579
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/adapters/impl/PerunAdapterRpc.java
@@ -0,0 +1,283 @@
+package cz.muni.ics.ga4gh.adapters.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import cz.muni.ics.ga4gh.adapters.PerunAdapterMethods;
+import cz.muni.ics.ga4gh.adapters.PerunAdapterMethodsRpc;
+import cz.muni.ics.ga4gh.config.AttributesConfig;
+import cz.muni.ics.ga4gh.config.RpcConfig;
+import cz.muni.ics.ga4gh.connectors.PerunConnectorRpc;
+import cz.muni.ics.ga4gh.mappers.RpcMapper;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import cz.muni.ics.ga4gh.model.Group;
+import cz.muni.ics.ga4gh.model.Member;
+import cz.muni.ics.ga4gh.model.PerunAttributeValue;
+import cz.muni.ics.ga4gh.model.UserExtSource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static cz.muni.ics.ga4gh.enums.MemberStatus.VALID;
+
+@Component
+@Slf4j
+public class PerunAdapterRpc implements PerunAdapterMethods, PerunAdapterMethodsRpc {
+
+    public static final String EXT_LOGIN = "extLogin";
+    public static final String EXT_SOURCE_NAME = "extSourceName";
+    public static final String USER_EXT_SOURCE = "userExtSource";
+    public static final String ATTR_NAMES = "attrNames";
+    public static final String VALUE_CREATED_AT = "valueCreatedAt";
+
+    public static final String ID = "id";
+    public static final String VO = "vo";
+    public static final String USER = "user";
+    public static final String MEMBER = "member";
+    public static final String GROUP = "group";
+
+    public static final String ATTRIBUTE_NAME = "attributeName";
+    public static final String ATTRIBUTE_VALUE = "attributeValue";
+
+    public static final String ATTRIBUTES_MANAGER = "attributesManager";
+    public static final String GROUPS_MANAGER = "groupsManager";
+    public static final String MEMBERS_MANAGER = "membersManager";
+    public static final String USERS_MANAGER = "usersManager";
+
+    public static final String GET_USER_BY_EXT_SOURCE_NAME_AND_EXT_LOGIN = "getUserByExtSourceNameAndExtLogin";
+    public static final String GET_USER_EXT_SOURCES = "getUserExtSources";
+    public static final String GET_GROUP_BY_ID = "getGroupById";
+    public static final String GET_MEMBER_BY_USER = "getMemberByUser";
+    public static final String GET_MEMBERS_BY_USER = "getMembersByUser";
+    public static final String GET_MEMBER_GROUPS = "getMemberGroups";
+    public static final String IS_GROUP_MEMBER = "isGroupMember";
+    public static final String GET_ATTRIBUTE = "getAttribute";
+    public static final String GET_ATTRIBUTES = "getAttributes";
+    public static final String GET_USERS_BY_ATTRIBUTE_VALUE = "getUsersByAttributeValue";
+
+    private final PerunConnectorRpc connectorRpc;
+    private final Map<String, AttributeMapping> attributeMappings;
+
+    @Autowired
+    PerunAdapterRpc(PerunConnectorRpc connectorRpc, AttributesConfig attributesConfig) {
+        this.connectorRpc = connectorRpc;
+        this.attributeMappings = attributesConfig.getAttributeMappings();
+    }
+
+    @Override
+    public Long getPreauthenticatedUserId(String extLogin, String extSourceName) {
+        if (!connectorRpc.isEnabled()) {
+            return null;
+        }
+
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(EXT_LOGIN, extLogin);
+        map.put(EXT_SOURCE_NAME, extSourceName);
+
+        JsonNode response = connectorRpc.post(USERS_MANAGER, GET_USER_BY_EXT_SOURCE_NAME_AND_EXT_LOGIN, map);
+
+        return response.get(ID) == null ? null : response.get(ID).asLong();
+    }
+
+    @Override
+    public boolean isUserInGroup(Long userId, Long groupId) {
+        if (!connectorRpc.isEnabled()) {
+            return false;
+        }
+
+        Map<String, Object> groupParams = new LinkedHashMap<>();
+        groupParams.put(ID, groupId);
+        JsonNode groupResponse = connectorRpc.post(GROUPS_MANAGER, GET_GROUP_BY_ID, groupParams);
+        Group group = RpcMapper.mapGroup(groupResponse);
+
+        Map<String, Object> memberParams = new LinkedHashMap<>();
+        memberParams.put(VO, group.getVoId());
+        memberParams.put(USER, userId);
+        JsonNode memberResponse = connectorRpc.post(MEMBERS_MANAGER, GET_MEMBER_BY_USER, memberParams);
+        Member member = RpcMapper.mapMember(memberResponse);
+
+        Map<String, Object> isGroupMemberParams = new LinkedHashMap<>();
+        isGroupMemberParams.put(GROUP, groupId);
+        isGroupMemberParams.put(MEMBER, member.getId());
+        JsonNode res = connectorRpc.post(GROUPS_MANAGER, IS_GROUP_MEMBER, isGroupMemberParams);
+
+        return res.asBoolean(false);
+    }
+
+    @Override
+    public List<Affiliation> getGroupAffiliations(Long userId, String groupAffiliationsAttr) {
+        if (!connectorRpc.isEnabled()) {
+            return new ArrayList<>();
+        }
+
+        List<Affiliation> affiliations = new ArrayList<>();
+        List<Member> userMembers = getMembersByUser(userId);
+
+        for (Member member : userMembers) {
+            if (VALID.equals(member.getStatus())) {
+                List<Group> memberGroups = getMemberGroups(member.getId());
+                for (Group group : memberGroups) {
+                    PerunAttributeValue attrValue = this.getGroupAttributeValue(group, groupAffiliationsAttr);
+                    if (attrValue != null && attrValue.valueAsList() != null) {
+                        long linuxTime = System.currentTimeMillis() / 1000L;
+
+                        for (String value : attrValue.valueAsList()) {
+                            Affiliation affiliation = new Affiliation(null, value, linuxTime);
+                            log.debug("found {} on group {}", value, group.getName());
+                            affiliations.add(affiliation);
+                        }
+                    }
+                }
+            }
+        }
+
+        return affiliations;
+    }
+
+    @Override
+    public String getUserAttributeCreatedAt(Long userId, String attrName) {
+        if (!connectorRpc.isEnabled() || attributeMappings.get(attrName) == null) {
+            return null;
+        }
+
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(USER, userId);
+        map.put(ATTRIBUTE_NAME, attributeMappings.get(attrName).getRpcName());
+
+        JsonNode res = connectorRpc.post(ATTRIBUTES_MANAGER, GET_ATTRIBUTE, map);
+
+        if (res == null || !res.hasNonNull(VALUE_CREATED_AT)) {
+            return null;
+        }
+
+        return res.get(VALUE_CREATED_AT).asText();
+    }
+
+    @Override
+    public List<Affiliation> getUserExtSourcesAffiliations(Long userId, String affiliationsAttr, String orgUrlAttr) {
+        if (!connectorRpc.isEnabled()) {
+            return new ArrayList<>();
+        }
+
+        List<UserExtSource> userExtSources = getUserExtSources(userId);
+        List<Affiliation> affiliations = new ArrayList<>();
+
+        Map<String, AttributeMapping> attrMappings = new HashMap<>();
+        attrMappings.put(affiliationsAttr, attributeMappings.get(affiliationsAttr));
+        attrMappings.put(orgUrlAttr, attributeMappings.get(orgUrlAttr));
+
+        for (UserExtSource ues : userExtSources) {
+            if ("cz.metacentrum.perun.core.impl.ExtSourceIdp".equals(ues.getExtSource().getType())) {
+                Map<String, PerunAttributeValue> uesAttrValues = getUserExtSourceAttributeValues(ues.getId(), attrMappings);
+
+                long asserted = ues.getLastAccess().getTime() / 1000L;
+
+                String orgUrl = uesAttrValues.get(affiliationsAttr).valueAsString();
+                String affs = uesAttrValues.get(orgUrlAttr).valueAsString();
+
+                if (affs != null) {
+                    for (String aff : affs.split(";")) {
+                        String source = ( (orgUrl != null) ? orgUrl : ues.getExtSource().getName() );
+                        Affiliation affiliation = new Affiliation(source, aff, asserted);
+                        log.debug("found {} from IdP {} with orgURL {} asserted at {}", aff, ues.getExtSource().getName(),
+                                orgUrl, asserted);
+                        affiliations.add(affiliation);
+                    }
+                }
+            }
+        }
+
+        return affiliations;
+    }
+
+    @Override
+    public Set<Long> getUserIdsByAttributeValue(AttributeMapping attrName, String attrValue) {
+        if (!connectorRpc.isEnabled()) {
+            return new HashSet<>();
+        }
+
+        Set<Long> result = new HashSet<>();
+
+        if (!StringUtils.hasText(attrName.getRpcName())) {
+            return result;
+        }
+
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(ATTRIBUTE_NAME, attrName.getRpcName());
+        map.put(ATTRIBUTE_VALUE, attrValue);
+
+        JsonNode res = connectorRpc.post(USERS_MANAGER, GET_USERS_BY_ATTRIBUTE_VALUE, map);
+
+        if (res != null) {
+            for (int i = 0; i < res.size(); i++) {
+                result.add(res.get(i).get(ID).asLong());
+            }
+        }
+
+        return result;
+    }
+
+    private List<Member> getMembersByUser(Long userId) {
+        if (!this.connectorRpc.isEnabled()) {
+            return new ArrayList<>();
+        }
+
+        Map<String, Object> params = new LinkedHashMap<>();
+        params.put(USER, userId);
+        JsonNode jsonNode = connectorRpc.post(MEMBERS_MANAGER, GET_MEMBERS_BY_USER, params);
+
+        return RpcMapper.mapMembers(jsonNode);
+    }
+
+    private List<Group> getMemberGroups(Long memberId) {
+        if (!this.connectorRpc.isEnabled()) {
+            return new ArrayList<>();
+        }
+
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(MEMBER, memberId);
+
+        JsonNode response = connectorRpc.post(GROUPS_MANAGER, GET_MEMBER_GROUPS, map);
+        return RpcMapper.mapGroups(response);
+    }
+
+    private PerunAttributeValue getGroupAttributeValue(Group group, String attrToFetch) {
+        if (attributeMappings.get(attrToFetch) == null) {
+            return null;
+        }
+
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(GROUP, group.getId());
+        map.put(ATTRIBUTE_NAME, attributeMappings.get(attrToFetch).getRpcName());
+        JsonNode res = connectorRpc.post(ATTRIBUTES_MANAGER, GET_ATTRIBUTE, map);
+
+        return RpcMapper.mapAttributeValue(res);
+    }
+
+    private List<UserExtSource> getUserExtSources(Long userId) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(USER, userId);
+
+        JsonNode response = connectorRpc.post(USERS_MANAGER, GET_USER_EXT_SOURCES, map);
+        return RpcMapper.mapUserExtSources(response);
+    }
+
+    private Map<String, PerunAttributeValue> getUserExtSourceAttributeValues(Long uesId, Map<String, AttributeMapping> attrMappings) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put(USER_EXT_SOURCE, uesId);
+        map.put(ATTR_NAMES, attrMappings.values().stream().map(AttributeMapping::getRpcName).collect(Collectors.toList()));
+
+        JsonNode response = connectorRpc.post(ATTRIBUTES_MANAGER, GET_ATTRIBUTES, map);
+
+        return RpcMapper.mapAttributes(response, attrMappings);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/aop/LogTimes.java b/src/main/java/cz/muni/ics/ga4gh/aop/LogTimes.java
new file mode 100644
index 0000000..0e2e60b
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/aop/LogTimes.java
@@ -0,0 +1,11 @@
+package cz.muni.ics.ga4gh.aop;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LogTimes {
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/AdapterConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/AdapterConfig.java
new file mode 100644
index 0000000..915582c
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/AdapterConfig.java
@@ -0,0 +1,19 @@
+package cz.muni.ics.ga4gh.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "adapter")
+@Getter
+@Setter
+public class AdapterConfig {
+
+    private String adapterPrimary;
+
+    private Boolean callFallback;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/AttributesConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/AttributesConfig.java
new file mode 100644
index 0000000..469443e
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/AttributesConfig.java
@@ -0,0 +1,20 @@
+package cz.muni.ics.ga4gh.config;
+
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Map;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "attributes")
+@Getter
+@Setter
+public class AttributesConfig {
+
+    private Map<String, AttributeMapping> attributeMappings;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/BasicAuthConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/BasicAuthConfig.java
new file mode 100644
index 0000000..5436cdb
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/BasicAuthConfig.java
@@ -0,0 +1,19 @@
+package cz.muni.ics.ga4gh.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "basic-auth")
+@Getter
+@Setter
+public class BasicAuthConfig {
+
+    private String username;
+
+    private String password;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/BrokerConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/BrokerConfig.java
new file mode 100644
index 0000000..ac59aaf
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/BrokerConfig.java
@@ -0,0 +1,37 @@
+package cz.muni.ics.ga4gh.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "broker")
+@Getter
+@Setter
+public class BrokerConfig {
+
+    private String bonaFideStatusAttr;
+
+    private String bonaFideStatusRemsAttr;
+
+    private String groupAffiliationsAttr;
+
+    private Long termsAndPoliciesGroupId;
+
+    private String affiliationsAttr;
+
+    private String orgUrlAttr;
+
+    private List<String> attributesToSearch;
+
+    private String issuer;
+
+    private String jku;
+
+    private String pathToJwkFile;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/Ga4ghConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/Ga4ghConfig.java
new file mode 100644
index 0000000..188a1de
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/Ga4ghConfig.java
@@ -0,0 +1,20 @@
+package cz.muni.ics.ga4gh.config;
+
+import cz.muni.ics.ga4gh.model.Repo;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "ga4gh")
+@Getter
+@Setter
+public class Ga4ghConfig {
+
+    private List<Repo> repos;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/LdapConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/LdapConfig.java
new file mode 100644
index 0000000..8a45101
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/LdapConfig.java
@@ -0,0 +1,33 @@
+package cz.muni.ics.ga4gh.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "ldap")
+@Getter
+@Setter
+public class LdapConfig {
+
+    private String host;
+
+    private String user;
+
+    private String password;
+
+    private String baseDn;
+
+    private Boolean useTls;
+
+    private Boolean useSsl;
+
+    private Boolean allowUntrustedSsl;
+
+    private Long timeoutSecs;
+
+    private int port;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/config/RpcConfig.java b/src/main/java/cz/muni/ics/ga4gh/config/RpcConfig.java
new file mode 100644
index 0000000..74f41d8
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/config/RpcConfig.java
@@ -0,0 +1,25 @@
+package cz.muni.ics.ga4gh.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties
+@ConfigurationProperties(prefix = "rpc")
+@Getter
+@Setter
+public class RpcConfig {
+
+    private Boolean enabled;
+
+    private String url;
+
+    private String username;
+
+    private String password;
+
+    private String serializer;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorLdap.java b/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorLdap.java
new file mode 100644
index 0000000..5f4c66f
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorLdap.java
@@ -0,0 +1,154 @@
+package cz.muni.ics.ga4gh.connectors;
+
+import cz.muni.ics.ga4gh.aop.LogTimes;
+import cz.muni.ics.ga4gh.config.LdapConfig;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory;
+import org.apache.directory.ldap.client.api.DefaultPoolableLdapConnectionFactory;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapConnectionPool;
+import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
+import org.apache.directory.ldap.client.api.search.FilterBuilder;
+import org.apache.directory.ldap.client.template.EntryMapper;
+import org.apache.directory.ldap.client.template.LdapConnectionTemplate;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Objects;
+
+@Repository
+@Slf4j
+@Getter
+public class PerunConnectorLdap implements DisposableBean {
+
+    private final String baseDN;
+    private final LdapConnectionPool pool;
+    private final LdapConnectionTemplate ldap;
+
+    @Autowired
+    public PerunConnectorLdap(LdapConfig config) {
+        if (config.getHost() == null || config.getHost().trim().isEmpty()) {
+            throw new IllegalArgumentException("Host cannot be null or empty");
+        } else if (config.getBaseDn() == null || config.getBaseDn().trim().isEmpty()) {
+            throw new IllegalArgumentException("baseDN cannot be null or empty");
+        }
+
+        boolean useTLS = Objects.requireNonNullElse(config.getUseTls(), false);
+        boolean useSSL = Objects.requireNonNullElse(config.getUseSsl(), false);
+        boolean allowUntrustedSsl = Objects.requireNonNullElse(config.getAllowUntrustedSsl(), false);
+        long timeoutSecs = Objects.requireNonNullElse(config.getTimeoutSecs(), 5L);
+
+
+        this.baseDN = config.getBaseDn();
+
+        LdapConnectionConfig ldapConnectionConfig = getLdapConnectionConfig(config.getHost(), config.getPort(), useTLS, useSSL, allowUntrustedSsl);
+        if (config.getUser() != null && !config.getUser().isEmpty()) {
+            log.debug("setting ldap user to {}", config.getUser());
+            ldapConnectionConfig.setName(config.getUser());
+        }
+        if (config.getPassword() != null && !config.getPassword().isEmpty()) {
+            log.debug("setting ldap password");
+            ldapConnectionConfig.setCredentials(config.getPassword());
+        }
+        DefaultLdapConnectionFactory factory = new DefaultLdapConnectionFactory(ldapConnectionConfig);
+        factory.setTimeOut(timeoutSecs * 1000L);
+
+        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
+        poolConfig.setTestOnBorrow(true);
+
+        pool = new LdapConnectionPool(new DefaultPoolableLdapConnectionFactory(factory), poolConfig);
+        ldap = new LdapConnectionTemplate(pool);
+        log.debug("initialized LDAP connector");
+    }
+
+    public String getBaseDN() {
+        return baseDN;
+    }
+
+    private LdapConnectionConfig getLdapConnectionConfig(String host, int port, boolean useTLS, boolean useSSL,
+                                           boolean allowUntrustedSsl) {
+        LdapConnectionConfig config = new LdapConnectionConfig();
+        config.setLdapHost(host);
+        config.setLdapPort(port);
+        config.setUseSsl(useSSL);
+        config.setUseTls(useTLS);
+        if (allowUntrustedSsl) {
+            config.setTrustManagers(new NoVerificationTrustManager());
+        }
+
+        return config;
+    }
+
+    @Override
+    public void destroy() {
+        if (!pool.isClosed()) {
+            pool.close();
+        }
+    }
+
+    /**
+     * Search for the first entry that satisfies criteria.
+     * @param dnPrefix Prefix to be added to the base DN. (i.e. ou=People) !DO NOT END WITH A COMMA!
+     * @param filter Filter for entries
+     * @param scope Search scope
+     * @param attributes Attributes to be fetch for entry
+     * @param entryMapper Mapper of entries to the target class T
+     * @param <T> Class that the result should be mapped to.
+     * @return Found entry mapped to target class
+     */
+    @LogTimes
+    public <T> T searchFirst(String dnPrefix, FilterBuilder filter, SearchScope scope, String[] attributes,
+                             EntryMapper<T> entryMapper)
+    {
+        Dn fullDn = getFullDn(dnPrefix);
+        return ldap.searchFirst(fullDn, filter, scope, attributes, entryMapper);
+    }
+
+    /**
+     * Perform lookup for the entry that satisfies criteria.
+     * @param dnPrefix Prefix to be added to the base DN. (i.e. ou=People) !DO NOT END WITH A COMMA!
+     * @param attributes Attributes to be fetch for entry
+     * @param entryMapper Mapper of entries to the target class T
+     * @param <T> Class that the result should be mapped to.
+     * @return Found entry mapped to target class
+     */
+    @LogTimes
+    public <T> T lookup(String dnPrefix, String[] attributes, EntryMapper<T> entryMapper) {
+        Dn fullDn = getFullDn(dnPrefix);
+        return ldap.lookup(fullDn, attributes, entryMapper);
+    }
+
+    /**
+     * Search for the entries satisfy criteria.
+     * @param dnPrefix Prefix to be added to the base DN. (i.e. ou=People) !DO NOT END WITH A COMMA!
+     * @param filter Filter for entries
+     * @param scope Search scope
+     * @param attributes Attributes to be fetch for entry
+     * @param entryMapper Mapper of entries to the target class T
+     * @param <T> Class that the result should be mapped to.
+     * @return List of found entries mapped to target class
+     */
+    @LogTimes
+    public <T> List<T> search(String dnPrefix, FilterBuilder filter, SearchScope scope, String[] attributes,
+                              EntryMapper<T> entryMapper)
+    {
+        Dn fullDn = getFullDn(dnPrefix);
+        return ldap.search(fullDn, filter, scope, attributes, entryMapper);
+    }
+
+    private Dn getFullDn(String prefix) {
+        String dn = baseDN;
+        if (StringUtils.hasText(prefix)) {
+            dn = prefix + "," + baseDN;
+        }
+
+        return ldap.newDn(dn);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorRpc.java b/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorRpc.java
new file mode 100644
index 0000000..ecacbf7
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/connectors/PerunConnectorRpc.java
@@ -0,0 +1,188 @@
+package cz.muni.ics.ga4gh.connectors;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import cz.muni.ics.ga4gh.aop.LogTimes;
+import cz.muni.ics.ga4gh.config.RpcConfig;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HeaderElement;
+import org.apache.http.HeaderElementIterator;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicHeaderElementIterator;
+import org.apache.http.protocol.HTTP;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.client.InterceptingClientHttpRequestFactory;
+import org.springframework.http.client.support.BasicAuthorizationInterceptor;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@Repository
+@Slf4j
+@Getter
+public class PerunConnectorRpc {
+
+    public static final String ATTRIBUTES_MANAGER = "attributesManager";
+    public static final String FACILITIES_MANAGER = "facilitiesManager";
+    public static final String GROUPS_MANAGER = "groupsManager";
+    public static final String MEMBERS_MANAGER = "membersManager";
+    public static final String REGISTRAR_MANAGER = "registrarManager";
+    public static final String SEARCHER = "searcher";
+    public static final String USERS_MANAGER = "usersManager";
+    public static final String VOS_MANAGER = "vosManager";
+    public static final String RESOURCES_MANAGER = "resourcesManager";
+
+    private String perunUrl;
+    private String perunUser;
+    private String perunPassword;
+    private boolean isEnabled;
+    private String serializer;
+    private RestTemplate restTemplate;
+
+    @Autowired
+    public PerunConnectorRpc(RpcConfig config) {
+        this.setPerunUrl(config.getUrl());
+        this.setPerunUser(config.getUsername());
+        this.setPerunPassword(config.getPassword());
+        this.setEnabled(config.getEnabled());
+        this.setSerializer(config.getSerializer());
+    }
+
+    public void setPerunUrl(String perunUrl) {
+        if (!StringUtils.hasText(perunUrl)) {
+            throw new IllegalArgumentException("Perun URL cannot be null or empty");
+        } else if (perunUrl.endsWith("/")) {
+            perunUrl = perunUrl.substring(0, perunUrl.length() - 1);
+        }
+
+        this.perunUrl = perunUrl;
+    }
+
+    public void setPerunUser(String perunUser) {
+        if (!StringUtils.hasText(perunUser)) {
+            throw new IllegalArgumentException("Perun USER cannot be null or empty");
+        }
+
+        this.perunUser = perunUser;
+    }
+
+    public void setPerunPassword(String perunPassword) {
+        if (!StringUtils.hasText(perunPassword)) {
+            throw new IllegalArgumentException("Perun PASSWORD cannot be null or empty");
+        }
+
+        this.perunPassword = perunPassword;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.isEnabled = Objects.requireNonNullElse(enabled, false);
+    }
+
+    public void setSerializer(String serializer) {
+        if (!StringUtils.hasText(serializer)) {
+            this.serializer = "json";
+        }
+
+        this.serializer = serializer;
+    }
+
+    @PostConstruct
+    public void postInit() {
+        restTemplate = new RestTemplate();
+        //HTTP connection pooling, see https://howtodoinjava.com/spring-restful/resttemplate-httpclient-java-config/
+        RequestConfig requestConfig = RequestConfig.custom()
+                .setConnectionRequestTimeout(30000) // The timeout when requesting a connection from the connection manager
+                .setConnectTimeout(30000) // Determines the timeout in milliseconds until a connection is established
+                .setSocketTimeout(60000) // The timeout for waiting for data
+                .build();
+
+        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
+        poolingConnectionManager.setMaxTotal(20); // maximum connections total
+        poolingConnectionManager.setDefaultMaxPerRoute(18);
+
+        ConnectionKeepAliveStrategy connectionKeepAliveStrategy = (response, context) -> {
+            HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
+
+            while (it.hasNext()) {
+                HeaderElement he = it.nextElement();
+                String param = he.getName();
+                String value = he.getValue();
+
+                if (value != null && param.equalsIgnoreCase("timeout")) {
+                    return Long.parseLong(value) * 1000;
+                }
+            }
+
+            return 20000L;
+        };
+
+        CloseableHttpClient httpClient = HttpClients.custom()
+                .setDefaultRequestConfig(requestConfig)
+                .setConnectionManager(poolingConnectionManager)
+                .setKeepAliveStrategy(connectionKeepAliveStrategy)
+                .build();
+
+        HttpComponentsClientHttpRequestFactory poolingRequestFactory = new HttpComponentsClientHttpRequestFactory();
+        poolingRequestFactory.setHttpClient(httpClient);
+        //basic authentication
+        List<ClientHttpRequestInterceptor> interceptors =
+                Collections.singletonList(new BasicAuthorizationInterceptor(perunUser, perunPassword));
+        InterceptingClientHttpRequestFactory authenticatingRequestFactory = new InterceptingClientHttpRequestFactory(poolingRequestFactory, interceptors);
+        restTemplate.setRequestFactory(authenticatingRequestFactory);
+    }
+
+    /**
+     * Make post call to Perun RPC
+     * @param manager String value representing manager to be called. Use constants from this class.
+     * @param method Method to be called (i.e. getUserById)
+     * @param map Map of parameters to be passed as request body
+     * @return Response from Perun
+     */
+    @LogTimes
+    public JsonNode post(String manager, String method, Map<String, Object> map) {
+        if (!this.isEnabled) {
+            return JsonNodeFactory.instance.nullNode();
+        }
+
+        String actionUrl = perunUrl + '/' + serializer + '/' + manager + '/' + method;
+        //make the call
+        try {
+            log.debug("calling {} with {}", actionUrl, map);
+
+            return restTemplate.postForObject(actionUrl, map, JsonNode.class);
+        } catch (HttpClientErrorException ex) {
+            MediaType contentType = ex.getResponseHeaders().getContentType();
+            String body = ex.getResponseBodyAsString();
+            log.error("HTTP ERROR " + ex.getRawStatusCode() + " URL " + actionUrl + " Content-Type: " + contentType);
+
+            if ("json".equals(contentType.getSubtype())) {
+                try {
+                    log.error(new ObjectMapper().readValue(body, JsonNode.class).path("message").asText());
+                } catch (IOException e) {
+                    log.error("cannot parse error message from JSON", e);
+                }
+            } else {
+                log.error(ex.getMessage());
+            }
+
+            throw new RuntimeException("cannot connect to Perun RPC", ex);
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/controllers/Ga4ghBrokerController.java b/src/main/java/cz/muni/ics/ga4gh/controllers/Ga4ghBrokerController.java
new file mode 100644
index 0000000..c37ecf1
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/controllers/Ga4ghBrokerController.java
@@ -0,0 +1,35 @@
+package cz.muni.ics.ga4gh.controllers;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import cz.muni.ics.ga4gh.facade.Ga4ghBrokerFacade;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+
+@RestController
+@RequestMapping("/ga4gh")
+public class Ga4ghBrokerController {
+
+    private final Ga4ghBrokerFacade ga4GhBrokerFacade;
+
+    @Autowired
+    public Ga4ghBrokerController(Ga4ghBrokerFacade ga4GhBrokerFacade) {
+        this.ga4GhBrokerFacade = ga4GhBrokerFacade;
+    }
+
+    @GetMapping(value = "/{eppn}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ArrayNode getGa4ghPassport(@PathVariable String eppn, HttpServletResponse response) {
+        ArrayNode result = ga4GhBrokerFacade.getGa4ghPassport(eppn);
+
+        if (result == null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
+
+        return result;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/controllers/JwkSetPublishingEndpoint.java b/src/main/java/cz/muni/ics/ga4gh/controllers/JwkSetPublishingEndpoint.java
new file mode 100644
index 0000000..90bd9c7
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/controllers/JwkSetPublishingEndpoint.java
@@ -0,0 +1,40 @@
+package cz.muni.ics.ga4gh.controllers;
+
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.JWKSet;
+import cz.muni.ics.ga4gh.service.JWTSigningAndValidationService;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+@CrossOrigin(originPatterns = "*")
+@RestController
+@RequestMapping("/public")
+@Getter
+@Setter
+public class JwkSetPublishingEndpoint {
+
+    public static final String URL = "jwk";
+
+    private JWTSigningAndValidationService jwtService;
+
+    @Autowired
+    public JwkSetPublishingEndpoint(JWTSigningAndValidationService jwtService) {
+        this.jwtService = jwtService;
+    }
+
+    @RequestMapping(value = "/" + URL, produces = MediaType.APPLICATION_JSON_VALUE)
+    public String getJwk() {
+        // map from key id to key
+        Map<String, JWK> keys = jwtService.getAllPublicKeys();
+        JWKSet jwkSet = new JWKSet(new ArrayList<>(keys.values()));
+        return jwkSet.toString();
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/enums/MemberStatus.java b/src/main/java/cz/muni/ics/ga4gh/enums/MemberStatus.java
new file mode 100644
index 0000000..9794780
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/enums/MemberStatus.java
@@ -0,0 +1,31 @@
+package cz.muni.ics.ga4gh.enums;
+
+public enum MemberStatus {
+
+    VALID,
+    EXPIRED,
+    INVALID,
+    DISABLED,
+    SUSPENDED;
+
+    public static MemberStatus fromString(String status) {
+        if (status == null) {
+            return null;
+        }
+
+        switch (status.toUpperCase().trim()) {
+            case "VALID":
+                return VALID;
+            case "INVALID":
+                return INVALID;
+            case "EXPIRED":
+                return EXPIRED;
+            case "DISABLED":
+                return DISABLED;
+            case "SUSPENDED":
+                return SUSPENDED;
+            default:
+                return null;
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/exceptions/InconvertibleValueException.java b/src/main/java/cz/muni/ics/ga4gh/exceptions/InconvertibleValueException.java
new file mode 100644
index 0000000..5816702
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/exceptions/InconvertibleValueException.java
@@ -0,0 +1,24 @@
+package cz.muni.ics.ga4gh.exceptions;
+
+public class InconvertibleValueException extends RuntimeException {
+
+    public InconvertibleValueException() {
+        super();
+    }
+
+    public InconvertibleValueException(String s) {
+        super(s);
+    }
+
+    public InconvertibleValueException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+
+    public InconvertibleValueException(Throwable throwable) {
+        super(throwable);
+    }
+
+    protected InconvertibleValueException(String s, Throwable throwable, boolean b, boolean b1) {
+        super(s, throwable, b, b1);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/exceptions/MissingFieldException.java b/src/main/java/cz/muni/ics/ga4gh/exceptions/MissingFieldException.java
new file mode 100644
index 0000000..a889a9b
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/exceptions/MissingFieldException.java
@@ -0,0 +1,24 @@
+package cz.muni.ics.ga4gh.exceptions;
+
+public class MissingFieldException extends RuntimeException {
+
+    public MissingFieldException() {
+        super();
+    }
+
+    public MissingFieldException(String s) {
+        super(s);
+    }
+
+    public MissingFieldException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+
+    public MissingFieldException(Throwable throwable) {
+        super(throwable);
+    }
+
+    protected MissingFieldException(String s, Throwable throwable, boolean b, boolean b1) {
+        super(s, throwable, b, b1);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/exceptions/UserNotUniqueException.java b/src/main/java/cz/muni/ics/ga4gh/exceptions/UserNotUniqueException.java
new file mode 100644
index 0000000..dc3eee0
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/exceptions/UserNotUniqueException.java
@@ -0,0 +1,24 @@
+package cz.muni.ics.ga4gh.exceptions;
+
+public class UserNotUniqueException extends RuntimeException {
+
+    public UserNotUniqueException() {
+        super();
+    }
+
+    public UserNotUniqueException(String s) {
+        super(s);
+    }
+
+    public UserNotUniqueException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+
+    public UserNotUniqueException(Throwable throwable) {
+        super(throwable);
+    }
+
+    protected UserNotUniqueException(String s, Throwable throwable, boolean b, boolean b1) {
+        super(s, throwable, b, b1);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/facade/Ga4ghBrokerFacade.java b/src/main/java/cz/muni/ics/ga4gh/facade/Ga4ghBrokerFacade.java
new file mode 100644
index 0000000..2c4ebf4
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/facade/Ga4ghBrokerFacade.java
@@ -0,0 +1,8 @@
+package cz.muni.ics.ga4gh.facade;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+public interface Ga4ghBrokerFacade {
+
+    ArrayNode getGa4ghPassport(String eppn);
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/facade/impl/Ga4GhBrokerFacadeImpl.java b/src/main/java/cz/muni/ics/ga4gh/facade/impl/Ga4GhBrokerFacadeImpl.java
new file mode 100644
index 0000000..bf3ce54
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/facade/impl/Ga4GhBrokerFacadeImpl.java
@@ -0,0 +1,23 @@
+package cz.muni.ics.ga4gh.facade.impl;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import cz.muni.ics.ga4gh.facade.Ga4ghBrokerFacade;
+import cz.muni.ics.ga4gh.service.Ga4ghBrokerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class Ga4GhBrokerFacadeImpl implements Ga4ghBrokerFacade {
+
+    Ga4ghBrokerService ga4GhBrokerService;
+
+    @Autowired
+    public Ga4GhBrokerFacadeImpl(Ga4ghBrokerService ga4GhBrokerService) {
+        this.ga4GhBrokerService = ga4GhBrokerService;
+    }
+
+    @Override
+    public ArrayNode getGa4ghPassport(String eppn) {
+        return ga4GhBrokerService.getGa4ghPassport(eppn);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/jose/keystore/JWKSetKeyStore.java b/src/main/java/cz/muni/ics/ga4gh/jose/keystore/JWKSetKeyStore.java
new file mode 100644
index 0000000..0c03f88
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/jose/keystore/JWKSetKeyStore.java
@@ -0,0 +1,79 @@
+package cz.muni.ics.ga4gh.jose.keystore;
+
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.JWKSet;
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Getter
+public class JWKSetKeyStore {
+
+    private JWKSet jwkSet;
+    private Resource location;
+
+    @Autowired
+    public JWKSetKeyStore(Resource location) {
+        setLocation(location);
+    }
+
+    public JWKSetKeyStore(JWKSet jwkSet) {
+        this.setJwkSet(jwkSet);
+        initializeJwkSet();
+    }
+
+    public void setJwkSet(JWKSet jwkSet) {
+        if (jwkSet == null) {
+            throw new IllegalArgumentException("Argument cannot be null");
+        }
+
+        this.jwkSet = jwkSet;
+        initializeJwkSet();
+    }
+
+    public void setLocation(Resource location) {
+        this.location = location;
+        initializeJwkSet();
+    }
+
+    public List<JWK> getKeys() {
+        if (jwkSet == null) {
+            initializeJwkSet();
+        }
+
+        return jwkSet.getKeys();
+    }
+
+    private void initializeJwkSet() {
+        if (jwkSet != null) {
+            return;
+        } else if (location == null) {
+            return;
+        }
+
+        if (location.exists() && location.isReadable()) {
+            try (BufferedReader br = new BufferedReader(
+                    new InputStreamReader(location.getInputStream(), StandardCharsets.UTF_8))
+            ) {
+                String s = br.lines().collect(Collectors.joining());
+                jwkSet = JWKSet.parse(s);
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Key Set resource could not be read: " + location);
+            } catch (ParseException e) {
+                throw new IllegalArgumentException("Key Set resource could not be parsed: " + location);
+            }
+        } else {
+            throw new IllegalArgumentException("Key Set resource could not be read: " + location);
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/mappers/RpcMapper.java b/src/main/java/cz/muni/ics/ga4gh/mappers/RpcMapper.java
new file mode 100644
index 0000000..37254d6
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/mappers/RpcMapper.java
@@ -0,0 +1,277 @@
+package cz.muni.ics.ga4gh.mappers;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cz.muni.ics.ga4gh.enums.MemberStatus;
+import cz.muni.ics.ga4gh.exceptions.MissingFieldException;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import cz.muni.ics.ga4gh.model.ExtSource;
+import cz.muni.ics.ga4gh.model.Group;
+import cz.muni.ics.ga4gh.model.Member;
+import cz.muni.ics.ga4gh.model.PerunAttributeValue;
+import cz.muni.ics.ga4gh.model.UserExtSource;
+
+
+/**
+ * This class is mapping JsonNodes to object models.
+ *
+ * @author Dominik Frantisek Bucik <bucik@ics.muni.cz>
+ */
+public class RpcMapper {
+
+    public static final String ID = "id";
+    public static final String UUID = "uuid";
+    public static final String PARENT_GROUP_ID = "parentGroupId";
+    public static final String NAME = "name";
+    public static final String DESCRIPTION = "description";
+    public static final String VO_ID = "voId";
+    public static final String USER_ID = "userId";
+    public static final String STATUS = "status";
+    public static final String TYPE = "type";
+    public static final String LOGIN = "login";
+    public static final String EXT_SOURCE = "extSource";
+    public static final String LOA = "loa";
+    public static final String LAST_ACCESS = "lastAccess";
+    public static final String PERSISTENT = "persistent";
+    public static final String FRIENDLY_NAME = "friendlyName";
+    public static final String NAMESPACE = "namespace";
+    public static final String VALUE = "value";
+
+    /**
+     * Maps JsonNode to Group model.
+     *
+     * @param json Group in JSON format from Perun to be mapped.
+     * @return Mapped Group object.
+     */
+    public static Group mapGroup(JsonNode json) {
+        if (json == null || json.isNull()) {
+            return null;
+        }
+
+        Long id = getRequiredFieldAsLong(json, ID);
+        Long parentGroupId = getFieldAsLong(json, PARENT_GROUP_ID);
+        String name = getFieldAsString(json, NAME);
+        String description = getFieldAsString(json, DESCRIPTION);
+        Long voId = getRequiredFieldAsLong(json, VO_ID);
+        String uuid = getRequiredFieldAsString(json, UUID);
+
+        return new Group(id, parentGroupId, name, description, null, uuid,  voId);
+    }
+
+    /**
+     * Maps JsonNode to List of Groups.
+     *
+     * @param jsonArray JSON array of groups in JSON format from Perun to be mapped.
+     * @return List of groups.
+     */
+    public static List<Group> mapGroups(JsonNode jsonArray) {
+        if (jsonArray.isNull()) {
+            return new ArrayList<>();
+        }
+
+        List<Group> result = new ArrayList<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JsonNode groupNode = jsonArray.get(i);
+            Group mappedGroup = RpcMapper.mapGroup(groupNode);
+            result.add(mappedGroup);
+        }
+
+        return result;
+    }
+
+    /**
+     * Maps JsonNode to Member model.
+     *
+     * @param json Member in JSON format from Perun to be mapped.
+     * @return Mapped Member object.
+     */
+    public static Member mapMember(JsonNode json) {
+        if (json == null || json.isNull()) {
+            return null;
+        }
+
+        Long id = getRequiredFieldAsLong(json, ID);
+        Long userId = getRequiredFieldAsLong(json, USER_ID);
+        Long voId = getRequiredFieldAsLong(json, VO_ID);
+        MemberStatus status = MemberStatus.fromString(getRequiredFieldAsString(json, STATUS));
+
+        return new Member(id, userId, voId, status);
+    }
+
+    /**
+     * Maps JsonNode to List of Members.
+     *
+     * @param jsonArray JSON array of members in JSON format from Perun to be mapped.
+     * @return List of members.
+     */
+    public static List<Member> mapMembers(JsonNode jsonArray) {
+        if (jsonArray.isNull()) {
+            return new ArrayList<>();
+        }
+
+        List<Member> members = new ArrayList<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JsonNode memberNode = jsonArray.get(i);
+            Member mappedMember = RpcMapper.mapMember(memberNode);
+            members.add(mappedMember);
+        }
+
+        return members;
+    }
+
+    /**
+     * Maps JsonNode to ExtSource model.
+     *
+     * @param json ExtSource in JSON format from Perun to be mapped.
+     * @return Mapped ExtSource object.
+     */
+    public static ExtSource mapExtSource(JsonNode json) {
+        if (json == null || json.isNull()) {
+            return null;
+        }
+
+        Long id = getRequiredFieldAsLong(json, ID);
+        String name = getRequiredFieldAsString(json, NAME);
+        String type = getRequiredFieldAsString(json, TYPE);
+
+        return new ExtSource(id, name, type);
+    }
+
+    /**
+     * Maps JsonNode to UserExtSource model.
+     *
+     * @param json UserExtSource in JSON format from Perun to be mapped.
+     * @return Mapped UserExtSource object.
+     */
+    public static UserExtSource mapUserExtSource(JsonNode json) {
+        if (json == null || json.isNull()) {
+            return null;
+        }
+
+        Long id = getRequiredFieldAsLong(json, ID);
+        String login = getRequiredFieldAsString(json, LOGIN);
+        ExtSource extSource = RpcMapper.mapExtSource(getRequiredFieldAsJsonNode(json, EXT_SOURCE));
+        int loa = getRequiredFieldAsInt(json, LOA);
+        boolean persistent = getRequiredFieldAsBoolean(json, PERSISTENT);
+        Timestamp lastAccess = Timestamp.valueOf(getRequiredFieldAsString(json, LAST_ACCESS));
+
+        return new UserExtSource(id, extSource, login, loa, persistent, lastAccess);
+    }
+
+    /**
+     * Maps JsonNode to List of UserExtSources.
+     *
+     * @param jsonArray JSON array of userExtSources in JSON format from Perun to be mapped.
+     * @return List of userExtSources.
+     */
+    public static List<UserExtSource> mapUserExtSources(JsonNode jsonArray) {
+        if (jsonArray.isNull()) {
+            return new ArrayList<>();
+        }
+
+        List<UserExtSource> userExtSources = new ArrayList<>();
+
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JsonNode userExtSource = jsonArray.get(i);
+            UserExtSource mappedUes = RpcMapper.mapUserExtSource(userExtSource);
+            userExtSources.add(mappedUes);
+        }
+
+        return userExtSources;
+    }
+
+    public static PerunAttributeValue mapAttributeValue(JsonNode json) {
+        if (json == null || json.isNull()) {
+            return null;
+        }
+
+        String friendlyName = getRequiredFieldAsString(json, FRIENDLY_NAME);
+        String namespace = getRequiredFieldAsString(json, NAMESPACE);
+        String type = getRequiredFieldAsString(json, TYPE);
+        JsonNode value = getFieldAsJsonNode(json, VALUE);
+
+        return new PerunAttributeValue(namespace + ':' + friendlyName, type, value);
+    }
+
+    public static Map<String, PerunAttributeValue> mapAttributes(JsonNode jsonNode, Map<String, AttributeMapping> attrMappings) {
+        Map<String, PerunAttributeValue> attributesAsMap = new HashMap<>();
+
+        for (int i = 0; i < jsonNode.size(); i++) {
+            JsonNode attribute = jsonNode.get(i);
+            PerunAttributeValue mappedAttributeValue = mapAttributeValue(attribute);
+
+            for (Map.Entry<String, AttributeMapping> entry : attrMappings.entrySet()) {
+                if (entry.getValue().getRpcName().equals(mappedAttributeValue.getAttrName())) {
+                    attributesAsMap.put(entry.getKey(), mappedAttributeValue);
+                }
+            }
+        }
+
+        return attributesAsMap;
+    }
+
+    private static Long getRequiredFieldAsLong(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            throw new MissingFieldException();
+        }
+        return json.get(name).asLong();
+    }
+
+    private static Long getFieldAsLong(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            return 0L;
+        }
+        return json.get(name).asLong();
+    }
+
+    private static int getRequiredFieldAsInt(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            throw new MissingFieldException();
+        }
+        return json.get(name).asInt();
+    }
+
+    private static int getFieldAsInt(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            return 0;
+        }
+        return json.get(name).asInt();
+    }
+
+    private static boolean getRequiredFieldAsBoolean(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            throw new MissingFieldException();
+        }
+        return json.get(name).asBoolean();
+    }
+
+    private static String getRequiredFieldAsString(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            throw new MissingFieldException();
+        }
+        return json.get(name).asText();
+    }
+
+    private static String getFieldAsString(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            return "";
+        }
+        return json.get(name).asText();
+    }
+
+    private static JsonNode getRequiredFieldAsJsonNode(JsonNode json, String name) {
+        if (!json.hasNonNull(name)) {
+            throw new MissingFieldException();
+        }
+        return json.get(name);
+    }
+
+    private static JsonNode getFieldAsJsonNode(JsonNode json, String name) {
+        return json.get(name);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Affiliation.java b/src/main/java/cz/muni/ics/ga4gh/model/Affiliation.java
new file mode 100644
index 0000000..767a472
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Affiliation.java
@@ -0,0 +1,19 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+
+@Getter
+@ToString
+@EqualsAndHashCode
+@AllArgsConstructor
+public class Affiliation {
+
+    private final String source;
+
+    private final String value;
+
+    private final long asserted;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/AttributeMapping.java b/src/main/java/cz/muni/ics/ga4gh/model/AttributeMapping.java
new file mode 100644
index 0000000..c90f81f
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/AttributeMapping.java
@@ -0,0 +1,23 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@EqualsAndHashCode
+public class AttributeMapping {
+
+    private String internalName;
+
+    private String rpcName;
+
+    private String ldapName;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/ExtSource.java b/src/main/java/cz/muni/ics/ga4gh/model/ExtSource.java
new file mode 100644
index 0000000..eeb1cd9
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/ExtSource.java
@@ -0,0 +1,40 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.util.StringUtils;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class ExtSource {
+
+    @Setter
+    private Long id;
+
+    private String name;
+
+    private String type;
+
+    public void setName(String name) {
+        if (StringUtils.hasText(name)) {
+            throw new IllegalArgumentException("name cannot be null nor empty");
+        }
+
+        this.name = name;
+    }
+
+    public void setType(String type) {
+        if (!StringUtils.hasText(type)) {
+            throw new IllegalArgumentException("type cannot be null nor empty");
+        }
+
+        this.type = type;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghClaimRepository.java b/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghClaimRepository.java
new file mode 100644
index 0000000..f9c7bd9
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghClaimRepository.java
@@ -0,0 +1,20 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+import org.springframework.web.client.RestTemplate;
+
+@Getter
+@ToString
+@EqualsAndHashCode
+@AllArgsConstructor
+public class Ga4ghClaimRepository {
+
+    private final String name;
+
+    private final String actionURL;
+
+    private final RestTemplate restTemplate;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghPassportVisa.java b/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghPassportVisa.java
new file mode 100644
index 0000000..6917574
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Ga4ghPassportVisa.java
@@ -0,0 +1,59 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
+public class Ga4ghPassportVisa {
+
+    public static final String GA4GH_VISA_V1 = "ga4gh_visa_v1";
+
+    public static final String TYPE_AFFILIATION_AND_ROLE = "AffiliationAndRole";
+    public static final String TYPE_ACCEPTED_TERMS_AND_POLICIES = "AcceptedTermsAndPolicies";
+    public static final String TYPE_RESEARCHER_STATUS = "ResearcherStatus";
+    public static final String TYPE_LINKED_IDENTITIES = "LinkedIdentities";
+
+    public static final String BY_SYSTEM = "system";
+    public static final String BY_SO = "so";
+    public static final String BY_PEER = "peer";
+    public static final String BY_SELF = "self";
+
+    public static final String SUB = "sub";
+    public static final String EXP = "exp";
+    public static final String ISS = "iss";
+    public static final String TYPE = "type";
+    public static final String ASSERTED = "asserted";
+    public static final String VALUE = "value";
+    public static final String SOURCE = "source";
+    public static final String BY = "by";
+    public static final String CONDITION = "condition";
+
+    private boolean verified = false;
+    private String linkedIdentity;
+    private String sub;
+    private String iss;
+    private String type;
+    private String value;
+
+    @ToString.Exclude
+    private String signer;
+
+    @ToString.Exclude
+    private String jwt;
+
+    @ToString.Exclude
+    private String prettyPayload;
+
+    public Ga4ghPassportVisa(String jwt) {
+        this.jwt = jwt;
+    }
+
+    public String getPrettyString() {
+        return prettyPayload + ", signed by " + signer;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Group.java b/src/main/java/cz/muni/ics/ga4gh/model/Group.java
new file mode 100644
index 0000000..49aea56
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Group.java
@@ -0,0 +1,45 @@
+package cz.muni.ics.ga4gh.model;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
+@NoArgsConstructor
+public class Group {
+
+    private Long id;
+
+    private Long parentGroupId;
+
+    private String name;
+
+    private String description;
+
+    private String uniqueGroupName;
+
+    private String uuid;
+
+    private Long voId;
+
+    private Map<String, JsonNode> attributes = new LinkedHashMap<>();
+
+    public Group(Long id, Long parentGroupId, String name, String description, String uniqueGroupName, String uuid, Long voId) {
+        this.id = id;
+        this.parentGroupId = parentGroupId;
+        this.name = name;
+        this.description = description;
+        this.uniqueGroupName = uniqueGroupName;
+        this.uuid = uuid;
+        this.voId = voId;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Member.java b/src/main/java/cz/muni/ics/ga4gh/model/Member.java
new file mode 100644
index 0000000..ca73483
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Member.java
@@ -0,0 +1,26 @@
+package cz.muni.ics.ga4gh.model;
+
+import cz.muni.ics.ga4gh.enums.MemberStatus;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+public class Member {
+
+    private Long id;
+
+    private Long userId;
+
+    private Long voId;
+
+    private MemberStatus status;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/PerunAttributeValue.java b/src/main/java/cz/muni/ics/ga4gh/model/PerunAttributeValue.java
new file mode 100644
index 0000000..541b63a
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/PerunAttributeValue.java
@@ -0,0 +1,173 @@
+package cz.muni.ics.ga4gh.model;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.BooleanNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.NumericNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import cz.muni.ics.ga4gh.exceptions.InconvertibleValueException;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class PerunAttributeValue {
+
+    public final static String STRING_TYPE = "java.lang.String";
+    public final static String INTEGER_TYPE = "java.lang.Integer";
+    public final static String BOOLEAN_TYPE = "java.lang.Boolean";
+    public final static String ARRAY_TYPE = "java.util.ArrayList";
+    public final static String MAP_TYPE = "java.util.LinkedHashMap";
+    public final static String LARGE_STRING_TYPE = "java.lang.LargeString";
+    public final static String LARGE_ARRAY_LIST_TYPE = "java.util.LargeArrayList";
+
+    private String attrName;
+    private String type;
+    private JsonNode value;
+
+    public void setAttrName(String attrName) {
+        if (!StringUtils.hasText(attrName)) {
+            throw new IllegalArgumentException("type can't be null or empty");
+        }
+
+        this.attrName = attrName;
+    }
+
+    public void setType(String type) {
+        if (!StringUtils.hasText(type)) {
+            throw new IllegalArgumentException("type can't be null or empty");
+        }
+
+        this.type = type;
+    }
+
+    public void setValue(String type, JsonNode value) {
+        if (isNullValue(value)) {
+            if (BOOLEAN_TYPE.equals(type)) {
+                value = JsonNodeFactory.instance.booleanNode(false);
+            } else if (ARRAY_TYPE.equals(type)) {
+                value = JsonNodeFactory.instance.arrayNode();
+            } else if (MAP_TYPE.equals(type)) {
+                value = JsonNodeFactory.instance.objectNode();
+            } else {
+                value = JsonNodeFactory.instance.nullNode();
+            }
+        }
+
+        this.value = value;
+    }
+
+    public String valueAsString() {
+        if ((STRING_TYPE.equals(type) || LARGE_STRING_TYPE.equals(type))) {
+            if (isNullValue(value)) {
+                return null;
+            } else if (value instanceof TextNode) {
+                return value.textValue();
+            }
+        }
+
+        return value.asText();
+    }
+
+    public Integer valueAsInteger() {
+        if (INTEGER_TYPE.equals(type)) {
+            if (isNullValue(value)) {
+                return null;
+            } else if (value instanceof NumericNode) {
+                return value.intValue();
+            }
+        }
+
+        throw this.inconvertible(Long.class.getName());
+    }
+
+    public boolean valueAsBoolean() {
+        if (BOOLEAN_TYPE.equals(type)) {
+            if (value == null || value instanceof NullNode) {
+                return false;
+            } else if (value instanceof BooleanNode) {
+                return value.asBoolean();
+            }
+        }
+
+        throw this.inconvertible(Boolean.class.getName());
+    }
+
+    public List<String> valueAsList() {
+        List<String> arr = new ArrayList<>();
+
+        if ((ARRAY_TYPE.equals(type) || LARGE_ARRAY_LIST_TYPE.equals(type))) {
+            if (isNullValue(value)) {
+                return null;
+            } else if (value instanceof ArrayNode) {
+                ArrayNode arrJson = (ArrayNode) value;
+                arrJson.forEach(item -> arr.add(item.asText()));
+            }
+        } else {
+            arr.add(this.valueAsString());
+        }
+
+        return arr;
+    }
+
+    public Map<String, String> valueAsMap() {
+        if (MAP_TYPE.equals(type)) {
+            if (isNullValue(value)) {
+                return new HashMap<>();
+            } else if (value instanceof ObjectNode) {
+                ObjectNode objJson = (ObjectNode) value;
+
+                Map<String, String> res = new HashMap<>();
+                Iterator<String> it = objJson.fieldNames();
+
+                while (it.hasNext()) {
+                    String key = it.next();
+                    res.put(key, objJson.get(key).asText());
+                }
+
+                return res;
+            }
+        }
+
+        throw this.inconvertible(Map.class.getName());
+    }
+
+    public JsonNode valueAsJson() {
+        return this.value;
+    }
+
+    public boolean isNullValue() {
+        return value == null ||
+                value instanceof NullNode ||
+                value.isNull() ||
+                "null".equalsIgnoreCase(value.asText());
+    }
+
+    public static boolean isNullValue(JsonNode value) {
+        return value == null ||
+                value instanceof NullNode ||
+                value.isNull() ||
+                "null".equalsIgnoreCase(value.asText());
+    }
+
+    private InconvertibleValueException inconvertible(String clazzName) {
+        return new InconvertibleValueException("Cannot convert value of attribute to " + clazzName +
+                " for object: " + this);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/Repo.java b/src/main/java/cz/muni/ics/ga4gh/model/Repo.java
new file mode 100644
index 0000000..23016ac
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/Repo.java
@@ -0,0 +1,27 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.List;
+
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+public class Repo {
+
+    private String name;
+
+    private String url;
+
+    private String jwks;
+
+    private List<RepoHeader> headers;
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/RepoHeader.java b/src/main/java/cz/muni/ics/ga4gh/model/RepoHeader.java
new file mode 100644
index 0000000..d8932c1
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/RepoHeader.java
@@ -0,0 +1,30 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+import java.io.IOException;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class RepoHeader implements ClientHttpRequestInterceptor {
+
+    private String header;
+
+    private String value;
+
+    @Override
+    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+        request.getHeaders().add(header, value);
+
+        return execution.execute(request, body);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/model/UserExtSource.java b/src/main/java/cz/muni/ics/ga4gh/model/UserExtSource.java
new file mode 100644
index 0000000..19fcda5
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/model/UserExtSource.java
@@ -0,0 +1,56 @@
+package cz.muni.ics.ga4gh.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.util.StringUtils;
+
+import java.sql.Timestamp;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class UserExtSource {
+
+    private Long id;
+
+    private ExtSource extSource;
+
+    private String login;
+
+    private int loa = 0;
+
+    private boolean persistent;
+
+    private Timestamp lastAccess;
+
+    public void setExtSource(ExtSource extSource) {
+        if (extSource == null) {
+            throw new IllegalArgumentException("extSource can't be null");
+        }
+
+        this.extSource = extSource;
+    }
+
+    public void setLogin(String login) {
+        if (!StringUtils.hasText(login)) {
+            throw new IllegalArgumentException("login can't be null or empty");
+        }
+
+        this.login = login;
+    }
+
+    public void setLoa(int loa) {
+        if (loa < 0) {
+            throw new IllegalArgumentException("loa has to be 0 or higher");
+        }
+
+        this.loa = loa;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/security/WebSecurityConfigurer.java b/src/main/java/cz/muni/ics/ga4gh/security/WebSecurityConfigurer.java
new file mode 100644
index 0000000..20d62d1
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/security/WebSecurityConfigurer.java
@@ -0,0 +1,50 @@
+package cz.muni.ics.ga4gh.security;
+
+import cz.muni.ics.ga4gh.config.BasicAuthConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+public class WebSecurityConfigurer {
+
+    private static final String ROLE_USER = "ROLE_USER";
+    private static final String PUBLIC_ENDPOINTS_PREFIX = "/public/**";
+
+    private final String username;
+    private final String password;
+
+    private final PasswordEncoder passwordEncoder;
+
+    @Autowired
+    public WebSecurityConfigurer(BasicAuthConfig config, PasswordEncoder passwordEncoder) {
+        this.username = config.getUsername();
+        this.password = config.getPassword();
+        this.passwordEncoder = passwordEncoder;
+    }
+
+    @Autowired
+    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+        auth.inMemoryAuthentication()
+                .withUser(username).password(passwordEncoder.encode(password))
+                .authorities(ROLE_USER);
+    }
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+
+        http.authorizeRequests()
+                .antMatchers(PUBLIC_ENDPOINTS_PREFIX).permitAll()
+                .anyRequest().authenticated()
+                .and()
+                .httpBasic();
+
+        http.headers().frameOptions().sameOrigin();
+
+        return http.build();
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/Ga4ghBrokerService.java b/src/main/java/cz/muni/ics/ga4gh/service/Ga4ghBrokerService.java
new file mode 100644
index 0000000..824d9fa
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/Ga4ghBrokerService.java
@@ -0,0 +1,8 @@
+package cz.muni.ics.ga4gh.service;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+public interface Ga4ghBrokerService {
+
+    ArrayNode getGa4ghPassport(String eppn);
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/JWTSigningAndValidationService.java b/src/main/java/cz/muni/ics/ga4gh/service/JWTSigningAndValidationService.java
new file mode 100644
index 0000000..9748662
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/JWTSigningAndValidationService.java
@@ -0,0 +1,37 @@
+package cz.muni.ics.ga4gh.service;
+
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jwt.SignedJWT;
+
+import java.util.Collection;
+import java.util.Map;
+
+public interface JWTSigningAndValidationService {
+
+    Map<String, JWK> getAllPublicKeys();
+
+    JWSAlgorithm getDefaultSigningAlgorithm();
+
+    Collection<JWSAlgorithm> getAllSigningAlgsSupported();
+
+    /**
+     * Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
+     * Use the default algorithm to sign.
+     *
+     * @param jwt the jwt to sign
+     * @throws IllegalStateException when calling default signing with no default signer ID set
+     */
+    void signJwt(SignedJWT jwt);
+
+    /**
+     * Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
+     * in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class.
+     *
+     * @param jwt the jwt to sign
+     * @param alg the name of the algorithm to use, as specified in JWS s.6
+     */
+    void signJwt(SignedJWT jwt, JWSAlgorithm alg);
+
+    String getDefaultSignerKeyId();
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/impl/Ga4GhBrokerBrokerServiceImpl.java b/src/main/java/cz/muni/ics/ga4gh/service/impl/Ga4GhBrokerBrokerServiceImpl.java
new file mode 100644
index 0000000..9999334
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/impl/Ga4GhBrokerBrokerServiceImpl.java
@@ -0,0 +1,61 @@
+package cz.muni.ics.ga4gh.service.impl;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import cz.muni.ics.ga4gh.adapters.PerunAdapter;
+import cz.muni.ics.ga4gh.config.AttributesConfig;
+import cz.muni.ics.ga4gh.config.BrokerConfig;
+import cz.muni.ics.ga4gh.exceptions.UserNotUniqueException;
+import cz.muni.ics.ga4gh.model.AttributeMapping;
+import cz.muni.ics.ga4gh.service.impl.brokers.Ga4ghBroker;
+import cz.muni.ics.ga4gh.service.Ga4ghBrokerService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Service
+@Slf4j
+public class Ga4GhBrokerBrokerServiceImpl implements Ga4ghBrokerService {
+
+    private final Ga4ghBroker broker;
+
+    private final PerunAdapter adapter;
+
+    private final List<String> attributesToSearch;
+
+    private final Map<String, AttributeMapping> attributes;
+
+    @Autowired
+    public Ga4GhBrokerBrokerServiceImpl(Ga4ghBroker broker, PerunAdapter adapter, BrokerConfig brokerConfig, AttributesConfig attributesConfig) {
+        this.broker = broker;
+        this.adapter = adapter;
+        this.attributesToSearch = brokerConfig.getAttributesToSearch();
+        this.attributes = attributesConfig.getAttributeMappings();
+    }
+
+    @Override
+    public ArrayNode getGa4ghPassport(String eppn) {
+        Set<Long> userIds = new HashSet<>();
+
+        for (String attrName : attributesToSearch) {
+            if (attributes.get(attrName) != null) {
+                userIds.addAll(adapter.getAdapterPrimary().getUserIdsByAttributeValue(attributes.get(attrName), eppn));
+            }
+        }
+
+        if (userIds.isEmpty()) {
+            log.debug("User {} not found", eppn);
+            return null;
+        }
+
+        if (userIds.size() > 1) {
+            throw new UserNotUniqueException("There are more users found by " + eppn + " - " + String.join(", ", userIds.toString()));
+        }
+
+        return broker.constructGa4ghPassportVisa(userIds.iterator().next(), eppn);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/impl/JWTSigningAndValidationServiceImpl.java b/src/main/java/cz/muni/ics/ga4gh/service/impl/JWTSigningAndValidationServiceImpl.java
new file mode 100644
index 0000000..0fc7b3b
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/impl/JWTSigningAndValidationServiceImpl.java
@@ -0,0 +1,227 @@
+package cz.muni.ics.ga4gh.service.impl;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSProvider;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.ECDSASigner;
+import com.nimbusds.jose.crypto.ECDSAVerifier;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.crypto.MACVerifier;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.jwk.ECKey;
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.OctetSequenceKey;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jwt.SignedJWT;
+import cz.muni.ics.ga4gh.jose.keystore.JWKSetKeyStore;
+import cz.muni.ics.ga4gh.service.JWTSigningAndValidationService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+@Slf4j
+@Service
+public class JWTSigningAndValidationServiceImpl implements JWTSigningAndValidationService {
+
+    private final Map<String, JWSSigner> signers = new HashMap<>();
+    private final Map<String, JWSVerifier> verifiers = new HashMap<>();
+
+    private String defaultSignerKeyId;
+    private JWSAlgorithm defaultAlgorithm;
+    private Map<String, JWK> keys = new HashMap<>();
+
+    /**
+     * Build this service based on the keys given. All public keys will be used
+     * to make verifiers, all private keys will be used to make signers.
+     *
+     * @param keys A map of key identifier to key.
+     */
+    public JWTSigningAndValidationServiceImpl(Map<String, JWK> keys) {
+        this.keys = keys;
+        buildSignersAndVerifiers();
+    }
+
+    /**
+     * Build this service based on the given keystore. All keys must have a key
+     * id ({@code kid}) field in order to be used.
+     *
+     * @param keyStore The keystore to load all keys from.
+     */
+    @Autowired
+    public JWTSigningAndValidationServiceImpl(JWKSetKeyStore keyStore) {
+        if (keyStore!= null && keyStore.getJwkSet() != null) {
+            for (JWK key : keyStore.getKeys()) {
+                if (!StringUtils.isEmpty(key.getKeyID())) {
+                    this.keys.put(key.getKeyID(), key);
+                } else {
+                    String fakeKid = UUID.randomUUID().toString();
+                    this.keys.put(fakeKid, key);
+                }
+            }
+        }
+
+        buildSignersAndVerifiers();
+
+        this.defaultSignerKeyId = keyStore.getKeys().get(0).getKeyID();
+        setDefaultSigningAlgorithmName(keyStore.getKeys().get(0).getAlgorithm().getName());
+    }
+
+    @Override
+    public String getDefaultSignerKeyId() {
+        return defaultSignerKeyId;
+    }
+
+    public void setDefaultSignerKeyId(String defaultSignerId) {
+        this.defaultSignerKeyId = defaultSignerId;
+    }
+
+    @Override
+    public JWSAlgorithm getDefaultSigningAlgorithm() {
+        return defaultAlgorithm;
+    }
+
+    public void setDefaultSigningAlgorithmName(String algName) {
+        defaultAlgorithm = JWSAlgorithm.parse(algName);
+    }
+
+    public String getDefaultSigningAlgorithmName() {
+        if (defaultAlgorithm != null) {
+            return defaultAlgorithm.getName();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void signJwt(SignedJWT jwt) {
+        if (getDefaultSignerKeyId() == null) {
+            throw new IllegalStateException("Tried to call default signing with no default signer ID set");
+        }
+
+        JWSSigner signer = signers.get(getDefaultSignerKeyId());
+
+        try {
+            jwt.sign(signer);
+        } catch (JOSEException e) {
+            log.error("Failed to sign JWT, error was: ", e);
+        }
+    }
+
+    @Override
+    public void signJwt(SignedJWT jwt, JWSAlgorithm alg) {
+        JWSSigner signer = null;
+
+        for (JWSSigner s : signers.values()) {
+            if (s.supportedJWSAlgorithms().contains(alg)) {
+                signer = s;
+                break;
+            }
+        }
+
+        if (signer == null) {
+            log.error("No matching algorithm found for alg={}", alg);
+        } else {
+            try {
+                jwt.sign(signer);
+            } catch (JOSEException e) {
+                log.error("Failed to sign JWT, error was: ", e);
+            }
+        }
+    }
+
+    @Override
+    public Map<String, JWK> getAllPublicKeys() {
+        Map<String, JWK> pubKeys = new HashMap<>();
+
+        keys.keySet().forEach(keyId -> {
+            JWK key = keys.get(keyId);
+            JWK pub = key.toPublicJWK();
+            if (pub != null) {
+                pubKeys.put(keyId, pub);
+            }
+        });
+
+        return pubKeys;
+    }
+
+    @Override
+    public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
+        Set<JWSAlgorithm> algs = new HashSet<>();
+        signers.values().stream().map(JWSProvider::supportedJWSAlgorithms).forEach(algs::addAll);
+        verifiers.values().stream().map(JWSProvider::supportedJWSAlgorithms).forEach(algs::addAll);
+
+        return algs;
+    }
+
+    private void buildSignersAndVerifiers() {
+        for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) {
+            String id = jwkEntry.getKey();
+            JWK jwk = jwkEntry.getValue();
+
+            try {
+                if (jwk instanceof RSAKey) {
+                    processRSAKey(signers, verifiers, jwk, id);
+                } else if (jwk instanceof ECKey) {
+                    processECKey(signers, verifiers, jwk, id);
+                } else if (jwk instanceof OctetSequenceKey) {
+                    processOctetKey(signers, verifiers, jwk, id);
+                } else {
+                    log.warn("Unknown key type: {}", jwk);
+                }
+            } catch (JOSEException e) {
+                log.warn("Exception loading signer/verifier", e);
+            }
+        }
+
+        if (defaultSignerKeyId == null && keys.size() == 1) {
+            setDefaultSignerKeyId(keys.keySet().iterator().next());
+        }
+    }
+
+    private void processOctetKey(Map<String, JWSSigner> signers, Map<String, JWSVerifier> verifiers, JWK jwk, String id)
+            throws JOSEException
+    {
+        if (jwk.isPrivate()) {
+            MACSigner signer = new MACSigner((OctetSequenceKey) jwk);
+            signers.put(id, signer);
+        }
+
+        MACVerifier verifier = new MACVerifier((OctetSequenceKey) jwk);
+        verifiers.put(id, verifier);
+    }
+
+    private void processECKey(Map<String, JWSSigner> signers, Map<String, JWSVerifier> verifiers, JWK jwk, String id)
+            throws JOSEException
+    {
+        if (jwk.isPrivate()) {
+            ECDSASigner signer = new ECDSASigner((ECKey) jwk);
+            signers.put(id, signer);
+        }
+
+        ECDSAVerifier verifier = new ECDSAVerifier((ECKey) jwk);
+        verifiers.put(id, verifier);
+    }
+
+    private void processRSAKey(Map<String, JWSSigner> signers, Map<String, JWSVerifier> verifiers, JWK jwk, String id)
+            throws JOSEException
+    {
+        if (jwk.isPrivate()) {
+            RSASSASigner signer = new RSASSASigner((RSAKey) jwk);
+            signers.put(id, signer);
+        }
+
+        RSASSAVerifier verifier = new RSASSAVerifier((RSAKey) jwk);
+        verifiers.put(id, verifier);
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/BbmriGa4ghBroker.java b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/BbmriGa4ghBroker.java
new file mode 100644
index 0000000..f9a89b7
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/BbmriGa4ghBroker.java
@@ -0,0 +1,204 @@
+package cz.muni.ics.ga4gh.service.impl.brokers;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import cz.muni.ics.ga4gh.adapters.PerunAdapter;
+import cz.muni.ics.ga4gh.config.BrokerConfig;
+import cz.muni.ics.ga4gh.config.Ga4ghConfig;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.Ga4ghClaimRepository;
+import cz.muni.ics.ga4gh.service.JWTSigningAndValidationService;
+import cz.muni.ics.ga4gh.utils.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_PEER;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SELF;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SO;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SYSTEM;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_ACCEPTED_TERMS_AND_POLICIES;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_AFFILIATION_AND_ROLE;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_LINKED_IDENTITIES;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_RESEARCHER_STATUS;
+
+@Service
+@Profile("bbmri")
+public class BbmriGa4ghBroker extends Ga4ghBroker {
+
+    private static final String BONA_FIDE_URL = "https://doi.org/10.1038/s41431-018-0219-y";
+    private static final String BBMRI_ERIC_ORG_URL = "https://www.bbmri-eric.eu/";
+    private static final String BBMRI_ID = "bbmri_id";
+    private static final String FACULTY_AT = "faculty@";
+
+    private final String bonaFideStatusAttr;
+    private final String groupAffiliationsAttr;
+    private final Long termsAndPoliciesGroupId;
+
+    @Autowired
+    public BbmriGa4ghBroker(BrokerConfig brokerConfig, PerunAdapter adapter, JWTSigningAndValidationService jwtService, Ga4ghConfig ga4ghConfig) throws URISyntaxException, MalformedURLException {
+        super(adapter, jwtService, ga4ghConfig, brokerConfig);
+
+        bonaFideStatusAttr = brokerConfig.getBonaFideStatusAttr();
+        groupAffiliationsAttr = brokerConfig.getGroupAffiliationsAttr();
+        termsAndPoliciesGroupId = Objects.requireNonNullElse(brokerConfig.getTermsAndPoliciesGroupId(), 10432L);
+    }
+
+    @Override
+    protected void addAffiliationAndRoles(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId)
+    {
+        //by=system for users with affiliation asserted by their IdP (set in UserExtSource attribute "affiliation")
+        if (affiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: affiliations) {
+            //expires 1 year after the last login from the IdP asserting the affiliation
+            long expires = Utils.getOneYearExpires(affiliation.getAsserted());
+            if (expires < now) {
+                continue;
+            }
+
+            JsonNode visa = createPassportVisa(TYPE_AFFILIATION_AND_ROLE, sub, userId, affiliation.getValue(), affiliation.getSource(), BY_SYSTEM, affiliation.getAsserted(), expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    @Override
+    protected void addAcceptedTermsAndPolicies(long now, ArrayNode passport, Long userId, String sub) {
+        //by=self for members of the group 10432 "Bona Fide Researchers"
+        boolean userInGroup = adapter.isUserInGroup(userId, termsAndPoliciesGroupId);
+        if (!userInGroup) {
+            return;
+        }
+
+        long asserted = now;
+        if (bonaFideStatusAttr != null) {
+            String bonaFideStatusCreatedAt = adapter.getAdapterRpc().getUserAttributeCreatedAt(userId, bonaFideStatusAttr);
+            if (bonaFideStatusCreatedAt != null) {
+                asserted = Timestamp.valueOf(bonaFideStatusCreatedAt).getTime() / 1000L;
+            }
+        }
+
+        long expires = Utils.getExpires(asserted, 100L);
+        if (expires < now) {
+            return;
+        }
+
+        JsonNode visa = createPassportVisa(TYPE_ACCEPTED_TERMS_AND_POLICIES, sub, userId, BONA_FIDE_URL, BBMRI_ERIC_ORG_URL, BY_SELF, asserted, expires, null);
+        if (visa != null) {
+            passport.add(visa);
+        }
+    }
+
+    @Override
+    protected void addResearcherStatuses(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId)
+    {
+        addResearcherStatusFromBonaFideAttribute(now, passport, userId, sub);
+        addResearcherStatusFromAffiliation(affiliations, now, passport, sub, userId);
+        addResearcherStatusGroupAffiliations(now, passport, sub, userId);
+    }
+
+    @Override
+    protected void addControlledAccessGrants(long now, ArrayNode passport, String sub, Long userId) {
+        if (claimRepositories.isEmpty()) {
+            return;
+        }
+
+        Set<String> linkedIdentities = new HashSet<>();
+        for (Ga4ghClaimRepository repo: claimRepositories) {
+            callPermissionsJwtAPI(repo, Collections.singletonMap(BBMRI_ID, sub), passport, linkedIdentities);
+        }
+
+        if (linkedIdentities.isEmpty()) {
+            return;
+        }
+
+        for (String linkedIdentity : linkedIdentities) {
+            long expires = Utils.getOneYearExpires(now);
+
+            JsonNode visa = createPassportVisa(TYPE_LINKED_IDENTITIES, sub, userId, linkedIdentity, BBMRI_ERIC_ORG_URL, BY_SYSTEM, now, expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    private void addResearcherStatusFromBonaFideAttribute(long now, ArrayNode passport, Long userId, String sub)
+    {
+        //by=peer for users with attribute elixirBonaFideStatusREMS
+        String bbmriBonaFideStatusCreatedAt = adapter.getAdapterRpc().getUserAttributeCreatedAt(userId, bonaFideStatusAttr);
+
+        if (bbmriBonaFideStatusCreatedAt == null) {
+            return;
+        }
+
+        long asserted = Timestamp.valueOf(bbmriBonaFideStatusCreatedAt).getTime() / 1000L;
+        long expires = Utils.getOneYearExpires(asserted);
+
+        if (expires > now) {
+            JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, BBMRI_ERIC_ORG_URL, BY_PEER, asserted, expires, null);
+
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    private void addResearcherStatusFromAffiliation(List<Affiliation> affiliations, long now, ArrayNode passport, String sub, Long userId)
+    {
+        //by=system for users with faculty affiliation asserted by their IdP (set in UserExtSource attribute "affiliation")
+        if (affiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: affiliations) {
+            if (!StringUtils.startsWithIgnoreCase(affiliation.getValue(), FACULTY_AT)) {
+                continue;
+            }
+
+            long expires = Utils.getOneYearExpires(affiliation.getAsserted());
+            if (expires < now) {
+                continue;
+            }
+
+            JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, affiliation.getSource(), BY_SYSTEM, affiliation.getAsserted(), expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    private void addResearcherStatusGroupAffiliations(long now, ArrayNode passport, String sub, Long userId) {
+        //by=so for users with faculty affiliation asserted by membership in a group with groupAffiliations attribute
+        List<Affiliation> groupAffiliations = adapter.getGroupAffiliations(userId, groupAffiliationsAttr);
+        if (groupAffiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: groupAffiliations) {
+            if (!StringUtils.startsWithIgnoreCase(affiliation.getValue(), FACULTY_AT)) {
+                continue;
+            }
+
+            long expires = Utils.getOneYearExpires(now);
+
+            JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, BBMRI_ERIC_ORG_URL, BY_SO, affiliation.getAsserted(), expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/ElixirGa4ghBroker.java b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/ElixirGa4ghBroker.java
new file mode 100644
index 0000000..cdef905
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/ElixirGa4ghBroker.java
@@ -0,0 +1,201 @@
+package cz.muni.ics.ga4gh.service.impl.brokers;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import cz.muni.ics.ga4gh.adapters.PerunAdapter;
+import cz.muni.ics.ga4gh.config.BrokerConfig;
+import cz.muni.ics.ga4gh.config.Ga4ghConfig;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.Ga4ghClaimRepository;
+import cz.muni.ics.ga4gh.service.JWTSigningAndValidationService;
+import cz.muni.ics.ga4gh.utils.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_PEER;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SELF;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SO;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.BY_SYSTEM;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_ACCEPTED_TERMS_AND_POLICIES;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_AFFILIATION_AND_ROLE;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_LINKED_IDENTITIES;
+import static cz.muni.ics.ga4gh.model.Ga4ghPassportVisa.TYPE_RESEARCHER_STATUS;
+
+@Service
+@Profile("elixir")
+public class ElixirGa4ghBroker extends Ga4ghBroker {
+
+    private static final String BONA_FIDE_URL = "https://doi.org/10.1038/s41431-018-0219-y";
+    private static final String ELIXIR_ORG_URL = "https://elixir-europe.org/";
+    private static final String ELIXIR_ID = "elixir_id";
+    private static final String FACULTY_AT = "faculty@";
+
+    private final String bonaFideStatusAttr;
+    private final String bonaFideStatusREMSAttr;
+    private final String groupAffiliationsAttr;
+    private final Long termsAndPoliciesGroupId;
+
+    @Autowired
+    public ElixirGa4ghBroker(BrokerConfig brokerConfig, Ga4ghConfig ga4ghConfig, PerunAdapter adapter, JWTSigningAndValidationService jwtService) throws URISyntaxException, MalformedURLException {
+        super(adapter, jwtService, ga4ghConfig, brokerConfig);
+
+        bonaFideStatusAttr = brokerConfig.getBonaFideStatusAttr();
+        bonaFideStatusREMSAttr = brokerConfig.getBonaFideStatusRemsAttr();
+        groupAffiliationsAttr = brokerConfig.getGroupAffiliationsAttr();
+        termsAndPoliciesGroupId = Objects.requireNonNullElse(brokerConfig.getTermsAndPoliciesGroupId(), 10432L);
+    }
+
+    @Override
+    protected void addAffiliationAndRoles(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId) {
+        if (affiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: affiliations) {
+            long expires = Utils.getOneYearExpires(affiliation.getAsserted());
+
+            if (expires < now) {
+                continue;
+            }
+
+            JsonNode visa = createPassportVisa(TYPE_AFFILIATION_AND_ROLE, sub, userId, affiliation.getValue(),
+                    affiliation.getSource(), BY_SYSTEM, affiliation.getAsserted(), expires, null);
+
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    @Override
+    protected void addAcceptedTermsAndPolicies(long now, ArrayNode passport, Long userId, String sub) {
+        boolean userInGroup = adapter.isUserInGroup(userId, termsAndPoliciesGroupId);
+        if (!userInGroup) {
+            return;
+        }
+
+        long asserted = now;
+        if (bonaFideStatusAttr != null) {
+            String bonaFideStatusCreatedAt = adapter.getAdapterRpc().getUserAttributeCreatedAt(userId, bonaFideStatusAttr);
+            if (bonaFideStatusCreatedAt != null) {
+                asserted = Timestamp.valueOf(bonaFideStatusCreatedAt).getTime() / 1000L;
+            }
+        }
+
+        long expires = Utils.getExpires(asserted, 100L);
+        if (expires < now) {
+            return;
+        }
+
+        JsonNode visa = createPassportVisa(TYPE_ACCEPTED_TERMS_AND_POLICIES, sub, userId, BONA_FIDE_URL, ELIXIR_ORG_URL, BY_SELF, asserted, expires, null);
+        if (visa != null) {
+            passport.add(visa);
+        }
+
+    }
+
+    @Override
+    protected void addResearcherStatuses(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId)
+    {
+        addResearcherStatusFromBonaFideAttribute(now, passport, sub, userId);
+        addResearcherStatusFromAffiliation(affiliations, now, passport, sub, userId);
+        addResearcherStatusGroupAffiliations(now, passport, userId, sub);
+    }
+
+    @Override
+    protected void addControlledAccessGrants(long now, ArrayNode passport, String sub, Long userId) {
+        if (claimRepositories.isEmpty()) {
+            return;
+        }
+        Set<String> linkedIdentities = new HashSet<>();
+        for (Ga4ghClaimRepository repo: claimRepositories) {
+            callPermissionsJwtAPI(repo, Collections.singletonMap(ELIXIR_ID, sub), passport, linkedIdentities);
+        }
+        if (linkedIdentities.isEmpty()) {
+            return;
+        }
+        for (String linkedIdentity : linkedIdentities) {
+            long expires = Utils.getOneYearExpires(now);
+            JsonNode visa = createPassportVisa(TYPE_LINKED_IDENTITIES, sub, userId, linkedIdentity,
+                    ELIXIR_ORG_URL, BY_SYSTEM, now, expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    private void addResearcherStatusFromBonaFideAttribute(long now, ArrayNode passport, String sub, Long userId)
+    {
+        String elixirBonaFideStatusREMSCreatedAt = adapter.getAdapterRpc().getUserAttributeCreatedAt(userId, bonaFideStatusREMSAttr);
+
+        if (elixirBonaFideStatusREMSCreatedAt == null) {
+            return;
+        }
+
+        long asserted = Timestamp.valueOf(elixirBonaFideStatusREMSCreatedAt).getTime() / 1000L;
+        long expires = Utils.getOneYearExpires(asserted);
+
+        if (expires < now) {
+            return;
+        }
+
+        JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, ELIXIR_ORG_URL, BY_PEER, asserted, expires, null);
+        if (visa != null) {
+            passport.add(visa);
+        }
+    }
+
+    private void addResearcherStatusFromAffiliation(List<Affiliation> affiliations, long now, ArrayNode passport, String sub, Long userId)
+    {
+        if (affiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: affiliations) {
+            if (!StringUtils.startsWithIgnoreCase(affiliation.getValue(), FACULTY_AT)) {
+                continue;
+            }
+
+            long expires = Utils.getOneYearExpires(affiliation.getAsserted());
+            if (expires < now) {
+                continue;
+            }
+
+            JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, affiliation.getSource(), BY_SYSTEM, affiliation.getAsserted(), expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+
+    private void addResearcherStatusGroupAffiliations(long now, ArrayNode passport, Long userId, String sub) {
+        List<Affiliation> groupAffiliations = adapter.getGroupAffiliations(userId, groupAffiliationsAttr);
+        if (groupAffiliations == null) {
+            return;
+        }
+
+        for (Affiliation affiliation: groupAffiliations) {
+            if (!StringUtils.startsWithIgnoreCase(affiliation.getValue(), FACULTY_AT)) {
+                continue;
+            }
+
+            long expires = Utils.getOneYearExpires(now);
+
+            JsonNode visa = createPassportVisa(TYPE_RESEARCHER_STATUS, sub, userId, BONA_FIDE_URL, ELIXIR_ORG_URL, BY_SO, affiliation.getAsserted(), expires, null);
+            if (visa != null) {
+                passport.add(visa);
+            }
+        }
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/Ga4ghBroker.java b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/Ga4ghBroker.java
new file mode 100644
index 0000000..51e8cc5
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/service/impl/brokers/Ga4ghBroker.java
@@ -0,0 +1,223 @@
+package cz.muni.ics.ga4gh.service.impl.brokers;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.jwk.source.RemoteJWKSet;
+import com.nimbusds.jose.proc.SecurityContext;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import cz.muni.ics.ga4gh.adapters.PerunAdapter;
+import cz.muni.ics.ga4gh.config.BrokerConfig;
+import cz.muni.ics.ga4gh.config.Ga4ghConfig;
+import cz.muni.ics.ga4gh.model.Affiliation;
+import cz.muni.ics.ga4gh.model.Ga4ghClaimRepository;
+import cz.muni.ics.ga4gh.model.Ga4ghPassportVisa;
+import cz.muni.ics.ga4gh.service.JWTSigningAndValidationService;
+import cz.muni.ics.ga4gh.utils.Utils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.web.client.HttpClientErrorException;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+@Slf4j
+public abstract class Ga4ghBroker {
+
+    public static final String GA4GH_CLAIM = "ga4gh_passport_v1";
+    public static final String JSON = "json";
+
+    protected final List<Ga4ghClaimRepository> claimRepositories = new ArrayList<>();
+    protected final Map<URI, RemoteJWKSet<SecurityContext>> remoteJwkSets = new HashMap<>();
+    protected final Map<URI, String> signers = new HashMap<>();
+    protected final ObjectMapper mapper = new ObjectMapper();
+
+    private final String issuer;
+    private final URI jku;
+    protected PerunAdapter adapter;
+
+    protected JWTSigningAndValidationService jwtService;
+
+    private final String affiliationsAttr;
+
+    private final String orgUrlAttr;
+
+    public Ga4ghBroker(PerunAdapter adapter, JWTSigningAndValidationService jwtService, Ga4ghConfig config, BrokerConfig brokerConfig) throws URISyntaxException, MalformedURLException {
+        this.adapter = adapter;
+        this.jwtService = jwtService;
+        this.affiliationsAttr = brokerConfig.getAffiliationsAttr();
+        this.orgUrlAttr = brokerConfig.getOrgUrlAttr();
+        this.issuer = brokerConfig.getIssuer();
+        this.jku = new URL(brokerConfig.getJku()).toURI();
+
+        Utils.parseConfigFile(config, claimRepositories, remoteJwkSets, signers);
+    }
+
+    public ArrayNode constructGa4ghPassportVisa(Long userId, String sub) {
+        List<Affiliation> affiliations = adapter.getAdapterRpc().getUserExtSourcesAffiliations(userId, affiliationsAttr, orgUrlAttr);
+
+        ArrayNode ga4gh_passport_v1 = JsonNodeFactory.instance.arrayNode();
+        long now = Instant.now().getEpochSecond();
+
+        addAffiliationAndRoles(now, ga4gh_passport_v1, affiliations, sub, userId);
+        addAcceptedTermsAndPolicies(now, ga4gh_passport_v1, userId, sub);
+        addResearcherStatuses(now, ga4gh_passport_v1, affiliations, sub, userId);
+        addControlledAccessGrants(now, ga4gh_passport_v1, sub, userId);
+
+        return ga4gh_passport_v1;
+    }
+
+
+    protected abstract void addAffiliationAndRoles(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId);
+
+    protected abstract void addAcceptedTermsAndPolicies(long now, ArrayNode passport, Long userId, String sub);
+
+    protected abstract void addResearcherStatuses(long now, ArrayNode passport, List<Affiliation> affiliations, String sub, Long userId);
+
+    protected abstract void addControlledAccessGrants(long now, ArrayNode passport, String sub, Long userId);
+
+    protected JsonNode createPassportVisa(String type, String sub, Long userId, String value, String source,
+                                          String by, long asserted, long expires, JsonNode condition)
+    {
+        long now = System.currentTimeMillis() / 1000L;
+
+        if (asserted > now) {
+            log.warn("Visa asserted in future, it will be ignored!");
+            log.debug("Visa information: perunUserId={}, sub={}, type={}, value={}, source={}, by={}, asserted={}",
+                    userId, sub, type, value, source, by, Instant.ofEpochSecond(asserted));
+
+            return null;
+        }
+
+        if (expires <= now) {
+            log.warn("Visa is expired, it will be ignored!");
+            log.debug("Visa information: perunUserId={}, sub={}, type={}, value={}, source={}, by={}, expired={}",
+                    userId, sub, type, value, source, by, Instant.ofEpochSecond(expires));
+
+            return null;
+        }
+
+        Map<String, Object> passportVisaObject = new HashMap<>();
+        passportVisaObject.put(Ga4ghPassportVisa.TYPE, type);
+        passportVisaObject.put(Ga4ghPassportVisa.ASSERTED, asserted);
+        passportVisaObject.put(Ga4ghPassportVisa.VALUE, value);
+        passportVisaObject.put(Ga4ghPassportVisa.SOURCE, source);
+        passportVisaObject.put(Ga4ghPassportVisa.BY, by);
+
+        if (condition != null && !condition.isNull() && !condition.isMissingNode()) {
+            passportVisaObject.put(Ga4ghPassportVisa.CONDITION, condition);
+        }
+
+        JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.parse(jwtService.getDefaultSigningAlgorithm().getName()))
+                .keyID(jwtService.getDefaultSignerKeyId())
+                .type(JOSEObjectType.JWT)
+                .jwkURL(jku)
+                .build();
+
+        JWTClaimsSet jwtClaimsSet = new JWTClaimsSet.Builder()
+                .issuer(issuer)
+                .issueTime(new Date())
+                .expirationTime(new Date(expires * 1000L))
+                .subject(sub)
+                .jwtID(UUID.randomUUID().toString())
+                .claim(Ga4ghPassportVisa.GA4GH_VISA_V1, passportVisaObject)
+                .build();
+
+        SignedJWT myToken = new SignedJWT(jwsHeader, jwtClaimsSet);
+        jwtService.signJwt(myToken);
+
+        return JsonNodeFactory.instance.textNode(myToken.serialize());
+    }
+
+    protected void callPermissionsJwtAPI(Ga4ghClaimRepository repo,
+                                         Map<String, String> uriVariables,
+                                         ArrayNode passport,
+                                         Set<String> linkedIdentities)
+    {
+        log.debug("GA4GH: {}", uriVariables);
+        JsonNode response = callHttpJsonAPI(repo, uriVariables);
+        if (response != null) {
+            JsonNode visas = response.path(GA4GH_CLAIM);
+            if (visas.isArray()) {
+                for (JsonNode visaNode : visas) {
+                    if (visaNode.isTextual()) {
+                        Ga4ghPassportVisa visa = Utils.parseAndVerifyVisa(visaNode.asText(), signers, remoteJwkSets, mapper);
+                        if (visa.isVerified()) {
+                            log.debug("Adding a visa to passport: {}", visa);
+                            passport.add(passport.textNode(visa.getJwt()));
+                            linkedIdentities.add(visa.getLinkedIdentity());
+                        } else {
+                            log.warn("Skipping visa: {}", visa);
+                        }
+                    } else {
+                        log.warn("Element of {} is not a String: {}", GA4GH_CLAIM, visaNode);
+                    }
+                }
+            } else {
+                log.warn("{} is not an array in {}", GA4GH_CLAIM, response);
+            }
+        }
+    }
+
+    @SuppressWarnings("Duplicates")
+    private static JsonNode callHttpJsonAPI(Ga4ghClaimRepository repo, Map<String, String> uriVariables) {
+        //get permissions data
+        try {
+            JsonNode result;
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug("Calling Permissions API at {}", repo.getRestTemplate().getUriTemplateHandler().expand(repo.getActionURL(), uriVariables));
+                }
+
+                result = repo.getRestTemplate().getForObject(repo.getActionURL(), JsonNode.class, uriVariables);
+            } catch (HttpClientErrorException ex) {
+                MediaType contentType = ex.getResponseHeaders().getContentType();
+                String body = ex.getResponseBodyAsString();
+
+                log.error("HTTP ERROR: {}, URL: {}, Content-Type: {}", ex.getRawStatusCode(), repo.getActionURL(), contentType);
+
+                if (ex.getRawStatusCode() == 404) {
+                    log.warn("Got status 404 from Permissions endpoint {}, ELIXIR AAI user is not linked to user at Permissions API",
+                            repo.getActionURL());
+
+                    return null;
+                }
+
+                if (JSON.equals(contentType.getSubtype())) {
+                    try {
+                        log.error(new ObjectMapper().readValue(body, JsonNode.class).path("message").asText());
+                    } catch (IOException e) {
+                        log.error("cannot parse error message from JSON", e);
+                    }
+                } else {
+                    log.error("cannot make REST call, exception: {} message: {}", ex.getClass().getName(), ex.getMessage());
+                }
+
+                return null;
+            }
+            log.debug("Permissions API response: {}", result);
+
+            return result;
+        } catch (Exception ex) {
+            log.error("Cannot get dataset permissions", ex);
+        }
+
+        return null;
+    }
+}
diff --git a/src/main/java/cz/muni/ics/ga4gh/utils/Utils.java b/src/main/java/cz/muni/ics/ga4gh/utils/Utils.java
new file mode 100644
index 0000000..7037cb9
--- /dev/null
+++ b/src/main/java/cz/muni/ics/ga4gh/utils/Utils.java
@@ -0,0 +1,218 @@
+package cz.muni.ics.ga4gh.utils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jose.Payload;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.JWKMatcher;
+import com.nimbusds.jose.jwk.JWKSelector;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jose.jwk.source.RemoteJWKSet;
+import com.nimbusds.jose.proc.SecurityContext;
+import com.nimbusds.jwt.JWTParser;
+import com.nimbusds.jwt.SignedJWT;
+import cz.muni.ics.ga4gh.config.Ga4ghConfig;
+import cz.muni.ics.ga4gh.model.Ga4ghClaimRepository;
+import cz.muni.ics.ga4gh.model.Ga4ghPassportVisa;
+import cz.muni.ics.ga4gh.model.Repo;
+import cz.muni.ics.ga4gh.model.RepoHeader;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.InterceptingClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class Utils {
+
+    public static void parseConfigFile(Ga4ghConfig config,
+                                       List<Ga4ghClaimRepository> claimRepositories,
+                                       Map<URI, RemoteJWKSet<SecurityContext>> remoteJwkSets,
+                                       Map<URI, String> signers)
+    {
+        for (Repo repo : config.getRepos()) {
+            initializeRepo(repo, claimRepositories);
+            initializeSigner(signers, remoteJwkSets, repo.getName(), repo.getJwks());
+        }
+    }
+
+    public static Ga4ghPassportVisa parseAndVerifyVisa(String jwtString,
+                                                       Map<URI, String> signers,
+                                                       Map<URI, RemoteJWKSet<SecurityContext>> remoteJwkSets,
+                                                       ObjectMapper mapper)
+    {
+        Ga4ghPassportVisa visa = new Ga4ghPassportVisa(jwtString);
+
+        try {
+            SignedJWT signedJWT = (SignedJWT) JWTParser.parse(jwtString);
+            URI jku = signedJWT.getHeader().getJWKURL();
+
+            if (jku == null) {
+                log.error("JKU is missing in JWT header");
+                return visa;
+            }
+
+            visa.setSigner(signers.get(jku));
+            RemoteJWKSet<SecurityContext> remoteJWKSet = remoteJwkSets.get(jku);
+
+            if (remoteJWKSet == null) {
+                log.error("JKU '{}' is not among trusted key sets", jku);
+                return visa;
+            }
+
+            List<JWK> keys = remoteJWKSet.get(new JWKSelector(
+                    new JWKMatcher.Builder().keyID(signedJWT.getHeader().getKeyID()).build()), null);
+
+            RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) keys.get(0)).toRSAPublicKey());
+            visa.setVerified(signedJWT.verify(verifier));
+
+            if (visa.isVerified()) {
+                Utils.processPayload(mapper, visa, signedJWT.getPayload());
+            }
+        } catch (Exception ex) {
+            log.error("Visa '{}' cannot be parsed and verified", jwtString, ex);
+        }
+        return visa;
+    }
+
+    public static void processPayload(ObjectMapper mapper, Ga4ghPassportVisa visa, Payload payload)
+            throws IOException
+    {
+        JsonNode doc = mapper.readValue(payload.toString(), JsonNode.class);
+        checkVisaKey(visa, doc, Ga4ghPassportVisa.SUB);
+        checkVisaKey(visa, doc, Ga4ghPassportVisa.EXP);
+        checkVisaKey(visa, doc, Ga4ghPassportVisa.ISS);
+
+        JsonNode visa_v1 = doc.path(Ga4ghPassportVisa.GA4GH_VISA_V1);
+        if (visa_v1.isMissingNode() || visa_v1.isNull() || visa_v1.isEmpty()) {
+            log.warn("Nothing available in '{}', considering visa as not verified", Ga4ghPassportVisa.GA4GH_VISA_V1);
+            visa.setVerified(false);
+            return;
+        }
+
+        checkVisaKey(visa, visa_v1, Ga4ghPassportVisa.TYPE);
+        checkVisaKey(visa, visa_v1, Ga4ghPassportVisa.ASSERTED);
+        checkVisaKey(visa, visa_v1, Ga4ghPassportVisa.VALUE);
+        checkVisaKey(visa, visa_v1, Ga4ghPassportVisa.SOURCE);
+        checkVisaKey(visa, visa_v1, Ga4ghPassportVisa.BY);
+
+        if (!visa.isVerified()) {
+            return;
+        }
+
+        long exp = doc.get(Ga4ghPassportVisa.EXP).asLong();
+        if (exp < Instant.now().getEpochSecond()) {
+            log.warn("visa expired on {}", isoDateTime(exp));
+            visa.setVerified(false);
+            return;
+        }
+
+        visa.setLinkedIdentity(URLEncoder.encode(doc.get(Ga4ghPassportVisa.SUB).asText(), StandardCharsets.UTF_8) +
+                ',' + URLEncoder.encode(doc.get(Ga4ghPassportVisa.ISS).asText(), StandardCharsets.UTF_8));
+
+        visa.setPrettyPayload(
+                visa_v1.get(Ga4ghPassportVisa.TYPE).asText() + ": '"
+                        + visa_v1.get(Ga4ghPassportVisa.VALUE).asText() + "' asserted at '"
+                        + isoDate(visa_v1.get(Ga4ghPassportVisa.ASSERTED).asLong()) + '\''
+        );
+    }
+
+    public static long getOneYearExpires(long asserted) {
+        return getExpires(asserted, 1L);
+    }
+
+    public static long getExpires(long asserted, long addYears) {
+        return Instant.ofEpochSecond(asserted).atZone(ZoneId.systemDefault()).plusYears(addYears).toEpochSecond();
+    }
+
+    private static void initializeSigner(Map<URI, String> signers,
+                                         Map<URI, RemoteJWKSet<SecurityContext>> remoteJwkSets,
+                                         String name,
+                                         String jwks)
+    {
+        try {
+            URL jku = new URL(jwks);
+            remoteJwkSets.put(jku.toURI(), new RemoteJWKSet<>(jku));
+            signers.put(jku.toURI(), name);
+
+            log.info("JWKS Signer '{}' added with keys '{}'", name, jwks);
+        } catch (MalformedURLException | URISyntaxException e) {
+            log.error("cannot add to RemoteJWKSet map: '{}' -> '{}'", name, jwks, e);
+        }
+    }
+
+    private static void initializeRepo(Repo repo, List<Ga4ghClaimRepository> claimRepositories) {
+        String name = repo.getName();
+        String actionURL = repo.getUrl();
+        List<RepoHeader> headers = repo.getHeaders();
+
+        if (actionURL == null || headers.isEmpty()) {
+            log.error("claim repository '{}' not defined with url|auth_header|auth_value", repo);
+            return;
+        }
+
+        RestTemplate restTemplate = new RestTemplate();
+        restTemplate.setRequestFactory(
+                new InterceptingClientHttpRequestFactory(restTemplate.getRequestFactory(), getClientHttpRequestInterceptors(headers))
+        );
+
+        claimRepositories.add(new Ga4ghClaimRepository(name, actionURL, restTemplate));
+        log.info("GA4GH Claims Repository '{}' configured at '{}'", name, actionURL);
+    }
+
+    private static void checkVisaKey(Ga4ghPassportVisa visa, JsonNode jsonNode, String key) {
+        if (jsonNode.path(key).isMissingNode()) {
+            log.warn("Key '{}' is missing in the Visa, therefore cannot be verified", key);
+            visa.setVerified(false);
+        } else {
+            switch (key) {
+                case Ga4ghPassportVisa.SUB:
+                    visa.setSub(jsonNode.path(key).asText());
+                    break;
+                case Ga4ghPassportVisa.ISS:
+                    visa.setIss(jsonNode.path(key).asText());
+                    break;
+                case Ga4ghPassportVisa.TYPE:
+                    visa.setType(jsonNode.path(key).asText());
+                    break;
+                case Ga4ghPassportVisa.VALUE:
+                    visa.setValue(jsonNode.path(key).asText());
+                    break;
+                default:
+                    log.warn("Unknown visa key: {}", key);
+            }
+        }
+    }
+
+    private static String isoDate(long linuxTime) {
+        return isoFormat(linuxTime, DateTimeFormatter.ISO_LOCAL_DATE);
+    }
+
+    private static String isoDateTime(long linuxTime) {
+        return isoFormat(linuxTime, DateTimeFormatter.ISO_DATE_TIME);
+    }
+
+    private static String isoFormat(long linuxTime, DateTimeFormatter formatter) {
+        ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochSecond(linuxTime), ZoneId.systemDefault());
+        return formatter.format(zdt);
+    }
+
+    private static List<ClientHttpRequestInterceptor> getClientHttpRequestInterceptors(List<RepoHeader> headers) {
+        return new ArrayList<>(headers);
+    }
+}
diff --git a/src/main/resources/application-bbmri.yml b/src/main/resources/application-bbmri.yml
new file mode 100644
index 0000000..39cd3d1
--- /dev/null
+++ b/src/main/resources/application-bbmri.yml
@@ -0,0 +1,77 @@
+---
+
+spring:
+  profiles: bbmri
+
+broker:
+  bona-fide-status-attr: bona_fide_status
+  bona-fide-status-rems-attr: bona_fide_status_rems
+  group-affiliations-attr: groupAffiliations
+  terms-and-policies-group-id: 1
+  affiliations-attr: affiliations
+  org-url-attr: orgUrl
+  ext-source-name: ext-source-name
+  issuer: issuer
+  path-to-jwk-file: path
+adapter:
+  adapter-primary: rpc
+  call-fallback: false
+ldap:
+  host: host
+  user: user
+  password: password
+  base-dn: dn
+  use-tls: false
+  use-ssl: true
+  allow-untrusted-ssl: false
+  timeout-secs: 10
+  port: 636
+rpc:
+  enabled: true
+  url: url
+  username: username
+  password: password
+  serializer: json
+attributes:
+  attributeMappings:
+    bona_fide_status:
+      internal-name: bona_fide_status
+      rpc-name: urn:perun:user:attribute-def:def:bonaFideStatus
+      ldap-name: bonaFideStatus
+    bona_fide_status_rems:
+      internal-name: bona_fide_status_rems
+      rpc-name: urn:perun:user:attribute-def:def:elixirBonaFideStatusREMS
+      ldap-name: bonaFideStatusREMS
+    groupAffiliations:
+      internal-name: groupAffiliations
+      rpc-name: urn:perun:group:attribute-def:def:groupAffiliations
+      ldap-name: groupAffiliations
+    affiliations:
+      internal-name: affiliations
+      rpc-name: urn:perun:ues:attribute-def:def:affiliation
+      ldap-name:
+    orgUrl:
+      internal-name: orgUrl
+      rpc-name: urn:perun:ues:attribute-def:def:organizationURL
+      ldap-name:
+ga4gh:
+  repos:
+        -
+          name: repo1
+          url: url1
+          jwks: jwks1
+          headers:
+            -
+              header: header
+              value: value
+        -
+          name: repo2
+          url: url2
+          jwks: jwks2
+          headers:
+            -
+              header: header
+              value: value
+basic-auth:
+  username: Honza
+  password: Lojza
diff --git a/src/main/resources/application-elixir.yml b/src/main/resources/application-elixir.yml
new file mode 100644
index 0000000..881f452
--- /dev/null
+++ b/src/main/resources/application-elixir.yml
@@ -0,0 +1,92 @@
+---
+
+spring:
+  config:
+    activate:
+      on-profile: elixir
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+
+broker:
+  bona-fide-status-attr: bona_fide_status
+  bona-fide-status-rems-attr: bona_fide_status_rems
+  group-affiliations-attr: groupAffiliations
+  terms-and-policies-group-id: 1
+  affiliations-attr: affiliations
+  org-url-attr: orgUrl
+  attributes-to-search:
+    - "elixir-persistent-shadow"
+  issuer: issuer
+  jku: jku-url
+  path-to-jwk-file: path
+adapter:
+  adapter-primary: ldap
+  call-fallback: false
+ldap:
+  host: host
+  user: user
+  password: password
+  base-dn: dn
+  use-tls: false
+  use-ssl: true
+  allow-untrusted-ssl: false
+  timeout-secs: 10
+  port: 636
+rpc:
+  enabled: true
+  url: url
+  username: username
+  password: password
+  serializer: json
+attributes:
+  attributeMappings:
+    bona_fide_status:
+      internal-name: bona_fide_status
+      rpc-name: name
+      ldap-name: name
+    bona_fide_status_rems:
+      internal-name: bona_fide_status_rems
+      rpc-name: name
+      ldap-name: name
+    groupAffiliations:
+      internal-name: groupAffiliations
+      rpc-name: name
+      ldap-name: name
+    affiliations:
+      internal-name: affiliations
+      rpc-name: name
+      ldap-name: name
+    orgUrl:
+      internal-name: orgUrl
+      rpc-name: name
+      ldap-name: name
+    elixir-persistent-shadow:
+      internal-name: elixir-persistent-shadow
+      rpc-name: name
+      ldap-name: name
+    preferred-mail:
+      internal-name: preferred-mail
+      rpc-name: name
+      ldap-name: name
+ga4gh:
+  repos:
+    -
+      name: repo1
+      url: url1
+      jwks: jwks1
+      headers:
+        -
+          header: header
+          value: value
+    -
+      name: repo2
+      url: url2
+      jwks: jwks2
+      headers:
+        -
+          header: header
+          value: value
+basic-auth:
+  username: username
+  password: password
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..63d98d7
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+---
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  profiles:
+    active: elixir
+
+logging:
+  file:
+    path: /var/lib/tomcat9/logs/broker.log
+  level:
+    root: debug
\ No newline at end of file
diff --git a/update-versions.sh b/update-versions.sh
new file mode 100755
index 0000000..d89eb68
--- /dev/null
+++ b/update-versions.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+./mvnw versions:set -DnewVersion=$1
\ No newline at end of file
-- 
GitLab