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/data/brialert.sqlite b/data/brialert.sqlite index 17fc7a02..3706a2cb 100644 Binary files a/data/brialert.sqlite and b/data/brialert.sqlite differ 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/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/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/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..7c8eb276 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 != 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) { fail('sourceCount must be a non-negative number'); @@ -31,12 +43,33 @@ async function main() { if (!parsed.health || typeof parsed.health !== 'object') { fail('health 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'); } 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`); + 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})`); } 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/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', '' + 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(); +});