gx;I*XZwVaSi0Kf{qTSzz&XrxmQ3
zPDq@W2y|hSjuwjj%Bws`mYb#LJ$KK8m-^Jy<9!Bs$JLJ>iSK?njjuTC_@uA=%7&GBdTnZevRBPz1d9J#Ukm!b>OoOn$J1RGL=q7dk~8ht
zDB+rpJ&Jxx*O&8H5tAfiDhrjF~y)^tt#mf=1X+`;|(
zlNsDV#sAZsj|QEaiq?c69x-R?^qSZs^vHV3`M}B8m6J0?=x5@J-E}FWO`9g(w5+4M
zHszKg%tTg&71}cv-JhhNrcnQsiR=CpRM3aDs=S+voGByA8|q9M?JOT1U>Eovhle8?
znt*_rEwmW2WyG1Lj#=zSjF@^Eq++gK5WY`vNT_l!^ph0ZY>BZun3ai3)V8ytB(Ds1
zeYER5huc^?35ctCbl!FLMx;}&sWX9aui-|1820Z2|5tc_9CI^!P8ey~ca%#cDV&|h
zL@WTqYS}K=U19cgWvwSvRWt*IT)=WaF`ru2sw^lq~{{JhmU5CxlsMCmCJRZS?^Jz_qjC1mK|i|
z8hf~RAsipav`pExEuvK(X?{2;AdZWEVOKxuIu_Xt5$~zPU27Ln4M_?&iYJ}4Pk3oN
zI1T>eF>c*_0P}o}1v^IIj*EG#RDrbg@jtTsp2E=1w0_s=bc%R0{9w_=K*ESeOkE~u
z`a90B6s`UF)5KMStZPxw>zsrYX2?_FI7X3jeo(pJ%NcDUox+-FwEuyT{@YOd;$r))
zpDTTngeJt)SjJM#=EaRBHiXv+$xqVxn(Vk(PPfr|Qfh2LFrJsER?c*vH_D+7^Anyx
zH6xqAG$$flqbE#MBSm{DU~jQ<9y+ZS=4NIV9^rZ}>~Jh_V(1T>&sm-EkzWe0J`x-n
z@bQS4L9d`&MHxNfl*=`HCDTGOsMsFdNmu7rQV1Is9`Saz@p^4fq;-a55?7b#hd6Fg
z)|;HYR~HBA`P?WloU)?YE*?*ho?F6srZC^ZkUUuG+o*cuR4p)_gkLAZ9hg@^
zD=RDfn?ZV%3u(n1mw7?iqnTv3Gc=ja-S&p-^Ey5h<{5fwuMVI0#KE~vk>~xCmdif;
z8e^(_kgr$rgZt0f-tXboskV#m53Kp{Ig$(Q2yZr2gwz^XvDku-+J
zDP)M!qY9R>_+P)Umi1+C++0h_Wxnyw{{z9>8|(O@_GD_}$rzUdix^rAJQ$YSQhq=9
z0^8}r-JPuiryzXj$O~gdl=1|GLgw<{cF6L`x)nQWCXL3P7d7qYWc|p^wL%s!RD9;N
z9P+GhG20Q$kmeCi0~3av6WJ1rhe?uaf8n0H{et-N@E1Lpbof-&z4CsHNwm6prrza;zRg($E2A;&@l3?6d=a)qiVZu4CtEVViw_U_xO{%j4_!u1}j
zvpN%5+C*Yr$q$jvgKzn6H76+Aa)AkwcD&FWGLy}y^HG_>W<3KMWzBEbjSD0L3z|t!
zUi8bnGw<8%vwt5ZXBA3S>^Vlo@GA5VkF42|sTM=QoAk8!{aNS}uQ5^f9XXDD7<}Fm
zGNGAdxr2wzTn$ohNBNTU>+b^<%HPF64khjzgO)4B&qi(sdiXC&lXNF6-Q*Y<#{C*^
zkPf${Nl7Tw*7``J<*{Q2{lwP#A*yho=Qg?r5~ueydj0rDwiD96a~CK93u%_j%_W}L
zx;{l7UmcwP_Ls^#$Q$3aplc*CxEW&{K$h|+MfY6YcKmmqDn*WiPn_4_*@c4z0BjKh
z03ZPT5f26I-K#FoMKRKLzmog>$#x374@~pPPo!hXMXPgO?Dgj?Gd(6F3k${91809b
zOtD!a{-~4`OaKjAYILVOeTAYGmBigGnoLJtGH2<$d#25Hw(0rzdVSIIWT&^@{FOO1
z-?P$*Zf#4xw|9^ObLp`51q+?shNWAnPt7$HM1GVGFb)x81kK_Rh1|ZwrmxY_@QhMj
zLRK=TO>LBxY)-1fH?yNpp{Vwcu>HOhOFKb7PeFG|6gNwi*mp&X)RN4Jg}&ff6CERo
zpNgEXu|KM)nr~2Rk)z$Q2?{iZYkoDhiPxW3i>qD!*kAcI@Qvp{SzJ5fJHL7QcHY{L
zf>#r5VlaojetpGp^Q}bb2%UBj{AMRjz_(PH7!RC2E>2*}0b*ku2W9fwE0wZ-XZ7@b
zTx>9|+zB&%>~v1G5%XO6&Z=HztZ;QpRpkb!v91!=MkJ%O2x(OYtBAJorsamdL@+!}
z-^FEg*7DbE#8Z&aV@lRilQs7{=8;)rMhlOxy|CIO1~daPkdJ3A+YZ#+tUqOqV36EU
zb2lxVV7%S2C#veoRw5IMaz0WtE+8Y%b)G-@s*vt8&_${V!hFJ%dg*w%ANu(Z;4@B3
z%r4%bq_GlN{HcrGfa1{3&v3t@>Scg1Q%Yxi!cCOp>(J#T<0t%`3
zJPl<8^xFB=1*itS8@Z;9hQ2e_VFu!48Q7Sy60WM`U)&s3X0^%{7}2>Knw()piJ_JX
zpHlVU_H}~OWzKgt#CTw6ZpTk}!s9T(<$wuS=9S-7aYiyo=8M@~Wksx%
zh)9oksvhkoQ*69<*V~KfYxZ808{o`5-Pl7M&@)*%X`pA<-sahA=f$B`3pnvKRz
zd+Va!E=<*G)u~)Fl1H{Hhxc{B1UA=cU?UJ2#P>plR30_oUOhPPqVLuh(|rMr@gjVU
z$Er5^Hk2i?Y^*-~xMm@LdF#>&x8~6@3ls6S9M2slHH-iB4hZ+a004xk;9HE`FypaAqyQ;`<(Sy;Kt!8>pt50!0RSN}w+aaTBAcL0
zrz;|MySkI9$>jU0(yG)c5dywO`fpwz&zxDu!09~?IQc3Zq$=1m=&qjCkDy2Pqbc3X
zHJ*KtQPFIwOw6d*ojG-Ul_#K-EdTpQLI86`QCp=F*SfuhBPBFcrkD&4Yny*eqPLN}
z7>G5e9CsEh)>?LTKr@40&Vti+R9^Or$2ofj(b?~I@artT**cC^iIzn(@p$Zk
z`QtDejX%x+EO@1B&R0GPzJt3z_m6fsDf!>%f$@4ZEJo+VIIa0v
zQqziEH^rD*d5d`3cx|g($NI~%BUqNLxSXW|?G5xN>XQ7Y6F-pAN4_4E&4Y6L43^3F
zk?g4;A|>ksAw^1%o|V3Ef6=};jv7*5{7(DOBG(^RX0#b7)%Q&>xX0X7O0rcTxUodv
zu|KRR#l%9LWjFbvfagcW*ubyB;9dp;xe03i_(5UiKfkVwmI~BTsLi4P5m{>qR&Lb3
zp64n0`dYba=wD{06Q2H09?XS>NB7m~Rfz-x41pA-5|_JzEYf
zJ5z<3OX>?AB;9}993#*B)t4vV6OdKCD!=YlPo2WHNK%zNP>W?9QXf-S8)zr^pkuA<
zvKh}kq+{pA;$fT<8=ty#1qUVc{*`bAEs_x1fP7wAvOJ3)^!i}7@dqwbUukEjVr4g)
z_{Z;Q6dGau`OdQc3&L-vijHrW%|lzg{eeOgZ!L}D4V@YVvv^x
zbeqY|xgvwa4A$Bgb*$R}%qH`Ud*aWY;n)Q1cVPNV4nBGWId4D%!fneG!p@0HHDY0H
z43(a+*W0Pd1{yGt0wmW#2A@Aa@j(PUq8gG_l<6&~bO-AA#$ee}UOl~EDUmNkne9n1
zI@e%6Z6ri5+l5G;J@k~BT97mvy)vY_QVVaAf4#u}oG)xSZ6^;v7U^Hd?`5>iP7-(a
zIE`APRIoW=$UA4;De$@Q$t3%wPe;NcW0^rB?ESomPVM(u>H^ln4F?q&%wamq;N%n9
ze_K_y?9!P3)1NKm0%M`@008(M9u3@yhm`g|9V`HV>Y>>A&v*=%<5tBOrhrFs%M&Hi
z0|5T6{9fJxuJ&GVeJ&8)|4%9YLjwRNnH~}hcDnzB6aawb|Kb3AHux?h+k<&-j5ZGV
r?o%#!I}a({zlZ+_0C0Z@LuCI?zl{sN!y}8K$P4G>WyS{Z{{#LPo+I%V
delta 4233
zcmY*cc{mhY`yOQ98N0E|IvEN{NGRE|4aUx7O=LI7ME0_dWn_u5k1Rt;WFkp+S+cKV
z>y>5fYxC9n`>w0+cm8;;bI$WT=lpZu*L^=99t>I4O;J&{&N)u3q2{RskV_DjCk`GY
z;oY#8*P{U@TAhJhl`Xeh@j}qc@}EU;4UJ|M*k5PKC@MX~k4C;oiGhhOH`nCNz2|lX
zuoQFY%OTM_InQN#;As$i^3Z1g=$44S$0zo5S|ibYZI0%3Bq<2b;nx6khLZs-S@qst
zx!q;rtLKjy(AHE5vADg8)Yh`B0YP>3*fLGAdwoP(<;Q-Xu47qmpRh9Eta0dM9oyB6
z4PNcx7w(0%rWO@c;1mt=Z1(q3^s1Z)G8X+T`3v(%5t)>Z$(Qu^vUs9fJ03lhSmbIG
zY#9pa*IT#&lXk-a^BBV4v7w(?B?FAdBs3jjh@uHBlxf`GA;YA*
z$jid0>}%J;$ox*jR0hQZ3J;$dm~|(ViMA{1Zf2fZx7WhHvlO@H^iFZV
zD`MQ+FsgEsP~*cKyER%6R3ts;xNJmS%|&yE%1KtYa%3Fo%(qT+Vm!${E?58X<^-dD
z7Qg$=mfDm@KU>O(t>~xyxS+0e3(y0n=I>htL~Sq82XN-7&>LIcGHYu30iFRXr;w6g
zhp75Mx);7J@YTq3#s(UYJn#66vYm-C73bv-MdqNwTh;ZPwc5x>Oi%`iw>W6J=5i5C
zYkiIOeQ??rn$E*w1WeNm|Tq%y!oGn`@FX&w|XQ{dBrvY0+>Q5)Pk1rG|G
zzswutBceNnN
z0Z>I0z=loQtK@WH$q+>X6#x*!g_33vLQW@73$es*%WSF&ZNXpoPrT-Ed+P}d+{Ok?
z+q2(HHfd|RWrRK50_9zYNttp~yHHS(<~1k?lY8y%^%QHFkLY?(8Eoz)U}(dY^^|uj
zj(Q2q7^#>>M&Le8f%>4JdjH|~N8yYtG;F*MLpP$8-1>TXU+g42Dr(Q{xgko9M>Z?&
zRa2M*i4?=K%Gh0_J=YUbTf(>-u^G`ZnKl%L*ERXwSs@V)Ro{=UiEg*^EGkV02~~Tr
z;!Le$;MAp`zn%xqT1i;&?y2vjr7kb*4D9e6D$SlJp-hHhK2@ngIr+|bLsEj8ys%u!
z^!fIu9ajH3Ga{h2;wM~~NQ}uu+BtPFf4aUuAgeVGW%f-I0^-LL_?{JixYM*XBiw7!H
zfWoP&>6^boEJ-c?3Gg?LTq#F{IiJa~eapLg6`w8Qe1b@nqs>h2H@_Gl;g!oPzGU{!
zNtnR&BvGh!5{*}a$#Fwb6>D70e3imz#g|Hs<2rLzorIZF$Nt*AB_3ZkLUNGv&%q_(
z`^S>`g=3_E;s&O(xqW#a7ebd*ik@IHZc0Ac#^-w{i5UPOkpO=}Mz)<%2ZSZM)^r8%
z#t6=3Y@P6#t5Q!KSpY~&d^JsYD>{Ak3tNQDY~@i^u!Px{m6g!e$-T{RUX3}tl3Iv17b5Wq?DGpOG$l?>Gg1M6km|d4v8;lN%!^e*YjorV}m2Y^M*IVuGUg~Vr_X!
z^yonP26hQo-iu2*Q#r6Hma9qKRJ4$C53&Xir=X>;Gb3ISlEY;K!&Et8FHwwa5C@lB
zW^kWT9{R)=Nv0EFugm9LrZOo+wt5ZRw06enDq+;;r72lYUCOAiJ^4(NoH;3xTF@Gu
zfBnzV_yMyXpR+6T?;k90Rs?~EFh-+4Z@(Vqcb!jY>c$3*0YWBJk64N|zCn*IEp
zFM-7A;=Vg}#8OYXyC!!Z_YZuQwiyW)d3?Bv?e?)9@0-j>mA>{z{!CJ;g)7)o4$r0R<_>leV6dt=^S|vRy5xqDyH70n2S2OI!7Zs$o02%9+kT
z3yJXXT=k+e$c)2C_0f)f%5!lQ_c`Kb8uU-0}J0y6u(`IQ--I&@B`!u2qc
z^6?bwTwjaI)!R7*rk{%ybcRHUNuF*ka_^YyNGSU;&l`(rY{iwo8uvKyL;O15C3XnR
z%Z_x+R-#AxcYpaIgRRwPAD$!O2-2h8Uq;adeiAg_*jcD4U@rk#B1M=>4jUTf(qHJy7r{KkC!8|
z=>AEqhbiisJ~ey0lbCgdgIuS#@w7k`M1Jw-K~8p?cyY}h?nq=bNOzfL%4#InmvYuO
z<|aUKF4F7CHDTHb(>I^c9P2hu3rac*z_hU)bREANxf6q9l9DlO8yRX^&WWiMs@~Oy
z=;T-Y)P-ME>sJ1efs=C*Z>cG0cVFtihSjcstK0MOJmn>+0+&ZiEg?+#hjlF4^9tGl
zpWimKO!+c1CL?pJyOVzcS(B=aQS61wvSL1b0St;o_qv@`e_~EjWQ)Nn*3a#NajP{@
z3o}g@DMz@1xUy3jp&f0K4W6vJrsxcw^V~32h1K6mvNPd%Rj)z(
ztfN|SxEc?8TvZ>ytn$x*8!q&A_)k2^b*Wg%b-!%+sr(96BTUWp`;W{vZO6%6ZA}fg
zsrKtMvCv^KWkhgog}8g}x91XSwQY3lU3I#9yw6#?cW_|2x$CgkJm4^2
zU;ZOp18h_Fa2GPTVS@>NLinXpJzt}|=a*A3z89MFYTIZW0n6TV0j;EOA{P$NK7>ag
zUX~pY{wshJoYZu59idV4p5y?)7B%XJ5FZk1Xf_RDX$>wT2@}F_U}SJQz_4gYivQ^+
z7%tmN=ey}W-e{SrzN{S=F1^;D#fP`8bc
zewKi;H~C31dm<5HBb
zV0$#f*>t!uql}(lUH8e&Mfqy1sCB-w^<$Cm?7H_bJN-ACK1lTLj9Nejv
z#S$ttS|^7?{`7+)g2{#0D$4+@iCK42|QvF;D-lQr|Mm=k-P;
zHwcgILCH#3?hmVhN(|kCKTx~ORB5iRz&@IYR`>K^<9VK682FeB*W=yin%2q?ZjDRm
zOr5N=zNFM!=2nIFQE&0p)=VEY<{k$dAJr7^y71^fPrvq07F^;S&1EWJktjx>T0!=5
zZkFhq9@Sm!G0ldlk?8*zFeVk6UGI-%000dm03ZrL$;pc&KUlVVkN(D=D3LjBTP&A6
z#-cxn`ROPHm!u#B=LQen%=xM`xw@Sr!1BhE65VsRtGjO`jIfsdymxvbmlE!0@a&)I
zB+t}qe0N6*@pj121A9d&3Z5N<>lGZR<{5mrFOgF1!HFbHx%>{+m^Y&zp}yT*0;bXh
z59-!8tZ^fSdKHXj8BPK0K@z$B9$d)UqQ)anB}-RhVvjCqBQR?KS<`>kI&vI&aP%}o
z(Bm7d64+Y&3>b6WNx&SicJ-B8Z^VnfxY>ZCk}>`W{9aDd8&XKFJX^?^T5d%r_Zt(`oSgj(*FYJ(@$wkS4vix9r&c4-qpwue~Ch^(v
z%Q0Sund=NM3Gph~$*$tJI|I0gx;X=;mN%-4Zzi$6IQ}5TiDw$%>*%z#zzkC-e=Bts
zIlEy{RvgH~#7(dE;}HlQk?1H4eDz8Xa>UA6A|^$zuV$ZalT;XeHnEo
znC5=-5ISS)SnAMS^QeV7jCuTt>Wxt8q1MWd@)_;Uml`rD_uUAcL%PlGOk8Y#@h53nG
zHwmZjp5^o!Nq-P@c2u@$A;T_+^54q#ztYXwg=N6ESwT1Wzr_~<-c*zhxA3=mTP*TZ
ze)k0yF3`(NgZT{`L&DTXYQK=7ss4*D%Lj8*S!?gOT<*
z*JW0WlC}eqRbBMuea
zot@v>Wk$V&y?PqnU2Sug>BI5$Y~<~Q?$pwcCpn9>sgWsNu?k!(V1$*oMMXTVp_T&u
zz2+kSJKI(U>dluvuC_FF=mZWB<>ZaDc;hm>+&`sfbpD7AAp`Q@PenSF|8HQqFRM!N
z-!VN!&h*j(EdYSJpyfr8ojy00030*8kpJ1)(+}m-+ucasRhsQ1Ca6?~@M-qn^sE
l@c#>h-vsyhtuL(qTLu^uMUBa;kwY(|fC?g1K&d~;{{VC(-`)TK
From 4522642603aff5c62e9fbbbe627adc6ba91f63d9 Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Fri, 12 Dec 2025 21:47:32 +0100
Subject: [PATCH 40/46] build: update build and test workflows (#68)
---
.github/workflows/build-validation.yml | 3 ---
.github/workflows/test-validation.yml | 5 +----
2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/.github/workflows/build-validation.yml b/.github/workflows/build-validation.yml
index c3dad0a..793cd3e 100644
--- a/.github/workflows/build-validation.yml
+++ b/.github/workflows/build-validation.yml
@@ -5,9 +5,6 @@ on:
branches:
- main
- develop
- paths:
- - "**.cs"
- - "**.csproj"
env:
DOTNET_VERSION: "10.0.x" # The .NET SDK version to use
diff --git a/.github/workflows/test-validation.yml b/.github/workflows/test-validation.yml
index 46b8f51..a348eb6 100644
--- a/.github/workflows/test-validation.yml
+++ b/.github/workflows/test-validation.yml
@@ -5,9 +5,6 @@ on:
branches:
- main
- develop
- paths:
- - "**.cs"
- - "**.csproj"
env:
DOTNET_VERSION: "10.0.x" # The .NET SDK version to use
@@ -31,4 +28,4 @@ jobs:
run: dotnet build --configuration Release --no-restore
- name: Test
- run: dotnet test --no-restore --verbosity normal
+ run: dotnet test --configuration Release --no-restore --no-build --verbosity normal
From 2a6bd8652a0e65817f83cfd57476b9e75ffb87f9 Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Sat, 13 Dec 2025 00:33:56 +0100
Subject: [PATCH 41/46] refactor: database seeding (#71)
---
.../Core/DependencyInjection.cs | 2 +
.../Database/Seeding/SeedingService.cs | 64 +++++++++++++++++++
.../Infrastructure/Documents/ExcelService.cs | 49 ++++++++------
backend/Infrastructure/Infrastructure.csproj | 1 +
.../Core/Extensions/MiddlewareExtensions.cs | 8 +--
5 files changed, 100 insertions(+), 24 deletions(-)
create mode 100644 backend/Infrastructure/Database/Seeding/SeedingService.cs
diff --git a/backend/Infrastructure/Core/DependencyInjection.cs b/backend/Infrastructure/Core/DependencyInjection.cs
index 2ea50ab..2800d84 100644
--- a/backend/Infrastructure/Core/DependencyInjection.cs
+++ b/backend/Infrastructure/Core/DependencyInjection.cs
@@ -3,6 +3,7 @@
using Domain.Core.Abstractions;
using Infrastructure.Core.Time;
using Infrastructure.Database;
+using Infrastructure.Database.Seeding;
using Infrastructure.Documents;
using Infrastructure.Reports;
using Microsoft.EntityFrameworkCore;
@@ -31,6 +32,7 @@ IConfiguration configuration
{
services.AddSingleton();
services.AddScoped();
+ services.AddScoped();
services.AddScoped();
services.AddDatabase(configuration);
diff --git a/backend/Infrastructure/Database/Seeding/SeedingService.cs b/backend/Infrastructure/Database/Seeding/SeedingService.cs
new file mode 100644
index 0000000..af642b5
--- /dev/null
+++ b/backend/Infrastructure/Database/Seeding/SeedingService.cs
@@ -0,0 +1,64 @@
+using Domain.Contacts;
+using Domain.Core.Primitives;
+using Infrastructure.Documents;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+
+namespace Infrastructure.Database.Seeding;
+
+///
+/// Represents the seeding service.
+///
+/// The excel service.
+/// The EF Core database context.
+/// The logger used for diagnostic and error output.
+public class SeedingService(
+ ExcelService excelService,
+ PhoneForgeDbContext context,
+ ILogger logger
+)
+{
+ ///
+ /// Reads contacts from the Excel document and seeds them into the database.
+ ///
+ ///
+ /// This method attempts to load contacts using .
+ /// If loading fails for any reason (e.g., invalid data),
+ /// the method exits without modifying the database.
+ /// Seeding is skipped when the contacts table already contains data.
+ ///
+ ///
+ /// A task representing the asynchronous operation.
+ /// The task completes when the contacts have been saved,
+ /// or exits early if excel parsing failed or the database already contains contacts.
+ ///
+ public async Task SeedContacts()
+ {
+ logger.LogInformation("Seeding contacts to the database.");
+
+ Result> getContactsResult = await excelService.GetContacts();
+
+ if (getContactsResult.IsFailure)
+ {
+ return;
+ }
+
+ List contacts = getContactsResult.Value;
+
+ if (await context.Contacts.AnyAsync())
+ {
+ logger.LogWarning(
+ "Contacts already exists in the database. Aborting process."
+ );
+ return;
+ }
+
+ context.AddRange(contacts);
+
+ await context.SaveChangesAsync();
+ logger.LogInformation(
+ "Successfully seeded {Count} contacts to the database.",
+ contacts.Count
+ );
+ }
+}
diff --git a/backend/Infrastructure/Documents/ExcelService.cs b/backend/Infrastructure/Documents/ExcelService.cs
index 68f83de..07a6311 100644
--- a/backend/Infrastructure/Documents/ExcelService.cs
+++ b/backend/Infrastructure/Documents/ExcelService.cs
@@ -1,32 +1,31 @@
using ClosedXML.Excel;
using Domain.Contacts;
using Domain.Core.Primitives;
-using Infrastructure.Database;
-using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Infrastructure.Documents;
///
-/// Provides functionality for interacting with excel documents.
+/// Represents the excel service.
///
-/// The database context.
-/// The logger used for diagnostic and error output
-public class ExcelService(PhoneForgeDbContext context, ILogger logger)
+/// The logger used for diagnostic and error output.
+public class ExcelService(ILogger logger)
{
///
- /// Seeds data from excel spreadsheet to the database.
+ /// Reads contacts from the Excel document and loads them into memory.
///
- /// The result of seeding process or an error.
- public async Task SeedExcelDataAsync()
+ ///
+ /// This method processes each row of the Excel worksheet and attempts to
+ /// create a instance using the domain value objects.
+ /// If any validation error occurs while reading a row, the operation is aborted
+ /// and the error is logged.
+ ///
+ /// A containing a list of successfully parsed entities,
+ /// or an error describing why loading failed.
+ ///
+ public async Task>> GetContacts()
{
- logger.LogInformation("Started seeding the database from excel document.");
-
- if (await context.Contacts.AnyAsync())
- {
- logger.LogWarning("Data already exists in the database. Aborting process.");
- return;
- }
+ logger.LogInformation("Loading contacts from excel document.");
List contacts = [];
@@ -55,7 +54,7 @@ public async Task SeedExcelDataAsync()
row.RowNumber(),
firstFailOrSuccess.Error
);
- return;
+ return firstFailOrSuccess.Error;
}
Contact contact = Contact.Create(
@@ -68,10 +67,20 @@ public async Task SeedExcelDataAsync()
contacts.Add(contact);
}
- context.AddRange(contacts);
+ if (contacts.Count == 0)
+ {
+ logger.LogInformation("No contacts found in excel document.");
+ return Error.Failure(
+ "ExcelDocument.Empty",
+ "No contacts found in excel document."
+ );
+ }
- await context.SaveChangesAsync();
+ logger.LogInformation(
+ "Successfully retrieved {Count} contacts from excel document.",
+ contacts.Count
+ );
- logger.LogInformation("Successfully seeded the database from excel document.");
+ return contacts;
}
}
diff --git a/backend/Infrastructure/Infrastructure.csproj b/backend/Infrastructure/Infrastructure.csproj
index 6768255..ee89bbe 100644
--- a/backend/Infrastructure/Infrastructure.csproj
+++ b/backend/Infrastructure/Infrastructure.csproj
@@ -12,6 +12,7 @@
+
diff --git a/backend/WebApi/Core/Extensions/MiddlewareExtensions.cs b/backend/WebApi/Core/Extensions/MiddlewareExtensions.cs
index 1a4f4ec..ffdbdac 100644
--- a/backend/WebApi/Core/Extensions/MiddlewareExtensions.cs
+++ b/backend/WebApi/Core/Extensions/MiddlewareExtensions.cs
@@ -1,5 +1,5 @@
using Infrastructure.Database;
-using Infrastructure.Documents;
+using Infrastructure.Database.Seeding;
using Microsoft.EntityFrameworkCore;
using Serilog;
using WebApi.Core.Middleware;
@@ -82,9 +82,9 @@ private static async Task SeedDatabase(this IApplicationBuilder app)
{
using IServiceScope scope = app.ApplicationServices.CreateScope();
- ExcelService excelService =
- scope.ServiceProvider.GetRequiredService();
+ SeedingService excelService =
+ scope.ServiceProvider.GetRequiredService();
- await excelService.SeedExcelDataAsync();
+ await excelService.SeedContacts();
}
}
From bc9acd6ba31bfb8f0fba5a1c893f99e8bd675c18 Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Mon, 15 Dec 2025 03:34:58 +0100
Subject: [PATCH 42/46] feat: console UI (#72)
* add GetContacts feature
* refactor GetContacts use case
* add Create, Delete and Update features
* remove CA2000 from .editorconfig
---
Directory.Build.props | 30 ++--
Directory.Packages.props | 69 ++++----
frontend/Console/Console.csproj | 18 ++
frontend/Console/Contacts/Contact.cs | 11 ++
frontend/Console/Contacts/ContactsLayout.cs | 137 ++++++++++++++
frontend/Console/Contacts/ContactsService.cs | 145 +++++++++++++++
frontend/Console/Contacts/ContactsView.cs | 101 +++++++++++
.../Console/Contacts/ContactsViewState.cs | 10 ++
.../Console/Contacts/Create/CreateContact.cs | 55 ++++++
.../Contacts/Create/CreateContactRequest.cs | 8 +
.../Console/Contacts/Delete/DeleteContact.cs | 57 ++++++
.../GenerateReport/GenerateContactsReport.cs | 36 ++++
.../GenerateContactsReportRequest.cs | 7 +
.../Contacts/Get/GetContactsRequest.cs | 9 +
.../Contacts/Get/GetContactsResponse.cs | 11 ++
frontend/Console/Contacts/IContactsClient.cs | 25 +++
.../Console/Contacts/Update/UpdateContact.cs | 104 +++++++++++
.../Contacts/Update/UpdateContactRequest.cs | 8 +
frontend/Console/Core/DependencyInjection.cs | 37 ++++
.../Console/Core/Enums/ContactsSortColumn.cs | 10 ++
frontend/Console/Core/Enums/PageSize.cs | 8 +
frontend/Console/Core/Enums/SortOrder.cs | 7 +
frontend/Console/Core/Input/UserInput.cs | 167 ++++++++++++++++++
.../Core/Validation/InputValidation.cs | 58 ++++++
frontend/Console/Program.cs | 16 +-
frontend/Console/appsettings.json | 6 +
26 files changed, 1100 insertions(+), 50 deletions(-)
create mode 100644 frontend/Console/Contacts/Contact.cs
create mode 100644 frontend/Console/Contacts/ContactsLayout.cs
create mode 100644 frontend/Console/Contacts/ContactsService.cs
create mode 100644 frontend/Console/Contacts/ContactsView.cs
create mode 100644 frontend/Console/Contacts/ContactsViewState.cs
create mode 100644 frontend/Console/Contacts/Create/CreateContact.cs
create mode 100644 frontend/Console/Contacts/Create/CreateContactRequest.cs
create mode 100644 frontend/Console/Contacts/Delete/DeleteContact.cs
create mode 100644 frontend/Console/Contacts/GenerateReport/GenerateContactsReport.cs
create mode 100644 frontend/Console/Contacts/GenerateReport/GenerateContactsReportRequest.cs
create mode 100644 frontend/Console/Contacts/Get/GetContactsRequest.cs
create mode 100644 frontend/Console/Contacts/Get/GetContactsResponse.cs
create mode 100644 frontend/Console/Contacts/IContactsClient.cs
create mode 100644 frontend/Console/Contacts/Update/UpdateContact.cs
create mode 100644 frontend/Console/Contacts/Update/UpdateContactRequest.cs
create mode 100644 frontend/Console/Core/DependencyInjection.cs
create mode 100644 frontend/Console/Core/Enums/ContactsSortColumn.cs
create mode 100644 frontend/Console/Core/Enums/PageSize.cs
create mode 100644 frontend/Console/Core/Enums/SortOrder.cs
create mode 100644 frontend/Console/Core/Input/UserInput.cs
create mode 100644 frontend/Console/Core/Validation/InputValidation.cs
create mode 100644 frontend/Console/appsettings.json
diff --git a/Directory.Build.props b/Directory.Build.props
index 025a729..f51c3df 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,17 +1,17 @@
-
- net10.0
- enable
- enable
- latest-Recommended
- true
- true
- true
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
+
+ net10.0
+ enable
+ enable
+ latest-Recommended
+ true
+ true
+ true
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ae7b640..5f9d6be 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,34 +1,37 @@
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/Console/Console.csproj b/frontend/Console/Console.csproj
index 052197a..8d75346 100644
--- a/frontend/Console/Console.csproj
+++ b/frontend/Console/Console.csproj
@@ -3,4 +3,22 @@
Exe
True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/Console/Contacts/Contact.cs b/frontend/Console/Contacts/Contact.cs
new file mode 100644
index 0000000..09d0ad3
--- /dev/null
+++ b/frontend/Console/Contacts/Contact.cs
@@ -0,0 +1,11 @@
+namespace Console.Contacts;
+
+internal sealed record Contact(
+ Guid Id,
+ string FirstName,
+ string LastName,
+ string FullName,
+ string Email,
+ string PhoneNumber,
+ DateTime CreatedOnUtc
+);
diff --git a/frontend/Console/Contacts/ContactsLayout.cs b/frontend/Console/Contacts/ContactsLayout.cs
new file mode 100644
index 0000000..a658024
--- /dev/null
+++ b/frontend/Console/Contacts/ContactsLayout.cs
@@ -0,0 +1,137 @@
+using System.Globalization;
+using Console.Contacts.Get;
+using Spectre.Console;
+
+namespace Console.Contacts;
+
+internal static class ContactsLayout
+{
+ public static void Display(GetContactsResponse response, GetContactsRequest request)
+ {
+ Table table = new();
+
+ table.Border(TableBorder.None);
+
+ table.AddColumn(new TableColumn("[blue]Contacts[/]").Centered());
+ table.AddColumn(new TableColumn("[blue]Options[/]").Centered());
+
+ table.AddRow(RenderContacts(response.Items), RenderOptions(request));
+
+ AnsiConsole.Clear();
+ AnsiConsole.Write(table);
+
+ AnsiConsole.MarkupLine(
+ CultureInfo.InvariantCulture,
+ $"{(response.HasPreviousPage ? "<" : "[grey]<[/]")} page {response.Page} of {response.TotalPages} {(response.HasNextPage ? ">" : "[grey]>[/]")}"
+ );
+
+ AnsiConsole.WriteLine();
+ AnsiConsole.MarkupLine($"[grey]Use left and right arrow keys to navigate.[/]");
+ AnsiConsole.MarkupLine(
+ $"[grey]Press [white on grey] Escape [/] to exit or choose an option.[/]"
+ );
+ AnsiConsole.WriteLine();
+ }
+
+ private static Table RenderContacts(IReadOnlyCollection contacts)
+ {
+ Table table = new() { ShowRowSeparators = true };
+
+ table.AddColumn(new TableColumn("[deepskyblue1]#[/]").Centered());
+ table.AddColumn(new TableColumn("[deepskyblue1]Name[/]").Centered());
+ table.AddColumn(new TableColumn("[deepskyblue1]Email[/]").Centered());
+ table.AddColumn(new TableColumn("[deepskyblue1]Phone number[/]").Centered());
+ table.AddColumn(new TableColumn("[deepskyblue1]Created[/]").Centered());
+
+ foreach ((int index, Contact contact) in contacts.Index())
+ {
+ table.AddRow(
+ (index + 1).ToString(CultureInfo.InvariantCulture),
+ contact.FullName,
+ contact.Email,
+ contact.PhoneNumber,
+ contact.CreatedOnUtc.ToString(
+ "d-MMM-yyyy HH:mm",
+ CultureInfo.InvariantCulture
+ )
+ );
+ }
+ return table;
+ }
+
+ private static Table RenderOptions(GetContactsRequest request)
+ {
+ Table table = new() { ShowHeaders = false };
+
+ table.Border(TableBorder.None);
+
+ table.AddColumn(new TableColumn("").Centered());
+
+ table.AddRow(RenderPagination(request));
+ table.AddRow(RenderFeatures());
+
+ return table;
+ }
+
+ private static Table RenderPagination(GetContactsRequest request)
+ {
+ Table table = new() { ShowRowSeparators = true };
+
+ table.AddColumn(new TableColumn("[deepskyblue1]Key[/]").Centered());
+ table.AddColumn(new TableColumn("[deepskyblue1]Option[/]").Centered());
+ table.AddColumn(new TableColumn($"[deepskyblue1]Value[/]").Centered());
+
+ table.AddRow("[white on grey] F [/]", "Search term", $"{request.SearchTerm}");
+ table.AddRow("[white on grey] S [/]", "Page size", $"{request.PageSize}");
+ table.AddRow(
+ "[white on grey] C [/]",
+ "Sort column",
+ $"{FormatSortColumn(request.SortColumn)}"
+ );
+ table.AddRow(
+ "[white on grey] D [/]",
+ "Sort direction",
+ $"{FormatSortOrder(request.SortOrder)}"
+ );
+
+ return table;
+
+ static string FormatSortColumn(string sortColumn)
+ {
+ return sortColumn switch
+ {
+ "first_name" => "First name",
+ "last_name" => "Last name",
+ "email" => "Email",
+ "phone_number" => "Phone number",
+ "created_on" => "Created",
+ _ => string.Empty,
+ };
+ }
+
+ static string FormatSortOrder(string sortOrder)
+ {
+ return sortOrder switch
+ {
+ "asc" => "Ascending",
+ "desc" => "Descending",
+ _ => string.Empty,
+ };
+ }
+ }
+
+ private static Table RenderFeatures()
+ {
+ Table table = new() { ShowRowSeparators = true, ShowHeaders = false };
+
+ table.AddColumn(new TableColumn("").Centered());
+ table.AddColumn(new TableColumn("").Centered());
+
+ table.AddRow("[white on grey] A [/]", "Add contact");
+ table.AddRow("[white on grey] R [/]", "Remove contact");
+ table.AddRow("[white on grey] E [/]", "Edit contact");
+ table.AddRow("[white on grey] P [/]", "Create report");
+
+ return table;
+ }
+}
diff --git a/frontend/Console/Contacts/ContactsService.cs b/frontend/Console/Contacts/ContactsService.cs
new file mode 100644
index 0000000..abc22a9
--- /dev/null
+++ b/frontend/Console/Contacts/ContactsService.cs
@@ -0,0 +1,145 @@
+using System.Globalization;
+using Console.Contacts.Create;
+using Console.Contacts.GenerateReport;
+using Console.Contacts.Get;
+using Console.Contacts.Update;
+using Console.Core.Input;
+using Refit;
+using Spectre.Console;
+
+namespace Console.Contacts;
+
+internal sealed class ContactsService(IContactsClient contactsClient)
+{
+ public async Task GetContacts(GetContactsRequest request)
+ {
+ try
+ {
+ ApiResponse result = await contactsClient.GetContacts(
+ request
+ );
+
+ if (!result.IsSuccessful)
+ {
+ AnsiConsole.MarkupLineInterpolated(
+ CultureInfo.InvariantCulture,
+ $"[red]{result.Error.Message}[/]"
+ );
+ UserInput.PromptAnyKeyToContinue();
+ }
+
+ return result.Content;
+ }
+ catch (Exception ex)
+ {
+ AnsiConsole.MarkupLine($"[red]There was an error: {ex.Message}[/]");
+ UserInput.PromptAnyKeyToContinue();
+
+ return null;
+ }
+ }
+
+ public async Task GenerateReport(GenerateContactsReportRequest request)
+ {
+ try
+ {
+ IApiResponse result = await contactsClient.GenerateContactsReport(request);
+
+ if (!result.IsSuccessful)
+ {
+ AnsiConsole.MarkupLineInterpolated(
+ CultureInfo.InvariantCulture,
+ $"[red]{result.Error.Message}[/]"
+ );
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ AnsiConsole.MarkupLine("[green]Report generated successfully![/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ catch (Exception ex)
+ {
+ AnsiConsole.MarkupLine($"[red]There was an error: {ex.Message}[/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ }
+
+ public async Task CreateContact(CreateContactRequest request)
+ {
+ try
+ {
+ IApiResponse result = await contactsClient.CreateContact(request);
+
+ if (!result.IsSuccessful)
+ {
+ AnsiConsole.MarkupLineInterpolated(
+ CultureInfo.InvariantCulture,
+ $"[red]{result.Error.Message}[/]"
+ );
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ AnsiConsole.MarkupLine("[green]Contact created successfully![/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ catch (Exception ex)
+ {
+ AnsiConsole.MarkupLine($"[red]There was an error: {ex.Message}[/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ }
+
+ public async Task DeleteContact(Guid id)
+ {
+ try
+ {
+ IApiResponse result = await contactsClient.DeleteContact(id);
+
+ if (!result.IsSuccessful)
+ {
+ AnsiConsole.MarkupLineInterpolated(
+ CultureInfo.InvariantCulture,
+ $"[red]{result.Error.Message}[/]"
+ );
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ AnsiConsole.MarkupLine("[green]Contact deleted successfully![/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ catch (Exception ex)
+ {
+ AnsiConsole.MarkupLine($"[red]There was an error: {ex.Message}[/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ }
+
+ public async Task UpdateContact(Guid id, UpdateContactRequest request)
+ {
+ try
+ {
+ IApiResponse result = await contactsClient.UpdateContact(id, request);
+
+ if (!result.IsSuccessful)
+ {
+ AnsiConsole.MarkupLineInterpolated(
+ CultureInfo.InvariantCulture,
+ $"[red]{result.Error.Message}[/]"
+ );
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ AnsiConsole.MarkupLine("[green]Contact updated successfully![/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ catch (Exception ex)
+ {
+ AnsiConsole.MarkupLine($"[red]There was an error: {ex.Message}[/]");
+ UserInput.PromptAnyKeyToContinue();
+ }
+ }
+}
diff --git a/frontend/Console/Contacts/ContactsView.cs b/frontend/Console/Contacts/ContactsView.cs
new file mode 100644
index 0000000..71835ec
--- /dev/null
+++ b/frontend/Console/Contacts/ContactsView.cs
@@ -0,0 +1,101 @@
+using Console.Contacts.Create;
+using Console.Contacts.Delete;
+using Console.Contacts.GenerateReport;
+using Console.Contacts.Get;
+using Console.Contacts.Update;
+using Console.Core.Input;
+
+namespace Console.Contacts;
+
+internal sealed class ContactsView(
+ ContactsService contactsService,
+ CreateContact createContact,
+ DeleteContact deleteContact,
+ UpdateContact updateContact,
+ GenerateContactsReport generateContactsReport
+)
+{
+ public async Task Display()
+ {
+ bool exit = false;
+
+ ContactsViewState state = new();
+
+ while (!exit)
+ {
+ GetContactsRequest request = new(
+ state.SearchTerm,
+ state.Page,
+ state.PageSize,
+ state.SortColumn,
+ state.SortOrder
+ );
+
+ GetContactsResponse? response = await contactsService.GetContacts(request);
+
+ if (response is null)
+ {
+ break;
+ }
+
+ ContactsLayout.Display(response, request);
+
+ ConsoleKeyInfo key = System.Console.ReadKey(true);
+
+ await HandleKeyInput(key, state, response);
+
+ if (key.Key == ConsoleKey.Escape)
+ {
+ exit = UserInput.ConfirmExit();
+ }
+ }
+ }
+
+ private async Task HandleKeyInput(
+ ConsoleKeyInfo key,
+ ContactsViewState state,
+ GetContactsResponse response
+ )
+ {
+ switch (key.Key)
+ {
+ case ConsoleKey.LeftArrow when response.HasPreviousPage:
+ state.Page--;
+ break;
+ case ConsoleKey.RightArrow when response.HasNextPage:
+ state.Page++;
+ break;
+ case ConsoleKey.F:
+ state.SearchTerm = UserInput.PromptString(
+ "Search term:",
+ allowEmpty: true
+ );
+ state.Page = 1;
+ break;
+ case ConsoleKey.D:
+ state.SortOrder = UserInput.PromptSortOrder();
+ state.Page = 1;
+ break;
+ case ConsoleKey.C:
+ state.SortColumn = UserInput.PromptContactsSortColumn();
+ state.Page = 1;
+ break;
+ case ConsoleKey.S:
+ state.PageSize = UserInput.PromptPageSize();
+ state.Page = 1;
+ break;
+ case ConsoleKey.P:
+ await generateContactsReport.Handle(state, response.Items);
+ break;
+ case ConsoleKey.A:
+ await createContact.Handle();
+ break;
+ case ConsoleKey.R:
+ await deleteContact.Handle(response.Items);
+ break;
+ case ConsoleKey.E:
+ await updateContact.Handle(response.Items);
+ break;
+ }
+ }
+}
diff --git a/frontend/Console/Contacts/ContactsViewState.cs b/frontend/Console/Contacts/ContactsViewState.cs
new file mode 100644
index 0000000..e03261d
--- /dev/null
+++ b/frontend/Console/Contacts/ContactsViewState.cs
@@ -0,0 +1,10 @@
+namespace Console.Contacts;
+
+internal sealed class ContactsViewState
+{
+ public string SearchTerm { get; set; } = string.Empty;
+ public int Page { get; set; } = 1;
+ public int PageSize { get; set; } = 10;
+ public string SortColumn { get; set; } = "first_name";
+ public string SortOrder { get; set; } = "asc";
+}
diff --git a/frontend/Console/Contacts/Create/CreateContact.cs b/frontend/Console/Contacts/Create/CreateContact.cs
new file mode 100644
index 0000000..ee55b15
--- /dev/null
+++ b/frontend/Console/Contacts/Create/CreateContact.cs
@@ -0,0 +1,55 @@
+using Console.Core.Input;
+using Spectre.Console;
+
+namespace Console.Contacts.Create;
+
+internal sealed class CreateContact(ContactsService contactsService)
+{
+ public async Task Handle()
+ {
+ AnsiConsole.Clear();
+ AnsiConsole.MarkupLine("[blue]Creating a new contact...[/]");
+
+ string firstName = UserInput.PromptString("First name: ", allowEmpty: false);
+ string lastName = UserInput.PromptString("Last name: ", allowEmpty: false);
+ string email = UserInput.PromptEmail("Email: ", allowEmpty: false);
+ string phoneNumber = UserInput.PromptPhoneNumber(
+ "Phone number: ",
+ allowEmpty: false
+ );
+
+ CreateContactRequest request = new(firstName, lastName, email, phoneNumber);
+
+ RenderInformation(request);
+
+ if (
+ await AnsiConsole.ConfirmAsync(
+ "Are you sure you want to create a new contact?"
+ )
+ )
+ {
+ await contactsService.CreateContact(request);
+ }
+ }
+
+ private static void RenderInformation(CreateContactRequest request)
+ {
+ Table table = new()
+ {
+ Title = new TableTitle("[blue]New contact[/]"),
+ ShowHeaders = false,
+ ShowRowSeparators = true,
+ };
+
+ table.AddColumn(new TableColumn("Property").Centered());
+ table.AddColumn(new TableColumn("Value").Centered());
+
+ table.AddRow("[deepskyblue1]First name[/]", $"{request.FirstName}");
+ table.AddRow("[deepskyblue1]Last name[/]", $"{request.LastName}");
+ table.AddRow("[deepskyblue1]Email[/]", $"{request.Email}");
+ table.AddRow("[deepskyblue1]Phone number[/]", $"{request.PhoneNumber}");
+
+ AnsiConsole.Clear();
+ AnsiConsole.Write(table);
+ }
+}
diff --git a/frontend/Console/Contacts/Create/CreateContactRequest.cs b/frontend/Console/Contacts/Create/CreateContactRequest.cs
new file mode 100644
index 0000000..dd8b2ee
--- /dev/null
+++ b/frontend/Console/Contacts/Create/CreateContactRequest.cs
@@ -0,0 +1,8 @@
+namespace Console.Contacts.Create;
+
+internal sealed record CreateContactRequest(
+ string FirstName,
+ string LastName,
+ string Email,
+ string PhoneNumber
+);
diff --git a/frontend/Console/Contacts/Delete/DeleteContact.cs b/frontend/Console/Contacts/Delete/DeleteContact.cs
new file mode 100644
index 0000000..8b33460
--- /dev/null
+++ b/frontend/Console/Contacts/Delete/DeleteContact.cs
@@ -0,0 +1,57 @@
+using Console.Core.Input;
+using Spectre.Console;
+
+namespace Console.Contacts.Delete;
+
+internal sealed class DeleteContact(ContactsService contactsService)
+{
+ public async Task Handle(IReadOnlyCollection contacts)
+ {
+ if (contacts.Count == 0)
+ {
+ AnsiConsole.MarkupLine("[red]No contacts to remove![/]");
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ int id = UserInput.PromptPositiveInteger(
+ "Enter contact Id to remove:",
+ allowZero: false
+ );
+ int index = UserInput.GetValidListIndex(id, contacts);
+
+ Contact? contact = contacts.ElementAtOrDefault(index);
+
+ if (contact is null)
+ {
+ AnsiConsole.MarkupLine("[red]Contact not found![/]");
+ return;
+ }
+
+ RenderInformation(contact);
+
+ if (
+ await AnsiConsole.ConfirmAsync(
+ $"Are you sure you want to delete this contact?"
+ )
+ )
+ {
+ await contactsService.DeleteContact(contact.Id);
+ }
+ }
+
+ private static void RenderInformation(Contact contact)
+ {
+ Table table = new() { ShowHeaders = false, ShowRowSeparators = true };
+
+ table.AddColumn(new TableColumn("Property").Centered());
+ table.AddColumn(new TableColumn("Value").Centered());
+
+ table.AddRow("[deepskyblue1]Name[/]", $"{contact.FullName}");
+ table.AddRow("[deepskyblue1]Email[/]", $"{contact.Email}");
+ table.AddRow("[deepskyblue1]Phone number[/]", $"{contact.PhoneNumber}");
+
+ AnsiConsole.Clear();
+ AnsiConsole.Write(table);
+ }
+}
diff --git a/frontend/Console/Contacts/GenerateReport/GenerateContactsReport.cs b/frontend/Console/Contacts/GenerateReport/GenerateContactsReport.cs
new file mode 100644
index 0000000..fa6e130
--- /dev/null
+++ b/frontend/Console/Contacts/GenerateReport/GenerateContactsReport.cs
@@ -0,0 +1,36 @@
+using Console.Core.Input;
+using Spectre.Console;
+
+namespace Console.Contacts.GenerateReport;
+
+internal sealed class GenerateContactsReport(ContactsService contactsService)
+{
+ public async Task Handle(
+ ContactsViewState state,
+ IReadOnlyCollection contacts
+ )
+ {
+ if (contacts.Count == 0)
+ {
+ AnsiConsole.MarkupLine(
+ "[red]Unable to generate a report with no contacts![/]"
+ );
+ AnsiConsole.MarkupLine("[grey]Edit filters or create contacts.[/]");
+ AnsiConsole.WriteLine();
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ GenerateContactsReportRequest contactsReportRequest = new(
+ state.SearchTerm,
+ state.SortColumn,
+ state.SortOrder
+ );
+
+ AnsiConsole.MarkupLine("Are you sure you want to generate a PDF report?");
+ if (await AnsiConsole.ConfirmAsync("Current filters will apply."))
+ {
+ await contactsService.GenerateReport(contactsReportRequest);
+ }
+ }
+}
diff --git a/frontend/Console/Contacts/GenerateReport/GenerateContactsReportRequest.cs b/frontend/Console/Contacts/GenerateReport/GenerateContactsReportRequest.cs
new file mode 100644
index 0000000..e02fedc
--- /dev/null
+++ b/frontend/Console/Contacts/GenerateReport/GenerateContactsReportRequest.cs
@@ -0,0 +1,7 @@
+namespace Console.Contacts.GenerateReport;
+
+internal sealed record GenerateContactsReportRequest(
+ string SearchTerm,
+ string SortColumn,
+ string SortOrder
+);
diff --git a/frontend/Console/Contacts/Get/GetContactsRequest.cs b/frontend/Console/Contacts/Get/GetContactsRequest.cs
new file mode 100644
index 0000000..07ed5a7
--- /dev/null
+++ b/frontend/Console/Contacts/Get/GetContactsRequest.cs
@@ -0,0 +1,9 @@
+namespace Console.Contacts.Get;
+
+internal sealed record GetContactsRequest(
+ string SearchTerm,
+ int Page,
+ int PageSize,
+ string SortColumn,
+ string SortOrder
+);
diff --git a/frontend/Console/Contacts/Get/GetContactsResponse.cs b/frontend/Console/Contacts/Get/GetContactsResponse.cs
new file mode 100644
index 0000000..f6494ca
--- /dev/null
+++ b/frontend/Console/Contacts/Get/GetContactsResponse.cs
@@ -0,0 +1,11 @@
+namespace Console.Contacts.Get;
+
+internal sealed record GetContactsResponse(
+ int Page,
+ int PageSize,
+ int TotalCount,
+ int TotalPages,
+ bool HasNextPage,
+ bool HasPreviousPage,
+ IReadOnlyCollection Items
+);
diff --git a/frontend/Console/Contacts/IContactsClient.cs b/frontend/Console/Contacts/IContactsClient.cs
new file mode 100644
index 0000000..120a77b
--- /dev/null
+++ b/frontend/Console/Contacts/IContactsClient.cs
@@ -0,0 +1,25 @@
+using Console.Contacts.Create;
+using Console.Contacts.GenerateReport;
+using Console.Contacts.Get;
+using Console.Contacts.Update;
+using Refit;
+
+namespace Console.Contacts;
+
+internal interface IContactsClient
+{
+ [Get("/contacts")]
+ Task> GetContacts(GetContactsRequest request);
+
+ [Get("/contacts/report")]
+ Task GenerateContactsReport(GenerateContactsReportRequest request);
+
+ [Post("/contacts")]
+ Task CreateContact([Body] CreateContactRequest request);
+
+ [Delete("/contacts/{id}")]
+ Task DeleteContact(Guid id);
+
+ [Put("/contacts/{id}")]
+ Task UpdateContact(Guid id, [Body] UpdateContactRequest request);
+}
diff --git a/frontend/Console/Contacts/Update/UpdateContact.cs b/frontend/Console/Contacts/Update/UpdateContact.cs
new file mode 100644
index 0000000..e78a4b8
--- /dev/null
+++ b/frontend/Console/Contacts/Update/UpdateContact.cs
@@ -0,0 +1,104 @@
+using Console.Core.Input;
+using Spectre.Console;
+
+namespace Console.Contacts.Update;
+
+internal sealed class UpdateContact(ContactsService contactsService)
+{
+ public async Task Handle(IReadOnlyCollection contacts)
+ {
+ if (contacts.Count == 0)
+ {
+ AnsiConsole.MarkupLine("[red]No contacts to update![/]");
+ UserInput.PromptAnyKeyToContinue();
+ return;
+ }
+
+ int id = UserInput.PromptPositiveInteger(
+ "Enter contact Id to edit:",
+ allowZero: false
+ );
+ int index = UserInput.GetValidListIndex(id, contacts);
+
+ Contact? contact = contacts.ElementAtOrDefault(index);
+
+ if (contact is null)
+ {
+ AnsiConsole.MarkupLine("[red]Contact not found![/]");
+ return;
+ }
+
+ RenderInformation(contact);
+ AnsiConsole.MarkupLine("Enter new information. [grey]Leave empty to skip.[/]");
+
+ string firstName = UserInput.PromptString("First name:", allowEmpty: true);
+ string lastName = UserInput.PromptString("Last name:", allowEmpty: true);
+ string email = UserInput.PromptString("Email:", allowEmpty: true);
+ string phoneNumber = UserInput.PromptString("Phone number:", allowEmpty: true);
+
+ UpdateContactRequest request = new(
+ string.IsNullOrWhiteSpace(firstName) ? contact.FirstName : firstName,
+ string.IsNullOrWhiteSpace(lastName) ? contact.LastName : lastName,
+ string.IsNullOrWhiteSpace(email) ? contact.Email : email,
+ string.IsNullOrWhiteSpace(phoneNumber) ? contact.PhoneNumber : phoneNumber
+ );
+
+ RenderUpdateInformation(contact, request);
+
+ if (await AnsiConsole.ConfirmAsync("Are you sure you want to save the changes?"))
+ {
+ await contactsService.UpdateContact(contact.Id, request);
+ }
+ }
+
+ private static void RenderInformation(Contact contact)
+ {
+ Table table = new() { ShowHeaders = false, ShowRowSeparators = true };
+
+ table.AddColumn(new TableColumn("Property").Centered());
+ table.AddColumn(new TableColumn("Value").Centered());
+
+ table.AddRow("[deepskyblue1]Name[/]", $"{contact.FullName}");
+ table.AddRow("[deepskyblue1]Email[/]", $"{contact.Email}");
+ table.AddRow("[deepskyblue1]Phone number[/]", $"{contact.PhoneNumber}");
+
+ AnsiConsole.Clear();
+ AnsiConsole.Write(table);
+ }
+
+ private static void RenderUpdateInformation(
+ Contact contact,
+ UpdateContactRequest request
+ )
+ {
+ Table table = new() { ShowRowSeparators = true };
+
+ table.AddColumn(new TableColumn("").Centered());
+ table.AddColumn(new TableColumn("[green]New[/]").Centered());
+ table.AddColumn(new TableColumn("[grey]Old[/]").Centered());
+
+ table.AddRow(
+ "[deepskyblue1]First name[/]",
+ $"{request.FirstName}",
+ $"[grey]{contact.FirstName}[/]"
+ );
+ table.AddRow(
+ "[deepskyblue1]Last name[/]",
+ $"{request.LastName}",
+ $"[grey]{contact.LastName}[/]"
+ );
+ table.AddRow(
+ "[deepskyblue1]Email[/]",
+ $"{request.Email}",
+ $"[grey]{contact.Email}[/]"
+ );
+ table.AddRow(
+ "[deepskyblue1]Phone number[/]",
+ $"{request.PhoneNumber}",
+ $"[grey]{contact.PhoneNumber}[/]"
+ );
+
+ AnsiConsole.Clear();
+ AnsiConsole.Write(table);
+ }
+}
diff --git a/frontend/Console/Contacts/Update/UpdateContactRequest.cs b/frontend/Console/Contacts/Update/UpdateContactRequest.cs
new file mode 100644
index 0000000..ae7bed8
--- /dev/null
+++ b/frontend/Console/Contacts/Update/UpdateContactRequest.cs
@@ -0,0 +1,8 @@
+namespace Console.Contacts.Update;
+
+internal sealed record UpdateContactRequest(
+ string FirstName,
+ string LastName,
+ string Email,
+ string PhoneNumber
+);
diff --git a/frontend/Console/Core/DependencyInjection.cs b/frontend/Console/Core/DependencyInjection.cs
new file mode 100644
index 0000000..5aae01d
--- /dev/null
+++ b/frontend/Console/Core/DependencyInjection.cs
@@ -0,0 +1,37 @@
+using Console.Contacts;
+using Console.Contacts.Create;
+using Console.Contacts.Delete;
+using Console.Contacts.GenerateReport;
+using Console.Contacts.Update;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Refit;
+
+namespace Console.Core;
+
+internal static class DependencyInjection
+{
+ public static void AddConsoleServices(
+ this IServiceCollection services,
+ IConfiguration configuration
+ )
+ {
+ services.AddLogging(b => b.ClearProviders());
+
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+
+ string apiAdress =
+ configuration.GetValue("ApiSettings:PhoneForgeApiAddress")
+ ?? throw new InvalidOperationException("Missing connection string.");
+
+ services
+ .AddRefitClient()
+ .ConfigureHttpClient(c => c.BaseAddress = new Uri(apiAdress));
+ }
+}
diff --git a/frontend/Console/Core/Enums/ContactsSortColumn.cs b/frontend/Console/Core/Enums/ContactsSortColumn.cs
new file mode 100644
index 0000000..6fa63d2
--- /dev/null
+++ b/frontend/Console/Core/Enums/ContactsSortColumn.cs
@@ -0,0 +1,10 @@
+namespace Console.Core.Enums;
+
+internal enum ContactsSortColumn
+{
+ FirstName,
+ LastName,
+ Email,
+ PhoneNumber,
+ CreatedOn,
+}
diff --git a/frontend/Console/Core/Enums/PageSize.cs b/frontend/Console/Core/Enums/PageSize.cs
new file mode 100644
index 0000000..23fb390
--- /dev/null
+++ b/frontend/Console/Core/Enums/PageSize.cs
@@ -0,0 +1,8 @@
+namespace Console.Core.Enums;
+
+internal enum PageSize
+{
+ Ten,
+ Twenty,
+ Thirty,
+}
diff --git a/frontend/Console/Core/Enums/SortOrder.cs b/frontend/Console/Core/Enums/SortOrder.cs
new file mode 100644
index 0000000..9c5c0cf
--- /dev/null
+++ b/frontend/Console/Core/Enums/SortOrder.cs
@@ -0,0 +1,7 @@
+namespace Console.Core.Enums;
+
+internal enum SortOrder
+{
+ Ascending,
+ Descending,
+}
diff --git a/frontend/Console/Core/Input/UserInput.cs b/frontend/Console/Core/Input/UserInput.cs
new file mode 100644
index 0000000..1901e78
--- /dev/null
+++ b/frontend/Console/Core/Input/UserInput.cs
@@ -0,0 +1,167 @@
+using Console.Core.Enums;
+using Console.Core.Validation;
+using Spectre.Console;
+
+namespace Console.Core.Input;
+
+internal static class UserInput
+{
+ public static void PromptAnyKeyToContinue()
+ {
+ AnsiConsole.Write("Press any key to continue...");
+ System.Console.ReadKey();
+ }
+
+ public static bool ConfirmExit()
+ {
+ if (AnsiConsole.Confirm("Are you sure you want to exit?"))
+ {
+ AnsiConsole.WriteLine("Goodbye!");
+ return true;
+ }
+ return false;
+ }
+
+ public static string PromptString(string displayMessage, bool allowEmpty)
+ {
+ TextPrompt prompt = new(displayMessage);
+
+ if (allowEmpty)
+ {
+ prompt.AllowEmpty();
+ }
+
+ return AnsiConsole.Prompt(prompt);
+ }
+
+ public static string PromptEmail(string displayMessage, bool allowEmpty)
+ {
+ TextPrompt prompt = new(displayMessage);
+
+ if (allowEmpty)
+ {
+ prompt.AllowEmpty();
+ }
+
+ prompt.Validate(InputValidation.IsValidEmail);
+
+ return AnsiConsole.Prompt(prompt);
+ }
+
+ public static string PromptPhoneNumber(string displayMessage, bool allowEmpty)
+ {
+ TextPrompt prompt = new(displayMessage);
+
+ if (allowEmpty)
+ {
+ prompt.AllowEmpty();
+ }
+
+ prompt.Validate(InputValidation.IsValidPhoneNumber);
+
+ return AnsiConsole.Prompt(prompt);
+ }
+
+ public static int PromptPositiveInteger(string displayMessage, bool allowZero)
+ {
+ TextPrompt prompt = new(displayMessage);
+ prompt.ValidationErrorMessage("[red]Input must a positive integer![/]");
+
+ if (allowZero)
+ {
+ prompt.Validate(InputValidation.IsGreaterThanOrEqualToZero);
+ }
+
+ prompt.Validate(InputValidation.IsGreaterThanZero);
+
+ return AnsiConsole.Prompt(prompt);
+ }
+
+ public static int GetValidListIndex(int input, IReadOnlyCollection list)
+ where T : notnull
+ {
+ while (input > list.Count)
+ {
+ AnsiConsole.MarkupLine("[red]Invalid Id![/]");
+ input = PromptPositiveInteger("Enter contact Id:", allowZero: false);
+ }
+ return input - 1;
+ }
+
+ public static string PromptSortOrder()
+ {
+ SortOrder selection = AnsiConsole.Prompt(
+ new SelectionPrompt()
+ .Title("Select sorting order:")
+ .AddChoices(Enum.GetValues())
+ );
+
+ return selection switch
+ {
+ SortOrder.Ascending => "asc",
+ SortOrder.Descending => "desc",
+ _ => "Unknown sort order option",
+ };
+ }
+
+ public static string PromptContactsSortColumn()
+ {
+ ContactsSortColumn selection = AnsiConsole.Prompt(
+ new SelectionPrompt()
+ .Title("Select sorting column:")
+ .UseConverter(ConvertSortColumnOptions)
+ .AddChoices(Enum.GetValues())
+ );
+
+ return selection switch
+ {
+ ContactsSortColumn.FirstName => "first_name",
+ ContactsSortColumn.LastName => "last_name",
+ ContactsSortColumn.Email => "email",
+ ContactsSortColumn.PhoneNumber => "phone_number",
+ ContactsSortColumn.CreatedOn => "created_on",
+ _ => "Unkown sort column option.",
+ };
+
+ static string ConvertSortColumnOptions(ContactsSortColumn options)
+ {
+ return options switch
+ {
+ ContactsSortColumn.FirstName => "First name",
+ ContactsSortColumn.LastName => "Last name",
+ ContactsSortColumn.Email => "Email",
+ ContactsSortColumn.PhoneNumber => "Phone number",
+ ContactsSortColumn.CreatedOn => "Date created",
+ _ => "Unkown sort column option.",
+ };
+ }
+ }
+
+ public static int PromptPageSize()
+ {
+ PageSize selection = AnsiConsole.Prompt(
+ new SelectionPrompt()
+ .Title("Select page size:")
+ .UseConverter(ConvertPageSizeOptions)
+ .AddChoices(Enum.GetValues())
+ );
+
+ return selection switch
+ {
+ PageSize.Ten => 10,
+ PageSize.Twenty => 20,
+ PageSize.Thirty => 30,
+ _ => 10,
+ };
+ static string ConvertPageSizeOptions(PageSize options)
+ {
+ return options switch
+ {
+ PageSize.Ten => "10",
+ PageSize.Twenty => "20",
+ PageSize.Thirty => "30",
+ _ => "Unkown page size option.",
+ };
+ }
+ }
+}
diff --git a/frontend/Console/Core/Validation/InputValidation.cs b/frontend/Console/Core/Validation/InputValidation.cs
new file mode 100644
index 0000000..4a9dfba
--- /dev/null
+++ b/frontend/Console/Core/Validation/InputValidation.cs
@@ -0,0 +1,58 @@
+using Spectre.Console;
+
+namespace Console.Core.Validation;
+
+internal static class InputValidation
+{
+ public static ValidationResult IsGreaterThanOrEqualToZero(int input)
+ {
+ return input switch
+ {
+ < 0 => ValidationResult.Error(
+ "[red]Input must be greater than or equal to zero![/]"
+ ),
+ _ => ValidationResult.Success(),
+ };
+ }
+
+ public static ValidationResult IsGreaterThanZero(int input)
+ {
+ return input switch
+ {
+ < 1 => ValidationResult.Error("[red]Input must be greater than 0![/]"),
+ _ => ValidationResult.Success(),
+ };
+ }
+
+ public static ValidationResult IsValidEmail(string input)
+ {
+ if (!input.Contains('@'))
+ {
+ return ValidationResult.Error("[red]Invalid email format![/]");
+ }
+
+ return ValidationResult.Success();
+ }
+
+ public static ValidationResult IsValidPhoneNumber(string input)
+ {
+ if (!input.All(char.IsDigit))
+ {
+ return ValidationResult.Error(
+ "[red]Invalid phone number! Only numbers are allowed.[/]"
+ );
+ }
+
+ if (input.Length < 6)
+ {
+ return ValidationResult.Error("[red]Minimum phone number length is 6![/]");
+ }
+
+ if (input.Length > 20)
+ {
+ return ValidationResult.Error("[red]Maximum phone number length is 20![/]");
+ }
+
+ return ValidationResult.Success();
+ }
+}
diff --git a/frontend/Console/Program.cs b/frontend/Console/Program.cs
index 3751555..04bb7f7 100644
--- a/frontend/Console/Program.cs
+++ b/frontend/Console/Program.cs
@@ -1,2 +1,14 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
+using Console.Contacts;
+using Console.Core;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+HostApplicationBuilder builder = Host.CreateApplicationBuilder();
+
+builder.Services.AddConsoleServices(builder.Configuration);
+
+using IHost host = builder.Build();
+
+ContactsView contactsView = host.Services.GetRequiredService();
+
+await contactsView.Display();
diff --git a/frontend/Console/appsettings.json b/frontend/Console/appsettings.json
new file mode 100644
index 0000000..6957519
--- /dev/null
+++ b/frontend/Console/appsettings.json
@@ -0,0 +1,6 @@
+{
+ "ApiSettings": {
+ "PhoneForgeApiAddress": "http://localhost:5111/api/v1"
+ }
+}
+
From a68baab020da0ef04b43b8e4db711ff6596b05df Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Mon, 15 Dec 2025 16:54:03 +0100
Subject: [PATCH 43/46] refactor: move database check before excel parsing when
seeding contacts (#75)
---
.../Database/Seeding/SeedingService.cs | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/backend/Infrastructure/Database/Seeding/SeedingService.cs b/backend/Infrastructure/Database/Seeding/SeedingService.cs
index af642b5..33a36a8 100644
--- a/backend/Infrastructure/Database/Seeding/SeedingService.cs
+++ b/backend/Infrastructure/Database/Seeding/SeedingService.cs
@@ -36,23 +36,23 @@ public async Task SeedContacts()
{
logger.LogInformation("Seeding contacts to the database.");
- Result> getContactsResult = await excelService.GetContacts();
-
- if (getContactsResult.IsFailure)
+ if (await context.Contacts.AnyAsync())
{
+ logger.LogWarning(
+ "Contacts already exists in the database. Aborting process."
+ );
return;
}
- List contacts = getContactsResult.Value;
+ Result> getContactsResult = await excelService.GetContacts();
- if (await context.Contacts.AnyAsync())
+ if (getContactsResult.IsFailure)
{
- logger.LogWarning(
- "Contacts already exists in the database. Aborting process."
- );
return;
}
+ List contacts = getContactsResult.Value;
+
context.AddRange(contacts);
await context.SaveChangesAsync();
From 0333a4c9c2cf6fe4d540d09bf02781f46a0f31af Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Mon, 15 Dec 2025 19:55:29 +0100
Subject: [PATCH 44/46] build: enable repeatable package restores in workflows
(#77)
* add RestorePackagesWithLockFile property
* add package caching to workflows
---
.github/workflows/build-validation.yml | 9 +-
.github/workflows/test-validation.yml | 9 +-
Directory.Build.props | 1 +
backend/Application/packages.lock.json | 124 +++
backend/Domain/packages.lock.json | 13 +
backend/Infrastructure/packages.lock.json | 401 +++++++++
backend/WebApi/packages.lock.json | 700 ++++++++++++++++
frontend/Console/packages.lock.json | 332 ++++++++
tests/ArchitectureTests/packages.lock.json | 726 ++++++++++++++++
tests/IntegrationTests/packages.lock.json | 921 +++++++++++++++++++++
tests/TestData/packages.lock.json | 621 ++++++++++++++
tests/UnitTests/packages.lock.json | 725 ++++++++++++++++
12 files changed, 4580 insertions(+), 2 deletions(-)
create mode 100644 backend/Application/packages.lock.json
create mode 100644 backend/Domain/packages.lock.json
create mode 100644 backend/Infrastructure/packages.lock.json
create mode 100644 backend/WebApi/packages.lock.json
create mode 100644 frontend/Console/packages.lock.json
create mode 100644 tests/ArchitectureTests/packages.lock.json
create mode 100644 tests/IntegrationTests/packages.lock.json
create mode 100644 tests/TestData/packages.lock.json
create mode 100644 tests/UnitTests/packages.lock.json
diff --git a/.github/workflows/build-validation.yml b/.github/workflows/build-validation.yml
index 793cd3e..74236f5 100644
--- a/.github/workflows/build-validation.yml
+++ b/.github/workflows/build-validation.yml
@@ -5,6 +5,11 @@ on:
branches:
- main
- develop
+ paths-ignore:
+ - "**/*.md"
+ - "**/*.gitignore"
+ - "**/*.gitattributes"
+ workflow_dispatch:
env:
DOTNET_VERSION: "10.0.x" # The .NET SDK version to use
@@ -20,9 +25,11 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
+ cache: true
+ cache-dependency-path: "**/packages.lock.json"
- name: Install dependencies
- run: dotnet restore
+ run: dotnet restore --locked-mode
- name: Build
run: dotnet build --configuration Release --no-restore
diff --git a/.github/workflows/test-validation.yml b/.github/workflows/test-validation.yml
index a348eb6..b3d58c2 100644
--- a/.github/workflows/test-validation.yml
+++ b/.github/workflows/test-validation.yml
@@ -5,6 +5,11 @@ on:
branches:
- main
- develop
+ paths-ignore:
+ - "**/*.md"
+ - "**/*.gitignore"
+ - "**/*.gitattributes"
+ workflow_dispatch:
env:
DOTNET_VERSION: "10.0.x" # The .NET SDK version to use
@@ -20,9 +25,11 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
+ cache: true
+ cache-dependency-path: "**/packages.lock.json"
- name: Install dependencies
- run: dotnet restore
+ run: dotnet restore --locked-mode
- name: Build
run: dotnet build --configuration Release --no-restore
diff --git a/Directory.Build.props b/Directory.Build.props
index f51c3df..6b3c0ef 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -3,6 +3,7 @@
net10.0
enable
enable
+ true
latest-Recommended
true
true
diff --git a/backend/Application/packages.lock.json b/backend/Application/packages.lock.json
new file mode 100644
index 0000000..bbacc28
--- /dev/null
+++ b/backend/Application/packages.lock.json
@@ -0,0 +1,124 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Microsoft.EntityFrameworkCore": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "Direct",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "Direct",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "domain": {
+ "type": "Project"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/Domain/packages.lock.json b/backend/Domain/packages.lock.json
new file mode 100644
index 0000000..f6639bd
--- /dev/null
+++ b/backend/Domain/packages.lock.json
@@ -0,0 +1,13 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/Infrastructure/packages.lock.json b/backend/Infrastructure/packages.lock.json
new file mode 100644
index 0000000..d084bac
--- /dev/null
+++ b/backend/Infrastructure/packages.lock.json
@@ -0,0 +1,401 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "ClosedXML": {
+ "type": "Direct",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "Handlebars.Net": {
+ "type": "Direct",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "Direct",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.Extensions.Caching.Memory": "9.0.4",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.3",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.4",
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/WebApi/packages.lock.json b/backend/WebApi/packages.lock.json
new file mode 100644
index 0000000..d245387
--- /dev/null
+++ b/backend/WebApi/packages.lock.json
@@ -0,0 +1,700 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Asp.Versioning.Http": {
+ "type": "Direct",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "Xu4xF62Cu9JqYi/CTa2TiK5kyHoa4EluPynj/bPFWDmlTIPzuJQbBI5RgFYVRFHjFVvWMoA77acRaFu7i7Wzqg==",
+ "dependencies": {
+ "Asp.Versioning.Abstractions": "8.1.0"
+ }
+ },
+ "Asp.Versioning.Mvc.ApiExplorer": {
+ "type": "Direct",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "a90gW/4TF/14Bjiwg9LqNtdKGC4G3gu02+uynq3bCISfQm48km5chny4Yg5J4hixQPJUwwJJ9Do1G+jM8L9h3g==",
+ "dependencies": {
+ "Asp.Versioning.Mvc": "8.1.0"
+ }
+ },
+ "FluentValidation.DependencyInjectionExtensions": {
+ "type": "Direct",
+ "requested": "[12.1.1, )",
+ "resolved": "12.1.1",
+ "contentHash": "D0VXh4dtjjX2aQizuaa0g6R8X3U1JaVqJPfGCvLwZX9t/O2h7tkpbitbadQMfwcgSPdDbI2vDxuwRMv/Uf9dHA==",
+ "dependencies": {
+ "FluentValidation": "12.1.1"
+ }
+ },
+ "Microsoft.AspNetCore.OpenApi": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "0aqIF1t+sA2T62LIeMtXGSiaV7keGQaJnvwwmu+htQdjCaKYARfXAeqp4nHH9y2etpilyZ/tnQzZg4Ilmo/c4Q==",
+ "dependencies": {
+ "Microsoft.OpenApi": "2.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.Tools": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "Gx6AWCf1CsBHTbvVVWBYBKp6hrwZt0IgBigoBPaybwOBG2EFIfZc7NP2BoR6r56YuuikbPIzCuvQuFYNnX43+A==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Design": "10.0.0"
+ }
+ },
+ "Serilog.AspNetCore": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "a/cNa1mY4On1oJlfGG1wAvxjp5g7OEzk/Jf/nm7NF9cWoE7KlZw1GldrifUBWm9oKibHkR7Lg/l5jy3y7ACR8w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Hosting": "10.0.0",
+ "Serilog.Formatting.Compact": "3.0.0",
+ "Serilog.Settings.Configuration": "10.0.0",
+ "Serilog.Sinks.Console": "6.1.1",
+ "Serilog.Sinks.Debug": "3.0.0",
+ "Serilog.Sinks.File": "7.0.0"
+ }
+ },
+ "Serilog.Sinks.Console": {
+ "type": "Direct",
+ "requested": "[6.1.1, )",
+ "resolved": "6.1.1",
+ "contentHash": "8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Sinks.File": {
+ "type": "Direct",
+ "requested": "[7.0.1-dev-02315, )",
+ "resolved": "7.0.1-dev-02315",
+ "contentHash": "LuwBs0Hrr7ptVY/u+h+GJ2Of0+Uv3JiISD3ipiuZYnsy+bqeHEC1LQPVTPW9MgjY3tg3B6HObVbL84qGBcbdBA==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "Asp.Versioning.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "mpeNZyMdvrHztJwR1sXIUQ+3iioEU97YMBnFA9WLbsPOYhGwDJnqJMmEd8ny7kcmS9OjTHoEuX/bSXXY3brIFA=="
+ },
+ "Asp.Versioning.Mvc": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "BMAJM2sGsTUw5FQ9upKQt6GFoldWksePgGpYjl56WSRvIuE3UxKZh0gAL+wDTIfLshUZm97VCVxlOGyrcjWz9Q==",
+ "dependencies": {
+ "Asp.Versioning.Http": "8.1.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Humanizer.Core": {
+ "type": "Transitive",
+ "resolved": "2.14.1",
+ "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.Build": {
+ "type": "Transitive",
+ "resolved": "17.7.2",
+ "contentHash": "AmWnumxsMiRycFfE3kq/XnFFTAoPpCWl3UuiKQWCa5Z0+hBKVoiydzS2iXJGd3x+jry+qaTR9GzoezjV9NFT5A==",
+ "dependencies": {
+ "Microsoft.Build.Framework": "17.7.2",
+ "Microsoft.NET.StringTools": "17.7.2",
+ "System.Configuration.ConfigurationManager": "7.0.0",
+ "System.Reflection.MetadataLoadContext": "7.0.0",
+ "System.Security.Permissions": "7.0.0"
+ }
+ },
+ "Microsoft.Build.Framework": {
+ "type": "Transitive",
+ "resolved": "17.14.28",
+ "contentHash": "wRcyTzGV0LRAtFdrddtioh59Ky4/zbvyraP0cQkDzRSRkhgAQb0K88D/JNC6VHLIXanRi3mtV1jU0uQkBwmiVg=="
+ },
+ "Microsoft.Build.Tasks.Core": {
+ "type": "Transitive",
+ "resolved": "17.14.28",
+ "contentHash": "jk3O0tXp9QWPXhLJ7Pl8wm/eGtGgA1++vwHGWEmnwMU6eP//ghtcCUpQh9CQMwEKGDnH0aJf285V1s8yiSlKfQ==",
+ "dependencies": {
+ "Microsoft.Build.Framework": "17.14.28",
+ "Microsoft.Build.Utilities.Core": "17.14.28",
+ "Microsoft.NET.StringTools": "17.14.28",
+ "System.CodeDom": "9.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.0",
+ "System.Formats.Nrbf": "9.0.0",
+ "System.Resources.Extensions": "9.0.0",
+ "System.Security.Cryptography.Pkcs": "9.0.0",
+ "System.Security.Cryptography.ProtectedData": "9.0.0"
+ }
+ },
+ "Microsoft.Build.Utilities.Core": {
+ "type": "Transitive",
+ "resolved": "17.14.28",
+ "contentHash": "rhSdPo8QfLXXWM+rY0x0z1G4KK4ZhMoIbHROyDj8MUBFab9nvHR0NaMnjzOgXldhmD2zi2ir8d6xCatNzlhF5g==",
+ "dependencies": {
+ "Microsoft.Build.Framework": "17.14.28",
+ "Microsoft.NET.StringTools": "17.14.28",
+ "System.Configuration.ConfigurationManager": "9.0.0",
+ "System.Security.Cryptography.ProtectedData": "9.0.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Transitive",
+ "resolved": "3.11.0",
+ "contentHash": "v/EW3UE8/lbEYHoC2Qq7AR/DnmvpgdtAMndfQNmpuIMx/Mto8L5JnuCfdBYtgvalQOtfNCnxFejxuRrryvUTsg=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "PC3tuwZYnC+idaPuoC/AZpEdwrtX7qFpmnrfQkgobGIWiYmGi5MCRtl5mx6QrfMGQpK78X2lfIEoZDLg/qnuHg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "568a6wcTivauIhbeWcCwfWwIn7UV7MeHEBvFB2uzGIpM2OhJ4eM/FZ8KS0yhPoNxnSpjGzz7x7CIjTxhslojQA==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp.Workspaces": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "QkgCEM4qJo6gdtblXtNgHqtykS61fxW+820hx5JN6n9DD4mQtqNB+6fPeJ3GQWg6jkkGz6oG9yZq7H3Gf0zwYw==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.CSharp": "[4.14.0]",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]",
+ "Microsoft.CodeAnalysis.Workspaces.Common": "[4.14.0]",
+ "System.Composition": "9.0.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.Workspaces.Common": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "wNVK9JrqjqDC/WgBUFV6henDfrW87NPfo98nzah/+M/G1D6sBOPtXwqce3UQNn+6AjTnmkHYN1WV9XmTlPemTw==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]",
+ "System.Composition": "9.0.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.Workspaces.MSBuild": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "YU7Sguzm1Cuhi2U6S0DRKcVpqAdBd2QmatpyE0KqYMJogJ9E27KHOWGUzAOjsyjAM7sNaUk+a8VPz24knDseFw==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.Build": "17.7.2",
+ "Microsoft.Build.Framework": "17.7.2",
+ "Microsoft.Build.Tasks.Core": "17.7.2",
+ "Microsoft.Build.Utilities.Core": "17.7.2",
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Workspaces.Common": "[4.14.0]",
+ "Newtonsoft.Json": "13.0.3",
+ "System.CodeDom": "7.0.0",
+ "System.Composition": "9.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.0",
+ "System.Resources.Extensions": "9.0.0",
+ "System.Security.Cryptography.Pkcs": "7.0.2",
+ "System.Security.Cryptography.ProtectedData": "9.0.0",
+ "System.Security.Permissions": "9.0.0",
+ "System.Windows.Extensions": "9.0.0"
+ }
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Design": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "R7BeFniEpBrHw8kKVtWiMG4PRAwJ4K1RZoQWB32Ak8ws3uvYH98DVp9Y2UBUgbwY5lR9wPlrxp7P3GGDQ7LUSQ==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.Build.Framework": "17.14.28",
+ "Microsoft.Build.Tasks.Core": "17.14.28",
+ "Microsoft.Build.Utilities.Core": "17.14.28",
+ "Microsoft.CodeAnalysis.CSharp": "4.14.0",
+ "Microsoft.CodeAnalysis.CSharp.Workspaces": "4.14.0",
+ "Microsoft.CodeAnalysis.Workspaces.MSBuild": "4.14.0",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Mono.TextTemplating": "3.0.0",
+ "Newtonsoft.Json": "13.0.3"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.NET.StringTools": {
+ "type": "Transitive",
+ "resolved": "17.14.28",
+ "contentHash": "DMIeWDlxe0Wz0DIhJZ2FMoGQAN2yrGZOi5jjFhRYHWR5ONd0CS6IpAHlRnA7uA/5BF+BADvgsETxW2XrPiFc1A=="
+ },
+ "Microsoft.OpenApi": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw=="
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "Mono.TextTemplating": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "YqueG52R/Xej4VVbKuRIodjiAhV0HR/XVbLbNrJhCZnzjnSjgMJ/dCdV0akQQxavX6hp/LC6rqLGLcXeQYU7XA==",
+ "dependencies": {
+ "System.CodeDom": "6.0.0"
+ }
+ },
+ "Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.3",
+ "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "Serilog.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "E7juuIc+gzoGxgzFooFgAV8g9BfiSXNKsUok9NmEpyAXg2odkcPsMa/Yo4axkJRlh0se7mkYQ1GXDaBemR+b6w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Serilog.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "vx0kABKl2dWbBhhqAfTOk53/i8aV/5VaT3a6il9gn72Wqs2pM7EK2OB6No6xdqK2IaY6Zf9gdjLuK9BVa2rT+Q==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ },
+ "Serilog.Formatting.Compact": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Settings.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LNq+ibS1sbhTqPV1FIE69/9AJJbfaOhnaqkzcjFy95o+4U+STsta9mi97f1smgXsWYKICDeGUf8xUGzd/52/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Serilog": "4.3.0"
+ }
+ },
+ "Serilog.Sinks.Debug": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.CodeDom": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "oTE5IfuMoET8yaZP/vdvy9xO47guAv/rOhe4DODuFBN3ySprcQOlXqO3j+e/H/YpKKR5sglrxRaZ2HYOhNJrqA=="
+ },
+ "System.Composition": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "3Djj70fFTraOarSKmRnmRy/zm4YurICm+kiCtI0dYRqGJnLX6nJ+G3WYuFJ173cAPax/gh96REcbNiVqcrypFQ==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "9.0.0",
+ "System.Composition.Convention": "9.0.0",
+ "System.Composition.Hosting": "9.0.0",
+ "System.Composition.Runtime": "9.0.0",
+ "System.Composition.TypedParts": "9.0.0"
+ }
+ },
+ "System.Composition.AttributedModel": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "iri00l/zIX9g4lHMY+Nz0qV1n40+jFYAmgsaiNn16xvt2RDwlqByNG4wgblagnDYxm3YSQQ0jLlC/7Xlk9CzyA=="
+ },
+ "System.Composition.Convention": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "+vuqVP6xpi582XIjJi6OCsIxuoTZfR0M7WWufk3uGDeCl3wGW6KnpylUJ3iiXdPByPE0vR5TjJgR6hDLez4FQg==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "9.0.0"
+ }
+ },
+ "System.Composition.Hosting": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "OFqSeFeJYr7kHxDfaViGM1ymk7d4JxK//VSoNF9Ux0gpqkLsauDZpu89kTHHNdCWfSljbFcvAafGyBoY094btQ==",
+ "dependencies": {
+ "System.Composition.Runtime": "9.0.0"
+ }
+ },
+ "System.Composition.Runtime": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "w1HOlQY1zsOWYussjFGZCEYF2UZXgvoYnS94NIu2CBnAGMbXFAX8PY8c92KwUItPmowal68jnVLBCzdrWLeEKA=="
+ },
+ "System.Composition.TypedParts": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "aRZlojCCGEHDKqh43jaDgaVpYETsgd7Nx4g1zwLKMtv4iTo0627715ajEFNpEEBTgLmvZuv8K0EVxc3sM4NWJA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "9.0.0",
+ "System.Composition.Hosting": "9.0.0",
+ "System.Composition.Runtime": "9.0.0"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Formats.Nrbf": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "F/6tNE+ckmdFeSQAyQo26bQOqfPFKEfZcuqnp4kBE6/7jP26diP+QTHCJJ6vpEfaY6bLy+hBLiIQUSxSmNwLkA=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Reflection.MetadataLoadContext": {
+ "type": "Transitive",
+ "resolved": "7.0.0",
+ "contentHash": "z9PvtMJra5hK8n+g0wmPtaG7HQRZpTmIPRw5Z0LEemlcdQMHuTD5D7OAY/fZuuz1L9db++QOcDF0gJTLpbMtZQ=="
+ },
+ "System.Resources.Extensions": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "tvhuT1D2OwPROdL1kRWtaTJliQo0WdyhvwDpd8RM997G7m3Hya5nhbYhNTS75x6Vu+ypSOgL5qxDCn8IROtCxw==",
+ "dependencies": {
+ "System.Formats.Nrbf": "9.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "System.Security.Permissions": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "H2VFD4SFVxieywNxn9/epb63/IOcPPfA0WOtfkljzNfu7GCcHIBQNuwP6zGCEIi7Ci/oj8aLPUNK9sYImMFf4Q==",
+ "dependencies": {
+ "System.Windows.Extensions": "9.0.0"
+ }
+ },
+ "System.Windows.Extensions": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "U9msthvnH2Fsw7xwAvIhNHOdnIjOQTwOc8Vd0oGOsiRcGMGoBFlUD6qtYawRUoQdKH9ysxesZ9juFElt1Jw/7A=="
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "infrastructure": {
+ "type": "Project",
+ "dependencies": {
+ "Application": "[1.0.0, )",
+ "ClosedXML": "[0.105.0, )",
+ "Handlebars.Net": "[2.1.6, )",
+ "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.0, )",
+ "PuppeteerSharp": "[20.2.5, )"
+ }
+ },
+ "ClosedXML": {
+ "type": "CentralTransitive",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "FluentValidation": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.0, )",
+ "resolved": "12.1.1",
+ "contentHash": "EPpkIe1yh1a0OXyC100oOA8WMbZvqUu5plwhvYcb7oSELfyUZzfxV48BLhvs3kKo4NwG7MGLNgy1RJiYtT8Dpw=="
+ },
+ "Handlebars.Net": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "CentralTransitive",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw=="
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/frontend/Console/packages.lock.json b/frontend/Console/packages.lock.json
new file mode 100644
index 0000000..9f42c1a
--- /dev/null
+++ b/frontend/Console/packages.lock.json
@@ -0,0 +1,332 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Microsoft.Extensions.Hosting": {
+ "type": "Direct",
+ "requested": "[10.0.1, )",
+ "resolved": "10.0.1",
+ "contentHash": "0jjfjQSOFZlHhwOoIQw0WyzxtkDMYdnPY3iFrOLasxYq/5J4FDt1HWT8TktBclOVjFY1FOOkoOc99X7AhbqSIw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.1",
+ "Microsoft.Extensions.Configuration.CommandLine": "10.0.1",
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.1",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.1",
+ "Microsoft.Extensions.Configuration.Json": "10.0.1",
+ "Microsoft.Extensions.Configuration.UserSecrets": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Diagnostics": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.1",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.1",
+ "Microsoft.Extensions.Logging.Console": "10.0.1",
+ "Microsoft.Extensions.Logging.Debug": "10.0.1",
+ "Microsoft.Extensions.Logging.EventLog": "10.0.1",
+ "Microsoft.Extensions.Logging.EventSource": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1"
+ }
+ },
+ "Refit.HttpClientFactory": {
+ "type": "Direct",
+ "requested": "[9.0.2, )",
+ "resolved": "9.0.2",
+ "contentHash": "lv9vBbPaOZ6PARmWLkB3v+wBqoBDiI5ROS5KTbJEAAXMVaPG5V+AdjNmU+8NFkztZzJRqujREqmY69w7afRhJA==",
+ "dependencies": {
+ "Microsoft.Extensions.Http": "9.0.3",
+ "Refit": "9.0.2"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "Spectre.Console": {
+ "type": "Direct",
+ "requested": "[0.54.1-alpha.0.10, )",
+ "resolved": "0.54.1-alpha.0.10",
+ "contentHash": "qphEEXM7f82A6TH/ltagRFW3P0Uk48dEhBWm6KoW2iMn1uaGAC3cT661xWaqQqtiXw0xD1qVBagZXlmfinhkig=="
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "njoRekyMIK+smav8B6KL2YgIfUtlsRNuT7wvurpLW+m/hoRKVnoELk2YxnUnWRGScCd1rukLMxShwLqEOKowDg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "kPlU11hql+L9RjrN2N9/0GcRcRcZrNFlLLjadasFWeBORT6pL6OE+RYRk90GGCyVGSxTK+e1/f3dsMj5zpFFiQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "Lp4CZIuTVXtlvkAnTq6QvMSW7+H62gX2cU2vdFxHQUxvrWTpi7LwYI3X+YAyIS0r12/p7gaosco7efIxL4yFNw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.CommandLine": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "s5cxcdtIig66YT3J+7iHflMuorznK8kXuwBBPHMp4KImx5ZGE3FRa1Nj9fI/xMwFV+KzUMjqZ2MhOedPH8LiBQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "csD8Eps3HQ3yc0x6NhgTV+aIFKSs3qVlVCtFnMHz/JOjnv7eEj/qSXKXiK9LzBzB1qSfAVqFnB5iaX2nUmagIQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.FileExtensions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "N/6GiwiZFCBFZDk3vg1PhHW3zMqqu5WWpmeZAA9VTXv7Q8pr8NZR/EQsH0DjzqydDksJtY6EQBsu81d5okQOlA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Json": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "0zW3eYBJlRctmgqk5s0kFIi5o5y2g80mvGCD8bkYxREPQlKUnr0ndU/Sop+UDIhyWN0fIi4RW63vo7BKTi7ncA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Configuration.UserSecrets": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "ULEJ0nkaW90JYJGkFujPcJtADXcJpXiSOLbokPcWJZ8iDbtDINifEYAUVqZVr81IDNTrRFul6O8RolOKOsgFPg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Configuration.Json": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "zerXV0GAR9LCSXoSIApbWn+Dq1/T+6vbXMHGduq1LoVQRHT0BXsGQEau0jeLUBUcsoF/NaUT8ADPu8b+eNcIyg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "oIy8fQxxbUsSrrOvgBqlVgOeCtDmrcynnTG+FQufcUWBrwyPfwlUkCDB2vaiBeYPyT+20u9/HeuHeBf+H4F/8g=="
+ },
+ "Microsoft.Extensions.Diagnostics": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "YaocqxscJLxLit0F5yq2XyB+9C7rSRfeTL7MJIl7XwaOoUO3i0EqfO2kmtjiRduYWw7yjcSINEApYZbzjau2gQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "QMoMrkNpnQym5mpfdxfxpRDuqLpsOuztguFvzH9p+Ex+do+uLFoi7UkAsBO4e9/tNR3eMFraFf2fOAi2cp3jjA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "+b3DligYSZuoWltU5YdbMpIEUHNZPgPrzWfNiIuDkMdqOl93UxYB5KzS3lgpRfTXJhTNpo/CZ8w/sTkDTPDdxQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Physical": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "4bxzGXIzZnz0Bf7czQ72jGvpOqJsRW/44PS7YLFXTTnu6cNcPvmSREDvBoH0ZVP2hAbMfL4sUoCUn54k70jPWw==",
+ "dependencies": {
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileSystemGlobbing": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.FileSystemGlobbing": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "49dFvGJjLSwGn76eHnP1gBvCJkL8HRYpCrG0DCvsP6wRpEQRLN2Fq8rTxbP+6jS7jmYKCnSVO5C65v4mT3rzeA=="
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "qmoQkVZcbm4/gFpted3W3Y+1kTATZTcUhV3mRkbtpfBXlxWCHwh/2oMffVcCruaGOfJuEnyAsGyaSUouSdECOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.1",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Http": {
+ "type": "Transitive",
+ "resolved": "9.0.3",
+ "contentHash": "rwChgI3lPqvUzsCN3egSW/6v4kP9/RQ2QrkZUwyAiHiwEoIB6QbYkATNvUsgjV6nfrekocyciCzy53ZFRuSaHA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.3",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.3",
+ "Microsoft.Extensions.Diagnostics": "9.0.3",
+ "Microsoft.Extensions.Logging": "9.0.3",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.3",
+ "Microsoft.Extensions.Options": "9.0.3"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "9ItMpMLFZFJFqCuHLLbR3LiA4ahA8dMtYuXpXl2YamSDWZhYS9BruPprkftY0tYi2bQ0slNrixdFm+4kpz1g5w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "YkmyiPIWAXVb+lPIrM0LE5bbtLOJkCiRTFiHpkVOvhI7uTvCfoOHLEN0LcsY56GpSD7NqX3gJNpsaDe87/B3zg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "Zg8LLnfZs5o2RCHD/+9NfDtJ40swauemwCa7sI8gQoAye/UJHRZNpCtC7a5XE7l9Z7mdI8iMWnLZ6m7Q6S3jLg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.1",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.Console": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "38Q8sEHwQ/+wVO/mwQBa0fcdHbezFpusHE+vBw/dSr6Fq/kzZm3H/NQX511Jki/R3FHd64IY559gdlHZQtYeEA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.Debug": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "VqfTvbX9C6BA0VeIlpzPlljnNsXxiI5CdUHb9ksWERH94WQ6ft3oLGUAa4xKcDGu4xF+rIZ8wj7IOAd6/q7vGw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "Zp9MM+jFCa7oktIug62V9eNygpkf+6kFVatF+UC/ODeUwIr5givYKy8fYSSI9sWdxqDqv63y1x0mm2VjOl8GOw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1",
+ "System.Diagnostics.EventLog": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventSource": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "WnFvZP+Y+lfeNFKPK/+mBpaCC7EeBDlobrQOqnP7rrw/+vE7yu8Rjczum1xbC0F/8cAHafog84DMp9200akMNQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Logging": "10.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "G6VVwywpJI4XIobetGHwg7wDOYC2L2XBYdtskxLaKF/Ynb5QBwLl7Q//wxAR2aVCLkMpoQrjSP9VoORkyddsNQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "pL78/Im7O3WmxHzlKUsWTYchKL881udU7E26gCD3T0+/tPhWVfjPwMzfN/MRKU7aoFYcOiqcG2k1QTlH5woWow==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.1",
+ "Microsoft.Extensions.Options": "10.0.1",
+ "Microsoft.Extensions.Primitives": "10.0.1"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "DO8XrJkp5x4PddDuc/CH37yDBCs9BYN6ijlKyR3vMb55BP1Vwh90vOX8bNfnKxr5B2qEI3D8bvbY1fFbDveDHQ=="
+ },
+ "Refit": {
+ "type": "Transitive",
+ "resolved": "9.0.2",
+ "contentHash": "zLAfOh1iYE1bXFdnPjX5V6Nq8d4vBwxXaCovNNcAt9Fz3mfxAqHS3fckbBX4wetVgN1A6tIOzrDtPTN2c4FNrQ=="
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.1",
+ "contentHash": "xfaHEHVDkMOOZR5S6ZGezD0+vekdH1Nx/9Ih8/rOqOGSOk1fxiN3u94bYkBW/wigj0Uw2Wt3vvRj9mtYdgwEjw=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ArchitectureTests/packages.lock.json b/tests/ArchitectureTests/packages.lock.json
new file mode 100644
index 0000000..7e06a96
--- /dev/null
+++ b/tests/ArchitectureTests/packages.lock.json
@@ -0,0 +1,726 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "coverlet.collector": {
+ "type": "Direct",
+ "requested": "[6.0.4, )",
+ "resolved": "6.0.4",
+ "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg=="
+ },
+ "Microsoft.NET.Test.Sdk": {
+ "type": "Direct",
+ "requested": "[18.0.1, )",
+ "resolved": "18.0.1",
+ "contentHash": "WNpu6vI2rA0pXY4r7NKxCN16XRWl5uHu6qjuyVLoDo6oYEggIQefrMjkRuibQHm/NslIUNCcKftvoWAN80MSAg==",
+ "dependencies": {
+ "Microsoft.CodeCoverage": "18.0.1",
+ "Microsoft.TestPlatform.TestHost": "18.0.1"
+ }
+ },
+ "NetArchTest.Rules": {
+ "type": "Direct",
+ "requested": "[1.3.2, )",
+ "resolved": "1.3.2",
+ "contentHash": "puPyNXkwJq8/UwXhHV8NrzNzkQl4IxEbcP+3PU0xLRiOedsVpaSdpwHhvOZfI0VwTcRvawCNxYQcSRbD4RUg4w==",
+ "dependencies": {
+ "Mono.Cecil": "0.11.3"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "xunit": {
+ "type": "Direct",
+ "requested": "[2.9.3, )",
+ "resolved": "2.9.3",
+ "contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
+ "dependencies": {
+ "xunit.analyzers": "1.18.0",
+ "xunit.assert": "2.9.3",
+ "xunit.core": "[2.9.3]"
+ }
+ },
+ "xunit.runner.visualstudio": {
+ "type": "Direct",
+ "requested": "[3.1.5, )",
+ "resolved": "3.1.5",
+ "contentHash": "tKi7dSTwP4m5m9eXPM2Ime4Kn7xNf4x4zT9sdLO/G4hZVnQCRiMTWoSZqI/pYTVeI27oPPqHBKYI/DjJ9GsYgA=="
+ },
+ "Asp.Versioning.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "mpeNZyMdvrHztJwR1sXIUQ+3iioEU97YMBnFA9WLbsPOYhGwDJnqJMmEd8ny7kcmS9OjTHoEuX/bSXXY3brIFA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "8.0.0"
+ }
+ },
+ "Asp.Versioning.Mvc": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "BMAJM2sGsTUw5FQ9upKQt6GFoldWksePgGpYjl56WSRvIuE3UxKZh0gAL+wDTIfLshUZm97VCVxlOGyrcjWz9Q==",
+ "dependencies": {
+ "Asp.Versioning.Http": "8.1.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.CodeCoverage": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "O+utSr97NAJowIQT/OVp3Lh9QgW/wALVTP4RG1m2AfFP4IyJmJz0ZBmFJUsRQiAPgq6IRC0t8AAzsiPIsaUDEA=="
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.Extensions.Caching.Memory": "9.0.4",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "H4SWETCh/cC5L1WtWchHR6LntGk3rDTTznZMssr4cL8IbDmMWBxY+MOGDc/ASnqNolLKPIWHWeuC1ddiL/iNPw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "tMF9wNh+hlyYDWB8mrFCQHQmWHlRosol1b/N2Jrefy1bFLnuTlgSYmPyHNmz8xVQgs7DpXytBRWxGhG+mSTp0g==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "SfK89ytD61S7DgzorFljSkUeluC1ncn6dtZgwc0ot39f/BEYWBl5jpgvodxduoYAs1d9HG8faCDRZxE95UMo2A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "/ppSdehKk3fuXjlqCDgSOtjRK/pSHU8eWgzSHfHdwVm5BP4Dgejehkw+PtxKG2j98qTDEHDst2Y99aNsmJldmw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "KrN6TGFwCwqOkLLk/idW/XtDQh+8In+CL9T4M1Dx+5ScsjTq4TlVbal8q532m82UYrMr6RiQJF2HvYCN0QwVsA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.OpenApi": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw=="
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "Microsoft.TestPlatform.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "qT/mwMcLF9BieRkzOBPL2qCopl8hQu6A1P7JWAoj/FMu5i9vds/7cjbJ/LLtaiwWevWLAeD5v5wjQJ/l6jvhWQ=="
+ },
+ "Microsoft.TestPlatform.TestHost": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "uDJKAEjFTaa2wHdWlfo6ektyoh+WD4/Eesrwb4FpBFKsLGehhACVnwwTI4qD3FrIlIEPlxdXg3SyrYRIcO+RRQ==",
+ "dependencies": {
+ "Microsoft.TestPlatform.ObjectModel": "18.0.1",
+ "Newtonsoft.Json": "13.0.3"
+ }
+ },
+ "Mono.Cecil": {
+ "type": "Transitive",
+ "resolved": "0.11.3",
+ "contentHash": "DNYE+io5XfEE8+E+5padThTPHJARJHbz1mhbhMPNrrWGKVKKqj/KEeLvbawAmbIcT73NuxLV7itHZaYCZcVWGg=="
+ },
+ "Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.3",
+ "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "Serilog.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "E7juuIc+gzoGxgzFooFgAV8g9BfiSXNKsUok9NmEpyAXg2odkcPsMa/Yo4axkJRlh0se7mkYQ1GXDaBemR+b6w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Serilog.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "vx0kABKl2dWbBhhqAfTOk53/i8aV/5VaT3a6il9gn72Wqs2pM7EK2OB6No6xdqK2IaY6Zf9gdjLuK9BVa2rT+Q==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Serilog": "4.2.0"
+ }
+ },
+ "Serilog.Formatting.Compact": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Settings.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LNq+ibS1sbhTqPV1FIE69/9AJJbfaOhnaqkzcjFy95o+4U+STsta9mi97f1smgXsWYKICDeGUf8xUGzd/52/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Serilog": "4.3.0"
+ }
+ },
+ "Serilog.Sinks.Debug": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.3",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.4",
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "xunit.abstractions": {
+ "type": "Transitive",
+ "resolved": "2.0.3",
+ "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
+ },
+ "xunit.analyzers": {
+ "type": "Transitive",
+ "resolved": "1.18.0",
+ "contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
+ },
+ "xunit.assert": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
+ },
+ "xunit.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]",
+ "xunit.extensibility.execution": "[2.9.3]"
+ }
+ },
+ "xunit.extensibility.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "kf3si0YTn2a8J8eZNb+zFpwfoyvIrQ7ivNk5ZYA5yuYk1bEtMe4DxJ2CF/qsRgmEnDr7MnW1mxylBaHTZ4qErA==",
+ "dependencies": {
+ "xunit.abstractions": "2.0.3"
+ }
+ },
+ "xunit.extensibility.execution": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "yMb6vMESlSrE3Wfj7V6cjQ3S4TXdXpRqYeNEI3zsX31uTsGMJjEw6oD5F5u1cHnMptjhEECnmZSsPxB6ChZHDQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]"
+ }
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "infrastructure": {
+ "type": "Project",
+ "dependencies": {
+ "Application": "[1.0.0, )",
+ "ClosedXML": "[0.105.0, )",
+ "Handlebars.Net": "[2.1.6, )",
+ "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.0, )",
+ "PuppeteerSharp": "[20.2.5, )"
+ }
+ },
+ "webapi": {
+ "type": "Project",
+ "dependencies": {
+ "Asp.Versioning.Http": "[8.1.0, )",
+ "Asp.Versioning.Mvc.ApiExplorer": "[8.1.0, )",
+ "FluentValidation.DependencyInjectionExtensions": "[12.1.1, )",
+ "Infrastructure": "[1.0.0, )",
+ "Microsoft.AspNetCore.OpenApi": "[10.0.0, )",
+ "Serilog.AspNetCore": "[10.0.0, )",
+ "Serilog.Sinks.Console": "[6.1.1, )",
+ "Serilog.Sinks.File": "[7.0.1-dev-02315, )"
+ }
+ },
+ "Asp.Versioning.Http": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "Xu4xF62Cu9JqYi/CTa2TiK5kyHoa4EluPynj/bPFWDmlTIPzuJQbBI5RgFYVRFHjFVvWMoA77acRaFu7i7Wzqg==",
+ "dependencies": {
+ "Asp.Versioning.Abstractions": "8.1.0"
+ }
+ },
+ "Asp.Versioning.Mvc.ApiExplorer": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "a90gW/4TF/14Bjiwg9LqNtdKGC4G3gu02+uynq3bCISfQm48km5chny4Yg5J4hixQPJUwwJJ9Do1G+jM8L9h3g==",
+ "dependencies": {
+ "Asp.Versioning.Mvc": "8.1.0"
+ }
+ },
+ "ClosedXML": {
+ "type": "CentralTransitive",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "FluentValidation": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.0, )",
+ "resolved": "12.1.1",
+ "contentHash": "EPpkIe1yh1a0OXyC100oOA8WMbZvqUu5plwhvYcb7oSELfyUZzfxV48BLhvs3kKo4NwG7MGLNgy1RJiYtT8Dpw=="
+ },
+ "FluentValidation.DependencyInjectionExtensions": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.1, )",
+ "resolved": "12.1.1",
+ "contentHash": "D0VXh4dtjjX2aQizuaa0g6R8X3U1JaVqJPfGCvLwZX9t/O2h7tkpbitbadQMfwcgSPdDbI2vDxuwRMv/Uf9dHA==",
+ "dependencies": {
+ "FluentValidation": "12.1.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0"
+ }
+ },
+ "Handlebars.Net": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.AspNetCore.OpenApi": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "0aqIF1t+sA2T62LIeMtXGSiaV7keGQaJnvwwmu+htQdjCaKYARfXAeqp4nHH9y2etpilyZ/tnQzZg4Ilmo/c4Q==",
+ "dependencies": {
+ "Microsoft.OpenApi": "2.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "CentralTransitive",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ },
+ "Serilog.AspNetCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "a/cNa1mY4On1oJlfGG1wAvxjp5g7OEzk/Jf/nm7NF9cWoE7KlZw1GldrifUBWm9oKibHkR7Lg/l5jy3y7ACR8w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Hosting": "10.0.0",
+ "Serilog.Formatting.Compact": "3.0.0",
+ "Serilog.Settings.Configuration": "10.0.0",
+ "Serilog.Sinks.Console": "6.1.1",
+ "Serilog.Sinks.Debug": "3.0.0",
+ "Serilog.Sinks.File": "7.0.0"
+ }
+ },
+ "Serilog.Sinks.Console": {
+ "type": "CentralTransitive",
+ "requested": "[6.1.1, )",
+ "resolved": "6.1.1",
+ "contentHash": "8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Sinks.File": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.1-dev-02315, )",
+ "resolved": "7.0.1-dev-02315",
+ "contentHash": "LuwBs0Hrr7ptVY/u+h+GJ2Of0+Uv3JiISD3ipiuZYnsy+bqeHEC1LQPVTPW9MgjY3tg3B6HObVbL84qGBcbdBA==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/IntegrationTests/packages.lock.json b/tests/IntegrationTests/packages.lock.json
new file mode 100644
index 0000000..5927e1b
--- /dev/null
+++ b/tests/IntegrationTests/packages.lock.json
@@ -0,0 +1,921 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Bogus": {
+ "type": "Direct",
+ "requested": "[35.6.5, )",
+ "resolved": "35.6.5",
+ "contentHash": "2FGZn+aAVHjmCgClgmGkTDBVZk0zkLvAKGaxEf5JL6b3i9JbHTE4wnuY4vHCuzlCmJdU6VZjgDfHwmYkQF8VAA=="
+ },
+ "coverlet.collector": {
+ "type": "Direct",
+ "requested": "[6.0.4, )",
+ "resolved": "6.0.4",
+ "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg=="
+ },
+ "Microsoft.AspNetCore.Mvc.Testing": {
+ "type": "Direct",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "Gdtv34h2qvynOEu+B2+6apBiiPhEs39namGax02UgaQMRetlxQ88p2/jK1eIdz3m1NRgYszNBN/jBdXkucZhvw==",
+ "dependencies": {
+ "Microsoft.AspNetCore.TestHost": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Microsoft.Extensions.Hosting": "10.0.0"
+ }
+ },
+ "Microsoft.NET.Test.Sdk": {
+ "type": "Direct",
+ "requested": "[18.0.1, )",
+ "resolved": "18.0.1",
+ "contentHash": "WNpu6vI2rA0pXY4r7NKxCN16XRWl5uHu6qjuyVLoDo6oYEggIQefrMjkRuibQHm/NslIUNCcKftvoWAN80MSAg==",
+ "dependencies": {
+ "Microsoft.CodeCoverage": "18.0.1",
+ "Microsoft.TestPlatform.TestHost": "18.0.1"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "xunit": {
+ "type": "Direct",
+ "requested": "[2.9.3, )",
+ "resolved": "2.9.3",
+ "contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
+ "dependencies": {
+ "xunit.analyzers": "1.18.0",
+ "xunit.assert": "2.9.3",
+ "xunit.core": "[2.9.3]"
+ }
+ },
+ "xunit.runner.visualstudio": {
+ "type": "Direct",
+ "requested": "[3.1.5, )",
+ "resolved": "3.1.5",
+ "contentHash": "tKi7dSTwP4m5m9eXPM2Ime4Kn7xNf4x4zT9sdLO/G4hZVnQCRiMTWoSZqI/pYTVeI27oPPqHBKYI/DjJ9GsYgA=="
+ },
+ "Asp.Versioning.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "mpeNZyMdvrHztJwR1sXIUQ+3iioEU97YMBnFA9WLbsPOYhGwDJnqJMmEd8ny7kcmS9OjTHoEuX/bSXXY3brIFA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "8.0.0"
+ }
+ },
+ "Asp.Versioning.Mvc": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "BMAJM2sGsTUw5FQ9upKQt6GFoldWksePgGpYjl56WSRvIuE3UxKZh0gAL+wDTIfLshUZm97VCVxlOGyrcjWz9Q==",
+ "dependencies": {
+ "Asp.Versioning.Http": "8.1.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Microsoft.AspNetCore.TestHost": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Q3ia+k+wYM3Iv/Qq5IETOdpz/R0xizs3WNAXz699vEQx5TMVAfG715fBSq9Thzopvx8dYZkxQ/mumTn6AJ/vGQ=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.CodeCoverage": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "O+utSr97NAJowIQT/OVp3Lh9QgW/wALVTP4RG1m2AfFP4IyJmJz0ZBmFJUsRQiAPgq6IRC0t8AAzsiPIsaUDEA=="
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.Extensions.Caching.Memory": "9.0.4",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "H4SWETCh/cC5L1WtWchHR6LntGk3rDTTznZMssr4cL8IbDmMWBxY+MOGDc/ASnqNolLKPIWHWeuC1ddiL/iNPw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "tMF9wNh+hlyYDWB8mrFCQHQmWHlRosol1b/N2Jrefy1bFLnuTlgSYmPyHNmz8xVQgs7DpXytBRWxGhG+mSTp0g==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.CommandLine": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "CRj5clwZciVs46GMhAthkFq3+JiNM15Bz9CRlCZLBmRdggD6RwoBphRJ+EUDK2f+cZZ1L2zqVaQrn1KueoU5Kg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TmFegsI/uCdwMBD4yKpmO+OkjVNHQL49Dh/ep83NI5rPUEoBK9OdsJo1zURc1A2FuS/R/Pos3wsTjlyLnguBLA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.FileExtensions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LqCTyF0twrG4tyEN6PpSC5ewRBDwCBazRUfCOdRddwaQ3n2S57GDDeYOlTLcbV/V2dxSSZWg5Ofr48h6BsBmxw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Json": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BIOPTEAZoeWbHlDT9Zudu+rpecZizFwhdIFRiyZKDml7JbayXmfTXKUt+ezifsSXfBkWDdJM10oDOxo8pufEng==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.UserSecrets": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "B4qHB6gQ2B3I52YRohSV7wetp01BQzi8jDmrtiVm6e4l8vH5vjqwxWcR5wumGWjdBkj1asJLLsDIocdyTQSP0A==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Configuration.Json": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Diagnostics": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "xjkxIPgrT0mKTfBwb+CVqZnRchyZgzKIfDQOp8z+WUC6vPe3WokIf71z+hJPkH0YBUYJwa7Z/al1R087ib9oiw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "SfK89ytD61S7DgzorFljSkUeluC1ncn6dtZgwc0ot39f/BEYWBl5jpgvodxduoYAs1d9HG8faCDRZxE95UMo2A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "/ppSdehKk3fuXjlqCDgSOtjRK/pSHU8eWgzSHfHdwVm5BP4Dgejehkw+PtxKG2j98qTDEHDst2Y99aNsmJldmw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Physical": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UZUQ74lQMmvcprlG8w+XpxBbyRDQqfb7GAnccITw32hdkUBlmm9yNC4xl4aR9YjgV3ounZcub194sdmLSfBmPA==",
+ "dependencies": {
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileSystemGlobbing": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileSystemGlobbing": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "5hfVl/e+bx1px2UkN+1xXhd3hu7Ui6ENItBzckFaRDQXfr+SHT/7qrCDrlQekCF/PBtEu2vtk87U2+gDEF8EhQ=="
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "KrN6TGFwCwqOkLLk/idW/XtDQh+8In+CL9T4M1Dx+5ScsjTq4TlVbal8q532m82UYrMr6RiQJF2HvYCN0QwVsA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "j8zcwhS6bYB6FEfaY3nYSgHdpiL2T+/V3xjpHtslVAegyI1JUbB9yAt/BFdvZdsNbY0Udm4xFtvfT/hUwcOOOg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Console": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "treWetuksp8LVb09fCJ5zNhNJjyDkqzVm83XxcrlWQnAdXznR140UUXo8PyEPBvFlHhjKhFQZEOP3Sk/ByCvEw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Debug": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A/4vBtVaySLBGj4qluye+KSbeVCCMa6GcTbxf2YgnSDHs9b9105+VojBJ1eJPel8F1ny0JOh+Ci3vgCKn69tNQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "EWda5nSXhzQZr3yJ3+XgIApOek+Hm+txhWCEzWNVPp/OfimL4qmvctgXu87m+S2RXw/AoUP8aLMNicJ2KWblVA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "System.Diagnostics.EventLog": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.EventSource": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "+Qc+kgoJi1w2A/Jm+7h04LcK2JoJkwAxKg7kBakkNRcemTmRGocqPa7rVNVGorTYruFrUS25GwkFNtOECnjhXg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "tL9cSl3maS5FPzp/3MtlZI21ExWhni0nnUCF8HY4npTsINw45n9SNDbkKXBMtFyUFGSsQep25fHIDN4f/Vp3AQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.OpenApi": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw=="
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "Microsoft.TestPlatform.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "qT/mwMcLF9BieRkzOBPL2qCopl8hQu6A1P7JWAoj/FMu5i9vds/7cjbJ/LLtaiwWevWLAeD5v5wjQJ/l6jvhWQ=="
+ },
+ "Microsoft.TestPlatform.TestHost": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "uDJKAEjFTaa2wHdWlfo6ektyoh+WD4/Eesrwb4FpBFKsLGehhACVnwwTI4qD3FrIlIEPlxdXg3SyrYRIcO+RRQ==",
+ "dependencies": {
+ "Microsoft.TestPlatform.ObjectModel": "18.0.1",
+ "Newtonsoft.Json": "13.0.3"
+ }
+ },
+ "Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.3",
+ "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "Serilog.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "E7juuIc+gzoGxgzFooFgAV8g9BfiSXNKsUok9NmEpyAXg2odkcPsMa/Yo4axkJRlh0se7mkYQ1GXDaBemR+b6w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Serilog.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "vx0kABKl2dWbBhhqAfTOk53/i8aV/5VaT3a6il9gn72Wqs2pM7EK2OB6No6xdqK2IaY6Zf9gdjLuK9BVa2rT+Q==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Serilog": "4.2.0"
+ }
+ },
+ "Serilog.Formatting.Compact": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Settings.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LNq+ibS1sbhTqPV1FIE69/9AJJbfaOhnaqkzcjFy95o+4U+STsta9mi97f1smgXsWYKICDeGUf8xUGzd/52/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Serilog": "4.3.0"
+ }
+ },
+ "Serilog.Sinks.Debug": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.3",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.4",
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "xunit.abstractions": {
+ "type": "Transitive",
+ "resolved": "2.0.3",
+ "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
+ },
+ "xunit.analyzers": {
+ "type": "Transitive",
+ "resolved": "1.18.0",
+ "contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
+ },
+ "xunit.assert": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
+ },
+ "xunit.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]",
+ "xunit.extensibility.execution": "[2.9.3]"
+ }
+ },
+ "xunit.extensibility.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "kf3si0YTn2a8J8eZNb+zFpwfoyvIrQ7ivNk5ZYA5yuYk1bEtMe4DxJ2CF/qsRgmEnDr7MnW1mxylBaHTZ4qErA==",
+ "dependencies": {
+ "xunit.abstractions": "2.0.3"
+ }
+ },
+ "xunit.extensibility.execution": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "yMb6vMESlSrE3Wfj7V6cjQ3S4TXdXpRqYeNEI3zsX31uTsGMJjEw6oD5F5u1cHnMptjhEECnmZSsPxB6ChZHDQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]"
+ }
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "infrastructure": {
+ "type": "Project",
+ "dependencies": {
+ "Application": "[1.0.0, )",
+ "ClosedXML": "[0.105.0, )",
+ "Handlebars.Net": "[2.1.6, )",
+ "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.0, )",
+ "PuppeteerSharp": "[20.2.5, )"
+ }
+ },
+ "testdata": {
+ "type": "Project",
+ "dependencies": {
+ "Bogus": "[35.6.5, )",
+ "WebApi": "[1.0.0, )"
+ }
+ },
+ "webapi": {
+ "type": "Project",
+ "dependencies": {
+ "Asp.Versioning.Http": "[8.1.0, )",
+ "Asp.Versioning.Mvc.ApiExplorer": "[8.1.0, )",
+ "FluentValidation.DependencyInjectionExtensions": "[12.1.1, )",
+ "Infrastructure": "[1.0.0, )",
+ "Microsoft.AspNetCore.OpenApi": "[10.0.0, )",
+ "Serilog.AspNetCore": "[10.0.0, )",
+ "Serilog.Sinks.Console": "[6.1.1, )",
+ "Serilog.Sinks.File": "[7.0.1-dev-02315, )"
+ }
+ },
+ "Asp.Versioning.Http": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "Xu4xF62Cu9JqYi/CTa2TiK5kyHoa4EluPynj/bPFWDmlTIPzuJQbBI5RgFYVRFHjFVvWMoA77acRaFu7i7Wzqg==",
+ "dependencies": {
+ "Asp.Versioning.Abstractions": "8.1.0"
+ }
+ },
+ "Asp.Versioning.Mvc.ApiExplorer": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "a90gW/4TF/14Bjiwg9LqNtdKGC4G3gu02+uynq3bCISfQm48km5chny4Yg5J4hixQPJUwwJJ9Do1G+jM8L9h3g==",
+ "dependencies": {
+ "Asp.Versioning.Mvc": "8.1.0"
+ }
+ },
+ "ClosedXML": {
+ "type": "CentralTransitive",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "FluentValidation": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.0, )",
+ "resolved": "12.1.1",
+ "contentHash": "EPpkIe1yh1a0OXyC100oOA8WMbZvqUu5plwhvYcb7oSELfyUZzfxV48BLhvs3kKo4NwG7MGLNgy1RJiYtT8Dpw=="
+ },
+ "FluentValidation.DependencyInjectionExtensions": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.1, )",
+ "resolved": "12.1.1",
+ "contentHash": "D0VXh4dtjjX2aQizuaa0g6R8X3U1JaVqJPfGCvLwZX9t/O2h7tkpbitbadQMfwcgSPdDbI2vDxuwRMv/Uf9dHA==",
+ "dependencies": {
+ "FluentValidation": "12.1.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0"
+ }
+ },
+ "Handlebars.Net": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.AspNetCore.OpenApi": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "0aqIF1t+sA2T62LIeMtXGSiaV7keGQaJnvwwmu+htQdjCaKYARfXAeqp4nHH9y2etpilyZ/tnQzZg4Ilmo/c4Q==",
+ "dependencies": {
+ "Microsoft.OpenApi": "2.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Hosting": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.1, )",
+ "resolved": "10.0.0",
+ "contentHash": "yKJiVdXkSfe9foojGpBRbuDPQI8YD71IO/aE8ehGjRHE0VkEF/YWkW6StthwuFF146pc2lypZrpk/Tks6Plwhw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.Configuration.CommandLine": "10.0.0",
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0",
+ "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0",
+ "Microsoft.Extensions.Configuration.Json": "10.0.0",
+ "Microsoft.Extensions.Configuration.UserSecrets": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Physical": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Configuration": "10.0.0",
+ "Microsoft.Extensions.Logging.Console": "10.0.0",
+ "Microsoft.Extensions.Logging.Debug": "10.0.0",
+ "Microsoft.Extensions.Logging.EventLog": "10.0.0",
+ "Microsoft.Extensions.Logging.EventSource": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "CentralTransitive",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ },
+ "Serilog.AspNetCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "a/cNa1mY4On1oJlfGG1wAvxjp5g7OEzk/Jf/nm7NF9cWoE7KlZw1GldrifUBWm9oKibHkR7Lg/l5jy3y7ACR8w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Hosting": "10.0.0",
+ "Serilog.Formatting.Compact": "3.0.0",
+ "Serilog.Settings.Configuration": "10.0.0",
+ "Serilog.Sinks.Console": "6.1.1",
+ "Serilog.Sinks.Debug": "3.0.0",
+ "Serilog.Sinks.File": "7.0.0"
+ }
+ },
+ "Serilog.Sinks.Console": {
+ "type": "CentralTransitive",
+ "requested": "[6.1.1, )",
+ "resolved": "6.1.1",
+ "contentHash": "8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Sinks.File": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.1-dev-02315, )",
+ "resolved": "7.0.1-dev-02315",
+ "contentHash": "LuwBs0Hrr7ptVY/u+h+GJ2Of0+Uv3JiISD3ipiuZYnsy+bqeHEC1LQPVTPW9MgjY3tg3B6HObVbL84qGBcbdBA==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/TestData/packages.lock.json b/tests/TestData/packages.lock.json
new file mode 100644
index 0000000..f08b81f
--- /dev/null
+++ b/tests/TestData/packages.lock.json
@@ -0,0 +1,621 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "Bogus": {
+ "type": "Direct",
+ "requested": "[35.6.5, )",
+ "resolved": "35.6.5",
+ "contentHash": "2FGZn+aAVHjmCgClgmGkTDBVZk0zkLvAKGaxEf5JL6b3i9JbHTE4wnuY4vHCuzlCmJdU6VZjgDfHwmYkQF8VAA=="
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "Asp.Versioning.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "mpeNZyMdvrHztJwR1sXIUQ+3iioEU97YMBnFA9WLbsPOYhGwDJnqJMmEd8ny7kcmS9OjTHoEuX/bSXXY3brIFA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "8.0.0"
+ }
+ },
+ "Asp.Versioning.Mvc": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "BMAJM2sGsTUw5FQ9upKQt6GFoldWksePgGpYjl56WSRvIuE3UxKZh0gAL+wDTIfLshUZm97VCVxlOGyrcjWz9Q==",
+ "dependencies": {
+ "Asp.Versioning.Http": "8.1.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.Extensions.Caching.Memory": "9.0.4",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "H4SWETCh/cC5L1WtWchHR6LntGk3rDTTznZMssr4cL8IbDmMWBxY+MOGDc/ASnqNolLKPIWHWeuC1ddiL/iNPw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "tMF9wNh+hlyYDWB8mrFCQHQmWHlRosol1b/N2Jrefy1bFLnuTlgSYmPyHNmz8xVQgs7DpXytBRWxGhG+mSTp0g==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "SfK89ytD61S7DgzorFljSkUeluC1ncn6dtZgwc0ot39f/BEYWBl5jpgvodxduoYAs1d9HG8faCDRZxE95UMo2A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "/ppSdehKk3fuXjlqCDgSOtjRK/pSHU8eWgzSHfHdwVm5BP4Dgejehkw+PtxKG2j98qTDEHDst2Y99aNsmJldmw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "KrN6TGFwCwqOkLLk/idW/XtDQh+8In+CL9T4M1Dx+5ScsjTq4TlVbal8q532m82UYrMr6RiQJF2HvYCN0QwVsA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.OpenApi": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw=="
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "Serilog.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "E7juuIc+gzoGxgzFooFgAV8g9BfiSXNKsUok9NmEpyAXg2odkcPsMa/Yo4axkJRlh0se7mkYQ1GXDaBemR+b6w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Serilog.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "vx0kABKl2dWbBhhqAfTOk53/i8aV/5VaT3a6il9gn72Wqs2pM7EK2OB6No6xdqK2IaY6Zf9gdjLuK9BVa2rT+Q==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Serilog": "4.2.0"
+ }
+ },
+ "Serilog.Formatting.Compact": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Settings.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LNq+ibS1sbhTqPV1FIE69/9AJJbfaOhnaqkzcjFy95o+4U+STsta9mi97f1smgXsWYKICDeGUf8xUGzd/52/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Serilog": "4.3.0"
+ }
+ },
+ "Serilog.Sinks.Debug": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.3",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.4",
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "infrastructure": {
+ "type": "Project",
+ "dependencies": {
+ "Application": "[1.0.0, )",
+ "ClosedXML": "[0.105.0, )",
+ "Handlebars.Net": "[2.1.6, )",
+ "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.0, )",
+ "PuppeteerSharp": "[20.2.5, )"
+ }
+ },
+ "webapi": {
+ "type": "Project",
+ "dependencies": {
+ "Asp.Versioning.Http": "[8.1.0, )",
+ "Asp.Versioning.Mvc.ApiExplorer": "[8.1.0, )",
+ "FluentValidation.DependencyInjectionExtensions": "[12.1.1, )",
+ "Infrastructure": "[1.0.0, )",
+ "Microsoft.AspNetCore.OpenApi": "[10.0.0, )",
+ "Serilog.AspNetCore": "[10.0.0, )",
+ "Serilog.Sinks.Console": "[6.1.1, )",
+ "Serilog.Sinks.File": "[7.0.1-dev-02315, )"
+ }
+ },
+ "Asp.Versioning.Http": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "Xu4xF62Cu9JqYi/CTa2TiK5kyHoa4EluPynj/bPFWDmlTIPzuJQbBI5RgFYVRFHjFVvWMoA77acRaFu7i7Wzqg==",
+ "dependencies": {
+ "Asp.Versioning.Abstractions": "8.1.0"
+ }
+ },
+ "Asp.Versioning.Mvc.ApiExplorer": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "a90gW/4TF/14Bjiwg9LqNtdKGC4G3gu02+uynq3bCISfQm48km5chny4Yg5J4hixQPJUwwJJ9Do1G+jM8L9h3g==",
+ "dependencies": {
+ "Asp.Versioning.Mvc": "8.1.0"
+ }
+ },
+ "ClosedXML": {
+ "type": "CentralTransitive",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "FluentValidation": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.0, )",
+ "resolved": "12.1.1",
+ "contentHash": "EPpkIe1yh1a0OXyC100oOA8WMbZvqUu5plwhvYcb7oSELfyUZzfxV48BLhvs3kKo4NwG7MGLNgy1RJiYtT8Dpw=="
+ },
+ "FluentValidation.DependencyInjectionExtensions": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.1, )",
+ "resolved": "12.1.1",
+ "contentHash": "D0VXh4dtjjX2aQizuaa0g6R8X3U1JaVqJPfGCvLwZX9t/O2h7tkpbitbadQMfwcgSPdDbI2vDxuwRMv/Uf9dHA==",
+ "dependencies": {
+ "FluentValidation": "12.1.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0"
+ }
+ },
+ "Handlebars.Net": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.AspNetCore.OpenApi": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "0aqIF1t+sA2T62LIeMtXGSiaV7keGQaJnvwwmu+htQdjCaKYARfXAeqp4nHH9y2etpilyZ/tnQzZg4Ilmo/c4Q==",
+ "dependencies": {
+ "Microsoft.OpenApi": "2.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "CentralTransitive",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ },
+ "Serilog.AspNetCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "a/cNa1mY4On1oJlfGG1wAvxjp5g7OEzk/Jf/nm7NF9cWoE7KlZw1GldrifUBWm9oKibHkR7Lg/l5jy3y7ACR8w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Hosting": "10.0.0",
+ "Serilog.Formatting.Compact": "3.0.0",
+ "Serilog.Settings.Configuration": "10.0.0",
+ "Serilog.Sinks.Console": "6.1.1",
+ "Serilog.Sinks.Debug": "3.0.0",
+ "Serilog.Sinks.File": "7.0.0"
+ }
+ },
+ "Serilog.Sinks.Console": {
+ "type": "CentralTransitive",
+ "requested": "[6.1.1, )",
+ "resolved": "6.1.1",
+ "contentHash": "8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Sinks.File": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.1-dev-02315, )",
+ "resolved": "7.0.1-dev-02315",
+ "contentHash": "LuwBs0Hrr7ptVY/u+h+GJ2Of0+Uv3JiISD3ipiuZYnsy+bqeHEC1LQPVTPW9MgjY3tg3B6HObVbL84qGBcbdBA==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/UnitTests/packages.lock.json b/tests/UnitTests/packages.lock.json
new file mode 100644
index 0000000..25e4c12
--- /dev/null
+++ b/tests/UnitTests/packages.lock.json
@@ -0,0 +1,725 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "coverlet.collector": {
+ "type": "Direct",
+ "requested": "[6.0.4, )",
+ "resolved": "6.0.4",
+ "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg=="
+ },
+ "Microsoft.NET.Test.Sdk": {
+ "type": "Direct",
+ "requested": "[18.0.1, )",
+ "resolved": "18.0.1",
+ "contentHash": "WNpu6vI2rA0pXY4r7NKxCN16XRWl5uHu6qjuyVLoDo6oYEggIQefrMjkRuibQHm/NslIUNCcKftvoWAN80MSAg==",
+ "dependencies": {
+ "Microsoft.CodeCoverage": "18.0.1",
+ "Microsoft.TestPlatform.TestHost": "18.0.1"
+ }
+ },
+ "SonarAnalyzer.CSharp": {
+ "type": "Direct",
+ "requested": "[10.16.1.129956, )",
+ "resolved": "10.16.1.129956",
+ "contentHash": "XjMarxz00Xc+GD8JGYut1swL0RIw2iwfBhltEITsxsqC/MDLjK+8dk58fPYkS+YPwtdqzkU4VUuSqX3qrN2HYA=="
+ },
+ "xunit": {
+ "type": "Direct",
+ "requested": "[2.9.3, )",
+ "resolved": "2.9.3",
+ "contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
+ "dependencies": {
+ "xunit.analyzers": "1.18.0",
+ "xunit.assert": "2.9.3",
+ "xunit.core": "[2.9.3]"
+ }
+ },
+ "xunit.runner.visualstudio": {
+ "type": "Direct",
+ "requested": "[3.1.5, )",
+ "resolved": "3.1.5",
+ "contentHash": "tKi7dSTwP4m5m9eXPM2Ime4Kn7xNf4x4zT9sdLO/G4hZVnQCRiMTWoSZqI/pYTVeI27oPPqHBKYI/DjJ9GsYgA=="
+ },
+ "Asp.Versioning.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "mpeNZyMdvrHztJwR1sXIUQ+3iioEU97YMBnFA9WLbsPOYhGwDJnqJMmEd8ny7kcmS9OjTHoEuX/bSXXY3brIFA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "8.0.0"
+ }
+ },
+ "Asp.Versioning.Mvc": {
+ "type": "Transitive",
+ "resolved": "8.1.0",
+ "contentHash": "BMAJM2sGsTUw5FQ9upKQt6GFoldWksePgGpYjl56WSRvIuE3UxKZh0gAL+wDTIfLshUZm97VCVxlOGyrcjWz9Q==",
+ "dependencies": {
+ "Asp.Versioning.Http": "8.1.0"
+ }
+ },
+ "Azure.Core": {
+ "type": "Transitive",
+ "resolved": "1.47.1",
+ "contentHash": "oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.ClientModel": "1.5.1",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "Azure.Identity": {
+ "type": "Transitive",
+ "resolved": "1.14.2",
+ "contentHash": "YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
+ "dependencies": {
+ "Azure.Core": "1.46.1",
+ "Microsoft.Identity.Client": "4.73.1",
+ "Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
+ }
+ },
+ "ClosedXML.Parser": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "ngTqjYreDYNytG1W5d3ewHsw0ukmmrgV7EKnS4/40rXoYZGt07jrBvo+N+GxT49rcageUMUiprV0jYT4nwVBHQ=="
+ },
+ "DocumentFormat.OpenXml": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "2z9QBzeTLNNKWM9SaOSDMegfQk/7hDuElOsmF77pKZMkFRP/GHA/W/4yOAQD9kn15N/FsFxHn3QVYkatuZghiA==",
+ "dependencies": {
+ "DocumentFormat.OpenXml.Framework": "3.1.1"
+ }
+ },
+ "DocumentFormat.OpenXml.Framework": {
+ "type": "Transitive",
+ "resolved": "3.1.1",
+ "contentHash": "6APEp/ElZV58S/4v8mf4Ke3ONEDORs64MqdD64Z7wWpcHANB9oovQsGIwtqjnKihulOj7T0a6IxHIHOfMqKOng==",
+ "dependencies": {
+ "System.IO.Packaging": "8.0.1"
+ }
+ },
+ "ExcelNumberFormat": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "R3BVHPs9O+RkExbZYTGT0+9HLbi8ZrNij1Yziyw6znd3J7P3uoIR07uwTLGOogtz1p6+0sna66eBoXu7tBiVQA=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
+ },
+ "Microsoft.Bcl.Cryptography": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ=="
+ },
+ "Microsoft.CodeCoverage": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "O+utSr97NAJowIQT/OVp3Lh9QgW/wALVTP4RG1m2AfFP4IyJmJz0ZBmFJUsRQiAPgq6IRC0t8AAzsiPIsaUDEA=="
+ },
+ "Microsoft.Data.SqlClient": {
+ "type": "Transitive",
+ "resolved": "6.1.1",
+ "contentHash": "syGQmIUPAYYHAHyTD8FCkTNThpQWvoA7crnIQRMfp8dyB5A2cWU3fQexlRTFkVmV7S0TjVmthi0LJEFVjHo8AQ==",
+ "dependencies": {
+ "Azure.Core": "1.47.1",
+ "Azure.Identity": "1.14.2",
+ "Microsoft.Bcl.Cryptography": "9.0.4",
+ "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
+ "Microsoft.Extensions.Caching.Memory": "9.0.4",
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
+ "Microsoft.SqlServer.Server": "1.0.0",
+ "System.Configuration.ConfigurationManager": "9.0.4",
+ "System.Security.Cryptography.Pkcs": "9.0.4"
+ }
+ },
+ "Microsoft.Data.SqlClient.SNI.runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.2",
+ "contentHash": "f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w=="
+ },
+ "Microsoft.EntityFrameworkCore.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "C+TT9k7f1GQ8agOfV512K9iwrzi76RXVSDiLx+iWC9pz3QhEpSF1Dyk+FpVvd8ULQ+rqymfM8KQ7g48ttQVyMg=="
+ },
+ "Microsoft.EntityFrameworkCore.Analyzers": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "TxHQq0kn0tpYs2ljeRl8jtmWk720B0nteqI6mAZM77HWJpYT9Zj8SkkBBlj8K3Yeq18a6NBjz6YutE+shEk4Ag=="
+ },
+ "Microsoft.EntityFrameworkCore.Relational": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "A3MX1ee7RDxWCUdx/KqP+74fbksz0UIhkVZh56YHvbPkEKsffCXgHU3LGkRDwqR/MrBNWLCWC/IVX79tzM30ZA==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "H4SWETCh/cC5L1WtWchHR6LntGk3rDTTznZMssr4cL8IbDmMWBxY+MOGDc/ASnqNolLKPIWHWeuC1ddiL/iNPw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "tMF9wNh+hlyYDWB8mrFCQHQmWHlRosol1b/N2Jrefy1bFLnuTlgSYmPyHNmz8xVQgs7DpXytBRWxGhG+mSTp0g==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
+ "Microsoft.Extensions.DependencyModel": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "RFYJR7APio/BiqdQunRq6DB+nDB6nc2qhHr77mlvZ0q0BT8PubMXN7XicmfzCbrDE/dzhBnUKBRXLTcqUiZDGg=="
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "SfK89ytD61S7DgzorFljSkUeluC1ncn6dtZgwc0ot39f/BEYWBl5jpgvodxduoYAs1d9HG8faCDRZxE95UMo2A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "/ppSdehKk3fuXjlqCDgSOtjRK/pSHU8eWgzSHfHdwVm5BP4Dgejehkw+PtxKG2j98qTDEHDst2Y99aNsmJldmw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "KrN6TGFwCwqOkLLk/idW/XtDQh+8In+CL9T4M1Dx+5ScsjTq4TlVbal8q532m82UYrMr6RiQJF2HvYCN0QwVsA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "BStFkd5CcnEtarlcgYDBcFzGYCuuNMzPs02wN3WBsOFoYIEmYoUdAiU+au6opzoqfTYJsMTW00AeqDdnXH2CvA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
+ "Microsoft.Identity.Client": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "6.35.0"
+ }
+ },
+ "Microsoft.Identity.Client.Extensions.Msal": {
+ "type": "Transitive",
+ "resolved": "4.73.1",
+ "contentHash": "xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
+ "dependencies": {
+ "Microsoft.Identity.Client": "4.73.1",
+ "System.Security.Cryptography.ProtectedData": "4.5.0"
+ }
+ },
+ "Microsoft.IdentityModel.Abstractions": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA=="
+ },
+ "Microsoft.IdentityModel.JsonWebTokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Logging": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Abstractions": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Protocols.OpenIdConnect": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Protocols": "7.7.1",
+ "System.IdentityModel.Tokens.Jwt": "7.7.1"
+ }
+ },
+ "Microsoft.IdentityModel.Tokens": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
+ "dependencies": {
+ "Microsoft.IdentityModel.Logging": "7.7.1"
+ }
+ },
+ "Microsoft.OpenApi": {
+ "type": "Transitive",
+ "resolved": "2.0.0",
+ "contentHash": "GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw=="
+ },
+ "Microsoft.SqlServer.Server": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug=="
+ },
+ "Microsoft.TestPlatform.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "qT/mwMcLF9BieRkzOBPL2qCopl8hQu6A1P7JWAoj/FMu5i9vds/7cjbJ/LLtaiwWevWLAeD5v5wjQJ/l6jvhWQ=="
+ },
+ "Microsoft.TestPlatform.TestHost": {
+ "type": "Transitive",
+ "resolved": "18.0.1",
+ "contentHash": "uDJKAEjFTaa2wHdWlfo6ektyoh+WD4/Eesrwb4FpBFKsLGehhACVnwwTI4qD3FrIlIEPlxdXg3SyrYRIcO+RRQ==",
+ "dependencies": {
+ "Microsoft.TestPlatform.ObjectModel": "18.0.1",
+ "Newtonsoft.Json": "13.0.3"
+ }
+ },
+ "Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.3",
+ "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
+ },
+ "RBush.Signed": {
+ "type": "Transitive",
+ "resolved": "4.0.0",
+ "contentHash": "aP5KQxL5RnFNGW1f0euYVBfCatkLw5iEzMRJcXKq8LWWP4Cp3+qoSq1tDDL2vvJ2rM0ychmVMa2VaEKLS6uX4w=="
+ },
+ "Serilog.Extensions.Hosting": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "E7juuIc+gzoGxgzFooFgAV8g9BfiSXNKsUok9NmEpyAXg2odkcPsMa/Yo4axkJRlh0se7mkYQ1GXDaBemR+b6w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Serilog.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "vx0kABKl2dWbBhhqAfTOk53/i8aV/5VaT3a6il9gn72Wqs2pM7EK2OB6No6xdqK2IaY6Zf9gdjLuK9BVa2rT+Q==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "10.0.0",
+ "Serilog": "4.2.0"
+ }
+ },
+ "Serilog.Formatting.Compact": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "wQsv14w9cqlfB5FX2MZpNsTawckN4a8dryuNGbebB/3Nh1pXnROHZov3swtu3Nj5oNG7Ba+xdu7Et/ulAUPanQ==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Settings.Configuration": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "LNq+ibS1sbhTqPV1FIE69/9AJJbfaOhnaqkzcjFy95o+4U+STsta9mi97f1smgXsWYKICDeGUf8xUGzd/52/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0",
+ "Serilog": "4.3.0"
+ }
+ },
+ "Serilog.Sinks.Debug": {
+ "type": "Transitive",
+ "resolved": "3.0.0",
+ "contentHash": "4BzXcdrgRX7wde9PmHuYd9U6YqycCC28hhpKonK7hx0wb19eiuRj16fPcPSVp0o/Y1ipJuNLYQ00R3q2Zs8FDA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "SixLabors.Fonts": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "LFQsCZlV0xlUyXAOMUo5kkSl+8zAQXXbbdwWchtk0B4o7zotZhQsQOcJUELGHdfPfm/xDAsz6hONAuV25bJaAg=="
+ },
+ "System.ClientModel": {
+ "type": "Transitive",
+ "resolved": "1.5.1",
+ "contentHash": "k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.3",
+ "System.Memory.Data": "8.0.1"
+ }
+ },
+ "System.Configuration.ConfigurationManager": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==",
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.4",
+ "System.Security.Cryptography.ProtectedData": "9.0.4"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ=="
+ },
+ "System.IdentityModel.Tokens.Jwt": {
+ "type": "Transitive",
+ "resolved": "7.7.1",
+ "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
+ "dependencies": {
+ "Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
+ "Microsoft.IdentityModel.Tokens": "7.7.1"
+ }
+ },
+ "System.IO.Packaging": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "KYkIOAvPexQOLDxPO2g0BVoWInnQhPpkFzRqvNrNrMhVT6kqhVr0zEb6KCHlptLFukxnZrjuMVAnxK7pOGUYrw=="
+ },
+ "System.Memory.Data": {
+ "type": "Transitive",
+ "resolved": "8.0.1",
+ "contentHash": "BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg=="
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "cUFTcMlz/Qw9s90b2wnWSCvHdjv51Bau9FQqhsr4TlwSe1OX+7SoXUqphis5G74MLOvMOCghxPPlEqOdCrVVGA=="
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "type": "Transitive",
+ "resolved": "9.0.4",
+ "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ=="
+ },
+ "xunit.abstractions": {
+ "type": "Transitive",
+ "resolved": "2.0.3",
+ "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
+ },
+ "xunit.analyzers": {
+ "type": "Transitive",
+ "resolved": "1.18.0",
+ "contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
+ },
+ "xunit.assert": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
+ },
+ "xunit.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]",
+ "xunit.extensibility.execution": "[2.9.3]"
+ }
+ },
+ "xunit.extensibility.core": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "kf3si0YTn2a8J8eZNb+zFpwfoyvIrQ7ivNk5ZYA5yuYk1bEtMe4DxJ2CF/qsRgmEnDr7MnW1mxylBaHTZ4qErA==",
+ "dependencies": {
+ "xunit.abstractions": "2.0.3"
+ }
+ },
+ "xunit.extensibility.execution": {
+ "type": "Transitive",
+ "resolved": "2.9.3",
+ "contentHash": "yMb6vMESlSrE3Wfj7V6cjQ3S4TXdXpRqYeNEI3zsX31uTsGMJjEw6oD5F5u1cHnMptjhEECnmZSsPxB6ChZHDQ==",
+ "dependencies": {
+ "xunit.extensibility.core": "[2.9.3]"
+ }
+ },
+ "application": {
+ "type": "Project",
+ "dependencies": {
+ "Domain": "[1.0.0, )",
+ "Microsoft.EntityFrameworkCore": "[10.0.0, )",
+ "Scrutor": "[7.0.0, )",
+ "Serilog": "[4.3.0, )"
+ }
+ },
+ "domain": {
+ "type": "Project"
+ },
+ "infrastructure": {
+ "type": "Project",
+ "dependencies": {
+ "Application": "[1.0.0, )",
+ "ClosedXML": "[0.105.0, )",
+ "Handlebars.Net": "[2.1.6, )",
+ "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.0, )",
+ "PuppeteerSharp": "[20.2.5, )"
+ }
+ },
+ "testdata": {
+ "type": "Project",
+ "dependencies": {
+ "Bogus": "[35.6.5, )",
+ "WebApi": "[1.0.0, )"
+ }
+ },
+ "webapi": {
+ "type": "Project",
+ "dependencies": {
+ "Asp.Versioning.Http": "[8.1.0, )",
+ "Asp.Versioning.Mvc.ApiExplorer": "[8.1.0, )",
+ "FluentValidation.DependencyInjectionExtensions": "[12.1.1, )",
+ "Infrastructure": "[1.0.0, )",
+ "Microsoft.AspNetCore.OpenApi": "[10.0.0, )",
+ "Serilog.AspNetCore": "[10.0.0, )",
+ "Serilog.Sinks.Console": "[6.1.1, )",
+ "Serilog.Sinks.File": "[7.0.1-dev-02315, )"
+ }
+ },
+ "Asp.Versioning.Http": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "Xu4xF62Cu9JqYi/CTa2TiK5kyHoa4EluPynj/bPFWDmlTIPzuJQbBI5RgFYVRFHjFVvWMoA77acRaFu7i7Wzqg==",
+ "dependencies": {
+ "Asp.Versioning.Abstractions": "8.1.0"
+ }
+ },
+ "Asp.Versioning.Mvc.ApiExplorer": {
+ "type": "CentralTransitive",
+ "requested": "[8.1.0, )",
+ "resolved": "8.1.0",
+ "contentHash": "a90gW/4TF/14Bjiwg9LqNtdKGC4G3gu02+uynq3bCISfQm48km5chny4Yg5J4hixQPJUwwJJ9Do1G+jM8L9h3g==",
+ "dependencies": {
+ "Asp.Versioning.Mvc": "8.1.0"
+ }
+ },
+ "Bogus": {
+ "type": "CentralTransitive",
+ "requested": "[35.6.5, )",
+ "resolved": "35.6.5",
+ "contentHash": "2FGZn+aAVHjmCgClgmGkTDBVZk0zkLvAKGaxEf5JL6b3i9JbHTE4wnuY4vHCuzlCmJdU6VZjgDfHwmYkQF8VAA=="
+ },
+ "ClosedXML": {
+ "type": "CentralTransitive",
+ "requested": "[0.105.0, )",
+ "resolved": "0.105.0",
+ "contentHash": "U0hAdnYyPvF7TqHMFloxrS7pmozab79tFFF4c/bgPtqeelUs7ILpUd3r3c7C0a/DXsUZb3k1n4Pf7Q2LMyMQOg==",
+ "dependencies": {
+ "ClosedXML.Parser": "2.0.0",
+ "DocumentFormat.OpenXml": "[3.1.1, 4.0.0)",
+ "ExcelNumberFormat": "1.1.0",
+ "RBush.Signed": "4.0.0",
+ "SixLabors.Fonts": "1.0.0"
+ }
+ },
+ "FluentValidation": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.0, )",
+ "resolved": "12.1.1",
+ "contentHash": "EPpkIe1yh1a0OXyC100oOA8WMbZvqUu5plwhvYcb7oSELfyUZzfxV48BLhvs3kKo4NwG7MGLNgy1RJiYtT8Dpw=="
+ },
+ "FluentValidation.DependencyInjectionExtensions": {
+ "type": "CentralTransitive",
+ "requested": "[12.1.1, )",
+ "resolved": "12.1.1",
+ "contentHash": "D0VXh4dtjjX2aQizuaa0g6R8X3U1JaVqJPfGCvLwZX9t/O2h7tkpbitbadQMfwcgSPdDbI2vDxuwRMv/Uf9dHA==",
+ "dependencies": {
+ "FluentValidation": "12.1.1",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0"
+ }
+ },
+ "Handlebars.Net": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.6, )",
+ "resolved": "2.1.6",
+ "contentHash": "WsYWCEXsIM6hEOSOSRHtIYLjC8BnbT5MVmqhNKRqUI7qiv0t8x3nJiBTEv0ZZfvUAMAFnadGIzSsS/U2anVG1Q=="
+ },
+ "Microsoft.AspNetCore.OpenApi": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "0aqIF1t+sA2T62LIeMtXGSiaV7keGQaJnvwwmu+htQdjCaKYARfXAeqp4nHH9y2etpilyZ/tnQzZg4Ilmo/c4Q==",
+ "dependencies": {
+ "Microsoft.OpenApi": "2.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "hHa2amRjMyBLUH/KTML6FgIAhZ0VFYkhCKwWEax0rO6iNeM1P5MflyeQLE5dniSIOZHc3Oqyv5UIyTFO4e1Auw==",
+ "dependencies": {
+ "Microsoft.EntityFrameworkCore.Abstractions": "10.0.0",
+ "Microsoft.EntityFrameworkCore.Analyzers": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "Microsoft.EntityFrameworkCore.SqlServer": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "9ip+r8Wtu0qNtFLYnQC3bkhQAsINIyo8XWYJHCVY22BFLxIT4rPxZPkbto56SjCnkwxS6nnbFZTU6KuAO2Nu1g==",
+ "dependencies": {
+ "Microsoft.Data.SqlClient": "6.1.1",
+ "Microsoft.EntityFrameworkCore.Relational": "10.0.0",
+ "Microsoft.Extensions.Caching.Memory": "10.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging": "10.0.0"
+ }
+ },
+ "PuppeteerSharp": {
+ "type": "CentralTransitive",
+ "requested": "[20.2.5, )",
+ "resolved": "20.2.5",
+ "contentHash": "w9/oEME3spddIKjh8C3sMxQziJe6lcdsTtQCnG3GevupZYQPx243dz1znh9YIE9otulXa9lg+Pnf/SMUCq4/Gw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "Scrutor": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "wHWaroody48jnlLoq/REwUltIFLxplXyHTP+sttrc8P7+jkiVqf38afDidJNv4qgD/6zz2NKOYg06xLZ1bG7wQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyModel": "10.0.0"
+ }
+ },
+ "Serilog": {
+ "type": "CentralTransitive",
+ "requested": "[4.3.0, )",
+ "resolved": "4.3.0",
+ "contentHash": "+cDryFR0GRhsGOnZSKwaDzRRl4MupvJ42FhCE4zhQRVanX0Jpg6WuCBk59OVhVDPmab1bB+nRykAnykYELA9qQ=="
+ },
+ "Serilog.AspNetCore": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "a/cNa1mY4On1oJlfGG1wAvxjp5g7OEzk/Jf/nm7NF9cWoE7KlZw1GldrifUBWm9oKibHkR7Lg/l5jy3y7ACR8w==",
+ "dependencies": {
+ "Serilog": "4.3.0",
+ "Serilog.Extensions.Hosting": "10.0.0",
+ "Serilog.Formatting.Compact": "3.0.0",
+ "Serilog.Settings.Configuration": "10.0.0",
+ "Serilog.Sinks.Console": "6.1.1",
+ "Serilog.Sinks.Debug": "3.0.0",
+ "Serilog.Sinks.File": "7.0.0"
+ }
+ },
+ "Serilog.Sinks.Console": {
+ "type": "CentralTransitive",
+ "requested": "[6.1.1, )",
+ "resolved": "6.1.1",
+ "contentHash": "8jbqgjUyZlfCuSTaJk6lOca465OndqOz3KZP6Cryt/IqZYybyBu7GP0fE/AXBzrrQB3EBmQntBFAvMVz1COvAA==",
+ "dependencies": {
+ "Serilog": "4.0.0"
+ }
+ },
+ "Serilog.Sinks.File": {
+ "type": "CentralTransitive",
+ "requested": "[7.0.1-dev-02315, )",
+ "resolved": "7.0.1-dev-02315",
+ "contentHash": "LuwBs0Hrr7ptVY/u+h+GJ2Of0+Uv3JiISD3ipiuZYnsy+bqeHEC1LQPVTPW9MgjY3tg3B6HObVbL84qGBcbdBA==",
+ "dependencies": {
+ "Serilog": "4.2.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
From 92c0ae65965166231cc94cd0676fe46710c0d840 Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Wed, 17 Dec 2025 16:12:06 +0100
Subject: [PATCH 45/46] docs: add README documentation (#82)
* add README documentation
* add Table of contents
* add Console preview image
* remove ignored paths from required workflows
---
.github/workflows/build-validation.yml | 4 -
.github/workflows/test-validation.yml | 4 -
README.md | 114 +++++++++++++++++++++++++
3 files changed, 114 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/build-validation.yml b/.github/workflows/build-validation.yml
index 74236f5..04af5f4 100644
--- a/.github/workflows/build-validation.yml
+++ b/.github/workflows/build-validation.yml
@@ -5,10 +5,6 @@ on:
branches:
- main
- develop
- paths-ignore:
- - "**/*.md"
- - "**/*.gitignore"
- - "**/*.gitattributes"
workflow_dispatch:
env:
diff --git a/.github/workflows/test-validation.yml b/.github/workflows/test-validation.yml
index b3d58c2..037321a 100644
--- a/.github/workflows/test-validation.yml
+++ b/.github/workflows/test-validation.yml
@@ -5,10 +5,6 @@ on:
branches:
- main
- develop
- paths-ignore:
- - "**/*.md"
- - "**/*.gitignore"
- - "**/*.gitattributes"
workflow_dispatch:
env:
diff --git a/README.md b/README.md
index bb7cde8..a96e0ce 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,117 @@
[](https://github.com/nwdorian/PhoneForge/actions/workflows/build-validation.yml)
[](https://github.com/nwdorian/PhoneForge/actions/workflows/test-validation.yml)
+
+This application is designed to demonstrate document processing in ASP.NET
+
+It allows users to work with contact data like in a phone book. They can load data from an Excel file and create PDF reports based on selected filters.
+
+Backend is a .NET Web API and frontend is a simple console application for contact management and PDF report generation.
+
+## Table of contents
+
+- [PhoneForge](#phoneforge)
+ - [Table of contents](#table-of-contents)
+ - [Technologies](#technologies)
+ - [Getting started](#getting-started)
+ - [Prerequisites](#prerequisites)
+ - [Installation](#installation)
+ - [Features](#features)
+ - [Solution structure](#solution-structure)
+ - [Best practices](#best-practices)
+ - [Contributing](#contributing)
+ - [License](#license)
+ - [Contact](#contact)
+
+## Technologies
+
+- **.NET 10**
+- SQL Server
+- Entity Framework Core
+
+## Getting started
+
+### Prerequisites
+
+- .NET 10 SDK
+- SQL Server (Developer, Express, Docker container)
+- IDE like VS2022, VS Code or Rider (optional)
+- Database management tool like SSMS or Dbeaver (optional)
+
+### Installation
+
+> [!NOTE]
+> EF Core migrations were created.
+>
+> Migrations will be applied on startup of the API application, create the database, tables and seed that data from excel document.
+
+1. Clone the repository
+ - `git clone https://github.com/nwdorian/PhoneForge.git`
+
+2. Configure `appsettings.json`
+ - replace the connection string if necessary
+
+3. Run the WebApi from project root
+ - `dotnet run --project ./backend/WebApi/WebApi.csproj`
+
+4. Run the Console from project root
+ - `dotnet run --project ./frontend/Console/Console.csproj`
+
+## Features
+
+- Contacts management
+ - Created, delete and update contacts
+ - Pagination, sorting and filtering
+
+
+
+
+- Excel data seeding
+ - `./documents/contacts.xlsx`
+ - edit the Excel document to change seed data
+- PDF report generation
+ - outputs reports to `./documents/report-timestamp.pdf`
+ - applies filtering and sorting options
+
+## Solution structure
+
+- Clean Architecture WebAPI project structure
+ - Rich domain model
+ - Value Objects enforcing invariants
+ - CQRS pattern Application layer
+ - REPR pattern WebAPI layer
+ - Feature folders oranization per layer
+
+### Best practices
+
+- Continuous Integration
+ - Github Actions workflows for build and test validation
+- Consistent code style enforced by `.editorconfig`
+- Central build configuration `Directory.Build.props`
+ - .NET 10 target framework for all projects
+ - code quality properties
+- Central package management `Directory.Packages.Props`
+- Static code analysis
+ - Treat warnings as errors
+ - Analysis level `latest-Recommended`
+ - `SonarAnalyzer.CSharp` package
+- Api versioning
+- Input validation with FluentValidation
+- Result pattern
+- Structured logging with Serilog
+- Soft delete and audit fields
+- EF Core configuration classes
+- Global exception handling
+- ProblemDetails [RFC7808](https://datatracker.ietf.org/doc/html/rfc7807) standard
+
+## Contributing
+
+Contributions are welcome! Please fork the repository and create a pull request with your changes. For major changes, please open an issue first to discuss what you would like to change.
+
+## License
+
+This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.
+
+## Contact
+
+For any questions or feedback, please open an issue.
From 38c53f694b84697dbe83a9f3b0ad36d749847357 Mon Sep 17 00:00:00 2001
From: nwdorian <118033138+nwdorian@users.noreply.github.com>
Date: Wed, 17 Dec 2025 17:10:58 +0100
Subject: [PATCH 46/46] fix: add condition for positive integer prompt
validation (#83)
---
frontend/Console/Core/Input/UserInput.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/frontend/Console/Core/Input/UserInput.cs b/frontend/Console/Core/Input/UserInput.cs
index 1901e78..09956ea 100644
--- a/frontend/Console/Core/Input/UserInput.cs
+++ b/frontend/Console/Core/Input/UserInput.cs
@@ -71,8 +71,10 @@ public static int PromptPositiveInteger(string displayMessage, bool allowZero)
{
prompt.Validate(InputValidation.IsGreaterThanOrEqualToZero);
}
-
- prompt.Validate(InputValidation.IsGreaterThanZero);
+ else
+ {
+ prompt.Validate(InputValidation.IsGreaterThanZero);
+ }
return AnsiConsole.Prompt(prompt);
}