From 33d76cffb1111f6bb07dd8e49d54fe9ff47e2668 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:46:19 +0000 Subject: [PATCH 1/3] chore: start implementation plan for brialert improvements Agent-Logs-Url: https://github.com/potemkin666/Brialert/sessions/0ac49de3-9169-4752-9774-d0966393cd77 Co-authored-by: potemkin666 <183807833+potemkin666@users.noreply.github.com> --- data/brialert.sqlite | Bin 3002368 -> 3022848 bytes data/quarantined-sources.json | 2 +- data/source-remediation-sweep.json | 3279 ++++++++++++++++++++++++- data/sources.json | 6 +- data/top-20-source-remediation.json | 324 ++- live-alerts.json | 3524 ++++++++++++++------------- source-quarantine.html | 4 +- 7 files changed, 5451 insertions(+), 1688 deletions(-) diff --git a/data/brialert.sqlite b/data/brialert.sqlite index 17fc7a0249ffb906c2f4fc2d41b85969a24be519..3706a2cb933f5870e6673e6187db98311da9bf04 100644 GIT binary patch delta 32851 zcmbt733wDm)?G8*J>7F==-dI5A%qY@NG2g9A>^2Z5JJd(0O1HBavu_qRYW9}(da5D zag$`Pb-k68YSDc?9>yi)KOju|+964%1stpAJNs;l#8Eqc1dB~l zp39T=dIXvg2JEQtCo#dZ{W~jK_b5nL&Z3@1cmF|tLXPPmi=y3g;-UM78FlSa&yAzV zNjFHzHL+^pw$Bps(Ud2EO1j6&6E)b{gq33tR-4_PclYg;iSj5J)cbIc=GeCVpL$;G zxj`QHZ8uw9*`m9gk(d$&tM84LcP!(9)%3dYKj3lWG_h4^H9Wz8#%FW0ShxN;eK=Fn z<%$S_(-WkeyqK`_;<4(8D^hC%$gx3)^!)t@EeKdvXr3iTNEul%VdpfCSOjbk+TJr| zq|MhttMPjxhBWG=Xel$t4|OkV$_xs%Rc4zRF^7?BEI1GXlg20(@r-(8s^|UptqvJ@ z7;5E%@pM0O8}+0-;>C|5&9UUi{v?kf*HgMIngz*mQdX`X3jlA*3W^2tN}dCKDt)Gx zO}s47p*oM5Gd%CTZ@XyTG#&1fSN82ue)NPsagch#jH3xji;;2*$o>I#H;m8U5O;Id zlIvWo(>R#nOge2T+`YHT3;U>|M}K?jPI;85EG0fz#yx}XaD4cX^eE~3pFPt#KN$Mx zy{Clv6jh~Jr(QAVq%8_!>on@bP~Z8gym(uEM26?{XH<6X0!};a**_|IHComl3x5j} zqC3h62MoW8EBQZgCk?gSWYe2RB99){=`q_p$DVVg1;Z<9$+gd`kCGZJd4V>*|9(NC zV2Kj~NqWm~VsPdwLf$wWH+~2;+2l8W&I@Xji84adpBW35yup7kD@iIYl`Vtko)>2Z z6F4ZOA~_H*T)Qn9mn?9pi9>o!!o2f(4EKiS24%-+MLqEH@2SI98r~JJXdB-2S9dGt z(Sb>>6YDh&Od>rAudPvnrOGE_sby^E4g~)fCZ`0l)~8>!W?i`1q_@`b7nNQqY!Ha- za~$PEfoJ7kw<}4co|0aFfO^8*nM{#yx*kXW{W@EX^)}0^=AX@@MT7AU@oDyPVS-^C zzXa^zI+=dfsL$1{z~=7GaJYDyRJu%#9fq8}{c3ANbgfOxCLy>xF%oS~=Z1+Q3X7!J zEwVHZAwIP%Zq_BsNABOWgH!XHDhAUbe{zWwTPM@x`TEWL3y%yas|m~VLz5wg*``XG zUWjQVazULB4uGiOPK%*%Ua^$CfgA(zI)hml_KGzhSSzA+^Yt3j(2gf`iORKTS$pN3 zE^1JzM%&(fLvw7$d#do2wkYYjQf!ON!l7gB-fquNYtbNcIPXol6$aMlh2{~is{Et< zIa_mDa}da>9cH}o4E5ya`|rcbaJQ%Z!v~c>^u{Z4q+)zRD%#p6TIL2t8!eVa*;2+D z8MVi8qQUdUGZ!DQwhio1(og%Y36qB`8Sz~UKMKx4Q=&{9m&Clo*b=N&mYwF8%~7U0 z<8JY!I7(P$=;q(ze&M3oIeMh)2X8U&kkGs*1a5AUS~lZ!Y^XMXQlA28XwjLFY0>(5 zS_h1}XX1?I_*s>$p(VZRlP8oLrw^`fj?}O$RvmCUqr(_}NVzx$| z7YfhzPirpKWfwF`$!#*qAq8u(+RB4cFj~$QHb{A`xYBd3GUNPs?!{JSXvWU2my%Y= zhk4F*=tjK`xNJPfxemO0u z_>2x33ac?f&wXFTpw0L4sp$W#tkGlp=VT>$;j;gQ1yzF-U^C(A|12DR2uu?_#h(=@ zXV8Z-v2uv!!8poe{mK=L2vG~5ukN6pF#qV~Cd`uJYbaZ@_UnRRmQy&x^3Zr_k#Ps3y3y&C{;tTo0J8MRUhP5t`ayG`EFMkd( z13LM}=+H(D1~eg<9vA5meo)ysTH7k;O9?F)uQ*s%9m3o7v$e>x;|Ep5LGAA74^f_i z=dDzjY56NN3A?+r2w2)2ng9XDsf=QJd7;)*{XZ4X3n~51StV6%j+JY*UH@Jc%)!yy zcCD0h@wU&&!qBz{b{ZT~9B2=(bEp~BPfpAd?N*gR1t2-PG@ zk)HeiW2MO~Um|6d`ki`Bt(fnb{-X+)aL!(!Q+I=LwEfCnEjgA9xhhZe>54Q?V=Kdj zR21Ql{YRBXP`U`OS{9lMBM8lkn6t}1VtKShv(ynF=A?H}xl}5^(m!Z{x14DWY6mo9 zCtWV(mdB_?)b(G!FjDIRfSfZGS8B1)Q~dK|GOyG%ti3;~>kl+l1uara9;Rx@lMacF z1M%rmHmw?|)@6rGgXf!H4#`hGiYUFs@z!94({tDVUNmRTlTv37F&bSri3>+3Ci0oi z#iG`BHGWT+WjZI2Sxw9%0L0Dog?70lw9B?kHW!+TjaP{Kg?|fShI0OH?t4yPv-Rtk zT%gz80bawv@;_K|tyDgni1460LymY5flhWC3(=jAgCKlC$re9+b1v1UOy4S%F7Ue) zXiGQMqQ?rnw;EeGiiG3d|i<~-_mFPnn^SL%55~|8kdQW3unM6 zLC=;Mmh+{2Dbaqo0&-HqW)ids0>JhV*D#WB1q0q?szhJsfn3j_ebgl{8kG++sl9YK zpc#9kD12>ajILxpp};geF40kA7bThcE^2-_>hrh-%R?%0$3Y zWTtD$14h*`3WkJcz$(Dgt zq0U2tlD@<&;MG&B5c5Pm8m5A~Q=?NJ4(P! z)ToL>Ez@c9uHulr6zr#_k_}P*U;LCAi{tju5wHSA4+cfb@S|%tSBUPJ0aW289lCby zaYUlVX@JTz(62MVE^5`vH(7dBEPKb0a|d_@_0FWNxSHKN%7N;3jlwy57T6{~s&*Y# z0ea;@^&wj-!Jnzo4=NSRj;aEW$fE=?T@1&xk6_N|Y?;=jmTvQxW+(WVIb$l(->!Qe zTd~c;Glp;ZfAC>k9$P`Sc+3u$z$~evRjz5ERrA22i}2(zvNFR3aI%z3m0M8Wd@x57 zmqsTHrIWB6PLXn5GI2vuC-8FlQDOBODvRJ;b+|zjnFVu5S}DhCAIt?a(ay)g1y&zv z`c}gtseF@PRD9|yz8Sq+s}@W7*wCS!K#^dbuA@CWA`(fjGYb|WldSETDVMVACsq?5@&rL)14@}qj; zxiDACol8o1ikz+GU3+=7IA1HE(8@fbWNBsKGMFvRo=5t&NW^q)6SzE5EBn;KN9Pgf zr}@LgZU+_sss%=65UOfuyRI5svJj{)cqkJIOQ92ijRpzLY6eirMnA)_P_H`#CV_AG z5@sQ8wyCpBGGA_5Y+NJWE%fQvak>0ic7fqDY;n^gU@crKCE&~)^M<~k0j{W$D4ka2 z8ts6N(w|H}a#3q?m4668Jri>Ev*g610 zl6`*sC18uSrdnp1Z!z_Pz06C-SB#uER+wqHL3bVhIQLI3m7S-bkJa@aJDd-%kuvd( z+BtPaH8+FVny&Zg&1w%xYf&BCBsrU9Ttgb#a+`5_6tAiJ{z*RVb(=aEDPf~*PSC;| zK!YZIU@|r%>;BHF%!qsv=z9nrryhGd6hYE=9YEC=LBT%n9>z>>zFsZ7G-t{>fRsR* zE0xZuYlk&AS~pKC0oAgK6irg+Fb?3|PT-YcRTBEhjdTP}25Eu|;I&c?K1!eV%RMW- z&j~Y~4O-6bg6+VZ--Aar348e#@Q`wlws;S015~w9wWqpU0d*gSe!5lB9g8Nl)0oje z+Ce6bdc$@)CG%Md+7lX#I7Ds*wsF>lmOFGtrqy%?-)?L&92cD+LAcrw$yae3***Hd z>FrpxvLax9M}$=3Z}@BOw$1bv&nSLtM5H9uq$y130{6(QQPp9Qcsrdisz*aSbfljun?>%6zJQ$!_zK=8=>=oejjxcfvDD8e+I+Hecfoyho~s&6ydUh57bSy~3$$2@m=K)>=y%)7b(TKsE^rpuvBo4yWmWQZ zCh9!^g6a~WmFD%`bkeROvina!eUBj1jP8Db4xm(1TOI_eDY1?1)WM35I;pJ8_fkvo4`GF<_Yt-EprKPbYNg~vA9Tr1 zV;q{gKn*P)BYN{ub%aH0`A>&{syBg}x}r}loz&n!uOf#c_eAtbP41|Wa|Jvc#g~p&4bGBn1vDg9lfiQpBCUno2(1KnA%b9*Ih+_P&dM`eu#RksfFnCfrIdJo9r^2sacK*+n4$4|Rf!#Y-|4uO(vM{hk2H8!DpN~l zUf8=ycVV*cv}22eyLt;`veAiWg0AX~?kJWrl4M-x!j5mmi5GFDJ4rrqi~fGbj<1No zzid;it(Ke251C#w@y1+nxp2GT2>%hjUl!Rskf(cxG($@u0y^D5%JYwW+D_mLmJ7dC zrW3H1j`dOL8Nf@#0y|Xxmg>5<2kUFy{2Nzkq%6Mv0T8 zN&5OVb#_RPu6uQupuhcjwY{LtX;H@psixddM`~)>%8LliDPkTw4#4q5QzZ^3Utnxe z`gYu7+h#su`a$=C@pkb!;S6@^Yxy4TTW%CvPSoUHogHR(%$Hmx4lIa6y%%R6)|Cg- zD?w{YX~%4-ra|5snmB`VpzrhfoFLPf%8n&cBJLo^MAD_y-Unie{9EVcvqbI1Adwc+ zijK>12LtLY1X0Lnsdj!ZZ$QL&`yJ9cPx++3OugQL(vZp=+?@Rgj7mj zu;F+Rdw_2AoL8p`<0;`nU+&kb(kgm%--EhgbZGKH^`2yE(A2%U&&OLVU*Xn)cNxnM zwp8X_@UZ!N^C(jZ?jYJDoH3j+IQe2Og^kqL>e_toYuaJ8o0Fo8?u| zJ&)+9HUpI;9(q*wsSK+cPv^|zTatXt5k80-aH2F>eGdxgHMSrr{?P=!)5w3 zE3S20q-9r~>$SPBPq!&jtJemlJ+5=0gKwy7nY1xYa+@V*f#2nt<5pv4P%o{~xJ%q7 zDK}HjCx(I<$1!Vmluom8&;KIU$t`@^m##D1u1RLjo9Y6aa)3$ zl~U`794IV1jFenaT7`1leDxL^XH$JdLYcbtoqbjpyF+K$-xpV{ub|pbR2p!9ot|o+ zP!9H8SFblvy(DCm+Jv}{*@!pMhEf{!x652r;y|Yx^;D%&HTcYIJ#}lP8uZN3|6OPL z5Uro9SJ_s1F;vy0*Di64n5S3y5{i6=0RtooIEKqj#T|Aj^$N-Yelt(scoEi=7NRQ` z>Zwi_)t-u)^(rqS@1^f-vtGYzTr@5&-_F=lt=Cv?6m%kEdd&!QHO8mFWJ4;S!`;Ll zV|jgn`9n|tiRI|!eC`3hBf>pOYC-)*HWFpGnCGKIfSoJjRo`?~>sYD=sJg??*R!gY z6xyd2yGP^vl7zY8XxVZ$3mspmH=>xo0@d3c)Z%|(S?w6&Mvm3)fXwDul`lz?6C&eb zCX8sQ;vcMXUnZ5Vp`y8D1G_kwXf9M<30~ul!0#C2{s9zM0pih7hm}LkPur4FvoIW+ z&k8Knl%P6Be~b1rH-!N#J(!<-Q{UYEe(QOG{pe6a)1&}IgQGnX=`y2NoZ?QBN__YFghxL+xvDf%5Zs}qXNG&6R5w?7 zO&o{X^SIn#Lza77c^-4NtN5}V=rlYmD13IuKH$<|lLf&+a%4U4t zuUfVy7F!gKb5a>xzTa;CtLc5?_r^qVzOd48JO4Uw<)*Wn^oMkx>cT)227(MWJ~MG| zsbAXNn{S#MWzkH#HQX9~Ow$Xw!xYtI6EsiD-7};H-_7h$MfA5~ZecL&q>;{Wmr51B zE+QFe_|AWG(}HSzq%oJcr%R=TFbV z!gi@Xsn$Kk=Q;+v-g_&!sz|L0u2#@VQ<(0~!JoezVjRL0hN62bgA-gT#>0hyf07qe zKH1rB;QRP$PTT?h+!u0^t5;RDD60<}ItrxH2K4MnER73#xnlIcQ=DdK-gm{vT&4;c zb!u;a!ckeJDyrY}DR+Q^RXLJB{)5{kk1D6`z2Y-YCl9Kn;qlKoRWeS!>dG+Y519rW zwAVzyqK<4Sxq!U7KosHp*OQzEArpQ11vkw5P@rg3r1qyWZ~2m=3b0DrQTbO~r#9`; zUvpGtgG^PNr*1AO*EQ%+=69TC`q+2&J5D$n&013V-MSHmW+Bb=h%HtBFgK3-hq%{x zO4sK&#NR+OQ0@OF!xkx-GSdh=!w2;#4MkHndiV&hDhpDZ6V5REeP8=Q;~wRy3bl%T zpFYZ~s)w|H$%2hiL83t0$24K88Y5sz$0{i&$4^e%Cfjo^qBDj1{-8LZ=pWAO zXp<6hNKHgx*=qI)X;H?D4V)<@HNM2m!8@prfYBXmq$K|iC-{!G#GdkA#s8Q_~beP5>_BDPOOMd6ciJm_IO&HO(__6ORht3MNAozk_>; zeH}A16F0}Zt8t^CT(ch%(zcf^Gt(ApFm1S4kdF4U-Q`kQo{Sr<{)i8%yMwl~h3*QR z>&r-o2zFgzofQHoWL7W~XPXB#_r{8ft{5PKNP5J(Bd^-iKd|#{Yi8uLlDm3$@0W{go z?j|Y4_c9SlK+Z=$Fv?OBGj6hG3W92ON8+!@zs(DQZeQsID&2FX0;*Ux#FuV^p(&`6 zD2;oDdybUTCTAK$xKED|>VrxoY24-R*;4L?p>#oh-KYOaQ=@a4CSNoTTHU=_>TZ;r z=e~3#BZt=uwa%7c-YKLhce)#-OkY83FtZ!t3S4E&3#zP2`d!|{Jkz@97dfBp`8>TfI>n}C1D;-5tPGYm>$Uhw?S9J$^B>J|rXJIH<1@xZ;y2r>Cs(pFZ&9geqYb?5W1% z1qjSxLwzLBC{7=XDiMAMd#W%<4eB!K20;{5cKtD=N>~beDltql>Uv{Tm__mZDCBt6 zP$;a1Jrx)r2RZVGkkISwc-1gnSO$A$VUUzSI8N^!|o^lM3i@KUD{NM`Vk5E$k`5;}y-QrgyCJQ0;#XZxpt| zo@scz0l@_k{@XZx$EdmDCfHMqK}rWvD7Vq}Z?0Cn0`?SPfXrrp8hVf5m(a*x4g6u!zPgtqX!#O5$5;>1N3^H^c3U+so zNGcMsfKSEaHM5cHe`A!q>KYT-AZ&m=xp=$`^{x{Am%vIe3LUEB(^$-~DabL&;;$(9 zNboOlSyyO-JvkUx>74_-KPn#>F2HASP=Gzz$T`6nh0^X$3F#|5mU2|L^Q4WRKbP2r zudU6N_blryym`Ah)Z{kljZpkq>=Z`|2ZTbyQNs-WU4A9^BX=_w$v(s;>i6jrbhqhv zu#9<`nM->n-~Y!NdL^bQuiUqP}kUQ#a9Jbr0cGT1tw^RJ?roy_$oR8$iS=O3L^xt=L(Eu_B?-EQ}brj zJmG5Cvlfq+qF(E`2*p7=I+JRJEwE<|9m_~+M0}uC;VZ8grcsLiG`bR(`{z*iEunzXLU>H|m8x2b1W*VUm_AJ6M1%ra3 zIK=LE4D-e7U{5nyXG4H(;EzC z(&wN<^8y`azthlUBnDzOMp3*qz#jUaHnng>pBfRU6QlgBV#tSvmBKZ!rvW2yqLv1u zzbQIhl33qNK0QC0X=H4_w}o2Uta=MH|6;xomu2=E|7YBc-+1+i6NG1k#fJ9{>-nGf zt-OuvaN#W!G17{c^e}+|LR_O&>MyU z%BlhYfS*FjjSHYRl#pH!g&e07!;~mopPDBV2nj>rMm8UW;sggyjm{!#j38^2A;)!k z$&W)Vb#b$BMB%j)7&MS>^5@X0+mohaAL$LjAbG7CXeyHG#4DlKM$l9QhB;M{RBiBD zF+^5fUHfO>_{GI1^RnlVu9DjA5j68*=+XJ8}ZH6d%mm>305 zoS#Qc$F9_C#M7O~z8iaQzhJTE21|yBr;8ZIRT6lK)4QUlV}I!tFib9TEF8i^Q!&sG zSs`8xy#@lJ!8iLm6KciFp_j)nSq1V^iY>$KwmcE)p_ju@r6}&Yp?FLIG%#A2FV2Bp z7Q-aq*f7vx!!M%JvGMil(YKx<<4hBLYE$AgwiSAH=)h+&0gS8TW^pQ854`}j*Wqqz zf4<#hNijha^y0U5@^EXQOoW0`N295g#l~$ba(-d(*V)srj+)KE1lV&O`o0y11%Atb z8@Me-9Lj9Lt0X`Wz%0~6+v>yxu;*ILi{t{-`z8Kk*0D7IWP(=uDcZslqWlMukxIu1nR;Nvpb za~0kb?iTd7ru_p^SBW^L`W?nlToYi=ZTaSzA`aj-Vt|sm001qw^Rspy7ucEc%r?e$ zn{9-(!}6JBmHA)hO=hEMrzzEV&{!`1U0fy#!XFGj8IU2H-^b77zT$4;tn7Yvrv4Ls zyFNyDr!E}~fVs@i%r;!3&d1yGl0YwK(1Ka-`Pdor!3hditg*^ zle?Eh=8$cr`nILu7+jc?g|kHOL`+o%a*hm;;5jzMRSOt(3Sk;LeeY1Du8=oi3&|#o zpCB`y7FlpMJd+TR9DuJ~$IO#W*y(!5V^PF^JSPBW+62=gf;}lP_L?6?XOiJ@^00!q z{>G7$OmGzRCi+%L_Jz1g-rHA)Z6p?WEZ(DISpWdAdqfFYBSBt+-eB)vqB8~T`NrV+ z*npqQlNDsRVuW%W>UrZaOmg7t5Ihq-OwC>gh}jLc)#L2oRweQFONM=;D%Ca!|s%P<1Rl0b~;G)}`&ns*dgVWU5Z zj$0F}SUf%wfu{n+^I)k|$zBD$G3ey#F=`ciEv%Y@5zrfrQXYs1KwV9wWgSNheiV9m za%cck4IeYNlF%U%Qyy@c z%eR)BEeYo5%r4V2re@=Z#`Q+Mc(0f&JR;;9-Z8A;f97}b30x2U2ljW8T~N$lIQIl!^B z980)Dz}AHXzd5LFk}65-e|J0D_heqKioULyBev0mi$346hZj=#ipX>JA>AS+!KfWof#tc}DKx&k`tnypdU#0`_uSU@*?`d0fCVuML- zEWXBn{q9APQ`p7On~%~w0i?Xmoj8>Y=LH^i{1!Ep?0#zC-5(d@GfBXli*~FZ(o_0$ zoW^*c@tuNcOCAg|6yChs7+O$~Jyx zyi)uPSF}vRb|J*zF-#q7ap_At%CFV4bpvb{FJK*AjX^Tyctq()r&y{<6t@b)WUL4v0nRV2 z6(kQOHKUvWby{#{)GU(Ht-#~X0OK_`#LW;Zp?5hRPl^vQ{A$oMjOTxka!+pLLV zHS{jU04V_wfH$MZi@2-YOUg$0%iUW7R6qN}_tNdqTqJ_$9y?)9g9$}JAg>KqT-9m wfsx8l0Xm%>s6y4dUtf(cL%gJTG^)&>p99XgOrmn6bcCZ&KhH4mcJ!402lE4_CjbBd delta 15879 zcmb_jd0bW1_CNcKcRF`q0~bXFL<9vyL`1|ZlZXfi2+n|@Ictg5E6wWedy{8_CLVLA z^-3+LCa03LL2a<8%&aV}US_?9SG}ITUeoJUzkSY~&OXAy_sPc=MwTC$Mi$LBymI8 zrl$_pgZfPAD<+01WgNxklkz&-LF+l|Fw5Ocsp%t-Dh&{ug**7CSe|!ri`W;sO5>E~ zhwo9g9fCM>9LQE2J1vT`2U8E?&}awDpOpv!Fqupq591+gnw5(WLj2}WwtVG_hn(cS z1oBRdQn<4p`M<@92E=Hun8+)D&?{{_CW563*g24VtdgoEE+a_-u0JH@vrCPH&S=67 zhh-z7(!O(>%2|ndJ4xHf@Ll)o{}xe&4Hi@@Lr=T$$v9wFhVEXZ|6Dn>Thaf`+m|u_ z#<^awSt;2zL%DXZ%1x)I+kkjer$qOJsG%cHyXLP=;E4@>7H;o~0*iMXX7mxWuK&AoBSZcw79 zQzkzCDNoiv9oj&CJQ@RFUQ3E*Mi4Zk$%9Yqmd11T=4P^5GQRzNz85}zffoobP0k^* zbqoW6pK;{cAFzw^blXYmZ@_QaYyQC;$IdkQq3gB-hGE-cNip!O@;+U(Y!@#0jmiV zc46i7!<56tBWFLDR}l4T?kQWIK`arq_JQRc_;NFV%IYI`>qU~$&_q~Ntgnr{$Qb%o<0R~V?Aewtd*iJWdqaHZdYQ9$*G z@LuE5;P~KLL@1I2f+}zS)kW5dA*88z^`+i2-d{-~D=c7qoMv5voi6s+3fZiJTTPS#7oMR$U}A^DVRURX!|4RP2%$Gx~qeW3jQqLvGZMYAZygm(R#InStJX$a%) zDupu27#w^>UHBg_d9JWl(rXDU04v?Gp*!!KWY8|D7ds14ylV zh;cN4<#v}m&E~a!!Vb6gw=6Mtnbt|KN}`y~Jj8!UQd1FbNOrGuRF8#~^CRg-IrC-< zaA@9p=ZLNmCs@T~{*&y}LLDeol8tAI(3QMPUv z?TAvIbdY%>6s5i6QFA%WT%igJ)Z7>fxrPtywLII*1~PWf$0RwnwEz=7A0s(&&L={6 z2k~f78BDqQzU{`|PUZBwCS~Xk zB4HD(4V9CjXAZ#^hQj)7d;@3xqiW9zZ{h9d_?^nT7oXA#6pzxU!o*v88CBc9!ZN{N zm3Wjf1!i_cliD5C22$QEF)3Z8eU*>@PDfhbzf(@=L?umd&|(6tf_qV{pHBjL>fVEZ zQ`@p~_VX=zp^4={g%(XAKr%o^ISnwcLbbbU!hK)GDeJz>0Yfx379LD=DjN@}C66Es z_rxG!AlHW6@SJs&A#{|+uPN9VkK$@zYD1K7UEUEp((tMq4X=((MRF8v>AsjL20x5P zNfTfSNnHl-zKoQfX32`zIB&LuAmyKxQfL=w)x^MzRa#Ew(SL-&)K0 zJ(hB2Dfch)GSi==Zt-7Yg@AxeJhV6-^}PxfRg)e-7v{i&OMenel*JE*!rTH_B1nRa z3YWl?xj~OrYJaF@`B?HnD*ooJG&!VWmSJ#xGFwNGVx1G!w7|malEUCrX}Hu%x*fG* z-##qapp%7~<(A7KS)f|#9e8^#=oOFh=E8!?0QYbQ z0(%SV-hsj;lO$6Dt7*Sy&arr@FG}51PzfY z7r$!)i}WP%sBED|qPn(Dvdc3}waQQb4ojv?_+D$QlwW?hQ}5$;bp8C;BIH)Lrh4=% zKd#UaK{Afih58o240dOq}=_lkP!oc z?fva!+{l?QXKGN|2>d)VL?qsCG727#u9^YcZ;WJ&VE7(5YrUG|X3iugNXC07n4HSG zi($Wd0)XU9eg(q+JYt@czo+cwlX)3U{U(F{xlQm6Qx(8#Rk@8F*2Tx<=Ai`jVO z0MKdJ+2X57k;@D^e?(N*>%Fh#rgKqgi@3neFmGW5lZ0f=fi)Z-l=b!o5VlG@8gdh? zo~kZD<)#B)+8YdY&WVPsrbuyhGMEPF0w)$}r5`U#1vhJ32~7g9DGl6DZB8wQPlW(V zKhiebKta0A1HmYoIo>)@V;U}PxH=tBwGPK+fXB!p5sL3KfZA9`9y~S(Q1wAZla`ZI zm=tH$3gYU)U?R&7*KFF8z&UZlJqZb+BqO3#9kBF9?8ycLyRXRvn*hanL^e}5v-E|O z!L*6P*c$}Q|B1NG@K~Q2*+|^>BHg$ee;T&Kxw+tZY#kP8mGPK7@Pa1VYj=T6b)JE% zhJ#PECu8yhGzq90NwMjO)7Yr_L-ieX=1_V-o($SCn4R4Vzc~yf8MssmZ@*b(4; zjY;NNUh8r2f&#F|s(*R=BGYPit`N*qF~N*r>Hc{n*vkdp4bF;Ge^6ng8#N#SrroHo zPM$%eBS%}T6Y=3;pa`4ug1h);G`L5VBs8YM-5#*Z-G)GH4qXW~23R?sw$j|KN?Pn`3De7Y*gBt%^+98#AQJaSkOwbGfacDu@RSh;#GEJ)icTf-FYr%evXIN+UiQq-;$!8OTd+l8Z4(VUY zlG!*C756ZXeEU35FYhBjILkW2a<%zYbBt-YG+x{xyv6r0_i&fl*<`;<2pmEsu%I?j zTy)iN!=}_?ym$%-m&2$+jkmXGCJd{U=SDHLglUx60 zEyY??ZFPsV)famv0~L%$w242P0#0a8EF2#Q%x|Xxs@HX){>TH18zLYWpPmM40M)+W z8>fRKdVRUk3{(V*rmL8pYWUjExvF_{GZ!AwCE%)e1*h`OZzg5yAuX&`)s2EhrBM|R zJS>di;+mSY>^Q11QbpV-85OE9%2-CgBbIUl_H?5KXe69EQ=J`Bl3gq}Pv`k&UME>p z7wSe6Q30%-6D3+hQ_M6@xI%$*qj6{iEQ)Sk&ZL{`IoltB44m7n)#9)Z;IEp&t$GdP zd98rz&3RObaxu70g1BZDKziCNnfO5ra}+qH+Ml$Wxx3^l+l|)0SZ+2yZhDk}nyPBR&+tCCxpHKw1tah}mEMKQ>wC59hc%v>PA&Q0MpbX1Py$IM?PH}>_r?qbG)Xa(8kU9tEXL#5YWNR ze$cIPBPGj$^KS)xG|({fRCxh zi;SC=?P9~z2E69abo#{;)`Gp%vIB3^%3RnZ-KYeuhJ~|K$e`ww@I?8*^QH;hWPY-? zS3T~l=nX?jAHCMQdl z9${iY8so^Yx5}GXi|y~$pRJ=UE6rb;b3vNv2FW7U3D@zvxVJf1=&d<8tt*H*LNjb^ z*$C7@Wdze=mqG(*{I+7q2D>)Vi4k9SH@#zAw;8O}@7Im``jTK#MI<(Y%0KaMdkMRI zIWeC)NzocO8h{X3Z}31-mF!xly{$4J&jJA9AU!jtPcQw+W5&#i<&=LmvR~ctkZ{ z7|_TPfz}A2xtT z{D`LIh#i(asv*?y1Jyqs)La_3ZAh`i7x)Ij%oa5>P%YRQpR0^*jV_2TVzhKvRTt?# zaH&T~#>Y?EhZ-7UT)hwY^wJKI#a(0;_5*Nq*iVUP?Af+YZ5h^nmSpp-rVFOg;4Ntp z^Mi0!7{E7j>)7W)aW@R(!-fP`@f4s>67jx+hM>Cn5THhd5~}qz!m29mNV@#HxDveM z3A$8DDBCv)W~OTt6`L)|_?KNQU4KtLNvCh#@*|T;kZ-yh#rZ0rCy(TD-He3{%3Seq zB)+qqoO=Y0?JZh+gjaOaR&k>wUo9*oYBjuHdMK$3-+sjKJ~`9!)ev%eIWq=FK~r!c zEg8f!D8W}v9b~C7hS4bz;OxN6c-Xf}mp~TpC<s?3kCAgs25yCCpCMQ6GB-~Gzyx}P;zCwmIm{cRBU*e6 zxN0!Yp;Qa^-IM%@))PeDD*?p^2$JaGU-)1F}qNv zZv||q)_FzsX#&!y3P{)8jm!9M{!Q@f>3qJNEVEFQJmPJR5yB(#SC;2(-}2``s@2Ec z#XbeTGv8x+nOVsH%GYxDacS&Y@D@nKsENxXXKcQ?FrA#w5%WX_*0}v4c2Y3Nm_gS&@7=|!la{c8@YTCnD!6gQ9+v9EcwtlE{H+Ube3+$9w0YA2?F1Hg zJjOnv=juX3eN$n>WSw%l9%N_G%E7(%v0w0(Df-HT`|UJJ{B7V#SYqvny_#7X%Zi?Ve2T9bmR6(?@1{n#+gDk}vR7S2VJ7xl zt8vBCtO{gxaIyTbW)t0$j)UyudIj52xjzP0g&-U`J?M`&EaZoCGq~v*ZV!$dwJe7d zo?z9vWmttc`$_gw{R2Cy@Y`W+h#fBOW~Z}k0^yX3@5~zzJ~48loBT4Ie|>QB>mhT_ zZZ-}dTWoFTX0V0Y%16EcPK;K$!xLaPit*cEZgFH76NGdr>n-_)n+I+*#BYT~`B4=m z<&=FS7w8TnM=Rlz13Q}Jw?Gd$^D}E%>!zb@9SAgQKBIYYM7ydz zBX@J~rDxb*TxhUggxO1V4*cu^wuyFNH!AcCux??5D7djM(b8;~;JDBTKM!*nRm}xk z>5^mY_+TsDbCw8s{8*%)bCayf!OUnFoGWo2Lz8^?INNUnYyGf0xt^<4$HNgjZ)@b# z(PsET_bpAF2=q^Q^D^c-;>#U4dkRNqhJQ`rXk2-0DyIUhFgLtu8uuYt}G(0WyX&IVvn&D9h)9IoCu~ho5WVrqES`*adtUK&9%1wh$&S!PmBO)D%fVg+3YP z=41Ia&>ycal~bbnfWvJZyKUgRj1!Dt969z?@}EttnX$e`4on*?PlFLsZ?RBV%b(&! zt~i7-ZxDTMe_z;+Pgsa~Mz-6U@qWNhCo0f2l?^N(=wQOb$YPGChq)qecyNm6sa6iJ z6?paJC!*Oxk*DI_g+}`O!OEqP#Dz;Fel}P@Wh~1sd!8o@Fv@V6&N5hoHJ00gFMHgBD)BgQ6pO&B_N-R%jZnhS28$Q?=Fiuf=O+ zo;o7HtL!`l`*DtgSC6*BTR!aM!SPJOCI+MekZNBf-{Tl&+hILrwOX9!3eyA9e({1h zRG7`Lg>P#?U>htmgs?=4>K z>B7R`BX9F+2d68X>)zqjB0y$-p<|obXZh1|CaQx;+MJopQ1F;{`C^t!BSuNVs|F-F z@HaO|kyS3dOK%zPe~;YsPIu7QKHRWqynO5Wl}u$)?!lA~`I;fnM8J(SeW z_xV?-2i6aG>fp{!j)}&@%&EZ%H~!!QzLpK%W6~1k6^Ba>v>a8&4kCwT1m~+_9r%!6 z`hUMBk-2jP%%6@sKH`&b$w9$_TU(_Z{NrDF3VY&3AMw;}NOe3p4rW$`mMgiyj{}n0 zBc%lH#~$6C86LYG{+Q?MvtpTdc*hd^E9@i8J8~WPhTFm~6NcD%+a~LG);h~-^D)!+ zrYh+H@pa*Q&2hTw?fAbQ;SGcOi~NINg*H-A_vsxi)UlQ;-%i7^#RA=Ks@Ey*D-r^J z6PiFf7&OYCNn$a0a*qEoN|?x+qKmX0mHD#>Mi0?tj1s1>QZyZ8P@}&fb|K zL+Q&6d`Va59|}Fy5n9|(AWWbo?f#`eXaUY#e+F!vP7f|-l5eQZkG9U8b1t?IWrl3jAO_(pjGmN zwogGB88}v26!UgdkEyS;LVRAd2{ZVe+&`Fc>>}#&j2q?pD`BlR zLZ)cjOC3!HS{Fff<6xzZ7M~~=rqQE(HyY-zfDO|lups2L&BA1MA?4w2l53wtQLksirk3>&m7HF}v!x&)75Ays!{VBKU|rassiZ!a>C z;!6{RZIn0I(P)1Wtf&gQFYcH~I{HgB!e}5GZ|&GgY8j>Fsz9E5EJ{bPBU@C1=6Two8^3yuxo{%+^TLKB5YB{bPr3@az&V;>8B zaLWOq9RGTeKJe;Z_K7f@dI`VxsX(3o;@y7})H^Ma%8Kv*OrUNFcQ5-~_+8}^i5q<6 zOMwC@BEwi}nIQyH4R(`uek#j7| z*%)b-X{hxHM-KO>kRg0#-pyW;yHoayYglc?5Y%v^k*E!3lJHSCq`OFVW~p4p!7ChC z<3|sP6zt~39n52)!~t=}lOjFb|IF}!H~q{!8=_Cev${nJ0pg)giByxoTjQC>L-etD z_YslWw0eL(1r}FEC5wi&V!7b}gte{1+g|{G!B0LdQqz9|0+}7!8eR1!ob#+`Rllx) zJ!XK7N#&Z?ieFg^V`HN z_M5q5rUk-n<};R;;iVs$S-7FTe>2{CQly)a>X*fp)B@&5nGUkRQa6hCErx}KQ5NVJ z;VO)3fCu_IU|OLH>H_|TQ+mXae^`_()0i}}Mv5D8zNK)GZuA>WGw5aez`%$(e9Xn# z+Hm~_OA@)zI+3I&-__cC`hX=jvw+V!kj={s25k5nb9mls;>*-79mT*F^1kJG$tm%I z{$qUe8zLRlWc++G6SM)xO#2gd3AD-A+IrX`TawjhIblgPPc^NT-X>qw$`{J{qvXcT z&k?>{p92;PHd9W9Vz>YHs@ng9*&P{fZiXYt+na<$T?}&j*LL1MD zfr~LOpA~N*Od$?kDd^ttu9zE0d!bBVN3;AhV77MLtonYhb7C_Xp@Ev|I})7u;?u71 zEXRck{L^8v4zl6j&x!3uq?qfU1`9hPl>whQFV3W!RXeKoPlZJ*R3dfNt?!F%+BXr% zT?^ya&FpBre+tYE-Ic`)KM5GM_4 zy1$+rJVl5xK^bw_`-)s-pmigMzYgZ+Mo5EvJJQX=*g11(83y@l2~>@uExpEG6U8^x zUjqvoqiD%l#keTi6n{0W@|Vdb%g5#HgCMN-=3B7mucktjj=d%U%{-k@PP~UA}U4wVIIDw4D`airVwaSyi!uT zSl!K{o|Te{Fd)8hl@y4+{i`GumgvenzEM(dW$1RicD3XsPs01)9obC(uF`(E<)$FJ z@Xf_>HyhZgmF7$+MHO~>rB1J@(`)YZS~|VfPOq)gD|dSBonA+$*V*ZHb$Vkuy|B|8 z+v$z#^u~93-JRZqPH(SHZ|_cTVyCxHr?+pXw_m3>sneU>=}qbM_V4tj9`+94x0%+6 zWn?k-uidufGz%9=U6JAx{@3b1j~$pseg~4@bn=@)eg~1?!Q?lS{AP8J9hiN5i&KCdPU;AqLzw!fe%>T+XF#QX!@&EZJ$-b2WGNHXAac-8S7aqDb+u2=mD*HJ5KPQ~H AAOHXW diff --git a/data/quarantined-sources.json b/data/quarantined-sources.json index d851726b..31bde545 100644 --- a/data/quarantined-sources.json +++ b/data/quarantined-sources.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-04-11T23:10:14.423Z", + "generatedAt": "2026-04-11T23:45:27.477Z", "count": 188, "sources": [ { diff --git a/data/source-remediation-sweep.json b/data/source-remediation-sweep.json index 4b161d62..79e1112f 100644 --- a/data/source-remediation-sweep.json +++ b/data/source-remediation-sweep.json @@ -1,48 +1,3283 @@ { "generatedFrom": "live-alerts.json", - "generatedAt": "2026-04-11T23:10:14.423Z", - "totalSourceErrors": 1, + "generatedAt": "2026-04-11T23:45:27.477Z", + "totalSourceErrors": 184, "byCategory": { - "anti-bot-protection": 1 + "network-failure": 184 }, "byKind": { - "rss": 1 + "html": 124, + "rss": 50, + "atom": 4, + "json": 6 }, - "machineReadableErrorCount": 1, - "htmlErrorCount": 0, + "machineReadableErrorCount": 60, + "htmlErrorCount": 124, "top20": [ { - "id": "gnet-radicalisation-rss", - "provider": "Global Network on Extremism & Technology (GNET) a Radicalisation (RSS)", - "endpoint": "https://gnet-research.org/tag/radicalisation/feed/", + "id": "act-campaign", + "provider": "ACT Awareness Campaign", + "endpoint": "https://act.campaign.gov.uk/", "finalUrl": "", - "category": "anti-bot-protection", - "message": "Blocked by anti-bot protection", - "status": 200, - "rankScore": 2, - "suggestedAction": "downgrade to non-bot-protected endpoint or quarantine if no public feed", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "attorney-generals-office-html", + "provider": "Attorney General's Office", + "endpoint": "https://www.gov.uk/government/organisations/attorney-generals-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-news", + "provider": "Austrian Interior Ministry - News", + "endpoint": "https://www.bmi.gv.at/news.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-rss-index", + "provider": "Austrian Interior Ministry - RSS Index", + "endpoint": "https://www.bmi.gv.at/rss_feed/start.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-and-somerset-police-news-html", + "provider": "Avon and Somerset Police - News", + "endpoint": "https://www.avonandsomerset.police.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-somerset-police-news", + "provider": "Avon & Somerset Police a News", + "endpoint": "https://www.avonandsomerset.police.uk/newsroom/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bbc-news-england-legacy", + "provider": "BBC News a England (Legacy RSS)", + "endpoint": "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/england/rss.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", "replacementCandidate": "", "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "bexley-council-news", + "provider": "Bexley Council a News", + "endpoint": "https://www.bexley.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bfv-de-english", + "provider": "BfV press page (Federal Office for the Protection of the Constitution)", + "endpoint": "https://www.verfassungsschutz.de/EN/service/press/press_node.html", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", "sourceLane": "prevention", "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cabinet-office-html", + "provider": "Cabinet Office", + "endpoint": "https://www.gov.uk/government/organisations/cabinet-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "camden-council-news", + "provider": "Camden Council a News", + "endpoint": "https://news.camden.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "chathamhouse-intl-security-feed", + "provider": "Chatham House a International Security Programme (RSS)", + "endpoint": "https://www.chathamhouse.org/path/83/feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chathamhouse-whatsnew", + "provider": "Chatham House a What's New (RSS)", + "endpoint": "https://www.chathamhouse.org/path/whatsnew.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chelsea-westminster-news", + "provider": "Chelsea and Westminster Hospital NHS Foundation Trust a News", + "endpoint": "https://www.chelwest.nhs.uk/about-us/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cisa-cybersecurity-advisories", + "provider": "CISA - Cybersecurity Alerts & Advisories", + "endpoint": "https://www.cisa.gov/news-events/cybersecurity-advisories", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "crown-office-news", + "provider": "Crown Office and Procurator Fiscal Service - News", + "endpoint": "https://www.copfs.gov.uk/about-copfs/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "croydon-council-news", + "provider": "Croydon Council a News", + "endpoint": "https://news.croydon.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "curia-press-rss-en", + "provider": "Court of Justice of the European Union - RSS (EN/FR)", + "endpoint": "https://curia.europa.eu/site/rss.jsp?lang=en&second. Lang=fr", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", "isMachineReadable": true + }, + { + "id": "dc-police-community-messaging", + "provider": "Dorset and Cornwall Police - Community Messaging", + "endpoint": "https://community-messaging.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "devon-cornwall-alerts", + "provider": "Devon and Cornwall Alerts", + "endpoint": "https://alerts.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false } ], "sources": [ { - "id": "gnet-radicalisation-rss", - "provider": "Global Network on Extremism & Technology (GNET) a Radicalisation (RSS)", - "endpoint": "https://gnet-research.org/tag/radicalisation/feed/", + "id": "act-campaign", + "provider": "ACT Awareness Campaign", + "endpoint": "https://act.campaign.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "attorney-generals-office-html", + "provider": "Attorney General's Office", + "endpoint": "https://www.gov.uk/government/organisations/attorney-generals-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-news", + "provider": "Austrian Interior Ministry - News", + "endpoint": "https://www.bmi.gv.at/news.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-rss-index", + "provider": "Austrian Interior Ministry - RSS Index", + "endpoint": "https://www.bmi.gv.at/rss_feed/start.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-and-somerset-police-news-html", + "provider": "Avon and Somerset Police - News", + "endpoint": "https://www.avonandsomerset.police.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-somerset-police-news", + "provider": "Avon & Somerset Police a News", + "endpoint": "https://www.avonandsomerset.police.uk/newsroom/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bbc-news-england-legacy", + "provider": "BBC News a England (Legacy RSS)", + "endpoint": "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/england/rss.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "bexley-council-news", + "provider": "Bexley Council a News", + "endpoint": "https://www.bexley.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bfv-de-english", + "provider": "BfV press page (Federal Office for the Protection of the Constitution)", + "endpoint": "https://www.verfassungsschutz.de/EN/service/press/press_node.html", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cabinet-office-html", + "provider": "Cabinet Office", + "endpoint": "https://www.gov.uk/government/organisations/cabinet-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "camden-council-news", + "provider": "Camden Council a News", + "endpoint": "https://news.camden.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "chathamhouse-intl-security-feed", + "provider": "Chatham House a International Security Programme (RSS)", + "endpoint": "https://www.chathamhouse.org/path/83/feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chathamhouse-whatsnew", + "provider": "Chatham House a What's New (RSS)", + "endpoint": "https://www.chathamhouse.org/path/whatsnew.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chelsea-westminster-news", + "provider": "Chelsea and Westminster Hospital NHS Foundation Trust a News", + "endpoint": "https://www.chelwest.nhs.uk/about-us/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cisa-cybersecurity-advisories", + "provider": "CISA - Cybersecurity Alerts & Advisories", + "endpoint": "https://www.cisa.gov/news-events/cybersecurity-advisories", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "crown-office-news", + "provider": "Crown Office and Procurator Fiscal Service - News", + "endpoint": "https://www.copfs.gov.uk/about-copfs/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "croydon-council-news", + "provider": "Croydon Council a News", + "endpoint": "https://news.croydon.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "curia-press-rss-en", + "provider": "Court of Justice of the European Union - RSS (EN/FR)", + "endpoint": "https://curia.europa.eu/site/rss.jsp?lang=en&second. Lang=fr", "finalUrl": "", - "category": "anti-bot-protection", - "message": "Blocked by anti-bot protection", - "status": 200, - "rankScore": 2, - "suggestedAction": "downgrade to non-bot-protected endpoint or quarantine if no public feed", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", "replacementCandidate": "", "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "dc-police-community-messaging", + "provider": "Dorset and Cornwall Police - Community Messaging", + "endpoint": "https://community-messaging.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "devon-cornwall-alerts", + "provider": "Devon and Cornwall Alerts", + "endpoint": "https://alerts.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "dhs-press-releases", + "provider": "US Department of Homeland Security - News", + "endpoint": "https://www.dhs.gov/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "dsn-at-english", + "provider": "DSN Austria news", + "endpoint": "https://www.dsn.gv.at/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", "sourceLane": "prevention", "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "dutch-police-rss-index", + "provider": "Politie.nl - RSS", + "endpoint": "https://www.politie.nl/rss", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "ealing-council-news", + "provider": "Ealing Council a News", + "endpoint": "https://www.ealing.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "echr-key-judgments-rss", + "provider": "European Court of Human Rights - Key Judgments RSS", + "endpoint": "https://hudoc.echr.coe.int/app/transform/rss?length=20&library=echreng&query=%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28+contentsitename%3AECHR+AND+%28NOT+%28doctype%3DPR+OR+doctype%3DHFCOMOLD+OR+doctype%3DHECOMOLD%29%29+AND+%28%28importance%3D%221%22%29+OR+%28importance%3D%222%22%29+OR+%28importance%3D%223%22%29%29+AND+%28%28documentcollectionid%3D%22GRANDCHAMBER%22%29+OR+%28documentcollectionid%3D%22CHAMBER%22%29+OR+%28documentcollectionid%3D%22DECGRANDCHAMBER%22%29+OR+%28documentcollectionid%3D%22ADMISSIBILITY%22%29%29%29+XRANK%28cb%3D14%29+doctypebranch%3AGRANDCHAMBER%29+XRANK%28cb%3D13%29+doctypebranch%3ADECGRANDCHAMBER%29+XRANK%28cb%3D12%29+doctypebranch%3ACHAMBER%29+XRANK%28cb%3D11%29+doctypebranch%3AADMISSIBILITY%29+XRANK%28cb%3D10%29+doctypebranch%3ACOMMITTEE%29+XRANK%28cb%3D9%29+doctypebranch%3AADMISSIBILITYCOM%29+XRANK%28cb%3D8%29+doctypebranch%3ADECCOMMISSION%29+XRANK%28cb%3D7%29+doctypebranch%3ACOMMUNICATEDCASES%29+XRANK%28cb%3D6%29+doctypebranch%3ACLIN%29+XRANK%28cb%3D5%29+doctypebranch%3AADVISORYOPINIONS%29+XRANK%28cb%3D4%29+doctypebranch%3AREPORTS%29+XRANK%28cb%3D3%29+doctypebranch%3AEXECUTION%29+XRANK%28cb%3D2%29+doctypebranch%3AMERITS%29+XRANK%28cb%3D1%29+doctypebranch%3ASCREENINGPANEL%29+XRANK%28cb%3D4%29+importance%3A1%29+XRANK%28cb%3D3%29+importance%3A2%29+XRANK%28cb%3D2%29+importance%3A3%29+XRANK%28cb%3D1%29+importance%3A4%29+XRANK%28cb%3D2%29+languageisocode%3AENG%29+XRANK%28cb%3D1%29+languageisocode%3AFRE&ranking. Model. Id=4180000c-8692-45ca-ad63-74bc4163871b&sort=kpdate+Descending&start=0", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "echr-press-releases-rss", + "provider": "European Court of Human Rights - Press Releases RSS", + "endpoint": "https://hudoc.echr.coe.int/app/transform/rss?length=20&library=echrengpress&query=contentsitename%3AECHR+AND+doctype%3DPR&ranking. Model. Id=11111111-0000-0000-0000-000000000000&sort=kpdate+Descending&start=0", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "echr-uk-grand-chamber-rss", + "provider": "European Court of Human Rights - UK Grand Chamber RSS", + "endpoint": "https://hudoc.echr.coe.int/app/transform/rss?length=20&library=echreng&query=%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28%28+contentsitename%3AECHR+AND+%28NOT+%28doctype%3DPR+OR+doctype%3DHFCOMOLD+OR+doctype%3DHECOMOLD%29%29+AND+%28%28respondent%3D%22GBR%22%29%29+AND+%28%28documentcollectionid%3D%22GRANDCHAMBER%22%29%29%29+XRANK%28cb%3D14%29+doctypebranch%3AGRANDCHAMBER%29+XRANK%28cb%3D13%29+doctypebranch%3ADECGRANDCHAMBER%29+XRANK%28cb%3D12%29+doctypebranch%3ACHAMBER%29+XRANK%28cb%3D11%29+doctypebranch%3AADMISSIBILITY%29+XRANK%28cb%3D10%29+doctypebranch%3ACOMMITTEE%29+XRANK%28cb%3D9%29+doctypebranch%3AADMISSIBILITYCOM%29+XRANK%28cb%3D8%29+doctypebranch%3ADECCOMMISSION%29+XRANK%28cb%3D7%29+doctypebranch%3ACOMMUNICATEDCASES%29+XRANK%28cb%3D6%29+doctypebranch%3ACLIN%29+doctypebranch%3AADVISORYOPINIONS%29+doctypebranch%3AREPORTS%29+doctypebranch%3AEXECUTION%29+doctypebranch%3AMERITS%29+doctypebranch%3ASCREENINGPANEL%29+XRANK%28cb%3D4%29+importance%3A1%29+XRANK%28cb%3D3%29+importance%3A2%29+XRANK%28cb%3D2%29+importance%3A3%29+XRANK%28cb%3D1%29+importance%3A4%29+XRANK%28cb%3D2%29+languageisocode%3AENG%29+XRANK%28cb%3D1%29+languageisocode%3AFRE&ranking. Model. Id=4180000c-8692-45ca-ad63-74bc4163871b&sort=kpdate+Descending&start=0", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eppo-news-node-7", + "provider": "European Public Prosecutor's Office - News and Media", + "endpoint": "https://www.eppo.europa.eu/en/node/7", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-cellar-rss-atom", + "provider": "Publications Office of the European Union (CELLAR) a RSS/Atom Feeds", + "endpoint": "https://op.europa.eu/en/web/cellar/cellar-data/rss-and-atom-feeds", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-commission-counter-terrorism-measures-2026", + "provider": "European Commission - Counter Terrorism Measures 2026", + "endpoint": "https://commission.europa.eu/news-and-media/news/commission-proposes-new-measures-prevent-and-counter-terrorism-2026-02-26_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-commission-home-affairs-topic", + "provider": "European Commission - Home Affairs", + "endpoint": "https://commission.europa.eu/topics/home-affairs_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-council-jha-meetings", + "provider": "Council of the European Union a Justice & Home Affairs Meetings (RSS)", + "endpoint": "https://www.consilium.europa.eu/en/rss/meetings.ashx?cat=jha", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eu-council-jha-register-rss", + "provider": "Council of the EU - Justice and Home Affairs Register RSS", + "endpoint": "https://www.consilium.europa.eu/en/register/rss/THMJHA.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eu-council-press-releases", + "provider": "Council of the European Union a Press Releases (RSS)", + "endpoint": "https://www.consilium.europa.eu/en/rss/pressreleases.ashx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eu-council-press-releases-html", + "provider": "Council of the EU - Press Releases", + "endpoint": "https://www.consilium.europa.eu/en/press/press-releases/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-ejustice-news-rss", + "provider": "European e-Justice - News RSS", + "endpoint": "https://e-justice.europa.eu/rss/news_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eu-eppo-news", + "provider": "European Public Prosecutor's Office a Press Releases", + "endpoint": "https://www.eppo.europa.eu/en/media/press-releases", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-fra-rss", + "provider": "EU Agency for Fundamental Rights (FRA) a RSS", + "endpoint": "https://fra.europa.eu/en/content/rss", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-home-affairs-news", + "provider": "European Commission a Home Affairs News", + "endpoint": "https://home-affairs.ec.europa.eu/news_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-olaf-news", + "provider": "OLAF (EU Anti-Fraud Office) a News", + "endpoint": "https://anti-fraud.ec.europa.eu/media-corner/news_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eu-security-union-strategy", + "provider": "European Commission a Security Union Strategy", + "endpoint": "https://home-affairs.ec.europa.eu/policies/internal-security_en", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "euaa-news", + "provider": "EUAA (EU Agency for Asylum) a News", + "endpoint": "https://euaa.europa.eu/news-events", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "border", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eulisa-news-events", + "provider": "eu-LISA - News and Events", + "endpoint": "https://www.eulisa.europa.eu/news-and-events", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "border", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eurojust-press-news-html", + "provider": "Eurojust - Press Releases and News", + "endpoint": "https://www.eurojust.europa.eu/media-and-events/press-releases-and-news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "eurojust-press-releases", + "provider": "Eurojust a Press Releases (RSS)", + "endpoint": "https://www.eurojust.europa.eu/rss/press-releases.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eurojust-publications", + "provider": "Eurojust a Publications (RSS)", + "endpoint": "https://www.eurojust.europa.eu/rss/publications.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "eurojust-rss-feeds-page", + "provider": "Eurojust - RSS Feeds", + "endpoint": "https://www.eurojust.europa.eu/rss-feeds", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "euronews-europe", + "provider": "Euronews a Europe", + "endpoint": "https://www.euronews.com/news/europe", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "europarl-committee-libe", + "provider": "European Parliament a LIBE Committee (RSS)", + "endpoint": "https://www.europarl.europa.eu/rss/committee/libe/en.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "europarl-committee-sede", + "provider": "European Parliament a SEDE Committee (RSS)", + "endpoint": "https://www.europarl.europa.eu/rss/committee/sede/en.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "europarl-pressreleases-committees", + "provider": "European Parliament a Press Releases (Committees) (RSS)", + "endpoint": "https://www.europarl.europa.eu/rss/doc/press-releases-committees/en.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "europol-news-rss", + "provider": "Europol a Newsroom (RSS)", + "endpoint": "https://www.europol.europa.eu/rss.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "extremism-commission-blog", + "provider": "Commission for Countering Extremism - Blog", + "endpoint": "https://extremismcommission.blog.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "fcdo-html", + "provider": "Foreign, Commonwealth & Development Office", + "endpoint": "https://www.gov.uk/government/organisations/foreign-commonwealth-development-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "french-justice-ministry-news", + "provider": "French Ministry of Justice - News", + "endpoint": "https://www.justice.gouv.fr/actualites", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "german-bka-press-releases-de", + "provider": "BKA Germany - Press Releases", + "endpoint": "https://www.bka.de/DE/Aktuelle. Informationen/Aktuelle. Meldungen/Pressemeldungen/pressemitteilungen_node.html", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gnet-artificial-intelligence-rss", + "provider": "Global Network on Extremism & Technology (GNET) a Artificial Intelligence (RSS)", + "endpoint": "https://gnet-research.org/tag/artificial-intelligence/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gnet-research", + "provider": "Global Network on Extremism & Technology (GNET) a Main Feed", + "endpoint": "https://gnet-research.org/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gosh-news", + "provider": "Great Ormond Street Hospital a News", + "endpoint": "https://www.gosh.nhs.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-scot-access-to-justice-latest", + "provider": "Scottish Government - Access to Justice Latest", + "endpoint": "https://www.gov.scot/policies/access-to-justice/latest/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-cabinet-office-atom", + "provider": "Cabinet Office a GOV.UK Atom Feed", + "endpoint": "https://www.gov.uk/government/organisations/cabinet-office.atom", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "atom", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-contest-strategy", + "provider": "GOV.UK a CONTEST Counter-Terrorism Strategy", + "endpoint": "https://www.gov.uk/government/collections/contest", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-counter-extremism-commissioner", + "provider": "Counter Extremism Commissioner a GOV.UK", + "endpoint": "https://www.govwire.co.uk/rss/commission-for-countering-extremism", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-fcdo-travel-advice", + "provider": "FCDO a Foreign Travel Advice Index", + "endpoint": "https://www.gov.uk/foreign-travel-advice", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "border", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-hmcts", + "provider": "HMCTS a Courts and Tribunals Announcements", + "endpoint": "https://www.gov.uk/government/organisations/hm-courts-and-tribunals-service", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-hmic", + "provider": "HM Inspectorate of Constabulary a GOV.UK", + "endpoint": "https://hmicfrs.justiceinspectorates.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-home-office-atom", + "provider": "UK Home Office a Atom Feed", + "endpoint": "https://www.gov.uk/government/organisations/home-office.atom", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "atom", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-ipco", + "provider": "Investigatory Powers Commissioner's Office a GOV.UK", + "endpoint": "https://www.ipco.org.uk/publications/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-mod-atom", + "provider": "Ministry of Defence a GOV.UK Atom Feed", + "endpoint": "https://www.gov.uk/government/organisations/ministry-of-defence.atom", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "atom", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-moj-atom", + "provider": "Ministry of Justice a GOV.UK Atom Feed", + "endpoint": "https://www.gov.uk/government/organisations/ministry-of-justice.atom", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "atom", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-news-and-communications-atom", + "provider": "GOV.UK - News and Communications Atom", + "endpoint": "https://www.gov.uk/search/news-and-communications.atom", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "gov-uk-prevent-strategy", + "provider": "UK Home Office - Prevent duty guidance", + "endpoint": "https://www.gov.uk/government/publications/prevent-duty-guidance", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-proscribed-terrorist-orgs", + "provider": "GOV.UK a Proscribed Terrorist Organisations", + "endpoint": "https://www.gov.uk/government/publications/proscribed-terror-groups-or-organisations--2", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "gov-uk-terrorism-search", + "provider": "GOV.UK Search - Terrorism", + "endpoint": "https://www.gov.uk/search/all?keywords=terrorism", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "guys-st-thomas-news", + "provider": "Guy's and St Thomas' NHS Foundation Trust a News", + "endpoint": "https://www.guysandstthomas.nhs.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hackney-council-news", + "provider": "Hackney Council a News", + "endpoint": "https://news.hackney.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "havering-council-news", + "provider": "Havering Council a News", + "endpoint": "https://www.havering.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hillingdon-council-news", + "provider": "Hillingdon Council a News", + "endpoint": "https://www.hillingdon.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hm-treasury-html", + "provider": "HM Treasury", + "endpoint": "https://www.gov.uk/government/organisations/hm-treasury", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hmiprisons-news", + "provider": "HM Inspectorate of Prisons - News", + "endpoint": "https://hmiprisons.justiceinspectorates.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hmiprobation-news", + "provider": "HM Inspectorate of Probation - News", + "endpoint": "https://hmiprobation.justiceinspectorates.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "home-office-media-blog", + "provider": "Home Office Media Blog", + "endpoint": "https://homeofficemedia.blog.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "hounslow-council-news", + "provider": "Hounslow Council a News", + "endpoint": "https://www.hounslow.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "independent-reviewer-terrorism-legislation", + "provider": "Independent Reviewer of Terrorism Legislation a Reports", + "endpoint": "https://terrorismlegislationreviewer.independent.gov.uk/category/reports/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "independent-reviewer-terrorism-legislation-html", + "provider": "Independent Reviewer of Terrorism Legislation", + "endpoint": "https://www.gov.uk/government/organisations/independent-reviewer-of-terrorism-legislation", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "islington-council-news", + "provider": "Islington Council a News", + "endpoint": "https://www.islington.media/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "judiciary-rss-feeds-page", + "provider": "Judiciary UK - RSS Feeds", + "endpoint": "https://www.judiciary.uk/rss-feeds/", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.judiciary.uk until 2026-04-11T23:50:15.275Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "judiciary-uk-announcements-feed", + "provider": "Judiciary UK - Announcements Feed", + "endpoint": "https://www.judiciary.uk/announcements/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "judiciary-uk-judgments-feed", + "provider": "Judiciary UK - Judgments Feed", + "endpoint": "https://www.judiciary.uk/judgments/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "judiciary-uk-news", + "provider": "Judiciary of England and Wales a News", + "endpoint": "https://www.judiciary.uk/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "judiciary-uk-publications-feed", + "provider": "Judiciary UK - Publications Feed", + "endpoint": "https://www.judiciary.uk/publications/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "kings-college-hospital-news", + "provider": "King's College Hospital NHS Foundation Trust a News", + "endpoint": "https://www.kch.nhs.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "kingston-council-news", + "provider": "Kingston Council a News", + "endpoint": "https://www.kingston.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "lambeth-council-news", + "provider": "Lambeth Council a News", + "endpoint": "https://love.lambeth.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "lnwh-news", + "provider": "London North West University Healthcare NHS Trust a News", + "endpoint": "https://www.lnwh.nhs.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "london-gov-rss-80603", + "provider": "Greater London Authority a RSS Feed 80603", + "endpoint": "https://www.london.gov.uk/rss-feeds/80603", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "london-gov-rss-80610", + "provider": "Greater London Authority a RSS Feed 80610", + "endpoint": "https://www.london.gov.uk/rss-feeds/80610", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "london-gov-rss-80611", + "provider": "Greater London Authority a RSS Feed 80611", + "endpoint": "https://www.london.gov.uk/rss-feeds/80611", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "london-gov-rss-80632", + "provider": "Greater London Authority a RSS Feed 80632", + "endpoint": "https://www.london.gov.uk/rss-feeds/80632", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "merton-council-news", + "provider": "Merton Council a News", + "endpoint": "https://www.merton.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "met-office-seasonal-advice", + "provider": "Met Office - Seasonal Advice", + "endpoint": "https://www.metoffice.gov.uk/weather/warnings-and-advice/seasonal-advice", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "met-police-latest-news", + "provider": "Metropolitan Police - Latest News", + "endpoint": "https://news.met.police.uk/latest_news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "met-police-news", + "provider": "Metropolitan Police Service a News", + "endpoint": "https://news.met.police.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "met-police-the-met-tag", + "provider": "Metropolitan Police - The Met Tag", + "endpoint": "https://news.met.police.uk/news/tag/the-met", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "mi5-uk-threat-level", + "provider": "MI5 (Security Service) a UK Threat Level", + "endpoint": "https://www.mi5.gov.uk/UKThreat. Level/UKThreat. Level.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "ministry-of-defence-html", + "provider": "Ministry of Defence", + "endpoint": "https://www.gov.uk/government/organisations/ministry-of-defence", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "moorfields-news", + "provider": "Moorfields Eye Hospital NHS Foundation Trust a News", + "endpoint": "https://www.moorfields.nhs.uk/about-us/news-and-blogs/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "mossos-news", + "provider": "Mossos d'Esquadra - News", + "endpoint": "https://mossos.gencat.cat/ca/actualitat/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "my-community-alert", + "provider": "My Community Alert", + "endpoint": "https://www.mycommunityalert.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "nelft-news", + "provider": "North East London NHS Foundation Trust a News", + "endpoint": "https://www.nelft.nhs.uk/news-events/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "netherlands-police-news", + "provider": "Dutch National Police - News", + "endpoint": "https://www.politie.nl/nieuws/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "newham-council-news", + "provider": "Newham Council a News", + "endpoint": "https://www.newham.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "nhs-london-nel-news", + "provider": "NHS North East London a News", + "endpoint": "https://northeastlondon.icb.nhs.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "nhs-london-nwl-news", + "provider": "NHS North West London a News", + "endpoint": "https://www.nwlondonicb.nhs.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "north-wales-community-alert", + "provider": "North Wales Community Alert", + "endpoint": "https://www.northwalescommunityalert.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "norway-pst-news", + "provider": "Norwegian Police Security Service - News", + "endpoint": "https://www.pst.no/alle-artikler/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "npcc-releases", + "provider": "National Police Chiefs' Council - Releases", + "endpoint": "https://news.npcc.police.uk/releases/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "nsa-cybersecurity-news", + "provider": "NSA - Cybersecurity Advisories & Guidance", + "endpoint": "https://www.nsa.gov/Press-Room/Press-Releases-Statements/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "ocam-be-english", + "provider": "CUTA (Belgium) threat analysis", + "endpoint": "https://cuta.belgium.be/general-threat-in-belgium/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "ofsi-blog-home", + "provider": "OFSI - Blog", + "endpoint": "https://ofsi.blog.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "ons-html", + "provider": "Office for National Statistics", + "endpoint": "https://www.gov.uk/government/organisations/office-for-national-statistics", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "osce-press-releases", + "provider": "OSCE a Press Releases", + "endpoint": "https://www.osce.org/press-releases", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "otsi-blog-home", + "provider": "OTSI - Blog", + "endpoint": "https://otsi.blog.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "oxleas-news", + "provider": "Oxleas NHS Foundation Trust a News", + "endpoint": "https://oxleas.nhs.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "parliament-all-bills-rss", + "provider": "Parliament - All Bills RSS", + "endpoint": "https://bills.parliament.uk/rss/allbills.rss", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "parliament-private-bills-rss", + "provider": "Parliament - Private Bills RSS", + "endpoint": "https://bills.parliament.uk/rss/privatebills.rss", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "parliament-public-bills-rss", + "provider": "Parliament - Public Bills RSS", + "endpoint": "https://bills.parliament.uk/rss/publicbills.rss", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-all-crime-leicester", + "provider": "Police.uk - Street Crime Around Leicester", + "endpoint": "https://data.police.uk/api/crimes-street/all-crime?lat=52.629729&lng=-1.131592", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-crime-categories-2024-01", + "provider": "Police.uk - Crime Categories (2024-01)", + "endpoint": "https://data.police.uk/api/crime-categories?date=2024-01", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-crimes-street-dates", + "provider": "Police.uk - Street Crime Dataset Dates", + "endpoint": "https://data.police.uk/api/crimes-street-dates", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain data.police.uk until 2026-04-11T23:50:20.916Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-outcomes-for-crime-e11dade0", + "provider": "Police.uk - Outcomes For Crime e11dade0", + "endpoint": "https://data.police.uk/api/outcomes-for-crime/e11dade0a92a912d12329b9b2abb856ac9520434ad6845c30f503e9901d140f1", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain data.police.uk until 2026-04-11T23:50:20.916Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-stops-force-leicestershire", + "provider": "Police.uk - Force Stops (Leicestershire)", + "endpoint": "https://data.police.uk/api/stops-force?force=leicestershire", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "police-uk-stops-street-leicester", + "provider": "Police.uk - Street Stops Around Leicester", + "endpoint": "https://data.police.uk/api/stops-street?lat=52.629729&lng=-1.131592", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "json", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "portugal-pj-news", + "provider": "Policia Judiciaria Portugal - News", + "endpoint": "https://www.policiajudiciaria.pt/?p=noticias", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "protectuk", + "provider": "ProtectUK (NPSA) a Protective Security Guidance", + "endpoint": "https://www.protectuk.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "psni-latest-news", + "provider": "Police Service of Northern Ireland - Latest News", + "endpoint": "https://www.psni.police.uk/latest-news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "redbridge-council-news", + "provider": "Redbridge Council a News", + "endpoint": "https://www.redbridge.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "rewards-for-justice", + "provider": "U.S. Department of State - Rewards for Justice", + "endpoint": "https://rewardsforjustice.net/rewards/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "richmond-council-news", + "provider": "Richmond Council a News", + "endpoint": "https://www.richmond.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "royal-brompton-harefield-news", + "provider": "Royal Brompton and Harefield Hospitals a News", + "endpoint": "https://www.rbht.nhs.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "sapo-se-english", + "provider": "Swedish Security Service English news", + "endpoint": "https://www.sakerhetspolisen.se/ovriga-sidor/other-languages/english-engelska/press-room/news.html", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "scotcourts-fai-determinations-rss", + "provider": "Scottish Courts - Fatal Accident Inquiry Determinations RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Fatal. Accident. Inquiry. Determinations", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-fai-hearings-rss", + "provider": "Scottish Courts - Fatal Accident Inquiry Hearings RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Fatal. Accident. Inquiry. Hearings", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-high-court-justiciary-judgments-rss", + "provider": "Scottish Courts - High Court of Justiciary Judgments RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Judgments/?Court=High+Court+of+Justiciary", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-high-court-practice-notes-rss", + "provider": "Scottish Courts - High Court of Justiciary Practice Notes RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Practice. Notes. And. Directions/?Category=High+Court+of+Justiciary", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-judgments-rss", + "provider": "Scottish Courts - Judgments RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Judgments", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-news-articles-rss", + "provider": "Scottish Courts - News Articles RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/News. Articles", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-publications-rss", + "provider": "Scottish Courts - Publications RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Publications", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "scotcourts-rss-feeds-page", + "provider": "Scottish Courts and Tribunals - RSS Feeds", + "endpoint": "https://www.scotcourts.gov.uk/rss-feeds/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "scotcourts-sheriff-criminal-practice-notes-rss", + "provider": "Scottish Courts - Sheriff Court Criminal Practice Notes RSS", + "endpoint": "https://api.pa.web.scotcourts.gov.uk/web/rss/Practice. Notes. And. Directions/?Category=Sheriff+Court+Criminal", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "serious-fraud-office-news", + "provider": "Serious Fraud Office a News", + "endpoint": "https://www.sfo.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "south-yorkshire-police-alerts", + "provider": "South Yorkshire Police Alerts", + "endpoint": "https://www.sypalerts.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "st-georges-news", + "provider": "St George's University Hospitals NHS Foundation Trust a News", + "endpoint": "https://www.stgeorges.nhs.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "state-dept-terrorism", + "provider": "US State Department - Bureau of Counterterrorism", + "endpoint": "https://www.state.gov/bureaus-offices/under-secretary-for-civilian-security-democracy-and-human-rights/bureau-of-counterterrorism/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "stay-in-the-know-home", + "provider": "Stay In The Know - Community Alerts", + "endpoint": "https://www.stayintheknow.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "stay-in-the-know-latest-alerts", + "provider": "Stay In The Know - Latest Alerts", + "endpoint": "https://www.stayintheknow.co.uk/Content/Pages/Latest-Alerts", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "sutton-council-news", + "provider": "Sutton Council a News", + "endpoint": "https://www.sutton.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "swlstg-news", + "provider": "South West London and St George's Mental Health NHS Trust a News", + "endpoint": "https://www.swlstg.nhs.uk/latest-news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uclh-news", + "provider": "University College London Hospitals a News", + "endpoint": "https://www.uclh.nhs.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-border-force", + "provider": "Border Force (UK) a Announcements and Publications", + "endpoint": "https://www.gov.uk/government/organisations/border-force", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "border", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-home-office", + "provider": "UK Home Office a Announcements and Publications", + "endpoint": "https://www.gov.uk/government/organisations/home-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-iopc-news", + "provider": "Independent Office for Police Conduct a News", + "endpoint": "https://www.policeconduct.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-ncsc-all-rss", + "provider": "UK NCSC - All Updates RSS", + "endpoint": "https://www.ncsc.gov.uk/api/1/services/v1/all-rss-feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "uk-ncsc-news", + "provider": "National Cyber Security Centre (UK) a News", + "endpoint": "https://www.ncsc.gov.uk/api/1/services/v1/news-rss-feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "uk-ncsc-threat-reports", + "provider": "National Cyber Security Centre (UK) a Threat Reports", + "endpoint": "https://www.ncsc.gov.uk/api/1/services/v1/report-rss-feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "uk-ofsi-blog", + "provider": "Office of Financial Sanctions Implementation (OFSI) a Blog", + "endpoint": "https://ofsi.blog.gov.uk/feed/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "uk-parliament-defence-committee", + "provider": "UK Parliament a Defence Select Committee", + "endpoint": "https://committees.parliament.uk/committee/24/defence-committee/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-parliament-home-affairs-committee", + "provider": "UK Parliament a Home Affairs Committee (News)", + "endpoint": "https://committees.parliament.uk/committee/83/home-affairs-committee/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-prevent-duty-guidance", + "provider": "GOV.UK a Prevent Duty Guidance (Collection)", + "endpoint": "https://www.gov.uk/government/collections/prevent-duty-guidance", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "uk-ukvi", + "provider": "UK Visas and Immigration a Announcements and Publications", + "endpoint": "https://www.gov.uk/government/organisations/uk-visas-and-immigration", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "border", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "unoct-news", + "provider": "UN Office of Counter-Terrorism (UNOCT) - News", + "endpoint": "https://www.un.org/counterterrorism/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "unsc-1267-press-releases", + "provider": "UN Security Council - ISIL/Da'esh & Al-Qaeda Sanctions Committee Press Releases", + "endpoint": "https://main.un.org/securitycouncil/en/sanctions/1267/press-releases", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "us-treasury-ofac-press-releases", + "provider": "U.S. Treasury (OFAC) - Press Releases", + "endpoint": "https://ofac.treasury.gov/press-releases", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "us-treasury-ofac-recent-actions", + "provider": "U.S. Treasury (OFAC) - Recent Actions", + "endpoint": "https://ofac.treasury.gov/recent-actions", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "sanctions", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "waltham-forest-council-news", + "provider": "Waltham Forest Council a News", + "endpoint": "https://www.walthamforest.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "wandsworth-council-news", + "provider": "Wandsworth Council a News", + "endpoint": "https://www.wandsworth.gov.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "west-midlands-community-alerts", + "provider": "WMNow - Community Alerts", + "endpoint": "https://www.wmnow.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "west-yorkshire-community-alert", + "provider": "West Yorkshire Community Alert", + "endpoint": "https://www.wypcommunityalert.co.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "west-yorkshire-police-all-rss", + "provider": "West Yorkshire Police - All Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/all/feed", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "west-yorkshire-police-appeals-rss", + "provider": "West Yorkshire Police - Appeals Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/appeals/feed", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "west-yorkshire-police-coroner-appeals-rss", + "provider": "West Yorkshire Police - Coroner Appeals Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/coroner-appeals/feed", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.westyorkshire.police.uk until 2026-04-11T23:49:26.933Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "west-yorkshire-police-news-appeals", + "provider": "West Yorkshire Police - News Appeals", + "endpoint": "https://www.westyorkshirepolice.co.uk/news-appeals", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "west-yorkshire-police-news-rss", + "provider": "West Yorkshire Police - News Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/feed", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "west-yorkshire-police-releases-rss", + "provider": "West Yorkshire Police - Releases Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/releases/feed", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "incidents", + "sourceRegion": "", "isMachineReadable": true } ] diff --git a/data/sources.json b/data/sources.json index db5bffee..88aa4d5e 100644 --- a/data/sources.json +++ b/data/sources.json @@ -25,15 +25,13 @@ { "id": "frontex-news-releases", "provider": "Frontex a News Releases", - "endpoint": "https://www.frontex.europa.eu/media-centre/news/management-board-updates/", + "endpoint": "https://www.frontex.europa.eu/media-centre/news/news-release/", "kind": "html", "lane": "border", "region": "eu", "isTrustedOfficial": true, "requiresKeywordMatch": true, - "comment": "No RSS endpoint consistently published; using the News Release listing and relying on keyword filtering.", - "quarantined": false, - "restoredAt": "2026-04-11T18:16:02.308Z" + "comment": "No RSS endpoint consistently published; using the News Release listing and relying on keyword filtering." }, { "id": "austria-interior-ministry-news", diff --git a/data/top-20-source-remediation.json b/data/top-20-source-remediation.json index dba496bc..e1dc7a54 100644 --- a/data/top-20-source-remediation.json +++ b/data/top-20-source-remediation.json @@ -1,23 +1,327 @@ { "generatedFrom": "live-alerts.json", - "generatedAt": "2026-04-11T23:10:14.423Z", - "totalSourceErrors": 1, + "generatedAt": "2026-04-11T23:45:27.477Z", + "totalSourceErrors": 184, "top20": [ { - "id": "gnet-radicalisation-rss", - "provider": "Global Network on Extremism & Technology (GNET) a Radicalisation (RSS)", - "endpoint": "https://gnet-research.org/tag/radicalisation/feed/", + "id": "act-campaign", + "provider": "ACT Awareness Campaign", + "endpoint": "https://act.campaign.gov.uk/", "finalUrl": "", - "category": "anti-bot-protection", - "message": "Blocked by anti-bot protection", - "status": 200, - "rankScore": 2, - "suggestedAction": "downgrade to non-bot-protected endpoint or quarantine if no public feed", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "attorney-generals-office-html", + "provider": "Attorney General's Office", + "endpoint": "https://www.gov.uk/government/organisations/attorney-generals-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-news", + "provider": "Austrian Interior Ministry - News", + "endpoint": "https://www.bmi.gv.at/news.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "austria-interior-ministry-rss-index", + "provider": "Austrian Interior Ministry - RSS Index", + "endpoint": "https://www.bmi.gv.at/rss_feed/start.aspx", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-and-somerset-police-news-html", + "provider": "Avon and Somerset Police - News", + "endpoint": "https://www.avonandsomerset.police.uk/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "avon-somerset-police-news", + "provider": "Avon & Somerset Police a News", + "endpoint": "https://www.avonandsomerset.police.uk/newsroom/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "incidents", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bbc-news-england-legacy", + "provider": "BBC News a England (Legacy RSS)", + "endpoint": "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/england/rss.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", "replacementCandidate": "", "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "bexley-council-news", + "provider": "Bexley Council a News", + "endpoint": "https://www.bexley.gov.uk/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "bfv-de-english", + "provider": "BfV press page (Federal Office for the Protection of the Constitution)", + "endpoint": "https://www.verfassungsschutz.de/EN/service/press/press_node.html", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", "sourceLane": "prevention", "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cabinet-office-html", + "provider": "Cabinet Office", + "endpoint": "https://www.gov.uk/government/organisations/cabinet-office", + "finalUrl": "", + "category": "network-failure", + "message": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "camden-council-news", + "provider": "Camden Council a News", + "endpoint": "https://news.camden.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "chathamhouse-intl-security-feed", + "provider": "Chatham House a International Security Programme (RSS)", + "endpoint": "https://www.chathamhouse.org/path/83/feed.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chathamhouse-whatsnew", + "provider": "Chatham House a What's New (RSS)", + "endpoint": "https://www.chathamhouse.org/path/whatsnew.xml", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": true + }, + { + "id": "chelsea-westminster-news", + "provider": "Chelsea and Westminster Hospital NHS Foundation Trust a News", + "endpoint": "https://www.chelwest.nhs.uk/about-us/news", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "cisa-cybersecurity-advisories", + "provider": "CISA - Cybersecurity Alerts & Advisories", + "endpoint": "https://www.cisa.gov/news-events/cybersecurity-advisories", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "crown-office-news", + "provider": "Crown Office and Procurator Fiscal Service - News", + "endpoint": "https://www.copfs.gov.uk/about-copfs/news/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "oversight", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "croydon-council-news", + "provider": "Croydon Council a News", + "endpoint": "https://news.croydon.gov.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "context", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "curia-press-rss-en", + "provider": "Court of Justice of the European Union - RSS (EN/FR)", + "endpoint": "https://curia.europa.eu/site/rss.jsp?lang=en&second. Lang=fr", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "rss", + "sourceLane": "oversight", + "sourceRegion": "", "isMachineReadable": true + }, + { + "id": "dc-police-community-messaging", + "provider": "Dorset and Cornwall Police - Community Messaging", + "endpoint": "https://community-messaging.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false + }, + { + "id": "devon-cornwall-alerts", + "provider": "Devon and Cornwall Alerts", + "endpoint": "https://alerts.dc.police.uk/", + "finalUrl": "", + "category": "network-failure", + "message": "fetch failed", + "status": 0, + "rankScore": 1, + "suggestedAction": "retry later and monitor domain circuit-breaker/failure trend", + "replacementCandidate": "", + "sourceKind": "html", + "sourceLane": "prevention", + "sourceRegion": "", + "isMachineReadable": false } ] } diff --git a/live-alerts.json b/live-alerts.json index 71065f78..c84110e9 100644 --- a/live-alerts.json +++ b/live-alerts.json @@ -1,6 +1,6 @@ { - "generatedAt": "2026-04-11T23:10:14.423Z", - "sourceCount": 186, + "generatedAt": "2026-04-11T23:45:27.477Z", + "sourceCount": 0, "alertCount": 120, "alerts": [ { @@ -6853,14 +6853,254 @@ ], "sourceErrors": [ { - "id": "gnet-radicalisation-rss", - "provider": "Global Network on Extremism & Technology (GNET) a Radicalisation (RSS)", - "endpoint": "https://gnet-research.org/tag/radicalisation/feed/", - "finalUrl": "https://gnet-research.org/tag/radicalisation/feed/", - "status": 200, - "message": "Blocked by anti-bot protection", - "errorCode": "BLOCKED_ANTI_BOT", - "category": "anti-bot-protection" + "id": "west-yorkshire-police-all-rss", + "provider": "West Yorkshire Police - All Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/all/feed", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "west-yorkshire-police-appeals-rss", + "provider": "West Yorkshire Police - Appeals Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/appeals/feed", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "west-yorkshire-police-news-rss", + "provider": "West Yorkshire Police - News Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/feed", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "west-yorkshire-police-releases-rss", + "provider": "West Yorkshire Police - Releases Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/releases/feed", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "eurojust-press-releases", + "provider": "Eurojust a Press Releases (RSS)", + "endpoint": "https://www.eurojust.europa.eu/rss/press-releases.xml", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "europol-news-rss", + "provider": "Europol a Newsroom (RSS)", + "endpoint": "https://www.europol.europa.eu/rss.xml", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "london-gov-rss-80603", + "provider": "Greater London Authority a RSS Feed 80603", + "endpoint": "https://www.london.gov.uk/rss-feeds/80603", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "london-gov-rss-80610", + "provider": "Greater London Authority a RSS Feed 80610", + "endpoint": "https://www.london.gov.uk/rss-feeds/80610", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "london-gov-rss-80611", + "provider": "Greater London Authority a RSS Feed 80611", + "endpoint": "https://www.london.gov.uk/rss-feeds/80611", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "london-gov-rss-80632", + "provider": "Greater London Authority a RSS Feed 80632", + "endpoint": "https://www.london.gov.uk/rss-feeds/80632", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "police-uk-all-crime-leicester", + "provider": "Police.uk - Street Crime Around Leicester", + "endpoint": "https://data.police.uk/api/crimes-street/all-crime?lat=52.629729&lng=-1.131592", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "police-uk-stops-force-leicestershire", + "provider": "Police.uk - Force Stops (Leicestershire)", + "endpoint": "https://data.police.uk/api/stops-force?force=leicestershire", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "police-uk-stops-street-leicester", + "provider": "Police.uk - Street Stops Around Leicester", + "endpoint": "https://data.police.uk/api/stops-street?lat=52.629729&lng=-1.131592", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "west-yorkshire-police-coroner-appeals-rss", + "provider": "West Yorkshire Police - Coroner Appeals Feed", + "endpoint": "https://www.westyorkshire.police.uk/news/coroner-appeals/feed", + "finalUrl": "https://www.westyorkshire.police.uk/news/coroner-appeals/feed", + "status": null, + "message": "Circuit open for domain www.westyorkshire.police.uk until 2026-04-11T23:49:26.933Z", + "errorCode": "NETWORK_CIRCUIT_OPEN", + "category": "network-failure" + }, + { + "id": "chathamhouse-intl-security-feed", + "provider": "Chatham House a International Security Programme (RSS)", + "endpoint": "https://www.chathamhouse.org/path/83/feed.xml", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "chathamhouse-whatsnew", + "provider": "Chatham House a What's New (RSS)", + "endpoint": "https://www.chathamhouse.org/path/whatsnew.xml", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "bbc-news-england-legacy", + "provider": "BBC News a England (Legacy RSS)", + "endpoint": "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/england/rss.xml", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "mossos-news", + "provider": "Mossos d'Esquadra - News", + "endpoint": "https://mossos.gencat.cat/ca/actualitat/", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "netherlands-police-news", + "provider": "Dutch National Police - News", + "endpoint": "https://www.politie.nl/nieuws/", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "portugal-pj-news", + "provider": "Policia Judiciaria Portugal - News", + "endpoint": "https://www.policiajudiciaria.pt/?p=noticias", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "met-police-latest-news", + "provider": "Metropolitan Police - Latest News", + "endpoint": "https://news.met.police.uk/latest_news", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "met-police-news", + "provider": "Metropolitan Police Service a News", + "endpoint": "https://news.met.police.uk/news", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "avon-and-somerset-police-news-html", + "provider": "Avon and Somerset Police - News", + "endpoint": "https://www.avonandsomerset.police.uk/news/", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "avon-somerset-police-news", + "provider": "Avon & Somerset Police a News", + "endpoint": "https://www.avonandsomerset.police.uk/newsroom/", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" + }, + { + "id": "psni-latest-news", + "provider": "Police Service of Northern Ireland - Latest News", + "endpoint": "https://www.psni.police.uk/latest-news", + "finalUrl": "", + "status": null, + "message": "fetch failed", + "errorCode": "FETCH_NETWORK_FAILURE", + "category": "network-failure" } ], "geoLookupSnapshot": [ @@ -7958,7 +8198,7 @@ "lng": 133.7751 } ], - "buildWarning": "Deferred 273 low-yield source(s) on health cooldown.", + "buildWarning": "Deferred 276 low-yield source(s) on health cooldown. | Build produced no fresh alerts; preserved previous alert set. | Guardrails breached: failure-rate-exceeded, successful-source-floor-breached (runtime=363371ms, failedRate=1.000, successfulSources=0)", "runMetrics": { "schedulerMode": "candidate", "htmlBudget": 32, @@ -7971,66 +8211,45 @@ "www.avonandsomerset.police.uk": 2, "www.psni.police.uk": 1, "www.westyorkshirepolice.co.uk": 1, - "www.bka.de": 1, - "www.metoffice.gov.uk": 1, - "www.protectuk.police.uk": 1, - "www.gov.uk": 3, - "ctc.westpoint.edu": 1, - "www.sakerhetspolisen.se": 1, - "www.osce.org": 1, - "news.hackney.gov.uk": 1, - "www.lnwh.nhs.uk": 1, - "www.newham.gov.uk": 1, - "www.rbht.nhs.uk": 1, - "hmicfrs.justiceinspectorates.gov.uk": 1, - "committees.parliament.uk": 1, - "act.campaign.gov.uk": 1, - "www.mycommunityalert.co.uk": 1, - "www.nsa.gov": 1, - "www.eppo.europa.eu": 1, - "fra.europa.eu": 1, - "home-affairs.ec.europa.eu": 1, - "www.eurojust.europa.eu": 1 + "www.bka.de": 1 }, "coverage": { "eligible": 460, - "scheduled": 187, - "initialScheduled": 93, - "continuationAttempted": 94, - "checked": 186, - "eligibleCheckedRate": 0.404, - "scheduledCheckedRate": 0.995 + "scheduled": 184, + "initialScheduled": 28, + "continuationAttempted": 156, + "checked": 0, + "eligibleCheckedRate": 0, + "scheduledCheckedRate": 0 }, "freshnessSlaByTier": { "low": { "count": 59, - "avgMinutes": 6346, - "p95Minutes": 9708 + "avgMinutes": 6382, + "p95Minutes": 9744 }, "high": { "count": 17, - "avgMinutes": 4262, - "p95Minutes": 8121 + "avgMinutes": 4297, + "p95Minutes": 8156 }, "medium": { "count": 15, - "avgMinutes": 1781, - "p95Minutes": 7783 + "avgMinutes": 1817, + "p95Minutes": 7818 } }, "failureReasons": { - "success": 23, - "unchanged": 4, - "blocked-or-anti-bot": 2 + "timeout-or-aborted": 368 }, "sourceRunStats": { "totalConfiguredSources": 462, - "sourcesCheckedThisRun": 187, - "sourcesUpdatedThisRun": 23, - "sourcesFailedThisRun": 1, - "sourcesUnchangedThisRun": 4 + "sourcesCheckedThisRun": 184, + "sourcesUpdatedThisRun": 0, + "sourcesFailedThisRun": 184, + "sourcesUnchangedThisRun": 0 }, - "runDurationMs": 510254, + "runDurationMs": 363371, "playwrightFallback": { "attempts": 0, "successes": 0, @@ -8042,16 +8261,19 @@ "maxFailedSourceRate": 0.65, "minSuccessfulSources": 8, "targetSuccessfulSourcesPerRun": 30, - "failedSourceRate": 0.005, - "successfulSources": 24, - "violations": [] + "failedSourceRate": 1, + "successfulSources": 0, + "violations": [ + "failure-rate-exceeded", + "successful-source-floor-breached" + ] } }, "health": { "expectedRefreshMinutes": 15, "staleAfterMinutes": 25, - "lastAttemptedRefreshTime": "2026-04-11T23:10:14.423Z", - "usedFallback": false, + "lastAttemptedRefreshTime": "2026-04-11T23:45:27.477Z", + "usedFallback": 120, "lastSuccessfulRefreshTime": "2026-04-11T23:10:14.423Z", "lastSuccessfulRunId": "24293550037", "lastSuccessfulRunNumber": "306", @@ -8059,9 +8281,9 @@ "lastSuccessfulHeadSha": "5f25946e5c48f964209cb7128987d2d77011aabf", "lastSuccessfulEvent": "schedule", "lastSuccessfulSourceCount": 186, - "sourceErrorCount": 1, + "sourceErrorCount": 184, "hasWarnings": true, - "autoDeferredSourceCount": 273, + "autoDeferredSourceCount": 276, "autoDeferredSources": [ { "id": "frontex-news-releases", @@ -8218,76 +8440,77 @@ "operationalDeferredSources": [], "sourceRunStats": { "totalConfiguredSources": 462, - "sourcesCheckedThisRun": 187, - "sourcesUpdatedThisRun": 23, - "sourcesFailedThisRun": 1, - "sourcesUnchangedThisRun": 4 + "sourcesCheckedThisRun": 184, + "sourcesUpdatedThisRun": 0, + "sourcesFailedThisRun": 184, + "sourcesUnchangedThisRun": 0 }, "extraMetrics": { "schedulerMode": "candidate", "coverage": { "eligible": 460, - "scheduled": 187, - "initialScheduled": 93, - "continuationAttempted": 94, - "checked": 186, - "eligibleCheckedRate": 0.404, - "scheduledCheckedRate": 0.995 + "scheduled": 184, + "initialScheduled": 28, + "continuationAttempted": 156, + "checked": 0, + "eligibleCheckedRate": 0, + "scheduledCheckedRate": 0 }, "freshnessSlaByTier": { "low": { "count": 59, - "avgMinutes": 6346, - "p95Minutes": 9708 + "avgMinutes": 6382, + "p95Minutes": 9744 }, "high": { "count": 17, - "avgMinutes": 4262, - "p95Minutes": 8121 + "avgMinutes": 4297, + "p95Minutes": 8156 }, "medium": { "count": 15, - "avgMinutes": 1781, - "p95Minutes": 7783 + "avgMinutes": 1817, + "p95Minutes": 7818 } }, "failureReasons": { - "success": 23, - "unchanged": 4, - "blocked-or-anti-bot": 2 + "timeout-or-aborted": 368 }, "sourceRunStats": { "totalConfiguredSources": 462, - "sourcesCheckedThisRun": 187, - "sourcesUpdatedThisRun": 23, - "sourcesFailedThisRun": 1, - "sourcesUnchangedThisRun": 4 + "sourcesCheckedThisRun": 184, + "sourcesUpdatedThisRun": 0, + "sourcesFailedThisRun": 184, + "sourcesUnchangedThisRun": 0 }, "playwrightFallback": { "attempts": 0, "successes": 0 }, - "guardrailViolations": [] + "guardrailViolations": [ + "failure-rate-exceeded", + "successful-source-floor-breached" + ] }, "sourceHealth": { "euaa-news": { "provider": "EUAA (EU Agency for Asylum) a News", "lane": "border", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 91, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 37, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-10T13:24:31.138Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8298,20 +8521,20 @@ "provider": "eu-LISA - News and Events", "lane": "border", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 96, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 96, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8341,26 +8564,26 @@ "quarantined": true, "quarantinedAt": "2026-04-11T19:36:50.305Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "austria-interior-ministry-news": { "provider": "Austrian Interior Ministry - News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8371,20 +8594,20 @@ "provider": "Austrian Interior Ministry - RSS Index", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8414,7 +8637,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "belgium-crisis-centre-news": { "provider": "Belgian National Crisis Centre - News", @@ -8439,7 +8662,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "denmark-pet-news": { "provider": "Danish Security and Intelligence Service - News", @@ -8464,7 +8687,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T22:50:23.222Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ecfr-feeds-index": { "provider": "ECFR - Feeds", @@ -8488,7 +8711,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "enisa-news": { "provider": "ENISA (EU Cybersecurity Agency) a News", @@ -8512,7 +8735,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "enisa-rss-transition-page": { "provider": "ENISA - RSS Feeds Transition Notice", @@ -8536,7 +8759,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "euiss-home": { "provider": "EU Institute for Security Studies", @@ -8561,7 +8784,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "euractiv-security-rss": { "provider": "Euractiv a Security & Defence (RSS)", @@ -8586,26 +8809,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eurojust-press-news-html": { "provider": "Eurojust - Press Releases and News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 1, "emptyRuns": 91, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 72, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-08T05:22:00.484Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8616,20 +8839,20 @@ "provider": "Eurojust a Press Releases (RSS)", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 2, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 109, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8659,26 +8882,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "europol-news-rss": { "provider": "Europol a Newsroom (RSS)", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 15, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -8708,7 +8931,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "finland-supo-news": { "provider": "Finnish Security Intelligence Service - News", @@ -8733,7 +8956,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T19:13:04.758Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "german-bfv-news": { "provider": "German BfV - News", @@ -8758,7 +8981,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T15:02:06.946Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "german-interior-ministry-press": { "provider": "German Federal Ministry of the Interior - Press", @@ -8783,7 +9006,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "icct-home": { "provider": "ICCT - Home", @@ -8808,7 +9031,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nctv-english-rss": { "provider": "NCTV Netherlands - English RSS", @@ -8833,7 +9056,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T11:05:48.972Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "paris-prefecture-police-rss-page": { "provider": "Paris Prefecture of Police - RSS", @@ -8858,7 +9081,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "spain-interior-ministry-news": { "provider": "Spanish Ministry of the Interior - Press", @@ -8883,7 +9106,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "statewatch-news": { "provider": "Statewatch - News", @@ -8908,7 +9131,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "belgian-federal-police-news": { "provider": "Belgian Federal Police - News", @@ -8933,7 +9156,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "czech-police-news": { "provider": "Police of the Czech Republic - News", @@ -8958,26 +9181,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T16:01:40.268Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dutch-police-rss-index": { "provider": "Politie.nl - RSS", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9007,7 +9230,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "finland-police-news": { "provider": "Finnish Police - News", @@ -9032,7 +9255,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "german-bka-press": { "provider": "German BKA - Press Releases", @@ -9057,26 +9280,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T16:01:40.268Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "german-bka-press-releases-de": { "provider": "BKA Germany - Press Releases", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 10, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 15, + "failedRuns": 11, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T11:53:28.993Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9106,26 +9329,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T16:01:40.268Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "mossos-news": { "provider": "Mossos d'Esquadra - News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9155,7 +9378,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "policia-nacional-news": { "provider": "Policia Nacional - Press", @@ -9180,7 +9403,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T19:21:50.287Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "romanian-police-news": { "provider": "Romanian Police - News", @@ -9205,26 +9428,26 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "curia-press-rss-en": { "provider": "Court of Justice of the European Union - RSS (EN/FR)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 5, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 46, + "failedRuns": 6, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T22:52:22.492Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9235,20 +9458,20 @@ "provider": "European Public Prosecutor's Office - News and Media", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 40, "emptyRuns": 54, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 54, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-09T11:09:45.168Z", - "lastFailureAt": "2026-04-08T05:22:00.484Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9259,20 +9482,20 @@ "provider": "Publications Office of the European Union (CELLAR) a RSS/Atom Feeds", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 66, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-08T15:30:48.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9283,20 +9506,20 @@ "provider": "European Commission - Counter Terrorism Measures 2026", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 1, "emptyRuns": 90, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 57, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T02:47:18.465Z", - "lastFailureAt": "2026-04-09T07:35:13.094Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9307,20 +9530,20 @@ "provider": "European Commission - Home Affairs", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 24, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T04:27:26.776Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9350,7 +9573,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eu-council-fight-against-terrorism": { "provider": "Council of the EU - Fight Against Terrorism", @@ -9375,26 +9598,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eu-council-jha-meetings": { "provider": "Council of the European Union a Justice & Home Affairs Meetings (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 13, "emptyRuns": 92, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T07:49:39.939Z", - "lastFailureAt": "2026-04-06T09:17:50.585Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9405,20 +9628,20 @@ "provider": "Council of the EU - Justice and Home Affairs Register RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9429,20 +9652,20 @@ "provider": "Council of the European Union a Press Releases (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 102, - "failedRuns": 4, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 90, + "failedRuns": 5, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T12:11:54.469Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9453,20 +9676,20 @@ "provider": "Council of the EU - Press Releases", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 90, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 89, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T13:27:14.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9496,7 +9719,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eu-ct-coordinator": { "provider": "EU Counter-Terrorism Coordinator a Council of the EU", @@ -9521,26 +9744,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eu-ejustice-news-rss": { "provider": "European e-Justice - News RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 102, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 102, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9551,20 +9774,20 @@ "provider": "European Public Prosecutor's Office a Press Releases", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T16:42:53.076Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9575,20 +9798,20 @@ "provider": "EU Agency for Fundamental Rights (FRA) a RSS", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 90, - "failedRuns": 4, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 20, + "failedRuns": 5, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T08:34:21.892Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9599,20 +9822,20 @@ "provider": "European Commission a Home Affairs News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 72, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-08T05:22:00.484Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9623,20 +9846,20 @@ "provider": "OLAF (EU Anti-Fraud Office) a News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 91, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 72, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T15:36:10.273Z", - "lastFailureAt": "2026-04-08T05:22:00.484Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9647,20 +9870,20 @@ "provider": "European Commission a Security Union Strategy", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 1, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T02:47:18.465Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9690,7 +9913,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eucrim-judicial-counter-terrorism-register": { "provider": "eucrim - Judicial Counter Terrorism Register", @@ -9715,26 +9938,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eurojust-publications": { "provider": "Eurojust a Publications (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 49, "emptyRuns": 56, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-09T19:21:50.287Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9745,20 +9968,20 @@ "provider": "Eurojust - RSS Feeds", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T07:49:39.939Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9769,20 +9992,20 @@ "provider": "European Parliament a LIBE Committee (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 90, "emptyRuns": 16, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-08T12:09:13.262Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9793,20 +10016,20 @@ "provider": "European Parliament a SEDE Committee (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 106, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 106, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9817,20 +10040,20 @@ "provider": "European Parliament a Press Releases (Committees) (RSS)", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 103, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 103, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -9860,7 +10083,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "fra-rss": { "provider": "EU Agency for Fundamental Rights - RSS", @@ -9885,7 +10108,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "europol-eu-iru": { "provider": "Europol a EU Internet Referral Unit (EU IRU)", @@ -9910,7 +10133,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "isd-global-publications": { "provider": "ISD - Publications", @@ -9935,7 +10158,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ncsc-nl-rss": { "provider": "NCSC Netherlands - RSS", @@ -9960,7 +10183,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "eu-council-terrorism-sanctions": { "provider": "Council of the EU - Sanctions Against Terrorism", @@ -9985,7 +10208,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "unhcr-europe-news": { "provider": "UNHCR Europe a News", @@ -10009,7 +10232,7 @@ "quarantined": true, "quarantinedAt": "2026-04-05T22:37:03.546Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "clingendael-publications": { "provider": "Clingendael Institute a Publications", @@ -10034,7 +10257,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dw-europe-rss": { "provider": "Deutsche Welle a Europe (RSS)", @@ -10059,7 +10282,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ecfr-publications": { "provider": "European Council on Foreign Relations (ECFR) a Publications", @@ -10084,26 +10307,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "euronews-europe": { "provider": "Euronews a Europe", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 2, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 46, "emptyRuns": 19, - "failedRuns": 4, - "consecutiveFailures": 0, + "failedRuns": 5, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": "2026-04-05T14:37:36.069Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-10T13:24:31.138Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10133,7 +10356,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "france24-europe-rss": { "provider": "France 24 a Europe (RSS)", @@ -10158,7 +10381,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "french-interior-ministry-news": { "provider": "French Ministry of the Interior - News", @@ -10182,7 +10405,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T07:49:39.939Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "icct-perspectives-on-terrorism": { "provider": "Perspectives on Terrorism (ICCT) a Journal", @@ -10207,7 +10430,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "icct-publications": { "provider": "International Centre for Counter-Terrorism (ICCT) - Publications", @@ -10231,7 +10454,8 @@ "autoSkipReason": "empty-cooldown", "quarantined": false, "quarantinedAt": null, - "quarantineReason": null + "quarantineReason": null, + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "netherlands-nctv-news": { "provider": "Dutch NCTV - News", @@ -10256,26 +10480,26 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "norway-pst-news": { "provider": "Norwegian Police Security Service - News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 45, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T23:47:36.169Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10304,7 +10528,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rte-ireland-news-rss": { "provider": "RTÉ News - Ireland (RSS)", @@ -10329,7 +10553,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T14:01:19.759Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "switzerland-fedpol-news": { "provider": "Swiss fedpol - News", @@ -10354,7 +10578,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T11:05:48.972Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "telegraph-world-news": { "provider": "The Telegraph a World News", @@ -10379,7 +10603,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "vox-pol-publications": { "provider": "VOX-Pol Network a Publications", @@ -10404,7 +10628,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "french-gendarmerie-news": { "provider": "Gendarmerie Nationale - News", @@ -10429,7 +10653,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "french-police-nationale-news": { "provider": "Police Nationale - News", @@ -10454,7 +10678,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ireland-gardai-press": { "provider": "An Garda Siochana - Press Releases", @@ -10479,26 +10703,26 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "netherlands-police-news": { "provider": "Dutch National Police - News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10528,26 +10752,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "portugal-pj-news": { "provider": "Policia Judiciaria Portugal - News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 111, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 20, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T08:34:21.892Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10577,7 +10801,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "coe-counter-terrorism": { "provider": "Council of Europe a Counter-Terrorism", @@ -10602,26 +10826,26 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "echr-key-judgments-rss": { "provider": "European Court of Human Rights - Key Judgments RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10632,20 +10856,20 @@ "provider": "European Court of Human Rights - Press Releases RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 103, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T02:43:47.675Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10656,20 +10880,20 @@ "provider": "French Ministry of Justice - News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10698,26 +10922,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T09:17:50.585Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bfv-de-english": { "provider": "BfV press page (Federal Office for the Protection of the Constitution)", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 9, "emptyRuns": 92, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-05T16:42:53.076Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10728,20 +10952,20 @@ "provider": "DSN Austria news", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 100, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 100, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-05T19:38:38.443Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10771,7 +10995,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nctv-nl-english": { "provider": "NCTV (Netherlands) a English News", @@ -10796,7 +11020,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T15:02:06.946Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nctv-nl-english-news": { "provider": "NCTV Netherlands latest news (English)", @@ -10820,26 +11044,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T20:40:59.773Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ocam-be-english": { "provider": "CUTA (Belgium) threat analysis", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 9, "emptyRuns": 88, - "failedRuns": 7, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 4, + "failedRuns": 8, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-11T20:04:36.062Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10869,7 +11093,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T15:02:06.946Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "pst-no-english": { "provider": "PST (Norway) English reporting page", @@ -10894,7 +11118,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ran-network": { "provider": "Radicalisation Awareness Network (RAN) a Publications", @@ -10919,26 +11143,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "sapo-se-english": { "provider": "Swedish Security Service English news", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 9, "emptyRuns": 92, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-05T16:42:53.076Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -10967,7 +11191,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T07:49:39.939Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "iom-news": { "provider": "IOM (International Organization for Migration) a News", @@ -10992,7 +11216,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "acled-updates": { "provider": "ACLED a Updates and Analysis", @@ -11017,7 +11241,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "aljazeera-news-rss": { "provider": "Al Jazeera English a Top Stories (RSS)", @@ -11042,7 +11266,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ap-top-news": { "provider": "Associated Press a Top News", @@ -11067,7 +11291,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bbc-news-world": { "provider": "BBC News a World", @@ -11092,7 +11316,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bbc-news-world-legacy": { "provider": "BBC News a World (Legacy RSS)", @@ -11117,7 +11341,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bellingcat": { "provider": "Bellingcat a Investigations", @@ -11142,7 +11366,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chatham-house-rss": { "provider": "Chatham House a Research & Commentary (RSS)", @@ -11167,7 +11391,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chathamhouse-events": { "provider": "Chatham House a Events (RSS)", @@ -11192,26 +11416,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chathamhouse-intl-security-feed": { "provider": "Chatham House a International Security Programme (RSS)", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 30, "emptyRuns": 10, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-09T21:05:22.885Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -11241,26 +11465,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chathamhouse-whatsnew": { "provider": "Chatham House a What's New (RSS)", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 32, "emptyRuns": 10, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-09T19:21:50.287Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -11290,7 +11514,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T14:01:19.759Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "crisis-group": { "provider": "International Crisis Group a Research & Analysis", @@ -11315,7 +11539,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "crisis-group-europe": { "provider": "International Crisis Group a Europe (RSS)", @@ -11340,7 +11564,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "global-initiative-news": { "provider": "Global Initiative Against Transnational Organized Crime a News", @@ -11365,7 +11589,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "interpol-news-events": { "provider": "INTERPOL a News and Events", @@ -11390,7 +11614,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "just-security": { "provider": "Just Security a Law, Rights & National Security", @@ -11415,7 +11639,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "lawfare-blog": { "provider": "Lawfare a Blog (National Security Law & CT Policy)", @@ -11440,7 +11664,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "long-war-journal": { "provider": "Long War Journal a News Feed", @@ -11465,7 +11689,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nato-news-rss": { "provider": "NATO a News (RSS)", @@ -11490,7 +11714,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "occrp-news": { "provider": "OCCRP a Organized Crime and Corruption Reporting Project", @@ -11515,26 +11739,26 @@ "quarantined": true, "quarantinedAt": "2026-04-08T22:50:23.222Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "osce-press-releases": { "provider": "OSCE a Press Releases", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -11564,7 +11788,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "reuters-uk": { "provider": "Reuters a UK News", @@ -11589,7 +11813,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rferl-security-news-rss": { "provider": "Radio Free Europe/Radio Liberty a Security (RSS)", @@ -11614,7 +11838,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T11:05:48.972Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "soufan-center-intelbrief": { "provider": "The Soufan Center a IntelBrief", @@ -11639,7 +11863,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T12:07:40.986Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tech-against-terrorism-podcast": { "provider": "Tech Against Terrorism - Podcast", @@ -11664,7 +11888,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tony-blair-institute-news": { "provider": "Tony Blair Institute for Global Change a Publications", @@ -11689,7 +11913,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "unodc-news": { "provider": "UNODC (UN Office on Drugs and Crime) a Press Releases", @@ -11714,7 +11938,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "war-on-the-rocks": { "provider": "War on the Rocks a National Security & CT Analysis", @@ -11739,7 +11963,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gctf-news": { "provider": "Global Counterterrorism Forum (GCTF) a News", @@ -11764,26 +11988,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "unoct-news": { "provider": "UN Office of Counter-Terrorism (UNOCT) - News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 1, "emptyRuns": 90, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 52, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T07:17:25.383Z", - "lastFailureAt": "2026-04-09T13:52:48.843Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -11812,26 +12036,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T20:40:59.773Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gnet-artificial-intelligence-rss": { "provider": "Global Network on Extremism & Technology (GNET) a Artificial Intelligence (RSS)", "lane": "prevention", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 101, "emptyRuns": 0, - "failedRuns": 5, - "consecutiveFailures": 0, + "failedRuns": 6, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": "2026-04-06T12:11:54.469Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -11860,7 +12084,8 @@ "autoSkipReason": "failure-cooldown", "quarantined": false, "quarantinedAt": null, - "quarantineReason": null + "quarantineReason": null, + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gnet-youth-rss": { "provider": "Global Network on Extremism & Technology (GNET) a Youth (RSS)", @@ -11885,7 +12110,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tech-against-terrorism": { "provider": "Tech Against Terrorism a Blog", @@ -11910,7 +12135,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tech-against-terrorism-home": { "provider": "Tech Against Terrorism - Home", @@ -11935,7 +12160,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "fatf-news": { "provider": "Financial Action Task Force (FATF) a News", @@ -11960,7 +12185,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "interpol-notices": { "provider": "INTERPOL a Notices", @@ -11984,26 +12209,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "unsc-1267-press-releases": { "provider": "UN Security Council - ISIL/Da'esh & Al-Qaeda Sanctions Committee Press Releases", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 89, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 51, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T15:33:36.097Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12033,7 +12258,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "barking-dagenham-council-news": { "provider": "Barking and Dagenham Council a News", @@ -12058,7 +12283,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "barnet-council-news": { "provider": "Barnet Council a News", @@ -12083,7 +12308,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "barts-health-news": { "provider": "Barts Health NHS Trust a News", @@ -12108,7 +12333,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bbc-news-london-rss": { "provider": "BBC News - London RSS", @@ -12133,26 +12358,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bexley-council-news": { "provider": "Bexley Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12182,7 +12407,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bromley-council-news": { "provider": "Bromley Council a Newsroom", @@ -12207,26 +12432,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "camden-council-news": { "provider": "Camden Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 93, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12237,20 +12462,20 @@ "provider": "Chelsea and Westminster Hospital NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12280,7 +12505,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cnwl-news": { "provider": "Central and North West London NHS Foundation Trust a News", @@ -12304,26 +12529,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T07:49:39.939Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "croydon-council-news": { "provider": "Croydon Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12334,20 +12559,20 @@ "provider": "Ealing Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12376,7 +12601,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "enfield-council-news": { "provider": "Enfield Council a News and Events", @@ -12401,26 +12626,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gosh-news": { "provider": "Great Ormond Street Hospital a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12431,20 +12656,20 @@ "provider": "Guy's and St Thomas' NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12455,20 +12680,20 @@ "provider": "Hackney Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 18, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T10:04:35.060Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12498,7 +12723,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "haringey-council-news": { "provider": "Haringey Council a News", @@ -12523,7 +12748,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "harrow-council-news": { "provider": "Harrow Council a News", @@ -12548,26 +12773,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "havering-council-news": { "provider": "Havering Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12597,26 +12822,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hillingdon-council-news": { "provider": "Hillingdon Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12646,26 +12871,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hounslow-council-news": { "provider": "Hounslow Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12695,26 +12920,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "islington-council-news": { "provider": "Islington Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 96, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 96, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12744,26 +12969,26 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "kings-college-hospital-news": { "provider": "King's College Hospital NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12774,20 +12999,20 @@ "provider": "Kingston Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 39, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-10T11:05:48.972Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12798,20 +13023,20 @@ "provider": "Lambeth Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12841,26 +13066,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "lnwh-news": { "provider": "London North West University Healthcare NHS Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -12890,7 +13115,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-city-airport-media-centre": { "provider": "London City Airport a Media Centre", @@ -12915,7 +13140,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-councils-news": { "provider": "London Councils a News", @@ -12939,7 +13164,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-fire-brigade-news": { "provider": "London Fire Brigade a News", @@ -12964,7 +13189,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-gov-home": { "provider": "London.gov.uk", @@ -12989,7 +13214,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-gov-press-releases-html": { "provider": "London.gov.uk - Press Releases", @@ -13014,26 +13239,26 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-gov-rss-80603": { "provider": "Greater London Authority a RSS Feed 80603", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 51, "emptyRuns": 56, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-09T15:33:36.097Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13044,20 +13269,20 @@ "provider": "Greater London Authority a RSS Feed 80610", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13068,20 +13293,20 @@ "provider": "Greater London Authority a RSS Feed 80611", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13092,21 +13317,21 @@ "provider": "Greater London Authority a RSS Feed 80632", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, - "cooldownUntil": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", + "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, "quarantinedAt": null, @@ -13135,26 +13360,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T19:13:04.758Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "merton-council-news": { "provider": "Merton Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 39, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-10T11:05:48.972Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13165,20 +13390,20 @@ "provider": "Metropolitan Police - The Met Tag", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 4, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 93, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13189,20 +13414,20 @@ "provider": "Moorfields Eye Hospital NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 92, - "failedRuns": 2, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 3, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T07:49:39.939Z", - "lastFailureAt": "2026-04-05T19:38:38.443Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13213,20 +13438,20 @@ "provider": "North East London NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13237,20 +13462,20 @@ "provider": "Newham Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13279,26 +13504,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nhs-london-nel-news": { "provider": "NHS North East London a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 46, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T22:52:22.492Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13309,20 +13534,20 @@ "provider": "NHS North West London a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13352,7 +13577,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T11:05:48.972Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nhs-london-swl-news": { "provider": "NHS South West London a News", @@ -13377,7 +13602,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "north-middlesex-news": { "provider": "North Middlesex University Hospital a News", @@ -13402,26 +13627,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "oxleas-news": { "provider": "Oxleas NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13451,26 +13676,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "redbridge-council-news": { "provider": "Redbridge Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 4, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T02:43:47.675Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13481,20 +13706,20 @@ "provider": "Richmond Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 66, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-08T15:30:48.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13505,20 +13730,20 @@ "provider": "Royal Brompton and Harefield Hospitals a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 82, "emptyRuns": 15, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 15, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T11:53:28.993Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13548,7 +13773,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "royal-greenwich-news": { "provider": "Royal Borough of Greenwich a News", @@ -13573,7 +13798,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "slam-news": { "provider": "South London and Maudsley NHS Foundation Trust a News", @@ -13598,7 +13823,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "southwark-newsroom": { "provider": "Southwark Council a Newsroom", @@ -13623,26 +13848,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "st-georges-news": { "provider": "St George's University Hospitals NHS Foundation Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 94, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13653,20 +13878,20 @@ "provider": "Sutton Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 96, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 96, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13677,20 +13902,20 @@ "provider": "South West London and St George's Mental Health NHS Trust a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13719,7 +13944,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tfl-press-releases": { "provider": "Transport for London a Press Releases", @@ -13744,7 +13969,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tfl-press-releases-html": { "provider": "Transport for London - Press Releases", @@ -13768,7 +13993,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "tower-hamlets-council-news": { "provider": "Tower Hamlets Council a News", @@ -13793,26 +14018,26 @@ "quarantined": true, "quarantinedAt": "2026-04-10T11:05:48.972Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "uclh-news": { "provider": "University College London Hospitals a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 97, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13823,20 +14048,20 @@ "provider": "Waltham Forest Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13847,20 +14072,20 @@ "provider": "Wandsworth Council a News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 66, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-08T15:30:48.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -13890,7 +14115,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "whittington-health-news": { "provider": "Whittington Health a News", @@ -13915,7 +14140,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T19:21:50.287Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "city-of-london-police-news": { "provider": "City of London Police a News", @@ -13940,7 +14165,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "city-of-london-police-news-html": { "provider": "City of London Police - News", @@ -13965,7 +14190,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "city-of-london-police-newsroom": { "provider": "City of London Police - Newsroom", @@ -13990,7 +14215,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-london": { "provider": "Counter Terrorism Policing London", @@ -14015,26 +14240,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "met-police-latest-news": { "provider": "Metropolitan Police - Latest News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 114, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14045,20 +14270,20 @@ "provider": "Metropolitan Police Service a News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 114, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14088,7 +14313,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T15:02:06.946Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "mopac-html": { "provider": "Mayor's Office for Policing and Crime", @@ -14113,7 +14338,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "london-resilience": { "provider": "Resilience First - Latest Updates", @@ -14138,26 +14363,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gov-uk-fcdo-travel-advice": { "provider": "FCDO a Foreign Travel Advice Index", "lane": "border", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 97, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14168,20 +14393,20 @@ "provider": "Border Force (UK) a Announcements and Publications", "lane": "border", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 97, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14192,20 +14417,20 @@ "provider": "UK Visas and Immigration a Announcements and Publications", "lane": "border", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 97, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14216,20 +14441,20 @@ "provider": "BBC News a England (Legacy RSS)", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 4, "emptyRuns": 11, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-10T19:57:58.800Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14259,7 +14484,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bbc-news-uk": { "provider": "BBC News a UK", @@ -14284,7 +14509,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bbc-news-uk-politics-legacy": { "provider": "BBC News a UK Politics (Legacy RSS)", @@ -14309,7 +14534,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chatham-house-home": { "provider": "Chatham House", @@ -14334,7 +14559,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "chatham-house-security-defence": { "provider": "Chatham House - Security and Defence", @@ -14359,7 +14584,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "essex-police-news": { "provider": "Essex Police a News", @@ -14384,7 +14609,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gov-uk-defence-intelligence": { "provider": "UK Defence Intelligence a GOV.UK", @@ -14409,26 +14634,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gov-uk-terrorism-search": { "provider": "GOV.UK Search - Terrorism", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14458,7 +14683,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "henry-jackson-society-news": { "provider": "Henry Jackson Society a Publications", @@ -14483,7 +14708,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hope-not-hate-home": { "provider": "Hope not hate podcast", @@ -14507,7 +14732,7 @@ "quarantined": true, "quarantinedAt": "2026-04-05T16:42:53.076Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "institute-global-home": { "provider": "Institute for Global Change", @@ -14532,7 +14757,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "kent-police-news": { "provider": "Kent Police a News", @@ -14556,7 +14781,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T07:49:39.939Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "mi5-news": { "provider": "MI5 (Security Service) a News", @@ -14581,7 +14806,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "mi5-news-rss-direct": { "provider": "MI5 - News RSS", @@ -14606,7 +14831,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "national-crime-agency-news": { "provider": "National Crime Agency a News", @@ -14631,26 +14856,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "npcc-releases": { "provider": "National Police Chiefs' Council - Releases", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 94, "emptyRuns": 1, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T16:40:42.612Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14661,20 +14886,20 @@ "provider": "Police.uk - Street Crime Around Leicester", "lane": "context", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 106, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 106, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14685,20 +14910,20 @@ "provider": "Police.uk - Force Stops (Leicestershire)", "lane": "context", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 106, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 106, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14709,20 +14934,20 @@ "provider": "Police.uk - Street Stops Around Leicester", "lane": "context", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 106, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 106, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -14751,7 +14976,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "report-fraud-newsroom": { "provider": "Report Fraud - Newsroom", @@ -14775,7 +15000,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T07:49:39.939Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rusi-home": { "provider": "RUSI", @@ -14800,7 +15025,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rusi-publications": { "provider": "RUSI (Royal United Services Institute) a Publications", @@ -14825,7 +15050,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rusi-terrorism-conflict": { "provider": "RUSI - Terrorism and Conflict", @@ -14850,7 +15075,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "skwawkbox": { "provider": "Skwawkbox", @@ -14875,7 +15100,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "sky-news-uk-rss": { "provider": "Sky News UK a Top Stories (RSS)", @@ -14900,7 +15125,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "the-sun-all": { "provider": "The Sun", @@ -14925,7 +15150,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "the-sun-all-english": { "provider": "The Sun", @@ -14950,7 +15175,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "the-sun-homepage": { "provider": "The Sun", @@ -14975,7 +15200,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "the-sun-news-english": { "provider": "The Sun", @@ -15000,26 +15225,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-yorkshire-police-coroner-appeals-rss": { "provider": "West Yorkshire Police - Coroner Appeals Feed", "lane": "context", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T07:49:39.939Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.westyorkshire.police.uk until 2026-04-11T23:49:26.933Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -15049,26 +15274,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T12:07:40.986Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "avon-and-somerset-police-news-html": { "provider": "Avon and Somerset Police - News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -15079,20 +15304,20 @@ "provider": "Avon & Somerset Police a News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -15122,7 +15347,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "bedfordshire-police-news-search": { "provider": "Bedfordshire Police - News Search", @@ -15147,7 +15372,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "british-transport-police-news": { "provider": "British Transport Police a News", @@ -15172,7 +15397,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "btp-british-transport-police-news-html": { "provider": "British Transport Police - News", @@ -15197,7 +15422,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cambridgeshire-police-news-search": { "provider": "Cambridgeshire Police - News Search", @@ -15222,7 +15447,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cheshire-police-news": { "provider": "Cheshire Constabulary - News", @@ -15247,7 +15472,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cleveland-police-news": { "provider": "Cleveland Police - News", @@ -15272,7 +15497,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cps-news-centre": { "provider": "Crown Prosecution Service a News Centre", @@ -15297,7 +15522,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-north-west": { "provider": "Counter Terrorism Policing North West", @@ -15322,7 +15547,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-uk-latest-news": { "provider": "Counter Terrorism Policing UK a Latest News", @@ -15347,7 +15572,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-uk-rss-feed": { "provider": "Counter Terrorism Policing UK - RSS Feed", @@ -15372,7 +15597,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cumbria-police-news": { "provider": "Cumbria Police - News", @@ -15397,7 +15622,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "cumbria-police-newsroom": { "provider": "Cumbria Police - Newsroom", @@ -15422,7 +15647,7 @@ "quarantined": true, "quarantinedAt": "2026-04-11T15:27:18.437Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "derbyshire-police-news": { "provider": "Derbyshire Police - News", @@ -15447,7 +15672,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "devon-and-cornwall-police-newsroom": { "provider": "Devon and Cornwall Police - Newsroom", @@ -15472,7 +15697,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "devon-cornwall-police-news": { "provider": "Devon and Cornwall Police - News", @@ -15497,7 +15722,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dorset-police-news": { "provider": "Dorset Police - News", @@ -15522,7 +15747,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dorset-police-newsroom": { "provider": "Dorset Police - Newsroom", @@ -15547,7 +15772,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "durham-constabulary-news": { "provider": "Durham Constabulary a News", @@ -15572,7 +15797,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "durham-police-durham-news": { "provider": "Durham Police - Durham News", @@ -15597,7 +15822,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dyfed-powys-police-news": { "provider": "Dyfed-Powys Police - News", @@ -15622,7 +15847,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "essex-police-news-html": { "provider": "Essex Police - News", @@ -15647,7 +15872,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gloucestershire-police-news": { "provider": "Gloucestershire Police - News", @@ -15672,7 +15897,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gmp-news": { "provider": "Greater Manchester Police a News", @@ -15697,7 +15922,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "greater-manchester-police-news": { "provider": "Greater Manchester Police - News", @@ -15722,7 +15947,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gwent-police-news": { "provider": "Gwent Police - News", @@ -15747,7 +15972,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hampshire-police-news": { "provider": "Hampshire & Isle of Wight Constabulary a News", @@ -15772,7 +15997,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hertfordshire-police-news": { "provider": "Hertfordshire Constabulary a News", @@ -15797,7 +16022,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "humberside-police-news-search": { "provider": "Humberside Police - News Search", @@ -15822,7 +16047,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "kent-police-news-html": { "provider": "Kent Police - News", @@ -15847,7 +16072,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "lancashire-constabulary-news": { "provider": "Lancashire Constabulary a News", @@ -15872,7 +16097,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "leicestershire-police-news": { "provider": "Leicestershire Police - News", @@ -15897,7 +16122,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "lincolnshire-police-news": { "provider": "Lincolnshire Police - News", @@ -15922,7 +16147,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "merseyside-police-news": { "provider": "Merseyside Police a News", @@ -15947,7 +16172,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "merseyside-police-news-html": { "provider": "Merseyside Police - News", @@ -15972,7 +16197,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "norfolk-constabulary-news": { "provider": "Norfolk Constabulary - News", @@ -15997,7 +16222,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "north-wales-police-news": { "provider": "North Wales Police - News", @@ -16022,7 +16247,7 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "north-yorkshire-police-news-html": { "provider": "North Yorkshire Police - News", @@ -16047,7 +16272,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "northamptonshire-police-news-html": { "provider": "Northamptonshire Police - News", @@ -16072,7 +16297,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "northumbria-police-news": { "provider": "Northumbria Police a News", @@ -16097,7 +16322,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "northumbria-police-northumbria-news": { "provider": "Northumbria Police - Northumbria News", @@ -16122,7 +16347,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nottinghamshire-police-news": { "provider": "Nottinghamshire Police a News", @@ -16147,7 +16372,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nottinghamshire-police-nottinghamshire-news": { "provider": "Nottinghamshire Police - Nottinghamshire News", @@ -16172,7 +16397,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "police-scotland-news": { "provider": "Police Scotland news", @@ -16196,26 +16421,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T15:36:10.273Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "psni-latest-news": { "provider": "Police Service of Northern Ireland - Latest News", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16245,7 +16470,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "south-wales-police-news": { "provider": "South Wales Police - News", @@ -16270,7 +16495,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "south-yorkshire-police-news": { "provider": "South Yorkshire Police a News", @@ -16295,7 +16520,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "staffordshire-police-news": { "provider": "Staffordshire Police a News", @@ -16320,7 +16545,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "staffordshire-police-staffordshire-news": { "provider": "Staffordshire Police - Staffordshire News", @@ -16345,7 +16570,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "suffolk-constabulary-news": { "provider": "Suffolk Constabulary - News", @@ -16370,7 +16595,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "surrey-police-news": { "provider": "Surrey Police a News", @@ -16395,7 +16620,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "sussex-police-news": { "provider": "Sussex Police a News", @@ -16420,7 +16645,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "thames-valley-police-news": { "provider": "Thames Valley Police a News", @@ -16445,7 +16670,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "thames-valley-police-news-html": { "provider": "Thames Valley Police - Thames Valley News", @@ -16470,7 +16695,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "warwickshire-police-news": { "provider": "Warwickshire Police - News", @@ -16495,7 +16720,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-mercia-police-news-html": { "provider": "West Mercia Police - News", @@ -16520,7 +16745,7 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-midlands-police-news": { "provider": "West Midlands Police a News", @@ -16545,26 +16770,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-yorkshire-police-all-rss": { "provider": "West Yorkshire Police - All Feed", "lane": "incidents", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16575,20 +16800,20 @@ "provider": "West Yorkshire Police - Appeals Feed", "lane": "incidents", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16618,7 +16843,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-yorkshire-police-news": { "provider": "West Yorkshire Police a News", @@ -16643,26 +16868,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "west-yorkshire-police-news-appeals": { "provider": "West Yorkshire Police - News Appeals", "lane": "incidents", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 114, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 114, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16673,20 +16898,20 @@ "provider": "West Yorkshire Police - News Feed", "lane": "incidents", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16697,20 +16922,20 @@ "provider": "West Yorkshire Police - Releases Feed", "lane": "incidents", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 109, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 109, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16740,26 +16965,26 @@ "quarantined": true, "quarantinedAt": "2026-04-07T11:11:10.131Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "attorney-generals-office-html": { "provider": "Attorney General's Office", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16770,20 +16995,20 @@ "provider": "Cabinet Office", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16813,26 +17038,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "crown-office-news": { "provider": "Crown Office and Procurator Fiscal Service - News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16843,20 +17068,20 @@ "provider": "European Court of Human Rights - UK Grand Chamber RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 105, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 105, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16867,20 +17092,20 @@ "provider": "Commission for Countering Extremism - Blog", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16891,20 +17116,20 @@ "provider": "Foreign, Commonwealth & Development Office", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 93, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16915,20 +17140,20 @@ "provider": "Scottish Government - Access to Justice Latest", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16939,20 +17164,20 @@ "provider": "Cabinet Office a GOV.UK Atom Feed", "lane": "oversight", "kind": "atom", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 106, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 106, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16963,20 +17188,20 @@ "provider": "HMCTS a Courts and Tribunals Announcements", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -16987,20 +17212,20 @@ "provider": "HM Inspectorate of Constabulary a GOV.UK", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 84, - "failedRuns": 5, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 45, + "failedRuns": 6, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T23:47:36.169Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17011,20 +17236,20 @@ "provider": "UK Home Office a Atom Feed", "lane": "oversight", "kind": "atom", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 21, "emptyRuns": 84, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 84, - "consecutiveBlockedFailures": 0, - "consecutiveDeadUrlFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, + "consecutiveBlockedFailures": 0, + "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T19:13:04.758Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17035,20 +17260,20 @@ "provider": "Investigatory Powers Commissioner's Office a GOV.UK", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17059,20 +17284,20 @@ "provider": "Ministry of Defence a GOV.UK Atom Feed", "lane": "oversight", "kind": "atom", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 19, "emptyRuns": 84, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 84, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T19:13:04.758Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17083,20 +17308,20 @@ "provider": "Ministry of Justice a GOV.UK Atom Feed", "lane": "oversight", "kind": "atom", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 103, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 103, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17107,20 +17332,20 @@ "provider": "GOV.UK - News and Communications Atom", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 19, "emptyRuns": 87, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 84, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T19:13:04.758Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17150,26 +17375,26 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "hmiprisons-news": { "provider": "HM Inspectorate of Prisons - News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17180,20 +17405,20 @@ "provider": "HM Inspectorate of Probation - News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 1, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T05:21:55.560Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17204,20 +17429,20 @@ "provider": "Home Office Media Blog", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17228,20 +17453,20 @@ "provider": "Independent Reviewer of Terrorism Legislation a Reports", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 3, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T23:39:53.431Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17252,20 +17477,20 @@ "provider": "Independent Reviewer of Terrorism Legislation", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T20:40:59.773Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17295,26 +17520,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T13:27:14.171Z", "quarantineReason": "Repeated dead-or-moved-url failures", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "judiciary-rss-feeds-page": { "provider": "Judiciary UK - RSS Feeds", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.judiciary.uk until 2026-04-11T23:50:15.275Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17325,20 +17550,20 @@ "provider": "Judiciary UK - Announcements Feed", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 7, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 89, + "failedRuns": 8, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T13:27:14.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17349,20 +17574,20 @@ "provider": "Judiciary UK - Judgments Feed", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 97, - "failedRuns": 8, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 89, + "failedRuns": 9, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T13:27:14.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17373,20 +17598,20 @@ "provider": "Judiciary of England and Wales a News", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 8, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 90, + "failedRuns": 9, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T12:11:54.469Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17397,20 +17622,20 @@ "provider": "Judiciary UK - Publications Feed", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 90, - "failedRuns": 6, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 88, + "failedRuns": 7, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T09:17:50.585Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17440,7 +17665,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "lords-library-notes-rss": { "provider": "Lords Library Notes RSS", @@ -17465,26 +17690,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ministry-of-defence-html": { "provider": "Ministry of Defence", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 4, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 92, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17495,20 +17720,20 @@ "provider": "Office for National Statistics", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17519,20 +17744,20 @@ "provider": "Parliament - All Bills RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17543,20 +17768,20 @@ "provider": "Parliament - Private Bills RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 6, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 90, + "failedRuns": 7, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T12:11:54.469Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17567,20 +17792,20 @@ "provider": "Parliament - Public Bills RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 11, "emptyRuns": 90, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 89, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-06T13:27:14.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17610,26 +17835,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "police-uk-crime-categories-2024-01": { "provider": "Police.uk - Crime Categories (2024-01)", "lane": "oversight", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 105, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 105, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17640,20 +17865,20 @@ "provider": "Police.uk - Street Crime Dataset Dates", "lane": "oversight", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain data.police.uk until 2026-04-11T23:50:20.916Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17683,26 +17908,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "police-uk-outcomes-for-crime-e11dade0": { "provider": "Police.uk - Outcomes For Crime e11dade0", "lane": "oversight", "kind": "json", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 13, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain data.police.uk until 2026-04-11T23:50:20.916Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17713,20 +17938,20 @@ "provider": "Scottish Courts - Fatal Accident Inquiry Determinations RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17737,20 +17962,20 @@ "provider": "Scottish Courts - Fatal Accident Inquiry Hearings RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 102, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 102, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17761,20 +17986,20 @@ "provider": "Scottish Courts - High Court of Justiciary Judgments RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17785,20 +18010,20 @@ "provider": "Scottish Courts - High Court of Justiciary Practice Notes RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17809,20 +18034,20 @@ "provider": "Scottish Courts - Judgments RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 102, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 102, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17833,20 +18058,20 @@ "provider": "Scottish Courts - News Articles RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 102, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 102, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17857,20 +18082,20 @@ "provider": "Scottish Courts - Publications RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 105, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 105, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17881,20 +18106,20 @@ "provider": "Scottish Courts and Tribunals - RSS Feeds", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 91, - "failedRuns": 1, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 66, + "failedRuns": 2, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-08T15:30:48.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17905,20 +18130,20 @@ "provider": "Scottish Courts - Sheriff Court Criminal Practice Notes RSS", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 105, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 105, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain api.pa.web.scotcourts.gov.uk until 2026-04-11T23:50:27.863Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17948,26 +18173,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "serious-fraud-office-news": { "provider": "Serious Fraud Office a News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -17978,20 +18203,20 @@ "provider": "UK Home Office a Announcements and Publications", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 42, "emptyRuns": 51, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 51, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-09T15:33:36.097Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18002,20 +18227,20 @@ "provider": "Independent Office for Police Conduct a News", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 2, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T15:36:10.273Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18026,20 +18251,20 @@ "provider": "National Cyber Security Centre (UK) a News", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 4, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 105, "emptyRuns": 1, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-10T11:05:48.972Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18050,20 +18275,20 @@ "provider": "National Cyber Security Centre (UK) a Threat Reports", "lane": "oversight", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 20, "emptyRuns": 86, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 35, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-10T16:07:00.487Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18093,26 +18318,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "uk-parliament-defence-committee": { "provider": "UK Parliament a Defence Select Committee", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 89, - "failedRuns": 4, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 79, + "failedRuns": 5, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-07T17:10:44.774Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18142,26 +18367,26 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "uk-parliament-home-affairs-committee": { "provider": "UK Parliament a Home Affairs Committee (News)", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 82, - "failedRuns": 5, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 49, + "failedRuns": 6, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-09T19:21:50.287Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18191,7 +18416,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "uk-parliament-justice-committee": { "provider": "UK Parliament a Justice Select Committee", @@ -18215,26 +18440,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T11:16:46.434Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "act-campaign": { "provider": "ACT Awareness Campaign", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 10, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18264,7 +18489,7 @@ "quarantined": true, "quarantinedAt": "2026-04-11T15:27:18.437Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-prevent-programme": { "provider": "Counter Terrorism Policing - Prevent", @@ -18288,7 +18513,7 @@ "quarantined": true, "quarantinedAt": "2026-04-05T19:38:38.443Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ct-policing-what-you-can-do": { "provider": "Counter Terrorism Policing - What You Can Do", @@ -18312,26 +18537,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T19:38:38.443Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dc-police-community-messaging": { "provider": "Dorset and Cornwall Police - Community Messaging", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 104, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 104, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18342,20 +18567,20 @@ "provider": "Devon and Cornwall Alerts", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 101, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 101, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18366,20 +18591,20 @@ "provider": "Global Network on Extremism & Technology (GNET) a Main Feed", "lane": "prevention", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 97, "emptyRuns": 0, - "failedRuns": 8, - "consecutiveFailures": 0, + "failedRuns": 9, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": "2026-04-06T13:27:14.171Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18390,20 +18615,20 @@ "provider": "GOV.UK a CONTEST Counter-Terrorism Strategy", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 12, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18414,20 +18639,20 @@ "provider": "Counter Extremism Commissioner a GOV.UK", "lane": "prevention", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 4, "emptyRuns": 92, - "failedRuns": 4, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 5, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-05T19:38:38.443Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18438,20 +18663,20 @@ "provider": "UK Home Office - Prevent duty guidance", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 9, "emptyRuns": 92, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": "2026-04-05T13:02:51.966Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18481,7 +18706,7 @@ "quarantined": true, "quarantinedAt": "2026-04-08T23:49:08.059Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gov-uk-terrorism-national-emergency": { "provider": "GOV.UK - Terrorism National Emergency", @@ -18506,7 +18731,7 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "icsr-kcl": { "provider": "International Centre for the Study of Radicalisation (ICSR) a Updates", @@ -18531,26 +18756,26 @@ "quarantined": true, "quarantinedAt": "2026-04-06T12:11:54.469Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "met-office-seasonal-advice": { "provider": "Met Office - Seasonal Advice", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 100, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 100, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18579,26 +18804,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T19:38:38.443Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "mi5-uk-threat-level": { "provider": "MI5 (Security Service) a UK Threat Level", "lane": "prevention", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 14, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18609,20 +18834,20 @@ "provider": "My Community Alert", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 99, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 99, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18633,20 +18858,20 @@ "provider": "North Wales Community Alert", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 96, - "failedRuns": 3, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 23, + "failedRuns": 4, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-11T05:55:24.715Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18676,7 +18901,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:04:11.606Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "npsa-blog": { "provider": "NPSA - Blog", @@ -18700,7 +18925,7 @@ "quarantined": true, "quarantinedAt": "2026-04-05T20:40:59.773Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "npsa-blog-news": { "provider": "NPSA - Blog News", @@ -18724,7 +18949,7 @@ "quarantined": true, "quarantinedAt": "2026-04-05T20:40:59.773Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "npsa-national-protective-security-authority": { "provider": "NPSA - Activity on GOV.UK", @@ -18748,26 +18973,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T13:02:51.966Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "protectuk": { "provider": "ProtectUK (NPSA) a Protective Security Guidance", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 3, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 101, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18778,20 +19003,20 @@ "provider": "South Yorkshire Police Alerts", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18802,20 +19027,20 @@ "provider": "Stay In The Know - Community Alerts", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18826,20 +19051,20 @@ "provider": "Stay In The Know - Latest Alerts", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18850,20 +19075,20 @@ "provider": "UK NCSC - All Updates RSS", "lane": "prevention", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 3, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 103, "emptyRuns": 3, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-10T07:53:55.569Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18892,26 +19117,26 @@ "quarantined": true, "quarantinedAt": "2026-04-05T20:40:59.773Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "uk-prevent-duty-guidance": { "provider": "GOV.UK a Prevent Duty Guidance (Collection)", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 9, "emptyRuns": 92, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 92, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T09:17:50.585Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18922,20 +19147,20 @@ "provider": "WMNow - Community Alerts", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 96, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 96, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18946,20 +19171,20 @@ "provider": "West Yorkshire Community Alert", "lane": "prevention", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 98, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 98, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18970,20 +19195,20 @@ "provider": "GOV.UK a Proscribed Terrorist Organisations", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 5, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T05:29:44.899Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -18994,20 +19219,20 @@ "provider": "HM Treasury", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 94, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 94, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "Circuit open for domain www.gov.uk until 2026-04-11T23:50:08.264Z", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19018,20 +19243,20 @@ "provider": "OFSI - Blog", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19042,20 +19267,20 @@ "provider": "OTSI - Blog", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 51, "emptyRuns": 43, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-09T15:33:36.097Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19066,20 +19291,20 @@ "provider": "Office of Financial Sanctions Implementation (OFSI) a Blog", "lane": "sanctions", "kind": "rss", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 1, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 107, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19109,7 +19334,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "ctc-sentinel": { "provider": "Combating Terrorism Center at West Point - CTC Sentinel", @@ -19133,26 +19358,27 @@ "autoSkipReason": "empty-cooldown", "quarantined": false, "quarantinedAt": null, - "quarantineReason": null + "quarantineReason": null, + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "dhs-press-releases": { "provider": "US Department of Homeland Security - News", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 6, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T05:29:44.899Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19182,7 +19408,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "doj-nsd-press-releases": { "provider": "U.S. Department of Justice - National Security Division Press Releases", @@ -19207,7 +19433,7 @@ "quarantined": true, "quarantinedAt": "2026-04-06T17:59:08.402Z", "quarantineReason": "HTTP 404 not found; needs manual source URL review", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "fbi-national-press-releases": { "provider": "FBI - National Press Releases (RSS)", @@ -19232,7 +19458,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "fbi-stories": { "provider": "FBI - Stories (RSS)", @@ -19257,7 +19483,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "fbi-top-stories": { "provider": "FBI - Top Stories (RSS)", @@ -19282,7 +19508,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "gw-program-extremism": { "provider": "George Washington University - Program on Extremism", @@ -19307,26 +19533,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "nsa-cybersecurity-news": { "provider": "NSA - Cybersecurity Advisories & Guidance", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 85, - "failedRuns": 4, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 85, + "failedRuns": 5, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": "2026-04-06T05:29:44.899Z", + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19356,26 +19582,26 @@ "quarantined": true, "quarantinedAt": "2026-04-09T21:05:22.885Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "rewards-for-justice": { "provider": "U.S. Department of State - Rewards for Justice", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 4, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-06T05:29:44.899Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19405,7 +19631,7 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "start-center-publications": { "provider": "START Center (UMD) - News & Publications", @@ -19430,26 +19656,26 @@ "quarantined": false, "quarantinedAt": null, "quarantineReason": null, - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "state-dept-terrorism": { "provider": "US State Department - Bureau of Counterterrorism", "lane": "context", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 4, "emptyRuns": 91, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 91, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-05T14:37:36.069Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19460,20 +19686,20 @@ "provider": "CISA - Cybersecurity Alerts & Advisories", "lane": "oversight", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", - "lastBuiltCount": 4, + "lastCheckedAt": "2026-04-11T23:45:27.477Z", + "lastBuiltCount": 0, "successfulRuns": 94, "emptyRuns": 0, - "failedRuns": 0, - "consecutiveFailures": 0, + "failedRuns": 1, + "consecutiveFailures": 1, "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": "2026-04-11T23:10:14.423Z", - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": null, - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19503,26 +19729,26 @@ "quarantined": true, "quarantinedAt": "2026-04-10T12:03:32.036Z", "quarantineReason": "Repeated blocked-or-auth failures on html source", - "lastDeferredAt": "2026-04-11T23:10:14.423Z" + "lastDeferredAt": "2026-04-11T23:45:27.477Z" }, "us-treasury-ofac-press-releases": { "provider": "U.S. Treasury (OFAC) - Press Releases", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 95, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 95, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, @@ -19533,20 +19759,20 @@ "provider": "U.S. Treasury (OFAC) - Recent Actions", "lane": "sanctions", "kind": "html", - "lastCheckedAt": "2026-04-11T23:10:14.423Z", + "lastCheckedAt": "2026-04-11T23:45:27.477Z", "lastBuiltCount": 0, "successfulRuns": 0, "emptyRuns": 93, - "failedRuns": 0, - "consecutiveFailures": 0, - "consecutiveEmptyRuns": 93, + "failedRuns": 1, + "consecutiveFailures": 1, + "consecutiveEmptyRuns": 0, "consecutiveBlockedFailures": 0, "consecutiveDeadUrlFailures": 0, "lastSuccessfulAt": null, - "lastFailureAt": null, + "lastFailureAt": "2026-04-11T23:45:27.477Z", "lastEmptyAt": "2026-04-11T23:10:14.423Z", - "lastErrorCategory": null, - "lastErrorMessage": null, + "lastErrorCategory": "network-failure", + "lastErrorMessage": "fetch failed", "cooldownUntil": null, "autoSkipReason": null, "quarantined": false, diff --git a/source-quarantine.html b/source-quarantine.html index c69a404a..8dd42774 100644 --- a/source-quarantine.html +++ b/source-quarantine.html @@ -170,7 +170,7 @@

Source Quarantine Review

- Generated: 2026-04-11T23:10:14.423Z + Generated: 2026-04-11T23:45:27.477Z Quarantined sources: 188 SLA: review within 48h
@@ -315,7 +315,7 @@

Source Quarantine Review

? 'Data mode: live API (restore enabled)' : 'Data mode: live read-only (restore unavailable)'; meta.innerHTML = [ - 'Generated: ' + escapeHtml(payload.generatedAt || '2026-04-11T23:10:14.423Z') + '', + 'Generated: ' + escapeHtml(payload.generatedAt || '2026-04-11T23:45:27.477Z') + '', 'Quarantined sources: ' + escapeHtml(currentEntries.length) + '', 'SLA: review within 48h', '' + From 1924995abf21e9810198d233f2f2ceccc7e88d54 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:52:18 +0000 Subject: [PATCH 2/3] feat: implement core brialert improvement set Agent-Logs-Url: https://github.com/potemkin666/Brialert/sessions/0ac49de3-9169-4752-9774-d0966393cd77 Co-authored-by: potemkin666 <183807833+potemkin666@users.noreply.github.com> --- .github/pull_request_template.md | 20 +++ .github/workflows/catalog-hygiene.yml | 8 + .github/workflows/ci-feed-validation.yml | 5 + README.md | 3 + api/_lib/admin-session.js | 25 +++ api/auth/github/callback.js | 5 + api/auth/github/start.js | 5 + api/auth/logout.js | 10 +- api/auth/session.js | 2 + api/quarantined-sources.js | 10 +- api/restore-source.js | 24 ++- app/boot/actions.mjs | 26 +++ app/boot/elements.mjs | 5 + app/boot/events.mjs | 38 +++++ app/boot/index.mjs | 10 ++ app/render/live.mjs | 19 +++ app/state/index.mjs | 4 + docs/runbooks/operations.md | 19 +++ index.html | 43 ++++- package.json | 4 +- scripts/build-live-feed.mjs | 131 ++++++++++++++- scripts/build-live-feed/alerts.mjs | 44 ++++- scripts/build-live-feed/config.mjs | 2 + scripts/ci/source-catalog-lint-hints.mjs | 73 +++++++++ scripts/validate-feed-data.mjs | 16 ++ scripts/validate-live-feed-output.mjs | 27 ++++ shared/feed-controller.mjs | 23 ++- shared/map-watch.mjs | 29 +++- shared/ui-constants.mjs | 15 ++ styles.css | 51 ++++++ tests/decision-logic.test.mjs | 15 +- tests/ui-e2e.test.mjs | 194 +++++++++++++++++++++++ 32 files changed, 881 insertions(+), 24 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 docs/runbooks/operations.md create mode 100644 scripts/ci/source-catalog-lint-hints.mjs create mode 100644 tests/ui-e2e.test.mjs diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..0893593b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,20 @@ +## Summary +- Describe what changed and why. + +## Source curation checklist +- [ ] I ran `npm run compile:sources` +- [ ] I ran `npm run check:sources:freshness` +- [ ] I ran `npm run check:sources:hints` +- [ ] I documented replacement/removal rationale for risky or dead endpoints + +## Validation +- [ ] I ran `npm run validate:feed-data` +- [ ] I ran `npm run validate:live-feed-output` (if feed output changed) +- [ ] I ran `npm test` + +## Operational impact +- [ ] No user-facing behavior change +- [ ] User-facing behavior changed (describe below) + +### Notes +- Add rollout, guardrail, or follow-up notes. diff --git a/.github/workflows/catalog-hygiene.yml b/.github/workflows/catalog-hygiene.yml index adb164cc..7faeef4b 100644 --- a/.github/workflows/catalog-hygiene.yml +++ b/.github/workflows/catalog-hygiene.yml @@ -44,6 +44,8 @@ jobs: path: | data/source-remediation-sweep.json data/top-20-source-remediation.json + data/build-observability-summary.json + data/build-observability-trend.json data/quarantined-sources.json source-quarantine.html if-no-files-found: warn @@ -59,6 +61,12 @@ jobs: if [ -f data/top-20-source-remediation.json ]; then git add data/top-20-source-remediation.json fi + if [ -f data/build-observability-summary.json ]; then + git add data/build-observability-summary.json + fi + if [ -f data/build-observability-trend.json ]; then + git add data/build-observability-trend.json + fi if [ -f data/quarantined-sources.json ]; then git add data/quarantined-sources.json fi diff --git a/.github/workflows/ci-feed-validation.yml b/.github/workflows/ci-feed-validation.yml index 4ece6702..a22aabdb 100644 --- a/.github/workflows/ci-feed-validation.yml +++ b/.github/workflows/ci-feed-validation.yml @@ -56,6 +56,9 @@ jobs: - name: Validate compiled source catalog freshness run: npm run check:sources:freshness + - name: Generate source catalog lint hints + run: npm run check:sources:hints + - name: Validate London source health env: BRIALERT_SOURCE_HEALTH_SCOPE: critical @@ -116,6 +119,8 @@ jobs: cp live-alerts.json .ci-artifacts/live-alerts.json 2>/dev/null || true cp data/source-remediation-sweep.json .ci-artifacts/source-remediation-sweep.json 2>/dev/null || true cp data/top-20-source-remediation.json .ci-artifacts/top-20-source-remediation.json 2>/dev/null || true + cp data/build-observability-summary.json .ci-artifacts/build-observability-summary.json 2>/dev/null || true + cp data/build-observability-trend.json .ci-artifacts/build-observability-trend.json 2>/dev/null || true node ./scripts/ci/generate-feed-smoke-summary.mjs live-alerts.json .ci-artifacts/feed-smoke-summary.json - name: Enforce CI smoke runtime budget diff --git a/README.md b/README.md index c44bb393..c2ec5451 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Requires Node `20.18.1` or newer. npm ci npm run compile:sources npm run check:sources:freshness +npm run check:sources:hints npm run validate:feed-data npm run validate:source-health npm test @@ -89,7 +90,9 @@ npm run build:feeds - If a refresh preserves prior alerts and reports `sourceCount: 0`, the app now falls back to `health.lastSuccessfulSourceCount` so the hero source count does not stick at zero. - Source catalog can be managed in sharded files under `data/sources//.json`; `npm run compile:sources` rebuilds `data/sources.json`. - Build runs now emit `data/source-remediation-sweep.json` and `data/top-20-source-remediation.json` to prioritize dead/moved URLs and replacement actions. +- Build runs now emit `data/build-observability-summary.json` and `data/build-observability-trend.json` for structured diagnostics and trend tracking. - Build/runtime knobs (timeouts, retries, prefetch counts, html budget, guardrail fail behavior) are configurable through `BRIALERT_*` environment variables for CI fast-mode tuning. +- Operational recovery procedures are documented in `docs/runbooks/operations.md`. ## Source catalog contribution rules diff --git a/api/_lib/admin-session.js b/api/_lib/admin-session.js index f57724a6..e8fd7952 100644 --- a/api/_lib/admin-session.js +++ b/api/_lib/admin-session.js @@ -153,12 +153,37 @@ export function applyCorsHeaders(request, response, methods) { } response.setHeader('Access-Control-Allow-Methods', methods); response.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + response.setHeader('Access-Control-Max-Age', '600'); if (request?.method === 'OPTIONS') { return !requestOrigin || allowedOrigins.has(requestOrigin); } return true; } +export function logAdminAudit(event, details = {}) { + const payload = { + event: String(event || 'unknown'), + at: new Date().toISOString(), + ...details + }; + console.info(`[admin-audit] ${JSON.stringify(payload)}`); +} + +export function ensureMutatingRequestIsTrusted(request, response) { + const allowedOrigins = new Set(getAllowedOrigins()); + const origin = normaliseOrigin(request?.headers?.origin); + const referer = normaliseOrigin(request?.headers?.referer); + if (origin && allowedOrigins.has(origin)) return true; + if (referer && allowedOrigins.has(referer)) return true; + + response.status(403).json({ + ok: false, + error: 'forbidden-origin', + message: 'Origin/referer is not authorized for state-changing admin actions.' + }); + return false; +} + export function readAdminSession(request) { const cookies = parseCookies(request?.headers?.cookie); const payload = verifySignedToken(cookies[SESSION_COOKIE_NAME]); diff --git a/api/auth/github/callback.js b/api/auth/github/callback.js index 3074771a..1a884cc3 100644 --- a/api/auth/github/callback.js +++ b/api/auth/github/callback.js @@ -5,6 +5,7 @@ import { clearOauthStateCookie, getAuthRedirectConfig, getOAuthRedirectUri, + logAdminAudit, readOauthState, setAdminSessionCookie } from '../../_lib/admin-session.js'; @@ -77,8 +78,12 @@ export default async function handler(request, response) { setAdminSessionCookie(request, response, user); clearOauthStateCookie(request, response); + logAdminAudit('auth.oauth.callback.success', { actor: user.login }); return redirect(response, appendQueryParams(returnTo, { auth: 'ok' })); } catch (error) { + logAdminAudit('auth.oauth.callback.failed', { + message: error instanceof Error ? error.message : String(error) + }); clearAdminSessionCookie(request, response); clearOauthStateCookie(request, response); return redirect(response, failRedirectTarget(mapErrorCode(error))); diff --git a/api/auth/github/start.js b/api/auth/github/start.js index 644bf93c..694ac77e 100644 --- a/api/auth/github/start.js +++ b/api/auth/github/start.js @@ -2,6 +2,7 @@ import { ApiError } from '../../_lib/github-persistence.js'; import { createOauthState, getOAuthRedirectUri, + logAdminAudit, normalizeReturnTo, setOauthStateCookie } from '../../_lib/admin-session.js'; @@ -53,11 +54,15 @@ export default async function handler(request, response) { authUrl.searchParams.set('scope', 'read:user read:org'); authUrl.searchParams.set('state', nonce); authUrl.searchParams.set('allow_signup', 'false'); + logAdminAudit('auth.oauth.start', { returnTo }); response.statusCode = 302; response.setHeader('Location', authUrl.toString()); return response.end(); } catch (error) { + logAdminAudit('auth.oauth.start.failed', { + message: error instanceof Error ? error.message : String(error) + }); return sendError(response, error); } } diff --git a/api/auth/logout.js b/api/auth/logout.js index 53fbf738..1ab2bd93 100644 --- a/api/auth/logout.js +++ b/api/auth/logout.js @@ -1,6 +1,9 @@ import { applyCorsHeaders, - clearAdminSessionCookie + clearAdminSessionCookie, + ensureMutatingRequestIsTrusted, + logAdminAudit, + readAdminSession } from '../_lib/admin-session.js'; export default async function handler(request, response) { @@ -16,7 +19,12 @@ export default async function handler(request, response) { message: 'Only POST is supported.' }); } + if (!ensureMutatingRequestIsTrusted(request, response)) { + return response; + } + const session = readAdminSession(request); clearAdminSessionCookie(request, response); + logAdminAudit('auth.logout', { actor: session?.login || 'anonymous' }); return response.status(200).json({ ok: true }); } diff --git a/api/auth/session.js b/api/auth/session.js index 8c9b9982..69e4cc9d 100644 --- a/api/auth/session.js +++ b/api/auth/session.js @@ -1,6 +1,7 @@ import { applyCorsHeaders, getAllowedOrigins, + logAdminAudit, readAdminSession } from '../_lib/admin-session.js'; @@ -35,6 +36,7 @@ export default async function handler(request, response) { const session = readAdminSession(request); const originHint = request.headers.origin; if (!session) { + logAdminAudit('auth.session.unauthenticated', {}); return response.status(200).json({ ok: true, authenticated: false, diff --git a/api/quarantined-sources.js b/api/quarantined-sources.js index 8713b1b8..aa2570fd 100644 --- a/api/quarantined-sources.js +++ b/api/quarantined-sources.js @@ -1,5 +1,5 @@ import { ApiError, loadJsonFile } from './_lib/github-persistence.js'; -import { applyCorsHeaders, requireAdminSession } from './_lib/admin-session.js'; +import { applyCorsHeaders, logAdminAudit, requireAdminSession } from './_lib/admin-session.js'; function sendError(response, error) { const status = error instanceof ApiError ? error.status : 500; @@ -50,7 +50,9 @@ export default async function handler(request, response) { message: 'Only GET is supported.' }); } - if (!requireAdminSession(request, response)) { + const session = requireAdminSession(request, response); + if (!session) { + logAdminAudit('quarantined-sources.unauthenticated', {}); return response; } @@ -77,6 +79,10 @@ export default async function handler(request, response) { sources }); } catch (error) { + logAdminAudit('quarantined-sources.failed', { + actor: session.login, + message: error instanceof Error ? error.message : String(error) + }); return sendError(response, error); } } diff --git a/api/restore-source.js b/api/restore-source.js index a26201ee..ec57e28e 100644 --- a/api/restore-source.js +++ b/api/restore-source.js @@ -6,7 +6,12 @@ import { normaliseEndpoint, validateAbsoluteHttpUrl } from './_lib/github-persistence.js'; -import { applyCorsHeaders, requireAdminSession } from './_lib/admin-session.js'; +import { + applyCorsHeaders, + ensureMutatingRequestIsTrusted, + logAdminAudit, + requireAdminSession +} from './_lib/admin-session.js'; const QUARANTINE_ONLY_FIELDS = new Set([ 'status', @@ -135,7 +140,12 @@ export default async function handler(request, response) { message: 'Only POST is supported.' }); } - if (!requireAdminSession(request, response)) { + const session = requireAdminSession(request, response); + if (!session) { + return response; + } + if (!ensureMutatingRequestIsTrusted(request, response)) { + logAdminAudit('restore-source.forbidden-origin', { actor: session.login }); return response; } @@ -217,12 +227,22 @@ export default async function handler(request, response) { `Restore quarantined source ${sourceId}` ); + logAdminAudit('restore-source.success', { + actor: session.login, + sourceId, + replacementUrl + }); + return response.status(200).json({ ok: true, restoredSource, message: 'Source restored successfully.' }); } catch (error) { + logAdminAudit('restore-source.failed', { + actor: session.login, + message: error instanceof Error ? error.message : String(error) + }); return sendError(response, error); } } diff --git a/app/boot/actions.mjs b/app/boot/actions.mjs index 2b2b8252..f6e4bdef 100644 --- a/app/boot/actions.mjs +++ b/app/boot/actions.mjs @@ -23,6 +23,32 @@ export function setSearchQuery(state, nextQuery) { state.searchQuery = String(nextQuery || ''); } +export function setActiveLane(state, nextLane) { + state.activeLane = String(nextLane || 'all'); + state.feedVisibleCount = INITIAL_RESPONDER_VISIBLE; + state.supportingVisibleCount = INITIAL_SUPPORTING_VISIBLE; +} + +export function setActiveSeverityThreshold(state, nextThreshold) { + state.activeSeverityThreshold = String(nextThreshold || 'all'); + state.feedVisibleCount = INITIAL_RESPONDER_VISIBLE; + state.supportingVisibleCount = INITIAL_SUPPORTING_VISIBLE; +} + +export function addMutedSource(state, source) { + const value = String(source || '').trim().toLowerCase(); + if (!value) return false; + if (state.mutedSources.has(value)) return false; + state.mutedSources.add(value); + return true; +} + +export function removeMutedSource(state, source) { + const value = String(source || '').trim().toLowerCase(); + if (!value) return false; + return state.mutedSources.delete(value); +} + export function toggleWatchedAlert(state, alertId) { if (!alertId) return; if (state.watched.has(alertId)) state.watched.delete(alertId); diff --git a/app/boot/elements.mjs b/app/boot/elements.mjs index 160d143c..7a79ace5 100644 --- a/app/boot/elements.mjs +++ b/app/boot/elements.mjs @@ -22,6 +22,11 @@ export function createElements() { mapEmptyState: document.getElementById('map-empty-state'), mapModeTabs: document.getElementById('map-mode-tabs'), filters: document.getElementById('filters'), + laneFilter: document.getElementById('lane-filter'), + severityFilter: document.getElementById('severity-filter'), + sourceMuteForm: document.getElementById('source-mute-form'), + sourceMuteInput: document.getElementById('source-mute-input'), + sourceMuteList: document.getElementById('source-mute-list'), tabbar: document.getElementById('tabbar'), briefingModePanel: document.getElementById('briefing-mode-panel'), briefingModeTitle: document.getElementById('briefing-mode-title'), diff --git a/app/boot/events.mjs b/app/boot/events.mjs index 18968c34..6411e1a6 100644 --- a/app/boot/events.mjs +++ b/app/boot/events.mjs @@ -16,7 +16,9 @@ export function bindEvents({ notesStorageKey, sourceRequestsStorageKey, watchedStorageKey, + mutedSourcesStorageKey, sourceRequestApiUrl, + severityThresholdStorageKey, actions, rendering, setActiveTab, @@ -37,6 +39,42 @@ export function bindEvents({ rendering.renderAll(); }); + elements.laneFilter?.addEventListener('change', (event) => { + actions.setActiveLane(state, String(event.target?.value || 'all')); + rendering.invalidateDerivedView(); + rendering.renderAll(); + }); + + elements.severityFilter?.addEventListener('change', (event) => { + const value = String(event.target?.value || 'all'); + actions.setActiveSeverityThreshold(state, value); + if (typeof localStorage !== 'undefined') { + localStorage.setItem(severityThresholdStorageKey, value); + } + rendering.invalidateDerivedView(); + rendering.renderAll(); + }); + + elements.sourceMuteForm?.addEventListener('submit', (event) => { + event.preventDefault(); + const value = String(elements.sourceMuteInput?.value || '').trim(); + if (!actions.addMutedSource(state, value)) return; + saveSet(mutedSourcesStorageKey, state.mutedSources); + if (elements.sourceMuteInput) elements.sourceMuteInput.value = ''; + rendering.invalidateDerivedView(); + rendering.renderAll(); + }); + + elements.sourceMuteList?.addEventListener('click', (event) => { + const button = event.target.closest('[data-remove-muted-source]'); + if (!button) return; + const source = button.getAttribute('data-remove-muted-source'); + if (!actions.removeMutedSource(state, source)) return; + saveSet(mutedSourcesStorageKey, state.mutedSources); + rendering.invalidateDerivedView(); + rendering.renderAll(); + }); + elements.feedLoadMore?.addEventListener('click', () => { actions.incrementResponderVisible(state); rendering.renderAll(); diff --git a/app/boot/index.mjs b/app/boot/index.mjs index ec9bf58a..440a2e92 100644 --- a/app/boot/index.mjs +++ b/app/boot/index.mjs @@ -19,8 +19,10 @@ import { MAP_INIT_FALLBACK_DELAY_MS, MAP_INIT_IDLE_TIMEOUT_MS, LIVE_FEED_URL, + MUTED_SOURCES_STORAGE_KEY, NOTES_STORAGE_KEY, POLL_INTERVAL_MS, + SEVERITY_THRESHOLD_STORAGE_KEY, SOURCE_REQUEST_API_URL, SOURCE_REQUESTS_STORAGE_KEY, WATCHED_STORAGE_KEY, @@ -120,7 +122,9 @@ export function initialiseApp() { notesStorageKey: NOTES_STORAGE_KEY, sourceRequestsStorageKey: SOURCE_REQUESTS_STORAGE_KEY, watchedStorageKey: WATCHED_STORAGE_KEY, + mutedSourcesStorageKey: MUTED_SOURCES_STORAGE_KEY, sourceRequestApiUrl: SOURCE_REQUEST_API_URL, + severityThresholdStorageKey: SEVERITY_THRESHOLD_STORAGE_KEY, actions, rendering, setActiveTab, @@ -151,6 +155,12 @@ export function initialiseApp() { state.watched = loadSet(WATCHED_STORAGE_KEY); state.notes = loadArray(NOTES_STORAGE_KEY, defaultNotes); state.sourceRequests = loadArray(SOURCE_REQUESTS_STORAGE_KEY, []); + state.mutedSources = loadSet(MUTED_SOURCES_STORAGE_KEY); + try { + state.activeSeverityThreshold = String(localStorage.getItem(SEVERITY_THRESHOLD_STORAGE_KEY) || 'all'); + } catch { + state.activeSeverityThreshold = 'all'; + } state.briefingMode = false; state.mapViewMode = state.mapViewMode || MAP_VIEW_MODES.world; diff --git a/app/render/live.mjs b/app/render/live.mjs index 12d479fc..b03cadf9 100644 --- a/app/render/live.mjs +++ b/app/render/live.mjs @@ -49,6 +49,18 @@ function trimTrailingPeriod(value) { return String(value || '').trim().replace(/\.+$/, ''); } +function renderMutedSources(elements, mutedSources) { + if (!elements.sourceMuteList) return; + const entries = [...(mutedSources || new Set())].sort(); + if (!entries.length) { + elements.sourceMuteList.innerHTML = `

No muted sources.

`; + return; + } + elements.sourceMuteList.innerHTML = entries + .map((entry) => ``) + .join(''); +} + export function renderPriority({ state, elements, view, modalController }) { const alert = view.topPriority; if (!alert) { @@ -170,6 +182,13 @@ export function renderHero({ state, elements }) { if (elements.heroSearch && elements.heroSearch.value !== state.searchQuery) { elements.heroSearch.value = state.searchQuery; } + if (elements.laneFilter && elements.laneFilter.value !== state.activeLane) { + elements.laneFilter.value = state.activeLane; + } + if (elements.severityFilter && elements.severityFilter.value !== state.activeSeverityThreshold) { + elements.severityFilter.value = state.activeSeverityThreshold; + } + renderMutedSources(elements, state.mutedSources); const healthRefresh = state.liveFeedHealth?.lastSuccessfulRefreshTime; const stamp = healthRefresh ? new Date(healthRefresh) : state.liveFeedGeneratedAt; const hasValidStamp = stamp instanceof Date && !Number.isNaN(stamp.getTime()); diff --git a/app/state/index.mjs b/app/state/index.mjs index 5ed42d7b..d35d788d 100644 --- a/app/state/index.mjs +++ b/app/state/index.mjs @@ -7,6 +7,8 @@ export const WATCHED_STORAGE_KEY = 'brialert.watched'; export const NOTES_STORAGE_KEY = 'brialert.notes'; export const SOURCE_REQUESTS_STORAGE_KEY = 'brialert.sourceRequests'; export const BRIEFING_MODE_STORAGE_KEY = 'brialert.briefingMode'; +export const SEVERITY_THRESHOLD_STORAGE_KEY = 'brialert.severityThreshold'; +export const MUTED_SOURCES_STORAGE_KEY = 'brialert.mutedSources'; export const SOURCE_REQUEST_API_URL = '/api/request-source'; export const INITIAL_RESPONDER_VISIBLE = 18; export const RESPONDER_LOAD_STEP = 16; @@ -21,6 +23,8 @@ export function createState() { searchQuery: '', activeRegion: 'all', activeLane: 'all', + activeSeverityThreshold: 'all', + mutedSources: new Set(), mapViewMode: 'world', watched: new Set(), lastBrowserPollAt: new Date(), diff --git a/docs/runbooks/operations.md b/docs/runbooks/operations.md new file mode 100644 index 00000000..94faf3df --- /dev/null +++ b/docs/runbooks/operations.md @@ -0,0 +1,19 @@ +# Brialert operations runbook + +## 1) Stale feed in UI +- Check latest `Update live feeds` workflow run status. +- If successful, confirm `live-alerts.json` has a recent `generatedAt` and `health.lastSuccessfulRefreshTime`. +- If stale, trigger a manual run and confirm the UI `Refresh feed` path reports a newer timestamp. +- If the run warns about guardrails, inspect `runMetrics.guardrails.violations` and reduce failing source load before retrying. + +## 2) Source outages / high failure rate +- Inspect `data/source-remediation-sweep.json` and `data/top-20-source-remediation.json` for category hotspots. +- Review `data/build-observability-summary.json` for failing lanes/kinds and guardrail violations. +- Temporarily quarantine repeatedly dead/blocked sources, then rebuild feed. +- For persistent host-wide outages, reduce scheduler pressure and retry after cooldown windows. + +## 3) Quarantine restore failures +- Confirm admin login succeeds at `/api/auth/session`. +- Verify restore requests come from an allowed frontend origin (`BRIALERT_ALLOWED_ORIGINS`). +- Check restore API response payload (`error`, `message`) and audit events prefixed with `[admin-audit]`. +- If duplicate conflict occurs, update the candidate endpoint so it does not collide with an existing active source. diff --git a/index.html b/index.html index 62b822af..e3a8efb2 100644 --- a/index.html +++ b/index.html @@ -88,12 +88,43 @@

Waiting for a verified source pull

-
- - - - -
+
+ + + + +
+
+
+ + +
+
+ + +
+
+
diff --git a/package.json b/package.json index 88b4cf1d..662c504f 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,14 @@ "scripts": { "compile:sources": "node ./scripts/compile-source-catalog.mjs", "check:sources:freshness": "node ./scripts/ci/check-source-catalog-freshness.mjs", + "check:sources:hints": "node ./scripts/ci/source-catalog-lint-hints.mjs", "split:sources": "node ./scripts/split-source-catalog.mjs", "validate:feed-data": "node ./scripts/compile-source-catalog.mjs --quiet && node ./scripts/validate-feed-data.mjs", "validate:source-health": "node ./scripts/validate-source-health.mjs", "validate:live-feed-output": "node ./scripts/validate-live-feed-output.mjs", "build:feeds": "node ./scripts/compile-source-catalog.mjs --quiet && node ./scripts/build-live-feed.mjs", - "test": "node --test ./tests/*.test.mjs" + "test": "node --test ./tests/*.test.mjs", + "test:e2e": "BRIALERT_RUN_E2E=true node --test ./tests/ui-e2e.test.mjs" }, "dependencies": { "cheerio": "^1.2.0", diff --git a/scripts/build-live-feed.mjs b/scripts/build-live-feed.mjs index b0441191..efea8028 100644 --- a/scripts/build-live-feed.mjs +++ b/scripts/build-live-feed.mjs @@ -41,6 +41,8 @@ import { sourceDeterministicHash, shouldRefreshSourceThisRun, outputPath, + observabilitySummaryPath, + observabilityTrendPath, quarantinedSourcesPath, quarantinedSourcesReviewPath, sourceRemediationSweepPath, @@ -162,6 +164,19 @@ function sourceMayAutoCooldown(source, previousEntry, buildDate) { return null; } +function clampReliabilityScore(value) { + const numeric = Number(value); + if (!Number.isFinite(numeric)) return 50; + return Math.max(0, Math.min(100, Math.round(numeric))); +} + +function reliabilityPenaltyForCategory(category) { + if (category === 'not-found-404' || category === 'dead-or-moved-url') return 16; + if (category === 'blocked-or-auth' || category === 'anti-bot-protection') return 11; + if (category === 'timeout' || category === 'network-failure') return 8; + return 6; +} + function nextSourceHealthEntry(source, stat, previousEntry, generatedAt) { const prior = previousEntry && typeof previousEntry === 'object' ? previousEntry : {}; const priorBlockedFailures = Number(prior.consecutiveBlockedFailures || 0); @@ -188,7 +203,9 @@ function nextSourceHealthEntry(source, stat, previousEntry, generatedAt) { autoSkipReason: null, quarantined: Boolean(prior.quarantined), quarantinedAt: prior.quarantinedAt || null, - quarantineReason: prior.quarantineReason || null + quarantineReason: prior.quarantineReason || null, + reliabilityScore: clampReliabilityScore(prior.reliabilityScore), + rehabilitationStreak: Number(prior.rehabilitationStreak || 0) }; if ((stat?.built || 0) > 0) { @@ -200,6 +217,9 @@ function nextSourceHealthEntry(source, stat, previousEntry, generatedAt) { next.lastErrorCategory = null; next.lastErrorMessage = null; next.lastSuccessfulAt = generatedAt; + next.rehabilitationStreak += 1; + const reliabilityBoost = next.rehabilitationStreak >= 3 ? 10 : 7; + next.reliabilityScore = clampReliabilityScore(next.reliabilityScore + reliabilityBoost); return next; } @@ -215,6 +235,10 @@ function nextSourceHealthEntry(source, stat, previousEntry, generatedAt) { next.lastFailureAt = generatedAt; next.lastErrorCategory = stat?.lastErrorCategory || null; next.lastErrorMessage = stat?.lastErrorMessage || null; + next.rehabilitationStreak = 0; + next.reliabilityScore = clampReliabilityScore( + next.reliabilityScore - reliabilityPenaltyForCategory(stat?.lastErrorCategory || '') + ); if (!next.quarantined && notFoundFailure) { next.quarantined = true; next.quarantinedAt = generatedAt; @@ -255,6 +279,8 @@ function nextSourceHealthEntry(source, stat, previousEntry, generatedAt) { next.lastErrorCategory = null; next.lastErrorMessage = null; next.lastEmptyAt = generatedAt; + next.rehabilitationStreak = 0; + next.reliabilityScore = clampReliabilityScore(next.reliabilityScore - 2); if (!source.isTrustedOfficial && source.lane !== 'incidents' && next.consecutiveEmptyRuns >= AUTO_SKIP_EMPTY_THRESHOLD) { next.cooldownUntil = new Date(Date.parse(generatedAt) + SOURCE_EMPTY_COOLDOWN_HOURS * 3600000).toISOString(); next.autoSkipReason = 'empty-cooldown'; @@ -315,22 +341,37 @@ function buildAlertChurnRows(previousAlerts, nextAlerts) { return rows; } -function sourceSchedulingPriority(source) { +function sourceSchedulingPriority(source, healthEntry = null) { if (isMachineReadableSourceKind(source?.kind)) { if (source?.lane === 'incidents') return 100; if (source?.isTrustedOfficial) return 90; - return 80; + let score = 80; + const reliabilityScore = Number(healthEntry?.reliabilityScore); + if (Number.isFinite(reliabilityScore)) { + if (reliabilityScore < 30) score -= 15; + else if (reliabilityScore < 45) score -= 8; + else if (reliabilityScore > 75) score += 3; + } + if (Number(healthEntry?.rehabilitationStreak || 0) >= 3) score += 4; + return score; } let score = 10; if (source?.lane === 'incidents') score += 15; if (source?.isTrustedOfficial) score += 10; if (source?.lane === 'prevention') score += 4; + const reliabilityScore = Number(healthEntry?.reliabilityScore); + if (Number.isFinite(reliabilityScore)) { + if (reliabilityScore < 30) score -= 10; + else if (reliabilityScore < 45) score -= 6; + else if (reliabilityScore > 75) score += 2; + } + if (Number(healthEntry?.rehabilitationStreak || 0) >= 3) score += 3; return score; } -function schedulingTier(source) { - const priority = sourceSchedulingPriority(source); +function schedulingTier(source, healthEntry = null) { + const priority = sourceSchedulingPriority(source, healthEntry); if (priority >= 90) return 'high'; if (priority >= 25) return 'medium'; return 'low'; @@ -1434,6 +1475,62 @@ function buildSourceRemediationSweep({ generatedAt, sourceErrors, sourceStats }) }; } +async function readJsonIfExists(filePath, fallback) { + try { + const raw = await fs.readFile(filePath, 'utf8'); + return JSON.parse(raw); + } catch { + return fallback; + } +} + +async function writeObservabilityArtifacts({ + generatedAt, + runMetrics, + buildWarning, + sourceErrors, + sourceStats, + guardrailViolations +}) { + const summary = { + schemaVersion: '2026-04-obs-v1', + generatedAt, + runMetrics, + buildWarning: buildWarning || null, + guardrailViolations: Array.isArray(guardrailViolations) ? guardrailViolations : [], + topSourceErrors: (Array.isArray(sourceErrors) ? sourceErrors : []).slice(0, 20), + sourceStats: (Array.isArray(sourceStats) ? sourceStats : []).map((entry) => ({ + id: entry.id, + provider: entry.provider, + lane: entry.lane, + kind: entry.kind, + built: entry.built, + errors: entry.errors, + fetchOutcome: entry.fetchOutcome, + lastErrorCategory: entry.lastErrorCategory + })) + }; + await fs.writeFile(observabilitySummaryPath, JSON.stringify(summary, null, 2) + '\n', 'utf8'); + + const previousTrend = await readJsonIfExists(observabilityTrendPath, { schemaVersion: '2026-04-obs-trend-v1', history: [] }); + const history = Array.isArray(previousTrend?.history) ? previousTrend.history : []; + history.push({ + generatedAt, + checked: Number(runMetrics?.coverage?.checked || 0), + eligible: Number(runMetrics?.coverage?.eligible || 0), + successfulSources: Number(runMetrics?.guardrails?.successfulSources || 0), + failedSourceRate: Number(runMetrics?.guardrails?.failedSourceRate || 0), + runDurationMs: Number(runMetrics?.runDurationMs || 0), + sourceErrors: Array.isArray(sourceErrors) ? sourceErrors.length : 0 + }); + const bounded = history.slice(-200); + await fs.writeFile(observabilityTrendPath, JSON.stringify({ + schemaVersion: '2026-04-obs-trend-v1', + generatedAt, + history: bounded + }, null, 2) + '\n', 'utf8'); +} + async function syncBuilderSQLite(snapshot) { const helperPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'build-live-feed', 'sqlite-sync.py'); const tempPath = path.join(os.tmpdir(), `brialert-sqlite-sync-${Date.now()}-${process.pid}.json`); @@ -1561,7 +1658,7 @@ async function main() { .map((source, index) => ({ source, index, - priority: sourceSchedulingPriority(source) + priority: sourceSchedulingPriority(source, sourceHealthEntry(previousHealth, source.id)) })) .sort((left, right) => { if (right.priority !== left.priority) return right.priority - left.priority; @@ -1597,7 +1694,8 @@ async function main() { } const continuationCandidates = [...continuationCandidatesById.values()] .sort((left, right) => { - const priorityDelta = sourceSchedulingPriority(right.source) - sourceSchedulingPriority(left.source); + const priorityDelta = sourceSchedulingPriority(right.source, sourceHealthEntry(previousHealth, right.source?.id)) + - sourceSchedulingPriority(left.source, sourceHealthEntry(previousHealth, left.source?.id)); if (priorityDelta !== 0) return priorityDelta; return left.index - right.index; }) @@ -1972,7 +2070,7 @@ async function main() { const sourceById = new Map(eligibleSources.map((source) => [source.id, source])); const freshnessByTier = Object.entries(nextSourceHealth).reduce((acc, [sourceId, entry]) => { const source = sourceById.get(sourceId) || entry; - const tier = schedulingTier(source); + const tier = schedulingTier(source, entry); const minutes = freshnessMinutes(entry, nowMs); if (minutes === null) return acc; if (!acc[tier]) acc[tier] = []; @@ -2001,6 +2099,7 @@ async function main() { }; const payload = { + schemaVersion: '2026-04-live-feed-v1', generatedAt, sourceCount: checked, alertCount: finalAlerts.length, @@ -2090,6 +2189,14 @@ async function main() { const existingRuntimeMs = Number(existing?.runMetrics?.runDurationMs || 0); if (hasExistingAlertsSnapshot && currentComparable === nextComparable && !sourceErrors.length && !geoLookupFallbackNote) { + await writeObservabilityArtifacts({ + generatedAt, + runMetrics: payload.runMetrics, + buildWarning, + sourceErrors, + sourceStats, + guardrailViolations + }); if (Number.isFinite(existingRuntimeMs) && existingRuntimeMs > GUARDRAIL_MAX_RUNTIME_MS) { console.log(`No alert changes detected, refreshing feed metadata because previous runDurationMs=${existingRuntimeMs} exceeds guardrail=${GUARDRAIL_MAX_RUNTIME_MS}.`); } else { @@ -2098,6 +2205,14 @@ async function main() { } } + await writeObservabilityArtifacts({ + generatedAt, + runMetrics: payload.runMetrics, + buildWarning, + sourceErrors, + sourceStats, + guardrailViolations + }); await fs.writeFile(outputPath, JSON.stringify(payload, null, 2) + '\n', 'utf8'); await fs.writeFile(quarantinedSourcesPath, JSON.stringify(quarantinedPayload, null, 2) + '\n', 'utf8'); await fs.writeFile(quarantinedSourcesReviewPath, renderQuarantinedSourcesHtml(generatedAt, quarantinedEntries), 'utf8'); diff --git a/scripts/build-live-feed/alerts.mjs b/scripts/build-live-feed/alerts.mjs index 09f5ab96..f22772e3 100644 --- a/scripts/build-live-feed/alerts.mjs +++ b/scripts/build-live-feed/alerts.mjs @@ -303,6 +303,47 @@ function shouldKeepPeopleInvolved(reliabilityProfile, confidenceScore, needsHuma return false; } +function dedupeTokens(value) { + return new Set( + clean(value) + .toLowerCase() + .replace(/[^a-z0-9\s]/g, ' ') + .split(/\s+/) + .filter(Boolean) + .filter((token) => token.length >= 4) + ); +} + +function jaccardSimilarity(left, right) { + const leftTokens = dedupeTokens(left); + const rightTokens = dedupeTokens(right); + if (!leftTokens.size || !rightTokens.size) return 0; + let intersection = 0; + for (const token of leftTokens) { + if (rightTokens.has(token)) intersection += 1; + } + const union = leftTokens.size + rightTokens.size - intersection; + return union > 0 ? intersection / union : 0; +} + +function nearDuplicateKey(item, deduped) { + const itemPublished = parseSourceDate(item?.publishedAt)?.getTime() || 0; + for (const existing of deduped) { + if (clean(item?.location).toLowerCase() !== clean(existing?.location).toLowerCase()) continue; + if (clean(item?.eventType).toLowerCase() !== clean(existing?.eventType).toLowerCase()) continue; + const existingPublished = parseSourceDate(existing?.publishedAt)?.getTime() || 0; + if (Math.abs(itemPublished - existingPublished) > 6 * 3600000) continue; + const similarity = jaccardSimilarity( + `${item?.title || ''} ${item?.summary || ''}`, + `${existing?.title || ''} ${existing?.summary || ''}` + ); + if (similarity >= 0.55) { + return existing.fusedIncidentId || existing.id; + } + } + return ''; +} + export function discardReasonForItem(source, item) { const sourceTier = inferSourceTier(source); const reliabilityProfile = inferReliabilityProfile(source, sourceTier); @@ -429,7 +470,8 @@ export function dedupeAndSortAlerts(items) { const seen = new Map(); for (const item of items) { - const key = item.fusedIncidentId || `${sameStoryKey(item)}|${item.location}|${item.eventType}`; + const semanticKey = nearDuplicateKey(item, deduped); + const key = semanticKey || item.fusedIncidentId || `${sameStoryKey(item)}|${item.location}|${item.eventType}`; if (seen.has(key)) { const existingIndex = seen.get(key); const incumbent = deduped[existingIndex]; diff --git a/scripts/build-live-feed/config.mjs b/scripts/build-live-feed/config.mjs index e597a40b..041a6518 100644 --- a/scripts/build-live-feed/config.mjs +++ b/scripts/build-live-feed/config.mjs @@ -15,6 +15,8 @@ export const quarantinedSourcesPath = path.join(repoRoot, 'data', 'quarantined-s export const quarantinedSourcesReviewPath = path.join(repoRoot, 'source-quarantine.html'); export const topSourceRemediationPath = path.join(repoRoot, 'data', 'top-20-source-remediation.json'); export const sourceRemediationSweepPath = path.join(repoRoot, 'data', 'source-remediation-sweep.json'); +export const observabilitySummaryPath = path.join(repoRoot, 'data', 'build-observability-summary.json'); +export const observabilityTrendPath = path.join(repoRoot, 'data', 'build-observability-trend.json'); export const parser = new XMLParser({ ignoreAttributes: false, diff --git a/scripts/ci/source-catalog-lint-hints.mjs b/scripts/ci/source-catalog-lint-hints.mjs new file mode 100644 index 00000000..9abf77d7 --- /dev/null +++ b/scripts/ci/source-catalog-lint-hints.mjs @@ -0,0 +1,73 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(__dirname, '../..'); +const sourcesPath = path.join(repoRoot, 'data', 'sources.json'); + +function normaliseEndpoint(value) { + const raw = String(value || '').trim(); + if (!raw) return ''; + try { + const parsed = new URL(raw); + parsed.hash = ''; + return parsed.toString().replace(/\/$/, '').toLowerCase(); + } catch { + return raw.replace(/\/$/, '').toLowerCase(); + } +} + +async function main() { + const raw = await fs.readFile(sourcesPath, 'utf8'); + const parsed = JSON.parse(raw); + const sources = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.sources) ? parsed.sources : []; + const byHost = new Map(); + const byEndpoint = new Map(); + const hints = []; + + for (const source of sources) { + const endpoint = normaliseEndpoint(source?.endpoint); + if (!endpoint) continue; + const host = (() => { + try { + return new URL(endpoint).hostname.toLowerCase(); + } catch { + return ''; + } + })(); + if (host) { + if (!byHost.has(host)) byHost.set(host, []); + byHost.get(host).push(source.id); + } + if (!byEndpoint.has(endpoint)) byEndpoint.set(endpoint, []); + byEndpoint.get(endpoint).push(source.id); + } + + for (const [endpoint, ids] of byEndpoint.entries()) { + if (ids.length > 1) { + hints.push(`duplicate endpoint candidate: ${endpoint} (ids=${ids.join(', ')})`); + } + } + + for (const [host, ids] of byHost.entries()) { + if (ids.length >= 8) { + hints.push(`high host concentration: ${host} (${ids.length} sources)`); + } + } + + if (!hints.length) { + console.log('source-catalog hints: no notable duplicate or concentration patterns detected'); + return; + } + + console.log(`source-catalog hints (${hints.length}):`); + for (const hint of hints.slice(0, 30)) { + console.log(`- ${hint}`); + } +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); +}); diff --git a/scripts/validate-feed-data.mjs b/scripts/validate-feed-data.mjs index 560fb8fc..05f0a79f 100644 --- a/scripts/validate-feed-data.mjs +++ b/scripts/validate-feed-data.mjs @@ -38,11 +38,27 @@ function validateSource(source, index) { const prefix = `source[${index}] (id=${JSON.stringify(source?.id)})`; if (!source || typeof source !== 'object') throw new Error(`${prefix}: not an object`); if (typeof source.id !== 'string' || !source.id.trim()) throw new Error(`${prefix}: missing or empty "id"`); + if (!/^[a-z0-9-]+$/.test(source.id.trim())) { + throw new Error(`${prefix}: "id" must use lowercase letters, numbers, and dashes only`); + } if (typeof source.provider !== 'string' || !source.provider.trim()) throw new Error(`${prefix}: missing or empty "provider"`); if (typeof source.endpoint !== 'string' || !source.endpoint.trim()) throw new Error(`${prefix}: missing or empty "endpoint"`); if (!source.endpoint.startsWith('https://') && !source.endpoint.startsWith('http://')) { throw new Error(`${prefix}: "endpoint" must be an http/https URL, got ${JSON.stringify(source.endpoint)}`); } + try { + const parsedEndpoint = new URL(source.endpoint); + if (!parsedEndpoint.hostname) throw new Error('missing hostname'); + if (parsedEndpoint.username || parsedEndpoint.password) { + throw new Error('must not contain credentials'); + } + if (/\s/.test(parsedEndpoint.toString())) { + throw new Error('must not contain spaces'); + } + } catch (error) { + const detail = error instanceof Error ? error.message : String(error); + throw new Error(`${prefix}: invalid endpoint URL (${detail})`); + } if (source.endpoint.startsWith('http://') && !LEGACY_HTTP_ALLOWLIST.has(source.endpoint)) { throw new Error(`${prefix}: "endpoint" must use https:// when available; got ${JSON.stringify(source.endpoint)}`); } diff --git a/scripts/validate-live-feed-output.mjs b/scripts/validate-live-feed-output.mjs index 091657ae..6abb5dbe 100644 --- a/scripts/validate-live-feed-output.mjs +++ b/scripts/validate-live-feed-output.mjs @@ -10,6 +10,15 @@ function fail(message) { throw new Error(`live-alerts.json integrity failure: ${message}`); } +function validUrl(value) { + try { + const parsed = new URL(String(value || '').trim()); + return parsed.protocol === 'http:' || parsed.protocol === 'https:'; + } catch { + return false; + } +} + async function main() { const raw = await fs.readFile(outputPath, 'utf8'); let parsed; @@ -21,6 +30,9 @@ async function main() { } if (!parsed || typeof parsed !== 'object') fail('payload is not an object'); + if (parsed.schemaVersion !== '2026-04-live-feed-v1') { + fail('schemaVersion must be 2026-04-live-feed-v1'); + } if (!Array.isArray(parsed.alerts)) fail('alerts must be an array'); if (!Number.isFinite(Number(parsed.sourceCount)) || Number(parsed.sourceCount) < 0) { fail('sourceCount must be a non-negative number'); @@ -31,12 +43,27 @@ async function main() { if (!parsed.health || typeof parsed.health !== 'object') { fail('health block is required'); } + if (!parsed.runMetrics || typeof parsed.runMetrics !== 'object') { + fail('runMetrics block is required'); + } + if (!parsed.runMetrics.coverage || typeof parsed.runMetrics.coverage !== 'object') { + fail('runMetrics.coverage block is required'); + } if (!Number.isFinite(Number(parsed.health.lastSuccessfulSourceCount)) || Number(parsed.health.lastSuccessfulSourceCount) < 0) { fail('health.lastSuccessfulSourceCount must be a non-negative number'); } if (!parsed.health.lastAttemptedRefreshTime || Number.isNaN(new Date(parsed.health.lastAttemptedRefreshTime).getTime())) { fail('health.lastAttemptedRefreshTime must be a valid timestamp'); } + parsed.alerts.forEach((alert, index) => { + if (!alert || typeof alert !== 'object') fail(`alerts[${index}] must be an object`); + if (!String(alert.id || '').trim()) fail(`alerts[${index}].id is required`); + if (!String(alert.title || '').trim()) fail(`alerts[${index}].title is required`); + if (!String(alert.lane || '').trim()) fail(`alerts[${index}].lane is required`); + if (!String(alert.region || '').trim()) fail(`alerts[${index}].region is required`); + if (!validUrl(alert.sourceUrl)) fail(`alerts[${index}].sourceUrl must be a valid http(s) URL`); + if (!String(alert.queueBucket || '').trim()) fail(`alerts[${index}].queueBucket is required`); + }); console.log(`live-alerts.json integrity OK (alerts=${parsed.alerts.length}, sourceCount=${parsed.sourceCount})`); } diff --git a/shared/feed-controller.mjs b/shared/feed-controller.mjs index a339c7f6..d7ec3338 100644 --- a/shared/feed-controller.mjs +++ b/shared/feed-controller.mjs @@ -1,5 +1,5 @@ import { isLondonAlert } from './alert-view-model.mjs'; -import { LANE_ALL, MAP_VIEW_MODES, QUEUE_BUCKETS } from './ui-constants.mjs'; +import { LANE_ALL, MAP_VIEW_MODES, QUEUE_BUCKETS, SEVERITY_LEVELS, SEVERITY_ORDER } from './ui-constants.mjs'; import { reportBackgroundError } from './logger.mjs'; function searchTerms(query) { @@ -39,14 +39,18 @@ function normaliseHealthSnapshot(health) { export function normaliseRenderState(state) { const next = state && typeof state === 'object' ? state : {}; const watched = next.watched instanceof Set ? next.watched : new Set(); + const mutedSources = next.mutedSources instanceof Set ? next.mutedSources : new Set(); + const activeSeverityThreshold = String(next.activeSeverityThreshold || 'all'); return { ...next, alerts: Array.isArray(next.alerts) ? next.alerts : [], searchQuery: String(next.searchQuery || ''), activeRegion: String(next.activeRegion || LANE_ALL), activeLane: String(next.activeLane || LANE_ALL), + activeSeverityThreshold: SEVERITY_LEVELS.includes(activeSeverityThreshold) ? activeSeverityThreshold : 'all', mapViewMode: String(next.mapViewMode || MAP_VIEW_MODES.world), watched, + mutedSources, notes: Array.isArray(next.notes) ? next.notes : [], sourceRequests: Array.isArray(next.sourceRequests) ? next.sourceRequests : [], feedVisibleCount: Math.max(1, Number(next.feedVisibleCount || 0)), @@ -101,6 +105,20 @@ export function normaliseRenderState(state) { }; } +function passesSeverityThreshold(alert, threshold) { + if (!threshold || threshold === 'all') return true; + const alertSeverity = String(alert?.severity || '').toLowerCase(); + const alertRank = SEVERITY_ORDER[alertSeverity] || 0; + const thresholdRank = SEVERITY_ORDER[threshold] || 0; + return alertRank >= thresholdRank; +} + +function isMutedSource(alert, mutedSources) { + const source = String(alert?.source || '').trim().toLowerCase(); + if (!source) return false; + return mutedSources.has(source); +} + function alertSearchText(alert) { const fields = [ alert?.title, @@ -135,9 +153,12 @@ export function matchesAlertSearch(alert, query) { } export function filteredAlerts(state) { + const mutedSources = new Set([...state.mutedSources].map((value) => String(value || '').trim().toLowerCase()).filter(Boolean)); return state.alerts.filter((alert) => (state.activeRegion === LANE_ALL || (state.activeRegion === MAP_VIEW_MODES.london ? isLondonAlert(alert) : alert.region === state.activeRegion)) && (state.activeLane === LANE_ALL || alert.lane === state.activeLane) && + passesSeverityThreshold(alert, state.activeSeverityThreshold) && + !isMutedSource(alert, mutedSources) && matchesAlertSearch(alert, state.searchQuery) ); } diff --git a/shared/map-watch.mjs b/shared/map-watch.mjs index d156fce9..73128d37 100644 --- a/shared/map-watch.mjs +++ b/shared/map-watch.mjs @@ -11,6 +11,8 @@ const WORLD_FALLBACK = Object.freeze({ center: [50.2, 10.4], zoom: 4 }); const LONDON_CLUSTER_MAX_ZOOM = 12; const WORLD_CLUSTER_MAX_ZOOM = 7; const FRESH_ALERT_WINDOW_MS = 90 * 60 * 1000; +const WORLD_MAP_ITEM_CAP = 220; +const LONDON_MAP_ITEM_CAP = 320; function statusLine(mode, count) { if (count <= 0) return 'No alerts in current view'; @@ -67,6 +69,30 @@ function isFreshAlert(alert, nowMs = Date.now()) { return Number.isFinite(publishedAtMs) && (nowMs - publishedAtMs) >= 0 && (nowMs - publishedAtMs) <= FRESH_ALERT_WINDOW_MS; } +function mapSeverityRank(alert) { + const severity = String(alert?.severity || '').toLowerCase(); + if (severity === 'critical') return 4; + if (severity === 'high') return 3; + if (severity === 'elevated') return 2; + return 1; +} + +function selectMapItems(mode, items) { + const cap = mode === MAP_VIEW_MODES.london ? LONDON_MAP_ITEM_CAP : WORLD_MAP_ITEM_CAP; + if (items.length <= cap) return items; + return [...items] + .sort((left, right) => { + const freshnessGap = Number(isFreshAlert(right)) - Number(isFreshAlert(left)); + if (freshnessGap !== 0) return freshnessGap; + const severityGap = mapSeverityRank(right) - mapSeverityRank(left); + if (severityGap !== 0) return severityGap; + const timeGap = alertPublishedAtMs(right) - alertPublishedAtMs(left); + if (timeGap !== 0) return timeGap; + return String(left.id || '').localeCompare(String(right.id || '')); + }) + .slice(0, cap); +} + export function createMapController(config) { const { mapElement, mapStatusLine, mapEmptyState, openDetail } = config; let liveMap = null; @@ -183,7 +209,8 @@ export function createMapController(config) { lastState = state; lastView = view; const mode = state.mapViewMode === MAP_VIEW_MODES.world ? MAP_VIEW_MODES.world : MAP_VIEW_MODES.london; - const items = view.filtered.filter((alert) => Number.isFinite(alert.lat) && Number.isFinite(alert.lng)); + const mappedItems = view.filtered.filter((alert) => Number.isFinite(alert.lat) && Number.isFinite(alert.lng)); + const items = selectMapItems(mode, mappedItems); const signature = `${mode}:${liveMap.getZoom()}:${items.map((item) => `${item.id}:${item.lat.toFixed(3)},${item.lng.toFixed(3)}`).join('|')}`; if (!forceFit && signature === lastSignature) return; lastSignature = signature; diff --git a/shared/ui-constants.mjs b/shared/ui-constants.mjs index b6ed6443..027f7d32 100644 --- a/shared/ui-constants.mjs +++ b/shared/ui-constants.mjs @@ -30,3 +30,18 @@ export const SOURCE_REQUEST_STATUS_KINDS = Object.freeze({ success: 'success', error: 'error' }); + +export const SEVERITY_LEVELS = Object.freeze([ + 'all', + 'critical', + 'high', + 'elevated', + 'moderate' +]); + +export const SEVERITY_ORDER = Object.freeze({ + critical: 4, + high: 3, + elevated: 2, + moderate: 1 +}); diff --git a/styles.css b/styles.css index 58e7ee6e..1b3a7aef 100644 --- a/styles.css +++ b/styles.css @@ -380,6 +380,57 @@ h1 { color: black; } +.compact-filter-panel { + margin: 0 0 16px; + padding: 14px; +} + +.filter-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; +} + +.control-select { + width: 100%; + margin-top: 6px; + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.16); + background: rgba(255, 255, 255, 0.08); + color: var(--text); + min-height: 42px; + padding: 8px 10px; +} + +.source-mute-form { + display: grid; + grid-template-columns: 1fr auto; + gap: 8px; + margin-top: 10px; +} + +#source-mute-input { + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.16); + background: rgba(255, 255, 255, 0.08); + color: var(--text); + min-height: 42px; + padding: 8px 10px; +} + +.source-mute-list { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 10px; +} + +.muted-source-chip { + min-height: 34px; + padding: 6px 10px; + border-radius: 999px; +} + .tab-panel { display: none; } diff --git a/tests/decision-logic.test.mjs b/tests/decision-logic.test.mjs index 2c7ce424..72bcfeef 100644 --- a/tests/decision-logic.test.mjs +++ b/tests/decision-logic.test.mjs @@ -1226,9 +1226,22 @@ test('validate-live-feed-output script passes valid feed and fails invalid sourc ); const validPayload = { + schemaVersion: '2026-04-live-feed-v1', generatedAt: '2026-04-04T09:00:00.000Z', sourceCount: 3, - alerts: [], + alerts: [{ + id: 'a-1', + title: 'Test alert', + lane: 'incidents', + region: 'uk', + sourceUrl: 'https://example.test/1', + queueBucket: 'responder' + }], + runMetrics: { + coverage: { + checked: 3 + } + }, health: { lastSuccessfulSourceCount: 3, lastAttemptedRefreshTime: '2026-04-04T09:00:00.000Z' diff --git a/tests/ui-e2e.test.mjs b/tests/ui-e2e.test.mjs new file mode 100644 index 00000000..0f4cd270 --- /dev/null +++ b/tests/ui-e2e.test.mjs @@ -0,0 +1,194 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import http from 'node:http'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { chromium } from 'playwright'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(__dirname, '..'); +const runE2E = process.env.BRIALERT_RUN_E2E === 'true'; + +let server; +let baseUrl = ''; + +function contentTypeFor(filePath) { + if (filePath.endsWith('.html')) return 'text/html; charset=utf-8'; + if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) return 'application/javascript; charset=utf-8'; + if (filePath.endsWith('.css')) return 'text/css; charset=utf-8'; + if (filePath.endsWith('.json')) return 'application/json; charset=utf-8'; + if (filePath.endsWith('.svg')) return 'image/svg+xml'; + if (filePath.endsWith('.jpg') || filePath.endsWith('.jpeg')) return 'image/jpeg'; + if (filePath.endsWith('.webmanifest')) return 'application/manifest+json; charset=utf-8'; + return 'text/plain; charset=utf-8'; +} + +async function startStaticServer() { + server = http.createServer(async (req, res) => { + try { + const requestPath = new URL(req.url || '/', 'http://localhost').pathname; + const safePath = requestPath === '/' ? '/index.html' : requestPath; + const fullPath = path.join(repoRoot, decodeURIComponent(safePath)); + const normalized = path.normalize(fullPath); + if (!normalized.startsWith(repoRoot)) { + res.writeHead(403); + res.end('Forbidden'); + return; + } + const data = await fs.readFile(normalized); + res.writeHead(200, { 'content-type': contentTypeFor(normalized) }); + res.end(data); + } catch { + res.writeHead(404); + res.end('Not found'); + } + }); + await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); + const address = server.address(); + baseUrl = `http://127.0.0.1:${address.port}`; +} + +async function stopStaticServer() { + if (!server) return; + await new Promise((resolve) => server.close(resolve)); + server = null; +} + +test.before(async () => { + if (!runE2E) return; + await startStaticServer(); +}); + +test.after(async () => { + await stopStaticServer(); +}); + +test('e2e dashboard/map/watchlists flow renders and updates', { skip: !runE2E }, async (t) => { + let browser; + try { + browser = await chromium.launch(); + } catch (error) { + t.skip(`Playwright browser unavailable: ${error instanceof Error ? error.message : String(error)}`); + return; + } + + const context = await browser.newContext(); + const page = await context.newPage(); + await page.route('**/live-alerts.json*', async (route) => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + schemaVersion: '2026-04-live-feed-v1', + generatedAt: '2026-04-04T10:00:00.000Z', + sourceCount: 12, + alertCount: 1, + alerts: [{ + id: 'test-alert-1', + fusedIncidentId: 'fusion-test-1', + title: 'Responder alert', + location: 'London', + region: 'uk', + lane: 'incidents', + severity: 'high', + status: 'Update', + source: 'CT Policing', + sourceUrl: 'https://example.test/a1', + queueBucket: 'responder', + queueReason: 'Trigger-tier terrorism incident candidate', + summary: 'Responder alert summary', + time: '04 Apr 2026, 10:00', + publishedAt: '2026-04-04T10:00:00.000Z', + lat: 51.5, + lng: -0.12 + }], + runMetrics: { coverage: { checked: 12 } }, + health: { + lastSuccessfulSourceCount: 12, + lastAttemptedRefreshTime: '2026-04-04T10:00:00.000Z' + } + }) + }); + }); + + await page.goto(`${baseUrl}/index.html`); + await page.waitForSelector('#feed-list .feed-card'); + await page.click('#feed-list .star-button'); + await page.click('[data-tab="watchlists"]'); + await page.waitForSelector('#watchlist-list [data-watch]'); + const summaryText = await page.locator('#watchlist-summary').textContent(); + assert.match(summaryText || '', /tracked/i); + + await page.click('[data-tab="map"]'); + await page.waitForSelector('#map-status-line'); + const mapStatus = await page.locator('#map-status-line').textContent(); + assert.match(mapStatus || '', /alert/i); + + await browser.close(); +}); + +test('e2e quarantine restore flow loads and restores source', { skip: !runE2E }, async (t) => { + let browser; + try { + browser = await chromium.launch(); + } catch (error) { + t.skip(`Playwright browser unavailable: ${error instanceof Error ? error.message : String(error)}`); + return; + } + + const context = await browser.newContext(); + const page = await context.newPage(); + await page.route('**/api/auth/session', async (route) => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + ok: true, + authenticated: true, + user: { login: 'admin' }, + loginUrl: '/api/auth/github/start', + logoutUrl: '/api/auth/logout' + }) + }); + }); + await page.route('**/api/quarantined-sources', async (route) => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + ok: true, + restoreAvailable: true, + generatedAt: '2026-04-04T10:00:00.000Z', + count: 1, + sources: [{ + id: 'source-1', + provider: 'Test source', + endpoint: 'https://example.test/feed', + kind: 'rss', + lane: 'context', + region: 'uk', + status: 'auto-quarantined', + reason: 'Needs review', + replacementSuggestion: 'https://example.test/new-feed' + }] + }) + }); + }); + await page.route('**/api/restore-source', async (route) => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ ok: true, restoredSource: { id: 'source-1' } }) + }); + }); + + await page.goto(`${baseUrl}/source-quarantine.html`); + await page.waitForSelector('tr[data-source-id="source-1"]'); + await page.click('tr[data-source-id="source-1"] button[data-action="restore"]'); + await page.waitForSelector('#toast.visible'); + const toast = await page.locator('#toast').textContent(); + assert.match(toast || '', /restored/i); + + await browser.close(); +}); From fc2373fab2f48fe75a8f4646eed1b96b6d84216d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 00:00:26 +0000 Subject: [PATCH 3/3] fix: keep live-feed output validation backward compatible Agent-Logs-Url: https://github.com/potemkin666/Brialert/sessions/0ac49de3-9169-4752-9774-d0966393cd77 Co-authored-by: potemkin666 <183807833+potemkin666@users.noreply.github.com> --- scripts/validate-live-feed-output.mjs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/scripts/validate-live-feed-output.mjs b/scripts/validate-live-feed-output.mjs index 6abb5dbe..7c8eb276 100644 --- a/scripts/validate-live-feed-output.mjs +++ b/scripts/validate-live-feed-output.mjs @@ -30,8 +30,8 @@ async function main() { } if (!parsed || typeof parsed !== 'object') fail('payload is not an object'); - if (parsed.schemaVersion !== '2026-04-live-feed-v1') { - fail('schemaVersion must be 2026-04-live-feed-v1'); + if (parsed.schemaVersion != null && parsed.schemaVersion !== '2026-04-live-feed-v1') { + fail('schemaVersion must be 2026-04-live-feed-v1 when provided'); } if (!Array.isArray(parsed.alerts)) fail('alerts must be an array'); if (!Number.isFinite(Number(parsed.sourceCount)) || Number(parsed.sourceCount) < 0) { @@ -43,11 +43,13 @@ async function main() { if (!parsed.health || typeof parsed.health !== 'object') { fail('health block is required'); } - if (!parsed.runMetrics || typeof parsed.runMetrics !== 'object') { - fail('runMetrics block is required'); - } - if (!parsed.runMetrics.coverage || typeof parsed.runMetrics.coverage !== 'object') { - fail('runMetrics.coverage block is required'); + if (parsed.schemaVersion === '2026-04-live-feed-v1') { + if (!parsed.runMetrics || typeof parsed.runMetrics !== 'object') { + fail('runMetrics block is required for schemaVersion 2026-04-live-feed-v1'); + } + if (!parsed.runMetrics.coverage || typeof parsed.runMetrics.coverage !== 'object') { + fail('runMetrics.coverage block is required for schemaVersion 2026-04-live-feed-v1'); + } } if (!Number.isFinite(Number(parsed.health.lastSuccessfulSourceCount)) || Number(parsed.health.lastSuccessfulSourceCount) < 0) { fail('health.lastSuccessfulSourceCount must be a non-negative number'); @@ -61,8 +63,12 @@ async function main() { if (!String(alert.title || '').trim()) fail(`alerts[${index}].title is required`); if (!String(alert.lane || '').trim()) fail(`alerts[${index}].lane is required`); if (!String(alert.region || '').trim()) fail(`alerts[${index}].region is required`); - if (!validUrl(alert.sourceUrl)) fail(`alerts[${index}].sourceUrl must be a valid http(s) URL`); - if (!String(alert.queueBucket || '').trim()) fail(`alerts[${index}].queueBucket is required`); + const sourceUrl = String(alert.sourceUrl || '').trim(); + if (/^https?:\/\//i.test(sourceUrl) && !validUrl(sourceUrl)) { + fail(`alerts[${index}].sourceUrl must be a valid http(s) URL when provided`); + } + if (!sourceUrl && !String(alert.source || '').trim()) fail(`alerts[${index}] requires sourceUrl or source`); + if (alert.queueBucket != null && !String(alert.queueBucket).trim()) fail(`alerts[${index}].queueBucket must be non-empty when provided`); }); console.log(`live-alerts.json integrity OK (alerts=${parsed.alerts.length}, sourceCount=${parsed.sourceCount})`);